Skip to content

mcpx: Phase 1 of #1834 — typed sampling errors (-1 on rejection, -32602 tool-shape, expiry stays -32603) #1835

Closed

Description

@dezren39

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 -1 with 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 -32602 tool-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 -1 naming the decline.
  • Cancelled sampling answer → upstream sees -1.
  • Expired wait (broker TTL) → upstream sees -32603 with 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 -32603 naming expiry; the typed-error passthrough in Client.answer is covered by tests in both the legacy wire path and the modern input_required path (the answer path is shared — verify both).
  • Gap sampling-client-errors-user-rejected-and-tool-shape is retired for its -1 half; the -32602 half is exercised end-to-end by Phase 2.
  • No elicitation error behaviour changes.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)
    effort/mMedium: expected under 1 day of work
    on Oct 28, 2026
  2. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  3. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    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).

  4. 30 remaining items

  5. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Oct 29, 2026
  6. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked (Lane C shift, gate recheck 23:01Z)

  7. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    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.

  8. dezren39 commented on Oct 30, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

  9. removed
    task/triageQueue packet kind: verify, reproduce, and route this item
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    work/assignedQueue worker lifecycle state
    on Oct 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/mcpxPackage/app: mcpx (pkgs/ or apps/ in this repo)effort/mMedium: expected under 1 day of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/design-architectFiled by the repo design architect job

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions