From b9aca6a2d989cd08627768398f33217d098f5e74 Mon Sep 17 00:00:00 2001 From: sylph-decoder Date: Sat, 29 Aug 2026 10:42:47 +0000 Subject: [PATCH] re: the decoder container has no disc -- root-caused to the volume migration find / -xdev turns up no ISO, no default.xex and no GP_TITLE.pak; /exchange is empty; SYLPHEED_DISC is unset; sylph-doctor agrees. Everything else in the container is healthy -- xenia_canary is built, :98 is up, screenshot works, Vulkan enumerates. There is simply no game to boot. The cause is in the launcher. Before 06676d3, sylph-agent bind-mounted the human's working tree at /work, and the ISO and sylph_extract/ live in that tree, so the disc arrived incidentally with the repository mount. 06676d3 replaced that with `-v sylpheed-decoder-repo:/work` -- correct for the collision class it was written for -- and nothing was added to replace the disc. sylph-decoder still forwards SYLPH_ISO, but as a bare environment variable naming a host path that does not exist inside the container. sylph-port mounts the disc explicitly, so the one container that owns the disc and the oracle is the one without them. This shuts the oracle, every sylpheed-cli call that names a pak, the disc-gated tests, and -- because the XEX is on the disc -- the static PPC route too. It does not touch the committed corpus, which is what this iteration worked from. A second, smaller casualty of the same migration: no git identity is configured anywhere, so the first commit in a fresh container fails outright. Both are recorded with their fixes; neither is worked around, since the launcher runs on the host and this container cannot restart itself. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_013UxPvE5cz7zekXBKi7Xw2r --- docs/port/HANDOFF.md | 28 ++++++ docs/re/INDEX.md | 3 +- docs/re/capture-harness-status.md | 136 ++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 1 deletion(-) diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index b69d0aef..734d6065 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -23,6 +23,24 @@ There is no fourth kind. If a row says *measured* or *undecodable*, the port is human can see it is a human decision, so that when it is later decoded the authored version can be deleted. +## πŸ”΄ 2026-08-29 β€” the decoder container has no disc, so nothing here can be extended right now + +`find / -xdev` finds **no ISO, no `default.xex` and no `GP_TITLE.pak`**; `/exchange` +is empty; `sylph-doctor` agrees. Root cause is in the launcher, not the disc: +`06676d3` moved `/work` from a bind mount of the human's working tree (which +*contained* the ISO and `sylph_extract/`) to the agent's own named volume, and no +disc mount was added to replace it β€” `sylph-decoder` still forwards `SYLPH_ISO` as +a bare environment variable with nothing bind-mounted behind it. `sylph-port` +mounts the disc properly, so **only the decoder is affected**. + +**What that means for you:** every row below still stands β€” they are already +written down with their evidence, and `docs/re/captures/` (99 MB) and +`docs/re/data/` (2.5 MB) are in git. But until a human adds the mount, the decoder +cannot boot the oracle, cannot run `sylpheed-cli` against a pak, cannot run the +disc-gated tests, and cannot disassemble the executable. **Do not wait on a new +measurement.** Full diagnosis and the one-line fix: +[`capture-harness-status.md`](../re/capture-harness-status.md#-2026-08-29--the-disc-is-not-in-the-decoder-container-at-all). + ## Status | | Question | State | Answer / link | @@ -900,6 +918,7 @@ here until 2026-08-28 and is now settled.) | 🟑 | **the paint-order tie-break** (Q3) | eight candidates refuted; costs one element's blend on one screen | | 🟑 | **GamePart ids behind the buttons** (Q4) | the *screens* are measured; the ids are a name match onto the executable's class names | | 🟑 | **the boot transitions in code** (Q6) | both levels decoded β€” phase at `this+132` (`entryβ†’2`, `2β†’0`, `2β†’3`, `3β†’4`, `4β†’2`) and state at `this+136` inside phase 4. Phase 0 = splash (`LOGO`), phase 2 = title + `PRESS β’Ά`, phase 4 = menu. Unknown: what the event *numbers* mean | +| 🟑 | **β’· leaving the main menu** (Q5) | **downgraded 2026-08-29.** The behaviour was seen once, with no capture, and the main menu is the only screen whose footer does not advertise β’· β€” measured, **0** red-β’· glyph pixels in the whole frame on two captures, against 514/518 on `EXTRAS`/`DIFFICULTY` with the same detector. An ~8–10 s idle also returns to the title, and nobody has separated the two. Implement it (it is the only exit) but treat it as **authored** β€” [`menu-navigation-semantics.md`](../re/menu-navigation-semantics.md#-refutation-attempt-2026-08-29--the-main-menus-own-footer-does-not-advertise-β“‘) | | ❔ | **builds 0/1 and 10/11**, the `DELTASABER` plates (Q2) | never seen anywhere in the boot path, the title-side screens or the attract loop. A mission load is the remaining candidate and this container kills runs before one completes | (An earlier version of this table called the audio items blocked on "an emulator @@ -912,6 +931,15 @@ box sitting at ~1 GB free with swap exhausted. Dynamic experiments here have to fit in roughly two minutes of guest time, which is why several of these residuals are unfinished rather than unattempted. +## The player's-eye map of the menus + +[`docs/game/navigation.md`](../game/navigation.md) is the screen-by-screen walk +through the game from the chair β€” every label, what the cursor does, what each +footer offers. It was filled in on 2026-08-29 from the committed oracle frames, +and it is the page to read if you want to know what a screen *looks like* rather +than how its bundle is laid out. Every βœ… there is a capture, and what is still ❔ +is what no capture answers. + ## Reference data Committed alongside the findings, so the port can be built without a disc in the diff --git a/docs/re/INDEX.md b/docs/re/INDEX.md index fc5177e8..2f00d97d 100644 --- a/docs/re/INDEX.md +++ b/docs/re/INDEX.md @@ -147,10 +147,11 @@ files, which is how the same ground got covered twice. | [`structures/unit-struct-runtime.md`](structures/unit-struct-runtime.md) | Runtime `Unit` struct (craft / vessel definitions) β€” read from live guest memory | β€” | | [`structures/weapon-struct-runtime.md`](structures/weapon-struct-runtime.md) | Runtime `Weapon` / `Shell` structs β€” read from live guest memory | β€” | | [`structures/xbg7-mesh.md`](structures/xbg7-mesh.md) | XBG7 β€” mesh geometry (inside XPR2 model containers) | β€” | +| [`capture-harness-status.md`](capture-harness-status.md) | Why the harness stops reaching the title β€” and, since 2026-08-29, why there is no oracle at all | πŸ”΄ **the decoder container has NO disc**: no ISO, no XEX, no pak anywhere on the filesystem. Root-caused to `06676d3` moving `/work` to a named volume without replacing the disc mount; `sylph-port` mounts it, `sylph-decoder` does not. Earlier sections: `screenshot` costs 10.8 s under xenia (92Γ—), and `trace_gpu_stream` is a no-op in the Release build | | [`title-crash-stl-tree.md`](title-crash-stl-tree.md) | The title-screen crash is an STL `map`/`set` erase on a bad iterator | βœ… CONFIRMED β€” the guest throws std::out_of_range from an STL | | [`ui-paint-order-third-permutation.md`](ui-paint-order-third-permutation.md) | A third measured paint order β€” tool built and validated, screen not reached | βœ… the reader works and is CONFIRMED against both previously | | [`ui-quad-class-foothold.md`](ui-quad-class-foothold.md) | The guest's UI quad class β€” a foothold found from the capture's vertex layout | 🟑 PROBABLE for the identification below (it is a static read, but | -| [`menu-navigation-semantics.md`](menu-navigation-semantics.md) | The title menu β€” how it moves, and where each button goes | βœ… measured: wraps both ends, β’· restores focus, β¬…βž‘ inert; 4 of 5 destinations driven. 🟑 GamePart id is a name match, ❔ `NEW GAME` untested | +| [`menu-navigation-semantics.md`](menu-navigation-semantics.md) | The title menu β€” how it moves, and where each button goes | βœ… measured: wraps both ends, β’· restores focus, β¬…βž‘ inert; all 5 destinations driven. 🟑 GamePart id is a name match. 🟑 **β’· leaving the MAIN menu downgraded 2026-08-29** β€” uncited, and the main menu is the only screen whose footer omits β’· (0 glyph px in frame vs 514/518 elsewhere). βœ… **MISSION SELECT's stuck cursor was a LOCKED stage list** β€” labels have three brightnesses, locked 104 / unfocused 183 / focused 254 | | [`screen-transitions.md`](screen-transitions.md) | Between two screens β€” a fade through black, and where its timing lives | βœ… the fade quad's keyframe group is decoded (disc-wide: per-pak all-or-nothing; `GP_TITLE` = the 6 screens, not the 6 overlays); the ~0.4 s fade-OUT is measured, not on the disc | | [`menu-audio-cues.md`](menu-audio-cues.md) | Menu audio β€” the event vocabulary is on the disc, the binding is not | βœ… `SE_UI_*` cue names/ids decoded and `BANK_SE`β†’`Static.slb` (0/322 in FILES); 🟑 event binding is a name match; ❔ `Static.slb` has no wave boundaries, so SE audio is not extractable | | [`boot-config-and-gamepart-registry.md`](boot-config-and-gamepart-registry.md) | What the game reads at boot β€” `config.ini`, and which GameParts exist | βœ… `config.ini` selects the language (the disc's only config); ❔ its `[SYSTEM]` is empty so the boot order is not in config; 🟑 24/29 ids bind to a class, `GP_ADVERTISE_DEMO` is never registered | diff --git a/docs/re/capture-harness-status.md b/docs/re/capture-harness-status.md index eb81db24..9d555ceb 100644 --- a/docs/re/capture-harness-status.md +++ b/docs/re/capture-harness-status.md @@ -362,3 +362,139 @@ The gamma run's flags plainly took effect β€” that run is where `VdGetCurrentDisplayGamma` was captured β€” while its dump showed the file's values. So the dump reflects the config file and cannot confirm or refute a command-line override. + +--- + +# πŸ”΄ 2026-08-29 β€” the disc is not in the decoder container at all + +**Status:** βœ… **diagnosed, root-caused in the launcher.** This supersedes every +"the emulator did not reach the title" entry above as the *current* reason the +oracle is unavailable: there is no game to run. + +## The measurement + +| looked for | result | +|---|---| +| `find / -xdev -iname '*.iso'` | **0** | +| `find / -xdev -iname 'default.xex'` | **0** | +| `find / -xdev -iname 'GP_TITLE.pak'` | **0** | +| `$SYLPHEED_DISC` | **empty** | +| `/work/sylph_extract` | does not exist | +| `/exchange/files` | **empty** | + +`sylph-doctor` agrees and says so in its own words: + +``` +── project ── + βœ– /work/xenia-canary not mounted + βœ– /work/Syplheed-Reborn not mounted + ! no ISO under /work β€” run-canary needs SYLPH_ISO + ! no extracted disc β€” Reborn disc tests will SKIP +``` + +Everything else is healthy: `xenia_canary` is built and present, display `:98` +is up, `screenshot` works, Vulkan (llvmpipe) enumerates, cargo and the python +stack are fine. **The emulator has no disc to boot.** + +## The cause β€” the volume migration, and a mount nobody replaced + +Before [`06676d3`](#) the launcher bind-mounted the human's working tree: + +``` +-v "$PROJECT:$PROJECT" +-v "$PROJECT:/work" +``` + +The ISO and `sylph_extract/` live in that tree, so the disc arrived **incidentally +with the repository mount**, and `run-canary`'s `find "$PROJECT_DIR" -maxdepth 2 +-iname '*.iso'` found it. + +`06676d3` replaced that with the agent's own clone in a named volume β€” + +``` +-v "sylpheed-decoder-repo:/work" +``` + +β€” which is the right fix for the collision class it was written for, and it +removed the disc along with the working tree. **Nothing was added to replace +it.** The launcher still forwards + +``` +[ -n "${SYLPH_ISO:-}" ] && _out+=(-e "SYLPH_ISO=$SYLPH_ISO") +``` + +but that is an **environment variable with no bind mount behind it** β€” it names a +host path that does not exist inside the container, so it cannot help. + +**The port container does not have this bug.** `docker/port/sylph-port` mounts +the disc explicitly: + +``` +_out+=(-v "$DISC:/disc:ro" -e "SYLPHEED_DISC=/disc") +``` + +So the one container that *owns* the disc and the oracle is the one container +without them. + +## Reach of the negative + +Whole-filesystem, single pass, `-xdev` per mount, three independent names (the +ISO, the executable, a pak the corpus names constantly). The exchange volume is +empty, so the disc is not arriving by `share` either. This is not "I looked in +the usual place". + +## What it blocks β€” everything disc-side and everything dynamic + +* the **oracle** β€” no boot, no capture, no `run-canary`; +* every `sylpheed-cli` invocation that names a pak β€” `screen list`, `screen info`, + `screen render`, `pak textures`; +* `build-reborn test` β€” the disc-gated tests self-skip, and per MISSION a green + run then means almost nothing. (`build-reborn` is *also* pointing at + `/work/Syplheed-Reborn`, a path the monorepo no longer has.) +* **static RE of the executable** β€” the XEX is on the disc, so the whole + PPC-disassembly route is shut too, not just the dynamic one. + +## What it does not block + +The committed corpus. `docs/re/captures/` is 99 MB of oracle frames and +`docs/re/data/` 2.5 MB of extracted tables, both in git β€” enough to re-measure +against captures, which is what this iteration did instead. + +## πŸ”΅ For the human β€” the one-line fix + +Add a disc mount to `docker/decoder/sylph-decoder`, the way `sylph-port` already +has one: + +```bash +[ -d "$DISC" ] && _out+=(-v "$DISC:/disc:ro" -e "SYLPHEED_DISC=/disc") +[ -f "$SYLPH_ISO" ] && _out+=(-v "$SYLPH_ISO:/disc.iso:ro" -e "SYLPH_ISO=/disc.iso") +``` + +Recorded rather than worked around, per *do not improvise around a blocker* β€” +and **not attempted**, because the launcher runs on the host and this container +cannot restart itself. + +⚠️ `sylph-doctor` reports the missing ISO as `!` (a warning) rather than `βœ–`. For +the decoder that is not a warning: it is the difference between having an oracle +and not having one. + +### A second, smaller consequence of the same migration β€” no git identity + +`git commit` in a fresh decoder container fails with *"Author identity +unknown"*: nothing in the image, the entrypoint or `sylph-decoder` sets +`user.name` / `user.email`, and the old bind mount used to bring the human's +`.git/config` along with the tree. + +Set locally, per iteration if the volume is recreated: + +```bash +git config --local user.name "sylph-decoder" +git config --local user.email "fabian@diekaulbachs.de" +``` + +⚠️ `push-work`'s header warns at length against `git config --local`, because +the credential helper it wrote there leaked a container-only path onto the host. +**That warning no longer applies to identity**: `/work` is a private named +volume now, not a shared bind mount, so nothing written to its `.git/config` +can reach a host checkout. The credential helper is still applied per-invocation +with `-c`, and should stay that way.