docs: REMAINING OB is at 0xbdb59668 - confirmed to the corpus's own standard

One filter to select (004 -> 008, 35897 -> 7), a second on a transition it was
NOT selected by (008 -> 012, 7 -> 1), leaving exactly one address; then three
live paired readings, RAM/screenshot/RAM, all agreeing with the HUD.

The address is the same one run 1 reported. That does NOT reverse yesterday's
refutation and the entry says so explicitly: runs 2 and 3 read a hard 0 there on
an allocated page while the HUD counted, so "it is there in every run" stays
refuted. What is withdrawn is the stronger claim that the number was meaningless
- it recurs exactly, in 2 of the 4 runs measured, and run 3's amber candidate
0xbdb49668 sits one 64 KB page below it at the identical page offset 0x9668. The
practical rule is therefore: try 0xbdb59668, check it against the HUD, re-scan
when it reads 0.

Why run 3 failed and run 4 did not is also recorded, because it is a method
lesson rather than luck: the evidence was always in the first four minutes of the
stage, and the earlier runs simply could not look often enough - every HUD
reading cost a human round trip, so the 008 step went by between two of them.

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 18:39:22 +00:00
parent abd72a2c24
commit dd39cdd03d
4 changed files with 90 additions and 28 deletions

View File

@@ -0,0 +1,21 @@
{
"scan_value": 4,
"transitions": [
{
"from": 4,
"to": 8,
"survivors": 7
},
{
"from": 8,
"to": 12,
"survivors": 1
}
],
"survivors": [
{
"off": 4793407080,
"va": 3182794344
}
]
}

View File

@@ -0,0 +1,4 @@
scanned at 004: 35897 candidates
004 -> 008 [SELECTED ON] 7 survive
008 -> 012 [verification (unselected)] 1 survive
va 0xbdb59668

View File

@@ -150,3 +150,51 @@ scanning and filtering as above, then watching `0xbdb4·9668`-equivalent across
HUD-verified change. The blocker is the pilot's survival, not the method — and
the same run would answer whether the page offset repeats, which is the stronger
result of the two.
## ✅ 2026-08-23 (third pass) — the counter is at `0xbdb59668` again, and the refutation above is *refined*, not reversed
Run 4, with the hunt automated end to end
([`ob_hunt.py`](../../tools/re-capture/ob_hunt.py) + the HUD reader), produced
**exactly one** surviving address:
```
scanned at 004: 35897 candidates (HUD confirmed 004 on BOTH sides)
004 -> 008 [SELECTED ON] 7 survive
008 -> 012 [verification (unselected)] 1 survive
va 0xbdb59668
```
([`captures/ob-hunt-stage02-run4.log`](../captures/ob-hunt-stage02-run4.log),
[`captures/ob-hunt-stage02-run4.json`](../captures/ob-hunt-stage02-run4.json))
That is the corpus's own standard met: one filter to select, a **second on a
transition it was not selected by** to verify. Then three live paired readings —
RAM read, screenshot, RAM read again — all `ram 12 -> 12 / hud 012`.
And it is **the same number as run 1**.
### What this does and does not overturn
| claim | status |
|---|---|
| the counter sits at `0xbdb59668` in *every* run | 🔴 **still refuted.** Runs 2 and 3 read a hard 0 there, on an allocated page, while the HUD counted 004 → 012. Nothing about run 4 makes those readings wrong. |
| the run-1 number was a meaningless artefact | 🔴 **withdrawn.** It recurs *exactly*: 2 of the 4 runs measured put the counter at `0xbdb59668`. |
| the address moves by whole 64 KB pages | 🟡 **consistent, twice.** Run 3's best candidate was `0xbdb49668` — one 64 KB page below — and both known-good addresses share the page offset **`0x9668`**. Run 3's candidate was only ever amber, so this rests on one confirmed address plus one plausible one. |
**So the practical rule is: try `0xbdb59668` first and *check it against the
HUD*, and re-scan when it reads 0.** A scan costs about five minutes now
(`ob_session.sh`), most of that being the boot.
### Why run 3 failed and run 4 did not
Nothing about the game changed; the *procedure* did. Run 3 filtered once, on
`004 → 012`, because the intermediate `008` step went by unnoticed between two
hand readings — and its 17 survivors then had no second transition to be tested
against, since `REMAINING OB` held at `012` for ten minutes while the pilot sat
in EVADE. Run 4 caught **both** early steps, five seconds apart from polling,
because reading the HUD stopped costing a human round trip. The evidence needed
was always in the first four minutes of the stage; the earlier runs were simply
not able to look often enough.
**Still open, and untouched:** ❔ what the counter counts, and whether an
`OB`-badged entity carries a flag in its entity object. That is the part the
autopilot actually needs, and knowing the address is only its precondition.

View File

@@ -1,45 +1,34 @@
#!/usr/bin/env bash
# Boot -> Stage 02 flight -> fly the survival pilot, sampling the candidate
# REMAINING OB address against the HUD the whole time.
# One task: boot -> Stage 02 flight -> fly the survival pilot -> hunt for
# REMAINING OB in RAM against the HUD.
#
# fly_session.sh with one addition: ob_sample.py runs alongside the pilot, so
# the RAM word and the HUD digits come from the same run rather than from two.
# The pilot is not optional decoration -- an unattended craft is dead in about a
# minute (upstream-baseline.md), and a dead craft produces no transitions, which
# is exactly the evidence this test needs.
#
# NOTE (2026-08-23): launch_mission.sh does not currently finish unattended on a
# freshly restored profile -- it reaches the READY ROOM and stops on BRIEFINGS
# (docs/re/dynamic-re-state-restore.md). Until that fixed `sleep 28` becomes a
# wait for the screen, this script inherits the same stop and the sampler never
# starts; drive the last two presses by hand, or fix the launcher first.
# The pilot is not decoration. An unattended craft is dead in about a minute
# (upstream-baseline.md), and a dead craft produces no transitions, which is
# exactly the evidence ob_hunt.py needs. Conversely the hunt does NOT depend on
# the pilot doing well: the counter climbs on its own as waves spawn in the first
# minutes of the stage, which is where both filters should land.
set -u
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
export PYTHONPATH=/sylph-home/.local/lib/python3.12/site-packages
SD="$(cd "$(dirname "$0")" && pwd)"
SECS="${1:-240}"
SECS="${1:-600}"
TAG="${2:-ob}"
VA="${OB_VA:-0xbdb59668}"
SHOTS=/sylph-home/re/shots/$TAG
CFG=/tmp/nav-live.json
"$SD/launch_mission.sh" fly || { echo "BOOT FAILED"; exit 1; }
mkdir -p "$SHOTS"
# Sample immediately -- the first reading is the cross-run test and must not
# depend on the pilot binding, which can fail on its own.
python3 "$SD/ob_sample.py" "$VA" "/tmp/$TAG-ob.csv" "$SHOTS" "$TAG" 25 \
"$(python3 -c "import math;print(max(2,math.ceil($SECS/25)))")" &
SAMPLER=$!
if python3 "$SD/entities2.py" self 0x130 "$CFG"; then
if python3 "$SD/entities2.py" self 0x130 "$CFG" >/dev/null; then
echo "--- config: $(cat "$CFG")"
python3 "$SD/pilot.py" "$CFG" "$SECS" || echo "PILOT EXITED $?"
nohup python3 "$SD/pilot.py" "$CFG" "$SECS" </dev/null >"/tmp/$TAG-pilot.log" 2>&1 &
PILOT=$!
else
echo "BIND FAILED -- sampling an unattended craft, expect a short run"
echo "BIND FAILED -- hunting an unattended craft, expect a short run"
PILOT=""
fi
wait $SAMPLER 2>/dev/null
echo "--- samples: /tmp/$TAG-ob.csv"
cat "/tmp/$TAG-ob.csv"
echo "SESSION DONE"
python3 "$SD/ob_hunt.py" "$SHOTS" "${OB_TRANSITIONS:-3}" "$SECS"
rc=$?
[ -n "$PILOT" ] && kill "$PILOT" 2>/dev/null
echo "SESSION DONE (hunt rc=$rc)"