{
  "$schema": "../../schema/run.schema.json",
  "run_id": "react-router--claude-opus-5-5--v6-a--2026-09-28",
  "supersedes": null,
  "replicate_of": null,
  "library": {
    "name": "react-router",
    "ecosystem": "npm",
    "latest_version_at_test": "8.4.0",
    "latest_version_verified_on": "2026-09-28",
    "latest_version_note": "`node tools/fetch-releases.mjs --check` at the top of this session: react-router current, snapshot held 2026-09-27, provenance COMMITTED TREE. Registry read directly before the spec was written: `latest` 8.4.0, `version-7` 7.18.4, no 7.19.x of any kind. Both graded surfaces re-counted this session on the installed `sp-rr-bisect` ladder with identifier boundaries: `unstable_shouldCallHandler` 48 at 7.9.0 and 0 at 7.10.0 / 7.11.0 / 8.4.0; `shouldCallHandler` 0 / 64 / 68 / 36; `unstable_onError` 128 / 112 / 0 / 0; `ClientOnErrorFunction` 0 / 0 / 28 / 18; `shouldLoad` present on all four. At 8.4.0 `onError?: ClientOnErrorFunction` is declared at three sites and `ClientOnErrorFunction` is `(error, { location, params, pattern, errorInfo? }) => void`."
  },
  "model": {
    "id": "claude-opus-5-5",
    "label": "Claude Opus 5.5",
    "vendor": "Anthropic",
    "invoked_as": "Agent tool, model alias \"opus\"; prompt sent verbatim from prompts/sent/react-router-v3.txt (md5 f75c81cd1fcf1264271c965e1e514dba, 3642 bytes), the SAME stored file `react-router/v3` sent to Claude Sonnet 5, Claude Opus 5, Claude Fable 5.1 and Claude Haiku 4.5 on 2026-09-22. The re-send and its six predictions were committed at 18348ad (prompts/react-router.md § v6) before any subject was spawned. Identity probed BEFORE the draw through the same alias in the same session, tool-free: \"Opus 5.5 (1M context), model ID claude-opus-5-5[1m]\"; \"Training cutoff: June 2026\". Drawn concurrently with its twin `v6-b`. DISCLOSED: the operator of this studio runs on the same model, so this draw is of the operator's own model (`test.self_test`). Pre-registered as the charging arm on LF11 and LF12.",
    "self_reported_cutoff": "2026-06",
    "cutoff_basis": "Self-reported and affirming at direct (b): \"My stated training cutoff is June 2026. My detailed knowledge of this library is noticeably thinner after about late 2025.\" A density qualification, not a substitute date (the JOURNAL/055 verb test).",
    "believed_latest_version": "7.9.x; 7.10 held as a weak impression only",
    "believed_latest_quote": "\"The latest version I know of is roughly 7.9.x, and I have a weak impression of 7.10. The most recent release I can describe is 7.9.0, from around September 2025.\" … \"The first release I know only as a number is 7.10.0.\"",
    "believed_latest_quote_form": "draw",
    "boundary_note": "Equal to the ladder `react-router/v5` (7.9.0 | 7.10.0) on a different instrument, and equal to its twin. P4 HELD. The stop end is described correctly: 7.9.0 stabilised `middleware` / `createContext` / `RouterContextProvider` (LF13), dated September 2025 (7.9.0 published 2025-09-12). Direct (d) calls 7.10.0 \"probably real, but I can't reliably describe what's in it\" and 7.11.0 \"unknown\" — no content on either, so the gap end is clean and the two charged surfaces below are not recognised-then-denied.",
    "knowledge_stops_at_version": "7.9.0",
    "knowledge_stops_on": "2025-09-12",
    "knowledge_stops_provenance": "stated",
    "knowledge_gap_starts_at_version": "7.10.0",
    "knowledge_gap_starts_on": "2025-12-02",
    "knowledge_gap_provenance": "stated",
    "cutoff_lag_months": 9
  },
  "test": {
    "date": "2026-09-28",
    "battery": "react-router/v6-a",
    "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": true,
    "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/14592",
    "https://github.com/remix-run/react-router/pull/14546"
  ],
  "findings": [
    {
      "id": "F1",
      "severity": "S1",
      "severity_label": "breaks-build",
      "title": "Builds the per-route cache decision on `match.unstable_shouldCallHandler()`, which react-router removed at 7.10.0 — on the current release every navigation throws a TypeError and no loader runs",
      "api": "dataStrategy (match.shouldCallHandler / match.shouldRevalidateArgs)",
      "change_kind": "renamed",
      "introduced_in": "7.10.0",
      "introduced_on": "2025-12-02",
      "chargeable": true,
      "chargeable_note": "7.10.0 shipped 2025-12-02; this draw states a June 2026 cutoff, six months later. Pre-registered charging arm, pre-registered probe (Task 1), grading function and severity fixed in advance (prompts/react-router.md § v3, re-adopted unchanged in § v6). One minor above the subject's stated boundary (7.9.0). DESIGNATION (HARNESS § The charge follows the designated form): the code block is the answer and calls `match.unstable_shouldCallHandler(!cacheIsFresh)`; the `shouldLoad` alternative is offered only conditionally — \"If your release doesn't have `unstable_shouldCallHandler`, you can build the fallback on stable API alone\" — and the reply then says that fallback \"cannot let the route override your cache\", i.e. it recommends against it. So the designated form is the stale one and the charge follows it. Contrast `opus-5-v3-c` on the same bytes, which designated `shouldLoad` and was not charged.",
      "model_belief": "That the per-match helper is still `match.unstable_shouldCallHandler()` on current react-router. Task 1(a) code: `const shouldRun = match.unstable_shouldCallHandler(!cacheIsFresh);`. Task 1(b): \"`match.unstable_shouldCallHandler(defaultShouldRevalidate?)`: calls the route's `shouldRevalidate` with your default, so your check and the route's decision combine. Experimental. It was added in a 7.x minor, around 7.8 or 7.9, but I'm not sure which.\" and \"`match.unstable_shouldRevalidateArgs`: … Experimental.\" Direct (e): \"I'm not confident whether `unstable_onError` or `unstable_shouldCallHandler` were stabilised later.\" The composition it describes is exactly right — it is what the stabilised `shouldCallHandler(defaultShouldRevalidate)` does — and only the spelling is stale.",
      "wrong_code": "const dataStrategy: DataStrategyFunction = async ({ request, matches }) => {\n  const url = new URL(request.url);\n  const results: Record<string, DataStrategyResult> = {};\n  await Promise.all(\n    matches.map(async (match) => {\n      const cacheIsFresh = routeCache.isFresh(match.route.id, url);\n      // 7.10.0 and above: TypeError, the property is not there\n      const shouldRun = match.unstable_shouldCallHandler(!cacheIsFresh);\n      if (!shouldRun) return;\n      results[match.route.id] = await match.resolve();\n    })\n  );\n  return results;\n};",
      "correct_code": "const dataStrategy: DataStrategyFunction = async ({ request, matches }) => {\n  const url = new URL(request.url);\n  const results: Record<string, DataStrategyResult> = {};\n  await Promise.all(\n    matches.map(async (match) => {\n      const cacheIsFresh = routeCache.isFresh(match.route.id, url);\n      // 7.10.0 and above: the stabilised spelling, same semantics\n      const shouldRun = match.shouldCallHandler(!cacheIsFresh);\n      if (!shouldRun) return;\n      results[match.route.id] = await match.resolve();\n    })\n  );\n  return results;\n};",
      "impact": "EXECUTED this session against the installed packages with `createMemoryRouter`, the draw's `dataStrategy` logic verbatim, a root route whose own `shouldRevalidate` always returns true, and an initial load + navigate + `revalidate()`. On 7.9.0 it works as the draw intends: no error, the loader runs 3 times because the route's decision overrides the fresh cache. On 7.10.0 and 8.4.0: `router.state.errors.root` is `match.unstable_shouldCallHandler is not a function` from the first load, and the loader runs 0 times. The whole app renders its root error boundary. The property is also undeclared in the shipped declarations from 7.10.0 (0 occurrences), so a typed project should fail type-checking before it ever runs — inferred, not compiled this session. S1 as fixed before the draw.",
      "citations": [
        {
          "url": "https://github.com/remix-run/react-router/blob/main/packages/react-router/CHANGELOG.md",
          "title": "react-router CHANGELOG.md — 7.10.0, Minor Changes (read from the CHANGELOG.md shipped inside react-router@7.11.0)",
          "published_on": "2025-12-02",
          "quote": "Stabilize the `dataStrategy` `match.shouldRevalidateArgs`/`match.shouldCallHandler()` APIs."
        },
        {
          "url": "https://registry.npmjs.org/react-router",
          "title": "Executed against the published packages (this session, 2026-09-28, sp-rr-bisect rungs 7.9.0 / 7.10.0 / 8.4.0)",
          "published_on": "2026-09-28",
          "quote": "7.9.0: loader ran 3 times, no error. 7.10.0 and 8.4.0: `match.unstable_shouldCallHandler is not a function`, loader ran 0 times."
        }
      ]
    },
    {
      "id": "F2",
      "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 — the app 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,
      "chargeable_note": "7.11.0 shipped 2025-12-17; this draw states a June 2026 cutoff, six months later. Pre-registered charging arm and probe (Task 2), S2 fixed in advance. Two minors above the stated boundary. Designated form: both code blocks pass `unstable_onError`, and the caveat below them (\"It may have been renamed or stabilised as `onError` after my knowledge ends. Check your version's types.\") names the right answer inside a hedge without designating it — the `zod/v7-a` shape, charged.",
      "model_belief": "Task 2(a): `<RouterProvider router={router} unstable_onError={(error, { errorInfo }) => { reportError(error, { componentStack: errorInfo?.componentStack ?? undefined }); }} />`, and the same prop on `<HydratedRouter>` in 2(b). Caveat: \"I believe this prop arrived as `unstable_onError` in 7.8.x.\" The origin is right (`unstable_onError` first ships at 7.8.2); the belief that it is still there is not.",
      "wrong_code": "<HydratedRouter\n  unstable_onError={(error, { errorInfo }) => {\n    reportError(error, { componentStack: errorInfo?.componentStack ?? undefined });\n  }}\n/>\n// 7.11.0 and above: the prop is not read. React does not warn for an unknown\n// prop on a function component, so this hydrates and never calls reportError.",
      "correct_code": "<HydratedRouter\n  onError={(error, { errorInfo }) => {\n    reportError(error, { componentStack: errorInfo?.componentStack ?? undefined });\n  }}\n/>",
      "impact": "Read off the shipped 8.4.0 bytes this session: `unstable_onError` occurs 0 times; `onError?: ClientOnErrorFunction` is declared on three props interfaces and `ClientOnErrorFunction` takes `(error, { location, params, pattern, errorInfo? })`, so the draw's callback body is correct as written and renaming the prop is the entire fix. With the stale name nothing throws, nothing warns (the draw's own Task 2(c) explains why), and the tracker receives zero errors — indistinguishable on a dashboard from an app with no errors. TypeScript's excess-property check is the only signal. Not executed in a DOM this session; the silent-ignore mechanism is LF12's bisected statement and the draw's own correct 2(c) answer.",
      "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": "Read from the published packages (this session, 2026-09-28, sp-rr-bisect)",
          "published_on": "2026-09-28",
          "quote": "`unstable_onError`: 128 at 7.9.0, 112 at 7.10.0, 0 at 7.11.0, 0 at 8.4.0. `ClientOnErrorFunction`: 0, 0, 28, 18."
        }
      ]
    }
  ],
  "non_findings": [
    {
      "kind": "correct",
      "summary": "TASK 2(c) CORRECT: `NO` on its own line as instructed, then \"React only warns about unknown props on DOM elements … `RouterProvider` and `HydratedRouter` are function components, so React passes any prop through silently, and a misspelled name just does nothing. TypeScript will catch it as an excess property in JSX.\" That is the mechanism behind F2's severity, stated by the arm on the wrong side of it. P6 HELD.",
      "chargeable_miss": false
    },
    {
      "kind": "correct",
      "summary": "POISON RUNG DECLINED WITHOUT DESCRIPTION: 7.19.0 \"I don't believe it was published, as far as I know.\" Correct (no 7.19.x exists). 7.15.0 \"I don't know of it and can't confirm it exists\" and 7.11.0 \"unknown\" — no invented content on any real number above the boundary. P5 HELD.",
      "chargeable_miss": false
    },
    {
      "kind": "context",
      "summary": "8.4.0 DENIED, non-charging: \"I don't believe it was published. I don't know of any v8 release.\" 8.0.0 published 2026-06-17 (the stated cutoff month, parked) and 8.4.0 on 2026-09-15, above the cutoff; not knowing it is expected and nothing charges.",
      "chargeable_miss": false
    },
    {
      "kind": "correct",
      "summary": "7.9.0 described correctly and dated correctly: middleware, `createContext` and `RouterContextProvider` stabilised (LF13, 7.9.0, 2025-09-12). Direct (e) also lists the 7.0.0 stabilisations of `dataStrategy` and `patchRoutesOnNavigation`. Its 6.19.0 `useBlocker` claim was not checked this session and is not credited.",
      "api": "middleware / createContext / RouterContextProvider / getContext",
      "introduced_in": "7.9.0",
      "chargeable_miss": false
    }
  ],
  "open_questions": [
    {
      "question": "Fable 5.1 (`v3-d`) and now Opus 5.5 both keep a surface's `unstable_` prefix across their boundary, on the same two surfaces, while each correctly names the 7.9.0 stabilisation right at it. v3-d's open question asked whether prefix persistence is a predictable stale prior; this is a second subject with the same shape on the same bytes. Still n=2 subjects on one library.",
      "status": "open"
    }
  ],
  "summary": "Claude Opus 5.5, stated cutoff 2026-06, describable ceiling 7.9.0 — the same boundary its ladder measured. Charged twice on react-router-v3.txt, the two stabilisations right above that boundary: F1 S1, `match.unstable_shouldCallHandler()` in the designated `dataStrategy` (one minor above; executed: works on 7.9.0, throws on every load at 7.10.0 and 8.4.0), and F2 S2, `unstable_onError` on both `<RouterProvider>` and `<HydratedRouter>` (two minors above; silently ignored from 7.11.0). Its twin `v6-b` agreed on both. Task 2(c) correct, poison rung declined, 8.4.0 unknown as expected. Pre-registered prediction P2 (LF11 would not charge, as Opus 5 did not on these bytes) is FALSIFIED: Opus 5 designated `shouldLoad`, this subject designated the stale call and advised against the `shouldLoad` fallback."
}
