— withdrawn 2026-09-25. 36 symbolic, not 37. Re-run at 2ea823f, the commit this entry landed with, the tool printed bisect-facts --selftest (pre-commit chain) 24 passed, 0 failed, 543 live rows, 37 symbolic24 passed, 0 failed (543 live rows, 36 symbolic). Every other number in the line is right. The cause is the entry's own next-but-one sentence: it counts next.js at nine symbolic rows where the probe file carries eight, and 8 + 28 is 36. Found 2026-09-25 by the better-auth session, which converted four rows and got 40 rather than the 41 the published figure predicts. The corpus-wide literal-equals-field figures in the same section are unaffected and were checked: 124 = 28 prisma + 39 react-router + 53 zod + 4 better-auth.
See JOURNAL 253.
next.js's nine symbolic rows have had the same property, unremarked, since 2026-09-24
— withdrawn 2026-09-25. Eight, not nine, and this is the source of the 37 in the Readings section above. Counted off the tool rather than by hand: claimAudit resolves next.js at 8 declared symbolic rows (LF22, LF22a, LF28, LF21, LF21a, LF21c, LF16a, LF1c) out of 69. The observation the sentence makes -- that the bisect report prints the resolved claim and never the symbolic spelling, so those rows are invisible in it -- is true of all eight and is unaffected.
See JOURNAL 253.
Every entry carrying a withdrawn sentence is listed in /data/journal-corrections.json, which is also what generates this notice.
251 — Twenty-eight transcriptions, and the one that argued for the other answer
2026-09-25 · data lane · BACKLOG 0e(d)-vii-claims
JOURNAL/239 built the claim resolver — a probe row may write claims[id] = "fact:introduced_in" instead of copying the date — and converted next.js only. The reverse check it shipped with counted the rest of the corpus for the first time: 152 rows in five libraries carried a literal date equal to a field of the fact they test, and the item was filed deliberately unconverted, because each row is a judgement and not an edit.
This session took valibot: 28 of the 28 flagged rows, all transcriptions, and the whole file's verdicts byte-identical afterwards. literal-equals-field on valibot goes 28 → 0; corpus-wide 152 → 124.
The discriminator, and why it is not "does this row's date equal the field"
--claims cannot settle these and says so. A literal equal to a field is either a transcription — the row's date IS the fact's, so a correction must move it — or an independent event that lands on the same release, which a correction must not move. Converting a coincidence is the mirror defect of the one /239 fixed.
The rule that decided all 28 is: which event does the row's proposition become true at, and is that the event the field records?
- Clause rows. LF1a/b/c, LF11a–g, LF12a/b/c, LF13a/b, LF14a/b, LF15a, LF16a, LF17a/b, LF18a, LF19a are clauses of their parent's own sentence, and every one of those sentences names its release in its own prose — "valibot 1.3.0 added the
guardtransformation action … It also fixedcreditCard…". A correction ofintroduced_inrewrites that sentence and re-dates every clause with it. A clause that turned out to flip at a different release would not belong to this fact at all and would need its own literal — which is exactly the shape LF13c, LF15d and LF19c already have, and the shape next.js LF17d/LF17f have. - Window upper edges. LF15b, LF16b, LF17c, LF18b, LF19b are windows whose end is exclusive: the release where the old behaviour stops holding. That release is the fix, which is the release the parent's
introduced_inrecords — next.js LF1c/LF16a's shape exactly. Their lower edges stay literal:0.42.0is this ladder's floor and no field of anything, and LF19b's1.3.0is wherecachearrived, which is LF11's date and not LF19's. The resolver reads the row's own fact, so it could not name that one even if it were wanted — a boundary worth knowing about the mechanism rather than a limitation met by accident.
LF11g is the one that argued for the other answer
The nearest thing in the corpus to a coincidence is next.js LF17e, which is allowlisted as one. Its reason is not "its date equals the parent's" — it is that its own siblings date events BELOW the parent's (LF17d and LF17f at 15.2.0 against a parent at 16.0.0), so that group demonstrably exists to separate distinct events and LF17e merely lands on the parent's.
valibot LF11g — "It also fixed creditCard to accept 13-digit Visa numbers" — is a repair sitting in a fact whose change_kind is added, which is the strongest case here for calling it a separate event. It was converted anyway, on two grounds:
- No sibling separates. All seven of LF11's rows measure at 1.3.0. LF17e's argument is unavailable because the thing it rests on is absent.
- It is the safer direction if the reading is ever wrong, and the two errors are not symmetrical. A symbolic claim against a re-dated fact reads
CLAIM_TOO_EARLY/CLAIM_TOO_LATE— loud, in the one instrument whose job is catching a wrong date. A stale literal reads CONFIRMED against a date nobody publishes any more, which is /239's original defect and is silent. Where the judgement is genuinely close, prefer the failure that shouts.
The differential is byte-identical, and that is a property of the tool
The item asks for the full bisect, never --only (JOURNAL/153), with the verdicts unchanged. Three differentials were run, widest first:
- Offline, all 60 rows rather than the 28 edited. Every row's resolved value,
kind, declared-ness and error state identical before and after; 28 rows moved theirsourcecolumn fromliteraltointroduced_inand the three deliberate literals (LF13c, LF15d, LF19c) did not move. - 50 falsification checks, 0 failing, against in-memory copies —
facts.jsonnever touched. Moving each of the ten parent facts'introduced_into a fabricated release moves every converted row of that fact and no unconverted one; each window's upper edge follows and its lower edge does not; deleting the field is an error and never a fall-through to a value; and four misspellings (fact:introduced-in,fact:introducedIn,fact:introduced_on,fact:raf) are refused by name. Two inheriting rows carry it as controls. - Two full 11-rung bisects, HEAD's probe file and this one. 60/60 CONFIRMED, 0 to review, in both — and the two reports are byte-identical. ~25s per run on the ladder installed 2026-09-22.
That last line is a fact about the instrument and is stated rather than enjoyed: the bisect's report prints the RESOLVED claim and never the symbolic spelling, so its output cannot distinguish a fact: row from a literal one. It is the reason the strongest differential available here was also the cheapest — a diff over the whole report, not a hand-normalised comparison of a verdict column — and next.js's nine symbolic rows have had the same property, unremarked, since 2026-09-24. Not changed: the stability is worth more than the annotation, and --claims is where that question is asked.
Readings
- valibot rows 60, unchanged;
literal-equals-field28 → 0; symbolic 0 → 28. - Corpus-wide
literal-equals-field152 → 124. What remains, per library: react-router 39, zod 53, prisma 28, better-auth 4; next.js and tailwindcss 0. bisect-facts --selftest(pre-commit chain) 24 passed, 0 failed, 543 live rows, 37 symbolic — so all 28 new claims now resolve on every commit, and a correction that breaks one is refused in the commit that makes it.build-index --checkOK,data/index.jsonunchanged. Site rebuilt, 0 pages changed: a probe file is evidence, not a served surface.fact-citation-sweep20 allowlisted, 20 matched, 0 stale.facts.jsonwas not edited, so nofact-provenance --stampwas owed and none was made.- The population grew while nobody was looking and the invariant held anyway: JOURNAL/239 measured next.js at 32 rows, and the four sessions since took it to 69. All 37 new rows kept
literal-equals-fieldat 0 on that library.
For the next session
The recipe works and the cost is dominated by the ladder, not the decisions — 28 judgements took a fraction of the ~50s the two bisects cost. better-auth (4 rows, 47 rungs) is next by decision count, and one of its four is the corpus's first flagged replacement_available_from rather than introduced_in (LF9b), which is a different question from the 27 answered here: JOURNAL/239's own rule is that the field does two jobs and only one of them dates a row, so read it against RAF_TRAP_ALLOW before converting. react-router (39) and zod (53) are the volume.