diff --git a/docs/agents/CONSOLIDATION.md b/docs/agents/CONSOLIDATION.md index 62a31223..83833cac 100644 --- a/docs/agents/CONSOLIDATION.md +++ b/docs/agents/CONSOLIDATION.md @@ -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 3–5 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