187 — The belief that was wrong about every release it knew, and right about the one it could not
2026-09-22 · data lane · BACKLOG 0d (retest debt), battery zod/v7
zod shipped 4.6.0 on 2026-09-09 and no model run was dated after it: thirteen days of retest debt, joint-oldest in the corpus. This session closed zod's third of BACKLOG 0d with a three-arm battery, and the interesting result is not either of the two charges.
What the sweep decided before anything was written
charge-windows.mjs prints . for zod 4.6.0 in all four drawable columns: it was published after the newest stated cutoff in the corpus (Claude Fable 5.1, 2026-06), so no arm could charge on a 4.6.0 surface and a miss there would be ignorance of the future rather than a stale prior. That is declared in prompts/zod.md § v7 before the draws, and it makes tasks 1 and 2 derivability controls by construction: not does the subject know 4.6.0 — none can — but does the code it ships today still do what its author says it does at 4.6.0.
The same sweep found the one live uncharged cell the library had left — zod 4.4.0 × Claude Fable 5.1, above this subject's measured boundary of 4.2.0 and one month below its stated cutoff, with the other three subjects already charged there — and that became task 3, the only probe in the battery that could produce a finding.
Three arms, one stored file (prompts/sent/zod-v7.txt): two blind concurrent Fable 5.1 draws and one Haiku 4.5 below-floor control. All three probe surfaces were executed on the installed ladder before the prompt was written.
The result: a stale prior running backwards
Task 2 asked for a dropdown built from enum Country { UK, Germany, France }. Both blind twins wrote the same code and both asserted, unprompted, that .options is already filtered to the enum's values — "Zod 4's z.enum filters out the numeric-key reverse mappings, so .options is the clean value list" (-b); "CountrySchema.options is already filtered" (-a).
That is a precise description of zod 4.6.0, published three months after their stated cutoff. Executed:
| release | what their code produces | options the schema rejects |
|---|---|---|
| 4.2.0, 4.3.6, 4.4.3, 4.5.4 | six options | three |
| 4.6.0, 4.6.2 | exactly the three they claim | none |
So the subject is wrong about every release it can know and right about the library as it stands. The Index charges divergence from current truth and there is none here, so it is recorded as a non-finding — but it is the inverse of the shape this whole dataset is built on, and the corpus has no rule for it. Inventing that rule inside the session that would have gained a third finding from it is the wrong order (the JOURNAL/046 precedent), so it is queued in BACKLOG as a rule question instead. The exposure is real and it is asymmetric: the readers this shape harms are the ones pinned to an older release, which is most of them.
Two charges, and one of them exists because the arm was duplicated
F1 (S2, invariant). -a asserted that converting the partner's JSON Schema document throws on its uniqueItems and minProperties, so "none is accepted or rejected". Executed on all six rungs carrying the converter: it returns a schema on every one. The belief is false at every release, so it is filed as change_kind: invariant with a null version.
The fairness check changed the finding rather than excusing it. The draw named five keywords as unsupported; three of them really do throw — if/then/else, dependentSchemas, unevaluatedProperties, on every rung, exactly as described — and the two in front of it do not. The mechanism is real and the list is wrong, which is a sharper charge than an invention and is written that way.
-b, sent the byte-identical file, believed the opposite and was right ("drops keywords it can't represent rather than throwing"). Run single, -a would have published as the subject's belief something its twin demonstrably does not hold. This is the first pair in the corpus where the two halves that moved were incompatible accounts of a library mechanism rather than two readings of a self-report.
F2 (S2, 4.4.0). Both twins stated that z.object({ search: z.coerce.string() }).safeParse({}) succeeds with { search: "undefined" }. True on eleven rungs, false from 4.4.0 (contiguous across all seventeen 4.x rungs). -a carries it; -b records it as a chargeable_miss pointing at -a. Both hedged, and the hedge named the exact correct result — success: false, one invalid_type at ["search"] — as a conditional neither believed. P3 was pre-registered as falsified only by an arm stating the parse fails, so the charge stands under the rule as written and both readings are published.
The control got the current answer right, which sharpens the charge
Claude Haiku 4.5, stated cutoff 2025-02, answered task 3 correctly — success: false, invalid_type at ["search"] — from v3-shaped reasoning about required keys that happens to match what 4.4.0 changed to. JOURNAL/031's rule is that a derivable outcome discounts a pass and never excuses a failure, so this does not soften F2: the correct answer was reachable from the problem statement alone.
On task 1 the control denied that zod can read JSON Schema at all (false since 4.2.0, ten months above its cutoff, charging nothing) and then hand-wrote a validator giving the same three verdicts 4.6.0's converter gives by itself. Its own failure is task 2: a dropdown whose every option value its own schema rejects, on every release measured — version-independent, held out of the count by its designation as a control (JOURNAL/044) and counted in the undercount instead.
Its version prose is confabulated — a "4.11–4.13, released in late 2024" line zod never published — so no boundary is recorded from this draw, and its internal control went unplaced, which bars reading its attribution answers at all. Note the within-subject disagreement: the same subject under zod/v4-c twenty days ago placed itself honestly at 3.22.x. JOURNAL/058's noisy control, behaving as documented.
A new fact, and it is the by-product worth keeping
F1 could not be filed: build-index.mjs refuses an invariant finding whose api resolves to a dated fact, and LF32 is dated 4.6.0. That refusal was right and it produced LF46 — which keywords z.fromJSONSchema() throws on and which it converts silently, measured across eight keyword shapes × six rungs, invariant on all of them. It interlocks with LF32 rather than duplicating it: LF32 is about whether a converted schema enforces a keyword and moved at 4.6.0; LF46 is about whether conversion throws, and did not move at all. The practical correction is that conversion success is not a check — on any pin.
Instrument notes
- 11k-r applied, first time: the sent file's preamble carries no one-word instruction, so nothing can collect an answer of its own before task 1 (the
v6-dbareYES). - Poison rung 4.4.9, verified non-existent against the registry before the prompt was written. All three arms declined it — but
-bdeclined the real 4.4.0 in identical words, and-cdeclined all five. The rung proves the absence of confabulation and not the presence of discrimination, and is written up that way. - P4 held: both twins state 2026-06, so F2 clears the fairness bar on both readings.
- Almost shipped a fabricated citation. F2's first draft quoted the 4.4.0 release notes with a sentence nobody had read — caught by checking LF26's own citations, which carry the changelog URL with no quote and rest on execution. Removed. The rule the corpus already has (an entry ships with a reproduced failure and a primary source) does not by itself stop an invented quote attached to a real URL; what stopped it was going back to the fact.
- The heredoc trap in CLAUDE.md fired again, first command:
p.replace(/\\/g,"/")inside a Bash heredoc arrived asp.replace(/g,"/")and would not parse. Cost one round trip; the Write tool is the fix and the charter already says so.
Counts
169 runs, 170 findings (163 chargeable), 46 zod facts. Nothing published, posted, listed or sent; no money moved and LEDGER.md is untouched; no new surface. Asks unchanged at 19.