The withdrawal last iteration was caused by `rm -f /tmp/xenia-canary.lock` --
the obvious way past a lock orphaned by kill -9, which also disables the guard
for every later launch. Three instances ended up live at once, sharing
/tmp/xenia_pad.txt and display :98, and silently confounded an input experiment.
Care is not a fix, so this is tooling. ensure_single_emulator.sh counts live
instances, stops them (plain kill, then -9, each with a bounded wait), verifies
ZERO, and only then removes the lock -- refusing loudly if any remain. The lock
is never removed before the condition it guards against is verified absent.
FOUR scripts did the bare `rm -f`, and only two were mine from today:
menu_loop_session.sh, title_draw_capture.sh, poke_control.sh and
resume_reliability.sh. So the footgun was corpus-wide rather than introduced
this session. All four now route through the guard.
The guard is controlled rather than assumed: run against a deliberately started
live instance it reports "1 instance(s) live -- stopping them", ends at 0 with
the lock cleared, and exits 0. A guard that only ever passes on an already-clean
slate would prove nothing.
It also kills by process NAME. `pkill -f xenia_canary` matches the shell running
it -- that has now cost this corpus three commands, one of them a cleanup that
died halfway and left the very instances it was meant to remove.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
sylpheed-port noted that build 5's ptloop parent can be static while the leaf
record animates, and asked me to check it against my table. My own corpus
refutes my claim outright.
ptloop-leaf-sweep-positions.txt -- written earlier in this same corpus -- records
ptloop01.rat's nested record at loop length 600, whose leaf pteff03.t32 sweeps a
400 px-wide quad with its centre running x~921->1041 over t=340..370. The
parent's declared rect is (441,270) 200x90. The leaf draws 300 px outside it: the
parent rect is a PIVOT ANCHOR, not the drawn extent.
Checked against the two JP captures: my measured rect differs by 0 px -- and so
does the whole dead region y 270..450 x 480..960 around it -- while the band the
sweep actually occupies (x 721..1241) differs by 44 025 px. The zero was measured
where nothing happens.
So the port's reading is right and now confirmed from the disc: parent static,
leaf animates, and the two nested records cycle at DIFFERENT lengths, 600 and
720. My "single static keyframe" described the parent only. The era adjudication
is unaffected -- its box overlaps the sweep band only at x 721..776, which shows
no between-session differences.
The menu-loop question is still unsettled after a second attempt, and the second
attempt's failure REFUTES my diagnosis of the first. menu_loop_probe.py gated on
the plate pulse (glyph in [500,2500] held 12 samples), fired at t=484.5 s with
glyph 1723 -- a verified settled BOOT title, not the attract one -- pressed A,
and the press was delivered ([file-pad] keystroke vk=5800 down/up, 8 RE-INPUT
lines). Twenty seconds later all five frames still classified as the title
(rmse ~67-70, margins 0.06-0.16, the "neither" signature; screen_id says title).
So "the attract title accepts nothing" does not explain attempt 1, and the
corpus's "the boot title accepts a single A, 2 of 2 runs" is no longer 2 of 2.
METHOD: a declared rect can be an anchor, not an extent -- confirm an element
draws in a region before diffing that region to ask whether it moves.
navigation.md: confirm the screen changed, do not infer it from a delivered
press.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v