Files
Sylpheed/docs/re/REFUTED.md
sylph-decoder 531c2d0ca4 re: F1 -- the "no auto-repeat" finding was measuring our own driver
Issue #1's premise (the human's play-test: a held direction repeats) directly
contradicted menu-navigation-semantics.md's 2026-08-30 "no auto-repeat"
row. Read the instrument before trusting either: nav_repeat_and_b.py drove
input through Canary's --hid=file driver, and that driver's GetKeystroke()
is explicitly, deliberately built to deliver exactly one event per held
press ("scripted input wants precisely one event per press, and repeat is
what makes menu steps overshoot" -- file_input_driver.h's own comment).
input-pad-read-path.md already established the game reads menu input via
this same Keystroke API. A driver engineered to prevent repeat cannot be
evidence the game lacks it -- the counter's control (a tap gives 1 spike)
proved the counter works, not that the driver could show more than one.

Not a clean reversal, and said so: the same driver's GetState() holds a
button continuously with no edge suppression, and pad.py's own docstring --
written by an earlier session driving this exact tool -- warns that a longer
dpad hold "auto-repeats and overshoots," describing an observed effect
through this same driver. The two pieces of evidence disagree and this page
does not resolve which wins.

Also read from Canary's source: the SDL input driver (what a real controller
goes through) auto-repeats keystrokes at 400 ms initial delay then 100 ms
interval, guest time (HID_SDL_REPEAT_DELAY/RATE, upstream Xenia, not a
project change) -- a concrete, testable prediction for what the real number
could be if the menu treats repeat-flagged keystrokes as nav steps, matching
the human's "medium pace" description. Not yet measured.

Refutation attempt this iteration, recorded per adversarial duty: targeted
the 2026-08-30 "no auto-repeat,  measured" claim. Survives only partially --
demoted to unsettled, not flipped to a confident opposite. New REFUTED.md
section (Menu navigation and input) and the row in
menu-navigation-semantics.md both corrected in place, old text kept per
convention.

What would close it: trace C_PAD_RINGBUF's producer (keystroke ring vs
polled state) statically, or add an opt-in repeat mode to the file driver
and read cursor position off the draw log per frame. Neither run this
iteration -- this is the static half, and reversing a standing claim is
enough for one unit without stacking a build-and-boot run on top of it
unverified.
2026-09-12 10:57:46 +00:00

72 KiB
Raw Blame History

Refuted — claims that were tested and died

Read this before proposing a hypothesis. Every line below was believed at some point, measured, and found false. Reviving one costs a whole iteration and produces nothing.

This file exists because the list had been living in the autonomous agent's loop prompt — the only copy, lost the moment the container was. A refuted result is a real result; it belongs in the corpus like any other.

Format: each entry is the claim as it was believed. Where the true answer is known it follows after . Grouped by subject so a grep for your noun finds the neighbourhood, not just the line.


How to read this file

Reclassified 2026-09-01 under rule R1, by the human, on the retro both agents asked to have adjudicated (../agents/RETRO-2026-08-31-agreed.md §7). Neither agent may reclassify this file; it is the file they both read to decide what not to try, and two agents agreeing is not the authority for changing it.

The rule

A refutation whose instrument is one of our renderers is not a refutation. It is "our renderer disagrees"🟡, not .

Not because such work is careless. The motivating case was careful: "blending those sprites additively worsens every measure against the capture" killed a real disc field for weeks, and the renderer that produced that measure had a stale keyframe association, no leaf geometry and no rotation. It read exactly like a publishable negative. Nothing in the entry could have told you otherwise — which is why the fix is structural rather than a warning to be more careful.

The verdicts

meaning may I re-open it?
(unmarked) dead. The instrument was not ours — a capture, the disc, the executable, Canary's source, or the claim's own control. no, unless you bring a new instrument
🟡 our instrument disagrees. The conclusion may be right; it has not been tested against the game. yes — and re-open it when that instrument improves
struck withdrawn by a later entry. Read the correction under it. it is already open
established, and kept here because it once sat in this file as dead no

The instruments

Every entry ends with ⟨instrument⟩. Ours are marked, and the mark is what --stale queries.

⟨tag⟩ ours? what it means
capture no the real game in Canary — a screenshot, a draw log, a GPU readback, an observed frame
disc no bytes on the disc: a parse, a census, a disc-wide scan
image no the executable: code, strings, tables, xrefs
canary-source no Xenia Canary's own source read directly
control no the method failed its own positive control. Valid whoever built it — a filter that cannot find a known-good is dead, not tuneable
environment no a fact about the container or host
audio-analysis no signal measurement on disc audio, with a control
corpus no a stale row found by reading our own documents
render-vs-capture yes a correlation, RMSE or box-mean between one of our renders and a capture
screen-render yes ui_layout::blit, sylpheed-cli screen render, the rest() heuristics
our-reader yes one of our decoders used as the yardstick, rather than disc bytes read directly
harness yes our capture harness: polling cadence, x11grab, frame classifiers
our-tool yes, but see below our own tool, where the question is about that tool
reasoning argued from structure, not measured
unrecorded the entry states no evidence. 83 of 222 are here

Two things this rule does not say

1. our-tool is not disqualifying when the question is about our tool. R5 disqualifies renderer-derived labels for disc-side questions. "Can screen render draw the developer splash?" and "does blit apply the pivot here?" are questions about our code, and our code is the right instrument for them. Those stay . The tag is still there so --stale our-tool can find them if the tool is rewritten.

2. unrecorded is not a verdict. It means nobody wrote down how the claim died. It is the single largest group in this file, and the honest reading is that a third of this register cannot be audited at all. Do not treat those rows as either safe or suspect. --stale unrecorded is the backfill queue.

What changed in the pass

Ten entries moved 🟡. Eight are render-vs-capture, one our-reader, one harness. Each names what would settle it, because a re-opened claim with no next experiment is just an unanswered question with a colour.

Two of them are the same question pointed both ways: the rest() pair. "rest = last keyframe" was refuted by a sibling argument, and that refutation was then itself refuted by correlating our render against captures. Both legs run through our renderer, so under R1 neither survives — the question is open, not settled, and it had been reading as settled in both directions depending on which entry you found first. That is the clearest thing this pass turned up.

One entry was already revived by the agents before the pass, on capture evidence: the additive-blend bit. It is the archetype and is kept in full, below.

Querying it

tools/stale-instrument                     # everything, grouped by instrument
tools/stale-instrument render-vs-capture   # what one instrument killed
tools/stale-instrument --ours              # only instruments that are ours

Run it when you improve a renderer, a reader or the harness: it lists exactly what that instrument killed, so those claims re-open instead of staying dead because nobody remembered which ones rested on it.


Offsets, structs and the progress singleton

  • position = instance 0x12c → refuted. ⟨unrecorded⟩
  • +0x29d0 → refuted. ⟨unrecorded⟩
  • "an offset intersection can find a struct's consumer" → only for LARGE or unusual offsets. Small ones have no power (+184: 301/351/115 hits). ⟨image⟩
  • "a +1956 store means a progress write" → writes go through the COPY, not direct stores. 9 direct stores, none of them a progress write. ⟨image⟩
  • "the singleton-global filter can find progress writers" → it fails its own control. ⟨unrecorded⟩
  • "the progress copy destination is an r1-relative stack local" → it is a frame register. The r1 assumption returned 0 for all 21 candidates including the known-good — the filter was killed by its own control. ⟨control⟩
  • "word B's writer also stores the Time/Points record" → it does not. ⟨unrecorded⟩
  • "the debriefing records the metric with the clear bit" → 44 calls, exactly two strings (DEBRIEFING, BASE_INFO), no Time, no Points. ⟨image⟩
  • "0x820AF030 holds live state" → all 384 words constant; it is a spawned-entity record, not live state. ⟨capture⟩

Screens, classes and RTTI

  • "the rotated draw in the title's capture is the Z swoosh (ptlogo_back2*)" → mine, and refuted. Its quads span y 209…925 and 292…1012 in screen space; the swoosh is a band at y 126…360. ui-title-build-map.md ⟨capture⟩
  • "the keyframe words at +4/+8/+12 are always zero" → they are non-zero in 4.76 %, 4.62 % and 14.50 % of 83 862 blocks disc-wide, reading as degrees (±180, ±90, 120, 360). The original note was a sample artefact. (Superseded figures: an earlier count of 72 287 blocks missed every nested record — see the alignment entry below.) ⟨disc⟩
  • "those angle fields are where the title's rotated quads come from" → no — every GP_TITLE build 4 element has all three at zero.that refutation was itself wrong, and is withdrawn (2026-08-28). +12 is exactly where they come from. Build 4's top-level elements do all read zero; the rotated quads belong to its two nested leaf records, ptloop01.rat (+12 = 30) and ptloop02.rat (+12 = 45), which the census never opened. Measured off the GPU: +30.26° and 45.28°. ui-keyframe-rotation.md ⟨disc⟩
  • "the rotated draw's element cannot be named from the capture" → refuted; its quads' edge lengths name it. 400 × 1076 and 400 × 1444 match pteff03 399×180 at 600 % and pteff03a 399×180 at 800 % — two different heights, both landing. ui-keyframe-rotation.md ⟨capture⟩
  • "a keyframe-block scanner may assume 4-byte alignment" → refuted; it found 0/3 of its own control blocks and under-counted the corpus by 16 341 blocks. Nested RATC blobs start at odd offsets (0xbb5966). ⟨disc⟩
  • "keyframe rotation lives only in nested .rat leaf records" → mine, and refuted within the hour by my own sweep. It held for the three archives I had checked (GP_TITLE, GP_BUNK, GP_CHALLENGE) and failed on the next: GP_DIALOG and GP_DEBRIEFING_PILOTLOG rotate top-level elements, and those are the clearest examples on the disc. ui-keyframe-rotation.md ⟨disc⟩
  • "the pivot-anchored scale formula kf.x pivot·(scale100)/100 is our renderer's reading, not a measurement" → now measured. At the ptloop pair's 600 %/800 % scale it predicts both quad centres at y = 360.0 against a captured 359.1/360.0, where top-left anchoring predicts 810/990. ui-keyframe-rotation.md ⟨capture⟩
  • "the game passes a pink per-vertex colour for the title swoosh" → refuted by draw capture. Every vertex colour in the capture is <alpha>FFFFFF, white RGB. ⟨capture⟩
  • "the swoosh discrepancy is undecodable" → solved: the game submits it as two rotated parallelograms; ui_layout::blit only does axis-aligned rectangles. ui-title-build-map.md ⟨capture⟩
  • "the --log_ui_draws per-draw capture reads the guest's blend state" → mine, and wrong. It records primitive type, index count, index-buffer address, VS/PS ucode hashes, texture bindings and vertex attribute 0 — no RB_BLENDCONTROL. It can test vertex colour as-is; blend state needs a Canary change. ui-title-build-map.md ⟨our-tool⟩
  • 🟡 "the plate-free title capture (t ≈ 4.0 s) may be too early to be settled" — our renderer disagrees (was before the R1 pass). The swoosh band correlates 0.7342 at t = 4.0 s and 0.7353 at t = 21.5 s — identical to 0.001 over 17.5 s. Both numbers are our render against a capture, so the test is blind to anything our renderer does not draw: an element missing from the render cannot move the correlation whether or not it moved on screen. To settle: compare the two captures to each other — no renderer in the path. ⟨render-vs-capture⟩
  • "T8aD +0x04 bit 0x02 selects an additive blend" → mine, and refuted. Blending those sprites additively worsens every measure against the capture. 🔴 REVIVED AND ESTABLISHED 2026-08-31 — the refutation was wrong, and it was wrong in a way this corpus has a rule for. "Blending them additively worsens every measure against the capture" is a claim about our renderer, which the protocol calls a hypothesis under test; at the time it had a stale keyframe association, no leaf geometry and no rotation. The claim was never tested against the game. It is now: the blend is read per draw out of RB_BLENDCONTROL0, and the bit partitions 35 elements over three screens with zero errors — and of every bit of the first twelve header words, exactly one does so, with no tie. The within-pair case: ptbtn00 0x0110 alpha-over, ptbtn00f 0x0112 additive — same screen, same bundle, adjacent draws, one bit apart. And an out-of-sample prediction committed before its capture held on a different archive: GP_OPTIONS entry 19 was predicted 3 additive of 16, and the game drew exactly po_menu_eff01/02/03 additive and nothing else. → structures/ui-blend-mode-decoded.md ⚠️ Two other readings of this same bit stay refuted, and are not revived by this: "the bit means the name contains eff" (fails on 2 657 of 4 995 disc-wide) and "the bit selects premultiplied alpha" (the flagged group violates RGB ≤ A more than the unflagged one). Those were readings of the bit's meaning; what is established here is its effect. ui-title-build-map.md ⟨capture⟩
  • "the title logo elements' wrong pivots (off by up to 59 px, authored against the other language's sprite) explain the swoosh rendering too thick" → mine, and refuted. blit sizes from the texture and applies the pivot only as pivot·(scale100)/100; all seven swoosh elements are scale (100,100) at every keyframe, so the term is zero. The mismatch is real but inert here — it would bite ptlogo1/ptlogo2, which scale to 150 during the build-in. ui-title-build-map.md ⟨our-tool⟩
  • "the title screen loops at ≈ 2.2 s" → mine, and doubly wrong. The title art is near-static (wordmark sd 0.06); the 2.3 s pulse is the PRESS Ⓐ BUTTON plate, which is a different build (2, not 4). Localised by a per-tile amplitude map and decoded in ptbtn00f.rat. ui-title-build-map.md ⟨capture⟩
  • "a .rat leaf record's keyframes use the build's 40-byte layout" → they do notwithdrawn. They do. The scan that "found nothing" required 29 increasing times; the records hold three. Decoded in ui-title-build-map.md. ⟨disc⟩
  • "the title's measured ≈ 2.2 s oscillation is the ptloop01/ptloop02 elements" → mine, and refuted by decoding them. Their sweeps run 7.5 s and 9.5 s; a 22 s capture showed 8 peaks, not 3. The period's source is unidentified. ⟨disc⟩
  • "the developer splash cannot be rendered by screen render at all" → it can, with --all. It is only invisible to the default listing, which filters on is_build. ui-title-build-map.md ⟨our-tool⟩
  • "the four GP_TITLE entries that are not screen builds are unidentified" → they are the splash: 10/13 the SQUARE ENIX logo, 11/14 the developer logos. ⟨disc⟩
  • "the boot title is phase 2 and the attract title is phase 4 state 0, and only phase 2 handles Ⓐ" → refutedthe REFUTATION is withdrawn. The test assumed Ⓑ lands in phase 4 state 0; the event-0 block actually sets phase = 2 and state = 0 together, so it probed phase 2. The hypothesis is untested, not dead. boot-config-and-gamepart-registry.md ⟨image⟩
  • "any title after the first one refuses input" → too broad. The Ⓑ-returned title accepts Ⓐ; only the attract-returned title is inert. canary-scripted-input-traps.md ⟨capture⟩
  • "sub_821C6458 is GamePart_Title's state machine" → mine, imprecise. It is the machine for phase 4 of a five-way outer dispatch at this+132; phase 0 is the splash. The ten states and eighteen edges are phase 4 only. boot-config-and-gamepart-registry.md ⟨image⟩
  • "sub_821CC860 is the game's by-name screen factory" → mine, and wrong. Its decoded arguments include BG, BLACK, FADE, FILE, KEY, PAD, SOUND, GAMMA_RGB — it is a generic name-keyed lookup, mostly config. ⟨image⟩
  • "DIFFICULTY and EXTRA_MENU are corroborated screen names" → mine, and wrong. Neither appears in r5 at any of the 48 call sites; they were strings merely referenced by the same functions. Only TUTORIAL_MENU survives. boot-config-and-gamepart-registry.md ⟨image⟩
  • "the {func, func, ptr} triples at 0x820a3b48 are a GamePart state table" → static-initialiser records trailing the RegisterToFactory strings. The bytes before them are the tail of a diagnostic string and the data column is zero-filled descriptors. boot-config-and-gamepart-registry.md ⟨image⟩
  • "the boot sequence is driven by a table the game reads" → it is not data-driven; four search spaces closed, transitions are calls with an id argument. boot-config-and-gamepart-registry.md ⟨image⟩
  • "config.ini is a GamePart settings table, so the boot order is in it" → its [SYSTEM] section is empty; the only populated section is [LANGUAGE]. boot-config-and-gamepart-registry.md ⟨disc⟩
  • "the attract loop is GP_ADVERTISE_DEMO (GamePart 1)" → 🟡 id 1 has no registration site in the shipped build; the attract is the title replaying ADV.wmv. ⟨image⟩
  • "the 29 id-table names are 29 distinct GameParts" → 24 register, and 3/4 are the same class (GamePart_SaveLoad). ⟨image⟩
  • "Ⓐ on NEW GAME leads to a standing black-screen hang" → it opens DIFFICULTY, then SELECT DATA. What looked like a hang was a menu waiting for input that nobody pressed; the crash that follows is the already documented sub_823070B0 cache throw. menu-navigation-semantics.md ⟨capture⟩
  • "tapping Ⓐ during the boot movie breaks the title" → one tap skips the movie cleanly and the title works normally. It is hammering (88 presses) that breaks it. movie-binding.md ⟨capture⟩
  • "the attract movie runs ~85 s, so it is not ADV.wmv (137 s)" → mine, and wrong. Sampling began 39 s into the movie, so what was timed was its tail. The attract movie is ADV.wmv, played in full. movie-binding.md ⟨capture⟩
  • "the boot intro and the attract movie are different videos" → one asset, one manifest slot (ADVERTISE_MOVIE). ⟨disc⟩
  • "the new-game intro is unidentified" → MS00AS00A.wmv, decoded from the movie manifest. ⟨disc⟩
  • "GP_READY_ROOM.pak holds the Ready Room screen" → its 317 distinct element names contain none of the six visible labels; it is the briefing / tactical-map content behind the BRIEFINGS item. ready-room-probe.md ⟨disc⟩
  • "the Ready Room might be 3D with a UI overlay" → it is 2D; the pak carries zero 3D containers. ⟨unrecorded⟩
  • "element kind 0x3002 is the button kind" → title-side only. All 902 GP_READY_ROOM bundles have zero 0x3002; that pak uses 0x3000, 0x3004, 0x300c, 0x3008. 0x3002 is one member of a 0x3000 family. ⟨disc⟩
  • "the transition between menu screens is a cut" → it is a fade through black; a 0.5 Hz screenshot burst simply samples too slowly to see it. screen-transitions.md ⟨capture⟩
  • "the main menu's initial focus is fixed" → three boots of one script gave TUTORIAL, TUTORIAL, NEW GAME. ⟨capture⟩
  • "the title menus drop d-pad presses shorter than ~0.3 s" → refuted by my own data. The menu wraps at both ends; every press registered, and the "missing" step was the wrap. See menu-navigation-semantics.md. ⟨capture⟩
  • "the main menu opens with NEW GAME focused" → it opens on TUTORIAL, 2/2 boots (🟡 a third recorded run implies NEW GAME, so this is reproducible, not invariant). ⟨capture⟩
  • "GP_TITLE builds 6/8/9 are three submenus" → 8 is the JAPANESE main menu, and 6/9 are the English and Japanese EXTRAS submenu. GP_TITLE holds eight screens shipped twice (EN/JP), and exactly one submenu. See ui-title-build-map.md. ⟨disc⟩
  • "the PRESS Ⓐ BUTTON plate is a state of the title build" → it is its own build (2/3), composited over build 4 and faded in a beat later. ⟨disc⟩
  • "the RTTI route can name the anonymous classes" → 1 150 vtables: 1 150 ANON_, 0 rtti_present, 0 base classes. ⟨image⟩
  • "the sibling vtable methods name the class" → they cannot. ⟨unrecorded⟩
  • "xrefs can name the callers of a vtable method" → no. ⟨unrecorded⟩
  • "the ind_call refutation voids existing corpus claims" → damage bounded, 4/4 caller claims verify. But xrefs.ind_call is a CROSS PRODUCT — always filter kind='call'. ⟨image⟩
  • "BASE_INFO marks the 5-slot screen family" → it discriminates screen-config from table-read, 9/9 vs 10/10. ⟨image⟩
  • "a high key count means a rich screen" → sub_82297550 / sub_822A2F00's 27 "keys" are coordinate pairs, i.e. a layout table. ⟨image⟩
  • "EX_ = the CHALLENGE-mission debriefing" → EX_ is EXTRA, mission-kind 3. ⟨unrecorded⟩
  • "the EX_ selection has not been shown" → it has: [[obj+4]+184] == 3. ⟨unrecorded⟩

Stages, missions and the challenge set

  • "the disc's stages are numbered 1..28" → S01S16 story, S17 cut, S18S23 tutorials, S24S29 challenge. ⟨disc⟩
  • "S24S29 are story missions" → they are the challenge missions. ⟨unrecorded⟩
  • "the challenge missions have their own maps" → they reuse GP_MAIN_GAME_E.pak's stage records. ⟨disc⟩
  • "the challenge REQUIREMENT values are 16,25,26,27,29" → the chain is 16→24→25→26→27→28. ⟨unrecorded⟩
  • "the Extra0n family shares one leaderboard metric" → RECORD_TYPE is per-stage: 3 Time / 3 Points. ⟨unrecorded⟩
  • "stage = filled SHAB count + 1" → refuted. ⟨unrecorded⟩
  • "the first TRIGGER is always the point of no return" → refuted. ⟨unrecorded⟩
  • "EnumUnit_S14.tbl might be missing" / "S14's 13 are a manifest omission" / "asteroids are exempt from the manifest" → S14's 13 are dangling deployments. NEEDS-HUMAN: fly S14. ⟨disc⟩
  • "StageMessageSet_S02.tbl is not in the pak" → it is. ⟨unrecorded⟩
  • "S28_p1 has an asteroid volume with no definition" → refuted. ⟨unrecorded⟩
  • "test_s8p1_asteroid.tbl is test-only" → refuted. ⟨unrecorded⟩
  • "the settings family has 28 or 29 objects" → 24. ⟨unrecorded⟩

ISL / mission scripting

  • "the bytecode is in the .embsec_ sections" → refuted. ⟨unrecorded⟩
  • "only 31 built-ins take a unit" → refuted. ⟨unrecorded⟩
  • "sub_8230C398 is the message pump" → refuted. ⟨unrecorded⟩
  • "bus+8216 is the subscriber registry" → refuted. ⟨unrecorded⟩
  • "the ScriptPhase vtable is ≥200 slots" → 113. ⟨unrecorded⟩

IDXD, paks and naming

  • "IDXD record keys are name_hash" → record keys are tag_hash (case-SENSITIVE); name_hash is case-INSENSITIVE and used for pak keys. ⟨disc⟩
  • "pak TOC order is stage order" / "TOC order is semantic order" → it is not. ⟨unrecorded⟩
  • "the executable holds the asset names" → the image names no data value at all; that route is powerless. ⟨image⟩
  • "the image might name a data VALUE" → powerless. ⟨unrecorded⟩
  • "the XPR2 manifest names hash to the DefTables tables" → refuted. ⟨unrecorded⟩
  • "the DefTables model names are unreachable" → reachable via the Enumerate declaration tables (1 413/1 425, 99.2 %). ⟨disc⟩
  • "the GP_MAIN_GAME_* unnamed block is undiscovered data" → refuted. ⟨unrecorded⟩
  • "each GP_MAIN_GAME_* Enumerate object declares something" → refuted. ⟨unrecorded⟩
  • "GP_HANGAR_ARSENAL is missing data tables" → refuted. ⟨unrecorded⟩
  • "the Enumeration self-index can name objects" → a self-index names records, not files. ⟨unrecorded⟩
  • "a per-pak prefix might close the 2D blocker" → no. ⟨unrecorded⟩
  • "the + paths might name the 2D or GP_READY_ROOM keys" → the +-dictionary route is exhausted, 0 of 1 817. ⟨disc⟩
  • "the game:\ paths are unresolved" → refuted. ⟨unrecorded⟩
  • "a set-difference over file names can see reuse" → it cannot; join per USER. Per-pak copies are ×6. ⟨disc⟩

Audio

  • "which bank the menu plays is not on the disc" → the cue table cannot say (all BGM cues are numeric), but the code can: sub_821C5580 plays cue 1103 = BGM_103, and its two declared waves match the two streams the XMA probe saw byte-for-byte. ⟨image⟩

  • "the observed BGM stream sizes match no bank's declared waves, so the game hands the decoder a window" → mine, and wrong — I checked only the BGM_0xx rows. They are BGM_103's two waves exactly; the game hands over the whole wave. ⟨disc⟩

  • "an individual SE cue's audio cannot be extracted" → mine, and wrong. --xma_param_probe=true logs each stream's head bytes; searching them in Static.slb locates the wave exactly. menu-audio-cues.md ⟨capture⟩

  • "Static.slb has no wave boundaries, so its layout is unknown" → it is a packed run of whole 2 048-byte XMA packets with no delimiters — the two located cues are contiguous. There is nothing to scan for, by design. ⟨disc⟩

  • "Pj_Silph.xgs holds the cue→wave index, so parse XACT" → no XACT container exists on this disc: 0 × XGSF/SDBK/WBND in all 1.08 GB of sound.pak, and no XACT/.xgs string in the executable. The extensions are the authoring tool's, not the format's. menu-audio-cues.md ⟨disc⟩

  • "every sound cue resolves to its own .slb bank" → the 322 SE_* cues do not; 0 of 322 are in FILES, and BANK_SE puts them all in Static.slb. ⟨disc⟩

  • "Static.slb can be split into waves like any other bank" → it holds 0 RIFF, 0 seek, 0 WAVE across all 8 353 472 readable bytes. menu-audio-cues.md ⟨disc⟩

  • "BGM_001.slb is three sub-waves (10 KB + 4.47 MB + 4.67 MB)" → the 10 KB is the bank header; a bank is two waves. ⟨disc⟩

  • "a music bank's two waves might be intro + loop, two variations, or two halves" → they are two stems of one performance, played together — equal duration in 32/32 banks, and sample-synchronous. structures/bgm-two-stems.md ⟨disc⟩

  • "BGM_106BGM_109 break the two-wave rule" → they are the leading-region straddle; realigned across entry boundaries they obey it. ⟨disc⟩

  • "the cue table names which BGM belongs to which screen" → all 32 BGM cues are numeric (BGM_001BGM_109). ⟨disc⟩

Units, weapons, effects and assets

  • "Generic (394) is the unit datasheet" → refuted. ⟨unrecorded⟩
  • "a loadout's Arm1 names an item" → it names a hardpoint slot (Turret_NNN), 59/59. ⟨disc⟩
  • "EnumUnit and the unit datasheet share a vocabulary" → they do not. ⟨unrecorded⟩
  • "the roster is the Generic.Model set" → roster 40, Generic.Model 46, GameResourceID 480 — three vocabularies. ⟨disc⟩
  • "every unit ID is UN_<l>###_<FACTION>_<name>" → the grammar is UN_<letter>###_[<subkind>_]<FACTION>_<name>. ⟨disc⟩
  • "_EXn is the Extra0n index" → three different EX vocabularies exist. ⟨unrecorded⟩
  • "the only two _EX5 names on the disc are the AA gun and the DeltaSaber" → refuted. ⟨unrecorded⟩
  • "running the tutorial will instantiate the _Ttrl weapons" → refuted. ⟨unrecorded⟩
  • "the disc has exactly three EnumWeapon tables" → four. ⟨unrecorded⟩
  • "the wep_NN package gaps are unshipped weapons" / "wep_85 is the tip of a family" → wep_85 is the only declared-but-unshipped asset (59/0/1/26). ⟨disc⟩
  • "nothing is deployed without being declared" → refuted. ⟨unrecorded⟩
  • "effects are one namespace" → refuted. ⟨unrecorded⟩
  • "the 58 undeclared effect names are missing assets" → refuted. ⟨unrecorded⟩
  • "all five orphan effects are unshipped" → refuted. ⟨unrecorded⟩
  • "eff_f0002 ships in Base.xpr" → refuted. ⟨unrecorded⟩
  • "Base.xpr holds more bound effects than ptc_pack" → refuted. ⟨unrecorded⟩
  • "the 34 unlocated are a scatter" → refuted. ⟨unrecorded⟩
  • "the 9 unlocated might be under another prefix" → refuted. ⟨unrecorded⟩
  • "ptc_pack has 532 names" → 727. ⟨unrecorded⟩
  • "the _e/_f law is effect-FIELD-specific" → it is the faction law, 564/564. ⟨unrecorded⟩
  • "a disc-wide .xpr byte search can show an effect is ABSENT" → it cannot. ⟨unrecorded⟩
  • "rot_n001 is on the disc" → refuted. ⟨unrecorded⟩
  • "rou_f004's mesh is in Stage_S28.xpr" → it is in DeltaSaber_A.xpr. ⟨unrecorded⟩
  • "parent + _all + _child is the composite-model convention" → refuted. _hangar is real (59 of 166, 59/59 with a bare twin); _all/_child is not. ⟨disc⟩
  • "Motion_guard_start has no damage variants" → refuted. ⟨unrecorded⟩
  • "CoverArea bits 2 and 3 are mutually exclusive" → refuted. ⟨unrecorded⟩
  • "the 27 unresolved NamePlate values are missing objects" → refuted. ⟨unrecorded⟩

LOD, background and misc tables

  • "EnumLODSet_* is a per-stage family" → EnumLODSet_test.tbl serves 17 stages; 17+5+1 = 23. ⟨disc⟩
  • "there are 8 orphan LOD tables" → 6. ⟨unrecorded⟩
  • "the orphans are stale copies of _test" → refuted. ⟨unrecorded⟩
  • "S25 is absent from the DefTables LOD families" → refuted. ⟨unrecorded⟩
  • "BackGroundID has no referent anywhere" → it is an identity. ⟨unrecorded⟩
  • "BackGroundPackage == BG_<id>.xpr" → refuted. ⟨unrecorded⟩
  • "<X>ID + <X>Package is a convention" → refuted. ⟨unrecorded⟩
  • "Placement_* / RouteTest_* are unattached" → refuted. ⟨unrecorded⟩
  • "the AsteroidDefinition join does not reproduce by hash" → it does. ⟨unrecorded⟩
  • "the 8-value frame is a new finding" → it was already in the corpus. ⟨unrecorded⟩

Loaders, config and tuning

  • "the config reader is XML" → INI. ⟨unrecorded⟩
  • "sub_822F9498 is the unit-definition loader" → it is PlayerParams's. ⟨unrecorded⟩
  • "sub_822AE628 reads the main-game Tweak" → refuted. ⟨unrecorded⟩
  • "sub_8230D1F8 is a rank table" → it is the stage-settings loader. ⟨unrecorded⟩
  • "sub_82286BC8's key list is new" → refuted. ⟨unrecorded⟩
  • "sub_825F2CF0 / sub_825F2F88 read a post-processing table" → refuted. ⟨unrecorded⟩
  • "Booster is a new schema" / "Booster is the player craft's flight envelope" → refuted; nothing selects Booster. ⟨unrecorded⟩
  • "the AnalogRevice/Tweak block is unreachable" → reachable (sub_821A6CF0, base 0x820A1630). ⟨unrecorded⟩
  • "a 0-xref string block has no reader" → refuted. ⟨unrecorded⟩
  • "the AI table was NEEDS-HUMAN" → refuted. ⟨unrecorded⟩
  • "the PG* HUD names are undocumented" → they are documented. ⟨unrecorded⟩
  • "a base-solver row identifies a FUNCTION" → it does not. ⟨unrecorded⟩
  • "a 64K-boundary base is low confidence" → inverted; it is high confidence. ⟨unrecorded⟩
  • "the 0x820B0000 cluster is a false positive" → refuted. ⟨unrecorded⟩
  • "a pointer to a function in the image implies a registry" → refuted. .pdata is not a registry. ⟨unrecorded⟩
  • "the 13 player-facing chatter tables are the WINGMAN tables" → refuted. ⟨unrecorded⟩
  • "the 8 undeclared chatter tables are tutorial chatter" → refuted. ⟨unrecorded⟩
  • "other datasheets ship a schema too" → refuted. ⟨unrecorded⟩

Encoding and text

  • "every IDXD string value is ASCII" → 6 non-ASCII values of 99 328. ⟨unrecorded⟩

  • "文字列 is a dev placeholder" → they are Shift-JIS type words. ⟨unrecorded⟩

  • "the splash _eff glows hold a constant α ≈ 33, contradicting their declared 255 plateau" → mine, and refuted within the iteration. They ramp 34 → 255 in exact steps of 34. I had printed the series' minimum and read it as its range. ui-keyframe-time-unit.md ⟨disc⟩

  • 🟡 "the declared keyframe timeline reproduces the captured splash" — our reader disagrees (was before the R1 pass). palogo_gamearts is still at a=255 nine frames after its declared a=32, and its declared 80-frame fade-in is never drawn. The capture half is sound; "declared" is not — it is whatever our keyframe reader said at the time, and that reader has since changed: the record-layout fix re-times a group's final pose (block 4 went to t = 80 / 74 / 269). The _eff glows do reproduce exactly, so this is about the group timeline, not the interpolation law. To settle: re-derive the declared timeline under the fixed record layout and re-compare against the same frames. ui-keyframe-time-unit.md ⟨our-reader⟩

  • "the _eff elements' agreement is the whole case for the keyframe-time shift, so it stays a shape argument" → superseded. The hold duration is calibration-free and decides it: observed 83 frames of full alpha against a predicted 2.0 as decoded and 80.0 shifted. The shift is nonetheless not adopted — it moves GP_TITLE build 7 by 13 % of pixels, away from its verified English twin's brightness. ui-keyframe-time-unit.md ⟨capture⟩

  • "the GP_TITLE build 7 render difference is evidence against the keyframe-time shift" → mine, and withdrawn. It is one element, ptlogo_eff3.t32, a transient bloom with no resting pose; rest()'s dwell fallback returns a different endpoint of the same movement under each reading. The brightness comparison measured our heuristic, not the decode. structures/ui-resting-pose.md ⟨screen-render⟩

  • "rest()'s longest-dwell fallback picks the pose the element rests at" → refuted structurally. A dwell gap is time spent interpolating between poses; an endpoint is only held when the two poses are equal, which is a plateau, which the earlier path already returned for. Every element that reaches the fallback has a guessed rest pose. ⟨reasoning⟩

  • 🟡 "rest() for a plateau-less element should be the last keyframe" — our renderer disagrees (was before the R1 pass). The developer splash's three sibling glows are structurally identical and differ by one byte (a=212 vs a=255 at t=45); that rule makes palogo_anima_eff alone invisible while gamearts_eff and seta_eff stay lit. Capture box-mean ratios (0.717 / 0.723 / 0.772) go the other way too. ⚠️ This entry and its re-refutation below both run through our renderer and they disagree — see the rest() pair note in the reading guide. Neither direction has a non-renderer instrument. To settle: a draw capture of the developer splash naming which of the three glows is submitted at rest. structures/ui-resting-pose.md ⟨render-vs-capture⟩

  • "a keyframe scale of 0 means unset, so render at 100 %" → refuted by a disc-wide control. 2 166 elements have a zero-scale keyframe and not one is zero on every keyframe, while 1 762 grow back out of zero (ptlogo_eff3.t32 runs 0 % → 200 %). Zero means collapsed; the renderer now draws nothing. structures/ui-rat-layout.md ⟨disc⟩

  • "a Japanese-locale capture is impossible in this container, because canary has no user_language cvar" → mine, and refuted the next iteration. The cvar really is absent, but the language is persisted in <storage_root>/xconfig.settings (user.language, BE u32 at file offset 0x912, located from three struct landmarks) and that file is writable. The capture is still not taken — a Japanese run never reached the title in 787 s — but it needs a longer run, not a rebuilt emulator. tools/re-capture/set_console_language.py ⟨canary-source⟩

  • "the Japanese-locale run never reached the title in 787 s" → the measurement was broken, not the run. wait_title.sh carried the superseded single-pixel oracle. Re-run with is_title.py: the game still did not present the interactive title, but that is now a measured statement (zero green-glyph pixels, correlation ≤ 0.22 to either build-7 render) rather than an artefact. ⟨harness⟩

  • "the Japanese-locale run fails to reach the interactive title because of the locale" → refuted by the English control. 75 samples over 734 s with the same flags and oracle, every one glyph = 0. Neither locale presents the interactive title without a pad press. ⟨control⟩

  • "neither locale reaches the interactive title without a pad press" / "the game sat in the attract loop for 604 s" → withdrawn as causes. Both rest on runs whose polling loop sampled every ~41 s, because screenshot costs 10.8 s while the emulator runs (0.117 s idle, 92×). A title lasting a few seconds would be missed. The observations stand; the conclusions drawn from them do not. capture-harness-status.md ⟨harness⟩

  • "the boot harness fails because its polling loop samples every ~41 s, slower than the title screen lasts" → mine, and refuted by my own fix. The sampling defect was real (3.98 s → 0.29 s per sample, 13.7×, control-verified at 753/327), but a probe running at 3.99 fps for 420 continuous seconds — 1 674 samples — still saw zero green-Ⓐ pixels. Sampling rate was not the cause. capture-harness-status.md ⟨harness⟩

  • 🟡 "neither locale reaches the interactive title without a pad press" — our harness disagrees (was reinstated as before the R1 pass). 1 674 dense samples over 420 s, English, zero glyph frames. ⚠️ Reach: a mid-run window only; it says nothing about the boot title. 🔴 And the entry two below withdrew a sibling negative — 2 391 frames, same probe — because a long-lived x11grab stream degrades to 1.60 fps and then repeats one stale frame. That withdrawal was written after this reinstatement and never reached it. A dense negative from a stream that may be frozen is not a dense negative, and this run used the same instrument for a comparable duration. To settle: re-run with the stall cross-check the withdrawal describes (compare surface mean against an import grab mid-run), or sample with per-frame import rather than a persistent stream. ⟨harness⟩

  • "the PRESS Ⓐ plate appears only in the boot title window, which mid-run sampling could never catch" → mine, and refuted. The fast probe was attached at t=0: 2 391 frames over 600 s at 3.98 fps from launch, max glyph 0. The plate did not appear at any point in the first ten minutes. capture-harness-status.md ⟨harness⟩

  • "2 391 frames over 600 s from t=0, max glyph 0, therefore the title never appears in the first ten minutes" → withdrawn: the instrument stalls. A single long-lived x11grab stream degrades 3.98 → 1.60 fps and then freezes, repeating one stale frame; cross-checked, it read surface mean 5.21 where import read 125.65 at the same moment. A dense negative from a frozen stream is not a negative. capture-harness-status.md ⟨harness⟩

  • "the T8aD layer key fully determines a screen's paint order" → refuted, and the remainder is undecodable. Elements sharing a key are tied; on the title the game paints the five tied ptlogo_back2eff glows 1,2,5,3,4 while the declaration table, the RATC child order and every field in the T8aD header (exhaustive 0x000x7f, u8/u16/u32, both directions — 0 matches against 64 for the declaration-order control) all give 1,2,3,4,5. ui-paint-order-derived-check.md ⟨capture⟩

  • "SE audio is undecodable from the disc — no XACT container exists anywhere" (as it stood on the handoff page) → stale: menu-audio-cues.md had already retracted it and located three cues in Static.slb that decode to PCM. The retraction never reached the row the port agent reads. Handoff row fixed; tools/re-capture/handoff_lint.py now checks for this class. ⟨corpus⟩

  • 🟡 "which of 8AX and ptbase the game draws needs a per-draw capture recording texture base addresses" — our renderer is in the path (was before the R1 pass; it read "refuted — it is settled statically"). The two carry the same art at two resolutions, so neither compares usefully against a capture; their difference does. Correlating the capture's departure-from-upscale against the 8AX-only detail gives +0.0475 (main menu) and +0.0634 (title), both 68 % of ceiling against matched controls of ≤0.0095. The game draws the full-res 8AX. 🟡 Downgraded from by the R1 pass. The conclusion may well be right — the matched controls are real work — but the instrument is our decode correlated against a capture, and this decode changed underneath it: 8AX was later found not to be a name at all (see the ratc-child-names entry), which is a defect in the same reader that produced the compared texture. To settle: the per-draw capture the claim says is unnecessary — texture base addresses name the drawn surface directly, with no correlation. ui-8ax-fullres-background.md ⟨render-vs-capture⟩

  • "the pixel-pair ratio shows the capture is native, not an upscale" → mine, and withdrawn as evidence. Upscales give 0.000.72, native 0.98, capture 1.01 — but additive noise pushes any such ratio toward 1, and both "native + noise" and "bilinear upscale + noise" fit the observed values. The conclusion happens to be right; this test does not establish it. ⟨our-tool⟩

  • "the render-vs-capture gamma may be canary's own BT.709 output transform, since kernel_display_gamma_type = 2" → mine, and refuted from the source. That cvar is the value a kStub getter (VdGetCurrentDisplayGamma) hands the guest; the game builds its own ramp from it and canary applies the guest's DC_LUT ramp in the swap path. No emulator-side gamma post-process exists to subtract. 🟡 Whether this game installs a ramp at all is still unestablished. ui-render-tone-curve.md ⟨canary-source⟩

  • "the GPU trace produced nothing because either the CLI flag did not reach the cvar or BeginTracing() failed silently" → both wrong. The trace writer is compiled out: trace_writer.h gates it on #ifdef NDEBUG, so a release build has no writer at all. Confirmed with a control — the format string _stream.xtr appears once in the Debug binary and zero times in the Release binary run-canary actually uses. capture-harness-status.md ⟨canary-source⟩

  • "the T8aD +0x04 bit 0x02 means the sprite's name contains eff" → refuted, now on evidence. ptlogo_back2eff is an eff name with the bit clear; the attribution is confirmed by header-order pairing (18/18 on build 4) rather than by a size match, which cannot separate it from the same-sized ptlogo_back2eff5. All 10 bit-set sprites are eff names, so the implication runs one way only. ⟨disc⟩

  • "the bit 0x02 marks a transient element" → refuted. pteff03 and pteff03a carry the bit and run to t=250, ramping to a=255 and holding. ui-paint-order-key.md ⟨disc⟩

  • "bit 0x02 set ⇒ the sprite's name contains eff" (the one-way reading that survived the biconditional's refutation) → mine, and refuted disc-wide the next iteration. True 10/10 on GP_TITLE build 4; over 14 709 sprites it fails on 2 657 of 4 995 bit-set ones. P(eff|set) = 0.468 against P(eff|clear) = 0.144 — an association, not an implication. ui-paint-order-key.md ⟨disc⟩

  • "T8aD +0x04 bit 0x02 selects premultiplied alpha" → refuted. Premultiplied requires RGB ≤ A everywhere; over 170 decoded textures the flagged group violates it on a median 52.5 % of pixels against 30.2 % unflagged — both far from premultiplied, and the flagged group further. ui-paint-order-key.md ⟨disc⟩

  • "build-reborn test cannot terminate" → mine, and too strong; corrected the next iteration. It is heavy, not hung: 19 of 166 .xpr containers exceed 25 s, Stage_S02 completes in 144 s with rc = 0, and one full pass is ~4560 minutes. The 3 h 26 m observed was that work at a load average of 914, inflated by my own two duplicate runs. test-suite-runtime.md ⟨environment⟩

  • "the case for the keyframe-time shift rests on a single element" → no longer true. Three elements across two screens discriminate and all favour it: palogo_gamearts and palogo_seta hold full alpha 83 frames, palogo_sqex ≥77, against 68 predicted by the current reading and 80102 by the shifted one. The _eff glows fit both and argue against neither. ui-keyframe-time-unit.md ⟨capture⟩

  • 🟡 "an element with no held pose should be drawn as NOTHING rather than at a guessed endpoint" — our renderer disagrees (was before the R1 pass). Suppressing every plateau-less element and re-correlating against the live captures: title +0.9500 → +0.6839, main menu +0.9460 → +0.9037, EXTRAS +0.9440 → +0.9094. Worse on all three. ⚠️ "Drawing something scores better than drawing nothing" is weak evidence that the guessed pose is the right one: a wrong pose still puts roughly the right ink in roughly the right place, and a correlation rewards that. To settle: compare the guessed pose against the drawn one per element in a draw capture, not the whole screen. ⟨render-vs-capture⟩

  • "rest() guesses for 24.57 % of elements (3 807 of 15 493)" → mine, and overstated by 65 %. The plateau test marks a single-keyframe element as plateau-less because it has no adjacent pair — but its one pose is unambiguously its rest. 1 502 of the 3 807 are those; the genuinely ambiguous population is 2 305 (14.88 %). ui-resting-pose.md ⟨our-tool⟩

  • 🟡 "rest() for a plateau-less element should be the last keyframe → refuted by the sibling argument" — our renderer disagrees with the refutation (was before the R1 pass). Rendering under the rule and correlating against the live captures: publisher splash +0.9600 → +0.9982, developer splash +0.9643 → +0.9758. Making palogo_anima_eff invisible improves the match; the sibling symmetry was my expectation, not evidence. ⚠️ But "improves the correlation of our render" is the same instrument the sibling argument used, pointed the other way. The pair above and this one cancel; the question is open, not settled in either direction. To settle: as above — a draw capture, not a correlation. ⟨render-vs-capture⟩

  • "the port's exposure to the rest-guessing defect is 14 elements" → two. The fallback needs an element to be plateau-less and multi-keyframe; title, main menu and EXTRAS reach it zero times, the two splashes once each. ui-resting-pose.md ⟨our-tool⟩

  • 🟡 "the shifted time reading implies rest = the last keyframe, so the plateau rule can be dropped" — our renderer disagrees (was before the R1 pass; the blank splashes part is a renderer-internal fact and stands regardless). Applying it to every element collapses all five screens (title 0.9500→0.6819, main menu 0.9460→0.6416, EXTRAS 0.9440→0.5745) and renders both splashes blank. A group is entry → hold → exit and the exit is the screen's dismissal: a displayed screen sits at the hold, not at its final pose. ui-resting-pose.md ⟨render-vs-capture⟩

  • 🟡 "rest_plateau renders elements the game has already finished with" (as a general claim) — narrowed by its control, but the control is our renderer (was before the R1 pass). It holds on transient screens only: suppressing the finished glows takes the two splashes from 0.9604/0.9659 to 0.9982/0.9980, while the same edit costs the title 0.002, the main menu 0.092 and EXTRAS 0.107. A plateau mid-animation is evidence the element is held at that point in the timeline, not that it is on screen once the screen has settled — and where a screen does settle, the rule is right. To settle: which elements a settled screen actually submits is a draw-list question; read it off a capture rather than off a correlation delta. ui-resting-pose.md ⟨render-vs-capture⟩

  • "the group header's undecoded lead-in word carries a per-element start offset" → refuted immediately. It is 0x00000000 for all seven elements of the developer splash — glows and logos alike — while those two families are observed to run sequentially (frames 94115 and 116211) despite declaring overlapping times. ui-group-start-time.md ⟨disc⟩

  • "the splash elements share one clock origin" → refuted. Fitting a single origin needs f₀ ≈ 93.5 for palogo_gamearts_eff and f₀ ≈ 103 for palogo_gamearts, ~19 units apart, and aligning one throws the other off by ~9 frames at both ends. Durations match (97.8 %, 98.5 %); starts do not. ⟨capture⟩

  • "the glows and logos might overlap and my size-grouping merged them" → tested and refuted. Across all 235 captured frames, zero contain both a glow and a logo; f110115 draw two glows and f116 onward two logos, with no transition frame. The sequencing is real. ⟨capture⟩

  • "a bundle's declared elements are what the screen shows" → refuted. Entry 11 declares three logo/glow pairs and only two are ever drawn — palogo_anima gets 0 frames against palogo_gamearts's 95, from byte-identical keyframe times. (Reach: within the capture's frames 1214.) ui-group-start-time.md ⟨capture⟩

  • "the glow and logo phases are one bundle with elements selectively activated" → mine, and withdrawn as unestablished. The alternative — two compositions shown in sequence — fits equally. The texture-base test fails its control: the publisher splash is a different bundle and shares the base 0x11C30000, so that address is a reused upload slot, not a bundle identity. What survives is that declared elements ≠ drawn elements. ui-group-start-time.md ⟨control⟩

  • "two compositions shown in sequence" (as the alternative to selective activation) → refuted statically. It requires a bundle declaring the glows without the logos; no such bundle exists. Only four GP_TITLE entries carry palogo elements, and both developer entries declare all six logos and glows — so whichever was active, a subset of its elements was drawn at a time. Selective activation is reinstated on evidence. ui-group-start-time.md ⟨disc⟩

  • "the splash's measured_paint_order records a front-to-back depth order" → mis-typed; between its glow and logo halves it records only the temporal order they were seen in."that refutation is itself refuted (same day). The vector is a read of the runtime child array (ui-screen-runtime.md: "paint order (child slots)"), not of the draw capture, so co-occurrence does not bear on it; and the halves carry distinct T8aD layer keys (0xa100 < 0xa110, paint_order_audit: 0 same-key ties), so the file orders them regardless. The no-overlap measurement was correct; the inference from it was not. What survives: a capture of this screen can only cross-check the order within each half. ui-prm-primitives.md ⟨our-reader⟩

  • "8AX is the name a T8aD is registered under" → it is not a name at all. It is three bytes of the preceding record's payload (38 41 58) that happen to be printable ASCII, which our backwards printable-run scan preferred over the name the format actually states in its opt block. The claim sat in HANDOFF.md and ui-8ax-fullres-background.md as though 8AX were a real identifier, and cost every menu screen its full-resolution background. ratc-child-names.md ⟨disc⟩

  • "pmbase.t32 is on the disc nowhere" (the one dangling asset behind 10 144 of 10 148 references resolve) → withdrawn; it is on the disc. It is the GP_STAGE_CLEAR child the same scan named 8AX. With the name decoded the count is 10 148 of 10 148. ratc-child-names.md ⟨disc⟩

UI timing (2026-08-29)

  • "a screen has SETTLED at its rest.t" → refuted. rest.t is the last hold keyframe before the exit, not the end of motion. Build 4's ptlogo1 rests at t=251 and stops moving at t=42; the title's visible build-in ends at t≈118, where pteff01, pteff02.prm and ptlogoall_eff end their ramps together. Believing rest.t put a port's plate 3.97 s late — title-plate-delay-measured.md. ⟨disc⟩
  • "the PRESS Ⓐ plate is composited a measured 2.13 s after the title settles, and the port should author that" → the measurement stands, the instruction was refuted by the port. Build 2 has a keyframe group of its own; both builds run on one clock started together and the plate's declared t=238 supplies the timing, so nothing is authored. 238 118 = 120 units = 2.000 s, of which 2.13 s was a wall-clock reading stretched by Canary presenting at ~28.1 fps. ⚠️ General lesson: a wall-clock duration off this emulator is ~6 % long, so a measured interval that lands near a round number of units probably is that number of units. ⟨disc⟩
  • "a music bank has three sub-waves" → refuted; it was our reader. The third is the bank header, emitted because to_xma_riffs derived a leading packet stream's start as first_riff % 2048 — valid only for a header shorter than one packet. 28/28 disc-wide — structures/slb-bank-header-not-a-wave.md. ⟨disc⟩

The oracle harness and the container (2026-08-29)

  • "the decoder container has no disc" → refuted the same day. The container was replaced and /disc is a real 6.2 GB read-only mount. Worse, both instruments behind the claim were blind to the answer either way: find / -xdev cannot cross into a bind mount on another device, and sylph-doctor only checks /work and never $SYLPHEED_DISC. "sylph-doctor agrees" was two instruments sharing one blind spot. → To test for the disc, ask the variable that names it: sylpheed-cli screen list "$SYLPHEED_DISC/dat/GP_TITLE.pak". ⟨environment⟩
  • 🟡 "the main menu returns to the title on its own after ~810 s idle" — our renderer is in the path (was before the R1 pass). The menu sat untouched for ≥ 60 s without moving (correlation never leaving 0.92450.9249). The ~810 s idle is real but belongs to the title. This was the only reason "Ⓑ leaves the main menu" was classed as authored. ⚠️ Here the renderer is a fixed yardstick and a defect in it biases every sample equally, so the reading is more robust than the other render-vs-capture rows — a return to the title would move the correlation far outside a 0.0004 band. It is 🟡 rather than only because a renderer blind spot is still invisible to it. To settle: cheap — compare consecutive captures to each other. ⟨render-vs-capture⟩
  • "whole-image statistics (green / white / mean) can tell the title from the attract movie" → refuted. A frame of ADV.wmv with a bright green laser reads green 0.0018 / white 0.086 / mean (53,67,76) — the title's numbers. A probe built on it tapped Ⓐ into the movie and waited 120 s for a menu that was never coming. → Correlate against a committed capture instead, and keep movie frames as the negative controls. ⟨control⟩
  • "a 360-bin angular cross-correlation can measure the focus ring's rotation angle" → refuted by its own control: a synthetic 30° rotation of a live frame came back as (peak 0.596), while 90/180/270° came back exactly (peak 1.000) — it only resolves exact pixel permutations. No angle was quoted; the spin was established from brightness conservation instead. ⟨control⟩
  • "a latency read off a classified x11grab stream is a duration" → refuted. At 1503 ms per classification against an 8 fps stream the consumer ran at 0.64 fps, so frames were stale and increasingly so. Four "durations" died with it. The tell was that a screen transition, a button press and a plate fade all came out at ~2025 s. → A backlog preserves ordering and destroys durations; check consumed-fps against requested-fps before quoting a time. ⟨harness⟩

UI timing and transitions (2026-08-30)

Seven claims died this session. Each was recorded in its own page at the time, and none of them reached this file — which is the one the brief says to grep before proposing anything. A refutation that lives only where it was made is not reachable by the person about to repeat it.

  • "the fade-OUT duration is not in the file — the port must author it" → mine, and wrong in every sentence. The record-layout fix times a group's final pose, so block 4 carries t = 80 / 74 / 269: the ramp is decoded at 10 / 10 / 8 units. The section asserting this stood 78 lines above its own correction, in a heading, telling the port to author a decoded value. screen-transitions.md ⟨disc⟩
  • "the ~14 units the fade-out does not account for are a black HOLD" → mine, arithmetic that fit. Measured: the content elements' own fade-outs, starting six frames before the quad's ramp. screen-transitions.md ⟨capture⟩
  • "the black interval between screens is a LOAD" → mine, refuted three ways. Bundle size runs backwards (the 12.3 MB screen gaps 0, the 7.0 MB one gaps 3); the gap is 3 frames in three independent runs; and press-to-change latency moved ~12 frames between those runs while the gap did not move at all. screen-transitions.md ⟨capture⟩
  • "Ⓑ has no black interval" → mine, one screen pair generalised. EXTRAS → menu via Ⓑ gives two completely empty frames. screen-transitions.md ⟨capture⟩
  • "ptloop01/ptloop02 do not free-run on the settled title" → mine, measured over the wrong rectangle. The parent's (441,270) 200×90 is a pivot anchor; the leaf sweeps a 400 px quad whose left edge travels 639…1521. The zero was measured in a dead zone. structures/ui-resting-pose.md ⟨disc⟩
  • "the game runs the splash dwells ~8.5 % long" → mine, and it was one element's visible span read as the screen's. The _eff glow is lit from t≈0 while the logo is still transparent, so the screen's visible span is the full group. Six ratios recomputed to a mean of 1.0146 with one below unity. boot-order-and-splash-dwell.md ⟨capture⟩
  • "EXTRAS can supply only one transition measurement — a structural limit" → mine, and refuted by one screen info. Build 6 declares three buttons (ptbtn11/12/13, kind 0x3002). ⚠️ sylpheed-port had copied this sentence out of a message into their own record as an established fact while holding the file that refuted it. data/fade-four-transitions.txt ⟨disc⟩
  • "the black gap is determined by the OUTGOING screen" → mine, superseded twice. The same origin gives 0 and 1 to different destinations; every repeated pair is identical across five replicates. The pair determines; the origin only constrains. data/fade-four-transitions.txt ⟨capture⟩

The JP title might not draw the sweep leaves at rest — REFUTED (2026-08-30, mine)

  • "the JP title does not draw the sweep leaves at rest" — refuted, see below. ⟨capture⟩
  • "build 7's denser logo stack occludes the sweep leaves" — refuted, see below. ⟨capture⟩

I hypothesised that build 7's denser logo stack (katakana + crystalline burst) occludes the two sweep leaves, to explain why two JP title captures differ by RMSE 0.32 inside the adjudication box while two EN captures a plateau-phase apart differ by 11.9. A draw capture in ja (control: the same extraction on the EN title log) shows the same three tall ROT strips, same dimensions, at HIGHER alpha than English — 180/188/194 vs 160/168/166. There is no absence to explain. data

The 0.32 had a different cause: my own gate. See below.

"Two sessions sample a free-running clock" — REFUTED (2026-08-30, mine)

  • "a free-running clock lands somewhere else on a fresh boot" — refuted, the gate phase-locks it. ⟨capture⟩
  • "the in-box capture noise of 0.32 between sessions" — refuted as a noise floor; it measures the trigger. ⟨harness⟩

jp-title-at-rest.txt justified a second capture as probing the between-run axis "where a free-running clock lands somewhere else on a fresh boot", and reported its in-box 0.32 as capture noise. Measured at the shutter instant, the sweep strips sit 2526 px apart across two runs in different locales and different sessions — 1.6 % of a ~1600 px traverse. The plate pulse is part of the animation, so gating on it phase-locks the shutter. 0.32 is a lower bound produced by the instrument, not a property of the game; the honest figure at an arbitrary phase is 11.9. The era adjudication is unaffected — its margin, 16.72, clears even 11.9. details

Refutation attempt on sylpheed-port THE CLAIM SURVIVED (2026-08-30)

Target: the port's rejection of a positional mechanism, resting on 98 % of off-edge area matching exactly with a residual of ±12 levels inside lit logos.

My attempt: if the sweep leaves' ink crosses the logos, that residual could be sweep ink our renderer omits — and phase-locking would have made it look stable across sessions rather than exposing it.

Result: refuted, the claim stands. jp-title-at-rest.txt has five frames ~1.5 s apart within a run — not gated individually, so genuinely different sweep phases — and the 350×396 logo ROI is byte-identical across all of them (0 / 138 600 px differing, max |d| 0), reproduced in two independent sessions, while 58 % of the whole frame moves as a contrast control. The sweep ink does not land on the logos. The ±12 residual is not sweep.

Music-bank stems (2026-08-30)

  • "wave 1 is wave 0 put through a filter" refuted on BGM_103 by magnitude-squared coherence. A real linear filter of wave 0 reads 0.930.94 in every band (positive control); the measurement reads 0.027 at 14 kHz. No linear filter does that in a band where both waves carry energy. data ⟨audio-analysis⟩
  • "the rear-pair reading can be tested by coherence" refuted, and it was my own test's premise. The control that matters — L vs R within one wave, genuinely one performance in two channels — reads only 0.2210.497, so in this material "same performance" does not imply high coherence. A 4-channel mix's rear pair is not a linear filter of its front pair, so the discriminator never had the power to separate the two readings. The 🟡 stands. ⟨control⟩

Refutation attempt on the corpus's "two stems of ONE PERFORMANCE" — 🟡 SURVIVED, WEAKENED (2026-08-30)

Target: structures/bgm-two-stems.md (the BGM_103 section is another agent's), which reads the two waves as two stems of one performance.

My attempt: if they are one performance, they should share signal structure; coherence should be well above the independent floor across the bands carrying the music.

Result: the claim survives, but one of its supporting readings is dead and the bands carrying 96 % of the energy read 0.169 and 0.184 — far above the 0.001 independent floor, so not independent, and far below a filtered copy. "One performance" stands; "rear pair, i.e. a filtered view of the same mix" does not.

Refutation attempt on sylpheed-port's band-energy check — SURVIVES, with a measured caveat (2026-08-31)

Target: their replacement for a disqualified difference-signal path — "band energies need no alignment", with transcodes matching their sources to 0.66 dB worst-case and an unrelated movie landing at 1920 dB.

My attempt: if band energies are genuinely alignment-free, a signal against a misaligned copy of itself must match as closely as against itself.

worst band
w0 vs itself 0.00 dB
vs itself shifted 1 s (misaligned, same content) 0.16 dB
vs itself shifted 10 s 1.00 dB
vs a different bank (BGM_104) 5.28 dB

The claim survives. A 1 s misalignment costs 0.16 dB, well inside their 0.66 dB pass band — alignment-insensitive as advertised, which is exactly what makes it the right instrument where a lag search failed.

⚠️ Two caveats it is worth them having. It is not literally alignment-free: at 10 s the figure reaches 1.00 dB, because a fixed analysis window covers different material once the shift is large relative to it. And the separation margin is material-dependent — two unrelated music banks separate by only 5.28 dB here, against the 1920 dB an unrelated movie gave them. A 0.66 dB threshold has an 8× margin against that floor rather than a 30× one, so the safety of the threshold depends on how different the chosen known-negative is, not on the method. data

Refutation attempt on sylpheed-port's extras/initial_focus: ptbtn11 SURVIVES (2026-08-31)

Target: their statement that EXTRAS keeps ptbtn11 and is "correct under the surviving reading" — i.e. that a submenu resets to the item it opens on, and that ptbtn11 is that item.

My attempt: the oracle shows EXTRAS opening on MISSION SELECT, the first of three. So their value is right only if ptbtn11 is the top button on that screen. Checked against the disc, with the main menu as a control (examples/extras_button_order.rs):

buttons top to bottom
control — main menu (entry 5) ptbtn01 y162, ptbtn02 y242, ptbtn03 y322, ptbtn04 y401, ptbtn05 y482 → top is ptbtn01 = NEW GAME
EXTRAS (entry 6) ptbtn11 y282, ptbtn12 y362, ptbtn13 y442 → top is ptbtn11

The claim survives, and the control confirms the ordering rule reproduces a screen whose answer is independently known.

Refutation attempt on sylpheed-port's BGM_103 exclusion — SURVIVES, and is stronger (2026-08-31)

Target: their audio.json rests P6's most important value on three legs, two of which they found to be a single disc-to-runtime comparison. The legs stand only if the disc census excludes alternatives — they measured "of 32 readable BGM_* banks, exactly one carries waves of that size".

My attempt: re-derive the exclusion from the committed census (data/bgm-wave-census.txt, produced by my own tool rather than their reader).

census rows 32
banks carrying both 3 876 864 and 3 930 112 1BGM_103.slb
banks carrying either size 1BGM_103.slb

The claim survives and the exclusion is tighter than they stated: no other bank carries either wave size, not merely not both. Their third leg is genuinely discriminating.

"T8aD +0x08 selects the frames' blend mode" — MY OWN candidate, refuted twice (2026-08-31)

+0x08 = 0x8050 is the one header word where ptframe1 and ptframe2 agree on a value no other main-menu sprite takes, and it was the only candidate the declaration entry left. It is dead on two independent grounds.

  1. Disc-wide — 38 sprites carry 0x8050, only 8 of them named *frame*, and the high byte tracks the archive: 0x80xx in GP_TITLE, 0xb1xx in GP_OPTIONS, 0xd8xx in GP_GAMEOVER, 0xf0xx in GP_DIALOG. An atlas word.
  2. On the second screenEXTRAS puts pteff21, pteff22 and pteff23 on 0x8050 alongside ptframe3/ptframe4, so it does not even separate the frames within one bundle. data/frame-blend-field-hunt.txt.

⚠️ And the wider negative it belonged to is now superseded in its conclusion: the mode is real and is additive, measured off the GPU (structures/ui-blend-mode-measured.md). The disc-side reach stands; what died is the instruction "any blend you choose is authored".

Refutation attempt on sylpheed-port's frame sharpener — REFUTED (2026-08-31)

Target: "neither frame has a single fully-opaque pixel, against ptbase's 99.1 %. For a wholly semi-transparent overlay the blend equation decides the output" — offered as what makes the frames special and why the draw-path route looked live.

My attempt: an alpha census of every T8aD sprite on both screens (examples/frame_alpha_census.rs, data/menu-sprite-alpha-census.txt).

sprite max alpha fully-opaque pixels the port's own accuracy
ptbase 255 99.1 % 1.31×
pteff10 130 0 nearly exact
pteff12 / pteff20 142 / 218 0 not flagged
pteff2123 200 0 not flagged
ptframe1 / ptframe2 173 / 174 0 too dark

The premise is true and it is not the discriminator. pteff10 has no opaque pixel either and renders accurately, so "wholly semi-transparent" does not separate the four frames from anything.

⚠️ What their conclusion did NOT depend on it, and survives: the draw path was the right place to look, and it answered — the frames are drawn additive, exactly as their own two-background composite solve had ranked them. A wrong reason attached to a right direction; only the reason is refuted here.

Menu navigation and input (2026-09-12)

  • 🟡 "a held direction moves the cursor exactly once — no auto-repeat" (data/nav-autorepeat-and-settled-b.txt, 2026-08-30) — its own instrument disagrees with itself. --hid=file's GetKeystroke() is written to deliver exactly one event per held press, by explicit design ("scripted input wants precisely one event per press, and repeat is what makes menu steps overshoot" — file_input_driver.h), and input-pad-read-path.md already found the game reads menu input through this same Keystroke API. A driver built to prevent repeat cannot be evidence the game doesn't have it. The counter's own control (a single tap gives exactly 1 spike) proves the counter works; it says nothing about the driver it was counting through. Complication, not a clean reversal: the same driver's GetState() holds a button continuously with no edge-suppression, and pad.py's own docstring — written by an earlier session driving this exact tool — warns that a longer dpad hold "auto-repeats and overshoots," which is a claim of an observed effect through this driver, not a hypothetical. The two do not agree. To settle: trace C_PAD_RINGBUF's producer (keystroke ring vs. polled state) — no emulator needed — or re-run with a repeat-capable file driver and read cursor position off the draw log per frame, not a coarse screen-diff. f1-no-repeat-was-the-harness.md ⟨harness⟩