Skip to content

Check route selection before every ACP prompt - #1166

Merged
trissim merged 3 commits into
mainfrom
fix/route-operation-locks
Oct 23, 2026
Merged

trissim merged 3 commits into
mainfrom
fix/route-operation-locks

Conversation

@trissim

@trissim trissim commented Oct 23, 2026 •

Copy link
Copy Markdown

MI's lifetime-hold finding is already partly fixed on Toad main by #1159: open_selected and ACP start no longer transfer their route contexts into cleanup. This PR keeps those scopes as direct with-blocks and removes their unnecessary ExitStack wrappers.

The supplied ACP prompt callback checks session and queue identity. AgentProcess.prompt reaches the existing CoordinationAccess through agent.controller.transcripts.access, then invokes access.require(self.route_selection) on its existing preparation worker. CoordinationAccess.require owns the live-route comparison; AgentProcess contains no copy. The session/queue callback still runs after that check and before the RPC. No lifetime route lock is added.

Paired with OpenHCSDev/agent-comms#2915 at d0ea1698fec34bcf0142974715d9a7007661a8c0, which shortens the Core watch client scopes before removing its route-publication deadline.

Step 0 after:

Holder after the change Scope
Toad comms_root.py:374-380 Open and validate one service; the context exits before observation attaches.
Toad acp/agent_process.py:73-93 Select/attach/start one connection; no cleanup-stack transfer. Prompt rechecks the route at :97.
Core cli_commands.py:939-940 One ordinary CLI operation.
Core cli_commands.py:1411-1413 Open the watch's history source, before either streaming task starts.
Core cli_commands.py:1449-1450 Watch setup only; stream.write runs after exit.
Core comms.py:100-101 Capture one recipient identity.
Core comms.py:106-112 One inbox page read, joining its worker before releasing the context.
Core comms.py:115-116 One acknowledgment, outside the generator yield.
Core route_selection.py:70-71 One synchronous selected write.
Core comms.py:92-93, active_route.py:62-63 Context-manager plumbing for the operations above, rather than application/process lifetime.
Core active_route.py:187-188 Historical-root write guard; callers hold it for individual message/channel/order writes.

client_wire is a context factory, not an entered lifetime holder. Historical-root write callers were traced in input_origin, messaging, channel_management, publisher, coordination_tables/refusals and todos; each encloses its one write operation. Route publication waits in active_route.py:267 through the existing UNBOUNDED_CONTENTION, with no deadline or refusal translation.

Search RouteReadersHold|default-route readers hold across Core and Toad src/tests: empty. At 12e6c7f, Ruff I001 passes. No tests, application launch or install ran, as directed.

Assumed: the pair ships in the same runtime update; the existing session and queue checks remain required alongside the route check.

@trissim
trissim marked this pull request as ready for review October 23, 2026 21:16
Copilot AI balanced review requested due to automatic review settings October 23, 2026 21:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@trissim
trissim merged commit 5a5cae3 into main Oct 23, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants