Repository navigation
Description
Phase 1 of #1834 — typed sampling errors
Design: #1834 (mcpx sampling trust boundary). Design doc: files/designs/code-mcpx-sampling-trust-boundary.md in the keep-the-four-repos-healthy goal workspace. Origin: dezren39/darwin-nix#256.
Problem
Every sampling failure reaches the upstream as -32603. The 2025-11-25 sampling error table assigns -1 to user rejection and -32602 to tool-shape violations (tool result missing in a request; tool results mixed with other content), but mcpx produces neither: a declined sampling answer becomes errors.New("the sampling request was " + action) in sampleViaBroker (pkgs/mcpx/internal/daemon/hooks.go), an expired/cancelled wait becomes the raw broker Await error, and Client.answer's handler wrap (pkgs/mcpx/internal/mcpclient/modern.go ~L296-303) flattens every handler error to &rpcError{Code: -32603}. Gap: sampling-client-errors-user-rejected-and-tool-shape in pkgs/mcpx/internal/conformance/coverage_clientfeatures.go.
Scope
- A typed sampling-rejection error in the daemon sampling path, carrying its JSON-RPC code.
- Answerer decline or cancel of a sampling question surfaces to the upstream as
-1with the action named in the message. - Expiry / no answerer stays
-32603, with a message explicitly naming expiry — nobody chose, so it is not a rejection. Do not map it to-1. Client.answer's handler-error wrap preserves a typed error's code instead of flattening it to-32603(typed errors pass through; untyped handler errors keep today's-32603).- Define the
-32602tool-shape error type here so Phase 2 (mcpx: design — sampling trust boundary (reviewable, validated, honestly error-coded) #1834's validation phase) raises it; Phase 1 does not itself add content checks.
Out of scope: any message/result validation (Phase 2), CLI rendering (Phase 3), elicitation error paths (untouched), sampling rate limits (nix#257).
Tests (defining)
- Declined sampling answer → upstream sees
-1naming the decline. - Cancelled sampling answer → upstream sees
-1. - Expired wait (broker TTL) → upstream sees
-32603with expiry named in the message. - Untyped handler failure → still
-32603. - Elicitation decline/cancel behaviour unchanged (existing tests pass).
Acceptance criteria
- Declined/cancelled sampling reaches the upstream as
-1; expired waits as-32603naming expiry; the typed-error passthrough inClient.answeris covered by tests in both the legacy wire path and the moderninput_requiredpath (the answer path is shared — verify both). - Gap
sampling-client-errors-user-rejected-and-tool-shapeis retired for its-1half; the-32602half is exercised end-to-end by Phase 2. - No elicitation error behaviour changes.
Activity
developing-today commentedon Oct 28, 2026
CODE-764
dezren39 commentedon Oct 28, 2026
Phase 1 of design #1834, filed by the design architect (2026-10-28). Triage packet enqueued to repo-health-code-pilot as task 2718 (verified: queue=repo-health-code-pilot, status=queued, last_error=null).
30 remaining items
dezren39 commentedon Oct 29, 2026
🤖 Agent note · parked (Lane C shift, gate recheck 23:01Z)
dezren39 commentedon Oct 29, 2026
Lane D (queue task 3050) gate recheck: PR #2440 still OPEN/CLEAN/MERGEABLE at 8e5c00d, no failing or pending checks; #2403 still OPEN; main still 5a34fa7. Gate unmet — re-parked without another enqueue cycle (four enqueue attempts by this shift on sibling PRs were all ejected within minutes; evidence on #2403). Resume verbatim: main advances past 5a34fa7 or #2403 closes → disposition any Codex findings on #2440 → re-enqueue → merge → complete fixed_merged + close this issue.
dezren39 commentedon Oct 30, 2026
🤖 Agent note · done
task/triagelabel was also removed — this was an implementation fix, not a triage item).