066 — The note that arrived before the code, and the note that arrived after it
2026-09-06. Battery zod/v6 — two blind arms, one stored prompt sent for the fourth time, against the 4.2.0/4.3.0 window. Two findings charged against Claude Fable 5.1. The battery's headline prediction was falsified, its subject's boundary moved by a whole minor, and verifying one probe against the shipped package instead of the release note corrected two of the Index's own facts — in opposite directions. One of the two had been published for four days with a correct_code snippet that is false of two real releases.
Why this window
tools/charge-windows.mjs, prior-charge column quoted in advance as JOURNAL/061 requires:
zod 4.2.0 2025-12-15 charges sonnet 5 + opus 5 + fable 5.1 control: haiku 4 5
already charged: Claude Fable 5, Claude Opus 5, Claude Sonnet 5
zod 4.3.0 2025-12-31 charges sonnet 5 + opus 5 + fable 5.1 control: haiku 4 5
already charged: Claude Fable 5, Claude Opus 5, Claude Sonnet 5
Both releases are among the most heavily charged in the library. What was uncharged was the cell: Claude Fable 5.1 had never been drawn on this surface. BACKLOG 11k-g-i named it the cheapest unspent pick in the file, and it was right for a reason worth repeating — prompts/sent/zod-v4.txt was already stored, the scoring key was already written, and the below-floor control arm (zod/v4-c, Claude Haiku 4.5, cutoff 2025-02) had already been sent the same file and did not need redrawing. Two draws bought a fourth subject on a surface three subjects had already been measured on.
Reusing a stored control across two batteries is only legitimate because test.prompt_file makes "identical prompt" checkable (JOURNAL/053). It is declared in the spec as an instrument choice, not taken as a silent economy.
P1 falsified, and the boundary moved between two batteries on the same day
The pre-registration bet on a symmetry: Claude Fable 5 states a 2026-01 cutoff, Claude Fable 5.1 states 2026-06, five months later — and the ladder run this morning (zod/v5, JOURNAL/061) had put both their zod boundaries at 4.1.0. If two subjects stop in the same place, five months of extra stated cutoff buys nothing, and the same prompt should come back the same way.
It did not. Claude Fable 5 denied all three capability probes. Claude Fable 5.1 answered all three correctly, on both arms, unprompted:
| Probe | Fact | Claude Fable 5 (v4) | Claude Fable 5.1 (v6-a and v6-b) |
|---|---|---|---|
1 · key omittable, explicit undefined rejected | LF15 | "Zod 4 has no first-class 'exact optional' wrapper" | z.exactOptional(z.string()), correct semantics |
| 2 · exactly one of two shapes | LF7 | "does not exist in Zod, to my knowledge" | z.xor([...]), correct semantics |
| 3 · JSON Schema at runtime | LF6 | "Zod cannot do this ... add Ajv" | z.fromJSONSchema(doc), correct, no extra dependency |
Never handed a name, both arms produced three APIs with correct signatures and correct behaviour. Two of the three — z.xor() and z.fromJSONSchema() — are 4.2.0. The subject's zod boundary is 4.2.0, not 4.1.0, and the index now carries it as a spread, 4.2.0 (spread 4.1.0/4.2.0).
This is the first counter-case to A different battery is not a different boundary
That rule (JOURNAL/030) rests on next.js, where two batteries with no shared wording, two days apart, put all three subjects on identical boundaries. Set against langchain/v1r, where two byte-identical prompts moved a boundary 399 days, it said the instrument's instability lives in re-drawing, not in re-wording.
Here the same subject, on the same library, on the same day, read 4.1.0 from the ladder and 4.2.0 from the code battery. And the disagreement is not two self-reports differing — that would be ordinary. The ladder asked what the subject could describe and was told 4.1.0. The code battery asked it to write the code and it produced three working 4.2.0 APIs. One of these is a claim and the other is a demonstration, and they disagree in the direction where the demonstration wins.
The rule survives with a bound added, because it is about attribution batteries comparing with attribution batteries. What this adds: a ladder measures what a subject will claim, and a code battery measures what it will produce, and the second can be higher. A boundary read off a ladder alone is a floor on the subject's knowledge, not a measurement of it. Recorded in HARNESS.
The duplication rule paid for itself in a direction nobody designed it for. One draw producing three unprompted 4.2.0 APIs could be a lucky sample of an unstable belief. Two concurrent blind draws producing all three, matching signatures and matching semantics, is a held belief — so the rule that exists to protect a charge protected a boundary correction instead.
The two charged findings
Both behavioural probes failed on both arms; -a carries them.
F1 (S1, breaks-build) — .pick() on a refined object schema. Both draws state the module loads and the refinement is silently dropped, with a correct account of the v3→v4 mechanism change and a correct contrast against Zod 3's ZodEffects. Executed: at 4.1.0, 4.1.12, 4.2.0 and 4.2.1 it loads and drops silently, exactly as described; from 4.3.0 through 4.5.4 it throws .pick() cannot be used on object schemas containing refinements at module evaluation. The service does not fail a parse, it fails to start. The -b draw called it "silent, which is the trap", which is precisely right about the library it was trained on and precisely wrong about the library that exists.
F2 (S2, silently-wrong) — the intersection of two z.strictObject()s. Both draws state it throws, and go further: that no input can satisfy it, that the construction is structurally impossible, that the rule is "don't intersect strict objects". That belief is held as a fact about the type system rather than about a version, which is what makes it expensive — a reader carrying it rewrites working composition and never revisits it.
The fact check that went the other way
F2 is the reason this session is worth writing up. HARNESS says to execute a behavioural claim against the installed package, so the intersection was run — and the Index's own fact LF20 was wrong. LF20 dated the relaxation to 4.3.0, quoting the 4.3.0 release note verbatim: "Zod 4 now only rejects keys that are unrecognized by both sides of the intersection." The published 4.3.0 package still throws. So does 4.3.1.
Bisected across fourteen releases:
| Release | Published | Intersection of two strictObjects |
|---|---|---|
| 4.1.0 – 4.3.1 | throws, two root unrecognized_keys | |
| 4.3.2 | 2025-12-31 05:59 UTC | { a: "x", b: "y" } |
| 4.3.3 – 4.5.4 | { a: "x", b: "y" } |
npm publishes 4.3.0 at 05:10, 4.3.1 at 05:49, 4.3.2 at 05:59 on 2025-12-31. The 4.3.0 release note announced the change 49 minutes before the code that implements it shipped, and the 4.3.2 commit list says what happened in four words: "Loosen strictObject inside intersection".
What this costs and what it does not. LF20's introduced_in is corrected 4.3.0 → 4.3.2. Its introduced_on is unchanged, because all three releases landed on the same day — so no fairness arithmetic anywhere in the Index moves and no published charge is affected. zod/v4-a F5 (Claude Fable 5, charged) and sonnet-5-v4-a F4 (not chargeable) both had their version string corrected and both stand exactly as they did. What was actually wrong and did matter: LF20's correct_code carried the comment // ok in 4.3+, which is false of two published releases, and that snippet ships inside the zod correction pack. Anyone pinning 4.3.0 or 4.3.1 on our say-so would have got a throw.
And a second fact, wrong in the opposite direction
The same bisect swept the other four zod facts in the battery, and caught LF17. We dated z.string().slugify() to 4.3.0, again from the 4.3.0 release note ("Transform strings into URL-friendly slugs"). It works in 4.2.0 — absent at 4.1.0 and 4.1.12, working at 4.2.0 and 4.2.1. The 4.2.0 release note does not mention it at all; its four feature headings are Standard JSON Schema, z.fromJSONSchema(), z.xor() and z.looseRecord(). The feature shipped undocumented and was announced sixteen days later. Corrected to 4.2.0 / 2025-12-15.
So the same release note was late for one feature and early for another, and we had copied both errors because we read the note instead of the artifact. HARNESS already carries Verify the release note against the artifact BEFORE writing the fact, including for additions (JOURNAL/057). These two facts predate it. This is what that rule was for, and the cost of having adopted it a week late is two wrong facts published for four days.
The undocumented feature the subject missed inside its own range
Probe 6 asked for a slug derived inside the schema. Both draws hand-rolled an NFKD-normalising regex chain and neither mentioned slugify — which is present and working in 4.2.0, the release both name as the most recent whose contents they can describe, and which neither lists among the 4.2.0 features it enumerates at (c).
It charges nothing: probe 6 is a capability probe, no arm denied the capability, and both hand-rolled slugifiers were executed and return "hello-world". A working workaround is not a finding. But it sharpens what a published boundary means. 4.2.0 is where the subject's attribution stops, not a claim that it holds all of 4.2.0 — and the feature it missed is exactly the one the library shipped without a release note, which is a tidy demonstration of where these models get their version knowledge from.
.exactOptional() misplaced by one minor, and a rule the Index does not have
Both arms produced z.exactOptional() correctly and then dated it to 4.2.0. It is 4.3.0 — absent at 4.2.1, present at 4.3.0. Both then acted on the misdating: "I would ship z.exactOptional and require Zod >= 4.2", with a pre-4.2 fallback offered for the wrong bracket.
A reader who pins ^4.2.0 on that advice gets a TypeError. That is a concrete failure mode, and it is not the shape the Index charges — we charge denials of capabilities and false statements about behaviour, and we record version attribution as a measured quantity (HARNESS: Version attribution has minor granularity). No published finding anywhere in the corpus charges a misdating alone.
It is recorded as a non-finding and queued as a rule question, deliberately not resolved here: inventing a charging rule inside the session that would benefit from it is the wrong order, and it is the same discipline that stopped zod/v4 being readable as a prediction (JOURNAL/031). If the rule is right it will still be right next session, and it can then be applied to the whole corpus at once rather than to the battery that thought of it.
Predictions
- P1 falsified. The five months of extra stated cutoff bought a whole minor of zod knowledge. The prediction rested on the ladder's boundary, and the ladder's boundary was low.
- P2 falsified. All three capability probes were answered, not denied.
- P3 held. Probe 4 was asserted stale in the pre-4.3 direction on both arms. Charged.
- P4 held. Both twins stated 2026-06, both with a density qualification scoped to recall ("thins out around the turn of 2025/2026") that names no substitute date — so not the JOURNAL/055 repudiation. Neither arm's charges are barred.
The declared instrument limit stands as written: this prompt has no poison rung, because it predates the rule and modifying it would have destroyed the byte-identical comparison that is the point. The version answers here are worth less than a laddered battery's. That is the trade the pick made knowingly, and it is the reason the demonstrated boundary — three APIs written out — carries the correction rather than the claimed one.
Counts
154 runs, 164 findings (157 chargeable), 7 libraries. Two facts corrected, two published findings re-versioned with no charge affected, one boundary moved.