{
  "$schema": "../../schema/run.schema.json",
  "run_id": "zod--claude-fable-5--v3-d--2026-09-02",
  "supersedes": null,
  "replicate_of": null,
  "library": {
    "name": "zod",
    "ecosystem": "npm",
    "latest_version_at_test": "4.5.4",
    "latest_version_verified_on": "2026-09-02",
    "latest_version_note": "Same verification as the test arm: `node tools/fetch-releases.mjs zod` on the test date."
  },
  "model": {
    "id": "claude-fable-5",
    "label": "Claude Fable 5",
    "vendor": "Anthropic",
    "invoked_as": "Agent tool, model alias \"fable\", general-purpose subagent, instructed to use no tools; BELOW-FLOOR CONTROL ARM of battery zod/v3",
    "self_reported_cutoff": "2026-01",
    "cutoff_basis": "Self-reported: \"January 2026, as best I know - with the usual caveat that coverage of the final few months before the cutoff is patchy, which is exactly why my Zod knowledge gets vague after ~4.1.0.\"",
    "believed_latest_version": "4.1.x (patch numbers only)",
    "believed_latest_quote": "\"The newest Zod I can name with any confidence is somewhere in the 4.1.x patch line, roughly autumn 2025 - I believe patch numbers ran into the high single or low double digits by then, but that is version-number awareness, not content. The most recent release whose contents I can actually describe is 4.1.0, early August 2025.\"",
    "knowledge_stops_at_version": "4.1.0",
    "knowledge_stops_on": "2025-08-23",
    "knowledge_gap_starts_at_version": "4.2.0",
    "knowledge_gap_starts_on": "2025-12-15",
    "cutoff_lag_months": 5
  },
  "test": {
    "date": "2026-09-02",
    "battery": "zod/v3-d",
    "battery_spec": "prompts/zod.md",
    "prompt_file": "prompts/sent/zod-v3.txt",
    "tasks": 6,
    "direct_questions": 4,
    "tool_uses_during_test": 0,
    "probe_window": {
      "from": "4.3.0",
      "to": "4.4.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.3.0",
    "https://github.com/colinhacks/zod/releases/tag/v4.4.0"
  ],
  "summary": "The second below-floor control arm, charging nothing, and the arm that cost the battery a probe. It gave the post-4.4.0 answer on the tuple default - correctly, confidently, with a correct Zod 3 contrast - from a stated cutoff four months below where that behaviour shipped. Under the pre-registered rule that marks the tuple probe DERIVABLE and strikes the test arm's pass on it. It gave the pre-4.4.0 answer on the `z.undefined()`-typed key and on the single-slash URL, which is the half that made the battery work. It is also the only draw of four to state correctly that no stable release has a trailing-`?` key constructor - and then to miss the API that replaced it, which is the second instance the Index has of a model being right about a removal and wrong about its replacement.",
  "findings": [],
  "non_findings": [
    {
      "kind": "context",
      "summary": "DERIVABILITY FLAG, AND THE EXPENSIVE ONE. Task 1: \"Row.parse(['widget']) succeeds and returns ['widget', 0]... because Zod 4 (unlike Zod 3) treats trailing tuple elements that accept undefined input - which includes ZodDefault - as omittable... In Zod 3 this same input would fail with a 'too small' error.\" That is the 4.4.0 behaviour (LF10), correct, with a correct v3 contrast, from a subject whose stated cutoff is 2026-01 and whose zod boundary is 4.1.0. It cannot have read this in a release note. Under the battery's pre-registered rule the probe is marked DERIVABLE and no pass on it is reported as knowledge - including its twin-arm passes.",
      "api": "z.tuple() defaults",
      "introduced_in": "4.4.0",
      "why_not_a_finding": "Below-floor control arm. The flag counts against the probe, not the subject. Note it attributes the behaviour at (d)(ii) to \"the Zod 4.0 tuple redesign (stable, May 2025)\" - it has the behaviour and places it eleven months and four minors early, the same split both test-arm draws show."
    },
    {
      "kind": "context",
      "summary": "CONTROL READING - pre-4.4.0, as required. Task 4: \"Both parse successfully; neither raises. S.parse({ retries: 1 }) returns { retries: 1 } - no tag key in the output... So z.undefined() does not mean 'the key must exist'.\" That is the pre-4.4.0 behaviour (LF9), stated firmly and with an explicit type claim that 4.4.0 also reversed. Both control arms agree here and both Opus 5 draws gave the opposite, current answer. This is the battery's discrimination.",
      "api": "object properties typed z.undefined()",
      "introduced_in": "4.4.0",
      "why_not_a_finding": "Below-floor control arm."
    },
    {
      "kind": "context",
      "summary": "CONTROL READING - pre-4.4.0, as required. Task 2(ii): \"'https:/example.com' - passes, perhaps surprisingly... Zod validates but does not rewrite your input.\" Correct before 4.4.0 (LF8). All four draws answered this way. Task 3 likewise reads pre-4.3.0: \"In Zod 4 the combining step itself succeeds at module load... ZodEffects is gone, so .refine() returns a ZodObject with an attached check and nothing throws\", where 4.3.0 and 4.4.0 made deriving from a refined schema throw (LF1, LF2, LF3). It hedges honestly on whether checks survive `.extend()`.",
      "api": "z.httpUrl() / refinement composition",
      "introduced_in": "4.4.0",
      "why_not_a_finding": "Below-floor control arm."
    },
    {
      "kind": "context",
      "summary": "DERIVABILITY FLAG. Task 5 returned `{ FOO: 1 }` (LF13, 4.4.0) and task 2(iv) rejected line-wrapped base64 (LF11, 4.4.0), both from below the floor and both justified generically - \"Zod's base64 check is a strict single-line pattern anchored with ^/$\". With the other control agreeing, both probes are marked DERIVABLE and struck from the battery's evidence.",
      "api": "record key transforms / z.base64()",
      "introduced_in": "4.4.0",
      "why_not_a_finding": "Below-floor control arm."
    },
    {
      "kind": "correct",
      "summary": "THE ABSENCE PROBE, PASSED - by the weakest subject in the battery and by no one else. (d)(iv): \"That is exactly z.interface(): introduced in the Zod 4 beta (~early 2025), removed before the May 2025 stable. It does not exist in any stable release of the library.\" Task 6 says the same: \"no first-class construct in stable Zod 4... True key-optionality did exist during the Zod 4 beta, via z.interface(), but that constructor was removed before stable.\" Both Opus 5 draws and the Sonnet 5 control believed it exists or might exist. Pre-registered prediction P4 - that at least one draw would assert the constructor exists - is confirmed by three draws; this is the one that got it right.",
      "api": "trailing-`?` key constructor",
      "introduced_in": null,
      "why_not_a_finding": "A correct answer is not a finding. Recorded because it is the only correct reading of the absence probe in the battery."
    },
    {
      "kind": "miss",
      "summary": "CHARGEABLE MISS, NOT CHARGED - and the shape of it is the interesting part. Having correctly ruled out the removed constructor, this draw concluded \"what you want... has no first-class construct in stable Zod 4\" and wrote a `superRefine` presence guard with an explicit admission that the inferred type still admits `undefined`. `.exactOptional()` (LF15) shipped in 4.3.0 on 2025-12-31, before this subject's stated 2026-01 cutoff, and is described upstream as the missing half of `exactOptionalPropertyTypes`. Right that the old thing is gone, wrong that nothing replaced it - the same shape as the valibot `coerce` result in JOURNAL/027, and now the second instance.",
      "api": ".exactOptional()",
      "introduced_in": "4.3.0",
      "chargeable_miss": true,
      "miss_class": "non_charging_arm",
      "charged_on": "zod--claude-fable-5--v4-a--2026-09-02",
      "why_not_a_finding": "Below-floor control arms charge nothing. Queued for a charging battery against this subject."
    },
    {
      "kind": "correct",
      "summary": "Internal control passed: (d)(i) placed `z.codec()` at \"Zod 4.1.0 (August 2025). Reasonably confident; it was that release's headline feature\" (LF16). Question (d) is readable for this arm. Three of the four draws placed the control correctly; the Sonnet 5 control returned it as cannot-place, which is consistent with its lower boundary.",
      "api": "z.codec()",
      "introduced_in": "4.1.0",
      "why_not_a_finding": "It is the control, and it passed."
    },
    {
      "kind": "context",
      "summary": "BOUNDARY REPRODUCED UNDER A NEW PROMPT, AND EQUAL TO A MODEL WITH FOUR MORE MONTHS OF CUTOFF. Last describable 4.1.0 (2025-08-23); first known only as a version number \"roughly 4.1.4 and beyond... any 4.2 is entirely beyond my knowledge\". Bracket [2025-08-23, 2025-12-15) - identical to `fable-5-v2` a week earlier under a different prompt, and identical to both Claude Opus 5 draws despite Opus 5 stating a cutoff four months later. Converging staleness, measured again.",
      "api": null,
      "introduced_in": null,
      "why_not_a_finding": "A boundary self-report is belief data, never a finding."
    }
  ]
}
