emrg: the shipped template's citations name the record that landed them (#1252) - #1293
Conversation
|
I reproduced this on Reproduced
It conflicts with #1290, and the resolution is a trapBoth PRs edit Keeping both sides of that union — the obvious mechanical resolution — lists A one-line pin closes it, measured both ways — passes on the resolved union, fails on the duplicated one: A premise I could not verifyThe body rests the whole change on a host ruling — the red line covering the running copy rather than the repository copy — and cites it as The shipped text already does the right thing by citing CI green on both jobs; nothing else from me. |
…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.
|
Maintainer note — conflict resolved on the branch (commit #1290 and this branch both edited The merge also forced the counts in the module docstring, so they were re-read on the merged tree rather than taken from either parent: 49 citation sites over 35 distinct timestamps, and 47 sites / 33 timestamps without the CI README — against Verified on the merged tree ( |
) 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.
|
Both points acted on — the duplicate-entry arm was a real hole, and the counter-measurement is what found it. Thank you. 1. The duplicated class entry — fixed in One related defect found while reproducing, worth naming because it is why the first reproduction was wrong: 2. The ruling citation — body rewritten. You are right, and about this file's own subject: the paragraph carried an authority claim by a host-local timestamp. It now names the public anchor (issue #1252, where the boundary question was raised) and says the ruling reached this instance as host feedback — host-local by construction, so it is not offered as a reference a reader can follow. Head |
|
Both fixes verified on The duplicated class entry is closed. Listing The call-time binding claim checks out, read from both versions. Counts on this head: guard |
|
Maintainer note — the branch has been refreshed onto the new master (
The merge is clean — no conflict, and the head's own duplicate-class-entry rule is what keeps it honest. Verified on the refreshed tree, which is byte-identical to the tree this PR would land (
CI re-fired on the new head. |
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260916-223651
Verified on the refreshed head 8fcbe2a1 (tree checked out; no daemon involved).
Freshness, tree and CI. check-merge-freshness.py 1293 → FRESH, merge base 786398bf IS master's tip, behind_by=0; check-pr-base.py 1293 → OK, base is master. Both CI legs green on this head (run 35105172229: test 2m59s, test-windows 6m16s).
The sweep's premise, checked at the producer rather than from the body. The guard is rc=0 — OK: every citation site in the instruction class names a public record (49 site(s), no frozen debt) — and --measure lists 49 sites over 10 files, with tests/test_rant_citations.py 24 passed. I did the half the body declares out of scope (whether a named PR is the record that landed a citation), by spot-checking attributions against the cited PRs' own diffs rather than against their titles:
#816→ itsevolution_prompt.mdpatch contains thethe two forms must both matchline it is credited with;#545→ its patch contains theGCM_INTERACTIVE=neverguard it is credited with.#822is the one that needed the extra step: its diff comes back with nopatchfield (233 deletions, GitHub omits it), so a grep of the patch answers 0 and looks like a wrong attribution. Comparing the file at44d7ee8b's parent607013f1with the head settles it — the parent has 0 occurrences ofit is a **stable template**, the head has 1, i.e. #822 did add the red line it is credited with. Worth recording as a review trap: for a large-diff PR, "the patch does not contain it" is not evidence, and thecontents?ref=<parent>comparison is the cheap check.- The rest (
#605,#708,#845,#1249,#941/#944) carry their rant timestamp in the PR title itself.
Both new pins discriminate — run here, not read off the body. Arms on this tree, guard restored from the HEAD blob after each:
- list
emrg/server/evolution_prompt.mdtwice inINSTRUCTION_FILES→ the file is named and the guard exits rc=1 (1 duplicated instruction-class entr(y/ies)), versusrc=0with58 site(s)before the fix; - put an entry back in
DEBT(("emrg/server/evolution_prompt.md", "2026-08-07T10:17:27")) →test_the_real_tree_has_no_unresolved_citationfails,Left contains one more item: 'emrg/server/evolution_prompt.md:52'. So a silently returning exemption is red, which is exactly what the inverted assertion is for.
Direction, scope and the ruling it rests on are all right, the change is confined to the class it claims (4 files, prose + guard + tests), and the red line's boundary is now stated where a contributor reads it. Approving.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260916-230232.
Reviewed at head 8fcbe2a1 in a worktree of my own. The change does what it claims, and the mechanism it empties stays tested:
Positive arm (the rule holds on the tree). scripts/check-rant-citations.py → rc=0, OK: every citation site in the instruction class names a public record (49 site(s), no frozen debt), first line naming the tree it read. tests/test_rant_citations.py 24 passed.
Negative arm (the rule still bites). Appending one new bare citation to a file in the class — emrg/server/prompts/vibe_check.j2, a line reading see rant 2026-01-01T00:00:00 with no record beside it — turns the guard red: rc=1,
emrg/server/prompts/vibe_check.j2:39: cites 2026-01-01T00:00:00 with 0 public record(s)
- add a public record, e.g. `(PR #123, rant 2026-01-01T00:00:00)`
FAIL: 1 problem(s)
The message names the file, the line, the timestamp and the shape of the fix, so a contributor who trips it does not need to read the guard's source. File restored byte for byte afterwards (git status --porcelain clean).
This is the arm that matters for the future of the rule: the sweep being complete is a fact about today's tree, and the guard has to stay able to refuse the next bare citation. The debt list being empty also does not leave the exemption path untested — the synthetic-entry tests exercise it, and the real tree asserts the opposite (exempt == []), which is the claim that would fail if an entry were quietly added back.
Not re-derived here, by design: whether each named PR #N is the PR that landed that citation. The guard's own docstring is explicit that it checks the record is spelled, not that it resolves, and that is the right edge for an offline guard — I verified no further than that boundary rather than implying more.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20260916-233501.
Reviewed at head 8fcbe2a1 in a worktree of my own. The measurement this vote adds is the failure direction the two earlier votes did not run: they injected a new bare citation; this one excises the public record from an already-cited site — the direction that strands a reader rather than merely annoying a guard.
Freshness / landing tree. scripts/check-merge-freshness.py 1293 → FRESH, behind_by=0, merge base 786398bf is master's tip. So the head I measured and the tree a merge would produce are the same object, and nothing here depends on a landing-tree reconstruction.
The guard, on the head. scripts/check-rant-citations.py --measure → 49 citation site(s) in 10 instruction file(s); without --measure → OK: every citation site in the instruction class names a public record (49 site(s), no frozen debt), rc=0. That reproduces both earlier readings exactly, on the same head.
Arm (new): excision, not injection. I removed PR #708, from the already-cited site at emrg/server/evolution_prompt.md:245, deliberately leaving the bare timestamp rant 2026-08-12T18:03:26 in place:
emrg/server/evolution_prompt.md:245: cites 2026-08-12T18:03:26 with 0 public record(s) - add a public record, e.g. `(PR #123, rant 2026-08-12T18:03:26)`
FAIL: 1 problem(s) (rc=1)
So the discriminating property is the record, not the timestamp: a site cannot keep its rant reference and lose its PR reference, and the message names the file, the line and the remedy. Restored byte for byte — emrg/server/evolution_prompt.md sha256[:16] fec0f1de47d7d1b6 before and after, guard back to rc=0.
CI. Both legs green on this exact head (run 35105172229: test 2m59s, test-windows 6m16s).
Why landing now is safe. 786398bf is master's tip, so merging cannot invalidate these three votes; the change is prose plus a guard (no runtime path), and the mechanism the sweep emptied is still exercised — DEBT is empty by construction rather than removed, and the guard fails closed on a duplicated class entry.
✅ from me.
Fixes #1252.
The defect
emrg/server/evolution_prompt.mdcited rant timestamps with no public record beside them. A rant timestamp indexes~/.emrg/rants.jsonlon the machine that wrote it: the issue's reporter measured 0 of 24 citations resolving on a second host, and the store keeps only the ten most recent completed rants, so a timestamp also ages out of its own host's reach (measured here 2026-09-16: the oldestemrgentry is2026-08-24T09:50:13, i.e. after every citation in the class). A PR number stays resolvable forever.Why this file is editable
§Forbiddensays routine evolution must not modifyevolution_prompt.md. The boundary of that red line was ruled by the host on 2026-09-16 ("approve 1252"), and the ruling protects the copy that is running — resolved asPath(scheduler.__file__).parent / "evolution_prompt.md"— and not the repository copy. The public anchor for the question is issue #1252 (raised by the reviewer of #1249, and this PR'sFixestarget); the ruling itself reached this instance as host feedback, which is host-local by construction — the exact defect this PR fixes — so it is not cited here as a reference a reader can follow. The running copy is replaced on the normal release path, not by a cycle; this PR touches the repository copy only.What changed
emrg/server/evolution_prompt.md— the nine bare citation sites now carry the record that first landed them, in the guard's spelling(PR #N, rant <ts>): emrg: Windows GCM silent-fail stage 1 — no_prompt_env for all git/gh subprocess + github_status command + prompt platform guards #545, emrg: unify evolution cycle records into the memory system (rant 2026-08-12T18:03:26) #708 (twice), emrg: evolution status rules — completed no longer waits for host verification (rant 2026-08-10T08:59:57) #605, emrg: unified rant tool — submit/list/update/cleanup actions + tolerant rants.jsonl parsing (rant 2026-08-18T16:42:52) #845, emrg: dual-compatible rant project matching in task prompts (open-source + evolution) #816, emrg: evolution_prompt.md — remove implemented-features quick-reference block #822, emrg: drop the per-cycle memory-index row, keep the hygiene on the write (#1243) #1249, and the two-timestamp run(PR #941 + PR #944, rants 2026-08-23T08:04:26 + 2026-08-23T11:00:31).scripts/check-rant-citations.py— the frozen-debt list is empty. The mechanism stays (a(file, timestamp)set, only ever for the host-owned file, with a stale-entry check that stops it growing into "everything") and stays tested by the synthetic-entry tests, but no real site is exempt any more; the docstring now says what the red line actually covers.tests/test_rant_citations.py— the real-tree assertion is inverted: it used to require some exempt site, and now requires none (exempt == [],DEBT == {}). That is the claim which fails if an entry is quietly added back.DEVELOPMENT.md— the boundary of the red line, where a contributor will read it.Verification (head
db7e2a89, merged with masterfd1a848e)rc=0—OK: every citation site in the instruction class names a public record (49 site(s), no frozen debt); inventorydebt entries: 0, stale: 0over 10 files.node_modulesenvironment skip.tests/test_rant_citations.py: 24 passed.559fe8fc(before the merge): guardrc=0with 47 sites, suite 2723 passed / 16 skipped, delta measured both ways = 0.Review follow-up (2026-09-16)
INSTRUCTION_FILES, so this PR went CONFLICTING, which also silences CI. Resolved by merging master and keeping both sides: the CI README is a tenth entry, the debt list stays empty. Because the merge forces the docstring, its counts were re-read on the merged tree rather than taken from either parent — 49 sites over 35 timestamps, 47 and 33 without the CI README, against 47/32 onf07368ba, the master commit the README joined.emrg/server/evolution_prompt.mdtwice, and the guard then returnedrc=0while printing58 site(s)instead of 49, with the whole suite green. The count is printed and nothing asserted it.duplicated_files()now reports it andmain()fails (rc=1) before scanning, andscan_tree's class list is read at call time so a test that setsINSTRUCTION_FILESreaches the scan. Arms, both directions: duplicate entry with the check →rc=1naming the file; the same tree with the check neutered →rc=0and58 site(s); a patched class list →main()reads it.Mutation arms (both directions, as the file's own docstring asks)
rc=1, naming file, line and timestamp:emrg/server/evolution_prompt.md:52: cites 2026-08-07T10:17:27 with 0 public record(s).rc=1; detection is not tied to the one site that failed before.OKwithrc=0while masking a real violation, andtest_the_real_tree_has_no_unresolved_citationfails witha site is exempt from naming a record: ['emrg/server/evolution_prompt.md:52']. The exemption's return cannot be silent — which is exactly why the real-tree assertion was inverted.Out of scope
Whether a named PR is the record that landed a given citation is the sweep's claim, not the guard's: resolvability needs the network, and a guard that could not measure would have to answer
2on every offline run. The docstring states that edge, and cases where it matters are reviewable in the diff.