# Agreed retro — Port and Decoder, 2026-08-31 Two self-reviews, one round of mutual attack, and the result both agents accept. * Decoder's own review: `docs/agents/RETRO-2026-08-31.md` on `auto/frame-blend-draw-path`. * Port's failures and the original eight proposals: this file's §1, and `docs/port/DECISIONS.md`. ⚠️ **Nothing here is applied to `PROTOCOL.md`.** The parts that change the shared refuted-claim register are presented for the human, not enacted by two agents agreeing with each other. Both agents remain paused. ## 1. The single most expensive thing we did **We let claims that rest on our own renderer sit in the register as settled refutations.** `REFUTED.md` killed *"`T8aD +0x04` bit `0x02` selects an additive blend"* with the reason *"blending those sprites additively worsens every measure against the capture"* — a statement about our renderer, made while that renderer had a stale keyframe association, no leaf geometry and no rotation. The field is real. It sat dead for weeks, and the cost was: a published *"the blend is not on the disc"*, an authored table built on it, **three rounds of per-element transcription**, and one agent steering a search deliberately around the entry. The Port paid the mirror of it: a phase sweep that *"refuted"* menu-looping was measuring the Port's own sweeps, not the game's, and was re-run and reported as *strengthened* one iteration before the oracle contradicted it. 📌 **Neither of us was careless. The rule was in `PROTOCOL.md` the whole time** — *"anything derived from our own renderer rather than a capture"* is named as a prime refutation target. What was missing is that nothing **re-opens** a claim when the instrument that killed it improves. ## 2. The gap underneath our controls `PROTOCOL.md` already requires running an instrument through a control. **We both did, and it did not help**, because: > **Our controls verified capability, not configuration.** * The Port's additive material passed every control — they tested whether the *method* detects a blend difference, not whether *this run* had `blend_mode` set. It was left at Godot's default, `MIX`. The change predicted a large move and delivered **0.03**, and would have been publishable as a careful negative. * The Decoder's vertex dump passed every control — they tested whether NDC→pixel conversion is right, not whether the dump captured all six quads. It captured **two**, with a well-formed line and no ellipsis, and four elements therefore appeared *in no draw on any screen*. ## 3. The gap neither of us had noticed > **We have never given a NEGATIVE a positive control.** Every *"undecodable, with reach"* page lists **where we looked**. Not one shows that the search method **can find a property that is there**. *"Absent"* and *"my search does not work"* are indistinguishable in all of them — and *"the blend is not on the disc"* is exactly that failure, published. ## 4. The rules we agree to work by | | rule | replaces / from | |---|---|---| | **R1** | **A refutation whose instrument is one of our renderers is not a refutation.** It is *"our renderer disagrees"* — 🟡, not ❌. Each register entry names its `instrument:`, and a `--stale ` mode lists everything that instrument killed, for re-opening when it changes. | Port P2, strengthened by Decoder | | **R2** | **State the expected number before you read the actual one** — the effect size for a change, the *count* for a parse. *"This draw declares 24 indices, so I expect 6 quads."* | Port P3+P4, merged by Decoder | | **R3** | **Instruments print their own completeness**: *n* resolved of *n* declared, and refuse to be trusted otherwise. | Port P4 | | **R4** | **A negative carries a positive control.** Before publishing *"no field encodes X"*, show the same search finding a field known to exist. | Decoder D1 — **neither agent had this** | | **R5** | **Label provenance is part of the artefact.** A field hunt states where its ground truth came from, and **renderer-derived labels are disqualified for disc-side questions.** | replaces Port P1, which had no teeth — the question *was* asked and answered wrongly | | **R6** | **Suppression localises disagreement; only the oracle labels it.** It is two renders of ours: it found the frames, it could not have said *additive*. | Decoder's correction of Port P5 | | **R7** | **Coverage is computed against a declared denominator** — *"35 of the 41 elements entry 6 declares"*, never *"everything is covered"*. | Port P6 + Decoder | | **R8** | **Hold the role line even when the answer looks obvious.** The asymmetry is the argument: refusing to infer `ptframe4` cost one message; inferring *"frame-shaped and mostly transparent ⇒ additive"* would have cost a wrong renderer until the title was captured — **and the title capture killed that exact rule.** | Port P7, agreed | | **R9** | **The message carries the delta and names the file and section; it does not summarise it.** Short messages are safe only when the pointer is precise. | Port P8 + Decoder's caveat | | **R10** | **A disagreement is evidence about the CHAIN — disc → decode → render → capture — not about a link.** A chain-level residual gets a named owner and a next experiment, or is recorded as unowned. | Decoder F | | **R11** | **A cross-agent pointer must fail loudly when it goes stale.** Every staleness incident here was silent. | Port, new | | **R12** | **Each iteration names the gate it moved, or says plainly that it moved none.** | Port, new — see §5 | ## 5. The efficiency finding neither review led with **The record has grown faster than the artifact.** `DECISIONS.md` is past 13 000 lines. This session produced twelve Port commits of genuine measurement — and the milestone gate did not move, because **P5's gate has needed a human, not code, the whole time.** Writing more is not free, and a capability that lives only in the record is, to the person who needs it, absent. R12 exists so that a run of iterations that moves no gate **says so**, rather than reading as progress because each entry is individually rigorous. ## 6. What each agent changes, without a human * **Decoder:** a standing pointer at the top of `HANDOFF.md` — which their brief already forces them to read every iteration, and which is theirs to write — to `git show origin/auto/port-p6-audio:docs/port/BLOCKED.md`. **One line in a file they own**, routing the Port's standing asks into a file they must already open. This closes a gap `BLOCKED.md` records as having cost three sessions. * **Port:** `instrument:` provenance and `--stale` in `check-claims`; completeness lines (R3) and predicted counts (R2) in the port's tools; a loud staleness failure for peer pointers (R11). ## 7. What needs the human 1. ✅ **The register re-classification (R1) — DONE 2026-09-01, by the human**, on `docs/re/REFUTED.md` at the Decoder's tip. All **222** entries now carry an `⟨instrument⟩`; the file opens with a reading guide naming which instruments are ours; R1 is now standing text in `PROTOCOL.md`; and `tools/stale-instrument` is the `--stale` query — run it whenever you improve a renderer, a reader or the harness, and it lists what that instrument killed. **Ten entries moved ❌ → 🟡**, each naming what would settle it: eight `render-vs-capture`, one `our-reader`, one `harness`. Three things the pass turned up that neither self-review had: * **The `rest()` question is open, and had been reading as settled in both directions.** *"rest = last keyframe"* was refuted by the sibling argument; that refutation was then refuted by correlating our render against captures. Both legs run through our renderer, so under R1 neither survives — and which one you believed depended on which entry you found first. 🔴 **This one is load-bearing for the port**: `rest()` decides the pose every plateau-less element is drawn at. * **A withdrawal never reached its sibling.** *"2 391 frames, max glyph 0"* was withdrawn because a long-lived `x11grab` stream degrades and then repeats a stale frame. The 1 674-sample negative three lines above it — same probe, same instrument, comparable duration — was left standing as a *reinstated measurement*. §1's lesson, inside the register itself. * **83 of 222 entries — 37 % — record no instrument at all.** Not disputed, not safe: **unauditable**. `stale-instrument unrecorded` is the backfill queue, and it is larger than every other group combined. 2. **P5's gate** — a person clicking through the port. Unchanged, and it is the only thing standing between the milestone and done.