Files
Sylpheed/docs/re/upstream-baseline.md
MechaCat02 1fdbb5f197
Some checks failed
CI / Native — linux (pull_request) Failing after 1h1m35s
CI / WASM — Web (pull_request) Successful in 24m37s
CI / Formatting (pull_request) Successful in 26s
fix(decoder): give the container the Canary it is supposed to run
The database mount below was one of three ways the decoder could not reach its
own oracle. The other two are here.

`run-canary` never looked in `Checked/`. It tried `Release/` then `Debug/`, and
both of those exist on this box -- an Aug 28 binary and a Jul 19 one. They boot
the game perfectly well and carry NO `audit_61` branch probe, so a probe run
against either returns zero hits that read as a finding about the game rather
than as a stale binary. Configuration is now the outer loop and location the
inner one, so a `Checked` build anywhere beats a `Release` build anywhere;
`$XENIA_BIN` still overrides everything. Measured here: `Checked` has
`audit_61_branch_probe_pcs`, `Release` and `Debug` do not.

The launcher also now says which instrumentation is missing BEFORE the run,
because the alternative is reading an empty log afterwards and guessing.

`build-canary` built `$PROJECT_DIR/xenia-canary`, which does not exist in this
container -- the source is bind-mounted at `/canary` and the launcher already
exports `XENIA_SRC=/canary`. CONTAINER-NOTES has carried that defect since
2026-08-29 with a symlink workaround and a warning to remember to delete the
symlink afterwards. It now reads `$XENIA_SRC` first, so there is nothing to
remember. Its default configuration moves Release -> Checked to match what
`run-canary` picks; the old default spent a full build on a binary nothing ran.

Two documented blockers are refuted rather than deleted, since the sequence of
wrong readings is what makes the right one checkable: the CONTAINER-NOTES
symlink dance (the warm build volume it was configured against is gone too,
removed in the 2026-09-18 cleanup, so the next build configures cleanly against
`/canary`), and `upstream-baseline.md`'s "`version.h` is never generated" --
`CMakeLists.txt` generates it at configure time now, with a stub fallback.

`decoder-loop.md` claimed the oracle was at `Linux/Release/` and that the probe
was on two side branches; both were true when written and neither is now.

Verified: five pick_bin cases against the extracted function body, and `strings`
on all three real binaries.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 18:08:10 +02:00

92 lines
4.6 KiB
Markdown

# A stock-upstream baseline runs Stage 02 crash-free
**Status:**`CONFIRMED` — upstream `canary_experimental` + **only** the pad
driver and the threading fix reaches Stage 02 flight with **zero** crash dumps,
where the instrumented branch produces 384 at the briefing and never reaches
flight. 🔴 pure upstream on its own is **less** stable, not more — it still has
the lost-resume race. 🔴 the `REMAINING OB` address is **not** found: the first
candidate was refuted.
## Why this was tried
The instrumented branch stops at the Stage 02 briefing under a storm of
`0x82307128` ([`title-crash-stl-tree.md`](title-crash-stl-tree.md)). The question
"is that crash ours or upstream's?" is answerable by building upstream clean.
## Building it, and two tooling gaps found on the way
`git fetch upstream` works from this container. The merge base is 82 commits
behind `upstream/canary_experimental` (`a5a18f5c7`); our branch carries 50 of its
own.
* ~~**`version.h` is never generated.**~~ ✅ **FIXED — `CMakeLists.txt` now
generates it at configure time**, calling `xenia-build.py`'s
`generate_version_h()` and falling back to a stub if that fails, so a
CMake-direct build no longer depends on a stale copy in the build directory.
It used to fail on `trace_writer.cc:17: fatal error: 'version.h' file not
found`, and the fix had to exist before the 2026-09-18 cleanup deleted the
build volume that was carrying that stale copy.
* **`build-canary` reports success on a failed build.** The harness recorded
"completed (exit code 0)" while ninja had stopped with `1 error generated`.
Only the missing binary gave it away.
## Pure upstream cannot be driven — and is not more stable
`--hid=file` is **ours** (`d15c8cfab` and two follow-ups), and there is no uinput
in this container, so a genuinely pure binary boots but cannot be scripted past
the title. The honest baseline is therefore **upstream + those three commits**.
That baseline reproduced the **lost resume** on its second boot: black screen,
guest alive at **522 % CPU**, the newest host thread at **`00:00:00`** CPU time,
its guest handle making zero kernel calls — the exact signature from
[`canary-scripted-input-traps.md`](canary-scripted-input-traps.md). Reading
`upstream/canary_experimental:src/xenia/base/threading_posix.cc` confirms the
two-lock-scope publish is still there. **So "pure upstream" is not a stable
state: it contains a real bug this project had already fixed.**
## ✅ Upstream + the threading fix: Stage 02, in flight, zero crashes
Adding **only** `a60fe7d11` on top — still none of the RE instrumentation —
`launch_mission.sh` drove boot → title → LOAD GAME → slot 01 → READY ROOM →
TAKE OFF → **flight**:
![Stage 02 in flight](captures/stage02-inflight-upstream-baseline.png)
`TIME 05:03.75`, wingman `Rhino 103 / Ellen Bernstein`, radio dialogue, asteroids,
tracer fire — and **`REMAINING OB 020`** with `OB` badges on the objective
targets. The run ended in a legitimate **GAME OVER** (the unattended craft was
shot down, exactly as `autopilot-memory-driven.md` warns) — **not** a crash.
**Crash dumps for the entire run: 0.** Against 384 on the instrumented branch at
the briefing alone.
So the mission crash is **not upstream's**. It is either in our 50 commits or
fixed among upstream's 82 — this run does not separate those two, and saying
which would need a bisect.
## 🔴 `REMAINING OB` in RAM: first candidate refuted
The counter is visible and moves (020 → 019 → 018 → 017), so it is scannable.
* A three-snapshot big-endian u32 filter (19 → 19 → 18) left **0** survivors.
* A direct differential across widths over the 19→18 transition gave exactly
**one** aligned BE u32: `va 0xbc22e83c` (the u16 hit at `…83e` is its low half).
* **Refuted.** Read live moments later it held **26** while the HUD showed
**017**. It is an unrelated counter that happened to step 19→18 in the same
window.
That the u32 filter came back empty is itself a result: the counter is not a
plain persistent big-endian word. Candidates worth trying next are a per-digit
representation, a value recomputed each frame from an entity list (in which case
the *list* is the real target), or a field inside a structure that moves.
## Not settled
* 🔴 Which side owns the mission crash — our 50 commits or upstream's 82. A
bisect would say; nothing cheaper will.
* 🔴 The `REMAINING OB` address.
* ⚠️ `wait_flight.sh` reported `NEVER REACHED FLIGHT` while the game was plainly
in flight — its detector is wrong, and `screen_id.py` got it right.
* ⚠️ Any future in-mission scan needs the pilot flying or a safe holding pattern:
an idle craft is dead in about a minute.