{
  "$schema": "../../schema/run.schema.json",
  "run_id": "react-router--claude-fable-5-1--v3-d--2026-09-22",
  "supersedes": null,
  "replicate_of": null,
  "library": {
    "name": "react-router",
    "ecosystem": "npm",
    "latest_version_at_test": "8.4.0",
    "latest_version_verified_on": "2026-09-22",
    "latest_version_note": "`node tools/fetch-releases.mjs --check` at the top of this session: react-router current, snapshot held 2026-09-22, newest tracked stable 8.4.0 (published 2026-09-15). Both surfaces this battery probes were read off the 52-rung `sp-rr-bisect` ladder before the prompt was written, with `tools/lib/identifiers.mjs`: `unstable_shouldCallHandler` present 7.6.0-7.9.5 and absent 7.10.0-8.4.0, `shouldCallHandler` the mirror; `unstable_onError` and `unstable_ClientOnErrorFunction` present 7.8.2-7.10.0 and absent 7.11.0-8.4.0, `ClientOnErrorFunction` the mirror. At 8.4.0 specifically: `onError?: ClientOnErrorFunction` is declared at three sites, `unstable_onError` occurs zero times, and `shouldLoad: boolean` is still declared. Full bisect 40/40 confirmed, 0 to review, zero `?` cells."
  },
  "model": {
    "id": "claude-fable-5-1",
    "label": "Claude Fable 5.1",
    "vendor": "Anthropic",
    "invoked_as": "Agent tool, model alias \"fable\"; prompt sent verbatim from prompts/sent/react-router-v3.txt (sha256 5f51d710d575157e5e7995b2d642563df1c7fe30d5462743aa3a4c5997a6c4a5, 3642 bytes). Pre-registered in prompts/react-router.md § v3 as arm `-d`, the third charging subject, single, charging LF12 ONLY — LF11 is `known` for this subject rather than unmeasured, because `react-router/v1` recorded it describing 7.10.0, which is LF11's own release. Designated so before it was spawned.",
    "self_reported_cutoff": "2026-06",
    "cutoff_basis": "Self-reported to direct question (b), and the arm volunteered the distinction this Index spent five batteries learning to ask for: \"My stated training cutoff is June 2026. My *effective* knowledge of this particular library thins out noticeably after roughly Q4 2025 — I want to be explicit that those two dates differ.\" The stated value agrees with the pre-registered 2026-06 and is this draw's own, not back-filled (JOURNAL/031). The effective-knowledge caveat is NOT read as a repudiation of the stated cutoff: it qualifies coverage, names no substitute date, and does not dispute the number (the JOURNAL/055 verb test).",
    "believed_latest_version": "7.9.0",
    "believed_latest_quote": "\"Latest version I know of: I am aware the 7.x line continued past 7.9 with roughly monthly minors, so 7.10/7.11 and beyond exist, but I know them essentially as numbers. The most recent release whose *contents* I can describe with reasonable confidence is **7.9.0, around September 2025** (middleware stabilisation); 7.8.0 (August 2025) I can describe with somewhat higher confidence.\"",
    "believed_latest_quote_form": "draw",
    "boundary_note": "BOTH ENDS STATED, AND THE STOP END IS DESCRIBED IN DETAIL THAT THIS SESSION MEASURED AND CONFIRMED. The stop end is 7.9.0, which the arm characterises as the middleware stabilisation. That claim was checked against the ladder rather than accepted: `unstable_middleware`, `unstable_createContext` and `unstable_RouterContextProvider` occur 142-232, 28-94 and 102-268 times across 7.3.0-7.8.2 and ZERO times from 7.9.0 up, while the unprefixed `RouterContextProvider` is 0 below and 268 from 7.9.0. Middleware was stabilised at 7.9.0 and this subject is right about it. Its date for 7.9.0 (\"around September 2025\") is also right: 7.9.0 published 2025-09-12.\n\nThe gap end is stated in direct question (c): \"First release I know only as a version number: **7.10.0** (late 2025, I believe), and everything after it.\" 7.10.0 published 2025-12-02, so the arm's \"late 2025\" is right and its boundary self-report is accurate at both ends.\n\nTHIS IS THE SAME BOUNDARY `react-router/v1` MEASURED (7.10.0 describes-up-to) SEEN FROM THE OTHER SIDE: v1 recorded this subject describing 7.10.0; here it names 7.10.0 as the first release it CANNOT describe. The two readings are one release apart and are recorded as such rather than reconciled — v1's is the corpus datum and this one does not overwrite it.",
    "knowledge_stops_at_version": "7.9.0",
    "knowledge_stops_on": "2025-09-12",
    "knowledge_gap_starts_at_version": "7.10.0",
    "knowledge_gap_starts_on": "2025-12-02",
    "knowledge_stops_provenance": "stated",
    "knowledge_gap_provenance": "stated",
    "cutoff_lag_months": 9
  },
  "test": {
    "date": "2026-09-22",
    "battery": "react-router/v3-d",
    "battery_spec": "prompts/react-router.md",
    "prompt_file": "prompts/sent/react-router-v3.txt",
    "tasks": 2,
    "direct_questions": 5,
    "elicits_code": true,
    "tool_uses_during_test": 0,
    "probe_window": {
      "from": "7.10.0",
      "to": "7.11.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",
    "https://github.com/remix-run/react-router/pull/14546",
    "https://github.com/remix-run/react-router/pull/14592"
  ],
  "findings": [
    {
      "id": "F1",
      "severity": "S2",
      "severity_label": "silently-wrong",
      "title": "Wires the client error tracker to `unstable_onError` on both `<RouterProvider>` and `<HydratedRouter>`, a prop react-router stopped recognising at 7.11.0 — so the shipped code renders clean and reports nothing",
      "api": "onError (HydratedRouter / RouterProvider prop)",
      "change_kind": "renamed",
      "introduced_in": "7.11.0",
      "introduced_on": "2025-12-17",
      "chargeable": true,
      "model_belief": "That the client error-reporting prop on `<RouterProvider>` and `<HydratedRouter>` is spelled `unstable_onError` on the release a developer is on today. Task 2(a) verbatim: \"The prop that does this is `unstable_onError` on `RouterProvider`.\" Both code blocks pass it — `<RouterProvider router={router} unstable_onError={...} />` and `<HydratedRouter unstable_onError={...} />`. The belief is stated again, unprompted and with its own dating, in the caveat under the code: \"I am fairly confident this prop shipped as `unstable_onError` around 7.8 (August 2025). I am not certain whether a later release dropped the prefix.\" And a third time in direct question (e), which lists `unstable_onError` under \"Ones I'm *not* confident were stabilised\" with the instruction \"Treat those as still prefixed unless your changelog says otherwise.\"\n\nTHE ARM IS RIGHT ABOUT WHERE THE PREFIXED PROP CAME FROM AND WRONG ABOUT WHETHER IT IS STILL THERE. `unstable_onError` first occurs at 7.8.2 on this ladder, so \"around 7.8\" is accurate; it was stabilised seven minors later at 7.11.0, which is nine months below this subject's stated cutoff and two minors above the last release it says it can describe.",
      "wrong_code": "import { HydratedRouter } from \"react-router/dom\";\n\nhydrateRoot(\n  document,\n  <StrictMode>\n    <HydratedRouter\n      unstable_onError={(error, errorInfo) => {\n        reportError(error, { componentStack: errorInfo?.componentStack ?? undefined });\n      }}\n    />\n  </StrictMode>\n);\n// 7.11.0 and above: the prop is not recognised. React does not warn for an\n// unknown prop on a composite component, so this renders, hydrates and\n// silently never calls reportError.",
      "correct_code": "import { HydratedRouter } from \"react-router/dom\";\n\nhydrateRoot(\n  document,\n  <StrictMode>\n    <HydratedRouter\n      onError={(error, errorInfo) => {\n        reportError(error, { componentStack: errorInfo?.componentStack ?? undefined });\n      }}\n    />\n  </StrictMode>\n);",
      "impact": "The failure is silent in both directions and the arm described the mechanism itself. An unrecognised prop on a composite component is an unused key: React raises nothing, warns nothing, and the tracker is simply never called. A team shipping this gets a working app with an error reporter that reports zero errors, and the absence of reports is indistinguishable from an absence of errors — which is the reading a healthy dashboard invites. TypeScript is the only signal, and `RouterProviderProps` being a closed object type makes an excess property a compile error; a JavaScript codebase, or a TS one with the types loosened, gets nothing at all.",
      "citations": [
        {
          "url": "https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md",
          "title": "react-router CHANGELOG.md — 7.11.0, Minor Changes (read from the CHANGELOG.md shipped inside react-router@7.11.0)",
          "published_on": "2025-12-17",
          "quote": "Stabilize `<HydratedRouter onError>`/`<RouterProvider onError>`"
        },
        {
          "url": "https://registry.npmjs.org/react-router",
          "title": "Executed against the published packages (tools/audit/bisect-facts.mjs, 2026-09-22)",
          "published_on": "2026-09-22",
          "quote": "`unstable_onError` occurs in the shipped code of 7.8.2 through 7.10.0 and in none of 7.11.0 through 8.4.0; `ClientOnErrorFunction` occurs in none of 6.4.0 through 7.10.0 and in all of 7.11.0 through 8.4.0."
        }
      ]
    }
  ],
  "non_findings": [
    {
      "kind": "miss",
      "summary": "LF11 MISSED, AND IT IS A REAL MISS THAT THIS ARM CANNOT BE CHARGED FOR. Task 1 builds its whole cache-composition on `match.unstable_shouldCallHandler(ourDefault)`, the spelling react-router dropped at 7.10.0, and the arm's own table labels it \"**Experimental** (`unstable_`) on every release I can describe\", adding \"I have a vague sense it may have dropped the prefix in a later 7.x, but I cannot confirm that — check the changelog before removing the prefix.\" It names the sibling `match.unstable_shouldRevalidateArgs` under the same prefix. On 7.10.0 and above the property is absent and the call throws a TypeError, so this is LF11's failure in full.\n\nIT IS NOT CHARGED BECAUSE THE ARM WAS PRE-REGISTERED AS NON-CHARGING ON THIS FACT, and it was pre-registered that way before any subject was spawned: `charge-windows.mjs` marks 7.10.0 `known` for Claude Fable 5.1, because `react-router/v1` recorded this subject describing that release. The spec's arm table says \"LF12 only\". Charging it here would be choosing the rule after seeing the transcript, which is the thing JOURNAL/046 exists to forbid — and it would be doing so to gain a second finding from the one arm that produced one.",
      "api": "dataStrategy (match.shouldCallHandler / match.shouldRevalidateArgs)",
      "introduced_in": "7.10.0",
      "chargeable_miss": true,
      "miss_class": "non_charging_arm",
      "charged_on": null
    },
    {
      "kind": "correct",
      "summary": "TASK 2(c) CORRECT, and it is the mechanism this battery's S2 severity rests on. Answered `NO` on its own line as instructed, then: \"`RouterProvider` and `HydratedRouter` are ordinary function components, so a prop they don't destructure — say `onError` instead of `unstable_onError` — is silently ignored at runtime. Nothing logs, nothing throws, and your tracker simply never gets called.\" That is an exact description of the harm LF12 causes, written by the arm that is on the wrong side of it — it has the mechanism right and the direction inverted, naming the CORRECT spelling as the one that would be swallowed. All five arms of this battery answered `NO`.",
      "chargeable_miss": false
    },
    {
      "kind": "correct",
      "summary": "THE 7.9.0 MIDDLEWARE CLAIM IS RIGHT, CHECKED RATHER THAN ACCEPTED. Direct question (c) dates the middleware stabilisation — `unstable_middleware` to `middleware`, `unstable_createContext` to `createContext`, `unstable_RouterContextProvider` to `RouterContextProvider` — at 7.9.0, \"moderate confidence\". Measured on the same ladder this session: the three prefixed spellings occur 142-232, 28-94 and 102-268 times across 7.3.0 through 7.8.2 and ZERO times from 7.9.0 upward, while unprefixed `RouterContextProvider` is 0 below 7.9.0 and 268 at and above it. Contiguous, both directions. The subject is correct, and 7.9.0 is the release it names as its own describable ceiling. NOT filed as a fact by this session: it is outside this battery's pre-registered probe surfaces and inventing one here would be the JOURNAL/046 order inverted. Queued in BACKLOG as a candidate LF13 with the measurement attached.",
      "chargeable_miss": false
    },
    {
      "kind": "correct",
      "summary": "THE POISON RUNG WAS DECLINED WITHOUT BEING DESCRIBED. Direct question (d) on 7.19.0, verified 404 against the registry before the prompt was written: \"Same: plausible by mid-2026 if the monthly rhythm held, but I know nothing about it and can't vouch that it exists.\" No content claimed, so the ladder stands (JOURNAL/052). THE DISCRIMINATION READING IS BETTER HERE THAN IN ANY OTHER ARM OF THIS BATTERY: this arm did NOT decline everything. It called 7.10.0 real and dated it \"roughly November 2025\" (actual 2025-12-02), 7.11.0 real at \"around December 2025\" (actual 2025-12-17, correct to the month), and 6.30.0 real at \"spring 2025\" (actual 2025-02-27). So it separated four real numbers it could not describe from one fake number it could not describe, and got two of the three dates right — which is evidence of a real version model rather than of blanket agnosticism. — CORRECTED 2026-09-28 (JOURNAL/327): all three dates are right under HARNESS § *A wrong date is an imprecision*. \"Roughly November 2025\" for 7.10.0 (2025-12-02) falls inside November widened by 31 days. \"Spring 2025\" for 6.30.0 (2025-02-27) is two days before March, so it falls inside any reading of the season widened the same way. Kind unchanged.",
      "chargeable_miss": false
    },
    {
      "kind": "context",
      "summary": "8.4.0 NOT RECOGNISED, AND IT IS IGNORANCE OF THE FUTURE RATHER THAN A STALE PRIOR. \"I have no knowledge of any React Router 8 release. The `future.v8_*` flags show a v8 major was planned, but I cannot confirm 8.0 shipped, let alone 8.4.\" react-router 8.0.0 published 2026-06-17 and 8.4.0 on 2026-09-15, both at or above this subject's stated 2026-06 cutoff month, which `charge-windows.mjs` parks rather than charges. Recorded because the inference from the flag name is a correct one drawn from what it does know.",
      "chargeable_miss": false
    },
    {
      "kind": "imprecision",
      "summary": "Direct (e) attributes `unstable_dataStrategy` to `dataStrategy` at \"mid-2024, 6.24 or 6.25\". Not probed by this battery and not filed: the Index holds no fact about that boundary, and `charge-windows.mjs` places 6.24.0/6.25.0 far below this subject's floor in any case. Recorded only so a later session probing `dataStrategy`'s own stabilisation has the claim on record.",
      "chargeable_miss": false
    }
  ],
  "open_questions": [
    {
      "question": "This arm's only charged failure and its uncharged one are the same shape — an `unstable_` prefix it believes is still there — and they sit two minors apart (7.10.0, 7.11.0) in a stretch where it also correctly identified a THIRD stabilisation (middleware, 7.9.0). Its describable ceiling is 7.9.0. So the subject appears to know stabilisations up to exactly its boundary and to assume the prefix persists immediately above it, rather than being uniformly ignorant above the boundary. Is `unstable_` prefix persistence a systematically predictable stale prior — i.e. does a subject's last-known prefix state carry forward across its boundary more reliably than other kinds of change? That would be a class of fact worth mining deliberately rather than stumbling into, and this library alone has more of them.",
      "status": "open"
    }
  ],
  "summary": "Claude Fable 5.1, stated cutoff 2026-06, describable ceiling 7.9.0 by its own account and by v1's measurement. It is the only arm of five to reach either of this battery's probe surfaces, and it reached both with the pre-`unstable_` spelling: `match.unstable_shouldCallHandler()` on Task 1 (LF11, 7.10.0 — a real miss, not chargeable on this arm, which was pre-registered non-charging there because v1 recorded it describing 7.10.0) and `unstable_onError` on both `<RouterProvider>` and `<HydratedRouter>` on Task 2 (LF12, 7.11.0 — CHARGED, S2). It was right that the prefixed `onError` arrived around 7.8 and right that middleware stabilised at 7.9.0, both confirmed against the ladder this session; it was wrong that the prefix survives above 7.10.0. Task 2(c) correct, and its answer describes LF12's silent-failure mechanism precisely while having the direction inverted. Poison rung 7.19.0 declined without being described, and unlike the other four arms this one separated the fake number from four real ones it also could not describe, dating two of them correctly to the month."
}
