diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index 7a913f16..3fd1ab3b 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -588,6 +588,17 @@ search cannot find a *schedule*. combat limit. 🔴 `SYLPH_HZ=3` refuted as a lever: it gave the LOWEST frame rate (8/s) with the most kills, so pilot polling is not the throttle. +* ✅🔴 **(2026-08-24) OB hunt, second attempt.** ✅ **Incremental saving verified** + — one `e010` event at t=241 s wrote **1187 candidates** to disk before the turn + timeout fired; session now clears the file at launch since offsets are only + valid within one emulator instance. 🔴 **The correlation had no value filter**: + survivors were float bit patterns (1044450858 ≈ 0.1f) whose integer forms + differed by the loss count. Fixed — candidates must be small non-negative + integers (`0 ≤ v < 1000`) in both samples. 🔴 **The attach was FROZEN**, not + merely unproductive: **25 of 26 samples flagged `GUEST STALLED`**. The witness + worked; the summary just quoted "0 events" before checking it. **Rule: read the + witness FIRST, before interpreting what a run showed.** ❔ Still no address; + needs 2–3 `e010` events in non-stalled samples. * ~~🚧 BLOCKER: t=210/240 unreachable in one turn~~ — **superseded, see above**; it rested on an untested assumption that a turn is one shell call. 595 s shell cap − ~220 s boot (a ~190 s title movie that cannot be tapped through) − ~25 s startup = **~350 s observation ≈ 193 game-seconds**. diff --git a/docs/re/remaining-ob-hunt.md b/docs/re/remaining-ob-hunt.md index ecb74c49..489a70e9 100644 --- a/docs/re/remaining-ob-hunt.md +++ b/docs/re/remaining-ob-hunt.md @@ -61,3 +61,53 @@ needs is a run that catches **two or three** `e010` kill events, which is the sa combat-effectiveness limit recorded in [mission-objectives-text.md](mission-objectives-text.md) — the preference knob gets about two marked-fighter kills per five minutes against a dozen turrets. + +--- + +# Second attempt: saving works, the filter was wrong (2026-08-24) + +## ✅ Incremental saving works + +A fresh mission caught one `e010` event at t = 241 s and **wrote 1187 candidates +to disk immediately**. The turn timeout then fired, exactly as before — but this +time the data survived it. The fix from the previous iteration is verified. + +The session also now clears `/tmp/ob_candidates.json` at launch: candidate +*offsets* are only meaningful within one emulator instance, so resuming across +launches would intersect unrelated addresses. + +## 🔴 The correlation had no value filter, and the survivors were floats + +The 1187 survivors are not counters: + +``` +va 0xbd0a42b8 value 1044450858 (~0.1f) +va 0xbd140bc0 value 3200164558 (a negative float) +va 0xbd14a120 value 3212461993 +``` + +The filter matched on the **delta** alone, so any two float bit patterns whose +integer representations differ by exactly `lost` qualified. In a 32 MB heap full +of positions and velocities that is thousands of words. + +Fixed: candidates must also *look like a counter* — a small non-negative integer +(`0 ≤ v < 1000`) in both samples. That removes float noise by construction rather +than hoping the intersection washes it out. + +## 🔴 The attach was frozen, and the witness said so + +The follow-up attach logged **0 events across 520 s**, which reads like the +combat-effectiveness limit again. It was not: **25 of its 26 samples were flagged +`GUEST STALLED`**. The guest was frozen for essentially the whole window. + +The witness added last iteration did its job. The lesson is about reading it — +the run summary quoted "0 events" first and the stall count only turned up on a +deliberate check. **A run's witness result should be the first thing looked at, +before any interpretation of what the run "showed".** + +## Still unfinished + +No address identified. What is needed is unchanged — two or three `e010` kill +events in *non-stalled* samples — and the two obstacles are now clearly separate: +the freeze rate, and the pilot managing roughly two marked-fighter kills per five +minutes. diff --git a/tools/re-capture/ob2_session.sh b/tools/re-capture/ob2_session.sh index 4c96b050..8ec2fc4a 100755 --- a/tools/re-capture/ob2_session.sh +++ b/tools/re-capture/ob2_session.sh @@ -26,6 +26,7 @@ if [ "$BOUND" = 1 ]; then /tmp/live-pilot.log 2>&1 & PILOT=$!; echo "--- pilot (SYLPH_HUNT=$HUNT)" else echo "BIND FAILED after 3 attempts -- aborting, an unattended run tests nothing"; exit 4; fi +rm -f /tmp/ob_candidates.json # offsets are per-emulator-instance; never resume across launches python3 "$SD/ob_probe2.py" "$SECS" "$EVERY"; rc=$? [ -n "$PILOT" ] && kill "$PILOT" 2>/dev/null echo "LIVENESS DONE rc=$rc" diff --git a/tools/re-capture/ob_probe2.py b/tools/re-capture/ob_probe2.py index e03b1ba3..81ea6b64 100755 --- a/tools/re-capture/ob_probe2.py +++ b/tools/re-capture/ob_probe2.py @@ -107,8 +107,14 @@ def main(): allo = sum(max(0, prev_s[k] - cur_s.get(k, 0)) for k in prev_s) if lost: events += 1 + # Filter on VALUE plausibility, not just on the delta. Without this + # the survivors are float bit patterns whose integer representations + # happen to differ by `lost` -- the first run's 1187 "candidates" + # were things like 1044450858 (~0.1f) and 3212461993 (a negative + # float). A remaining-target counter is a small non-negative integer. d = prev_r - cur_r # positive where a word FELL - hit = np.nonzero(d == lost)[0] + plausible = (cur_r >= 0) & (cur_r < 1000) & (prev_r < 1000) + hit = np.nonzero((d == lost) & plausible)[0] s = set(hit.tolist()) cand = s if cand is None else (cand & s) json.dump(sorted(cand), open(CAND, 'w')) # save NOW: the previous