The review sweep
OPS-149. The owner asked for this on 2026-09-17:
And I think each ticket should have, like, a last reviewed on, like, a date that it was last reviewed. So maybe now we do, like, a sweep, but maybe from here, we say, like, if a ticket was lying around for, like, a certain amount of time, then we revise it and keep it, like, a parameter that we can play with. Um, but I think, like, ten days, two weeks sounds reasonable to me. maybe it start even less.
Everything below the marker is generated by python3.12 scripts/check_ticket_lifecycle.py --write. It is a function of the clock, so it is the one generated document in this repository that make doc-gates does not drift-check - a --check on it would go red every midnight and teach everybody to ignore the gate. It carries its own as of date instead, and a reader judges its age by reading it. Re-run the generator rather than quoting this file from memory.
The three things the owner asked for, and where each one lives
| he asked for | it is | where |
|---|---|---|
| a terminal status, so a finished ticket can be filtered out | already there, three times over: merged, accepted, withdrawn. done is a retired spelling on purpose | backlog/schema.toml, the [[status]] blocks and [retired.status] |
| tickets not deleted | a gate that did not exist. Four ticket ids have left the register | scripts/check_ticket_lifecycle.py --ever and --deletions |
last_reviewed_on, and a sweep with a threshold he can play with | a new optional field, seeded from each ticket's filing date | the field in backlog/schema.toml, the sweep below |
No status was added. CLAUDE.md forbids a second name for something that has one, and the ask was about filtering and about enforcement rather than about a missing word. What merged and accepted already do, gen_state.py's stage_of already reports: unbuilt, built, closed, so a terminal ticket drops out of every count a planner reads while its file and its id stay exactly where they are.
Four ids have left the register, and no subject has
python3.12 scripts/check_ticket_lifecycle.py --ever, on 2026-09-17: 513 ids ever written, 510 now, 4 gone. Thirteen ticket files were deleted across seven commits between 2026-09-12 and 2026-09-16. The two counts differ because most of those deletions replaced a file in place, and an id is what the register is keyed on.
| id | what happened | where the subject went |
|---|---|---|
ADAPT-003 | deleted at af2404ab, "drop five duplicate tickets, keep three" | CORE-019, the uncalled adapter layer |
CORE-020 | deleted in the same commit | backlog/cli/export-claims-matches-a-bare-name.md |
CORE-021 | renumbered to CORE-034 in the same commit, same file | CORE-034 |
OPS-065 | renumbered to OPS-068 during an id collision on 2026-09-13 | OPS-068 |
So the answer to "I hope we haven't" is: we have, thirteen times, and no subject was lost - each deletion folded its content into a surviving ticket or replaced a reserved stub. Two costs remain and neither is recoverable by a gate:
- Five bodies exist only in git history.
af2404abdropped five substantive tickets, 143 to 203 lines each, and62d4ff78two more. Their reasoning is in the object store and in no file a reader will open. - Five ids were reused for a different subject after their earlier file was deleted:
CORE-014,CORE-040,DOC-022,OPS-016,CLI-041. A merged commit message sayingRef: CORE-040now resolves to a ticket about something else, which is exactly the harmreserve_ticket_id.py'snext_freedocstring refuses to create and which deletion created anyway.
--deletions is the half that is cheap enough to run every build. It compares against the merge base with the trunk rather than against the trunk itself, because main moves about 170 times in two days here and an id it gained after a branch was cut would otherwise read as that branch deleting one.
<!-- BEGIN GENERATED review-sweep -->
<!-- Generated by check_ticket_lifecycle.py --write. As of 2026-09-17. -->
As of 2026-09-17, at a threshold of 10 days and a limit of 20: 0 of 247 reviewable tickets are eligible, 0 of them because nothing has ever recorded a review.
Reviewable means unbuilt. A merged, accepted or withdrawn ticket is not in the pool, which is the owner's "then it can easily filter them out" and needed no new status to do - scripts/gen_state.py's stage_of already answers it from the schema.
What each row is asking for
Three verdicts, and two of them are an edit to the ticket:
| verdict | what it means | how it is recorded |
|---|---|---|
| keep | it still matters, as written | python3.12 scripts/check_ticket_lifecycle.py --reviewed <ID> |
| re-score | it matters differently now | edit value, urgency, importance, then python3.12 scripts/score.py --check |
| retire | it will not happen, or it already did | status: withdrawn with a reason - or merged/accepted if the work landed. Never delete the file |
OPS-150 is the open question behind the second one: nothing in this repository recomputes a score, so re-scoring today is a person re-asserting a number.
When the queue arrives
Every ticket in this backlog was filed between 2026-09-11 and 2026-09-17, so seeding last_reviewed_on from the filing date moves the queue rather than spreading it. This is the table to read before changing the threshold.
| date | newly eligible | eligible in total |
|---|---|---|
| 2026-09-17 | 0 | 0 |
| 2026-09-18 | 0 | 0 |
| 2026-09-19 | 0 | 0 |
| 2026-09-20 | 0 | 0 |
| 2026-09-21 | 0 | 0 |
| 2026-09-22 | 9 | 9 |
| 2026-09-23 | 80 | 89 |
| 2026-09-24 | 38 | 127 |
| 2026-09-25 | 37 | 164 |
| 2026-09-26 | 41 | 205 |
| 2026-09-27 | 34 | 239 |
| 2026-09-28 | 8 | 247 |
| 2026-09-29 | 0 | 247 |
| 2026-09-30 | 0 | 247 |
| 2026-10-01 | 0 | 247 |
--limit is why that is survivable. The sweep asks for 20 decisions, oldest first, and recording them is what makes tomorrow's list different.
The head of the queue, 20 of 247
Ordered by age of review, then by derived priority. The eligible column is where the 10-day threshold falls, so moving the parameter moves a line through this one table rather than producing a different one - which is the only way to see what a threshold is worth before choosing it.
never in the last-reviewed column would mean no review has ever been recorded. Nothing shows it today because --seed gave all 247 of these their filing date, which is the date somebody last asserted the ticket mattered - see backlog/schema.toml.
| ticket | eligible | priority | status | last reviewed | age | the decision |
|---|---|---|---|---|---|---|
DOC-001 | not yet | P1 | pending | 2026-09-11 | 6d | keep, re-score, or withdraw |
DOC-004 | not yet | P1 | pending | 2026-09-11 | 6d | keep, re-score, or withdraw |
OPS-004 | not yet | P2 | pending | 2026-09-11 | 6d | keep, re-score, or withdraw |
OPS-006 | not yet | P2 | pending | 2026-09-11 | 6d | keep, re-score, or withdraw |
COMP-006 | not yet | P3 | pending | 2026-09-11 | 6d | keep, re-score, or withdraw |
COMP-007 | not yet | P3 | pending | 2026-09-11 | 6d | keep, re-score, or withdraw |
CLI-002 | not yet | unscored | unscoped | 2026-09-11 | 6d | no reason and no scores: scope it, or withdraw it |
COMP-002 | not yet | unscored | unscoped | 2026-09-11 | 6d | no reason and no scores: scope it, or withdraw it |
COMP-004 | not yet | unscored | unscoped | 2026-09-11 | 6d | no reason and no scores: scope it, or withdraw it |
CORE-040 | not yet | P0 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
CORE-043 | not yet | P0 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
OPS-038 | not yet | P0 | in_progress | 2026-09-12 | 5d | is anybody still on this? (no branch named) - if not, back to pending or withdraw |
COMP-014 | not yet | P1 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
COMP-016 | not yet | P1 | pending | 2026-09-12 | 5d | blocked on unbuilt COMP-077: keep, or withdraw as overtaken |
COMP-019 | not yet | P1 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
COMP-020 | not yet | P1 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
COMP-022 | not yet | P1 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
COMP-026 | not yet | P1 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
COMP-031 | not yet | P1 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
CORE-010 | not yet | P1 | pending | 2026-09-12 | 5d | keep, re-score, or withdraw |
python3.12 scripts/check_ticket_lifecycle.py --limit 100 prints more of it, and --threshold 5 is the parameter moved to the number the owner guessed at when he said "maybe it start even less".
<!-- END GENERATED review-sweep -->