A snapshot of the non-game files as of0148cb8("port: F5/F6 hand-off -- one-minute human checks, and a refutation attempt that survived", 2026-09-04), the tip of auto/port-p6-audio. The branch was deleted from the server on 2026-09-17 during the consolidation cleanup; issue #7 asks for this work as a reviewable PR, so it is recovered here before the commits are garbage collected. Contents: the 84 files the branch changed relative to its fork pointb305aa4, which is this commit's parent. The tree is therefore 0148cb8's tree with the 854 exported game assets left out -- export-probe/, export-probe2/, three .wav renders of game audio and adv-v2-screenlog.tsv. Game data stays out of git; the exporter regenerates those from the disc. docs/port/DECISIONS.md still refers to them by name. Not recovered: the branch's own 366 commits. Keeping them would make those assets reachable again, so this is one snapshot instead. The original commits stay unreferenced in the server's object store, and in this clone under the local branch archive/port-p6-audio, until either is garbage collected. Refs #7. The OPTIONS work that issue #6 asks for is a subset of this branch, also recovered as recover/options-menu. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.6 KiB
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.mdonauto/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_modeset. 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 <instrument> 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 — togit 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 gapBLOCKED.mdrecords as having cost three sessions. - Port:
instrument:provenance and--staleincheck-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
-
✅ The register re-classification (R1) — DONE 2026-09-01, by the human, on
docs/re/REFUTED.mdat 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 inPROTOCOL.md; andtools/stale-instrumentis the--stalequery — 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, oneour-reader, oneharness.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
x11grabstream 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 unrecordedis the backfill queue, and it is larger than every other group combined.
- The
-
P5's gate — a person clicking through the port. Unchanged, and it is the only thing standing between the milestone and done.