Skip to content

test(repo): guard prose that has an expiry date#44

Merged
donislawdev merged 1 commit into
masterfrom
test/pending-marker-guard
Jul 25, 2026
Merged

test(repo): guard prose that has an expiry date#44
donislawdev merged 1 commit into
masterfrom
test/pending-marker-guard

Conversation

@donislawdev

Copy link
Copy Markdown
Owner

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.py deliberately does not check prose at all. So nothing anywhere
enforced 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 naming
that 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_markers checks both directions, and the second one is the
    non-obvious half: a marker naming a closed stage fails (the prose beside it is now a lie), and
    an id in OPEN_PENDING that nothing references also fails (a leftover entry). That is why
    OPEN_PENDING is documented as not a roadmap - it is the set of ids that prose points at.
  • Mutation-checked, not asserted (convention 5): a probe file carrying a marker for an
    unlisted stage, and an unreferenced id added to the set, were each confirmed to turn the test
    red with the offending file:line in the message. The probe was removed; git status --untracked-files=all is clean.
  • The guard skips its own file, which holds the ids rather than pointing at them - the same
    idiom this file already uses for scrollable.py and crashlog.py. The <id> placeholder form
    does not match the pattern, so docs and changelogs can name the token without registering it.
  • First real marker goes on the SocketEvent comment in socketwatch.py, which was itself a
    leftover of 2c ("carried for the connection log later"). proto / remote_ip / remote_port /
    outbound are genuinely still unconsumed, so the comment now says so plainly and the marker
    forces that decision to be revisited rather than quietly kept. Whoever closes it deletes one
    line from OPEN_PENDING and the guard makes sure the comment does not survive alone.
  • Rejected, measured not guessed: scanning for the word "yet". 25 hits across beantester/
    and tests/, roughly 21 of them permanently true ("width 1 == not laid out yet", "no honest
    answer yet"). A guard with that false-positive rate gets switched off within a week, so the
    token is opt-in by design.
  • Known coverage limit, stated on purpose: this catches marked prose. Unmarked "not yet"
    free text still gets through, and the guard cannot see PROJECT_NOTES.md at all because that
    file 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 tests passes locally. (661 tests, 0 failures - one more than before, which
    is the new guard; on an elevated shell, so the two known non-admin failures are absent
    rather than excused. smoke_gui.py: OK.)
  • New behaviour has tests (see tests/ for the style). - the change is a test, and it was
    mutation-checked in both directions rather than trusted.
  • UI text goes through i18n keys, with both lang/en.json and lang/pl.json updated. -
    n/a: no UI text.
  • User-facing changes noted in CHANGELOG.md; technical ones and new tests in
    CHANGELOG-INTERNAL.md, under [Unreleased]. - internal only (convention 39): a new test
    and one comment, nothing a tester can see.
  • Commits follow Conventional Commits (type(scope): summary).
  • No version bump - the owner closes a version via VERSION.txt.

🤖 Generated with Claude Code

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>
@donislawdev
donislawdev merged commit 2d3a12e into master Jul 25, 2026
8 checks passed
@donislawdev
donislawdev deleted the test/pending-marker-guard branch July 25, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant