re: state 1 = not yet deployed, and arrivals are directly observed
Watching [ScriptMission+40] and the three phase-1 objective squadrons together: all of ADN110/111/112 flip state 1 -> 2 at ~143s, while records in state 2 climb 24 -> 35 over four minutes. So state 1 means 'not yet deployed' for these, not 'gone'. The built-in table's '1/3/4 = gone/dead/invalid' shorthand is incomplete, and reading state != 2 as destroyed would have been wrong exactly as flagged last iteration. This also answers a much older question: mission-arrival-watch.md and the wave work recorded '0 confirmed arrivals' across many runs by watching the CRAFT population. The script's own unit table shows arrivals plainly -- eleven records enter state 2 within four minutes. The old negative measured the wrong structure; craft counts conflate deployment with attrition, the per-unit state field does not. Both attempts froze (at ~70s and ~253s), so no phase advance was reached. The freeze witness caught both immediately, which is why the truncation is visible instead of a silently flat line. New harness tools/re-capture/phase_watch.py.
This commit is contained in:
13
docs/re/data/phase-watch-s02.txt
Normal file
13
docs/re/data/phase-watch-s02.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
file base 0xAB860010 ScriptMission 0xBC79C960
|
||||
[ 1.8s] phase=1 finished=0 active= 24 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 58.2s] phase=1 finished=0 active= 27 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 90.7s] phase=1 finished=0 active= 30 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 120.8s] phase=1 finished=0 active= 29 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 143.4s] phase=1 finished=0 active= 32 ADN110:2 ADN111:2 ADN112:2
|
||||
[ 188.4s] phase=1 finished=0 active= 34 ADN110:2 ADN111:2 ADN112:2
|
||||
[ 223.3s] phase=1 finished=0 active= 35 ADN110:2 ADN111:2 ADN112:2
|
||||
[ 253.4s] *** GUEST FROZEN -- readings below are about a dead world ***
|
||||
[ 315.6s] *** GUEST FROZEN -- readings below are about a dead world ***
|
||||
[ 377.7s] *** GUEST FROZEN -- readings below are about a dead world ***
|
||||
[ 439.9s] *** GUEST FROZEN -- readings below are about a dead world ***
|
||||
[ 502.1s] *** GUEST FROZEN -- readings below are about a dead world ***
|
||||
@@ -49,6 +49,44 @@ So the mirror is not a phase readout at all in phase 1, and **`+40` is**. It is
|
||||
reachable from `/dev/shm` with no debugger, which is what made three runs of
|
||||
polling the wrong address avoidable in hindsight.
|
||||
|
||||
## ✅ PINNED: state 1 = not yet deployed, state 2 = active — and arrivals are real
|
||||
|
||||
Watching `[ScriptMission+40]` and the three objective squadrons together across a
|
||||
live run (`data/phase-watch-s02.txt`):
|
||||
|
||||
```
|
||||
[ 1.8s] phase=1 finished=0 active= 24 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 58.2s] phase=1 finished=0 active= 27 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 90.7s] phase=1 finished=0 active= 30 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 120.8s] phase=1 finished=0 active= 29 ADN110:1 ADN111:1 ADN112:1
|
||||
[ 143.4s] phase=1 finished=0 active= 32 ADN110:2 ADN111:2 ADN112:2 <-- arrive
|
||||
[ 223.3s] phase=1 finished=0 active= 35 ADN110:2 ADN111:2 ADN112:2
|
||||
```
|
||||
|
||||
**All three flip 1 → 2 at ~143 s**, and the count of records in state 2 climbs
|
||||
**24 → 35** over the same window. So for these squadrons **state 1 is
|
||||
"not yet deployed", not "gone"** — the built-in table's shorthand
|
||||
*"1/3/4 = gone/dead/invalid"* is incomplete, and reading `state != 2` as
|
||||
"destroyed" would have been wrong in exactly the way flagged last iteration.
|
||||
Good that it was flagged rather than assumed.
|
||||
|
||||
### ✅ This also answers a much older question: arrivals DO happen
|
||||
|
||||
[mission-arrival-watch](mission-arrival-watch.md) and the wave work recorded
|
||||
**"0 confirmed arrivals"** after many runs, measured by watching the *craft*
|
||||
population. The script's own unit table shows arrivals plainly: eleven more
|
||||
records enter state 2 within four minutes, three of them the phase-1 objective
|
||||
squadrons at a distinct moment.
|
||||
|
||||
The old negative was not wrong about what it measured — it was measuring the
|
||||
wrong structure. Craft counts conflate deployment with attrition; the per-unit
|
||||
state field does not.
|
||||
|
||||
⚠️ **Both runs of this experiment froze** — at ~70 s and ~253 s — so the window
|
||||
above is all that was observed, and **no phase advance was reached**. The freeze
|
||||
witness caught both immediately, which is the only reason the truncation is
|
||||
visible rather than silently producing a flat line.
|
||||
|
||||
## 🟡 The per-unit `state` encoding is not what the summary implies
|
||||
|
||||
For the three phase-1 objective squadrons, early in a fresh mission:
|
||||
@@ -70,7 +108,12 @@ catching.
|
||||
|
||||
## What this makes possible
|
||||
|
||||
The decisive phase experiment is no longer blocked on attribution: sample
|
||||
`[ScriptMission+40]` and the three squadrons' records together over a run, and a
|
||||
phase advance becomes directly observable along with the state change that caused
|
||||
it. That run has **not** been done yet.
|
||||
The decisive phase experiment is no longer blocked on attribution — and it has
|
||||
now partly run: the arrival of the three objective squadrons is directly
|
||||
observed. What is still missing is a run that survives long enough (no freeze)
|
||||
for them to be **destroyed**, which is when `[ScriptMission+40]` should step to
|
||||
2. Two attempts froze first.
|
||||
|
||||
`tools/re-capture/phase_watch.py` is the harness: it samples the real counter and
|
||||
the watched squadrons together, witnesses the freeze every 60 s, and prints only
|
||||
on change.
|
||||
|
||||
73
tools/re-capture/phase_watch.py
Normal file
73
tools/re-capture/phase_watch.py
Normal file
@@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Watch the REAL phase counter and every squadron's state, together.
|
||||
|
||||
Three earlier runs polled `[*(0x828F35F8)+236]` and saw 0 forever -- that mirror
|
||||
is only written once the ordinal exceeds 1 (script-runtime-probe.md). This reads
|
||||
`[ScriptMission+40]`, the counter itself, plus the per-unit records the phase
|
||||
conditions actually test, so a phase advance and the state change that caused it
|
||||
are visible in one sample.
|
||||
|
||||
It also does two things the earlier probes had to learn the hard way:
|
||||
|
||||
* witnesses the freeze every 60 s (a frozen guest produces a perfectly
|
||||
clean-looking negative -- see mission-freeze-resume-spin.md);
|
||||
* re-locates the ScriptMission if the pointer stops validating, rather than
|
||||
silently reporting stale numbers.
|
||||
|
||||
Usage: phase_watch.py <Stage02.ssb> [secs] [every_s]
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
sys.path.insert(0, __file__.rsplit('/', 1)[0])
|
||||
import gmem
|
||||
import isl
|
||||
import squadron_state as S
|
||||
|
||||
WATCH = ['ADN110', 'ADN111', 'ADN112']
|
||||
|
||||
|
||||
def main():
|
||||
ssb = isl.load(sys.argv[1])
|
||||
sym2 = isl.symbols(ssb, 2)
|
||||
secs = float(sys.argv[2]) if len(sys.argv) > 2 else 900
|
||||
every = float(sys.argv[3]) if len(sys.argv) > 3 else 5
|
||||
path = gmem.mem_path()
|
||||
size = os.path.getsize(path)
|
||||
import frozen
|
||||
t0 = time.time()
|
||||
with open(path, 'rb', buffering=0) as f:
|
||||
m, fb = S.find_mission(f, size, ssb)
|
||||
if m is None:
|
||||
print('ScriptMission not located'); return 1
|
||||
print('file base 0x%08X ScriptMission 0x%08X' % (fb, m), flush=True)
|
||||
last = None
|
||||
next_frozen = 0.0
|
||||
while time.time() - t0 < secs:
|
||||
now = time.time() - t0
|
||||
if now >= next_frozen:
|
||||
next_frozen = now + 60
|
||||
try:
|
||||
dead, _ = frozen.frozen(5.0)
|
||||
except Exception:
|
||||
dead = False
|
||||
if dead:
|
||||
print(' [%6.1fs] *** GUEST FROZEN -- readings below are about '
|
||||
'a dead world ***' % now, flush=True)
|
||||
r = S.read_states(f, m, sym2, WATCH)
|
||||
key = (r['phase_ordinal'], r['finished'], r['active_records'],
|
||||
tuple((n, (v or {}).get('state')) for n, v in r['units'].items()))
|
||||
if key != last:
|
||||
print(' [%6.1fs] phase=%s finished=%s active=%3d %s' % (
|
||||
now, r['phase_ordinal'], r['finished'], r['active_records'],
|
||||
' '.join('%s:%s' % (n, (v or {}).get('state'))
|
||||
for n, v in r['units'].items())), flush=True)
|
||||
last = key
|
||||
time.sleep(every)
|
||||
print('done', flush=True)
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user