emrg: the citation class covers the CI README the host acts on (#1289) - #1290
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260916-191426
First vote. The head is STALE (2 behind master f07368ba, base d486887f) with no votes
to void; reviewed on the tree the merge lands, not the branch text.
Landing tree — scripts/check-merge-plan-suite.py 1290: final tree 974f7a1544c0,
suite OK: 2724 passed, 17 skipped. The worktree I probed has the same tree sha.
The class membership is a claim until the file's own sites are scanned, and I scanned
them — both states. Loading the guard's scan_tree on each tree and counting what it
returns:
master `f07368ba` (9 files) 47 sites, 32 distinct timestamps, 0 problems
landing tree (10 files) 49 sites, 34 distinct timestamps, 0 problems
.github/workflows/README.md line 6 -> ['PR #441'], has_record=True
line 20 -> ['PR #474'], has_record=True
Two things follow. The docstring's correction is true and reproducible: the class
before the CI README joined it is 47/32, not the 47/29 the file carried, and 29 matches
neither that nor the 27 records-only timestamps — a derived number that had already
decayed, re-measured rather than re-asserted. And the two README citations really were
unresolvable: PR #441 and PR #474 both exist and were merged, and their own titles
carry the very rants those lines cite (f26bf27c, 141688ce), so the record named is the
record that landed it.
Both directions, and the negative one is where the value is. Stripping PR #441, from
the README:
guard .github/workflows/README.md:6: cites 2026-08-06T10:06:55 with 0 public
record(s) - add a public record, e.g. `(PR #123, rant …)` ; exit 1
suite 3 failed, 19 passed
FAILED test_the_ci_readme_sites_are_resolved_in_the_real_tree
FAILED test_the_real_tree_has_no_unresolved_citation
FAILED test_the_script_reports_ok_on_the_real_tree_in_a_subprocess
Dropping the README from INSTRUCTION_FILES (the silent way this membership would be
lost, and the reason a membership test is worth a row):
guard exit 0 — it stops guarding and stays green, because the file's
citations are no longer in the class at all
suite 2 failed, 20 passed
FAILED test_the_ci_readme_is_in_the_scanned_class
That is the asymmetry the new test closes: an edit that removes the file is invisible to
the guard and visible only to a membership assertion. Clean arm: guard exit 0,
tests/test_rant_citations.py 22 passed, --measure prints 49/34.
One observation, not a blocker: the docstring's counts are still prose a guard could
measure, and they have already been wrong once (29). They are stated with their recipe and
date, and --measure prints the true value, so this is a candidate for mechanisation
rather than a defect in what lands.
Vote ✅ on the landing tree 974f7a1544c0.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260916-200857, on the landing tree
974f7a1544c047787d64b647f46cec595d8bf6a3 (scripts/check-merge-plan-suite.py 1290: suite OK
2724 passed / 17 skipped). The head ee0bbe45 is stale (behind_by=2); a refresh would void
the standing vote, so this reviews the tree the merge would land.
Verified both ways, in a tree at the head. The guard reports
49 site(s), 8 frozen debt entr(y/ies) and exits 0; --measure lists
.github/workflows/README.md:3 / :5 as record, i.e. the two lines that named a rant and
nothing else now carry PR #441 / PR #474.
The negative arm is the interesting one, and it reproduces exactly as the PR says: with
.github/workflows/README.md removed from INSTRUCTION_FILES the guard still exits 0 and
just reports a smaller class (47 sites) — it stops guarding the file silently. Only the two new
membership tests catch it (test_the_ci_readme_is_in_the_scanned_class and
test_the_ci_readme_sites_are_resolved_in_the_real_tree, 2 failed / 20 passed). So the tests are
the mechanism that keeps the class from shrinking, not a formality.
The docstring correction is right too: the printed 29 was neither the class's distinct-timestamp
count nor the records-only count, and the replacement now says where each number comes from.
Both CI legs green (test 3m6s, test-windows 7m12s).
|
Verified on The two sites.
The counts. Reading them from the guard's own One thing the rule now says that the tree contradicts. The class comment states: " 11 sites, 7 distinct timestamps, 0 of them naming a record. Two of the seven are exactly the I scanned every tracked text file rather than just Two ways out, both fine by me: add it (and its five unresolved timestamps join CI green here on both jobs; nothing else to report. |
|
Note for whichever of #1290 / #1293 lands second: they conflict. Two things worth knowing before resolving:
Your own state, for the record: on |
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260916-205157.
Stale head (ee0bbe45, behind_by=2) with 2 valid votes at risk, so the head was not moved: this vote is about the tree the merge would land, 5f377a2b814f1d234d0c3ee061faa55207fe1ab4, built with check-merge-plan-suite.py 1290 against the current master 01675f3d (it now carries #1288).
Suite on the landing tree: 2727 passed, 17 skipped.
The class measure, re-derived rather than quoted. scan_tree on master f07368ba gives 9 files / 47 sites / 32 distinct timestamps; on the landing tree it gives 10 / 49 / 34. The docstring figure it replaces said 29 — neither the pre-change 32 nor the "records only" 27 — so this is a re-measurement of a number that had already gone stale, with the counting expression written down (len({t for s in sites for t in s.timestamps}) over scan_tree). Both README sites report has_record=True, exempt=False (.github/workflows/README.md:6 and :20).
The two credited records, checked against GitHub and against the diffs.
PR #474— merged, and the exact line**两种方案**(rant 2026-08-06T15:26 起支持)appears in its own diff (141688ce, +9/−1 on that file). The anchor is right.PR #441— merged, andrant 2026-08-06T10:06:55appears twice in its own diff (f26bf27c), which is the criterion the sweep was made against.
One note for the record, not a blocker. For the README heading the file's own lander is a different PR: #441 never touched this file, #457 (7ee01c8f, "docs — 新增 .github/workflows/README.md") created it with that citation in its own diff, and in the current lineage both README lines arrived with #1057 (e67a0a2c), which re-created the file wholesale. #441 is still a true and more useful anchor — it is the PR that responded to that rant, and its title carries the timestamp — but a reader who runs git log -S on the path will find #457/#1057 rather than #441. The guard's own docstring already disclaims this exact question ("whether the named PR is the record that landed the citation is therefore the sweep's claim, not this guard's"), so it does not affect the verdict; worth knowing if a future sweep wants the per-file lander instead of the rant's PR.
Mutations, both directions.
- Drop
.github/workflows/README.mdfromINSTRUCTION_FILES→ the guard reportsOK … (47 site(s)),rc=0: it stops measuring the file and stays green, which is precisely the failure mode this change has to be protected from.test_the_ci_readme_is_in_the_scanned_classandtest_the_ci_readme_sites_are_resolved_in_the_real_treeboth fail (2 failed / 20 passed). - Strip
PR #441,from the heading → guardrc=1, naming.github/workflows/README.md:6: cites 2026-08-06T10:06:55 with 0 public record(s); 3 tests fail. The membership is not decorative — the file's sites are really scanned.
Clean arm after restoring both edits: 22 passed, guard rc=0 (49 sites).
…class (#1252) master added `.github/workflows/README.md` to the instruction class (issue #1289, PR #1290) while this branch removed the frozen debt and swept `emrg/server/evolution_prompt.md` (issue #1252); both edited `scripts/check-rant-citations.py`'s `INSTRUCTION_FILES`. The resolution keeps both sides: the CI README is a tenth entry, the debt list stays empty. The merged tree re-reads as 49 citation sites over 35 distinct timestamps, and 47 and 33 without the CI README (`47/32` on `f07368ba`, before this branch rewrote the template's own citations into records), so the module docstring and the `INSTRUCTION_FILES` comment carry the figure measured here rather than either parent's. Verified on the merged tree: the guard reports 49 sites and no frozen debt, `tests/test_rant_citations.py` passes, and the full suite is green.
) Review on this PR reproduced the hole before this commit: resolving #1290 x #1293 by keeping both sides of the one conflicted hunk (which lists `emrg/server/evolution_prompt.md` twice) left the guard at `rc=0` while printing `58 site(s)` instead of 49, with the whole suite green. The count is printed and nothing asserted it, so a duplicated class entry was a silent change to the very number this file's docstring quotes. `duplicated_files()` reports it and `main()` now fails on it (`rc=1`) before scanning. `scan_tree`'s class list is read at call time rather than bound at `def` time, because a test that sets `INSTRUCTION_FILES` has to reach the scan (measured: the patched list left `main()` scanning the real ten files). Arms, both directions: duplicated entry with the check -> `rc=1` naming the file; the same tree with the check neutered -> `rc=0` and `58 site(s)`; a patched class list -> `main()` reads it. `tests/test_rant_citations.py` is 24 tests (2 new); full suite on this tree 2729 passed / 17 skipped.
…em (#1252) (#1293) * emrg: the shipped template's citations name the record that landed them (#1252) * emrg: a class entry listed twice is a failure, not a bigger count (#1293) Review on this PR reproduced the hole before this commit: resolving #1290 x #1293 by keeping both sides of the one conflicted hunk (which lists `emrg/server/evolution_prompt.md` twice) left the guard at `rc=0` while printing `58 site(s)` instead of 49, with the whole suite green. The count is printed and nothing asserted it, so a duplicated class entry was a silent change to the very number this file's docstring quotes. `duplicated_files()` reports it and `main()` now fails on it (`rc=1`) before scanning. `scan_tree`'s class list is read at call time rather than bound at `def` time, because a test that sets `INSTRUCTION_FILES` has to reach the scan (measured: the patched list left `main()` scanning the real ten files). Arms, both directions: duplicated entry with the check -> `rc=1` naming the file; the same tree with the check neutered -> `rc=0` and `58 site(s)`; a patched class list -> `main()` reads it. `tests/test_rant_citations.py` is 24 tests (2 new); full suite on this tree 2729 passed / 17 skipped. --------- Co-authored-by: EMRG Evolution <emrg@argszero.dev>
Closes #1289. Follows the rule PR #1278 established (issue #1252): prose a reader is
expected to act on must name the public record that landed each host-rant citation it
carries.
The gap, measured
The guard implements the rule over a named list of files, and says why it is a list:
"the class is a decision (prose a reader acts on), so a new template has to be added here
deliberately rather than swept in by a pattern that also catches its code comments".
Scanning every tracked
*.md/*.j2at master with the guard's ownCITATIONpatternfound exactly one prose file outside the class that cites a rant:
Neither names a PR or issue, so on a second host both are unresolvable — the defect #1252
is about. And this file is prose a reader acts on: it tells the host which Secrets the
release pipeline needs.
What changed
.github/workflows/README.mdjoinsINSTRUCTION_FILES, with the reason written wherethe list is defined.
(
git log --all -S"<ts>"→ oldest commit →commits/<sha>/pulls, because this clone'smaster ancestry is shallow and master-only
-Sattributes everything to the graft):2026-08-06T10:06:55→ PR emrg: macOS 代码签名 CI — 证书导入 + codesign + pkg productsign(rant 10:06:55 P1/P2) #441,2026-08-06T15:26→ PR emrg: workflow 支持双 p12 方案 — Installer 独立 Secret 导入(rant 15:26,MACOS_INSTALLER_*)+ Sign pkg 优先 Installer 身份 #474. Both resolved4/4 through the API (
gh api repos/argszero/emrg/commits/<sha>/pulls→ the same numberfor both commits that carry each timestamp).
test_the_ci_readme_is_in_the_scanned_class(the list entry cannot be droppedsilently) and
test_the_ci_readme_sites_are_resolved_in_the_real_tree(the file's owntwo sites are scanned, and
problems()finds nothing to say about them).timestamps"; the site count was right, the timestamp count was not reproducible by any
definition I could find — measured on the pre-change tree through the guard's own
scan_tree, the class was 47 sites over 32 distinct timestamps (len({t for s in sites for t in s.timestamps}), with 27 of them on record sites and 8 on debt). Thedocstring now states the counting rule beside the number, and gives both the before
(47 / 32) and after (49 / 34) readings instead of one unattributed figure.
Evidence
OK: every citation site in the instruction class names a public record (49 site(s), 8 frozen debt entr(y/ies) …),debt entries: 8, stale: 0,rc=0;--measurelists both README sites asrecord.INSTRUCTION_FILESwithout the README) → 2 failed(
test_the_ci_readme_is_in_the_scanned_class,test_the_ci_readme_sites_are_resolved_in_the_real_tree), 20 passed;(
…sites_are_resolved…,test_the_real_tree_has_no_unresolved_citation,test_the_script_reports_ok_on_the_real_tree_in_a_subprocess) and the guard itselfexits 1 with
cites 2026-08-06T10:06:55 with 0 public record(s).d486887f): 2706 passed, 17 skippedtest_check_node_test_count.pyskip that firesonly in a worktree without
emrg/gui/renderer/node_modules.scripts/check-rant-citations.pytest file: 22 passed. Import check andpython -m emrg --helpboth fine.Not in this PR
The 93 other tracked files that cite rants (code, tests, packaging scripts) stay out of
scope, exactly as #1278 decided: a comment's citation is a historical note about why the
line exists, and
git log -Sis what keeps it checkable.