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. Before06676d3, 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.06676d3replaced 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) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013UxPvE5cz7zekXBKi7Xw2r
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user