You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
mcpx: initialize sends rootUri/workspaceFolders for scope-resolved instances #959
Slice 3 of decision record 0004 (pkgs/mcpx/docs/decisions/0004-scope-resolved-roots.md, PR #957). Design source: dezren39/darwin-nix#819 — this issue carries its acceptance criteria. Depends on slice 1 (ResolvedScope plumbing).
What to build (spec §5)
mcpclient.Options gains the instance root; when non-empty, initialize for that instance includes rootUri (file:// URI of the root), workspaceFolders ([{uri, name = base name of root}]), and declares the workspace.workspaceFolders client capability true.
Both fields are sent for every era (legacy and modern) — initialize params are extensible and non-consuming servers ignore them. When the root is empty, initialize is byte-for-byte what it is today.
For an instance with a scope-resolved root, the initialize request includes rootUri/workspaceFolders naming that root (demonstrated by a captured handshake or a test-double server recording initialize params).
Servers that don't negotiate workspace support initialize exactly as before.
global-scoped instances send no rootUri/workspaceFolders — no fabricated daemon-cwd root.
Tests cover: root present for repo/worktree scopes, absent for global scope.
(The live gopls go_package_api proof is slice 4's acceptance.)
Still live (verified this run): nothing on main sends rootUri/workspaceFolders for scope-resolved instances — the prerequisite ResolvedScope plumbing (#958) does not exist on main yet, and its design record is still in open PR #957. No merged PR addresses this.
Related:#958 (slice 1, prerequisite) · PR #957 (decision 0004, open) · #961 (slice 4 consumes this for the live gopls proof) · design origin dezren39/darwin-nix#819.
Notes / risks: Marked status/blocked at intake because it cannot be implemented before slice 1 lands. The byte-for-byte-unchanged requirement for empty-root instances is the key regression guard — a captured-handshake comparison for a global-scoped server is the cleanest proof. Sending both fields for every era is deliberate (extensible initialize params); do not era-gate it.
Suggested approach: After #958 merges, thread the instance root into mcpclient.Options, add the fields + capability declaration behind "root non-empty", and cover repo/worktree-present vs global-absent with a test-double server recording initialize params.
— Fleet monitor intake enrichment (acceptance criteria were already in the body; labels normalized, meta/enriched added).
Relocated copy of this work arrived (from dezren39/darwin-nix#819) and was closed as a duplicate — two deltas folded in
developing-today/code#1993 was the placement-audit relocation of dezren39/darwin-nix#819 (this issue's design source). Triaged today (queue task 2899, worker repo-worker-code, origin openchamber-scheduled-lane) against main @ 4d157755: duplicate of this issue, closed with the pointer — it carries no acceptance criterion that is missing here.
Two things from the relocated copy worth keeping:
Era gate (a real divergence, needs a decision before implementation). This issue's spec says rootUri/workspaceFolders are sent "for every era (legacy and modern)". The relocated copy said the opposite — send only what the negotiated revision and capabilities allow. The modern era 2026-07-28 dropped the roots feature and mcpx already declares roots: {} there (internal/mcpclient/modern.go:64-65,80), so sending workspace fields inside a 2026-07-28 initialize is spec-questionable and untested. The stricter, negotiate-gated wording is the safer default until someone verifies the modern path; worth settling when mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958 lands rather than assuming it in the diff.
State re-checked today, still as the intake review says: Client.initializeParams() (internal/mcpclient/client.go:422-429) sends only protocolVersion, capabilities, clientInfo; SetRoots (client.go:921), the roots capability declaration (modern.go:80-83) and the roots/list relay (modern.go:287-303) exist, so the missing piece is precisely "put the resolved root in the initialize request"; and ResolvedScope plumbing (#958) is still absent from pkgs/mcpx/internal, so this stays blocked on slice 1.
🤖 Agent note — triage verdict: CONFIRMED, still blocked on slice 1 (queue task 2294, lane D, 2026-11-01T02:2xZ)
Fresh verification against current main:
Nothing on main sends rootUri/workspaceFolders for scope-resolved instances: code search finds ResolvedScope and rootUri only in pkgs/mcpx/docs/decisions/0004-scope-resolved-roots.md — the design doc, not code.
The dependency is real and unmet: slice 1, mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958 (ResolvedScope plumbing + spawn cwd), is still OPEN, and mcpclient.Options has no instance root to send. This issue's spec (§5) is buildable only on top of that plumbing.
status/blocked stays — the blocker is #958 landing. Once #958 merges, this slice is a small, fully-specced fix (Options root + initialize params + capability declaration + scope tests) and can be enqueued directly against the acceptance criteria above.
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/normal). Issue carries status/blocked; the covering triage must re-derive and name the current blocker. If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
Slice 3 is not implemented: git grep -n 'rootUri|RootURI|WorkspaceFolders|workspaceFolders' origin/main -- 'pkgs/mcpx/**/*.go' returns no hits; the only mentions are in pkgs/mcpx/docs/decisions/0004-scope-resolved-roots.md.
Fix path scoped (enqueued as task 7814, small_fix, 45 min): mcpclient.Options gains the instance root; when non-empty, initialize (both eras) sends rootUri = file:// URI of the root, workspaceFolders = [{uri, name=<base name>}], and declares workspace.workspaceFolders true; empty root keeps initialize byte-for-byte unchanged and global scope fabricates no root. Root comes from the ResolvedScope slice 1 already plumbs. Tests: test-double recording initialize params for repo/worktree vs global.
Label correction:status/blocked is no longer truthful — the blocker has cleared; it is removed as the fix packet queues.
Ordering: slice 4's live gopls go_package_api proof stays out of scope and depends on this landing.
mcpclient.Options now carries the instance root, and initialize names it when it is non-empty:
rootUri: file:// URI of the scope-resolved root.
workspaceFolders: [{uri: <same>, name: <base name of root>}].
capabilities.workspace.workspaceFolders: true.
Both eras send the same fields; a rootless instance (global scope, degraded resolution) sends exactly what it sent before, so no daemon-cwd root is fabricated.
Verified: go build ./... clean, gofmt -l clean, and the new test-double test records the initialize params — present with a root (uri + base name + capability), absent without one. Targeted run: go test ./internal/mcpx... → ok internal/mcpclient 0.040s, ok internal/pool 0.930s. PR checks: basic: production line limit pass. Merged as 62344683de67512ddb4f50e2795af1e9eca525be.
Slice 4 — flipping gopls to worktree scope plus the live go_package_api proof — is #961, as this issue's own AC says.
🤖 Agent note · done
Agent: queue worker (repo-worker-code), lane ec118cad-0fd3-4652-91c4-27432f2f2efd
Session / ID: queue task 7814
Found via: queue claim, revalidated against origin/main before working
Activity
dezren39 commentedon Oct 26, 2026
Intake review
Still live (verified this run): nothing on main sends
rootUri/workspaceFoldersfor scope-resolved instances — the prerequisiteResolvedScopeplumbing (#958) does not exist on main yet, and its design record is still in open PR #957. No merged PR addresses this.Related: #958 (slice 1, prerequisite) · PR #957 (decision 0004, open) · #961 (slice 4 consumes this for the live gopls proof) · design origin dezren39/darwin-nix#819.
Notes / risks: Marked
status/blockedat intake because it cannot be implemented before slice 1 lands. The byte-for-byte-unchanged requirement for empty-root instances is the key regression guard — a captured-handshake comparison for a global-scoped server is the cleanest proof. Sending both fields for every era is deliberate (extensible initialize params); do not era-gate it.Suggested approach: After #958 merges, thread the instance root into
mcpclient.Options, add the fields + capability declaration behind "root non-empty", and cover repo/worktree-present vs global-absent with a test-double server recording initialize params.— Fleet monitor intake enrichment (acceptance criteria were already in the body; labels normalized,
meta/enrichedadded).dezren39 commentedon Oct 29, 2026
Relocated copy of this work arrived (from dezren39/darwin-nix#819) and was closed as a duplicate — two deltas folded in
developing-today/code#1993was the placement-audit relocation of dezren39/darwin-nix#819 (this issue's design source). Triaged today (queue task2899, workerrepo-worker-code, originopenchamber-scheduled-lane) againstmain@4d157755: duplicate of this issue, closed with the pointer — it carries no acceptance criterion that is missing here.Two things from the relocated copy worth keeping:
rootUri/workspaceFoldersare sent "for every era (legacy and modern)". The relocated copy said the opposite — send only what the negotiated revision and capabilities allow. The modern era2026-07-28dropped the roots feature and mcpx already declaresroots: {}there (internal/mcpclient/modern.go:64-65,80), so sending workspace fields inside a 2026-07-28 initialize is spec-questionable and untested. The stricter, negotiate-gated wording is the safer default until someone verifies the modern path; worth settling when mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958 lands rather than assuming it in the diff.go_package_apiproof also needs the child-cwd half. That is mcpx: spawn repo/worktree-scoped instances with the child cwd set to the resolved scope root #1989 (open, nix#817). Note mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958's title — "ResolvedScope plumbing + spawn cwd = resolved scope root" — appears to claim the same spawn-cwd work, so mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root #958 and mcpx: spawn repo/worktree-scoped instances with the child cwd set to the resolved scope root #1989 look like duplicates of each other for the cwd half; flagged for whoever owns them, not resolved here.State re-checked today, still as the intake review says:
Client.initializeParams()(internal/mcpclient/client.go:422-429) sends onlyprotocolVersion,capabilities,clientInfo;SetRoots(client.go:921), therootscapability declaration (modern.go:80-83) and theroots/listrelay (modern.go:287-303) exist, so the missing piece is precisely "put the resolved root in the initialize request"; andResolvedScopeplumbing (#958) is still absent frompkgs/mcpx/internal, so this stays blocked on slice 1.dezren39 commentedon Nov 1, 2026
🤖 Agent note — triage verdict: CONFIRMED, still blocked on slice 1 (queue task 2294, lane D, 2026-11-01T02:2xZ)
Fresh verification against current main:
rootUri/workspaceFoldersfor scope-resolved instances: code search findsResolvedScopeandrootUrionly inpkgs/mcpx/docs/decisions/0004-scope-resolved-roots.md— the design doc, not code.mcpclient.Optionshas no instance root to send. This issue's spec (§5) is buildable only on top of that plumbing.status/blockedstays — the blocker is #958 landing. Once #958 merges, this slice is a small, fully-specced fix (Options root + initialize params + capability declaration + scope tests) and can be enqueued directly against the acceptance criteria above.dezren39 commentedon Nov 3, 2026
agent-note:v1
state: triaged (coverage pass)
Coverage pass 2026-11-03: reviewed in the fleet-wide per-issue pass (drift / overlap / already-handled / stale / blockers / ordering). Verdict: still live; queued in repo-health-code-pilot as triage at priority 30 (priority/normal). Issue carries status/blocked; the covering triage must re-derive and name the current blocker. If this is already handled at current main, the triage closes it with evidence; if it needs splitting, the triage files the split.
Found via: coverage pass 2026-11-03
dezren39 commentedon Nov 3, 2026
🤖 Agent note · triaged — confirmed live, blocker cleared, fix packet enqueued
77970ebbc6). The issue's dependency is satisfied.git grep -n 'rootUri|RootURI|WorkspaceFolders|workspaceFolders' origin/main -- 'pkgs/mcpx/**/*.go'returns no hits; the only mentions are inpkgs/mcpx/docs/decisions/0004-scope-resolved-roots.md.small_fix, 45 min):mcpclient.Optionsgains the instance root; when non-empty, initialize (both eras) sendsrootUri= file:// URI of the root,workspaceFolders=[{uri, name=<base name>}], and declaresworkspace.workspaceFolderstrue; empty root keeps initialize byte-for-byte unchanged and global scope fabricates no root. Root comes from theResolvedScopeslice 1 already plumbs. Tests: test-double recording initialize params for repo/worktree vs global.status/blockedis no longer truthful — the blocker has cleared; it is removed as the fix packet queues.go_package_apiproof stays out of scope and depends on this landing.Merge pull request #4992 from developing-today/queue/7814-959-initial…
dezren39 commentedon Nov 3, 2026
Done: slice 3 merged in #4992
mcpclient.Optionsnow carries the instance root, and initialize names it when it is non-empty:rootUri:file://URI of the scope-resolved root.workspaceFolders:[{uri: <same>, name: <base name of root>}].capabilities.workspace.workspaceFolders: true.pool.startLanepassesResolvedScope.Root(slice 1, mcpx: ResolvedScope plumbing + spawn cwd = resolved scope root (#958) #3925).Verified:
go build ./...clean,gofmt -lclean, and the new test-double test records the initialize params — present with a root (uri + base name + capability), absent without one. Targeted run:go test ./internal/mcpx...→ok internal/mcpclient 0.040s,ok internal/pool 0.930s. PR checks:basic: production line limitpass. Merged as62344683de67512ddb4f50e2795af1e9eca525be.Slice 4 — flipping gopls to
worktreescope plus the livego_package_apiproof — is #961, as this issue's own AC says.🤖 Agent note · done
ec118cad-0fd3-4652-91c4-27432f2f2efdorigin/mainbefore working