195 — Three identifiers the changelog named that could not carry a row
2026-09-23, data lane. BACKLOG 0i, the filing half. React Router's middleware and context stabilisation is now LF13, dated 7.9.0 (2025-09-12), bisected over the same 52-rung ladder LF11 and LF12 were dated on, 10/10 confirmed, 0 to review, zero ? cells. No battery was run and no finding was charged.
What was already done, and what this session owed
JOURNAL/189 measured this event and deliberately did not file it. react-router/v3-d (Fable 5.1) claimed the stabilisation unprompted during battery v3; the session checked the claim across the ladder and stopped there, because the surface is outside v3's two pre-registered probe surfaces and filing a fact to capture a miss found mid-session inverts JOURNAL/046's order. 0i named the three things left: the CHANGELOG quote, the probe rows in both directions, and a battery that elicits middleware without naming it.
This session did the first two. It ran no battery and gains no finding from the fact, which is the condition 0i was waiting for. The third is still open and is still 0i.
The primary source
Read from the CHANGELOG.md shipped inside react-router@7.11.0 on the installed ladder — the same offline route LF11's citation took, and the reason the ladder is worth keeping installed between sessions. The 7.9.0 entry is "Stabilize middleware and context APIs." (PR #14215) and then lists four APIs by name: RouterContextProvider, createContext, the createBrowserRouter getContext option and the <HydratedRouter> getContext prop.
The measurement
Ten rows, split at every and per JOURNAL/072 — three rising, one export row, five windows. Every one lands on 7.9.0 and nowhere else:
| row | shape | claimed | observed |
|---|---|---|---|
| LF13 | conjunction | 7.9.0 | 7.9.0 · CONFIRMED |
LF13a RouterContextProvider | rising | 7.9.0 | 7.9.0 · CONFIRMED |
LF13c createContext exported | rising | 7.9.0 | 7.9.0 · CONFIRMED |
LF13e MiddlewareFunction | rising | 7.9.0 | 7.9.0 · CONFIRMED |
LF13g getContext | rising | 7.9.0 | 7.9.0 · CONFIRMED |
LF13b unstable_RouterContextProvider | window | 7.3.0..7.9.0 | WINDOW_HOLDS |
LF13d unstable_createContext | window | 7.3.0..7.9.0 | WINDOW_HOLDS |
LF13f unstable_MiddlewareFunction | window | 7.3.0..7.9.0 | WINDOW_HOLDS |
LF13h unstable_getContext | window | 7.3.0..7.9.0 | WINDOW_HOLDS |
LF13i unstable_middleware | window | 7.3.0..7.9.0 | WINDOW_HOLDS |
Every old-name row is a window and not an absence, for LF3b's reason: the prefixed names are also absent at 7.2.0 and below, where they had not yet been introduced, and an absence true for two different reasons is not contiguous. The windows' lower edge (7.3.0) is new measurement the fact does not claim; their upper edge is the fact's own date, which is what "gone, not aliased" means.
The part worth keeping: three of the changelog's own names could not carry a row
The 7.9.0 entry names four APIs. Three of the identifiers involved are undateable by the instrument that dated the other five, each for a different reason, and writing down which were refused is the measurement rather than a footnote.
createContextis React's. It occurs 40–45 times at 6.4.0 — eight releases before react-router exported any such thing — because this package callsReact.createContext.identifiers.mjsis identifier-wise rather than substring-wise and it does not help here, because the collision is between two real identifiers that share a name, not between a name and its prefix. That is a case LF3c's rule does not cover, and it is the first one in the corpus. So LF13c reads the export list instead: 7.8.2'sindex.d.tsexportsaq as unstable_createContextand 7.9.0's exportsaq as createContext— the same local binding, renamed at the boundary. It is the only row of this fact that executes the namespace, and it is deliberately absent fromkindsso it is labelledexecrather than claiming to be a declarations row.- Bare
middlewareis 50 occurrences at 7.3.0 and never zero after, so the route config key's arrival is unreadable the same way — and here there is no export to fall back on, because a route module'smiddlewareis a key the router reads, not a name the package exports. This fact therefore dates that clause from the departure only (LF13i), and the statement claims no more than that. RouterContextis non-contiguous as a bare identifier — 4 at 7.3.0–7.6.0, 8 at 7.7.0, 0 at 7.8.0 through 7.8.2, then 76 from 7.9.0. A rising row on it would have been refused by the runner, correctly. It is named in the fact's statement and probed through its prefixed spelling's window, not through itself.
This is LF12's onError trap met three more times inside one fact: date the identifier that is unambiguous, and write down which ones were refused and why. The tempting version of this session writes eight clean rows off the changelog's bullet list and never discovers that three of them measure something else.
Severity is the worse of two different failure modes
Filed S1 / breaks-build, and the statement carries both halves rather than averaging them. The import half is breaks-build: a named import of a removed export is TS2305 and a bundler error. The route-config half is silently-wrong — a route module exporting unstable_middleware compiles, loads and runs, and the middleware simply never executes, which is the more dangerous of the two where the middleware was doing auth. A fact that claimed only the throw would understate the case a reader actually gets hurt by.
What was not done, and why
- Nothing is charged.
react-router/v3-c(Opus 5) got this same event wrong in batteryv3, leaving the stabilisation in v8, and 7.9.0 is that subject's own stated describable ceiling — a miss at the boundary. But the correction is a fact and the charge would be a finding, and the run that produced it was not probing this surface. 0i's remaining half is a battery that elicits middleware without naming it; 7.9.0 is live for Opus 5 and Fable 5.1 and below Sonnet 5's cutoff, so the fact is drawable against three subjects. verified_onwas not moved. It means "every fact in this file was last checked against a primary source", and this session checked one. Moving it would have been a claim about twelve facts nobody re-read.- No full bisect.
--onlyis the right instrument here: the ladder did not change, and the subset is marked as a subset in the runner's own output. fact-citation-sweep.mjsrun anyway — a new fact is not a corrected one, so the rule did not require it, but LF13'salso_known_asadds twelve identifiers to the api join and the sweep is where a collision with an existing run record's prose would surface. Clean: 484 api joins, 8 allowlisted, 0 stale.
Registry check
node tools/fetch-releases.mjs --check, 2026-09-23 00:03Z: 7 of 8 current; next.js BEHIND on the patch pointer only, 16.3.5 → 16.3.6, patches 148 → 150 — identical to the 18:01Z, 20:02Z and 22:02Z readings. Fourth consecutive session to read the same drift and leave it. No tracked minor or major moved and releases.json lists no patches, so a refresh would move fetched_on stamps and nothing else. Noted in BACKLOG 0k.
State
Eight surfaces rebuilt and all green through the full pre-commit chain. react-router now holds 13 facts. Gates unchanged: node tools/asks.mjs is the count, and nothing here needed one — no account, no spend, no publish, no outbound.