Fix bind_context active workspace routing - #812
Conversation
| collectMatchesForContextID: { contextID in | ||
| await MainActor.run { | ||
| WindowStatesManager.shared.allWindows.compactMap { windowState in | ||
| guard let candidate = windowState.workspaceManager.bindingCandidate(forContextID: contextID) else { | ||
| guard let candidate = windowState.workspaceManager.storedBindingCandidate(forContextID: contextID) else { | ||
| return nil | ||
| } | ||
| return MCPContextBindingMatch( |
There was a problem hiding this comment.
Bug: The debug scope validation incorrectly fails if a bound context exists in a non-active workspace, as bindingCandidate(forContextID:) now only searches the active one.
Severity: LOW
Suggested Fix
The debug scope validation should be updated to search across all workspaces for a binding candidate, not just the active one. Consider using a method similar to storedBindingCandidate which performs a broader search, ensuring the check doesn't fail when the context is valid but in an inactive workspace.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: Sources/RepoPrompt/Infrastructure/MCP/MCPConnectionManager.swift#L6505-L6511
Potential issue: A debug-only scope validation check in
`MCPConnectionManager+DebugDiagnosticsWorktreeStartup.swift` will incorrectly fail when
a user's MCP connection is bound to a context in a non-active workspace. The refactored
`bindingCandidate(forContextID:)` method now only searches the active workspace.
Consequently, the check `window.workspaceManager.bindingCandidate(forContextID:
boundContextID)?.workspaceID == workspace.id` fails by returning `nil` if the bound
context is in another workspace. This throws a
`DebugWorktreeStartupBenchmarkError.invalidScope` error, creating a false negative
during diagnostic tests, as the connection is legitimately bound.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
This is not a valid issue. The changed resolver at this location intentionally uses storedBindingCandidate for generic/internal routing that may target an inactive stored workspace.\n\nThe separate DEBUG benchmark validator has a stricter contract: it first requires an activeWorkspace, then requires boundWorkspaceID == activeWorkspace.id, and finally verifies that boundContextID belongs to that active workspace. A binding to a non-active workspace is intentionally invalid for this visible-workspace benchmark scope. Keeping bindingCandidate active-only makes the final check consistent with those preceding guards; changing it to storedBindingCandidate would weaken the diagnostic invariant rather than fix a false negative.
|
Can you please explain the use case/issue that motivated you to make this PR. What problem are we trying to solve? Where did this fail you? |
|
The motivating failure was a deterministic cross-window routing mismatch in self-hosted MCP workflows. Concrete reproduction:
This is a relatively narrow edge case: it requires multiple windows, overlapping saved-workspace metadata, and a long-lived MCP connection with stale affinity (or deterministic lowest-window fallback). Most single-window workflows are unaffected. However, when triggered, it can route Git, file, or worktree operations to a different repository than the bound context reports, so the fix is primarily about fail-closed routing correctness. Before this change, That becomes user-visible when root-oriented operations run next: The intended invariant here is therefore narrow: |
|
Quick status update: the production routing invariant in this PR still looks correct—the The hosted failures exposed an incomplete test-fixture migration: some persistent MCP fixtures still bind synthetic contexts without first making their synthetic workspace active. I’m preparing a narrow test-only follow-up that activates the fixture consistently and removes the duplicated suite-local setup. I do not plan to weaken the production active-workspace requirement. The unrelated Context Builder timeout is being treated separately. |
|
Updated at exact head This follow-up completes only the test-fixture migration required by the active-workspace Validation:
The path-selected full root-test lane completed with both directly changed suites passing, but remained red from shared-state/time-out failures in unrelated Context Builder and Git cancellation tests plus a later protected-mutation shared-server timeout. Those failures are recorded rather than hidden; exact-head hosted CI is now queued to validate the isolated PR integration. |
Audit disposition — best immediate merge candidate (2026-08-14)The external Exact-head CI was green in the reviewed state, and I did not find a code-level blocker. Subject to normal branch protection and a non-author approval, this is suitable to merge. |
Deep-review assessment — 2026-08-14Disposition: merge candidate. This establishes the right authority split: external I did not find a code-level blocker, and the reviewed exact-head hosted CI was green. Obtain the required non-author review and merge without broadening this into general routing or synchronization work. |
Summary
Validation
The aggregate local pr-ready suite reached its one-hour timeout due suite-order/global-state failures. The routing-related failures found by the first run were corrected; the remaining timeout case and known auth-recovery race both pass independently. Hosted exact-head checks remain the final backstop.
Scope
No locks, serialization, telemetry, retries, or project-specific routing behavior were added. The broad shared-fixture activation attempted during validation was removed in favor of narrow test-local setup.