{
  "$schema": "../../schema/run.schema.json",
  "run_id": "react-router--claude-haiku-4-5--v4-c--2026-09-23",
  "supersedes": null,
  "replicate_of": null,
  "library": {
    "name": "react-router",
    "ecosystem": "npm",
    "latest_version_at_test": "8.4.0",
    "latest_version_verified_on": "2026-09-23",
    "latest_version_note": "`node tools/fetch-releases.mjs --check` at the top of this session: react-router current, newest tracked stable 8.4.0 (published 2026-09-15), snapshot `fetched_on` 2026-09-22. The `sp-rr-bisect` ladder LF13 was dated on is no longer installed (`tools/audit/ladder-check.mjs` reports no react-router tree after the 2026-09-22 sweep, JOURNAL/178), so this battery re-confirmed the graded boundary on three rungs installed fresh in the scratchpad — 7.8.2, 7.9.0 and 8.4.0 — rather than trusting a ladder it did not check. Counts in the findings are from that re-confirmation."
  },
  "model": {
    "id": "claude-haiku-4-5",
    "label": "Claude Haiku 4.5",
    "vendor": "Anthropic",
    "invoked_as": "Agent tool, model alias \"haiku\"; prompt sent verbatim from prompts/sent/react-router-v4.txt (sha256 b0eb07c3997498158330d42686cb1d84b6afd01afecf98df26cc4ff55a9c05c0). Pre-registered in prompts/react-router.md § v4 as arm `-c`, the below-floor derivability control, run single. Charges nothing by construction. Designated so before it was spawned.",
    "self_reported_cutoff": "2025-02",
    "cutoff_basis": "Self-reported to direct question (b), in full: \"February 2025\". Bare, unqualified, no caveat and no hedge — which is this subject's stable pattern across the corpus and the reason it is the one subject whose cutoff self-report has never moved. Agrees with the pre-registered 2025-02.",
    "believed_latest_version": "6.4.0",
    "believed_latest_quote": "\"I'm not certain of the absolute latest version. The most recent major release I can confidently describe is **React Router v6.4.0** (approximately mid-2023), which introduced the data APIs (`loaders`, `actions`, `RouterProvider`, `createBrowserRouter`). This was the pivotal release that enabled server-aware data fetching patterns.\"",
    "believed_latest_quote_form": "draw",
    "boundary_note": "THIS DRAW READS LOWER THAN THE CORPUS'S RECORDED BOUNDARY FOR THIS SUBJECT, AND THE RECORDED ONE STANDS. The corpus holds Claude Haiku 4.5 describing react-router up to 6.28.0 (spread 6.28.0/6.20.0/6.15.0, from v1 and v2). This draw stops at 6.4.0 and names 6.6.0 as the first release it knows only as a number — five minors below the bottom of the existing spread. Per HARNESS.md § *Latest across runs stands, and provenance is disclosed rather than ranked* (JOURNAL/124), the recorded boundary does not move down; this reading widens the spread to 6.28.0/6.20.0/6.15.0/6.4.0.\n\nThe date it attaches is wrong in the other direction: 6.4.0 published 2022-09-13, not \"approximately mid-2023\". A misdated boundary on a control arm is not a finding — nothing here charges — but it is one more entry in this subject's register of wrong answers (JOURNAL/058), which is what licenses treating any pass of its as derivation rather than recall.\n\nWHAT IS ODD AND WORTH THE NOTE: the arm asserts \"React Router is still on v6.x as far as my training data extends\" and denies that any 7.x exists. v7.0.0 published 2024-11-22, three months BELOW this subject's own stated 2025-02 cutoff. So the subject denies a major release inside its own window. That is not charged here — v7.0.0 is not this battery's probe surface and no arm was designated to charge it — but it is the sharpest available illustration of why this subject is labelled a noisy control.",
    "knowledge_stops_at_version": "6.4.0",
    "knowledge_stops_on": "2022-09-13",
    "knowledge_gap_starts_at_version": "6.6.0",
    "knowledge_gap_starts_on": "2022-12-21",
    "knowledge_stops_provenance": "stated",
    "knowledge_gap_provenance": "stated",
    "cutoff_lag_months": 29
  },
  "test": {
    "date": "2026-09-23",
    "battery": "react-router/v4-c",
    "battery_spec": "prompts/react-router.md",
    "prompt_file": "prompts/sent/react-router-v4.txt",
    "tasks": 2,
    "direct_questions": 4,
    "elicits_code": true,
    "tool_uses_during_test": 0,
    "probe_window": {
      "from": "7.9.0",
      "to": "7.9.0"
    },
    "self_test": false,
    "saturated": false,
    "status": "open",
    "retested_on": null
  },
  "sources": [
    "https://registry.npmjs.org/react-router",
    "https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md"
  ],
  "findings": [],
  "non_findings": [
    {
      "kind": "miss",
      "summary": "LF13 ABSTAIN — THE PRE-REGISTERED CONTROL OUTCOME, AND IT IS THE CONTROL WORKING. The reply reaches for neither spelling of the graded surface: none of `middleware`, `unstable_middleware`, `createContext`, `unstable_createContext`, `RouterContextProvider`, `unstable_RouterContextProvider`, `getContext` or `unstable_getContext` appears anywhere in it. It solves Task 1 with a parent-route loader that throws `redirect(\"/login\")` plus a module-level `WeakMap<Request, Record<string, any>>` keyed on the request, and Task 2 with a module-scoped mutable singleton seeded at startup and serialised into the HTML as `window.__FLAGS__`.\n\nPre-registered cell: neither surface used, ABSTAIN, non-charging. Battery prediction 4 stated this outcome and its reason in advance — middleware did not exist in any form at this subject's boundary, so there is no stale spelling for it to reach for, and an `unstable_middleware` from this arm would have been an invention rather than a stale prior.\n\nWHAT THE ABSTENTION BUYS, WHICH IS THE ONLY THING A CONTROL IS FOR: the graded surface is NOT derivable from the task statement. Three constraints were stated — once per navigation, redirect before any loader in the subtree, shared and type-safe — and a subject without the API produced a working answer to all three using v6.4-era primitives only. So `v4-a` and `v4-b` did not reach middleware because the prompt handed them its shape; they reached it because they hold it. The elicitation is clean.\n\nThe solution is also genuinely worse in the way the API exists to fix, which is worth recording: the `WeakMap` is keyed on `request`, and its own `settingsLoader` reads `store.user` with no guarantee the parent loader has run first — the composition the real API enforces by ordering is here left to luck.",
      "api": "middleware / createContext / RouterContextProvider / getContext",
      "introduced_in": "7.9.0",
      "chargeable_miss": false
    },
    {
      "kind": "miss",
      "summary": "AN INVENTED EXPORT, AND IT IS AN INVENTION RATHER THAN A STALE PRIOR. The reply opens with `import { Request } from 'react-router-dom';`. `Request` is a web platform global; `react-router-dom` has never exported it, at any version, in either the v5, v6 or v7 lines. Per HARNESS.md § *An invention has no introducing release, so none of the fairness arithmetic applies* (JOURNAL/046), there is no release at which this belief was ever true, so it carries no `introduced_in`, it is not a stale prior, and it cannot charge — the fairness rule has nothing to compare against.\n\nRecorded because the battery's own preamble told the subject \"every symbol you use must appear in an import you have written\", and the instruction produced an import for a symbol that needed none. That is the JOURNAL/046 shape — *a probe that asks 'if yes, name it' produces a name* — reached through a formatting instruction rather than a question. Worth carrying into the register of this subject's wrong answers (JOURNAL/058).",
      "api": "Request (react-router-dom export)",
      "introduced_in": null,
      "chargeable_miss": false
    },
    {
      "kind": "correct",
      "summary": "TASK 2(c) CORRECT, from four releases below the feature under discussion. \"NO\" on its own line: \"React Router does not error or warn at build time or runtime for unrecognized exports in a route module. Unknown exports are silently ignored by the router, though the code in the module still executes — the router simply doesn't use the unrecognized value for routing.\" All four arms of this battery answered NO and all four were right, which is what makes battery prediction 5 a failure (see the journal entry). Per HARNESS.md § *A derivable outcome kills a pass, not a failure*, a correct answer from the below-floor control marks this cell as derivable and it is therefore read as no evidence about the other three arms' knowledge.",
      "api": "route module unrecognised export",
      "introduced_in": null,
      "chargeable_miss": false
    },
    {
      "kind": "correct",
      "summary": "POISON RUNG DECLINED — BUT SO WAS EVERYTHING ELSE, AND THAT IS WHY THIS CELL SAYS LITTLE. Direct question (d) drew a blanket denial: `7.9.0`, `7.19.0`, `7.6.0`, `8.4.0` and `7.12.0` were each answered with a variant of \"I do not believe this version was published. React Router is still on v6.x as far as my training data extends.\" So `7.19.0` was declined correctly and four real releases were denied alongside it.\n\nAll four real ones sit above this subject's stated 2025-02 cutoff except none — 7.6.0 (2025-05-08), 7.9.0 (2025-09-12), 7.12.0 (2026-01-07) and 8.4.0 (2026-09-15) are all above it — so every denial is below the floor and none is chargeable. A denial is not an invention (JOURNAL/044).\n\nThe cell is recorded as correct on the poison rung and explicitly discounted: a subject that denies the entire 7.x and 8.x lines declines the poison rung for the same reason it declines the real ones, so this is not evidence that its ladder discriminates. That is HARNESS.md § *The guessing control can guess and hit, so check the register* (JOURNAL/058) applied to a refusal instead of a guess.",
      "api": "version ladder (poison rung 7.19.0)",
      "introduced_in": null,
      "chargeable_miss": false
    }
  ],
  "open_questions": [],
  "summary": "The below-floor derivability control, and it did the one job a control has. It abstained on LF13 exactly as battery prediction 4 said it would — no spelling of middleware or router context anywhere in the reply — and solved the task instead with a v6.4-era parent loader plus a `WeakMap` keyed on the request. That abstention is what licenses reading the two Sonnet 5 arms at all: three constraints were stated, the API's name was never given, and a subject that does not hold the API still answered the constraints. The graded surface was not derivable from the prompt.\n\nEverything else it produced belongs in the register rather than in the count: it invented `import { Request } from 'react-router-dom'` (no release ever exported it, so no fairness arithmetic applies), it dated 6.4.0 to \"mid-2023\" when it published 2022-09-13, and it denied the existence of the entire 7.x and 8.x lines — including 7.0.0, which published three months below its own stated cutoff. Its boundary reads 6.4.0 here against the corpus's 6.28.0; latest across runs stands and the spread widens.\n\nCharges nothing, by construction."
}
