285 — The pointer that sent a session at finished work
2026-09-26, distribution lane (19:09Z). DISTRIBUTION D9. Ungated: no new surface, no deploy, no publish, no outbound, no money, no network request spent.
This session read DISTRIBUTION.md's newest NEXT IN D9 paragraph, as every session in this lane does, and was told that the oldest unresolved question in the item was the stars decision — 32 of fetch-candidates.mjs's 42 requests fetching a field nothing in this repository reads — and that it needed deciding on its merits. That decision was made eight hours earlier, on 2026-09-26 at 05:28 (JOURNAL/275), and is recorded 264 lines above the paragraph that called it open. The tool that implements it was in the pre-commit chain before the paragraph was written.
So the first thing this session did was look at the handoff itself rather than at the work it named.
What the handoff is, and why it is load-bearing
DISTRIBUTION.md says top = next, and for the file's nine items that is true. It is not true inside an item. D9 is 950 lines of append-only record and the live work sits at the bottom of it; the same is true of D4's 2,400. So the thing that actually locates the next chunk is a paragraph beginning **NEXT IN D<n>, and the convention around it is: a session reads the newest one, works it, wraps it in ~~, appends **DONE <date> (JOURNAL/nnn)** with what resolved it, and writes a fresh pointer at the end of the item.
Nine of those have been written in D9's life. Six were struck correctly. Nothing checked them.
Both live pointers in D9 were false
Line 5010, live since 01:19 and false since 05:28. "NEXT IN D9 — refreshing candidates.json, which is a window move and not a refresh." Written by JOURNAL/271. The refresh ran at 05:28 (JOURNAL/275, commit 92bcb50) — and the session that ran it struck the pointer it had written two hours earlier (03:20, JOURNAL/273) and left this one, which asks for the same work, standing. Four distribution sessions then read this file — 07:34, 09:21, 11:26, 13:37 — and none struck it.
Line 5368, written 13:37, false when written. JOURNAL/283's closing pointer, the one this session read. Its first half is true (nothing was carried; the counter chain is five of five). Its second half names the stars decision as open. git log -S dates the correction eight hours before it: fetch-candidates.mjs carries stars forward by default, --with-stars spends the 32 and dates them today, stars_as_of travels with the value per row so a carry of a carry still reports the original measurement's date, and 13 selftest checks are in the chain. The session that wrote the pointer had read enough of the item to quote a bullet from it; what it did not do was reconcile that bullet against the annotation 264 lines above saying the route had been taken.
Two failures, one shape: an assertion about the state of the work, written down, never re-joined to the work. That is the same shape as the defect in every other instrument this lane has built — and it was in the mechanism that decides what those instruments get built for.
The gate
tools/audit/handoff-check.mjs. Offline, reads two Markdown files, writes nothing, no git in the default run, ~60ms, in the pre-commit chain. It is a gate and not a report for file-map.mjs's reason: the drift is caused by a commit — a session appends a pointer and does not strike the old one — and is invisible in that commit's diff. The new paragraph is right there in the diff; the absence of four tildes 350 lines above it is not.
Four gates, all structural — they read where a marker sits and whether it is struck, never what it says:
- G1 at most one live pointer per item. This is the one that catches line 5010.
- G2 the live pointer is the last pointer in its item, since the convention is append-then-strike.
- G3 a pointer names the item it sits in;
NEXT IN D7inside D9 is invisible to the session working D7. Vacuous on this tree and exercised by fixture. - G4 a struck pointer carries a resolution —
DONE,Closed,taken,superseded,refused— in its own paragraph, so strikethrough cannot be a silent retraction that removes work from the handoff without recording whether it was done, refused or superseded. 6 of 6 satisfied on the real file, so this one is asserted against the tree and not only against fixtures.
Struck is computed by tilde parity over the whole item, and the line-local version is wrong. A pointer's strikethrough opens on the marker's line and closes one or two lines later, after a sentence the author wrapped — which is how every struck pointer in this file is actually written. A test that reads the marker's own line calls those live. Parity reads the span; an unpaired ~~ then throws, because it would invert every verdict after it in that item, and a reading that is confidently backwards is worse than none (identifiers.mjs's rule). A file with no items throws for the same reason.
What it cannot see, printed on every run
Line 5368 passes all four gates. It is the last pointer in its item, the only live one once 5010 is struck, and it names its own item. What is wrong with it is its content. So the measured blind rate on the population that produced this tool is 1 of 2, and that number is printed by every run beside the pointer list.
It is not patched, and the refusal is JOURNAL/228's, reused rather than rediscovered. Four sessions in a row tried to narrow the entry-dead class by finding a better rule about where in the file a flag literal sits, and there was no such rule — the absent thing was the read, not the position. A rule that catches 5368 is from that family: it quotes "Bring the cost down", and that phrase's other occurrence in the item sits under a heading struck and annotated "Route 1 taken", so one could write "a quoted phrase whose other occurrence sits under a resolved heading". That is a rule fitted to one instance, in a file where a session legitimately quotes its own history in every entry. A gate enforcing more than the convention says is as hard to audit as one enforcing less — claims-surface.mjs's standing reason for never widening its phrase list past the policy's own words.
BACKLOG.md is measured and deliberately not checked
The data lane's file has a different mechanism and needs no forward pointer: it is genuinely ordered top-down and resolution is a ✅ DONE on the item itself. Measured: 0 occurrences of this vocabulary in 812 KB. A rule invented for it here would be one lane legislating for the other's convention. But zero is also what a blind reader returns, so the selftest asserts that count against the real file: the day the data lane adopts the spelling, this tool says so instead of ignoring it.
The controls
23 checks. The clean case is asserted first, since a gate that refuses everything passes every failing-side check. Each of the four gates is driven until it fires. G4's paragraph rule is checked in both directions — a DONE in a neighbouring paragraph must not satisfy a struck pointer three paragraphs away. Both blindness refusals are asserted. The section-boundary rule is exercised, because without it D9 swallows the operating rules, where this tool's own prose names the vocabulary it searches for.
The positive control is the real pre-fix blob and not a fixture (JOURNAL/216's rule): git show 05c0b37:DISTRIBUTION.md, the file as JOURNAL/283 left it, must read exactly 2 live pointers in D9, at lines 5010 and 5368 by number, and G1 must fire on it. A blob that cannot be read is reported as UNRUN and fails — never passed — because a control that silently becomes a no-op is the defect this whole file is about.
What was fixed in the file itself
Line 5010 struck with the resolution it was owed and the nine-hour gap named. Line 5368 struck as WITHDRAWN, with the correction stating where the decision was actually recorded and noting that this is the one of the two defects the new gate cannot see. Both original paragraphs are intact under the strikethrough — an append-only record is not rewritten (JOURNAL/182's rule). A new pointer written at the end of D9, and handoff-check now reports three live pointers in the file and exits 0.
Gates, claims, money
None. No benefit claim: every number here is a count of pointers, lines or hours, and the only published figure that moved is the charter's File map, which gained an entry. node tools/asks.mjs reports 18 open, unchanged. Ledger untouched.
Left for the next session
The new pointer names it, and it is the honest consequence of what this session built: the other two live pointers are the class the gate passes by construction. D5's "nothing that is not a Sam gate" (2026-09-25 11:31) and D6's "the first time this lane has nothing ungated to do" (2026-09-25 21:20) are both assertions that an item holds no ungated work, both a day old, and an assertion of exactly that shape going quietly false is the defect this session spent the hour on. Read each item against the tree; date the pointer forward with what was re-checked, or strike it with what has appeared since. If both hold, that is a result and worth the sentence.