From cc82e57267c786c5c26536553bf25ce5996d53fa Mon Sep 17 00:00:00 2001 From: EMRG Evolution Date: Fri, 23 Oct 2026 18:04:04 +0800 Subject: [PATCH] emrg: the cycle id names a run, not a file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A cycle was minting one cycle-.md per run into .emrg/memory/ — 45 files, 380 KB, 37 of them written in a single day — and nothing reads them: the readers went in #2476, no MEMORY.md row links one, and the same deletion removed the only instrument that noticed the files. So the loop kept believing it owed one, and grew one more, every cycle, invisibly. Section 4 gave it the belief: it told the cycle to write where "a later cycle can find the record by cycle id" and handed it "The record's `id`: `cyc{{ timestamp }}`". The id is real and load-bearing — vote bodies are attributed by it — but it names a run, not a file. Section 4 now says so, and still tells the cycle to write what it found, what it changed, how it was verified and what it expects. Section 1.3's meta-review read "the last 3-5 cycle records in memory", a corpus that stops existing once the loop stops writing it. It now reads the memory index already embedded in the prompt, which section 1.5 already rules out re-reading as a file. The guard that pulls the cycle id out of the rendered prompt to check the instructed vote examples against it anchored on the old wording. It is re-anchored on the new declaration and renamed to what it reads — CYCLE_ID, _declared_cycle_id — because there is no record's id to name. It is anchored on the declaration rather than on a bare `cyc…` token on purpose: the vote examples are cycle ids too and precede it, so a token scan would check the examples against themselves. --- emrg/server/evolution_prompt.md | 4 ++-- tests/test_evolution_prompt_vote_body.py | 18 +++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/emrg/server/evolution_prompt.md b/emrg/server/evolution_prompt.md index 3453cf79..913107b5 100644 --- a/emrg/server/evolution_prompt.md +++ b/emrg/server/evolution_prompt.md @@ -112,7 +112,7 @@ For each: **merged** → confirm master is healthy after it, with no regression; #### 1.3 Your own records and the rant queue -Read the last 3–5 cycle records in memory and look for: the same trivial change made repeatedly (batch it), the same feature fixed over and over (refactor it), a change that had no lasting effect, or consecutive "nothing to evolve" cycles while rants are non-empty (re-check — that is a contradiction, not a state). Then read the rant queue with `submit_rant(action="list")` — the tool is the only way it is read (R6). +Read the memory index already embedded in this prompt (§1.5 rules out re-reading it as a file) and look for: the same trivial change made repeatedly (batch it), the same feature fixed over and over (refactor it), a change that had no lasting effect, or consecutive "nothing to evolve" cycles while rants are non-empty (re-check — that is a contradiction, not a state). Then read the rant queue with `submit_rant(action="list")` — the tool is the only way it is read (R6). #### 1.4 master @@ -312,7 +312,7 @@ gh issue comment "$ISSUE" -R {{ owner }}/{{ repo }} --body "Handled by #cyc\d{8}-\d{6})`") +#: The id the same render tells the cycle to name this run by (§4 Record). Anchored on the +#: declaration rather than on a bare ``cyc…`` token: the vote examples below are cycle ids +#: too, and they come before it in the file, so a token scan would read an example as the +#: declaration and check the examples against themselves. +CYCLE_ID = re.compile(r"The cycle id — `(?Pcyc\d{8}-\d{6})` —") def _load_counter(): @@ -119,11 +122,12 @@ def _instructed_examples(text: str) -> list[str]: return [m.group("body") for region in regions for m in VOTE_EXAMPLE.finditer(region)] -def _record_id(text: str) -> str: - match = RECORD_ID.search(text) +def _declared_cycle_id(text: str) -> str: + match = CYCLE_ID.search(text) assert match is not None, ( - "the rendered prompt no longer states the cycle record's id (``id``: ``cyc…``) — " - "without it the examples below have nothing to be checked against" + "the rendered prompt no longer declares this run's cycle id " + "(``The cycle id — `cyc…` —``) — without it the examples below have nothing to be " + "checked against" ) return match.group("id") @@ -132,7 +136,7 @@ def test_the_instructed_vote_examples_name_exactly_one_cycle_id(rendered, counte """Each example body attributes the vote to exactly one cycle — this cycle.""" examples = _instructed_examples(rendered) assert len(examples) == 3, f"expected 3 instructed examples, found {len(examples)}" - cycle_id = _record_id(rendered) + cycle_id = _declared_cycle_id(rendered) for body in examples: ids = counter.distinct_cycle_ids(body) assert ids == [cycle_id], (