From e7163d5eb62c58b8f3b02ffcbd60ced15753041d Mon Sep 17 00:00:00 2001 From: Sylpheed port agent Date: Sun, 30 Aug 2026 15:28:19 +0000 Subject: [PATCH] port: the third clock was in my own enumeration and I did not wire it Last iteration I enumerated three free-running clocks, wrote that the leaf is pinned only by --leaf-time, then tested reproducibility without passing --leaf-time and concluded nothing free-runs on the menu path. The answer was one paragraph above the experiment that contradicted it. My own flagged weakness found it: deliberate wall-clock variation via --script=wait:N, putting the capture at t=96 units against t=369. Spin pinned only, wait 0.5 vs 5.0 differs by max 91.19 per channel; with --leaf-time=0 added it is byte-identical. draw_leaf_for is ptloop01/ptloop02, present on main_menu and not just the title, which is why that row drifted. verify-capture passed --loop-phase=0 and not --leaf-time=0 -- I fixed the clock I had been bitten by and left the one I had merely listed. Enumeration without follow-through fails exactly like no enumeration. Both are now pinned at all six render sites. main_menu returns 13.21 across three runs and two renders after different waits are byte-identical. The number moved 13.26 -> 13.21 and that is NOT an accuracy improvement: pinning the leaf at phase 0 puts ptloop01/02 at one specific pose rather than wherever the wall clock left them. A different configuration, now reproducible. Which pose the game shows at rest is not settled by this. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF --- docs/port/DECISIONS.md | 53 ++++++++++++++++++++++++++++++++++++++- tools/port/verify-capture | 12 ++++----- 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index bf4cff25..9d287ba0 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -9,7 +9,7 @@ dies, which is what this file is for. -174 sections. Search this before re-deriving anything. +175 sections. Search this before re-deriving anything. * [P0 β€” the exporter, 2026-08-28](#p0--the-exporter-2026-08-28) * [P1 β€” Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28) @@ -185,6 +185,7 @@ dies, which is what this file is for. * [Counting the fallbacks instead of inspecting them β€” and one I had misjudged](#counting-the-fallbacks-instead-of-inspecting-them--and-one-i-had-misjudged) * [The oracle harness was nondeterministic, and I quoted its numbers for a dozen iterations](#the-oracle-harness-was-nondeterministic-and-i-quoted-its-numbers-for-a-dozen-iterations) * [Answering "an unenumerated set" β€” don't enumerate, test](#answering-an-unenumerated-set--dont-enumerate-test) +* [πŸ”΄ The third clock was in my own list, and I did not wire it](#the-third-clock-was-in-my-own-list-and-i-did-not-wire-it) ## P0 β€” the exporter, 2026-08-28 @@ -9968,3 +9969,53 @@ this time the proxy was my own tool's output format. ⚠️ Conclusion unchanged: 2.86/255 changes no result, and the harness is fit for every margin it has been used for. What was wrong was the claim's basis, not the claim. + +## πŸ”΄ The third clock was in my own list, and I did not wire it + +Last iteration I enumerated three free-running clocks, said the leaf was pinned +only by `--leaf-time`, then tested reproducibility **without passing +`--leaf-time`** and concluded *"nothing free-runs on the menu path"*. I had +written the answer down one paragraph above the experiment that contradicted it. + +⚠️ I also flagged the weakness myself β€” *"I have not tested against a deliberately +varied wall clock, only whatever variation two consecutive runs happen to +produce"* β€” and that flag is what found this. + +### Deliberate variation finds it immediately + +`--menu=main_menu --script=wait:N --loop-phase=0`, varying N so the capture lands +at genuinely different clock positions (t = **96 units** at N=0.5, **369** at +N=5.0): + +| | max per-channel | +|---|---| +| wait 0.5 vs 5.0, spin pinned only | **91.19** | +| …with `--leaf-time=0` added | **0** | + +βœ… Byte-identical. The leaf was the whole of the residual, and `draw_leaf_for` is +`["ptloop01", "ptloop02"]` β€” present on `main_menu`, not just the title, which is +why the menu row drifted. + +πŸ”΄ **`verify-capture` passed `--loop-phase=0` and not `--leaf-time=0`.** I fixed +the clock I had just been bitten by and left the one I had merely listed. That is +the same shape as the guard built for one clock while the row that drifted used a +second β€” except this time the set *was* enumerated and I still did not act on it. +**Enumeration without follow-through fails exactly like no enumeration.** + +### Now pinned, and verified by frame rather than by statistic + +`verify-capture` pins both at all six render sites. `main_menu` returns **13.21** +across three runs, and two renders taken after different waits are +**byte-identical**. + +⚠️ **The number moved, 13.26 β†’ 13.21, and that is not an accuracy improvement.** +Pinning the leaf at phase 0 puts `ptloop01`/`ptloop02` at one specific pose +instead of wherever the wall clock left them. It is a *different configuration*, +now a reproducible one. Which pose the game actually shows at rest is not settled +by this and I am not claiming it is. + +πŸ“Œ The Decoder's framing applies to their own correction and to mine equally: +**reaching for the number that is to hand instead of the one that applies.** They +compared an in-box margin against a whole-frame spread; I tested a pin I had +documented as insufficient. Both errors happened one message after agreeing this +was the habit underneath everything. diff --git a/tools/port/verify-capture b/tools/port/verify-capture index 8e6f236b..924889a8 100755 --- a/tools/port/verify-capture +++ b/tools/port/verify-capture @@ -144,20 +144,20 @@ for row in "${MAP[@]}"; do if [ ${#want[@]} -gt 0 ] && ! printf '%s\n' "${want[@]}" | grep -qx "$name"; then continue; fi [ -f "$cap" ] || { printf '%-17s %s\n' "$name" "no capture"; continue; } if [ "$pose" = band ]; then - godot --path port --resolution 1280x720 -- --loop-phase=0 "--screen=title" --overlay=press_start \ + godot --path port --resolution 1280x720 -- --loop-phase=0 --leaf-time=0 "--screen=title" --overlay=press_start \ --time=3.95 "--capture=$OUT/$name.full.png" >"$OUT/$name.log" 2>&1 || true [ -f "$OUT/$name.full.png" ] && convert "$OUT/$name.full.png" \ -crop 1279x120+0+520 +repage "$OUT/$name.render.png" elif [ "$pose" = focus ]; then - godot --path port --resolution 1280x720 -- --loop-phase=0 "--menu=main_menu" "--focus=$forced" \ + godot --path port --resolution 1280x720 -- --loop-phase=0 --leaf-time=0 "--menu=main_menu" "--focus=$forced" \ --script=wait "--shots=$OUT/$name" >"$OUT/$name.log" 2>&1 || true [ -f "$OUT/${name}_00_start.png" ] && cp "$OUT/${name}_00_start.png" "$OUT/$name.render.png" elif [ "$pose" = menu ]; then - godot --path port --resolution 1280x720 -- --loop-phase=0 "--menu=$name" --script=wait \ + godot --path port --resolution 1280x720 -- --loop-phase=0 --leaf-time=0 "--menu=$name" --script=wait \ "--shots=$OUT/$name" >"$OUT/$name.log" 2>&1 || true [ -f "$OUT/${name}_00_start.png" ] && cp "$OUT/${name}_00_start.png" "$OUT/$name.render.png" elif [ "$pose" = plate ]; then - godot --path port --resolution 1280x720 -- --loop-phase=0 "--screen=title" --overlay=press_start \ + godot --path port --resolution 1280x720 -- --loop-phase=0 --leaf-time=0 "--screen=title" --overlay=press_start \ --time=3.95 "--capture=$OUT/$name.render.png" >"$OUT/$name.log" 2>&1 || true elif [ "$pose" = t357 ]; then # πŸ”΄ NO `--time` HERE EITHER, and the row's note used to claim otherwise. @@ -177,7 +177,7 @@ for row in "${MAP[@]}"; do # # So: pose at the settle, which is what was actually being measured, and let # the leaf loop carry the sweeps' phase. - godot --path port --resolution 1280x720 -- --loop-phase=0 "--screen=$name" \ + godot --path port --resolution 1280x720 -- --loop-phase=0 --leaf-time=0 "--screen=$name" \ "--capture=$OUT/$name.render.png" >"$OUT/$name.log" 2>&1 || true else # NO `--time`. It used to pass `--time=99` as an idiom for "settled", and @@ -189,7 +189,7 @@ for row in "${MAP[@]}"; do # that accident. Now that `--time` is honoured, asking for it explicitly # would pose past the end of every group, so the request is simply dropped # and the settled pose asked for by omission. - godot --path port --resolution 1280x720 -- --loop-phase=0 "--screen=$name" \ + godot --path port --resolution 1280x720 -- --loop-phase=0 --leaf-time=0 "--screen=$name" \ "--capture=$OUT/$name.render.png" >"$OUT/$name.log" 2>&1 || true fi [ -f "$OUT/$name.render.png" ] || { printf '%-17s %s\n' "$name" "render failed"; continue; }