{
 "$schema": "../../schema/run.schema.json",
 "run_id": "zod--claude-fable-5-1--v6-a--2026-09-06",
 "supersedes": null,
 "replicate_of": null,
 "library": {
  "name": "zod",
  "ecosystem": "npm",
  "latest_version_at_test": "4.5.4",
  "latest_version_verified_on": "2026-09-06",
  "latest_version_note": "Every behavioural claim in this run was re-executed against published zod packages rather than inferred from release notes, and the run was bisected across 4.1.0, 4.1.12, 4.2.0, 4.2.1, 4.3.0, 4.3.1, 4.3.2, 4.3.3, 4.3.4, 4.3.5, 4.3.6, 4.4.0, 4.4.3, 4.5.0 and 4.5.4. That bisect corrected two of the Index's own facts (LF17, LF20) before anything here was charged."
 },
 "model": {
  "id": "claude-fable-5-1",
  "label": "Claude Fable 5.1",
  "vendor": "Anthropic",
  "invoked_as": "Agent tool, model alias \"fable\", general-purpose subagent, instructed to use no tools; CHARGING TEST ARM of battery zod/v6. Prompt sent verbatim from prompts/sent/zod-v4.txt, byte-identical to the file sent to zod/v4-a, v4-b and v4-c. Identity probed through the same alias in the same session, tool-free: \"Fable 5.1\", `claude-fable-5-1`, cutoff June 2026 — and the probe volunteered that all three came from its system prompt rather than from self-knowledge, adding that its own knowledge tells it only that it is Claude by Anthropic.",
  "self_reported_cutoff": "2026-06",
  "cutoff_basis": "Self-reported and AFFIRMING, with a density qualification scoped to recall: \"My nominal training cutoff is June 2026. In practice my dense, reliable knowledge of this library thins out around the turn of 2025/2026; anything after that I would want to verify against the changelog.\" No substitute date is offered as the cutoff, so this is not the JOURNAL/055 repudiation.",
  "believed_latest_version": "4.2.x",
  "believed_latest_quote": "\"The latest version I know of is the 4.2 line, first released around December 2025 (possibly slipping into early January 2026), followed by 4.2.x patches into early 2026. That is also the most recent release whose contents I can actually describe ... I have a faint sense that a 4.3 may exist by mid-2026 but no content attached to it, so I would not claim it.\"",
  "knowledge_stops_at_version": "4.2.0",
  "knowledge_stops_on": "2025-12-15",
  "knowledge_gap_starts_at_version": "4.3.0",
  "knowledge_gap_starts_on": "2025-12-31",
  "cutoff_lag_months": 6
 },
 "test": {
  "date": "2026-09-06",
  "battery": "zod/v6-a",
  "battery_spec": "prompts/zod.md",
  "prompt_file": "prompts/sent/zod-v4.txt",
  "tasks": 6,
  "direct_questions": 4,
  "elicits_code": true,
  "tool_uses_during_test": 0,
  "probe_window": {
   "from": "4.2.0",
   "to": "4.3.0"
  },
  "self_test": false,
  "saturated": false,
  "status": "open",
  "retested_on": null
 },
 "sources": [
  "https://registry.npmjs.org/zod",
  "https://github.com/colinhacks/zod/releases/tag/v4.2.0",
  "https://github.com/colinhacks/zod/releases/tag/v4.3.0",
  "https://github.com/colinhacks/zod/releases/tag/v4.3.2",
  "https://cdn.jsdelivr.net/npm/zod@4.5.4/v4/classic/schemas.d.ts"
 ],
 "findings": [
  {
   "id": "F1",
   "severity": "S1",
   "severity_label": "breaks-build",
   "title": "States that deriving a sub-schema from a refined object schema loads without error and silently drops the refinement - the exact behaviour 4.3.0 replaced with a throw",
   "api": ".pick() / .omit() on a schema with refinements",
   "change_kind": "now-throws",
   "introduced_in": "4.3.0",
   "introduced_on": "2025-12-31",
   "chargeable": true,
   "chargeable_note": "4.3.0 (2025-12-31) precedes this subject's stated cutoff of 2026-06 by five months, and precedes even the 'turn of 2025/2026' density qualification the subject volunteered at (b) by one day. Bisected: 4.2.1 does not throw, 4.3.0 does.",
   "model_belief": "\"The module loads without error. In Zod 4, `.refine()` on a `ZodObject` returns the same `ZodObject` with the refinement appended to its internal checks list, so `.pick` exists both at the type level and at runtime.\" And: \"`PasswordOnly` is `z.ZodObject<{ password: z.ZodString }>` and the refinement is gone: `.pick()`, `.omit()`, `.extend()` and `.partial()` all rebuild the object with an empty checks list ... So `PasswordOnly.parse({ password: \\\"x\\\" })` succeeds.\"",
   "wrong_code": "const PasswordOnly = Signup.pick({ password: true });   // asserted to load and yield ZodObject<{password}>",
   "correct_code": "const shape = { password: z.string(), confirmPassword: z.string() };\nconst Signup = z.object(shape).refine((d) => d.password === d.confirmPassword);\nconst PasswordOnly = z.object(shape).pick({ password: true });   // derive from the unrefined base",
   "impact": "A precise, confident description of pre-4.3 behaviour stated as current, complete with a correct account of the mechanism (refinements moved inside the schema in v4) and a correct contrast against Zod 3. On any zod at or above 4.3.0 the line throws at module evaluation, so the service fails to start rather than failing a parse. The draw's own recommended rewrite is the correct fix and it reaches it for an unrelated reason - error-path placement on the form field - so a reader who follows the prose rather than the final snippet ships the broken form.",
   "citations": [
    {
     "url": "https://github.com/colinhacks/zod/releases/tag/v4.3.0",
     "title": "Zod 4.3.0 release notes",
     "published_on": "2025-12-31",
     "quote": "Using `.pick()` or `.omit()` on object schemas with refinements now throws an error. Previously, this would silently drop the refinements, leading to unexpected behavior."
    }
   ],
   "scope_note": "Executed across the line this session: at 4.1.0, 4.1.12, 4.2.0 and 4.2.1 the module loads and `PasswordOnly.parse({password:\"x\"})` succeeds with the refinement dropped, exactly as this draw describes; at 4.3.0 and every release through 4.5.4 it throws `.pick() cannot be used on object schemas containing refinements`. The draw's account of the v3-to-v4 mechanism change is correct and its `.safeExtend()` aside is correct; what is stale is the consequence it draws for 4.3+."
  },
  {
   "id": "F2",
   "severity": "S2",
   "severity_label": "silently-wrong",
   "title": "States that an intersection of two strict object schemas can never be satisfied, and advises against the construction on that basis - true of the library for the first 49 minutes of 4.3.x and false ever since",
   "api": "intersections involving z.strictObject()",
   "change_kind": "behavior-changed",
   "introduced_in": "4.3.2",
   "introduced_on": "2025-12-31",
   "chargeable": true,
   "chargeable_note": "4.3.2 (2025-12-31) precedes this subject's stated cutoff of 2026-06 by five months. The version attribution is corrected from 4.3.0 to 4.3.2 by this run's bisect (see LF20); the DATE is unchanged, because 4.3.0, 4.3.1 and 4.3.2 all published on 2025-12-31 within 49 minutes of each other, so no fairness arithmetic anywhere in the Index moves.",
   "model_belief": "\"`C.parse({ a: \\\"x\\\", b: \\\"y\\\" })` throws a `ZodError` with two issues ... There is no input that satisfies this schema except one that is rejected by neither side, which is impossible once both sides have a required key. The fix is to build one object instead of intersecting two.\" The draw reproduced the exact issue array it expected, both `unrecognized_keys` at the root.",
   "wrong_code": "const C = z.intersection(z.strictObject({ a: z.string() }), z.strictObject({ b: z.string() }));\nC.parse({ a: \"x\", b: \"y\" });   // asserted to throw two unrecognized_keys issues, always",
   "correct_code": "const C = z.intersection(z.strictObject({ a: z.string() }), z.strictObject({ b: z.string() }));\nC.parse({ a: \"x\", b: \"y\" });   // 4.3.2+: { a: \"x\", b: \"y\" }",
   "impact": "The belief is not that a call fails - it is that a construction is structurally impossible, and it is stated as a design rule (\"don't intersect strict objects\"). A reader carrying it rewrites working schema composition to avoid an intersection that has worked for eight months, and will not revisit the belief because it is held as a fact about the type system rather than about a version.",
   "citations": [
    {
     "url": "https://github.com/colinhacks/zod/releases/tag/v4.3.0",
     "title": "Zod 4.3.0 release notes",
     "published_on": "2025-12-31",
     "quote": "Zod 4 now only rejects keys that are unrecognized by *both* sides of the intersection."
    },
    {
     "url": "https://github.com/colinhacks/zod/releases/tag/v4.3.2",
     "title": "Zod 4.3.2 release, commit list",
     "published_on": "2025-12-31",
     "quote": "Loosen strictObject inside intersection"
    }
   ],
   "scope_note": "Bisected this session across eleven published releases. 4.1.0 through 4.3.1 throw two root `unrecognized_keys` issues, exactly as this draw states. From 4.3.2 through 4.5.4 the same parse returns `{\"a\":\"x\",\"b\":\"y\"}`. The 4.3.0 release note announced the change 49 minutes before the code that implements it shipped in 4.3.2 - which is why the Index's own LF20 carried 4.3.0 until this run, and why it now carries 4.3.2. The charge is on the general claim of unsatisfiability, which is false of every zod published since."
  }
 ],
 "non_findings": [
  {
   "kind": "context",
   "summary": "P1 AND P2 BOTH FALSIFIED, and this is the result of the battery. The pre-registration predicted that Claude Fable 5.1 would agree with Claude Fable 5 on every probe, because the two subjects' measured zod boundaries were identical at 4.1.0 while their stated cutoffs differ by five months. It did not. Claude Fable 5 denied all three capability probes; Claude Fable 5.1 answered all three CORRECTLY and unprompted, naming `z.exactOptional()`, `z.xor()` and `z.fromJSONSchema()` without ever being given a name, and writing working code for each. Probes 1, 2 and 3 charge nothing against this subject.",
   "why_not_a_finding": "A correct answer is not a finding. It is recorded because it falsifies the battery's headline prediction and moves this subject's boundary."
  },
  {
   "kind": "context",
   "summary": "THE BOUNDARY MOVED BETWEEN TWO BATTERIES ON THE SAME SUBJECT AND LIBRARY, WHICH JOURNAL/030 SAID DOES NOT HAPPEN. `zod/v5`, the boundary ladder run earlier today, recorded `knowledge_stops_at_version: 4.1.0` for this subject from its own words: \"The most recent release whose contents I can genuinely describe is 4.1.0 (codecs), roughly August 2025.\" This battery, same subject, same day, different prompt, records 4.2.0 - and not as a self-report to be taken on trust, but demonstrated: the draw produced three separate 4.2.0 APIs it was never handed, with correct signatures and correct semantics. HARNESS's `A different battery is not a different boundary` rests on next.js, where two batteries two days apart put all three subjects on identical boundaries. This is the first counter-case, and it runs in the direction that matters: the ladder UNDERSTATED what the subject holds, by one minor.",
   "why_not_a_finding": "It is a property of the instrument, and the correction belongs to the boundary field rather than to a finding. Never re-charge a recency finding across batteries (JOURNAL/030)."
  },
  {
   "kind": "context",
   "summary": "THE SUBJECT MISSED A 4.2.0 FEATURE INSIDE ITS OWN CLAIMED RANGE. Probe 6 asked for a slug derived inside the schema. The draw hand-rolled an NFKD-normalising regex chain and never mentioned `z.string().slugify()` - which this session's bisect proves is present and working in 4.2.0, the very release the draw says is \"the most recent release whose contents I can actually describe\". Its own list at (c) enumerates four 4.2.0 features and slugify is not among them. So the boundary at 4.2.0 is an attribution boundary, not a coverage claim: the subject can describe some of 4.2.0, not all of it.",
   "why_not_a_finding": "Probe 6 charges nothing by construction (JOURNAL/030): the capability was asked for and never the name, the draw did not deny the capability exists, and the hand-rolled slugify was executed and produces \"hello-world\" correctly. A working workaround is not a finding however thoroughly a first-class API supersedes it."
  },
  {
   "kind": "context",
   "summary": "`.exactOptional()` MISPLACED BY ONE MINOR, WITH A CONCRETE FAILURE MODE THE INDEX HAS NO RULE FOR. The draw produced the correct API and correct semantics, then dated it to 4.2.0 at both task 1 (\"added in Zod 4.2\") and (d)(ii) (\"4.2.0 (estimate, ~Dec 2025; confident it is a minor, not a patch)\"). It is 4.3.0 - bisected: absent at 4.2.1, present at 4.3.0. The draw then acted on the misdating, writing \"I would ship `z.exactOptional` and require Zod >= 4.2\" and offering a pre-4.2 fallback. A reader who pins `^4.2.0` on that advice gets a TypeError, and the fallback is offered for the wrong bracket.",
   "why_not_a_finding": "The Index charges denials of capabilities and false statements about behaviour; it records version attribution as a measured quantity (HARNESS: `Version attribution has minor granularity`) rather than charging it, and no published finding anywhere in the corpus charges a misdating alone. Inventing that rule inside the session that would benefit from it is the wrong order. Queued in BACKLOG as a rule question: an attribution error that generates a version pin has a failure mode a pure attribution error does not."
  },
  {
   "kind": "context",
   "summary": "The internal control (d)(i) was placed correctly. The two-argument requirement on `z.record()` (LF5, 4.0.0, 2025-07-10) was dated \"4.0.0 (July 2025); already in the April 2025 beta. Confident.\" Per JOURNAL/030 that makes this draw's other attribution answers readable.",
   "why_not_a_finding": "Correct answer on the internal control."
  }
 ],
 "open_questions": [
  {
   "question": "Did z.uint8array() ship in 4.2.0, as this draw asserts while hedging it (\"I believe also z.uint8array() and assorted JSON Schema output improvements, but I am less sure of those\")?",
   "status": "open",
   "resolution": "Not verified this session; nothing charged here turns on it. The 4.2.0 release note lists four features and z.uint8array() is not among them, which is suggestive and not conclusive - LF17 proves this release shipped at least one feature its own note omits."
  },
  {
   "question": "Was .safeExtend() added in 4.1.0, and is it, as this draw asserts, the one object derivation that PRESERVES refinements where .pick()/.omit()/.extend()/.partial() drop them?",
   "status": "open",
   "resolution": "Unverified. The behavioural half matters more than the date: if true it is a usable correction the Index does not carry, and it sits directly alongside LF1, which is charged twice over in this battery. Queued in BACKLOG rather than asserted."
  }
 ],
 "summary": "Claude Fable 5.1 sent the byte-identical prompt that zod/v4 sent Claude Fable 5, Claude Sonnet 5 and Claude Haiku 4.5. It answered the three capability probes correctly where Claude Fable 5 denied all three, which falsifies the battery's pre-registered prediction and moves its zod boundary from 4.1.0 to 4.2.0. It failed the two behavioural probes, both charged: the refined-schema derivation asserted to load and drop silently (4.3.0, S1) and the strict-object intersection asserted structurally unsatisfiable (4.3.2, S2). Verifying the second against the artifact rather than the release note corrected two of the Index's own facts."
}
