test(repo): guard prose that has an expiry date#44
Merged
Conversation
The 2b/2c drift cleaned up in #43 was not a set of false claims. All four sentences were TRUE when written and were supposed to die when a stage landed, and nothing enforced the expiry: convention 5 covers claims that are wrong, and check_notes.py deliberately does not check prose at all. So they outlived the code they described by several PRs, telling every later session the opposite of what the code did. Discipline alone produced four stale sites in one transition, so this adds the mechanical step. Prose that is only true until a stage lands now carries a PENDING marker naming that stage, and the open ids live in exactly one place. Closing a stage is one deletion from that set, which turns the guard red on every marker still pointing at it - so the prose is corrected in the same commit as the code. - test_no_stale_pending_markers scans every .py and .md for markers and checks BOTH directions: an id that is not open fails, and an open id that nothing references fails (a leftover entry) - OPEN_PENDING is the single source of open ids and is deliberately NOT a roadmap - it is the set of ids that PROSE points at, which is what makes the second check meaningful - mutation-checked both ways, not asserted: a probe marker for an unlisted stage and an unreferenced id each turned the test red, with file:line in the message - first real marker goes on the SocketEvent comment, itself a leftover of 2c: proto/remote_ip/remote_port/outbound are still unconsumed, so the comment now says so and PENDING(socket-event-fields) forces the decision to be revisited - rejected, measured not guessed: scanning for the word "yet" gives 25 hits of which ~21 are permanently true, a false-positive rate that gets a guard switched off within a week - convention 44, the sub-rule under process rule 5 and a new definition-of-done step live in the private notes, which this test cannot see - that half stays manual on purpose Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Follow-up to #43. That PR cleaned up four stale comments; this one stops them coming back.
The important bit about #43 is that it was not a set of false claims. All four sentences were
true when they were written and were supposed to die when a stage landed - "NOT read by targeting
yet - that is 2c" was accurate right up to the moment chunk 2c shipped. Convention 5 covers claims
that are wrong;
check_notes.pydeliberately does not check prose at all. So nothing anywhereenforced the expiry, and the sentences outlived the code they described by several PRs, telling
every later session the opposite of what the code actually did. Discipline alone produced four
stale sites in a single transition, which is the argument for a mechanical step rather than
another reminder.
So: prose that is only true until a stage lands now carries a
PENDING(<id>)marker namingthat stage, and the ids still open live in exactly one place. Closing a stage is one deletion from
that set, which turns the guard red on every marker still pointing at it - so the prose is
corrected in the same commit as the code that outdated it, instead of whenever somebody happens to
re-read it.
What a reviewer should know:
test_no_stale_pending_markerschecks both directions, and the second one is thenon-obvious half: a marker naming a closed stage fails (the prose beside it is now a lie), and
an id in
OPEN_PENDINGthat nothing references also fails (a leftover entry). That is whyOPEN_PENDINGis documented as not a roadmap - it is the set of ids that prose points at.unlisted stage, and an unreferenced id added to the set, were each confirmed to turn the test
red with the offending
file:linein the message. The probe was removed;git status --untracked-files=allis clean.idiom this file already uses for
scrollable.pyandcrashlog.py. The<id>placeholder formdoes not match the pattern, so docs and changelogs can name the token without registering it.
SocketEventcomment insocketwatch.py, which was itself aleftover of 2c ("carried for the connection log later").
proto/remote_ip/remote_port/outboundare genuinely still unconsumed, so the comment now says so plainly and the markerforces that decision to be revisited rather than quietly kept. Whoever closes it deletes one
line from
OPEN_PENDINGand the guard makes sure the comment does not survive alone.beantester/and
tests/, roughly 21 of them permanently true ("width 1 == not laid out yet", "no honestanswer yet"). A guard with that false-positive rate gets switched off within a week, so the
token is opt-in by design.
free text still gets through, and the guard cannot see
PROJECT_NOTES.mdat all because thatfile is not in this repo. Convention 44 and a new definition-of-done step (grep for the id when
closing a stage) cover that half manually, and say so explicitly.
Checklist
python -m pytest testspasses locally. (661 tests, 0 failures - one more than before, whichis the new guard; on an elevated shell, so the two known non-admin failures are absent
rather than excused.
smoke_gui.py: OK.)tests/for the style). - the change is a test, and it wasmutation-checked in both directions rather than trusted.
lang/en.jsonandlang/pl.jsonupdated. -n/a: no UI text.
CHANGELOG.md; technical ones and new tests inCHANGELOG-INTERNAL.md, under[Unreleased]. - internal only (convention 39): a new testand one comment, nothing a tester can see.
type(scope): summary).VERSION.txt.🤖 Generated with Claude Code