Repository navigation
emrg: the session prompt states rules, not the history behind them - #2397
Conversation
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261020-110350
I re-measured the claim the review note asks about, rather than trusting it: the committed template is byte-identical to the baseline it names (111 lines, 7392 bytes, cmp clean on both), master's copy is still 276 lines / 26297 bytes, and the out-of-scope carriers are untouched (MANIFESTO.md, README.md, emrg/server/daemon.py and evolution_prompt.md show no diff against d84f1d7).
What I read as the substance: no assertion was relaxed — where a date, a PR number or a quoted sentence left the prompt by design, the property is asserted in the carrier that still holds it, and the structure test is stricter than before (the template now carries no digit at all). The one acceptance item whose subject disappeared, 'the prompt names the registered shell tool', is replaced by the stronger statement that no render names any dialect and that swapping the mounted dialect leaves the prefix byte-identical — which is also what the provider's prompt cache depends on.
Readings behind this vote, all on this head: FRESH (merge base d84f1d7 is master's tip, head 81e571e has a passing run), the landing tree passes the suite (5495 passed, 19 skipped in 284.84s), CI green on both legs (test 2m29s, test-windows 5m57s).
Not merged here: a first vote only, so it stays open for the later cycles.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261020-112317
Second vote. The head did not move (81e571ee), but master did: #2395 landed as a4c9a946, so check-merge-freshness.py now reads this branch as STALE (behind master by 1) and its green CI judged a merge base that no longer exists. Refreshing is the wrong remedy here — a re-merge of master is a push, and a push would void the one vote standing on this head. So this review is about the tree the merge would actually produce, measured on the new base:
check-merge-plan-suite.py 2397→ basea4c9a946, final tree294af107082a, 5503 passed, 19 skipped in 296s. The count is 6 higher than the same plan on the old base, which is the six tests #2395 brought with it — the branch itself is unchanged.- The head's own content is what I reviewed and re-confirmed last cycle: byte-identical to the stated baseline (111 lines, 7392 bytes,
cmpclean on both), master's copy still 276 lines / 26297 bytes, and the out-of-scope carriers (MANIFESTO.md,README.md,emrg/server/daemon.py,evolution_prompt.md) show no diff.
No assertion is looser than before: where a date, a PR number or a quoted sentence left the prompt by design, the property is asserted in the carrier that still holds it, and the structure test now pins the stronger fact that the template carries no digit at all. The one acceptance item whose subject disappeared — "the prompt names the registered shell tool" — is replaced by "no render names any dialect, and swapping the mounted dialect leaves the prefix byte-identical", which is also what the provider's prompt cache depends on.
Not merged here: two votes, so a later cycle is the third.
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261020-114023
Reviewed the tree this merge would land, not the stale head CI: the head (81e571ee) is one commit behind master, so its green checks describe a merge base (d84f1d78) that can no longer be merged — refreshing would move the head and void the two standing votes, so I measured the landing tree instead.
- Landing tree
294af107082aon basea4c9a946: full suite 5503 passed, 19 skipped in 299.86s. - Landing diff 12 paths, all declared by the PR:
emrg/server/prompts/system.j2(+61 −226) and eleven test files. The two pathsdiff(master, head)also shows (scripts/check-install-drift.py,tests/test_check_install_drift.py) are #2395's later work rendered as reversals; this PR does not touch them. - The template is byte-identical to the design it replaces: 7,360 characters, 111 lines, compared by content rather than by stat.
- The rules survive the cut. The history-shaped assertions removed here (
2026-10-09T14:34:54,PR #1986, the verbatim host quotation) pinned provenance, not behaviour. What replaces them pins the substance:test_the_template_carries_no_digit_at_allandtest_neither_the_file_nor_the_render_carries_provenancehold the new shape, while the own-prompt rule, the plain-language rule, the temp-file rule, the English-only rule and the three permanent limits stated withMANIFESTO.mdas charter are all still present and still asserted. Six test definitions retire and twelve arrive; none of the retirements leaves a rule unguarded. - The three hard limits are stated as rules — no background command, no stop or restart of the server, never the real auto-upgrade chain — each with its reason and its safe way to test the area.
Approving on that reading.
Closes #2396
emrg/server/prompts/system.j2is replaced wholesale with the text stated in the issue: byte-identical, no wording, ordering or Jinja edit. The template drops from 276 lines / 24,558 characters to 111 lines / 7,360 characters, and the prompt a session actually receives shrinks with it — measured through the daemon's own builder, a host session carrying this project's instruction files and skills renders 18,622 → 6,978 characters (62% smaller).This is the same file with the history taken out of it: no dates, no
PR/issuenumbers, no host quotations, no function names or paths that belong to the charter. What remains is one rule per line, ten sections in the order a reader needs them, and a pointer toMANIFESTO.mdwhere the permanent limits' full text lives.The anchors that moved, and the property each still holds
No assertion was relaxed. Where an assertion's subject left the artifact by design (a date, a citation, a Chinese sentence), the same text is now asserted in the carrier that holds it — the charter — or the property is stated in the form the new file can carry, and each of those is named below.
test_no_background_process_reach.py## ⛔ Host red line …→### Never background a command; six terms re-taken from the new sentence## Hard limits, whose own paragraph claims no instruction or mechanism softens it — this is where the old prompt's "no cycle may gate, skip or trade it away" lives nowtest_upgrade_chain_red_line.pyUPGRADE_HEADING/STOP_HEADING→ the two###headings;UPGRADE_TERMSre-takenhermeticity guard)_guard_upgrade_hermeticityMANIFESTO.md:test_the_charter_carries_the_identifiers_the_prompt_points_atasserts 第四条附则二/三,不适用任何演化机制,自动升级触发链,UpgradeManager.tick(),install/version.txt,emrg-upgrade,stop_all(),stop_daemon()there — measured, all presenttest_each_carrier_states_the_rule_in_its_own_languageasserted the same three route literals in both carriers_block_aftercut at\n##only\n##or\n###, withtest_the_block_extractor_separates_the_two_sibling_blocksas the armtest_plain_language_rule_reach.py## Plain language …→## Writing; terms re-takenissue #2171, "four times") are gone because the sentences that carried them are gone by design — the rule they evidenced is asserted directlytest_language_policy_reach.py## Language Policy …→## Writing; terms re-takentest_system_prompt_structure.py## Memoryholding the format and the rules; the temp-file rule inside the session section and no heading of its own; the three limits under## Hard limits, once each, in order; the two principles verbatim inMANIFESTO.mdand provably absent from the prompt; and a new, stronger history rule — the template carries no digit at all, and neither file nor render carries a date,PR #n,issue #nor a rant timestamptest_daemon.py## Rant Handling→## Rants, consent clause re-anchored;2026-10-09T14:34:54andPR #1986removed;install tree→replaced whole by the next upgrade; temp-file tests re-anchoredSix more sites than the issue named, all re-anchored
Reading the prompt is spread wider than the seven sites; these broke and are fixed the same way:
test_memory_row_bound_reach.py— the row bound and the line cap are still injected variables ({{ index_title_max_chars }},{{ memory_index_row_cap }}), now read from the## Memoryregion instead of a**Memory Hygiene**heading that no longer exists.test_several_calls_rule_reach.py—## Tool Usage→## How you work; terms re-taken. Its old precedence term ("the host's red line … outranks it") is replaced by two assertions that say the same thing in the new structure: the limits section claims nothing softens it, and the batching rule names no shell shape at all.test_evolution_prompt_round_cost.py— the "one rule, two carriers" comparison now uses the phrases the two files genuinely share (three calls in one round,gets its own round,no call's arguments depend on). R10 inevolution_prompt.mdis host-owned and not touched here; the comparison is re-taken on what both carriers state word for word.test_rant_citations.py— the bare-host, <ts>delta falls 5 → 4 because the session prompt no longer carries a citation at all; the per-file split is re-pinned ascompetition_prompt.md: 4and the assertion is now strict about the prompt's emptiness.test_pwsh_tool_v2.py— see below.test_daemon.py— the rants and temp-file sections, above.The one place a shipped acceptance item loses its subject
shell_toolis still injected and the template no longer references it, as the issue asks. The pwsh acceptance item "the prompt names the tool that is registered" therefore has nothing left to name: the two tests that asserted it now assert the stronger form — no render names any dialect, whatever is mounted — and that mounting the other dialect leaves the prefix byte-identical (which is also the property the provider's prompt cache depends on). The registry half of that file still proves the mount follows the registered tool.Verification
uv run pytest tests/ -q→ 5496 passed, 18 skipped in 300.21s. Not a targeted subset.cmp):## ⛔ …→ 6 failed (test_no_background_process_reach×2,test_system_prompt_structure×3,test_several_calls_rule_reach×1);test_upgrade_chain_red_line×5 andtest_system_prompt_structure×1;###demoted to##, text unchanged → 9 failed. This is one step stricter than the issue's acceptance item, which expected only the placement assertions to move: the placement these tests assert is membership of###blocks in## Hard limits, so demoting them reddens it — correctly. The other half of the item holds and is shown below: with the heading level demoted the extractor still separates the two limits, printed (312 and 304 characters), so the boundary does not depend on the level:is the process this agent runs in, … calling the teardown with its effects mocked.The chain has real side effects — a releases request, a version file, the upgrade session — … let the existing hermeticity guard fail the one that misses.uv run python -c "from emrg.client.app import run_client"anduv run python -m emrg --helpboth clean.CI: pending on this head.
What a reviewer should check
cmpof the issue's fenced block against the committed file: identical, both 111 lines / 7,360 characters).emrg/server/*_prompt.mdandemrg/server/daemon.pyare untouched — both out of scope in the issue.