DUNIN7 · LOOMWORKS · RECORD
record.dunin7.com
Status Current
Path change-requests/cr-2026-210-loomworks-commit-error-truth-v0_2.md

DUNIN7-M4 — INFRASTRUCTURE CHANGE REQUEST

CR-2026-210 — The commit ceremony says what the server said: the catch block stops manufacturing a cause, both directions (v0.2)

Version. 0.2 · Date. 2026-08-14 · Author. Claude Code (drafting) / Marvin Percival (approving). Supersedes. v0.1 (kept). The amendment: §1.C's "No api() change" is lifted for exactly one parse, per the Operator's ruling at the Step-1 halt (session-handoffs/cr-2026-210-step1-halt-v0_1): api()'s 401 branch parses the response body exactly as the non-401 path already does and attaches it as the ApiError's detail; redirect behavior untouched. Everything else in v0.1 stands. Target. /Users/dunin7/loomworks (surface only). Baseline. Surface 8871997. CC confirms at Step 0. Charter. Autonomous regime. Status. APPROVED IN EXECUTION — the v0.1 approval carries; build, test, halt at Checkpoint A.


0. Settled — the Operator's rulings. Do not re-raise.

  1. Site 1 only; the api() change is a parse and nothing more; no shared helper; no general mechanism. The fence of v0.1 §0.1 holds in full.
  2. Why the parse is right beyond unblocking (the Operator's reason, recorded): bypassUnauthorizedRedirect promises "handle this 401 yourself" and delivers half of that — the caller is left with a status and no cause. Fixing the parse makes the flag's name honest — the same class as everything else in this arc, one layer down.
  3. The 401 case remains in scope as ruled in v0.1 §0.2 (failed tap ≠ expired session, or it fixes half), now implementable.
  4. The sweep before the build is BY OBSERVATION, not reading: produce a 401 through each existing consumer and record what it actually receives. That is the whole lesson of the third instance — this CR read the code it was fenced around, cited the flag by name, and still got it wrong because the name misled.

0b. The third instance, counted in its sharpest form (the Operator's wording, recorded)

Wrong about the server (B-96's 503 — the route composes a 200 around key absence). Wrong about the proxy (B-96's 502 — the rewrite answers 500-no-body). Wrong about our own transport, in code the CR itself cited (v0.1 §1.C named bypassUnauthorizedRedirect as the reason no api() change was needed — and the flag skips only the redirect; the body is discarded either way). Three consecutive failure mechanisms produced by reading; three corrected only by producing the failure and watching. The general form now reads: how a stack fails is not visible in the stack, including one's own layer of it — and a name is not a behavior.

1. The changes (v0.1 §1 with the amendment applied)

A0. The api() parse (the amendment — a parse and nothing more). The 401 branch reads the response body with the same content-type-gated logic the non-401 path uses, and throws ApiError("Unauthorized", 401, payload). The redirect condition, its AUTH_FLOW_PATHS guard, and the bypass flag's redirect semantics are byte-identical. A 401's body stops being the only body api() discards.

A. The catch branches on the server's stated cause — as v0.1 §1.A, now implementable: 409 not_converged → the server's message; 401 whose detail is/starts step_up_required, commit_attestation_failed:, commit_challenge_invalid: (all three OBSERVED live at the Step-1 halt, verbatim) → the passkey sentence, no redirect; bare/other 401 → today's redirect, component-driven; other ApiError → FallbackAffordance extraction or honest ignorance; non-ApiError → "The passkey step didn't complete." unchanged.

B. The 401s reach the component. The three commit-ceremony.ts calls pass bypassUnauthorizedRedirect: true; the component performs the expired-session redirect in the bare-401 branch.

C. Nothing else. No engine change; no shared helper; no registry; [B-94] untouched.

2. The pre-build sweep — produce a 401 through each existing consumer, record what it receives

Enumerate every api() caller that can receive a 401 (bypass and non-bypass), then OBSERVE: drive a real 401 through each (invalid/absent session against the live engine) pre-change, and confirm post-change that each receives what it received before plus a detail it ignores. The sweep's pass condition: no consumer's observed behavior changes except CommitCeremony's. Recorded in the checkpoint note with the observed list.

3. Tests — each observed failing first

v0.1 §3's seven component cases, plus: an api()-level test pinning the amendment (a 401 with a JSON body → ApiError.detail carries it; a 401 with no body → detail undefined; redirect fired/skipped per flag, byte-identical to before). The guard stays the point: the 409 body through the component, asserting the passkey sentence does NOT render.

4–6. seed-mutability, build steps, acceptance gate

As v0.1, with Step 1 now reading: the consumer sweep by observation + tests written, observed failing. Acceptance gains: the sweep's no-behavior-change condition holds; the api() diff is a parse and nothing more (reviewed at checkpoint against the fence).

7. Kickoff prompt


Execute CR-2026-210 v0.2 (supersedes v0.1; the api() 401-parse
amendment is ruled). Surface repo only. Baseline 8871997.

§0: the parse and nothing more; the flag's name becomes honest.
Sweep by observation — produce a 401 through each consumer; read
nothing you can produce. The three server spellings are already
observed facts. Halt at Checkpoint A.

DUNIN7 — Done In Seven LLC — Miami, Florida CR-2026-210 — v0.2 — 2026-08-14 A name is not a behavior. The parse makes it one.