re: the main menu remembers its cursor across menu -> title -> menu
F1 TUTORIAL, two delivery-confirmed DOWNs to EXTRAS, B to the title, A back: F3 is EXTRAS. Re-entry restores the item you left. Reframes the initial-focus disagreement rather than settling it: if focus persists, any 'initial focus' reading not taken on a fresh boot's first menu entry measures history. It still says nothing about what the menu opens on -- this run's F1 was itself carried over from a prior probe's press. Reached on the plate-pulse gate, not boot_menu.sh, whose stillness test cannot fire on this title -- TITLE at 422.7 s on a boot skip_intro could not gate at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
This commit is contained in:
@@ -10,6 +10,32 @@ delivered.
|
||||
|
||||
|
||||
|
||||
|
||||
## ✅ 2026-08-30 — the main menu remembers its cursor; re-entry is not a reset
|
||||
|
||||
**measured, and it changes what `on_cancel` should do.** Ⓑ from the menu to the
|
||||
title and Ⓐ back returns you to **the item you left**, not to a default.
|
||||
|
||||
| step | focus |
|
||||
|---|---|
|
||||
| on the menu | `TUTORIAL` |
|
||||
| after 2× DOWN (both delivery-confirmed) | `EXTRAS` |
|
||||
| after Ⓑ → title → Ⓐ → menu | **`EXTRAS`** |
|
||||
|
||||
Control passed: two DOWN presses moved the cursor exactly two items, and the run
|
||||
is discarded if they do not.
|
||||
[`data/focus-persists-across-title.txt`](../re/data/focus-persists-across-title.txt)
|
||||
|
||||
📌 **This also reframes the initial-focus warning I sent earlier today.** If focus
|
||||
persists, an "initial focus" reading not taken on a fresh boot's *first* menu entry
|
||||
is measuring history — so the records that disagree need not disagree about the
|
||||
game. **It still does not say what the menu opens on.** Your authored `NEW GAME`
|
||||
stands on its own reasoning; nothing here confirms or refutes it.
|
||||
|
||||
⚠️ Reach: one boot, one round trip, one direction. Persistence across a **reboot**
|
||||
is untested and is the reading that would matter for authoring a default.
|
||||
|
||||
|
||||
## 🔴 2026-08-30 — do not hardcode the menu's initial focus; the sources disagree
|
||||
|
||||
**New, and it is a warning rather than an answer.** `menu-navigation-semantics.md`
|
||||
|
||||
62
docs/re/data/focus-persists-across-title.txt
Normal file
62
docs/re/data/focus-persists-across-title.txt
Normal file
@@ -0,0 +1,62 @@
|
||||
# Does the main menu REMEMBER its cursor across menu -> title -> menu?
|
||||
# MEASURED 2026-08-30. Answer: YES.
|
||||
#
|
||||
# WHY IT MATTERS: menu-navigation-semantics.md records initial focus as TUTORIAL
|
||||
# (2/2 boots) while boot_menu.sh's closing line says NEW GAME and
|
||||
# menu-state-in-memory.md reaches EXTRAS in four downs, which only counts from
|
||||
# NEW GAME. If focus PERSISTS, then any "initial focus" reading not taken on a
|
||||
# fresh boot's FIRST menu entry is measuring history, not initial focus -- which
|
||||
# would explain the disagreement without any of the records being wrong.
|
||||
#
|
||||
# HARNESS: tools/re-capture/focus_persistence.py, on the path b_from_menu.py
|
||||
# validated -- plate-pulse title detector, glyph-327 menu detector, and every
|
||||
# press confirmed from the guest's own [RE-INPUT] log rather than from the pad.
|
||||
# NOT boot_menu.sh: its title gate tests for stillness and this title never
|
||||
# stills (harness-title-gate-assumes-a-static-title.md). The plate-pulse gate
|
||||
# reached TITLE at 422.7 s on the boot skip_intro could not gate at all.
|
||||
#
|
||||
# ✅ CONTROL, and it is the reason run 1 is discarded rather than reported:
|
||||
# two DOWN presses must move the cursor exactly two items. If they do not,
|
||||
# the reader is not tracking and F3 may not be read.
|
||||
#
|
||||
# [ 1.0s] MENU (glyph 327) F1 = TUTORIAL ring 130 76 254 69 64
|
||||
# [ 7.3s] DOWN delivered (attempt 1)
|
||||
# [ 8.2s] DOWN delivered (attempt 1)
|
||||
# [ 1.0s] after 2x DOWN F2 = EXTRAS ring 130 76 66 69 254
|
||||
# ✅ CONTROL PASSED: 2x DOWN moved TUTORIAL -> EXTRAS
|
||||
# [ 13.3s] B delivered (attempt 1)
|
||||
# [ 24.0s] BACK AT TITLE (glyph 1403)
|
||||
# [ 25.8s] A delivered (attempt 1)
|
||||
# [ 33.6s] MENU AGAIN F3 = EXTRAS ring 130 76 66 69 254
|
||||
#
|
||||
# F1=TUTORIAL F2=EXTRAS F3=EXTRAS => FOCUS PERSISTS
|
||||
#
|
||||
# The ring vector is menu_focus.py's geometry byte for byte: the peak moves from
|
||||
# index 2 to index 4 and STAYS at 4 across the round trip.
|
||||
#
|
||||
################################################################################
|
||||
# 🔴 RUN 1 IS DISCARDED, AND ITS FAILURE IS THE USEFUL PART.
|
||||
#
|
||||
# The first attempt read F1 = LOAD GAME and F2 = LOAD GAME -- the cursor had not
|
||||
# moved -- and the control refused to report F3. The cause was NOT the reader:
|
||||
# the two frames genuinely differ by 911 px, so they are different frames. It is
|
||||
# that run 1 sent the DOWN presses through pad.py with NO delivery confirmation,
|
||||
# while A and B were confirmed. The guest's own log settles it:
|
||||
#
|
||||
# vk=5811 (dpad down) flags=0001 ... delivered ONCE for TWO presses
|
||||
# vk=5800 (A) flags=0001 ... delivered once
|
||||
#
|
||||
# So a press that leaves the harness is not a press the guest received, and the
|
||||
# corpus already knew that for A and B and had not applied it to the d-pad.
|
||||
# Fixed: every press in this probe is now confirmed the same way, and the run
|
||||
# above shows 2/2 DOWN delivered.
|
||||
#
|
||||
# ⚠️ REACH. One boot, one round trip, one direction. NOT tested:
|
||||
# * persistence across a full REBOOT -- this is within one boot;
|
||||
# * whether F1 = TUTORIAL here is an initial focus. IT IS NOT: run 1 had
|
||||
# already moved the cursor LOAD GAME -> TUTORIAL with its one delivered
|
||||
# press, and run 2 found it still on TUTORIAL. That is a second, incidental
|
||||
# confirmation of persistence -- across two separate probe processes -- but
|
||||
# it means this run says NOTHING about what the menu opens on.
|
||||
# * whether a longer absence, or a submenu round trip, behaves the same.
|
||||
# (Ⓑ from a submenu restoring the entered-from item is already 4/4.)
|
||||
@@ -30,6 +30,30 @@ with [`tools/re-capture/menu_focus.py`](../../tools/re-capture/menu_focus.py).
|
||||
Wrap holds on both screens tested — the 5-item main menu and the 3-item `EXTRAS`
|
||||
submenu — so it is a menu rule, not a per-screen table.
|
||||
|
||||
## ✅ 2026-08-30 — the menu REMEMBERS its cursor across menu → title → menu
|
||||
|
||||
**measured** — [`data/focus-persists-across-title.txt`](data/focus-persists-across-title.txt),
|
||||
`tools/re-capture/focus_persistence.py`. One run, control passed:
|
||||
|
||||
| step | focus | ring vector |
|
||||
|---|---|---|
|
||||
| F1, on the menu | `TUTORIAL` | 130 76 **254** 69 64 |
|
||||
| F2, after 2× DOWN (**both delivery-confirmed**) | `EXTRAS` | 130 76 66 69 **254** |
|
||||
| F3, after Ⓑ → title → Ⓐ → menu | **`EXTRAS`** | 130 76 66 69 **254** |
|
||||
|
||||
**F3 == F2, so focus persists** — the menu is re-entered on the item you left,
|
||||
not on a fixed one.
|
||||
|
||||
📌 **And this reframes the disagreement below rather than settling it.** If focus
|
||||
persists, then *any* "initial focus" reading not taken on a fresh boot's **first**
|
||||
menu entry is measuring history. The records need not disagree about the game at
|
||||
all — they may differ in what the cursor had already been moved to. **Nothing here
|
||||
says what the menu opens on**; this run's F1 was itself carried over from a prior
|
||||
probe's press.
|
||||
|
||||
⚠️ Reach: one boot, one round trip, one direction. Persistence across a **reboot**
|
||||
is untested, and is the reading that would matter for authoring a default.
|
||||
|
||||
⚠️ **2026-08-30 — and the sources DISAGREE, which nothing here had noticed.**
|
||||
`boot_menu.sh`'s own closing line says *"AT MAIN MENU (cursor on NEW GAME)"*, and
|
||||
[`menu-state-in-memory.md`](menu-state-in-memory.md)'s run reaches `EXTRAS` in
|
||||
|
||||
196
tools/re-capture/focus_persistence.py
Executable file
196
tools/re-capture/focus_persistence.py
Executable file
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Does the main menu REMEMBER its cursor across menu -> title -> menu?
|
||||
|
||||
menu-navigation-semantics.md carries this 🟡: "Initial focus is reproducible but
|
||||
not established as invariant. Both of my boots opened on TUTORIAL, and both used
|
||||
boot_menu.sh." Two runs through one harness are not two samples. And the sources
|
||||
DISAGREE: boot_menu.sh's own closing line says NEW GAME, and
|
||||
menu-state-in-memory.md reaches EXTRAS in four downs, which only counts from NEW
|
||||
GAME. Two say NEW GAME, one says TUTORIAL.
|
||||
|
||||
⚠️ THIS DELIBERATELY DOES NOT USE boot_menu.sh. Its title gate admits a "static"
|
||||
screen at d <= 1500 between grabs 0.6 s apart, and the title never stills -- the
|
||||
sweep leaves free-run. Minimum observed 1551 over 72 samples, 0 able to pass.
|
||||
See harness-title-gate-assumes-a-static-title.md. Everything here is instead the
|
||||
harness b_from_menu.py validated: plate-pulse title detector, glyph-327 menu
|
||||
detector, delivery confirmed from [RE-INPUT] rather than from the pad.
|
||||
|
||||
SEQUENCE
|
||||
F1 focus when the menu first appears <- re-measures initial focus
|
||||
F2 focus after 2x DOWN <- CONTROL for the focus reader
|
||||
F3 focus after B (to title) then A (back) <- persist or reset?
|
||||
|
||||
F3 == F2 => the menu restores where you were. F3 == F1 => it resets.
|
||||
|
||||
🔴 CONTROL GATE: if F2 is not exactly two items below F1 (with wrap), the reader
|
||||
is not tracking the cursor and NOTHING after it may be read. The run says so and
|
||||
stops rather than reporting a number it cannot justify.
|
||||
|
||||
focus_persistence.py LOG OUTDIR [wait_s]
|
||||
"""
|
||||
import os, re, subprocess, sys, time
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
LOG, OUT = sys.argv[1], sys.argv[2]
|
||||
WAIT = float(sys.argv[3]) if len(sys.argv) > 3 else 900
|
||||
W, H = 1280, 720
|
||||
NEED, CEIL, HOLD = 500, 2500, 12 # title plate pulse band
|
||||
MENU_LO, MENU_HI, MENU_HOLD = 250, 420, 6 # glyph-327 menu detector
|
||||
PAD = os.path.join(os.path.dirname(os.path.abspath(__file__)), "pad.py")
|
||||
|
||||
# menu_focus.py's geometry, byte for byte: the focus RING sits in the gutter
|
||||
# left of the label and nothing else is bright there.
|
||||
NAMES = ["NEW GAME", "LOAD GAME", "TUTORIAL", "OPTIONS", "EXTRAS"]
|
||||
YS = [166, 241, 315, 390, 465]
|
||||
|
||||
|
||||
def focus(a):
|
||||
g = np.asarray(Image.fromarray(a.astype(np.uint8)).convert("L"), dtype=float)
|
||||
v = [g[y - 20:y + 20, 500:542].max() for y in YS]
|
||||
return int(np.argmax(v)), v
|
||||
|
||||
|
||||
def deliveries(vk):
|
||||
pat = re.compile((r"RE-INPUT\] XamInputGetKeystrokeEx -> user=\d+ vk=%s flags=0001" % vk).encode())
|
||||
try:
|
||||
return len(pat.findall(open(LOG, "rb").read()))
|
||||
except FileNotFoundError:
|
||||
return 0
|
||||
|
||||
|
||||
def press(btn, vk, tries=5):
|
||||
for k in range(tries):
|
||||
before = deliveries(vk)
|
||||
subprocess.run([sys.executable, PAD, "tap", btn, "0.5"], check=False)
|
||||
for _ in range(20):
|
||||
time.sleep(0.25)
|
||||
if deliveries(vk) > before:
|
||||
print(f"[{time.time()-T0:7.1f}s] {btn} delivered (attempt {k+1})", flush=True)
|
||||
return True
|
||||
print(f"[{time.time()-T0:7.1f}s] {btn} NOT delivered (attempt {k+1})", flush=True)
|
||||
return False
|
||||
|
||||
|
||||
def _open():
|
||||
return subprocess.Popen(
|
||||
["ffmpeg", "-loglevel", "error", "-f", "x11grab", "-draw_mouse", "0",
|
||||
"-video_size", f"{W}x{H}", "-i", ":98", "-r", "4",
|
||||
"-f", "rawvideo", "-pix_fmt", "rgb24", "-"],
|
||||
stdout=subprocess.PIPE, bufsize=W * H * 3 * 2)
|
||||
|
||||
|
||||
def fresh(proc):
|
||||
"""A CURRENT frame, not a buffered one.
|
||||
|
||||
⚠️ Reading one frame from the pipe after a sleep returns whatever ffmpeg
|
||||
buffered while we were not reading. Reopening the stream is the only cheap
|
||||
way to be sure the frame is now.
|
||||
"""
|
||||
proc.kill()
|
||||
q = _open()
|
||||
a = None
|
||||
for _ in range(3):
|
||||
buf = q.stdout.read(W * H * 3)
|
||||
if len(buf) == W * H * 3:
|
||||
a = np.frombuffer(buf, np.uint8).reshape(H, W, 3).astype(int)
|
||||
return q, a
|
||||
|
||||
|
||||
def glyph(a):
|
||||
r, g, b = a[:, :, 0], a[:, :, 1], a[:, :, 2]
|
||||
return int(((g > 130) & (g - r > 45) & (g - b > 45)).sum())
|
||||
|
||||
|
||||
T0 = time.time()
|
||||
p, n, seg = _open(), W * H * 3, time.time()
|
||||
os.makedirs(OUT, exist_ok=True)
|
||||
log = open(f"{OUT}/series.tsv", "w"); log.write("# t_s\tglyph\tphase\n")
|
||||
phase, streak, mark = ("frommenu" if "--from-menu" in sys.argv else "wait"), 0, None
|
||||
F1 = F2 = F3 = None
|
||||
|
||||
while True:
|
||||
el = time.time() - T0
|
||||
if el > WAIT:
|
||||
print(f"TIMEOUT in phase {phase}", flush=True); break
|
||||
if time.time() - seg > 30:
|
||||
p.kill(); p = _open(); seg = time.time()
|
||||
buf = p.stdout.read(n)
|
||||
if len(buf) < n:
|
||||
p.kill(); p = _open(); seg = time.time(); continue
|
||||
a = np.frombuffer(buf, np.uint8).reshape(H, W, 3).astype(int)
|
||||
c = glyph(a)
|
||||
log.write(f"{el:.3f}\t{c}\t{phase}\n"); log.flush()
|
||||
|
||||
if phase == "frommenu":
|
||||
# already sitting on the menu: fall straight into the menu handler
|
||||
streak = MENU_HOLD; phase = "tomenu"
|
||||
|
||||
elif phase == "wait":
|
||||
streak = streak + 1 if NEED <= c <= CEIL else 0
|
||||
if streak >= HOLD:
|
||||
print(f"[{el:7.1f}s] TITLE (glyph {c})", flush=True)
|
||||
press("A", "5800"); phase, streak = "tomenu", 0
|
||||
|
||||
elif phase == "tomenu":
|
||||
streak = streak + 1 if MENU_LO <= c <= MENU_HI else 0
|
||||
if streak >= MENU_HOLD:
|
||||
time.sleep(2.0) # let the menu settle
|
||||
p, a = fresh(p)
|
||||
Image.fromarray(a.astype(np.uint8)).save(f"{OUT}/1-F1.png")
|
||||
F1, v = focus(a)
|
||||
print(f"[{el:7.1f}s] MENU (glyph {c}) F1 = {NAMES[F1]} ring "
|
||||
+ " ".join(f"{x:5.0f}" for x in v), flush=True)
|
||||
# 🔴 Run 1 pressed DOWN twice through pad.py with NO delivery
|
||||
# confirmation and the guest logged vk=5811 exactly ONCE. A and B
|
||||
# were confirmed; the d-pad was not, so the run was unreadable.
|
||||
# Confirm every press the same way.
|
||||
ok = all(press("DOWN", "5811") for _ in range(2))
|
||||
if not ok:
|
||||
print("🔴 a DOWN was never delivered — refusing to read F2", flush=True)
|
||||
break
|
||||
time.sleep(1.5)
|
||||
p, a = fresh(p)
|
||||
Image.fromarray(a.astype(np.uint8)).save(f"{OUT}/2-F2.png")
|
||||
F2, v = focus(a)
|
||||
print(f"[{el:7.1f}s] after 2x DOWN F2 = {NAMES[F2]} ring "
|
||||
+ " ".join(f"{x:5.0f}" for x in v), flush=True)
|
||||
want = (F1 + 2) % len(NAMES)
|
||||
if F2 != want:
|
||||
print(f"🔴 CONTROL FAILED: 2x DOWN from {NAMES[F1]} should give "
|
||||
f"{NAMES[want]}, read {NAMES[F2]}. The reader is not tracking "
|
||||
f"the cursor; refusing to report F3.", flush=True)
|
||||
break
|
||||
print(f"✅ CONTROL PASSED: 2x DOWN moved {NAMES[F1]} -> {NAMES[F2]}", flush=True)
|
||||
press("B", "5801"); mark = time.time(); phase, streak = "backtitle", 0
|
||||
|
||||
elif phase == "backtitle":
|
||||
streak = streak + 1 if NEED <= c <= CEIL else 0
|
||||
if streak >= HOLD:
|
||||
Image.fromarray(a.astype(np.uint8)).save(f"{OUT}/3-title.png")
|
||||
print(f"[{el:7.1f}s] BACK AT TITLE (glyph {c})", flush=True)
|
||||
press("A", "5800"); phase, streak = "remenu", 0
|
||||
elif time.time() - mark > 60:
|
||||
print(f"[{el:7.1f}s] B did not reach the title in 60 s (glyph {c})", flush=True)
|
||||
break
|
||||
|
||||
elif phase == "remenu":
|
||||
streak = streak + 1 if MENU_LO <= c <= MENU_HI else 0
|
||||
if streak >= MENU_HOLD:
|
||||
time.sleep(2.0)
|
||||
p, a = fresh(p)
|
||||
Image.fromarray(a.astype(np.uint8)).save(f"{OUT}/4-F3.png")
|
||||
F3, v = focus(a)
|
||||
print(f"[{el:7.1f}s] MENU AGAIN F3 = {NAMES[F3]} ring "
|
||||
+ " ".join(f"{x:5.0f}" for x in v), flush=True)
|
||||
print(f"\nF1={NAMES[F1]} F2={NAMES[F2]} F3={NAMES[F3]}")
|
||||
if F3 == F2:
|
||||
print("=> FOCUS PERSISTS across menu -> title -> menu")
|
||||
elif F3 == F1:
|
||||
print("=> FOCUS RESETS to its initial item")
|
||||
else:
|
||||
print("=> NEITHER — F3 matches neither F1 nor F2; unexplained")
|
||||
break
|
||||
|
||||
p.kill()
|
||||
print("FOCUS PERSISTENCE RUN DONE", flush=True)
|
||||
@@ -1,58 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# Does the main menu REMEMBER its cursor across menu -> title -> menu?
|
||||
#
|
||||
# menu-navigation-semantics.md carries this 🟡: "Initial focus is reproducible
|
||||
# but not established as invariant. Both of my boots opened on TUTORIAL, and
|
||||
# both used boot_menu.sh." Two runs through one harness are not two samples --
|
||||
# the same shape as two captures through one gate (plate-pulse-phase-lock.md).
|
||||
#
|
||||
# And the sources DISAGREE. boot_menu.sh's own final line says "cursor on NEW
|
||||
# GAME"; the page says TUTORIAL 2/2; menu-state-in-memory.md reaches EXTRAS in
|
||||
# four downs, which only counts from NEW GAME. Two say NEW GAME, one says
|
||||
# TUTORIAL.
|
||||
#
|
||||
# ONE BOOT settles both, and the round trip is the part no run has done:
|
||||
# F1 focus when the menu first appears <- re-measures initial focus
|
||||
# F2 focus after 2x DOWN <- CONTROL for the reader
|
||||
# F3 focus after B (to title) then A (back) <- persist or reset?
|
||||
#
|
||||
# F3 == F2 => the menu restores where you were; F3 == F1 => it resets.
|
||||
# If F2 is not two items below F1 the reader is not tracking the cursor and
|
||||
# NOTHING below it may be read. Run as ONE BLOCKING FOREGROUND call.
|
||||
set -u
|
||||
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
|
||||
SD="$(cd "$(dirname "$0")" && pwd)"
|
||||
OUT="${OUT:-/sylph-home/re/focuspersist}"; mkdir -p "$OUT"
|
||||
NAMES=(NEW_GAME LOAD_GAME TUTORIAL OPTIONS EXTRAS)
|
||||
|
||||
. "$SD/ensure_single_emulator.sh"
|
||||
|
||||
echo "── EFFECTIVE CONFIG ──────────────────────────────"
|
||||
echo " out dir = $OUT"
|
||||
echo " harness = boot_menu.sh (the one under suspicion)"
|
||||
echo " sequence = F1 -> 2x DOWN -> F2 -> B -> plate pulse -> A -> F3"
|
||||
|
||||
BOOT_MENU_LOG="$OUT/boot.stdout" "$SD/boot_menu.sh" fp >"$OUT/boot.log" 2>&1 \
|
||||
|| { echo "BOOT FAILED"; tail -5 "$OUT/boot.log"; exit 1; }
|
||||
tail -2 "$OUT/boot.log"
|
||||
|
||||
shot(){ screenshot "$OUT/$1.png" >/dev/null 2>&1; }
|
||||
focus(){ python3 "$SD/menu_focus.py" "$OUT/$1.png" | tail -1; }
|
||||
|
||||
shot f1; echo "F1 $(focus f1)"
|
||||
|
||||
python3 "$SD/pad.py" dpad down 0.06; sleep 1
|
||||
python3 "$SD/pad.py" dpad down 0.06; sleep 2
|
||||
shot f2; echo "F2 $(focus f2)"
|
||||
|
||||
echo "-- B to the title --"
|
||||
python3 "$SD/pad.py" tap B 0.25
|
||||
python3 "$SD/wait_plate_pulse.py" 120 >"$OUT/pulse.log" 2>&1 \
|
||||
&& echo " title settled (plate pulse)" || echo " ⚠️ NO PLATE PULSE in 120 s"
|
||||
shot title
|
||||
|
||||
echo "-- A back to the menu --"
|
||||
python3 "$SD/pad.py" tap A 0.25; sleep 12
|
||||
shot f3; echo "F3 $(focus f3)"
|
||||
|
||||
echo "FOCUS PERSISTENCE RUN DONE"
|
||||
36
tools/re-capture/focus_persistence_session.sh
Executable file
36
tools/re-capture/focus_persistence_session.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
# Boot, then run focus_persistence.py. NO skip_intro -- the probe finds the title
|
||||
# itself by the plate pulse, which is the gate that works on a screen whose sweep
|
||||
# leaves never stop (harness-title-gate-assumes-a-static-title.md).
|
||||
set -u
|
||||
export HOME=/sylph-home/re SDL_AUDIODRIVER=dummy DISPLAY=:98
|
||||
SD="$(cd "$(dirname "$0")" && pwd)"
|
||||
OUT="${OUT:-/sylph-home/re/focuspersist}"; mkdir -p "$OUT"
|
||||
LOG="$OUT/canary.stdout"
|
||||
|
||||
bash "$SD/ensure_single_emulator.sh"
|
||||
|
||||
if ! xdpyinfo -display "$DISPLAY" >/dev/null 2>&1; then
|
||||
rm -f "/tmp/.X${DISPLAY#:}-lock" 2>/dev/null || true
|
||||
nohup bash -c 'Xvfb "$0" -screen 0 1280x720x24 -ac -nolisten tcp \
|
||||
+extension GLX +extension RANDR >/tmp/xvfb98.log 2>&1' "$DISPLAY" </dev/null >/dev/null 2>&1 &
|
||||
for _ in $(seq 1 50); do xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 && break; done
|
||||
nohup env DISPLAY="$DISPLAY" HOME=/sylph-home openbox </dev/null >/tmp/openbox98.log 2>&1 &
|
||||
fi
|
||||
xdpyinfo -display "$DISPLAY" >/dev/null 2>&1 || { echo "DISPLAY UNAVAILABLE"; exit 1; }
|
||||
|
||||
# The profile is NOT optional: naming a XUID with no profile opens a sign-in
|
||||
# dialog, and IsUIActive() then swallows every keystroke for the rest of the run.
|
||||
XUID="${SYLPH_XUID:-$(ls "${XENIA_CONTENT:-$HOME/.local/share/Xenia/content}" 2>/dev/null | head -1)}"
|
||||
[ -n "$XUID" ] || { echo "NO PROFILE"; exit 2; }
|
||||
|
||||
echo "── EFFECTIVE CONFIG ──────────────────────────────"
|
||||
echo " out dir = $OUT"
|
||||
echo " profile = $XUID"
|
||||
echo " title gate= plate pulse (NOT skip_intro's stillness test)"
|
||||
echo " log = $LOG [RE-INPUT] delivery confirmation reads this"
|
||||
|
||||
cd /sylph-home/re
|
||||
nohup run-canary --apu=sdl --log_mask=13 --log_level=2 \
|
||||
--logged_profile_slot_0_xuid="$XUID" </dev/null >"$LOG" 2>&1 &
|
||||
python3 "$SD/focus_persistence.py" "$LOG" "$OUT" "${WAIT:-900}"
|
||||
Reference in New Issue
Block a user