From ce235e153b0e8189e5d39ebdd817da7554fe100f Mon Sep 17 00:00:00 2001 From: Sylpheed RE agent Date: Mon, 24 Aug 2026 16:28:59 +0000 Subject: [PATCH] re: cheap probe verified; its one "arrival" is flicker First run of wave7_probe: zero stalled samples across the whole run, against three consecutive heavy-probe runs that stalled at roughly 27, 83 and 255 s. The fix works. The guest is also visibly healthier -- 19 losses against 8 in a heavy-probe run of comparable length -- so starving the emulator had been suppressing the very activity the probe existed to watch. It also reported the first arrival of the whole line of work, and that arrival does not survive inspection. A record went 1 -> 0 at t=229, 0 -> 2 at t=259 and 2 -> 0 at t=274. Two craft appearing and vanishing within fifteen seconds is not a wave. The same log contains the giveaway: at t=60 a record read 13 and at t=75 the same record read 14, an increase, with nothing printed, because the probe only surfaced decreases. The hull-based liveness read flickers, and a flicker that straddles zero was indistinguishable from an arrival under the old rule. The count therefore stands at zero confirmed arrivals in eleven runs. Two changes, neither yet exercised: every increase is printed rather than only those from zero, and an increase from zero counts only if it persists across two consecutive samples, with a candidate that returns to zero discarded as flicker. Recorded because it was close: under the old rule this run would have been written up as "first arrival observed", which would have been the strongest-looking result so far and wrong. --- docs/re/BACKLOG.md | 12 ++++++++--- docs/re/guest-stalls.md | 19 +++++++++++++++++ docs/re/mission-arrival-watch.md | 35 ++++++++++++++++++++++++++++++++ tools/re-capture/wave7_probe.py | 30 +++++++++++++++++++++------ 4 files changed, 87 insertions(+), 9 deletions(-) diff --git a/docs/re/BACKLOG.md b/docs/re/BACKLOG.md index c5e35ba..73c46bd 100644 --- a/docs/re/BACKLOG.md +++ b/docs/re/BACKLOG.md @@ -410,9 +410,15 @@ search cannot find a *schedule*. ⚠️ **Consequence: every "no arrival" result was collected under a struggling or frozen guest** — none is as strong as written, and the arrival question needs re-running with cheap sampling before silence means anything. - ✅ Fix written: `wave7_probe.py` enumerates once then polls only the hull word - per known craft (~1.2 KB/sample vs 32 MB), full rescan every 90 s — **not yet - run**. ❔ Multi-squadron threshold test still not run (zero losses that run). + ✅ **Fix VERIFIED (2026-08-24)**: `wave7_probe.py` (enumerate once, then poll + only the hull word per known craft, ~1.2 KB/sample, rescan every 90 s) ran + **0 stalled samples** and produced **19 losses vs 8** — starving the emulator + had been suppressing the activity the probe existed to watch. + 🔴 **Its one apparent arrival (`0→2` at t=259 s) is FLICKER, not a wave** — it + reverted to 0 fifteen seconds later, and the same log shows a record reading 13 + then 14 with no event printed because only decreases were surfaced. Count + stands at **0 confirmed arrivals in 11 runs**. Probe now prints every increase + and requires an arrival to **persist across 2 samples** (not yet run). ❔ Multi-squadron threshold test still not run (zero losses that run). ⚠️ The ~210 s title movie at boot is the binding constraint on observable game time per turn. Earlier framing: diff --git a/docs/re/guest-stalls.md b/docs/re/guest-stalls.md index d08b071..7c34396 100644 --- a/docs/re/guest-stalls.md +++ b/docs/re/guest-stalls.md @@ -125,3 +125,22 @@ That is 3–4 heavy scans per run instead of 25. Implemented, **not yet run** — so the claim that it stops the stalling is untested, and the next run must report the witness before anything else. + +--- + +# ✅ The cheap probe does not stall the guest (2026-08-24) + +First run of `wave7_probe.py` — one enumeration, then hull polling, full rescan +every 90 s: + +``` +TOTAL candidate-up=1 down=19 stalled samples=0 +``` + +**Zero stalled samples across the whole run**, against three consecutive heavy-probe +runs that stalled at ~27, ~83 and ~255 s. The fix works, and the previous +iteration's confirmation is now supported from the other direction as well. + +The guest is also visibly healthier: **19 losses against 8** in the heavy-probe +run of comparable length. Starving the emulator was suppressing the very activity +the probe existed to watch. diff --git a/docs/re/mission-arrival-watch.md b/docs/re/mission-arrival-watch.md index 4381ad2..e9a9ed4 100644 --- a/docs/re/mission-arrival-watch.md +++ b/docs/re/mission-arrival-watch.md @@ -272,3 +272,38 @@ advance. This makes every future run self-validating. It is implemented but has * Whether an arrival is observable at all. Nine runs, zero `0 → n`. * Re-examining earlier "flat" results now that a stall and a quiet mission are known to look the same. + +--- + +# The first apparent arrival is flicker, not a wave (2026-08-24) + +Status: 🔴 the single `0 → 2` observed on the cheap probe is **not** accepted as +an arrival; ✅ the reason is visible in the same log; ✅ the probe now requires +persistence. + +The first run with cheap sampling reported one arrival: + +``` +t=229s loss UN_e007_ADAN_Turret 1 -> 0 +t=259s ARRIVAL UN_e007_ADAN_Turret 0 -> 2 +t=274s loss UN_e007_ADAN_Turret 2 -> 0 +``` + +Two craft appearing and vanishing again within 15 s is not what a wave looks +like. **The same log contains the giveaway:** at t = 60 s a record read **13**, and +at t = 75 s the same record read **14** — an *increase* — with no event printed, +because the probe only surfaced decreases. The hull-based liveness read +flickers, and a flicker that happens to straddle zero is indistinguishable from +an arrival under the old rule. + +So the count is **0 confirmed arrivals**, in eleven runs. + +## The rule this produces + +An increase from zero counts only if it **persists across two consecutive +samples**, and every increase is now printed, not just those from zero. A +candidate that returns to zero at the next sample is discarded as flicker. Both +changes are in `wave7_probe.py`; **neither has run yet.** + +Had the old rule stood, this run would have been written up as "first arrival +observed" — the strongest-looking result of the whole line of work, and wrong. diff --git a/tools/re-capture/wave7_probe.py b/tools/re-capture/wave7_probe.py index 621237e..b7568a2 100755 --- a/tools/re-capture/wave7_probe.py +++ b/tools/re-capture/wave7_probe.py @@ -89,6 +89,7 @@ def main(): print('t= 0s deployed=%d strengths %s' % (len(prev), sorted(collections.Counter(prev.values()).items())), flush=True) t0 = time.time(); last_rescan = t0; arr = los = 0; stalls = 0 + pending, confirmed = {}, 0 while time.time() - t0 < secs: time.sleep(every) el = round(time.time() - t0) @@ -100,15 +101,32 @@ def main(): now = struct.unpack('>I', os.pread(fd, 4, tick))[0] if now <= last_tick: st = ' *** GUEST STALLED ***'; stalls += 1 last_tick = now - a_ = [(o, cur[o]) for o in cur if prev.get(o, 0) == 0 < cur[o]] + # Report EVERY increase, not just 0 -> n. The first run logged a record + # reading 13 then 14 with no event printed, which is how flicker in the + # hull-based liveness read hides: only decreases were being surfaced, so + # a spurious 0 -> 2 looked like an arrival while 13 -> 14 looked like + # nothing. An arrival must also PERSIST to count. + a_ = [(o, prev.get(o, 0), cur[o]) for o in cur if cur[o] > prev.get(o, 0)] l_ = [(o, prev[o], cur.get(o, 0)) for o in prev if cur.get(o, 0) < prev[o]] - arr += len(a_); los += len(l_) - print('t=%4ds deployed=%d ARRIVALS=%d losses=%d (cum %d/%d)%s' - % (el, len(cur), len(a_), len(l_), arr, los, st), flush=True) - for o, c in a_: print(' ARRIVAL %-30s 0 -> %d' % (label.get(o, '?'), c), flush=True) + for o, x, y in a_: + if x == 0: pending[o] = pending.get(o, 0) + 1 + for o in list(pending): + if cur.get(o, 0) == 0: pending.pop(o, None) # vanished: flicker + elif pending[o] == 2: + confirmed += 1 + print(' *** CONFIRMED ARRIVAL %-26s now %d (persisted 2 samples)' + % (label.get(o, '?'), cur[o]), flush=True) + pending[o] = 3 + arr += sum(1 for x in a_ if x[1] == 0); los += len(l_) + print('t=%4ds deployed=%d up=%d down=%d (cum up %d / down %d, confirmed %d)%s' + % (el, len(cur), len(a_), len(l_), arr, los, confirmed, st), flush=True) + for o, x, y in a_: + print(' up %-30s %d -> %d%s' % (label.get(o, '?'), x, y, + ' <- candidate arrival' if x == 0 else ''), flush=True) for o, x, y in l_: print(' loss %-30s %d -> %d' % (label.get(o, '?'), x, y), flush=True) prev = cur - print('\nTOTAL arrivals=%d losses=%d stalled samples=%d' % (arr, los, stalls)) + print('\nTOTAL candidate-up=%d down=%d CONFIRMED arrivals=%d stalled samples=%d' + % (arr, los, confirmed, stalls)) return 0 if __name__ == '__main__':