route_ports_on: semantic checks depend on battle RNG timing and on frame-exact after: replays #34
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
route_ports_on.*(run_route.py --port all=on --check --semantic) cannot pass once any field port is on, independently of the port's correctness. Found while validating the field ports of #32 (PR fromfield-batch1).Evidence (JP title_to_first_battle_win, one port on at a time)
Each port is shadow-exact over the three routes and fuzzing (0 mismatch), yet each moves the frame where the first battle starts, so the battle RNG seed (game time) changes and the party HP after the battle changes:
DecTimersis a 20-instruction per-frame leaf: removing its CPU time shifts the route by 7 frames (sound handshake / event waits, docs/validation.md "Why on is not compared frame by frame"). Which ports "pass" is luck.With all ports on: title US ok; title JP fails (party_hp); field_menu_tour US fails (party_hp); field_menu_tour JP gets stuck at frame 10156: the route starts with
after:title_to_first_battle_win, i.e. a frame-exact replay of the title movie, which no longer ends on the field when ports change timing.Two causes
party_hpafter a random battle is not a semantic invariant once CPU time changes (battle seed = game time at battle start, lessons.md §5).after:<route>replay that route's movie input by input, under ports on.Possible fixes (decision needed)
after:movie with ports off, switch the ports on at the route's own start; or re-run the previous route's behaviour instead of its movie.party_hponly in exact (non-semantic) checks.narshe_to_world_map with all ports on (field ports of #32 + battle/Rand):
In shadow the same ports are exact over the whole route on both versions (0 mismatch).
Decision (user, 2026-11-02), after an independent review of plan and strategy:
docs/validation.md. Same definition will serve the native build.after:movie: they start from the SRAM start points made by the interpreter (#26).Also in scope: battle policy more robust (more attempts / input jitter),
rom.portsdivergences classified against the timing census (first divergence at an unlisted site = finding), validation doctrine (shadow = exact proof; interpreter movies = frame-exact; ports-on/native = route goal + timing-invariant checkpoints) indocs/validation.md. Cycle charging in bridges is not used.Then PR #35 is updated from
mainand rechecked. Delegated now (branchports-on-checks).Fixed by PR #44 (merged,
b3d3f47).Check definition, before -> after
battles: {...: "won"}, save slot); a route'sEXACT_ONLYkeys (party HP) are compared by exact checks only. Exclusion and justification indocs/validation.md(doctrine section).after:<route>movie replays removed (run_route refuses them); chained routes start from SRAM start points. New producer routetitle_to_mines_save(power-on -> first battle -> mines save point (33, 22), slot 1; US 23 834 / JP 23 368 frames) feedsfield_menu_tourandnarshe_to_world_map.behaviours.win_battle, 8 attempts with jitter (first attempt unchanged, movies keep their inputs).rom.ports: first divergence classified against the timing census (E4/E5/E8 sites, US and JP addresses), unlisted site ->FINDINGline, still a report.narshe_to_world_mapended at a world position that depended on input timing (JP ports-on (84, 36) vs (84, 35)); it now saves on a fixed tile (84, 36).Evidence
Correction to the evidence above: the debug (ASan) rom.ports runs were not OOM-killed; they were stopped on purpose because under ASan the emulator is ~12x slower (5 611 s without finishing, past the 1 800 s ctest timeout). It is slowness, not a hang. rom/slow tests are validated with the release build (rom.ports 335 s, passed, classified E8); debug covers ctest -LE slow (24/24).