docs: the REMAINING OB address does not survive a run - refuted twice over

0xbdb59668 reads 0 in two independent Stage 02 runs while the HUD counts
004 -> 008 -> 012. Not an unmapped read: SEEK_DATA at that offset returns the
offset itself and the next hole is 5 MB later, so it is an allocated,
zero-filled word. The address was a per-run artefact, exactly as that file
already suspected it might be; the method is the durable result.

Re-finding it in the new run also failed, and both failures are recorded because
they are the instructive part. Two candidates were produced and both died on the
corpus's own rule -- verify across a transition you did not select on:
0xbc2377dc went 12 -> 18 while the HUD stayed 012 and read 3 two minutes later,
and 0xbd295b04 was plain noise.

One correction to the method note in that file: the scan is not slow. Over the
live /dev/shm image it takes 0.9 s. The real trap is that REMAINING OB climbs
004 -> 012 within about four minutes as waves spawn, so a scan is only valid if
the HUD is confirmed to hold the same value immediately before AND after it --
which is why the earlier 4-then-8 intersection came back empty.

What blocked finishing: with pilot.py retired at hull 340/1500 nothing was
killing objectives and the counter sat at 012 for five minutes, so there was no
later transition to filter on. What the counter counts, and whether an OB-badged
entity carries a flag, is untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Sylpheed RE agent
2026-08-23 17:16:07 +00:00
parent 15166bc1ad
commit 37c3585f4f
2 changed files with 93 additions and 0 deletions

View File

@@ -199,6 +199,50 @@ See [`structures/ui-composable-bundles.md`](structures/ui-composable-bundles.md)
The investigation that got here follows, kept in full because most of it is
refutations that were worth the cost.
## The dynamic-RE state is not in git, and it was gone
**Found 2026-08-23.** Everything the oracle runs on — the baseline emulator
binary, the Xbox profile, the Stage 02 save, the shader/code caches — lives
outside both repos and had been wiped. `sylph-doctor` says "all good" without
any of it; the first symptom is `NO PROFILE on disc` one second into a boot.
**Rebuilt and verified by driving it** (LOAD GAME lists the slot → READY ROOM →
Stage 02 flight): [`dynamic-re-state-restore.md`](dynamic-re-state-restore.md)
carries the recipe — incremental rebuild of `auto/upstream-baseline` in the
shared checkout (202 files, no submodule churn), profile bootstrapped with the
*instrumented* binary's `--create_profile_if_none`, and the committed
`savedata-stage02-5pct.bin` installed **without** an Xbox content header, which
`ContentManager::ListContent` does not need.
**Open, and cheap:**
* 🔎 **`launch_mission.sh` does not finish unattended on restored state.** It now
reaches the READY ROOM and stops on **BRIEFINGS** — its `step up; tap A` for
TAKE OFF is swallowed because a fixed `sleep 28` precedes it. Replacing that
sleep with a wait for the screen (`screen_id.py`) is the whole fix. Both runs
on 2026-08-23 were finished by hand from where it stopped.
***Nothing guarantees this state survives the next container.** If it is
meant to, the profile + save + `bin/` copies want a home inside a repo or a
named volume; that is a call for the user, not for an agent.
## The mission objective counter's ADDRESS is per-run
🔴 **`0xbdb59668` is refuted as a durable address** (2026-08-23): 0 in two
independent Stage 02 runs while the HUD read `004`/`008`/`012`, on an allocated
(not sparse) page. The **method** stands; the number does not, and every session
must re-scan. Two candidates from the re-scan were themselves refuted by the
corpus's own "verify across a transition you did not select on" rule. Detail and
the corrected method note (the scan takes **0.9 s** — the trap is the counter
climbing `004 → 012` in four minutes, not scan duration) in
[`structures/mission-objective-counter.md`](structures/mission-objective-counter.md).
**First step for whoever takes it:** a run whose pilot is still *engaging* when
the scan happens, so a later transition exists to filter on — `pilot.py` had
retired to hull 340/1500 and the counter then sat at `012` for five minutes.
The follow-on that the autopilot actually needs is unchanged and untouched:
❔ what the counter counts, and whether an `OB`-badged entity carries a flag in
its entity object.
## The declaration table is not a paint order on every screen
**Found 2026-08-17**, building the Explorer's UI Screens browser on

View File

@@ -58,3 +58,52 @@ evidence; the same offset tracking a *later*, unselected change is.
the natural follow-on — and it is what the pilot actually needs to *choose*
targets rather than merely know how many are left.
* ❔ Whether the same address holds for other stages.
## 🔴 2026-08-23 — cross-run stability: **REFUTED**
`0xbdb59668` does **not** repeat. A second Stage 02 run on the same baseline
(rebuilt per [`../dynamic-re-state-restore.md`](../dynamic-re-state-restore.md))
reads **0** at that address for the whole mission while the HUD counts up:
| HUD | RAM `0xbdb59668` |
|---|---|
| `004` (t+18 s, flight entry) | 0 |
| `008` | 0 |
| `012` (held for ~5 min) | 0 |
A **second, independent** run of the same mission repeats it: at `TIME 01:08.96`
with the HUD on `REMAINING OB 004`, the word is again **0**
([`../captures/stage02-inflight-run2-ob-address-zero.png`](../captures/stage02-inflight-run2-ob-address-zero.png)).
Read three times back-to-back at `004` — all zero — and `±64 bytes` around it are
zero too. The page is **not** a sparse hole (`SEEK_DATA` at the offset returns the
offset itself; the next hole is 5 MB later), so this is an allocated,
zero-filled word, not an unmapped read. The number was a **per-run artefact**, as
this file already suspected; the method is the durable part, and every future
session must re-scan.
**And re-finding it in the new run failed too — recorded because both failures
are instructive.** Two candidates were produced and both were killed by the
"verify across a transition you did not select on" rule:
* `0xbc2377dc` — held 12 at selection, then went 12 → 18 while the HUD stayed
`012`, and was reading **3** two minutes later at HUD `012`.
* `0xbd295b04` — read 12 once, then 0, 21, 54, 46, 4 in the next 50 s. Noise.
🔴 **A correction to this file's own method note.** The trap is *not* that the
scan is slow: `ob_scan.py scan` over the live `/dev/shm` image takes **0.9 s**
(9 555 hits at value 12; the SEEK_DATA extent walk skips the sparse 4.6 GB). The
real trap is that **`REMAINING OB` climbs fast early in Stage 02** — `004``008`
`012` inside about four minutes as waves spawn — so a scan is only valid if the
HUD is confirmed to hold the same value **immediately before and after it**. The
earlier `4 ∩ 8` intersection here came back with no survivor for exactly that
reason: the value-8 scan was actually taken at 12.
**What blocked finishing it:** with the pilot in `RETIRE` (hull 340/1500) nothing
was killing objectives, and the counter sat at `012` for five minutes — no
transition to filter on. A run that intends to find this address needs a pilot
that is still *engaging*, which is the same constraint
[`../autopilot-memory-driven.md`](../autopilot-memory-driven.md) records.
**Unchanged and still open:** what the counter counts, and whether an `OB`-badged
entity carries a flag in its entity object. Nothing in this pass touched that.