Version. 0.1 · Date. 2026-08-14 · Author. Claude Code (drafting, from [B-96] + its scoping note) / Marvin Percival (approving).
Target. /Users/dunin7/loomworks (surface only — the scoping established the branch is status-class; the converse residue carries no stable codes and needs none; no server prerequisite). Baseline. Surface 00ed2f2. CC confirms at Step 0.
Companion to. [B-96] (build list v0.75, corrected entry), scoping-notes/loomworks-b96-converse-failure-vocabulary-scoping-note-v0_1, standing note v0.4 third revision.
Ordering. RANKS ABOVE CR-2026-210 per the Operator; 210 holds until this ships.
Charter. Autonomous regime. Status. DRAFT — awaiting the gate. Do not execute.
/operator/converse: useConversation.ts:448 and ChatView.tsx:535. Nothing else — dev-auth is nothing; the second-tier cause-discarding sites are not this CR.no_credential is NOT a member (the route composes a 200 around it).
A. The shared helper. converseFailureMessage(err: unknown): string (home: src/lib/api/converse.ts, next to the call both sites wrap):
ApiError (thrown fetch — network/frontend down; nothing came back) → "Couldn't reach the Companion. Try again in a moment." — the sentence, kept where it is true.ApiError 502/503/504 (the Next rewrite's proxy layer: engine down or restarting — a real state on this deployment; the Companion's process was not reached) → the same sentence — true in substance.ApiError with a response (500, 422, anything else — the server was reached) → the FallbackAffordance extraction: a usable string detail renders when present and informative; else "Something went wrong on our side. Try again in a moment." — honest ignorance, no manufactured cause. (The 500's constant "Internal Server Error" body counts as uninformative; the generic renders.)
B. The two catch sites call it. Each site's non-401 arm becomes setError(converseFailureMessage(err)) / setLocalSendError(...) respectively. The 401 arms are untouched (their silent-return/redirect behavior is not this CR — and not CR-210's §B either; converse 401s are session-expiry, correctly redirected).
C. Nothing else. No engine change; no change to the armored 200-composed server paths; no shared component; no registry; [B-95]/CR-2026-210 untouched behind this per the ranking.
Helper unit tests (all three branches) plus per-site component/hook tests:
ApiError 500 body {"detail": "Internal Server Error"} through each site → the generic renders; the unreachability sentence does NOT render (the guard, both sites).ApiError 422 with a field-error array → the generic renders; no unreachability sentence.TypeError (fetch failure) → the unreachability sentence DOES render — the true branch is pinned, not just the false ones removed.ApiError 502 → the unreachability sentence renders (the engine-down case).ApiError 500 with a real string detail (a future engine error) → the detail renders (FallbackAffordance shape).Existing converse/ChatView suites re-run.
Kind C expected: surface error-rendering only; nothing reads or writes the seed. Checked at Step 1; a null finding is an entry.
| Step | What | Mode | |---|---|---| | 0 | Pre-flight — baseline, clean tree. | Auto | | 1 | Verify the two catch arms + the rewrite's engine-down status (probe the proxy with the engine stopped in dev — observed, not assumed); tests written, observed failing. | Auto | | 2 | The helper + the two call sites. | Auto | | 3 | vitest; tsc. | Auto | | 4 | Eye-test: with the dev engine STOPPED, send a turn → the unreachability sentence (true branch, observed live); engine up, force a 500 (dev-only route or mocked) if practical — else the 500/422 branches ride on the tests. | Auto | | A | Checkpoint. | Checkpoint | | 5 | Push; watch the run; redeploy; post-deploy smoke on the conversation surface. | Auto |
Execute CR-2026-211 v0.1 at change-requests/cr-2026-211-loomworks-
converse-error-truth-v0_1.md in loomworks-record. Surface repo only
(/Users/dunin7/loomworks). Confirm baseline first.
§0: two sites, one route, one string-returning helper — the line is
a code table or a route parameter. Status-class branching; the
corrected vocabulary (500/422 are the false members, no_credential
is not one) is ground truth. Pin the TRUE branch too: thrown fetch
must still say "couldn't reach."
DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-211 — the converse catches tell the truth — v0.1 — 2026-08-14 The sentence keeps its true branches and loses its false ones.