diff --git a/docs/port/DECISIONS.md b/docs/port/DECISIONS.md index 45299003..d976c28a 100644 --- a/docs/port/DECISIONS.md +++ b/docs/port/DECISIONS.md @@ -3433,3 +3433,68 @@ free and a history of parallel builds OOM-killing the host. should start it mid-loop. Until then the port keeps authoring with the known recorded: one stream of three, 🔴 in the manifest, the console line and `authored/audio.json`. + +## The settle run carries an unmeasured real-time factor — and the numbers it touches were already unauthored + +The Decoder has withdrawn one of the two arguments propping up its settle-time +run. It had claimed the plate *pulse period* was an internal clock proving the +run was not slowed; re-examined, that estimate rests on **one interval at a +125 ms sample interval (±6.7 %)**, and re-running the trough-picking gives +**2.628 s** rather than the 2.369 quoted — an adjacent local minimum had been +counted as a separate trough. Against the corpus's 2.24 s that is **+17.3 %**. It +is too weak to show anything and **cannot resolve a real-time factor below +~7 %**. + +**✅ Nothing in the port moves, and this is the second time in two iterations that +the right call was to have authored nothing.** + +| number from that run | anchored by | did the port take it? | +|---|---|---| +| title → plate, 2.247 s | three prior readings (2.13 / 2.132 / 2.138) and the disc's declared 120 units | ✅ it is what the port already draws | +| menu build-in, 0.531 s | **nothing** | ❌ not authored | +| Ⓑ → title, 0.482 s | **nothing** | ❌ not authored | +| Ⓐ → menu, 3.763 s | contains a 1.53 s load stall | ❌ explicitly refused | + +Checked rather than remembered: `grep` over `authored/` and `port/scripts/` finds +no `0.531` and no `0.482`. The only build-in reference in the tree is the plate +arithmetic — `t=118 → t=238`, 120 units — which is the **anchored** leg. + +I declined those two because they were one-run figures the Decoder had itself +flagged, and because the port was already within ~0.1 s of both from the disc's +own keyframes. **That reasoning has now been joined by a second, independent one +I did not have at the time**: a few per cent of slowdown sits inside them +undetected. A provisional measurement adopted over a decoded number would have +imported an error nobody could see. + +## `verify-dwell` — the comparison that refuted my own 🔴, made repeatable + +Last iteration I measured the port's visible spans against the oracle's dwells by +hand, and it refuted a red flag I had filed myself: `rest.t` *is* the wrong settle +landmark, but *"everything the sequencer paces off it is therefore late"* was +false, and I nearly went and re-paced screens that already matched. + +That check existed once, in a transcript. It is now `tools/port/verify-dwell`. + +``` +screen port oracle (3 cold boots) verdict +publisher wordmark 4.25 s 4.297 / 4.604 / 4.370 agrees +developer logos 3.75 s 3.508 / 3.503 / 3.366 agrees +``` + +⚠️ **The trap it exists to prevent is in its header, because it is the whole +point:** a port's *transition timestamps* and the oracle's *visible spans* are +not the same quantity — they differ by the exit ramp plus the black hold, about +0.6 s, which was the entire discrepancy I was about to chase. This corpus has +been bitten by the identical confusion before, on the plate delay, where the two +readings differ by 0.48 s against 6 ms. + +**The bar is the oracle's own run-to-run spread**, plus one film interval. Three +cold boots of the real game differ by 0.3 s; agreeing more tightly than the +oracle agrees with itself would not mean anything, and a tighter bar would be a +number chosen to look impressive. The developer-logo span read 3.50 s on the +hand-run and 3.75 s here — one film interval apart, both inside the bar, which is +the tool reporting its own resolution honestly rather than hiding it. + +**The oracle's numbers are quoted in the script as a test fixture and labelled as +the oracle's**, with the RE document they come from. Nothing in the port derives +them and nothing may. diff --git a/tools/port/verify-dwell b/tools/port/verify-dwell new file mode 100755 index 00000000..7f36ee67 --- /dev/null +++ b/tools/port/verify-dwell @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# Measure the port's own VISIBLE SPANS and put them beside the oracle's dwells. +# +# tools/port/verify-dwell +# +# WHY THIS IS A TOOL AND NOT A ONE-OFF. Doing this by hand once already refuted a +# 🔴 I had filed myself. `docs/port/BLOCKED.md` said `rest.t` was the wrong +# settle landmark AND that "everything the sequencer paces off it is therefore +# late". The first half is true; the second was wrong, and I nearly went and +# "fixed" screens that already matched the game to 0.05 s. +# +# ⚠️ THE TRAP THAT CAUSED IT, AND THE REASON THIS SCRIPT EXISTS AT ALL: +# a port's TRANSITION TIMESTAMPS and the oracle's VISIBLE SPANS are not the same +# quantity. They differ by the exit ramp plus the black hold -- about 0.6 s here, +# which was the entire discrepancy. This corpus has been bitten by the identical +# confusion before, on the plate delay: "timed from where build 4 stops +# animating, not from where it first appears -- measured the other way the two +# runs differ by 0.48 s against 6 ms." So this measures the port the way the +# oracle was measured: first ink to last ink. +# +# THE EXPECTED NUMBERS BELOW ARE THE ORACLE'S, NOT THE PORT'S. They are three +# cold boots from `docs/re/boot-order-and-splash-dwell.md`, first-visible to +# last-visible, and they are quoted here as a test fixture. Nothing in the port +# derives them and nothing may. +set -euo pipefail +cd "${PROJECT_DIR:-/work}" +export DISPLAY="${DISPLAY:-:97}" +OUT="${OUT:-$(mktemp -d)}" +mkdir -p "$OUT" + +echo "running the boot (the intro is skipped -- the splashes are what this measures)" +timeout "${TIMEOUT:-200}" godot --path port --resolution 1280x720 -- \ + --boot --skip-at=1 "--film=$OUT/f" >"$OUT/boot.log" 2>&1 || true + +python3 - "$OUT" <<'PYEOF' +import glob, os, subprocess, sys +out = sys.argv[1] +frames = sorted(glob.glob(os.path.join(out, "f_*.png"))) +if not frames: + print("no frames -- is there a display? see", os.path.join(out, "boot.log")); raise SystemExit(2) +INTERVAL = 0.25 # boot.gd's --film cadence +means = [] +for f in frames: + m = subprocess.run(["convert", f, "-colorspace", "Gray", "-format", + "%[fx:mean*255]", "info:"], capture_output=True, text=True) + means.append(float(m.stdout.strip() or 0)) + +# A frame is "ink" if anything at all is drawn. The splashes are dim -- surface +# means of 5/255 -- so the bar is ">0", not a percentage of full scale. +ink = [m > 0.0 for m in means] +spans, i = [], 0 +while i < len(ink): + if ink[i]: + j = i + while j < len(ink) and ink[j]: j += 1 + spans.append((i * INTERVAL, j * INTERVAL)) + i = j + else: + i += 1 + +# The oracle: three cold boots, first-visible to last-visible. +# docs/re/boot-order-and-splash-dwell.md. NOT the port's numbers. +ORACLE = [ + ("publisher wordmark", [4.297, 4.604, 4.370]), + ("developer logos", [3.508, 3.503, 3.366]), +] +print() +print("%-20s %-12s %-26s %s" % ("screen", "port", "oracle (3 cold boots)", "verdict")) +for k, (name, runs) in enumerate(ORACLE): + if k >= len(spans): + print("%-20s %-12s %-26s no such span in this run" % (name, "-", "")) + continue + a, b = spans[k] + d = b - a + lo, hi = min(runs), max(runs) + # Inside the oracle's own run-to-run spread, or within one film interval of + # it. The spread is the honest bar: three boots of the real game differ by + # 0.3 s, so agreeing more tightly than that would not mean anything. + ok = (lo - INTERVAL) <= d <= (hi + INTERVAL) + print("%-20s %-12s %-26s %s" + % (name, "%.2f s" % d, "%.3f / %.3f / %.3f" % tuple(runs), + "agrees" if ok else "DIFFERS")) +print() +print("port spans (first ink -> last ink), +/- %.2f s from the film cadence:" % INTERVAL) +for a, b in spans[:6]: + print(" %6.2f - %6.2f s (%.2f s)" % (a, b, b - a)) +print() +print("⚠️ Read this beside the transition timestamps in the boot log, never") +print(" instead of them -- they differ by the exit ramp plus the black hold.") +PYEOF +echo "artifacts in $OUT"