Packet — R93 B3 Document Dual Error-Envelope Pattern in s17

Round: R93 debug-sweep Branch: feature/r93-b3-s17-dual-envelope Audit: docs/audits/r93-b3-s17-dual-envelope-audit.md Contract: docs/contracts/r93-b3-s17-dual-envelope-contract.md β task: 1a267787-b864-4f5f-a7dd-669a6268dbe7

§1. Edit list

# File Operation
1 docs/spec/s17-mcp-surface.md Edit §6 “Response shape” (lines 77-91 of the existing file). Replace single error-envelope block with §6.1 Success envelope, §6.2 Failure envelopes — two patterns, §6.3 Pattern attribution by tool family.

No code edits. No other doc edits.

§2. Replacement text (canonical)

## 6. Response shape

The α middleware emits a uniform success envelope. Failure paths use one of two patterns, depending on whether the handler **threw** or **returned a structured error value**. Both patterns are observable on the live MCP wire and are intentional.

### 6.1. Success envelope

```json
{ "ok": true, "data": { /* tool-specific payload */ } }

Every successful handler return is wrapped in this shape by src/server.ts:357-361. The data payload is the unwrapped return value.

6.2. Failure envelopes — two patterns

Pattern A — middleware-emitted (handler threw). The α middleware catches a thrown error at Stage 4 (src/server.ts:362-375) or rejects an invalid input at Stage 2 (src/server.ts:309-336) and emits:

{ "ok": false, "error": { "code": "INVALID_PARAMS|HANDLER_ERROR", "message": "<human>", "details": { /* optional */ } } }

The JSON-RPC structuredContent IS this envelope; isError: true is also set at the transport layer. Error codes:

  • INVALID_PARAMS — Zod input validation failed. details.issues carries the Zod issue list.
  • HANDLER_ERROR — the handler threw at runtime. message carries the thrown error’s .message.

Pattern B — handler-returned (no throw). Some handlers return a structured error value as their normal return; the middleware wraps it in the success envelope of §6.1, leaving the domain error inside data:

{ "ok": true, "data": { "ok": false, "error": { "code": "<DOMAIN_CODE>", "message": "...", /* optional fields */ } } }

structuredContent.ok === true but structuredContent.data.ok === false. Clients reading ok at the top level alone will miss the error. This pattern is the canonical “domain error vs transport error” distinction and is documented at src/tools/merkle.ts:392-405 (which calls out the same pattern in src/domains/tasks/repository.ts:700-765).

A defensive client should read both structuredContent.ok AND, when it is true, also inspect structuredContent.data?.ok before treating the response as success.

6.3. Pattern attribution by tool family

Tool family Pattern Notes
α System (server_ping, server_health) A No domain errors; only INVALID_PARAMS is reachable
ε Skill (skill_list) A Throws on DB error
ζ Decision Trail (thought_record, thought_record_list, audit_verify_chain) A Throws on Zod failure / SQLite UNIQUE violation
β Task Pipeline (task_create, task_get, task_update, task_list, task_next_actions) B Returns {ok:false, error:{code:"ERR_NOT_FOUND|ERR_WRITEBACK_REQUIRED|ERR_INVALID_TRANSITION|…"}} as data
η Proof Store (audit_session_start, merkle_finalize, merkle_root) B Returns {ok:false, error:{code:"ERR_SESSION_EXISTS|ERR_SESSION_NOT_FOUND|ERR_ALREADY_FINALIZED|ERR_NO_RECORDS|ERR_NOT_FINALIZED"}} as data
λ Reputation (reputation_*) A Throws on Zod failure
θ Consensus (consensus_*, vrf_eval) A Throws on Zod failure or domain error (ROUND_NOT_FOUND, ALREADY_VOTED, INVALID_KEY) — error code is encoded in the message prefix
δ Router (router_*) A Throws on Zod failure or FallbackChainExhaustedError

Both patterns are stable for Phase 0+; clients SHOULD support both. Future phases MAY unify on one pattern, but that is a separate scope (docs/architecture/decisions/).

6.4. Stable error codes

The complete catalogue of stable error codes per tool — both Pattern A INVALID_PARAMS|HANDLER_ERROR.message strings and Pattern B data.error.code values — lives in docs/reference/mcp-tools-phase-0.md. That catalogue is the source of truth for the precise string each tool produces.


## §3. Build/lint/test

Doc-only change → no source impact. Run `npm run build && npm run lint && npm test` to confirm baseline behaviour (3492 / 79 suites + documented flakes).

## §4. Commit message template

docs(r93-b3): document dual error-envelope pattern in s17

The α middleware emits one success envelope but two distinct failure envelopes: Pattern A (handler-threw → middleware wraps as {ok:false, error}), Pattern B (handler-returned error envelope as data → middleware wraps as {ok:true, data:{ok:false, error}}). Both are intentional and stable on the Phase 0+ MCP surface, but the spec at s17 §6 documented only one. A naïve client that checks structuredContent.ok alone misses Pattern B errors.

This patch restructures s17 §6 into three subsections: 6.1 Success envelope 6.2 Failure envelopes — two patterns 6.3 Pattern attribution by tool family

References the canonical Pattern B definition at src/tools/merkle.ts:392-405. No code touched.

Closes R93 B3. ```

Proceeding to implement.


Back to top

Colibri — documentation-first MCP runtime. Apache 2.0 + Commons Clause.

This site uses Just the Docs, a documentation theme for Jekyll.