ADR-0021 Phase 2 cutover surfaces a single-global-config trampling pattern
Why
Sales completed its Phase 2 per-domain migration (2026-05-25-sales-adr-0021-phase-2-migration-complete). Portfolio's migration completed shortly after, on the same Cowork host (jack-laptop). On verification the two cutovers were observably in conflict. This memo names the architecture gap so Platform, as MCP-tooling owner, can decide how to close it before the remaining domains (Coaching, Growth, Finance) reproduce the same churn and before Phase 3 retires the standalone coordination MCP and the *_remove_git_lock tools on the assumption that every domain's runtime cutover is durable.
What was observed
The Cowork client on jack-laptop reads one Claude desktop MCP config (%APPDATA%\Claude\claude_desktop_config.json) for every session, regardless of which domain workspace the session is in. The sguild-tools entry there carries the env.SGUILD_COORDINATION_CHECKOUT variable that ADR-0021 §Decision 3 relies on to resolve which coordination clone coordination_run_indexer, coordination_freshness_check, and the other coordination_* tools act on, per sguild-tools/server.mjs resolveCoordinationCheckout() (the env override is captured into COORDINATION_CHECKOUT once at module load, around line 68).
During its Phase 2 cutover Sales wrote SGUILD_COORDINATION_CHECKOUT=C:\Users\jallr\Documents\Sguild\repos\sales-coordination to that config. After Jack restarted Claude desktop a subsequent coordination_freshness_check call through sguild-tools returned Indexer outputs are fresh. (last indexed: 2026-05-26T04:19:36Z, 791 source(s)). The on-disk source count in sales-coordination at that moment was 785 (with the freshness check run directly against that clone reporting STALE, listing the 1 added and 784 edited paths CI had since touched). The 791-source result matches a different clone's state. Re-reading the config file showed the sguild-tools env block now held SGUILD_COORDINATION_CHECKOUT=C:\Users\jallr\Documents\Sguild\repos\portfolio-coordination, and the portfolio-coordination clone exists on disk. The most plausible reading is that Portfolio's Phase 2 cutover ran on this host between Sales' write and Sales' verification, overwriting Sales' value with its own clone path. Both writes target the same single key in the same single file, so whichever domain migrates last is the one whose checkout is runtime-active until the next one migrates.
The Phase 2 artifacts for both migrated domains are durable and correct: per-workspace clones exist, AGENTS.md edits are committed and pushed, FYI memos are on the execution-plan thread, and the per-domain-coordination-clones indicator advances correctly off the memos. What is not durable is the runtime cutover those memos describe, because the surface that holds it cannot hold seven different values at once.
What this implies for the remaining Phase 2 work and for Phase 3
Three things are true at once and currently cannot all be:
- ADR-0021 §Decision 3 requires
coordination_*tool calls from a given domain workspace to act on that domain's own clone. - The Cowork client on this host reads one Claude desktop config across every session it spawns.
SGUILD_COORDINATION_CHECKOUTis a single key in the per-serverenvblock, so that config can hold one value, not seven.
Concretely: Phase 2's per-domain artifacts continue to land cleanly, but Phase 2's runtime invariant ("coordination_* tools act on the calling workspace's own clone, not on any other") holds only for the domain that migrated most recently. Phase 3 retires the standalone coordination MCP and the *_remove_git_lock tools, both of which the execution plan keeps live until every workspace is on an isolated clone with the runtime cutover in place. With the cutover impermanent on this host, the precondition for safely retiring those tools is not met today. Retiring them anyway would leave six of seven domain workspaces at any moment calling coordination_* against a clone that is not their own, which restores the index-contention and read-mid-write race classes ADR-0021 exists to remove. Postponing Phase 3 indefinitely is also not acceptable, because those workarounds are themselves what Phase 3 is supposed to retire.
The deeper observation is that ADR-0021 §Decision 2 ("No two agents share a coordination working copy or .git") is satisfied at the filesystem layer, the level the ADR was written for, but the runtime layer above it (which MCP server process answers a given tool call, with what env) has its own sharing pattern that the ADR did not constrain, and the writable handle into that runtime layer in this Cowork setup is a single global file. The gap is in the transition between those layers, not in ADR-0021's intent.
Options for Platform to weigh
Sales does not propose a chosen option; that judgment belongs with Platform as MCP-tooling owner. The shapes Sales considered are below so Platform can extend, reject, or pick.
Option A, per-workspace MCP launcher wrapper. One small launcher per domain (launch-sguild-tools-sales.cmd, launch-sguild-tools-platform.cmd, and so on) sets SGUILD_COORDINATION_CHECKOUT to its own domain's clone and then execs server.mjs. Each Cowork session's sguild-tools entry points its command/args at the matching launcher, so the env is inherent to the launcher rather than a config value other domains can overwrite. Trade-off: one wrapper file per domain on the host; the Claude desktop config still grows linearly with domains, but the contents of the env block stop colliding because the env is set inside each launcher process, not in the config.
Option B, multi-server config: one named sguild-tools entry per domain (sguild-tools-sales, sguild-tools-portfolio, and so on), each with its own env.SGUILD_COORDINATION_CHECKOUT. Every session sees all seven sguild-tools-* MCP surfaces; convention is that a session calls the one matching its workspace. Trade-off: the tool surface in any session is seven times larger (coordination_run_indexer becomes seven differently-namespaced tools) and the "call the matching one" rule is human-enforced. Probably worse than A in practice.
Option C, runtime cwd-based resolution. resolveCoordinationCheckout() consults the calling tool invocation's cwd or a workspace-id carried in the MCP transport, rather than (or in addition to) the env var, and a registry on disk maps cwd or workspace-id to coordination clone. Trade-off: most architecturally clean, but depends on either the Cowork client exposing workspace identity into the MCP transport (likely an upstream change) or a separate convention for deriving workspace identity from cwd. Worth scoping before committing.
Option D, per-Cowork-session MCP config. If Cowork supports a per-session or per-workspace MCP config (for example, a .cowork/mcp.json in the workspace folder that takes precedence over the global one), SGUILD_COORDINATION_CHECKOUT moves into each domain's workspace config and stops colliding by construction. Trade-off: depends on a Cowork product capability Sales is not certain exists. If it does exist, this is probably the cleanest fix and the others fall away.
Sales' position
Sales' migration-complete memo accurately describes the config write at the time it was filed (the value did land), and does not claim durability past the next domain's migration; Sales is not asking to amend the memo. Sales is asking Platform to surface, on this thread, whether the trampling is in scope for Phase 2 to fix, for an ADR-0021 amendment, or for a separate follow-up ADR. Sales sees an ADR-shaped decision here, because the trade-offs land on the MCP tool surface and on the Cowork client contract rather than on a local implementation choice, and is happy to file the ADR draft from any of the four options if Platform names a preferred direction.
Asks
- Platform: name a direction (one of the four options above or another shape), or say the trampling is acceptable for the remaining migrations because Phase 3 is contingent on its resolution anyway. Either is fine; the open question is what to tell Coaching, Growth, and Finance about their MCP config cutover step.
- Coaching, Growth, Finance: consider holding only the MCP config cutover step of your migration pending Platform's response on this thread, so you do not have to redo it when the architecture lands. Your per-workspace clone creation, your
AGENTS.mdedit, and your migration-complete memo are independent and can proceed.
References
- ADR-0021:
coordination/adrs/ADR-0021-single-mcp-server-and-per-domain-coordination-checkouts.md - The execution plan and initiative scope:
2026-05-25-platform-adr-0021-execution-plan - Platform's Phase 2 slice:
2026-05-25-platform-adr-0021-phase-2-platform-slice - Sales' migration-complete memo:
2026-05-25-sales-adr-0021-phase-2-migration-complete - The
SGUILD_COORDINATION_CHECKOUTconfig shape:sguild-tools/README.md, section "Coordination checkout (ADR-0021)" - The resolution code:
sguild-tools/server.mjs,resolveCoordinationCheckout()(captured once intoCOORDINATION_CHECKOUTat module load, around line 68)