docs(agents): phases 0-1 done, and the Phase 2 gate corrects the page
All checks were successful
CI / Native — linux (pull_request) Successful in 42m58s
CI / WASM — Web (pull_request) Successful in 31m31s
CI / Formatting (pull_request) Successful in 1m1s

PHASE 0 -- the single-copy work is secured. Canary 8e63a9542 commits the
--pad_file_repeat instrument that had been uncommitted while the numbers it
produced were already shipping in the port; sylpheed-re and
audit-handle-lifecycle-probes pushed; all 14 local branches reachable.

Two corrections found by running it:

  * There is no DirectXShaderCompiler gitlink drift. `git submodule status`
    shows no '+'. The ' m' is NESTED submodule dirt (DXC's own SPIRV-Headers
    and SPIRV-Tools), which is upstream's business.
  * The gate itself was wrong. It compared branches to remotes BY SHA and
    called seven safe branches unpushed -- a branch that is an ANCESTOR of a
    pushed branch is already preserved. It now tests reachability, which is
    what it meant. A check that goes red for something unactionable is the
    failure this repo keeps naming, and this page shipped one.

PHASE 1 -- the four retiring xenia-rs branches pushed (32/52/56/59 commits).
The loop is clean everywhere except pi/clippy, pi/clippy-clean and pi/reauth3,
unreachable by ancestry and redundant by patch-id: the one case where the
answer lives outside the gate.

PHASE 2 GATE -- run, and it corrected this page in two directions.

  extract      (xex2tractor, no -r)    IDENTICAL to the project .pe
  extract -r   (xex2tractor)           differs -- 1,903 bytes over 273 runs
  extract      (xenia-rs, iterate-4A)  IDENTICAL, and .xex.json too

Right: the .pe is an xex2tractor extract. Wrong: it was made WITHOUT -r. So
the dependency this gate existed to protect does not exist -- the tool Phase 3
keeps already reproduces the file. -r drops from 'must port' to optional, with
a warning that it must never become the .pe, since it writes into the image
and would invalidate every byte-offset citation in docs/re/.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-09-13 19:18:54 +02:00
parent e54fe16077
commit 1ebb924851

View File

@@ -80,19 +80,31 @@ reproducibility of a measurement that is already live in the port.
1. Commit `file_input_driver.h` + `xenia_main.cc` on `sylpheed-re`.
2. Push `sylpheed-re` (4 + 1 commits) and `audit-handle-lifecycle-probes`.
3. Resolve the `third_party/DirectXShaderCompiler` submodule drift
**deliberately**`HANDOFF-crash-oracle-2026-07-16.md` pins the *recorded*
pointer on purpose.
3. ~~Resolve the `third_party/DirectXShaderCompiler` submodule drift.~~
**There is none.** `git submodule status` shows no `+`: the checked-out
commit matches the recorded one. The ` m` in `git status` is *nested*
submodule dirt — DXC's own `external/SPIRV-Headers` and `SPIRV-Tools` — which
is upstream's business and must not be committed here.
**Gate:** `git status` clean in `xenia-canary`, and every local branch contained
in a remote:
**Gate — and the first version of it was wrong.** It compared each local branch
to a remote **by SHA**, and reported seven safe branches as unpushed: a branch
that is an *ancestor* of a pushed branch is already preserved. A check that goes
red for something unactionable is the failure this repo keeps naming, so the
gate tests what it means — **reachability**:
```bash
git for-each-ref --format='%(refname:short) %(objectname)' refs/heads | while read b s; do
git for-each-ref --format='%(objectname)' refs/remotes | grep -q "^$s$" || echo "UNPUSHED $b"
git for-each-ref --format='%(refname:short)' refs/heads | while read b; do
s=$(git rev-parse "$b"); found=""
for r in $(git for-each-ref --format='%(refname:short)' refs/remotes); do
git merge-base --is-ancestor "$s" "$r" 2>/dev/null && { found=$r; break; }
done
[ -n "$found" ] || echo "🔴 $b NOT REACHABLE from any remote"
done
```
**PASSED 2026-09-13**`8e63a9542` commits the instrument; `sylpheed-re` and
`audit-handle-lifecycle-probes` pushed; all **14** local branches reachable.
## Phase 1 — Make the archive honest
Push xenia-rs `iterate-4B/ui-perf`, `4C/jit`, `4D/parallel`, `4E/native-threads`.
@@ -102,6 +114,13 @@ is not retired — it is deleted, quietly, by someone who thought it was safe.
**Gate:** the same loop, run in every repo, prints nothing.
**PASSED 2026-09-13** — all four pushed (32 / 52 / 56 / 59 commits ahead of
`master`). The loop is clean in all five repos **except** `pi/clippy`,
`pi/clippy-clean` and `pi/reauth3` in Sylpheed, which are unreachable by
ancestry and redundant by *patch-id* — the ledger's reason, and Phase 7's
disposal. The gate is right to flag them; they are the one case where the
answer lives outside it.
## Phase 2 — Harvest xex2tractor, then retire it
Four things exist only there.
@@ -109,23 +128,46 @@ Four things exist only there.
| take | why |
|---|---|
| **XEX2 devkit + XEX1 retail master keys** | `xenia-xex` hardcodes retail only; devkit is present but `#[allow(dead_code)]` and XEX1 is absent. xex2tractor tries all three in a validating loop. |
| **`extract -r`** — Xenia-style thunk stubs and variable slots written into the extracted PE | 🔴 **this is almost certainly how the project's `.pe` was made.** Nothing in xenia-rs writes a resolved PE. |
| ~~**`extract -r`**~~ | 🔴 **RUN, AND THE INFERENCE WAS WRONG** — see the gate below. Optional, and dangerous if it is ever mistaken for the `.pe`. |
| **`doc/xex2_format.md`** (39 KB) and **`doc/xbox360_exports.json`** (938 KB, 2,913 exports across xboxkrnl / xam / xbdm) | byte-identical to untracked loose copies in the project root. Tracked by **no repo**. |
| **`LICENSE`** (MIT) | Sylpheed has none. |
Leave everything else: `xenia-xex` is ahead on `resources.rs` (XDBF/XACH),
`pdata.rs`, `tls.rs`, basic zero-fill compression, and the analysis layer.
**Gate — and it is the load-bearing test of this plan:** `extract -r` reproduces
the existing `.pe` **byte-for-byte**.
**Gate — ✅ RUN 2026-09-13, and it corrected this page in two directions.**
> The provenance evidence: the README's example prints `9568256 bytes`; the
> project's `.pe` *is* 9,568,256 bytes with an `MZ` header, dated 18 Apr — three
> weeks after xex2tractor's last commit (2026-03-29).
>
> It is evidence, not proof. **If the gate fails, the inference is wrong and
> Phases 35 stop until it is understood** — because every `.pe`-offset citation
> in the corpus depends on that file being regenerable.
```
extract (xex2tractor, no -r) ✅ IDENTICAL to the project .pe
extract -r (xex2tractor) ❌ differs — 1,903 bytes over 273 runs
extract (xenia-rs, iterate-4A) ✅ IDENTICAL — and .xex.json identical too
```
**Right:** the `.pe` *is* an xex2tractor extract. Hash-for-hash.
**Wrong:** it was made **without** `-r`. The project's `.pe` is the plain
decrypted-and-decompressed image, imports **unresolved** — and `-r`'s 1,903
differing bytes sit in the import thunk region from `VA 0x82000600`.
🔴 **So the dependency this gate existed to protect does not exist.** This page
claimed *"drop this and the file every `.pe`-offset citation depends on can
never be rebuilt."* It can: **`xenia-rs extract`, the tool Phase 3 keeps,
reproduces it byte-for-byte** — along with the loose `.xex.json`, which turns out
to have come from xenia-rs, not xex2tractor.
⚠️ **And `-r` must never become the `.pe`.** It writes into the image, so a `.pe`
built with it would silently invalidate every byte-offset citation in
`docs/re/`. If resolved-import disassembly is ever wanted, it is a **separate
artifact under a different name**, never a replacement.
That leaves xex2tractor's unique list at three items, none urgent — the two
master keys, the two doc assets, and the licence. **The doc assets are now the
only reason to visit that repository.**
📌 Learned in passing: `iterate-4A` **builds clean** (`xenia-app`, one unused
variable warning), so Phase 3's source is not bit-rotted — and it needs
`libavutil-dev` and friends via `ffmpeg-sys-next`, dragged in by the emulator's
XMA audio. The standalone tool sheds a C library the CI image did not have.
## Phase 3 — Lift the DB tool out of the emulator