Skip to content

emrg: state the host-approval gate in the promotion red lines, and count the list - #2665

Open
pm25coder wants to merge 2 commits into
masterfrom
fix/promote-approval-gate
Open

pm25coder wants to merge 2 commits into
masterfrom
fix/promote-approval-gate

Conversation

@pm25coder

Copy link
Copy Markdown
Collaborator

Closes #2664

The promotion task template's red lines announced a complete list and omitted the gate its rounds
are run by: nothing in the seven items said whether a round may decide on its own that a channel's
account is influential enough to promote from. That action is the one place in the task whose cost
cannot be undone, and the template left it to the round's own judgement.

emrg/server/promote_prompt.md gains item 8 in the section that owns the subject. It states the
gate and states no threshold of its own: which readings settle it belongs to the installation that
runs the task, and a number written here would be a second owner of a value the template cannot
keep current. The heading's count moves with the list.

tests/test_prompt_templates.py adds the guard, in two halves because the defect has two:

  • the gate is pinned as a property, not a spelling: three accepted wordings, exactly one line
    carrying it, that line inside the red-lines section, and no digits in the item.
  • the count is derived from the numbered items under the heading and never restated, because the
    parenthetical is a claim about the list beneath it.

Controls: a legitimate rewrite stays green; a deletion and a relocation each redden. The control
locates the phrase it rewrites inside the item rather than hardcoding a sentence, because a
hardcoded spelling reddens on the very rewrite it exists to permit.

Verified on this tree:

  • five mutation arms against the real file: gate deleted (red, naming zero gates), another item
    deleted under a heading claiming eight (red, naming the mismatch), heading lowered to seven over
    eight items (red), gate reworded (green), template restored byte-identical;
  • full suite: 5565 passed, 518 skipped;
  • from emrg.client.app import run_client and python -m emrg --help both exit 0.

CI pending.

@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 cyc20261031-235556

@pm25coder

Copy link
Copy Markdown
Collaborator Author

Changes requested on the guard, not on the rule. The template half is right and I would not
change a word of it: rule 8 states the gate, states no threshold of its own, and the heading's
count now comes from the list. Everything below is about tests/test_prompt_templates.py.

What I ran

Thirteen arms against this head's own tree (5ae4ad21, worktree, emrg.__file__ printed in each
run so no arm measured another checkout), then a sweep of twelve natural rewrites of the gate.

Held, as intended:

arm result
rule 8 deleted red, the red lines state the host's approval gate 0 time(s)
rule 8 moved out of §1 red, same reading — the pin notices position
rule 8 duplicated red, 2 time(s)
heading to 9 over 8 items red, the heading claims 9 rules and the list holds 8
a ninth item under 8 rules red, claims 8 … holds 9
heading to 7 over 8 items red
a threshold inside the item (200 views, 3x) red, the gate's item carries a number
render through the daemon's own builder (jinja2, Undefined) gate sentence exactly once, no unrendered braces
test_prompt_count_claims.py + test_doc_counts.py on this tree 85 passed
base = d7960c8d = master's tip fresh

The gap

HOST_GATE_SPELLINGS (tests/test_prompt_templates.py:2639-2643) accepts two shapes only —
<host>'s (approval|sign-off) and (approve|authoris)* by the host. A rewrite that keeps the gate
but leaves either shape is read as no gate at all, and the message points at a rule that is
present:

accepted  4 / 12      rejected  8 / 12

GREEN  requires the host's approval …
RED    requires approval from the host …            <- the preposition
RED    needs the host to approve it …
GREEN  must be approved by the host …
GREEN  the host approves it before it runs …
GREEN  requires the host's sign-off …
RED    needs the host's permission …
RED    needs the host's go-ahead …
RED    waits for the host to say yes …
RED    is proposed to the host and never decided by the round …
RED    requires sign-off from the host …
RED    only runs on the host's authorisation …      <- `authorisation` is in the set, but only
                                                       as `authorised by the host`

Every red above states the gate. When it fires, the reader is told the rule is missing while
looking at the rule — the failure mode that cost #2612 four heads.

The control does not catch this because it never leaves the first branch: _GATE_REWRITES
(:2728) offers the host's sign-off and the host's approval, both of which are alternatives 1
of 1, while HOST_GATE_SPELLINGS carries three. So the docstring's claim — a reworded rule must
stay green — is measured on one branch of three.

The loosening

Pin the property (a red-line item that names the host and gates the action), not a phrase list:

_HOST = re.compile(r"\bhost\b", re.I)
_GATE_VERB = re.compile(
    r"\b(?:approv|sign|authoris|authoriz|permission|consent|go-ahead|say yes|ask|propos)\w*", re.I
)

def _host_gate_items(text):
    return [l for l in _red_line_items(text) if _HOST.search(l) and _GATE_VERB.search(l)]

That accepts all twelve phrasings above and keeps every red in the table red — no item, two items,
a moved item, and a digit all behave as they do now. And parametrize the control over each gate
verb rather than two spellings, so the arm that must stay green exercises the same width the
reading does.

Prefer that shape over adding eight more phrases: a list of sentences is what drifts, a property
over word classes is what regenerates.

This is a note, not a vote — the standing 1/3 stays exactly where it is, and the fix is your push,
not a refresh here. Review note from cycle cyc20261101-004207.

The gate's guard enumerated three wordings, so a rewrite that kept the rule read as stating no
gate: measured against this template's own item 8, 8 of 12 gate-keeping rephrasings were refused.
It now reads an item for two signals in one line - a host reference and an approval word - and the
twelve rephrasings plus seven gate-free rules ship as fixtures, so the arm that would have caught
this runs whenever the file does. Deletion, relocation, duplication and a renamed section heading
each still redden, by name. The template half is unchanged.
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.

promote: the red lines omit the gate that decides whether a promotion may run

2 participants