# ✅ `--build N` is an ordinal into a filtered list — and on 21 of 24 archives it is not the entry **Status:** ✅ **decoded**, disc-wide, instrument controlled against the CLI's own output. The object decoded is *the addressing*, not a file field: how `sylpheed-cli screen --build N` resolves, and where that number stops agreeing with the pak entry index a reader will assume it means. ## Why this was swept Last iteration I rendered `--build 10` and `--build 11` of `GP_TITLE` believing they were the two splash screens, wrote three claims on the output, and every downstream number validated. They are entries **12** and **15** — the loading screens. I retracted it, and named the untested remainder in my own report: *"how much else in the corpus used `--build` as an entry index — not swept."* This is that sweep. ## The mechanism `crates/sylpheed-cli/src/main.rs:394` builds the list: ```rust fn screen_builds(pak: &Path, all: bool) -> Result)>> { for (i, e) in ar.entries().iter().enumerate() { let keep = if all { ui_layout::is_composable(&bytes) } else { ui_layout::is_build(&bytes) }; if keep { out.push((i, bytes)); } // (entry, bytes) } } ``` `--build N` indexes `out`, so `N` counts only entries that **passed a predicate**. Every entry the predicate rejects shifts every later ordinal down by one. ## 🔴 The result: `GP_TITLE` is the mildest case on the disc [`data/ordinal-entry-map.txt`](../data/ordinal-entry-map.txt) — all 24 archives holding builds: * **21 of 24 diverge.** Only `GP_MOVIE_THEATER`, `GP_SYSTEM` and `GP_TUTORIAL` have ordinal == entry throughout. * **18 of the 21 diverge at ordinal 0** — `--build 0` is *not* entry 0. The worst are the six `GP_MAIN_GAME_*2D` paks, where `[0]` is entry **108**, and `GP_HANGAR_ARSENAL` / `GP_READY_ROOM`, where `[0]` is entry **24** / **26**. * `GP_TITLE` is the **only** archive whose first ten ordinals happen to be the identity. It diverges at ordinal 10 and nowhere earlier. So the corpus was not lucky in general — it was lucky in the one archive almost all of it is about, and unlucky in exactly the two indices I used. ## ⚠️ Second foot-gun: `--all` renumbers, on 18 archives `--all` swaps the predicate, which changes the list, which changes the ordinals. **`--build N` and `--build N --all` are not the same object** on 18 of 24 archives — including `GP_TITLE`, where `--build 10` is entry 12 but `--build 10 --all` is entry 10. Any citation of a build index that does not also record whether `--all` was passed is under-specified. ## ✅ Audit of every build citation in `docs/` 226 citations of a build index across `docs/` (this file excluded). The 207 that name an ordinal 0–9 of `GP_TITLE` are safe by the accident above. The **19** that name an ordinal ≥10, or a non-`GP_TITLE` archive, are the ones that can be wrong, so each was opened and checked rather than counted: | # | citations | verdict | |---|---|---| | 6 | carry `--all`, where ordinals 10/11 *are* entries 10/11 | ✅ correct | | 4 | inside last iteration's retraction, already marked void | ✅ n/a | | 2 | `GP_TITLE` `--build 10` bare — `ui-title-build-map.md:85` | ✅ correct: it names what comes back, the **loading screen** `pgloading_str.t32` | | 2 | `GP_DIALOG --build 0` (`[0]` is entry 2) | ✅ re-run, reproduces | | 2 | `GP_DEBRIEFING_PILOTLOG build 10` (`[10]` is entry **131**) | ✅ re-run, reproduces | | 2 | prose about an unfinished sweep / the renumbering warning itself | ✅ n/a | | **1** | `ui-keyframe-time-unit.md:59` | 🔴 **wrong, and fixed** | ### The two re-runs Neither claim asserted an entry number — both cite *the output of a command*, so a reader running it gets the same object the author had. Confirmed by running them, not by arguing it: ``` $ sylpheed-cli screen info --build 0 --geometry /disc/dat/GP_DIALOG.pak 4 pceff03.t32 0: a=0 r=90 8: a=128 r=30 12: a=192 r=10 14: a=224 r=3 16: a=255 5 pceff04.t32 0: a=0 r=90 8: a=128 r=30 12: a=192 r=10 14: a=224 r=3 16: a=255 $ sylpheed-cli screen info --build 10 --geometry /disc/dat/GP_DEBRIEFING_PILOTLOG.pak 5 pjeff24a.t32 382x140 0: 335,49 210%,210% a=53 r=90 (one keyframe) ``` Both stand unchanged. ### 🔴 The one real defect the sweep found [`ui-keyframe-time-unit.md`](../ui-keyframe-time-unit.md) headed a five-row table *"declared element (build 11)"*. Its first row is `palogo_sqex.t32` — and `--all --build 11` does not contain it: ``` --all --build 10 palogo_sqex, palogo_sqex_eff --all --build 11 palogo_gamearts{,_eff}, palogo_seta{,_eff}, palogo_anima{,_eff} ``` The rows span **two** bundles. All five placements re-verified and are correct — `palogo_sqex.t32` 666×68 @ (309,330) in build 10, `palogo_gamearts_eff.t32` 521×91 @ (379,154) in build 11 — so the measurement the table supports (the ramp is linear) is untouched. Only the label was wrong. Fixed: the table now carries a per-row bundle column. That is the shape worth remembering: **the index error did not corrupt the numbers, it corrupted the sentence around them**, and the numbers kept validating. ## ⚠️ For the port: this is an addressing hazard, not a decoding one If you address bundles by **pak entry index** — which [`ui-splash-addressing.md`](../ui-splash-addressing.md) recommends for the splashes — and cross-reference a doc that says "build 6", those are different objects on 21 archives. When quoting an index, say which kind it is. Our docs now say *ordinal* or *entry*. ## Refutation attempted — `sylpheed-port`'s corrected mid-ramp test — **survives** The port withdrew their own `title_jp` "separating case" this iteration, on the grounds that `ptlogo_all_eff` **holds** a=127 from t=112 to t=246 rather than ramping through it, so their old `0 < alpha < 255` test had counted a steady semi-transparent glow as a transition. Their whole correction — and the 5/5 result they say survives it — rests on the keyframes of that one element, which is disc data and therefore mine to check. Quoted against the disc: ``` $ sylpheed-cli screen info --build 7 --geometry /disc/dat/GP_TITLE.pak 29 ptlogo_all_eff.t32 538x255 0: a=0 76: a=0 112: a=127 246: a=127 258: a=0 (kind 0x3000, 200%,200%, position constant) ``` Their quote `[0:a0 76:a0 112:a127 246:a127 258:a0]` is **exact**, and a=127 is held flat across 134 units with nothing else moving. It is a plateau. The refutation fails and their correction stands — including the part that costs them, since it removes the one case that would have separated their hypothesis from mine. ⚠️ Note what this does *not* establish: that a=127 is a glow. That reading is theirs and rests on kind `0x3000` and the 200 % scale, neither of which I have tested against the running game. What I checked is the keyframes. ## What this does not settle * Whether anything **outside `docs/`** — scripts under `tools/`, committed test fixtures — hard-codes a build ordinal for a diverging archive. I swept the prose, not the code. * The three identity archives are identity *today*. Nothing enforces it; a change to `is_build` moves every ordinal on the disc. This is a property of a predicate, not of the format.