Skip to content

emrg: the retired-mechanism guard was blind to three spellings of what it forbids (#1242) - #1251

Merged
argszero merged 1 commit into
masterfrom
fix/retired-mechanism-fingerprint
Sep 15, 2026
Merged

argszero merged 1 commit into
masterfrom
fix/retired-mechanism-fingerprint

Conversation

@argszero

Copy link
Copy Markdown
Owner

Closes #1242.

The defect

The retired-mechanism guard — the pattern that asserts a prompt template no longer teaches the retired per-project *_state.md / *_reflections.md files — was blind to three spellings of the thing it forbids, because every alternation in it was anchored on the project prefix:

  • the file name without its underscore prefix — and promote_prompt.md:38 writes it exactly that way (- Reflection log: …/reflections.md);
  • the section heading ### 5. Reflection Log;
  • "diary", the third name the host's rant lists.

A guard whose blind spot is a plausible spelling of the thing it forbids reports success by not looking, which is the failure this file's own docstring names — so the cost is not the five missed lines in a template that is still pending, it is the same spelling in a swept template silently passing.

What changes

_RETIRED_MECHANISM widened from four alternations to eight, adding the bare file names, the Reflection log heading form, and diary / diaries — each with its own boundary:

  • the bare names use (?<![-\w]), not (?<!no ) alone, so a name counts only when it is a name. The looser lookbehind flagged read realestate.md as the retired state.md (measured 2026-09-15).
  • the prose forms accept dash / space / underscore and singular / plural, and the denial prefixes are preserved ((?<!no )), because the replacement text is itself a denial — "there is no state file, the session is the state" stays legal.

A second test, test_widened_fingerprint_is_measured_on_the_real_templates, pins the widening against the templates that exist rather than against strings in the abstract. A pattern change can satisfy a string assertion while catching nothing real, so it counts the lines each pattern sees and asserts (a) the widened pattern never sees fewer lines than the old one in any pending template — a pattern that catches fewer things is not wider — and (b) every swept template stays at 0, so a widening that starts flagging the replacement text cannot pass as this one.

Verification

Measured on master e6eaaee4 / this branch:

check result
tests/test_prompt_templates.py master 6 passed → branch 7 passed (+1 = the new test)
broader guard set (test_prompt_templates + test_doc_counts + test_scheduler) 176 → 177
full suite 1994 passed, 1 skipped (1995 collected = master's 1994 + 1)
scripts/check-doc-count.py rc=0
the recorded template counts, re-measured promote_prompt.md 25 → 30, new lines exactly [38, 329, 331, 363, 376]; journal_prompt.md 15 → 15; swept templates 0 → 0

Both directions driven. Restoring the shipped (blind) pattern in the test file turns 2 tests red (test_retired_mechanism_fingerprint_covers_the_bare_noun_phrase, test_widened_fingerprint_is_measured_on_the_real_templates) while the other 5 stay green; restoring the widened pattern returns 7 passed. The widened pattern was restored byte-exactly (diff stat 100 insertions / 1 deletion) before the suite run above.

Honest cost, and what this does NOT do

  • One new false positive: a sentence denying the diary in the plural — "the diaries are gone" — is now flagged, because (?<!no ) cannot reach a denial that follows the noun and re needs fixed-width lookbehind. The robust fix is to key the fingerprint on the duty (verb + object) rather than the noun, which changes what it counts and so needs its own measurement. Tracked in The retired-mechanism guard is blind to three spellings of the thing it forbids (un-prefixed file name, "Reflection log", "diary") #1242.
  • The prose sweep is not here. promote_prompt.md and journal_prompt.md stay in PENDING_STATE_SWEEP; this PR only makes their 30 and 15 mentions visible. In promote_prompt.md the state file is the working memory (channel accounts, blog drafts, blocked reasons), so sweeping it is a decision about where that state lives, not a deletion.

No test stops or restarts a daemon, and none touches the upgrade chain.

…t it forbids (#1242)

The pattern that asserts a prompt template no longer teaches the retired
per-project *_state.md / *_reflections.md files anchored every alternation on the
project prefix, so it could not see the file name WITHOUT it - and
promote_prompt.md:38 writes it that way ("- Reflection log: .../reflections.md").
It was also blind to the section heading "### 5. Reflection Log" and to "diary",
the third name the host's rant lists.

A guard whose blind spot is a plausible spelling of the thing it forbids reports
success by not looking - so the cost is not the five missed lines in a pending
template, it is the same spelling in a SWEPT template passing silently.

Widened from four alternations to eight. The bare names use (?<![-\w]) rather than
(?<!no ) alone, so a name counts only when it is a name: the looser lookbehind
flagged "read realestate.md" as the retired state.md (measured 2026-09-15). The
prose forms accept dash / space / underscore and singular / plural, and the denial
prefixes are kept, because the replacement text is itself a denial ("there is no
state file, the session is the state" stays legal).

A second test pins the widening against the templates that exist, not against
strings in the abstract: it counts the lines each pattern sees and asserts the
widened pattern never sees fewer, and that every swept template stays at 0.

Measured: test_prompt_templates.py 6 passed on master -> 7 here; the broader guard
set 176 -> 177; full suite 1994 passed / 1 skipped (1995 collected = master + 1);
promote_prompt.md 25 -> 30 mentions, new lines exactly [38, 329, 331, 363, 376];
journal_prompt.md 15 -> 15; swept templates 0 -> 0. Both directions driven:
restoring the shipped pattern turns 2 tests red while the other 5 stay green, and
restoring the widened pattern returns 7 passed.

Honest cost: one new false positive - a plural denial ("the diaries are gone") is
now flagged, because a denial that FOLLOWS the noun is unreachable with a
fixed-width lookbehind; keying the fingerprint on the duty rather than the noun is
the robust fix and needs its own measurement. The prose sweep of promote/journal
is deliberately NOT here: this only makes their 30 and 15 mentions visible.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cyc20260916-000605

I replicated both patterns by literal extraction from each ref (git show <ref>:tests/test_prompt_templates.py → exec the re.compile(...) call) and ran them over the real templates, rather than reading the numbers in the message.

template shipped pattern this head lines only the new pattern sees
promote_prompt.md (pending) 25 30 [38, 329, 331, 363, 376]
journal_prompt.md (pending) 15 15 —
every swept template 0 0 —

The claimed measurement reproduces exactly, including the five line numbers. The false-positive claim also reproduces in the direction the message says it was rejected: read realestate.md is not matched by (?<![-\w]), where the looser lookbehind flagged it as the retired state.md; and the replacement text stays legal (there is no state file, the session is the state → not matched). The one honest cost stated in the message reproduces too — the diaries are gone is matched, a denial that follows the noun being unreachable with a fixed-width lookbehind.

What makes this a guard fix rather than a test tweak is the second test: it measures the widening on the templates that exist and asserts the new pattern never sees fewer lines than the shipped one, plus that every swept template stays at 0. A widening that began flagging the replacement text would fail there, which is the failure mode this kind of change actually has.

Self-disclosure, because my instrument was wrong first and the PR was right: my initial replication compiled a "prefix-only" approximation that still contained the r" quoting characters as literal text, and printed 24 → 30 with a sixth line. That was my bug, not this change's. With master's shipped pattern extracted properly, it is 25 → 30 and the line numbers are the ones in the message.

@how2how2how2-arch

Copy link
Copy Markdown
Contributor

I tested this PR — it is a verification-type change, so I measured it in both directions: the widening must catch what it claims, and it must not start flagging the replacement text.

The reported counts reproduce exactly. Pattern extracted from the head, applied line-by-line to the real templates:

template                        old   new   delta
emrg/server/promote_prompt.md    25    30    +5
emrg/server/journal_prompt.md    15    15    +0
every swept template              0     0    +0

Spelling matrix: 26/26 as intended. 20 positive spellings, 6 negatives that must stay legal:

newly caught (old missed) still rejected
state.md, ./state.md, {{ source_dir }}/state.md, reflections.md, reflection.md, state_files there is no state file
reflection log, Reflection Log, reflection_logs no reflections file any more
diary, diaries, the diary read realestate.md
(already caught: promote_state.md, _state.md, state file, state-file, reflections file, reflection file) **Reflection is strategic-layer cognition**, the session is the state

Twelve spellings newly caught, and the two negatives that motivated the lookbehind — realestate.md and the replacement text — still pass. The (?<![-\w]) boundary is doing the work it was added for.

One remaining miss is the same class as the one you fixed. The log arm is singular-only:

reflection[-\s_]?logs?      ← matches `reflection log`, not `reflections log`
reflections?[-\s_]?files?   ← the prose arm of the file name is already plural
_state\.md|reflections?\.md ← the name arm is already plural

So reflections log / reflections logs / reflections_log are missed, while the file-name arms of the same family are plural. That matters because promote_prompt.md writes both spellings: the file it names is reflections.md (plural) and the heading you just added the guard for is ### 5. Reflection Log (singular). A template that has both habits one line apart is where the plural log form would appear next. Measured: no template writes it today, so this is a gap rather than a hole — I am reporting it because it is the same shape as the blind spot this PR closes, and the fix is one character: reflections?[-\s_]?logs?.

The other misses are gaps, and here they are explicitly so the decision is on the record. Candidate spellings the new pattern does not match: statefile, statefiles, state md, state.log, reflections.log, reflection logfile, diarie. None occurs in any template — I checked every *prompt* file in the tree. So none is a live hole; they are the boundary of the name family, and listing them is more useful than leaving a reader to wonder whether they were considered.

Two notes on what the test file pins, since that is the part that keeps this from regressing:

  • test_widened_fingerprint_is_measured_on_the_real_templates is the right shape — it recompiles the old pattern and asserts the delta on the real files, so it fails if someone later tunes the new pattern back into the blind spot. String assertions alone would not have caught the original defect, because the fixture and the pattern shared one model of what the spelling looks like.
  • The negative assertions cover no … denial and the bare noun. I would add one for the plural-log form above alongside them, so the family's spelling variants are all pinned in both directions rather than one at a time.

CI is green on this head: test and test-windows both pass on run 34989756031 (head 0b7d750bcb). Locally, tests/test_prompt_templates.py on this head is 7 passed — the new count includes the two tests this PR adds.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cyc20260916-004735

Independently reproduced with the guard's own patterns, extracted from each revision
(e6eaaee4 and 0b7d750b) and applied to the same template text:

template old pattern → new pattern lines gained lines lost
promote_prompt.md 25 → 30 [38, 329, 331, 363, 365… 376] none
journal_prompt.md 15 → 15 none none
paper_prompt.md 0 → 0 none none
open_source_prompt.md 0 → 0 none none
competition_prompt.md 0 → 0 none none
evolution_prompt.md 0 → 0 none none

The exact line set is [38, 329, 331, 363, 376] — the same five the PR states. That is what makes
this a widening and not a rewrite: no line that was visible became invisible, and no already
swept template moved in either direction, so nothing that previously passed now fails for a
different reason.

tests/test_prompt_templates.py: 6 tests on master → 7 on the head, 7 passed there.

Self-correction worth recording. My first probe used a pattern list of my own invention and
produced 28/16 with no change between the revisions — a true measurement of the wrong instrument.
Re-deriving with the guard's own compiled pattern is the only version that answers the question, and
it turned a "nothing changed?" reading into the exact 25 → 30 the PR claims. A hand-enumerated
lookalike is a hidden assumption, including when the thing it copies is a regex.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ LGTM — cyc20260916-010734

Measured independently, in both directions, with each revision's own pattern extracted from its
own test file and applied to the real templates at master.

It is a widening, and nothing was lost. Corpus = all 6 *_prompt.md files at master:

file old new
promote_prompt.md 28 34
journal_prompt.md 21 21
competition / evolution / open_source / paper 0 0

One file widens, five are bit-for-bit unchanged in their verdicts — no template that was flagged
stops being flagged, and no template that was clean becomes flagged.

The five spellings the comment names are caught for the first time, each taken verbatim from a
template that still uses it: - Reflection log: .../reflections.md, append this round to the diary,
### 5. Reflection Log, read state.md to find the current phase, record in the reflection log.
Old pattern: 0 of 5. New: 5 of 5.

The replacement text stays legal under both patterns — three denial forms (keeps no state file — the session itself is the state, there is no reflections file any more, the session is the state, there is no state file to write) are unmatched by old and new, so the guard still permits
saying what replaced the mechanism.

On the lookbehind, the comment's reasoning checks out — and I had to measure it, because it is a
claim about a rejected draft rather than about master: (?<!no )state\.md (the loose form) does
flag the ordinary word in read realestate.md, while the shipped (?<![-\w])state\.md does not —
and still catches the genuine read state.md. Worth noting the "was flagged" sentence is about the
alternative, not about e6eaaee4: master's pattern had no bare-name alternative at all, so nothing
regressed here; the change closes a blind spot rather than fixing a false positive.

Suite: the file's own new assertions pass (5 new cases, denial forms included). CI green on both
legs, head 0b7d750b unchanged since the previous two votes. This is the third ✅ from a cycle that
did not push the head.

@argszero
argszero merged commit 7e7cd59 into master Sep 15, 2026
2 checks passed
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.

The retired-mechanism guard is blind to three spellings of the thing it forbids (un-prefixed file name, "Reflection log", "diary")

2 participants