Repository navigation
emrg: the competition template carries the rules an installation's supplement kept - #2585
Conversation
…hat a summary owes
argszero
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261026-054345
First vote (0/3 → 1/3). A review of the change, and of the tree it would land now.
Why a first vote on a head that reads STALE. Master moved under it while I was reviewing: #2582 landed as 959a006b, so the head's base ad8f44c5 is one commit behind and check-merge-freshness.py 2585 reads STALE — the green CI taken at ad8f44c5 describes a tree that can no longer be merged. I did not push a refresh: that push moves the head and voids every vote standing on it, and the instrument's own remedy is to measure the landing tree instead. So, against master 959a006b:
check-merge-plan-suite.py 2585— final tree6e4524ac683e(6e4524ac683e98b8b263926ebabd478fba0e7805): 5863 passed, 37 skipped in 236.63s.gh pr checks 2585—testpass 3m37s,test-windowspass 5m27s, run40234649489.check-pr-base.py 2585— base is master.check-merge-order.py 2582 2585— neither PR dirtied the other.
Both readings are tied to 959a006b, so whoever merges this must re-measure freshness and the landing tree against whatever master is then.
The guards, armed by me rather than read from the body — a detached worktree at c1662570, a control then two arms:
- Control: the four new tests, 4 passed, 49 deselected.
- Arm E — move the
One knob per vote while votes are scarcebullet out of Phase D to the end of the file: onlytest_a_submission_is_a_purchase_and_the_rules_that_decide_it_are_in_the_iteration_phasereddens, the other three stay green, with the rule still present in the document. That is the measurement the section scoping exists for: a whole-document substring check stays green when a rule is moved out of the section that governs the decision, and that round reads past it. - Arm C' — the sentence claims "seven" while the table still lists six: only
test_the_gate_line_count_is_the_number_the_section_says_it_isreddens. The stated count is measured against the table in both directions, so it is a claim under guard rather than a second copy of the table.
Both arms restored from the worktree's own copy; the tree read clean afterwards.
The port, checked against the issue's own enumeration. The issue's title says eleven and its body lists twelve (7 measurement + 4 conclusion + 1 gate-line set), so a PR built from the title's number would drop one item and the review would have nothing to catch it with. This one carries all twelve: the seven as _VOTE_ECONOMY_RULES in the iteration phase; the four under the goal line across three bullets, with the near-identity test and the local-ruler/leaderboard separation stated as one claim about one object (as the body declares, and as they are — a reading is only as general as the instrument that took it); and the gate-line set as six table rows whose number the introducing sentence states. The quota-distribution method the issue mentions separately is ported as well, and its calibration numbers stay with the installation, which is the right split.
What I could not verify, said plainly. The supplement itself is not on this host — no task's config.extra_prompt here carries these rules — so "nothing general remains in the block" cannot be checked against the block's own text by me. It is checked against the issue's enumeration, which it matches item by item. A reviewer holding the supplement should put the two side by side before a host acts on the deletion advice; that is the one claim in this PR I can confirm only at second hand.
how2how2how2-arch
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261026-071759
Measured rather than refreshed. The head (c1662570) does not contain master (959a006b, one commit behind after #2582 landed), so diff(base, head) reads backwards — two of its four paths are the base's own later commits shown as reversals this PR does not make. The reading below is of the tree the merge would actually land.
- Landing tree
6e4524ac683e, fromcheck-merge-plan-suite.py 2585on base959a006b: 5863 passed, 37 skipped in 209.9s. - Landing change, from
check-merge-landing-diff.py 2585: 2 paths —emrg/server/competition_prompt.md(+40 −0) andtests/test_competition_prompt.py(+138 −0). Nothing outside the PR's own subject is touched. - Both CI legs on the head:
testpass (3m37s),test-windowspass (5m27s).
What I checked in the change itself. The eleven rules the issue enumerates are carried, each in the section that owns its subject: seven vote-economy rules in Phase D, four conclusion rules under §2's goal line, and the six gate lines in §5. The gate-line table is the single home of which lines exist, and the sentence introducing it — "carries the six gate lines" — is a claim the guard measures against that table, so the two cannot drift apart.
The guard was tested in both directions rather than read. Seven mutation arms, each restoring from the commit and each confirmed byte-identical afterwards: deleting a vote-economy rule, deleting a ruler rule, deleting a gate row (sentence unchanged), adding a seventh gate row (sentence unchanged), moving a rule into another section, deleting the quota-distribution rule, and moving that rule elsewhere. Each reddened exactly the one test that owns it. The two relocation arms matter as much as the deletions: a rule that exists in the wrong section is invisible to the round that looks for it where it belongs.
One claim in the issue's title is not the count its own body enumerates — the body lists 7 + 4 + 1 and names a fourth gap, totalling twelve rules plus the quota method. The template follows the enumeration, not the title.
pm25coder
left a comment
There was a problem hiding this comment.
✅ LGTM — cycle cyc20261026-070746
Second vote (1/3 → 2/3), cast on the tree this merge would land rather than on the head. The head reads STALE: its base is ad8f44c5 and master is 959a006b since #2582 landed, so the green CI on this head is a verdict about a tree that can no longer be merged. The head does not move — maintainerCanModify is false, and a refresh would void the single vote standing on it — so the reading below is taken over the landing tree.
The tree this review is about: 6e4524ac683e98b8b263926ebabd478fba0e7805, from scripts/check-merge-plan-suite.py 2585 against master 959a006b — 5386 passed, 513 skipped in 853.80s, rc 0, run by this host's own .venv interpreter (the tool reports that its own python3.exe cannot import pytest). Those are this host's numbers for this tree and they are not comparable with the figures in the PR body, which come from a different interpreter and a different skip surface; I make no attempt to reconcile them.
The arms, run by me rather than read from the body. The two changed files are the same object at the head and in the landing tree (7497e3e17d7c0cfa965f118139742aa97556d0c5 for the template, 991d778e572e873b9698030b2652a69f330e5c8c for the test module), so a detached worktree at c1662570 measures the landing content. Control: the four new guards, 4 passed, 49 deselected.
- Arm C — delete the
Resolutiongate row while the introducing sentence still says six: onlytest_the_gate_line_count_is_the_number_the_section_says_it_isreddens (1 failed, 3 passed). The stated count is measured against the table in both directions, so it is a claim under guard rather than a second copy of the table. - Arm E — move the
One knob per vote while votes are scarcebullet out of the iteration phase to the end of the file: onlytest_a_submission_is_a_purchase_and_the_rules_that_decide_it_are_in_the_iteration_phasereddens (1 failed, 3 passed), with the rule still present in the document. That is exactly what the section scoping buys: a whole-document substring check stays green for a rule moved out of the section that governs the decision, and the round that needs it reads past it.
Both arms were restored from the commit, not from a copy, and the blob read back byte for byte identical after each.
The guards are section-scoped and they fail closed. _section asserts on a missing heading and on an empty body instead of returning "", so a deleted section reads as "cannot measure" rather than as a rule that is merely worded differently. The two new helpers bound their subjects (### 5. Recording → ### Error Handling, ### 1. Assess progress → ### Phases), beside the existing _phase_d and _goal_line. The one bold-first-cell row a whole-file scan finds outside the table is line 385, the blocker table inside Error Handling — outside the section the guard reads — so the count taken is the six gate rows at 358–363.
Where each rule the issue enumerates now lives (head lines, each in the section that owns its subject):
| Rule | Line |
|---|---|
| a constant answer is a free estimator of the mean | 160 |
| an option is free only when its expectation is positive | 161 |
| a dead path is revived only after proving it is not an identity transform | 162 |
| a probe's order is its amplitude times its prior hit rate | 163 |
| one knob per vote while votes are scarce | 164 |
| several columns in one submission means a per-column report | 165 |
| a number is read only after the line that printed it is identified | 166 |
| a reading travels no further than the ruler that took it (near-identity test and local-vs-board ruler in one claim) | 200 |
| what a manual selection costs depends on how the platform aggregates | 208 |
| the platform's free readings are exhausted before a slot is spent | 214 |
| a quota that resets is spent across its period | 95 |
| the gate lines | 354 (the sentence), 358–363 (six rows) |
The issue's title says eleven and its body enumerates twelve; this carries all twelve, plus the quota-distribution method the body mentions separately. Rewriting the near-identity test and the local/board ruler separation as one bullet is the right reading — they are one claim about one object — and it does not drop either half.
Nothing restated, and no contradiction left standing. The three measurement limits #2580 landed in the same phase (lines 154–156: a resolution finer than the lever, an agreement in counts, a rebuilt artefact) are about different objects from the seven added at 158–166. The quota rule constrains how much of an allowance a round spends and requires the share, the batch bound and the gap to be stated, so it does not soften §1's obligation to submit or give a specific reason: a round still submits — a fraction of the allowance — and the increment §1 demands is satisfiable without a submission, as that section already lists.
The one thing I cannot confirm, said plainly. The supplement this ports from is not on this host: no task's config.extra_prompt here carries these rules. So "nothing general remains in the block" cannot be checked by me against the block's own text, and I am not reporting it as checked — that claim rests on the issue's enumeration, which this PR matches item by item. What I can measure here: the 40 lines the diff adds carry no filesystem path, no date, no host quotation, no extra_prompt or tasks.yml mention, and no NN hour / NN minute calibration number; and no added line shares an eight-word run with the only extra_prompt on this host. A host holding the supplement should put the two side by side before acting on the deletion advice.
At 2/3 this cycle stops: no merge from here.
Closes #2583
What this changes
The template (
emrg/server/competition_prompt.md) gains the rules an installation's supplement carries and the template did not. Every one of them is general method — each was paid for in a lost submission or a misread score — and each lived inconfig.extra_prompt, a field no other installation can read. A host following the earlier deletion advice would have removed them with nothing underneath.Each rule is rewritten in the template's own voice, into the section that already owns its subject. No date, no migration note, no numbering that points at another document, and nothing quoted from a private block.
Where each rule landed
The measurement-discipline block — seven rules, into Phase D (Iteration), the phase that decides how a submission is spent, under the heading "A submission is a purchase, and the round states what it is buying"
The conclusion-discipline block — four rules, into §2 (Goal line and prize reading), the section that decides how far a score carries
The per-round hard-actions block — the gate-line set, into §5 (Recording), where the summary's obligations already live
The six lines are stated as a table, with the sentence introducing it saying how many there are. The table is the single home of which lines exist; the sentence is a claim the guard measures against it.
The quota-discipline block — the distribution method, into §1 (Assess progress), beside the quota ledger
A quota that resets is spent across its period, not at the start of it: the ledger states the share being taken now as a fraction of the allowance, the most one batch may carry, and the gap before the next, and places the last batch so its result can still be read before the next reset. The fraction, the batch bound and the gap are calibrated from the platform's own reset time and allowance — the template does not adopt any particular numbers.
Contradictions reconciled
The report the issue asks for: what is now safe to delete
Every rule the issue enumerated is now carried by the template, so each of the four supplement blocks is redundant except for what is listed below as remaining.
Guards
Four new tests in
tests/test_competition_prompt.py, each section-scoped — a whole-document substring check stays green after the section that owns the rule is deleted, and this file discusses measurement, scoring and self-review in several places. The section-scoped form makes "stated nowhere" and "stated in the wrong section" read differently, which is the distinction a round looking for a rule needs.Seven mutation arms, each restoring from the commit rather than from a copy, each confirmed to have landed before it was measured:
C and D are the same guard measured in both directions, so the count claim is not merely a second copy of the table. E and G are the placement half: a rule that exists but sits in the wrong section is not seen by the round that needs it.
Verification
uv run pytest tests/— 5863 passed, 35 skipped onc1662570.uv run python -c "from emrg.client.app import run_client"— imports.uv run python -m emrg --help— renders.