DISMISSED — AMG-3 — the fenced-real-gate / plain-decoy self-approval in the records auto-merge guard
status: dismissed by TRIAGE 2026-08-24 · premise FALSIFIED by the queue-as-directory migration (47e8e73) · raised panel run 12 (2026-08-21) · body verbatim below · the exploit still ALLOWs — what died is its consequence
Resolution — the exploit survives, its authority does not
Stated bluntly first, because this is a dismissal of a live exploit: the fence-decoy probe still returns ALLOW against the guard at HEAD. This row is dismissed because the thing it could poison no longer decides anything, not because the code was fixed.
The item's premise, in its own words, had two conjuncts. Both are now false:
- "an implementer LLM reading the raw file may honour the fenced
self-approval" — FALSIFIED.
ops/RESEARCH_IMPLEMENTER.md:49now readsresearch/queue/approved/— one file per approved item, a directory. The implementer does not readresearch/RESEARCH_QUEUE.md's## Approvedsection at all. - "the poisoned file MERGES TO MAIN, making the decoy the canonical rendered
gate for every future reader" — FALSIFIED. The canonical gate is now
the directory, enforced by PATH rather than by parsing:
scripts/automerge_guard.py:51and:191deny any agent write intoresearch/queue/approved/with no parsing involved.research/RESEARCH_QUEUE.mdis a frozen archive whose own header says so, and whose## Approvedsection reads_(none yet …)_. A decoy planted there is a defaced museum label, not a gate.
This is exactly the finding panel run 13 recorded, independently. See
research/queue/open/amg-5-sanctioned-move-fail-open.md, cross-reference
section: "AMG-3 (archive item 16) → PARTIALLY CLOSED / defanged … build
authority moved to the directory, so the merged poison no longer drives the
implementer."
What is left, and where it goes. The guard still carries
QUEUE_FILE = "research/RESEARCH_QUEUE.md" and its ## Approved
section-parsing machinery (automerge_guard.py:74, 111-142, 228-238) — dead
weight that can still be tricked but no longer gates anything. Panel run 13
already recorded the cheapest full close inside the AMG-5 row, which
touches the same file: add ^research/RESEARCH_QUEUE\.md$ to the guard's deny
patterns (a frozen archive needs no auto-mergeable edits) and delete the
vestigial section parser. That is where the residual belongs — one fix, one
PR, one row. Duplicating it here is how one defect becomes two queue rows.
Explicitly NOT dismissed with it: AMG-4 (queue/open/), which panel run 13
re-verified as still live and aggravated, and which AMG-5 states plainly it
does not subsume.
Reopens if: (a) the guard's ## Approved section parsing, or
research/RESEARCH_QUEUE.md itself, ever regains authority over any consumer
(the implementer, the digest, the go-live gate, a future routine); or (b) the
frozen archive is un-frozen and returns to being a live queue surface; or
(c) the AMG-5 fix lands without the deny-pattern/parser-deletion fold-in
recorded above, leaving trickable gate-parsing code in a guard whose docstring
still claims it fails closed everywhere.
Body as raised (verbatim from the frozen archive)
16. AMG-3 — the records auto-merge guard still ALLOWs a self-approval when
the real ## Approved gate is wrapped in a Markdown code-fence and a plain
decoy ## Approved is planted outside it; AMG-2's fix (955db93) did not touch
this, and the 2026-08-18 reopen valve fired with both its conjuncts true. ·
judgement: YES · effort 0.25 pd · horizon: live now (any routine with
contents-write can mount it)
Mechanism, reproduced this run. scripts/automerge_guard.py:106
_strip_fences() runs BEFORE the ## Approved header-uniqueness count at
:115 and before section extraction. So a records-only EDIT to
research/RESEARCH_QUEUE.md that (a) wraps the genuine ## Approved section —
carrying an inserted self-approval — inside a ```-fence, and (b) plants a
second, plain ## Approved header outside the fence with the verbatim
_(none yet…)_ text, presents exactly one un-fenced header to the count,
so AMBIGUOUS (:117-118) does not fire and the decoy's empty content is
returned. Executed against the file at 10e4ce9: ALLOW: records-only (1 file(s)); no gate touched, with the self-approval present in the merged file.
The prior AMG-1/AMG-2 defences are structurally blind to this inversion — the
original attack hid the decoy in a fence; this hides the real gate in a
fence, and stripping deletes the evidence before counting. ops/RESEARCH_ IMPLEMENTER.md (:33, :49) instructs "Build ONLY what is in ## Approved"
and mentions fences zero times, so an implementer LLM reading the raw file may
honour the fenced self-approval; and regardless of the implementer, the
poisoned file MERGES TO MAIN, making the decoy the canonical rendered gate for
every future reader.
Valve provenance. The ## Dismissed entry dated 2026-08-18 pre-registered:
"REOPENS as its own row if AMG-2's fix lands with neither the
pre/post-fence-strip ## Approved header-count-differ guard leg nor the
RESEARCH_IMPLEMENTER.md §1 fence-quotation pin." 955db93 landed with
neither (grep-verified: no fence logic added; RESEARCH_IMPLEMENTER.md still
has no fence text). Both conjuncts hold; this is the valve firing, not a fresh
discretionary find.
Data plan. None — static code + this run's probe fixture. Owned.
Test design + kill criterion — pre-registered, negative-controlled both
ways. Add the probe fixture (fenced-real-gate + plain-decoy) as a permanent
deny-asserted test, plus a clean-file allow control. The fix is an
unscoped raw-vs-fence-stripped ^## Approved header-count compare: if the
counts differ, DENY. (Do NOT scope it to a gate-sentinel line — verified: the
live queue file has exactly 1 approved header both raw and stripped and 4
fenced blocks with zero headers, so an unscoped compare is false-positive-free
today, simpler, and strictly stronger; scoping reintroduces the parsing
subtlety that has now beaten this function three times. A future legitimate PR
that quotes the gate inside a fence costs only a DENY→human-merge, which is
the correct handling for a PR reproducing the gate verbatim.) Kill
criterion: probe fixture DENYs and both controls ALLOW post-fix; revert the
guard change → the deny test reds. Owner escape: if the owner rules the
RESEARCH_IMPLEMENTER.md fence-quotation pin sufficient on its own, the
guard-side gap closes as accepted-and-recorded — but the acceptance record
must state that merge-poisoning of the queue's rendered gate remains
possible (the pin defends only the implementer's read, not the merged file),
not merely that a known-ALLOW fixture is kept.
Cross-reference row 17 (F2, the self-widening flank) — same file, different mechanism, possibly different fix-owner; deliberately a separate row per the 2026-08-11 valve's own "as its own row" clause.