← board

The question

Do we want to spend model time, every day, having something read every open ticket against the tree — or is that the job of whoever picks the ticket up?

That is the whole fork and it is answerable in a word. It is stated as a recurring cost and not as "whose job is it", because the cost is the part that is genuinely the owner's: the token budget is explicitly his dial, and the only approach measured to work here is a model pass over 586 open tickets on a cadence. Who-does-what is a design he has no stake in; what it costs, forever, he owns outright.

The cheap half needs no answer and is already built — see What has already been done below. This ticket is only about whether to add the standing spend.

Why it is worth a decision at all

Five stale summaries in one day, two lanes, every one with a correct body. Three are recorded in CLAUDE.md (task-b-write-the-lekkerzeilen-pxx-platform-backend at p85 — the highest open number under its umbrella — saying "IS A 39-LINE STUB" of a file the owner had rewritten to 974 lines; the alt-stack ticket dispatched at p70 with forty lines of its own body already saying FIXED; the DCE ticket still listing arm32/aarch64 as REMAINING after both landed). Two more were found by this seat the same day.

The cost is not tidiness. The summary carries the prio into the ranker, so a stale one promotes dead work to the top of a queue and a seat is dispatched to it.

What I measured before proposing anything

586 open tickets (backlog-*, urgent, working, unfinished, blocked).

1. A text-marker heuristic: recall 1 of 5, precision 0 of 7

The obvious check is "body announces completion while the summary is silent". Against the five real cases, reconstructed from git at their pre-fix revision:

ticket would the rule fire?
alt-stack yes
lekkerzeilen backend no — body never said FIXED; the world changed
DCE no
pxxcoswitch/riscv32 no
foreign-thread no

On the live backlog the same rule flags 7 of 586, and inspecting all seven: every one is a correctly open ticket whose summary already says so — "FIXED piece 1 of the three", "RESOLVED IN TWO HALVES", "FIXED AT HEAD, STILL WRONG IN THE PIN". Precision zero. Partial completion is the normal case, and it is indistinguishable from staleness by text.

Loosening the markers makes it worse, not better: no longer matches 79 tickets and is fixed matches 80 — the cry-wolf shape, and a guard that cries wolf on its first outside run teaches that it can be ignored.

2. The four misses fail for three different reasons

3. The one mechanically-checkable class FAILED ITS POSITIVE CONTROL

A summary that quotes a compiler diagnostic verbatim looked checkable: if the tree no longer contains the string, the ticket quotes something that cannot happen. 11 open tickets do this. Built it, then ran it against the case it was designed from — the riscv32 ticket, pre-fix:

probe = 'target riscv32: unsupported node in IR codegen:'
flagged = False

It cannot see its own founding case. The quoted string is a generic template still in the source; only the coswitch arm was added. The check would have shipped flagging 3 other tickets (unverified) while missing the one it existed for. A guard that cannot catch the case it was built from is not a guard, and this one only announced itself because it was given a control.

4. Age is not a signal here, and the first attempt to show that was wrong

Top-ranked tickets are 0-12 days old; nothing open exceeds 19 days. This tree takes ~250 commits a day (2,566 in the last ten). Staleness is caused by velocity, not neglect — the lekkerzeilen ticket went stale inside its own short life — so "flag anything older than N" has nothing to bite on.

Recorded because it nearly became a number in this ticket: the first age measurement used git log -- <path>, which does not follow renames, and the per-lane backlog folders are a recent reorganisation. It reported a tidy "median 13 days, max 19" that was really days since the file arrived at that path. --follow gives the real figures above.

5. The system-side answer is PARTLY BUILT, and its cost is visible today

tools/progress.sh check already carries eleven aperture families, two of them aimed at this idea from the other side — STALE-PARK (prose names a blocker that has since closed) and PROSE-EDGE-NOT-IN-FRONTMATTER (prose states a block the frontmatter never carried). Neither reads a summary against its own body, and none of the five cases is visible to any of the eleven.

Its present output is 45 findings, 36,395 bytes, of which 20 are NEAR-DUP and 11 are STALE-PARK-HELD. That is the shape a text-marker aperture takes at scale, and it is the cost this decide has to weigh: a 36KB report is not read, and adding a family with precision 0 makes it 36KB plus noise.

AND THE TOOL THIS DECIDE IS ABOUT IS ALREADY SPECIFIED: bug-t-check-has-no-aperture-for-a-ticket-whose-body-records-its-own-completion (Track T, p60, low-prio/), filed 2026-08-30 by frankB off a real dispatch loss, proposes exactly the missing aperture and states it as the mirror of the two that exist. Nobody has built it in twenty days.

The measurements above are that ticket's answer, and it is not the one it expects. Its aperture is the body-says-done rule: recall 1 of 5, precision 0 of 7. It would have caught its own founding case (feature-random-library, whose log says "Tier 1 is closed") — that is the class it was written from, and it is one class of three. It should be read before it is built, and this decide is the reason it should not simply be promoted.

The options

A — a standing model pass. Something reads every open ticket against its own body and against the tree, on a cadence. It is the only approach shown to be capable of the three classes that matter. The cost is the decision: 586 open tickets, re-read periodically, forever. That is a standing token commitment, and fleet token spend is the owner's dial, not a seat's.

B — the seat that picks it up. Already built (below). Costs no compute and no new judgement: the ticket's summary is put in front of the seat at claim, and tools/progress.sh verified <slug> records the outcome.

C — do nothing, and say so. Treat a ticket as a claim with a date on it, and put that sentence in CLAUDE.md. Honest, and it leaves the p85-pointing-at-finished-work case intact.

Recommendation: B is done; A is a later question, not a foreclosed one

Take no decision on A yet. B landing is what makes A arguable, because it produces the one thing this ticket cannot: a measured failure rate for the cheap option. If stale summaries keep arriving with verified: blank across the board, that is B not being used and the answer is not more automation. If they keep arriving with verified: dates on them, the cheap option has been tried and failed, and the recurring spend has an evidence base instead of an anecdote.

Do not read B as this being closed. And do not build a detector on the strength of this ticket: the measurements above are the argument against the cheap ones, and if the answer is A it should be A deliberately, with a budget, not a greppable subset that flags seven correct tickets and misses four wrong ones.

What has already been done (B, landed — this decide did not gate it)

A reversible tooling change in Track T's own lane, so the act-then-report rule covers it and a filed decide is not a reason to stall the half that needs no decision:

What would change this

A sixth and seventh instance whose bodies announce completion while their summaries stay silent would move recall above 1-in-5 and make the textual check worth its false positives. Re-run the reconstruction above before assuming it still holds — and give any detector a positive control drawn from the real cases, since that is the only thing that caught the diagnostic-quote check.

Related