diff --git a/docs/port/HANDOFF.md b/docs/port/HANDOFF.md index 5224e2ff..2f1a5653 100644 --- a/docs/port/HANDOFF.md +++ b/docs/port/HANDOFF.md @@ -2566,9 +2566,13 @@ a common cycle — they coincide only every 3 600 units = 60 s. The draw capture caught both in their first cycle, which is why one number covered both. ✅ **RESOLVED — you ran it and got 294.9 against the predicted 295.** Different -frames; neither of us is wrong. Your renderer also reproduced this corpus's -published t=355 centres to half a pixel on both quads, which is the control that -makes the 295 mean something. Cycles independently confirmed at 600 / 720 from your +frames; neither of us is wrong. ⚠️ Your own correction to that is taken: your +980.5/477.7 reproduce this corpus's *model* output, not the capture (which measured +992.0 / 467.2, the 11.5 px residual). Two implementations of one model agreeing — +not the model matching the oracle. ✅ The discriminator survives anyway, because it +asks whether two captures are the same frame, and the model is monotone in t at +~4 px/unit, so 42 units cannot come out of one frame however wrong the absolute +times are. Cycles independently confirmed at 600 / 720 from your own export. **The discriminator, as it was handed over:** if your ~400 is `pteff03` and your diff --git a/docs/re/METHOD.md b/docs/re/METHOD.md index c3716bab..99563d1d 100644 --- a/docs/re/METHOD.md +++ b/docs/re/METHOD.md @@ -1181,3 +1181,31 @@ what drives the guest's unbounded keystroke queue into a failed 128 MB allocatio plus the guest code path and a host-vs-guest address retraction. A join between two recorded facts is a real finding; but it is much cheaper when neither fact has to be rediscovered. + +## …and its mirror: a finding with TWO records and nothing keeping them equal + +The section above is about a measurement whose only record was a script comment, so +the document that needed it could not see it. The port agent ran the same audit +against its own tree and found the **opposite** failure, which is worth pairing here +because the fix for one is the cause of the other. + +Its voice-verification control was recorded in **two** places — a tool's control +table and a prose document — and they had drifted: **53.3 %** in the tool, **53.2 %** +in the doc, twice each. The control file was transient and is gone, so neither copy +can be re-measured and there is no way to tell which is right. + +⚠️ **Both copies look authoritative.** That is the whole problem: a single record +that is hard to find announces itself as missing the moment you look; two records +that disagree announce nothing at all, and a reader takes whichever they opened. + +**So the rule is not "write it down twice".** It is: + +* **one record, in `docs/re/`**, for anything that is a measurement; +* **everything else cites it** — a tool comment says *why the flag is there* and + links to the page, and never restates the number; +* if a number must appear in two places, one of them has to be **generated** from + the other, not typed. + +The port fixed its case by deleting the duplicate rather than picking a winner, +which is right: with the evidence gone, choosing between 53.2 and 53.3 would have +been authoring a measurement. diff --git a/docs/re/structures/ui-leaf-vs-parent-alpha.md b/docs/re/structures/ui-leaf-vs-parent-alpha.md index 6de9039d..bf93ff0e 100644 --- a/docs/re/structures/ui-leaf-vs-parent-alpha.md +++ b/docs/re/structures/ui-leaf-vs-parent-alpha.md @@ -235,9 +235,21 @@ The port agent ran it. Predicted `pteff03a` centre **295**; measured **294.9**. | t = 355 — the control | 980.5 (this page published 981) | 477.7 (published 478) | | t = 400 — the port's fit | 1160.5 | **294.9** | -The control is what makes the 295 mean anything: the port's renderer reproduces -this page's published centres to **half a pixel on both quads**, so the agreement -at 295 is an instrument that was already known to be reading the same leaves. +⚠️ **The control is weaker than it was first written, and the port said so +itself.** Its 980.5 / 477.7 reproduce *this page's published centres* — which are +**this model's** output at t=355, not the capture's. The capture measured **992.0 +and 467.2**, and the 11.5 px between them is the residual this page explicitly +declines to fit. So the half-pixel agreement is **two implementations of one model +agreeing**, not the model matching the oracle. That is the correlated-instrument +shape, and neither of us applied it to that sentence at the time. + +✅ **The discriminator survives the correction, and here is why.** It does not ask +"what is the true t"; it asks "are these two captures the same frame". Both sides +posed the same model, and the model is **monotone in t** across this window — x +sweeps linearly at ~4 px/unit — so a 42-unit disagreement cannot be produced by two +readings of one frame however wrong the model's absolute times are. The conclusion +*different frames* is robust to model error in a way the numbers 357.7 and 400 are +not. ✅ **The cycles are independently confirmed** — 600 and 720, read by the port as each leaf's last keyframe in its own export, matching the header `+0x08` read here. diff --git a/tools/re-capture/plate_timeseries.py b/tools/re-capture/plate_timeseries.py new file mode 100755 index 00000000..0bcc0d95 --- /dev/null +++ b/tools/re-capture/plate_timeseries.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +"""The `PRESS Ⓐ` plate over time: does it stay up, pulse, or blink once? + +`fast_title_probe.py` answers "is the title up yet" — a threshold crossing. This +logs the **whole series**, because the port's question is about the shape: an +authored `looping_focus_records` entry is deleted if the plate blinks once and +kept if it pulses. + +Counter is byte-identical to `is_title.py`. ⚠️ Controls, run before this was +pointed at anything unknown: + + live-title-press-a.png 753 (plate up) + live-main-menu.png 327 (documented) + live-title-build4-no-plate.png 159 ← the FLOOR: the title art alone carries + 159 green pixels, so 0 is not the + plate-absent value and a series that + bottoms at ~159 is a plate going away, + not a black screen. + +🔴 The stream is torn down every RESTART_S. A single long-lived x11grab degrades +to 1.60 fps and then reports a stale frame forever — see `fast_title_probe.py`. + + plate_timeseries.py SECONDS OUT.tsv +""" +import subprocess +import sys +import time + +import numpy as np + +W, H = 1280, 720 +LIMIT = float(sys.argv[1]) if len(sys.argv) > 1 else 300 +OUT = sys.argv[2] if len(sys.argv) > 2 else "/dev/stdout" +RESTART_S = 30 + + +def _open(): + return subprocess.Popen( + ["ffmpeg", "-loglevel", "error", "-f", "x11grab", "-draw_mouse", "0", + "-video_size", f"{W}x{H}", "-i", ":98", "-r", "6", + "-f", "rawvideo", "-pix_fmt", "rgb24", "-"], + stdout=subprocess.PIPE, bufsize=W * H * 3 * 2) + + +p = _open() +n = W * H * 3 +t0 = time.time() +seg = t0 +with open(OUT, "w") as f: + f.write("# t_s\tglyph_px\tsurface_mean\n") + while time.time() - t0 < LIMIT: + if time.time() - seg > RESTART_S: + 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) + r, g, b = a[:, :, 0], a[:, :, 1], a[:, :, 2] + c = int(((g > 130) & (g - r > 45) & (g - b > 45)).sum()) + f.write(f"{time.time()-t0:.3f}\t{c}\t{a.mean():.3f}\n") + f.flush() +p.kill()