Repository navigation
Description
Design from the design-architect pass 16 (2026-10-29). Full design doc: files/designs/code-mcpx-error-honesty.md in the keep-the-four-repos-healthy goal workspace. Origins: conformance gap errors-local-errors-not-mistaken-for-peer (ex-nix#206) and the accept-unadvertised + 32021-broker-fallback gap keys of #1957 (ex-nix#257 — split out under its own acceptance rule, same pattern as #2192). Audited against origin/main 5a34fa70.
Problem
mcpx sits between two peers and speaks for both, but its errors do not say whose they are:
- A peer's failure arrives dressed as mcpx's own. Pass-through relays an upstream JSON-RPC error whole (
UpstreamError,internal/mcpserver/capability.go). The gateway path flattens the same failure to text at the daemon/v1surface, theninternal/cli/serve_ask.go(~L225-255) reconstructs it by guessing at the text — with exactly one structured special case (-32021 at serve_ask.go:241). Structureddatais destroyed and heuristically rebuilt. Spec (2026-07-28, lowercase should): local errors surfaced in JSON-RPC-shaped structures "should ensure they cannot be mistaken for errors received from the peer." - mcpx answers methods it did not advertise.
capabilities()(server.go:2410) declarescompletionsonly where the revision defines it — with the comment thatcompletion/complete"is answered for every revision" — so a 2024-11-05 peer is served a method that cannot be advertised to it;resources/subscribeis dispatched unconditionally (server.go:938) even whenresources.subscribewas advertisedfalse. The 2026 schema's MethodNotFoundError guidance asks for -32601 for a method "gated behind a server capability the server did not advertise". TheRemoved()check (server.go:785) is the precedent seam; modern HTTP already pairs -32601 with 404 (modernStatus). -32021exists only in islands. Emitted correctly by tasksmissingTasks(tasks.go:199) andsubscriptions/listen(listen.go:138), relayed in pass-through — but when a gateway call cannot finish without a capability the host never declared, the question waits in the broker even when no broker audience can answer it. ERR-08 (pkgs/mcpx/docs/compare/register/errors.md) + conflict Bump build/buck/preludes/buck2-prelude from3a02ea3to3e4d218#8 (docs/spec/revision-conflicts.md) already record the resolution: mcpx never requires the capability while a broker audience can answer — the complement (no audience ⇒ required ⇒ -32021) is unimplemented.
Decisions recorded
- One structured error carriage through the gateway. The
/v1call reply gains a structured upstream-error field (code/message/data); the gateway relays it verbatim viaUpstreamError; text-reconstruction heuristics are deleted wherever the structured field is present. mcpx's OWN errors are minted through one helper that stampserror.datawith an origin marker ("mcpx": {"origin": "local"}) — peer errors never gain it, local errors always carry it. That asymmetry is the "cannot be mistaken" mechanism. No new codes, no message prefixes. - Dispatch consults the same map advertisement used. One gate after the
Removed()check: refuse -32601 any method whose gating capability is absent/false in thecapabilities()map for that peer. Initial gated set is only the two proven disagreements:completion/complete←completions(pre-completions revisions),resources/subscribe/unsubscribe←resources.subscribe. Accept-liberally stands for everything else; the gate's table grows by evidence. Tasks keep their own gating. -32021exactly when waiting is not an answer. At the ask seam: question needs a capability the peer did not declare AND the broker has no audience that can answer it ⇒ modern peer gets -32021 withdata.requiredCapabilities(existing shape; HTTP 400 viamodernStatus); legacy keeps existing behaviour. When any audience can answer, the broker fallback is unchanged.
Phases
- Phase 1: structured carriage + origin marker (independent).
- Phase 2: advertised-capability gate (independent).
- Phase 3: -32021 at the ask seam + register/conflict truth-up + gap rows retired + mcpx: smaller conformance gaps -- user identity, annotation trust, rate limits, cursors, URI encoding, prompt validation, restart, invalidation #1957/Phase 8: open design items, retention, multi-device, and views #206 evidence (gated on Phase 1).
Open questions stay in the design doc (client-side origin marker vs #1481's choke point; prompts-validate-io deliberately excluded — it neighbours #1481, not this seam; gated-set growth needs evidence; ERR-09/ERR-13 belong to #2209's classification, not absorbed here).
🤖 Design-architect pass 16 — agent note: this issue is the design of record; phases are its sub-issues. Do not re-derive the decisions above in triage; flag genuine blockers here instead.
Acceptance criteria
- The three implementation phases (mcpx: Phase 1 of #2434 — structured upstream-error carriage through the gateway + local-error origin marker #2435, mcpx: Phase 2 of #2434 — advertised-capability gate at dispatch (-32601 for completion/complete pre-2025-03-26 and resources/subscribe when not advertised) #2436, mcpx: Phase 3 of #2434 — -32021 when no broker audience can answer + error-register truth-up (ERR-08, conflict #8, three gap rows) #2438) stay linked from this design issue until each merges or is explicitly declined with rationale recorded here.
- Each phase meets its own acceptance criteria; no phase widens scope beyond the design doc (
files/designs/code-mcpx-error-honesty.md). - When all phases have landed or been declined, this issue closes with a summary linking the merged PRs.
Activity
developing-today commentedon Oct 29, 2026
CODE-1241
dezren39 commentedon Oct 29, 2026
🤖 agent-note:v1 — design-architect pass 16 (2026-10-29). Design of record for the error-honesty cluster: origins are the conformance gap
errors-local-errors-not-mistaken-for-peer(ex-nix#206) and #1957'saccept-unadvertised+32021-broker-fallbackkeys, split out under #1957's own acceptance rule. Phases: #2435 (structured carriage + origin marker, pilot task 3646 queued), #2436 (advertised-capability gate, pilot task 3647 queued), #2438 (Phase 3: -32021 when no broker audience can answer + truth-up, gated on #2435, pilot task 3648 queued). All three linked as sub-issues and verified. Nouser/review: the spec rows and ERR-08/conflict #8 already record the ends; the judgment calls are the architect's, recorded in the design doc.dezren39 commentedon Oct 30, 2026
Intake review (fleet monitor, 2026-10-29 run):
files/designs/code-mcpx-error-honesty.md(goal workspace); origins cited in the body (mcpx: smaller conformance gaps -- user identity, annotation trust, rate limits, cursors, URI encoding, prompt validation, restart, invalidation #1957 gap keys, ex-nix#206/CI: nix flake check intermittently dies with 'No space left on device' in id-test/id-ci #257).developing-today 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 40 (priority/normal). 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 · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · handed off
dezren39 commentedon Nov 4, 2026
🤖 Agent note · picked up
queue/claimed,work/assigned,status/in-progress); no hard-stop labels. Linked PR feat(mcpx): advertised-capability gate at dispatch (#2436) #2873 is merged.dezren39 commentedon Nov 4, 2026
agent-note:v1
event: triaged
task: 7917
worker: repo-worker-code (OpenChamber scheduled lane 8ac61616-3815-4e7b-b33d-840a3829154a)
checked: 2026-11-04 at current main origin/main@85c0e0b89
verdict: STILL LIVE; keep #2434 open under its own acceptance criteria.
evidence:
ordering: mcpx: Phase 1 of #2434 — structured upstream-error carriage through the gateway + local-error origin marker #2435 must land before mcpx: Phase 3 of #2434 — -32021 when no broker audience can answer + error-register truth-up (ERR-08, conflict #8, three gap rows) #2438; mcpx: Phase 2 of #2434 — advertised-capability gate at dispatch (-32601 for completion/complete pre-2025-03-26 and resources/subscribe when not advertised) #2436 is complete.
scope: no code changed; Phase 1 stays on mcpx: Phase 1 of #2434 — structured upstream-error carriage through the gateway + local-error origin marker #2435 and Phase 3 stays gated as filed.