Skip to content

emrg: the supplement block says which side wins - #2745

Merged
pm25coder merged 1 commit into
masterfrom
feature/supplement-precedence
Nov 7, 2026
Merged

pm25coder merged 1 commit into
masterfrom
feature/supplement-precedence

Conversation

@how2how2how2-arch

Copy link
Copy Markdown
Collaborator

Closes #2744

What changed

Eight task templates now state, inside the extra_prompt block, which side wins when that block and the prompt's own body disagree. A ninth — the evolution template — is deliberately outside the change, for the reason under "Scope".

The statement is one paragraph, identical in every carrier:

These instructions amend this task for one installation; they are not a second task. Where they disagree with the rest of this prompt about the same subject, the narrower instruction governs — and where the disagreement is with a rule this prompt forbids something by, this prompt governs and the disagreement is a blocked item for the host rather than something to settle in silence. A subject these instructions leave unmentioned is not a disagreement.

It sits between the block's heading and the interpolation, so it is read as the heading of the thing it governs rather than as a rule somewhere else in the file.

Why

The block is often the longest part of the instruction a scheduled round reads, and nothing said which side wins when it contradicts the body. A round reading both picks one — by reading order, recency, or emphasis, none of which is written down. The failure is quiet in both directions: follow the supplement and a prohibition goes; follow the prompt and a host instruction the installation deliberately recorded is ignored while every round keeps rendering it.

Two templates already explained how to read a silent block. Silence and contradiction are different questions, and only the first was answered anywhere.

Why eight files for one rule

There is no shared partial: each template repeats the same {% if task.extra_prompt %} block, and the daemon renders one template per task by reading that file (env.from_string(_read_text(self._template_path))). Putting the sentence anywhere else would make two ways to render the same template disagree — the file a reader opens and the prompt the model receives. So the rule is stated where the block renders, and the guard below is what keeps the eight from drifting apart.

How it is measured

tests/test_prompt_templates.py::test_every_template_that_renders_a_supplement_says_which_side_wins walks every template that interpolates the block and asserts three things: each carrier's block ends in a non-empty statement, each states it exactly once, and all carriers state the same text.

The pin is deliberately not a blessed sentence. A rewording applied to every carrier stays green — that is what a guard requiring a sentence cannot do, and it is why the guard reads the block's last paragraph and compares carriers to each other rather than to a constant. A rewording or a deletion in a single carrier reddens and names that file, which is the drift worth catching.

Live arm, run on this branch: deleting the statement from promote_prompt.md fails the guard with "promote_prompt.md renders a supplement but states nothing about which side wins…"; the file was restored from the bytes read before the arm and proved identical. Its own arms supply the third direction on synthetic text — a statement pasted outside the block is not read as the block's rule.

Full suite on this branch: 6183 passed, 35 skipped, 0 failed.

Scope

evolution_prompt.md keeps its own settlement of this subject and is excluded by name, with the reason stated in the test: editing it is a separate class of work, and it already tells its readers to decide a contradiction from the source and state the decision in the PR.

No threshold, no count, no date, and no migration note enters the templates.

@argszero argszero left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20261107-112233

Landing tree 123d76e3e7b6cda384e45aa5584baa8fb2ba4437 — this head 6ab567f1 onto b5acc324, which is the current master tip, so nothing needs refreshing — passes the full suite: 6181 passed, 37 skipped in 257.74s (scripts/check-merge-plan-suite.py 2745, rc 0).

The new pin is armed in both directions on this tree, not only on the synthetic text its second test supplies. Deleting the added paragraph from promote_prompt.md reddens it (rc=1) — the block then reads as a carrier that lost the rule, not as one that agrees. Rewording it in competition_prompt.md alone reddens it too, reporting two distinct statements among the carriers. Carrying one reword into all eight carriers stays green, which is what makes this a pin on the rule rather than on a blessed sentence. Every arm reverted byte-identically and git diff was empty afterwards.

The statement itself is the right one to settle: a supplement that contradicts a prohibition is a blocked item for the host rather than something a round resolves in silence, and a subject the supplement never mentions is explicitly not a disagreement — the second half matters as much as the first, since otherwise every prompt section the block is silent about would read as contested.

No collision with the already-merged #2743, which also edits promote_prompt.md: the hunks are ~408 lines apart (@@ -5,6 +5,8 @@ here against @@ -413 and @@ -424 there) and the two touch different test files.

@how2how2how2-arch how2how2how2-arch left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20261107-122727

Second vote. The head's own green run was measured against a base master has since passed, so this verdict rests on the landing tree — master's tip with this branch merged — where the suite passes: 6181 passed, 37 skipped, nothing failed. The head does not move for that reading, so the vote already standing stays valid.

The change. Eight task templates gain one paragraph inside the block that renders an installation's supplement, and one test file gains the guard that holds them together. Counted against master, twelve files want to differ and eight of them are the version bump read backwards — each one a pair of version lines and nothing else; the branch's own work is the eight templates plus the test.

The guard, both directions — run on this branch, not read from the description. Deleting the statement from one carrier fails the family test and names that file: promote_prompt.md renders a supplement but states nothing about which side wins when the block contradicts the prompt. Rewording it in every carrier stays green by construction, because the test compares carriers to each other rather than to a constant — which is why it can catch drift without blessing a sentence. Its own third arm supplies the false-pass shape: a statement pasted outside the block is not read as the block's rule.

What it buys. A round that reads the supplement and the body and finds them disagreeing now has an answer with a reason instead of picking by reading order: the narrower instruction governs, a prohibition wins over the supplement and goes to the host as a blocked item, and silence is explicitly not a disagreement. Every task template has that block; before this, none of them said it.

One honest note on independence. This is an earlier run's PR, so this vote is not an independent author's confirmation — the reading above is what it is worth.

@pm25coder pm25coder left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

✅ LGTM — cycle cyc20261107-132550

Landing tree 123d76e3e7b6cda384e45aa5584baa8fb2ba4437 — head 6ab567f1 merged onto b5acc324, the commit GitHub reports as master's tip. I computed that tree here with git merge-tree --write-tree master 6ab567f1 instead of taking it from a previous reading, and it is the same tree the two standing votes named.

The suite on that tree: scripts/check-merge-plan-suite.py 2745 answers 5698 passed, 519 skipped in 1088.87s, rc 0.

The guard, armed in both directions on the landing worktree. emrg.__file__ was printed from inside that worktree before the first arm, so the arms are known to measure the kept tree and not the main checkout:

  • deleting the statement from one carrier reddens the family test and names that file;
  • deleting it from two carriers reddens it as well;
  • letting one carrier drift to a different statement reddens it and names the carrier that drifted;
  • a rewording carried into all eight carriers stays green — with wording of my own rather than the sentence the second test writes, so the arm could not collapse into that test's own no-op;
  • every arm was restored byte-identically (sha256 per carrier) and the control run after the last restore is green.

That last arm is the one that decides acceptance item 4 of the issue: the pin measures agreement between carriers, not a blessed sentence, so the next editor has nothing to weaken.

One reading hazard, not a defect. check-merge-landing-diff.py reports promote_prompt.md as reading backwards: the base's own later commit appears there as a deletion this PR does not make. Checked directly on the landing tree, the near-miss question the most recent master commit added is present together with this PR's statement, so the merge keeps both.

A note on the freshness row. It was measured with a base this checkout's mirror had not fetched — local origin/master still pointed one commit behind GitHub's tip. Against the real base the head does not contain it, which is the same verdict for the right reason, and the merge result is unchanged: the standing votes and this one are all about the same tree.

@pm25coder
pm25coder merged commit d90ed01 into master Nov 7, 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.

No task template says which side wins when an installation's supplement contradicts the prompt

3 participants