port: correct a check that asserted an absence of measurement as a finding
The pair I shipped this iteration -- focus_persists on for main_menu, off everywhere else -- reported both halves as agreement with the contract. Nothing measured that extras does not persist. The corpus has EXTRAS' opening item from one entry and (B) restoring the PARENT's focus 4/4; neither says what a submenu's own cursor does on re-entry. Caught by the Decoder. It is the mirror of the trap it was written to avoid. I refused to let a derived menu-wide rule overwrite a measured value, then let 'not measured here' become a positive assertion of the negative. Both treat a gap in the corpus as if it carried information and differ only in which direction they fill it. And the failure mode was the bad one: if the game does persist EXTRAS, the check holds the port to the wrong behaviour and passes while doing it. check_focus_persists now asserts only the measured half. The scope became a separate guard with its own outcome word -- 'only main_menu, AUTHORED DEFAULT, unmeasured elsewhere' -- which still fails if widened, since that should be a deliberate edit, but can no longer be read as the game being known to reset. focus_persists_why records the correction rather than being rewritten. It also weakens a label. EXTRAS' initial_focus is marked measured and was taken on a single entry; now that the main menu is known to remember its cursor, a one-entry reading of any screen may be measuring history rather than what the screen opens on -- the same objection that reframed the TUTORIAL/NEW GAME disagreement. The observation stands, its reading as an initial focus does not. Caveat attached, kind left as measured with a note that it changes if EXTRAS turns out to persist. Not building on the non-persistence half until their EXTRAS re-entry run returns. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
@@ -219,17 +219,46 @@ def flow_buttons(screen):
|
||||
|
||||
|
||||
def check_focus_persists(h):
|
||||
"""The menu remembers its cursor -- measured on the MAIN MENU, one screen.
|
||||
"""The menu remembers its cursor -- MEASURED, on the main menu, one screen.
|
||||
|
||||
Checked as a pair: the behaviour must be on where it was measured and off
|
||||
everywhere else. A one-sided check would pass a port that had quietly made it
|
||||
a menu-wide rule, which would override `extras`' measured initial focus.
|
||||
🔴 This checked a PAIR until 2026-08-30: on for `main_menu`, off everywhere
|
||||
else. The second half asserted that `extras` does NOT persist, and **nothing
|
||||
measured that**. What the corpus has is EXTRAS' initial focus from a single
|
||||
entry and Ⓑ restoring the PARENT's focus 4/4 — neither says what a submenu's
|
||||
own cursor does on re-entry. So one measured behaviour and one absence of a
|
||||
measurement were being reported identically, and if the game does persist
|
||||
EXTRAS the check would have held the port to the wrong behaviour AND PASSED.
|
||||
|
||||
The mirror of the trap it was written to avoid: refusing to let a derived
|
||||
rule overwrite a measured value, then letting "not measured here" become a
|
||||
positive assertion of the negative. Now only the measured half is asserted
|
||||
against the contract; the scope is a guard, below.
|
||||
"""
|
||||
want = bool(re.search(r"the main menu remembers its cursor; re-entry is not a reset", h))
|
||||
scr = (jload("authored/flow.json") or {}).get("screens") or {}
|
||||
on = [n for n, v in scr.items() if isinstance(v, dict) and v.get("focus_persists")]
|
||||
report("menu remembers its cursor", want or None, on == ["main_menu"] and on,
|
||||
want and on == ["main_menu"])
|
||||
got = (((jload("authored/flow.json") or {}).get("screens") or {})
|
||||
.get("main_menu", {}).get("focus_persists"))
|
||||
report("menu remembers its cursor", want or None, got, want and got is True)
|
||||
|
||||
|
||||
def guard_focus_scope(_h):
|
||||
"""NOT a contract check. A regression guard on an AUTHORED DEFAULT.
|
||||
|
||||
No screen but `main_menu` persists its cursor in this port, and that is the
|
||||
port's choice, not a finding: it preserves EXTRAS' measured opening item and
|
||||
invents the least. Guarded so that widening it is a deliberate edit with a
|
||||
`why`, and labelled so a passing run cannot be read as the game being known
|
||||
to reset.
|
||||
"""
|
||||
global FAIL
|
||||
on = sorted(n for n, v in ((jload("authored/flow.json") or {}).get("screens") or {}).items()
|
||||
if isinstance(v, dict) and v.get("focus_persists"))
|
||||
if on == ["main_menu"]:
|
||||
print(f" {'focus_persists scope':<30} guard only main_menu"
|
||||
f" -- AUTHORED DEFAULT, unmeasured elsewhere")
|
||||
else:
|
||||
FAIL += 1
|
||||
print(f" {'focus_persists scope':<30} 🔴 GUARD {on} -- widened past the"
|
||||
f" one screen measured; needs a why and a measurement")
|
||||
|
||||
|
||||
def check_menu_labels(_h):
|
||||
@@ -295,7 +324,7 @@ def main():
|
||||
for fn in (check_fade_quads, check_fade_out, check_plate_period,
|
||||
check_bgm_window, check_black_hold, check_menu_bank,
|
||||
check_splash_dwell, check_menu_labels, check_extras_labels,
|
||||
check_wrap, check_focus_persists):
|
||||
check_wrap, check_focus_persists, guard_focus_scope):
|
||||
fn(h)
|
||||
print()
|
||||
print(" A passing run means the port agrees with the contract ON THESE VALUES.")
|
||||
|
||||
Reference in New Issue
Block a user