The UI draw capture printed 8 vertices = two quads per draw, so a batched draw dropped the rest silently. Four EXTRAS elements therefore appeared in no draw on any screen, which reads as 'the game does not draw these' -- and the port spent an iteration measuring them as the worst on the screen and asking about them. When an instrument says an element never appears, check its limits before believing the game. And 'press down until the cursor stops moving' is not a stop condition on a menu that WRAPS: it was unreachable, the loop only exited by exhausting its budget, and it landed on EXTRAS because a dropped press cancelled one lap. An earlier version of the same loop pressed (A) on NEW GAME after two identical readings caused by a dropped press. What held throughout is the part worth keeping: verify the state you measured, never the actions you took. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
3387 lines
211 KiB
Markdown
3387 lines
211 KiB
Markdown
# Method traps already paid for
|
||
|
||
Each line cost an iteration at least once. They are general — they are not about
|
||
Sylpheed, they are about how this kind of measurement goes wrong.
|
||
|
||
Like [`REFUTED.md`](REFUTED.md), this list had been living in the autonomous
|
||
agent's loop prompt, i.e. nowhere durable. See [`README.md`](README.md) for the
|
||
✅/🟡/❔ confidence convention itself.
|
||
|
||
## Controls
|
||
|
||
* **Every result needs a control. A control that fails kills the instrument.**
|
||
* **Run the known-positive through a new filter FIRST.** Three filters have been
|
||
killed by their own control. When one fails, **read the known-good's
|
||
disassembly** before assuming a shape.
|
||
* **A measured negative is a result** — but a negative is only as strong as the
|
||
route you ran, so **state its reach**.
|
||
* **A null result needs its cause shown to have happened.**
|
||
* **A result with NO unknowns is suspicious.**
|
||
* **Census the whole set; always run the other population as the control.**
|
||
**Zero partials is stronger than a majority.**
|
||
* **A 2×2 partition is the sharpest general tool** — both off-diagonals empty is
|
||
a law.
|
||
* **Re-derive a doc's own numbers as the control.**
|
||
|
||
## Inference
|
||
|
||
* **Never conclude from ONE sample.**
|
||
* **⚠️ The specific observation and the general rule read identically on the
|
||
page — and the general one is what the next reader uses.** This cost five
|
||
corrections across two agents in two days, and none of them was carelessness
|
||
about the measurement; every underlying observation was true of the asset
|
||
actually looked at. The failure is reaching for the general form in the same
|
||
breath as the specific one:
|
||
* "the two chunks are two stems of one performance" — true of a *music bank*,
|
||
written as a fact about voice, where one of the two is digital silence;
|
||
* "the extra bytes are a duplicated channel, not fidelity" — true of `ADV`,
|
||
and the size ratio it implies runs 0.0778 to 2.9163 across the disc;
|
||
* "everything the sequencer paces off `rest.t` is late" — true of the *title*,
|
||
and false of the screens actually checked;
|
||
* "a three-stream cue is a movie cue" — mine, and `BIRD_224` is neither;
|
||
* "take the highest-rate, highest-gain stream" — mine, and on `ADV` those two
|
||
criteria select *different* streams.
|
||
|
||
**The counter is cheap and it is always the same one: run the census before
|
||
writing the rule.** A ratio that is tight over 28 assets is a format fact; a
|
||
ratio that scatters 37× was one asset wearing a rule's clothing. Where the
|
||
census cannot be run, write the specific sentence and *say* it is specific.
|
||
* **A law proved on one population is a hypothesis on the next.**
|
||
* **Finding one exception does not imply a family.**
|
||
* **Consistency is not proof. A suggestive coincidence is a coincidence until
|
||
measured.** **An analogy is not a measurement.**
|
||
* **Same layout ≠ same instance.** **Same record-name set ≠ same object.**
|
||
* **A marker is only proven by what it leaves out.**
|
||
* **A high-confidence SCORE is not a high-confidence MECHANISM.**
|
||
* **Knowing HOW MANY is not knowing WHICH.**
|
||
* **Round numbers matching is weak evidence — unless you read the constant.**
|
||
* **My own last-turn result is a hypothesis too.**
|
||
* **A global partition can understate a per-owner one.**
|
||
* **A residual is measured against a population — name it.**
|
||
* 🔴 **An insensitive observable fails TWICE, and the second way is worse.**
|
||
Two bugs in one exchange, one cause:
|
||
1. A leaf-composition rule was checked against **alpha**, which moves ~0.3
|
||
levels per keyframe unit — so a one-keyframe association error barely
|
||
shifted it and the rule **looked confirmed**. The same span moved `x` by
|
||
**1 560 px**.
|
||
2. Fitting `t` from that same alpha then **manufactured an 11.5 px position
|
||
residual that did not exist**, and sent the consumer hunting a
|
||
pivot/rotation mechanism to explain it. One byte of alpha quantisation is
|
||
worth 1.5–1.9 keyframe units, i.e. 6–8 px of sweep.
|
||
**Solve on the fastest-moving field; check the slow one. Never the reverse.**
|
||
⚠️ The second failure is the more expensive: not-falsifying leaves you falsely
|
||
reassured, but **inventing a residual sends you looking for a mechanism**.
|
||
* ⚠️ **A stated reach is a boundary, not a hedge — do not extrapolate past it.**
|
||
`ui-render-tone-curve.md` fitted γ ≈ 1.34–1.49 on **dark flat patches** and
|
||
wrote "nothing constrains midtones or highlights". Used above that range the
|
||
model is simply wrong: binned by level, the exponent falls monotonically and
|
||
**crosses 1.0 near render ≈ 40**, so above it the capture is *brighter* than
|
||
the render and no single exponent can express the curve. The page had already
|
||
said where it stopped being true; the error was reading past the sentence.
|
||
✅ **The fix was not a better fit — it was printing the curve instead of a
|
||
scalar**, so it can be argued with. A scalar hides its own domain.
|
||
* ⚠️ **Normalising? Divide by how many inputs CARRY SIGNAL, not how many there
|
||
are.** The port hit this three times in one pipeline, each invisible to every
|
||
check except a level measurement, and each the same mistake:
|
||
a digitally silent *chunk* counted in a voice sum; a digitally silent
|
||
*channel* counted in a mono fold (−5.94 dB); a digitally silent *sub-wave* —
|
||
the 10 240-byte bank header, wrapped to 10 300 B — counted as a third stem in
|
||
a music sum, putting every real stem at 1/3 instead of 1/2 (**−3.52 dB on all
|
||
menu music, shipping for two iterations**). This corpus's own census said
|
||
those banks hold **two** waves; the exporter's divisor said three. **A count
|
||
that disagrees with a census is the count that is wrong**, and the symptom is
|
||
never a crash — it is everything being quietly a few dB down.
|
||
|
||
## Searching and tooling
|
||
|
||
* **A search that returns thousands has no power; state the reach.**
|
||
* **A substring match is not a hit.** **A regex miss looks like a null result —
|
||
print one raw sample before believing a zero.**
|
||
* **A derived table can be a cross product — measure its shape first.**
|
||
* **After refuting an instrument, sweep everything that depended on it.**
|
||
* **Before measuring how wrong a tool is, read what the tool actually does.**
|
||
* **The instrument must pass its own control.**
|
||
* **Classify a bulk before mining it. The residual is the prize.**
|
||
* **Rank by similarity — the cliff is the finding.** But **read the values
|
||
before trusting the rank.**
|
||
* **Grep the nouns before designing the experiment — and believe it.**
|
||
* **Grep gives you a file list — read *every* file on it.**
|
||
* **The answer is often already in the doc that owns the subject — read it end
|
||
to end.** A 🟡 often names its own route.
|
||
* **Before re-trying a blocked idea, check whether the blocker's own doc already
|
||
tried it.**
|
||
* **Ship a regenerator with every artefact.** An artefact that moves by a pure
|
||
reorder is a tool bug.
|
||
* **Never print per-entry lines from a disc-wide sweep — aggregate.**
|
||
|
||
## Reading the data
|
||
|
||
* **Read what a loader NAMES, not where it stores.**
|
||
* **A field the disc never values still gets named by the loader.**
|
||
* **An indexed read beats a deduped-pool adjacency read.**
|
||
* **Check the whole string set, not the one matching word.**
|
||
* **A dict keyed by record name across a multi-entry pak is a lie.**
|
||
* **A set-difference over names hides reuse — join per USER.**
|
||
* **A self-index names records, not files.**
|
||
* **Case-insensitive hashing means two spellings can be one entry.**
|
||
* **An "unresolved" name may be the wrong kind, namespace or prefix — or part of
|
||
a cut asset.**
|
||
* **A garbled value may be a real string in another encoding.**
|
||
* **Two of my own counts disagreeing is a grammar clue.**
|
||
* **A game's own typo is a join key.**
|
||
* **A bias constant in the code is a join key.**
|
||
* **A prefix trap: enumerate maximal `[A-Za-z0-9_]` runs, not `startswith`.**
|
||
* **Re-deriving a format is not a finding — asking whether its values *resolve*
|
||
is.**
|
||
|
||
## Mechanics that have bitten
|
||
|
||
* **Never hand-convert a decimal VA — print `hex()`.**
|
||
* **`grep -c` counts LINES** — use `grep -o | wc -l`.
|
||
* **`Counter.most_common()` tie-breaks by insertion order — use `sorted()`.**
|
||
* **Raw grep cannot see inside compressed pak entries.**
|
||
* **Commit messages go in a file** (`git commit -F`); a literal `|` in a table
|
||
cell needs escaping; `git log --all -- <path>` can hang.
|
||
* 🔴 **Never clamp a value before something compares it.** A focus detector
|
||
printed a degenerate `margin=12359888888.89`, so it was capped at 999 to keep
|
||
the output readable. That cap ran *before* the vote-sorting step, so two
|
||
different votes compared **equal**, the stable sort kept the wrong one, and a
|
||
correct `NEW GAME` became an out-of-range index and a refusal — which aborted a
|
||
seven-minute driven boot. The measurement was right the whole time; a cosmetic
|
||
fix changed a decision. **Clamp at the point of display, never upstream of a
|
||
comparison that depends on the value.**
|
||
* **`pkill -f PATTERN` / `pgrep -f PATTERN` match YOUR OWN command line.** Hit
|
||
twice in one session: `pkill -9 -f adv_audio_cap.sh` killed the shell that ran
|
||
it, and an `until ! pgrep -f "probe.py --run"` loop never exited because the
|
||
loop's own command line contained the pattern. Kill by process name
|
||
(`ps -o pid= -C xenia_canary`) or exclude self; a wait-loop that greps for its
|
||
own text waits forever and looks like the job hanging.
|
||
* **"Build 10" of a pak is ambiguous — always say which index space.**
|
||
`sylpheed-cli screen list GP_TITLE.pak` reports **12** builds and numbers them
|
||
0–11; `screen list --all` reports **16** and numbers them 0–15. Only under
|
||
`--all` does the ordinal equal the pak entry. Without it, ordinal 10 is pak
|
||
entry **12** and ordinal 11 is entry **15** — so "builds 10/11 are the loading
|
||
screen" and "entries 12/15 are the loading screen" are the same true statement,
|
||
while "**entries** 10/11 are the loading screen" is false: those are the
|
||
publisher (`palogo_sqex`) and developer (`palogo_gamearts`/`seta`/`anima`)
|
||
splashes. This cost a wrong line in HANDOFF that the port caught, and it would
|
||
have validated silently because the port's `screen_names.json` is keyed by
|
||
entry. **Write `entry N`, not `build N`, whenever the number leaves this
|
||
repository.**
|
||
|
||
🔴 **This entry was already here when I broke the rule.** So was
|
||
`ui-splash-addressing.md`, which says in as many words that the splashes are
|
||
entries 10/11/13/14, that `is_build` **rejects** them, and that they are
|
||
reachable *only* through `--all`. Two documents in my own corpus, and I still
|
||
ran `--build 10` bare and wrote three claims on the output. The failure was not
|
||
missing knowledge — it was **addressing a bundle by index without grepping for
|
||
the index first**. A rule written down is not a rule applied. Before any
|
||
`--build N`, run `screen list` on that pak and read the `entry` column; it costs
|
||
one command and it is the only step that would have caught this.
|
||
|
||
📌 **And the sweep says `GP_TITLE` was the mildest case on the disc**
|
||
([`structures/build-ordinal-vs-entry.md`](structures/build-ordinal-vs-entry.md),
|
||
[`data/ordinal-entry-map.txt`](data/ordinal-entry-map.txt)): **21 of 24**
|
||
archives diverge, **18 of them at ordinal 0** — in the six `GP_MAIN_GAME_*2D`
|
||
paks `--build 0` is entry **108**. `GP_TITLE` is the *only* archive whose first
|
||
ten ordinals are the identity, which is why the corpus survived: almost
|
||
everything written about builds is about `GP_TITLE`, at ordinals 0–9. That is
|
||
luck in one archive, not a property of the format, and it does not extend to the
|
||
screens the port has left to do.
|
||
|
||
* **A layout fix has to be swept across every READER of that layout, not just the
|
||
crate.** The keyframe record-layout fix (a pose's time precedes it) landed in
|
||
`ui_layout.rs`, and `sylpheed-cli` was found stale and rebuilt. **Two more
|
||
readers survived it**: `tools/re-capture/fade_quads.py`, which read each pose's
|
||
time from `blk+36` — the *next* record's time word — and therefore printed a
|
||
trailing untimed keyframe; and, through it,
|
||
[`screen-transitions.md`](screen-transitions.md), which labelled the quad's
|
||
**clear-hold** as its *fade-in* and published 0.87–4.08 s for a ramp that is
|
||
0.20–0.27 s. Both looked right: a shifted time series is still monotone,
|
||
plausible, and internally consistent. The tell is structural, not numeric — the
|
||
stale reader **cannot time the last pose**, so any output with a trailing `t=—`
|
||
or `-` is that bug's signature. Grep the corpus for readers of a structure
|
||
before calling its fix done.
|
||
|
||
* **An absence of output is not a status.** `sylpheed-port` reported "still
|
||
running, two lines, both ok" for three consecutive iterations of a check script.
|
||
The first attempt had already died silently under its own timeout with
|
||
block-buffered output — so there had been *zero* information from it, and "still
|
||
two lines" was being read as patience rather than as the alarm it was. The
|
||
underlying process was wedged on an ffmpeg that finishes its work and never
|
||
exits (an orphan from an older form of the same script was found still running
|
||
after **9.5 hours**). Two rules fall out, and this corpus has now paid for both:
|
||
a long-running job needs **line-buffered output and a bound**, and *"no new
|
||
output"* must be treated as **no information**, never as progress. Check the
|
||
artifact, not the exit code — the artifact reached its correct 8.0 s duration
|
||
while the process it came from never returned.
|
||
|
||
* **An allowance is a claim, and it decays like any other.** `sylpheed-port`'s
|
||
`check-all` printed *"2 DIFFERS, allowed: the pin is not on main, so this
|
||
compares two decoder eras"* — in green, for weeks, and both of us quoted it back
|
||
without testing it. Tested: `sylpheed-cli` built at `formats-pin-2026-08-30` and
|
||
at workspace HEAD render `title`, `title_jp` and `main_menu` **byte-identically**,
|
||
despite 508 lines of difference in `ui_layout.rs`. The eras explain nothing; the
|
||
allowance was making a real disagreement look accounted for, and the real reasons
|
||
were already written down elsewhere in their own notes. Two rules:
|
||
**an excuse in a passing check is an untested assertion that never gets read as
|
||
one**, because green output is not scrutinised; and **allow by NAME, never by
|
||
COUNT** — a count cannot notice that a *different* row started failing while the
|
||
total held steady, which is exactly the hole the allowance opens. ⚠️ Same
|
||
signature as the `.tbm` and stale-`sylpheed-cli` findings: *the times moved, the
|
||
pixels did not*. When two versions of a renderer are supposed to differ, check
|
||
whether they actually do before explaining a mismatch with the difference.
|
||
|
||
* **Two things that should differ producing IDENTICAL output is a broken
|
||
experiment until proven otherwise — and a *zero* is its most dangerous form,
|
||
because it reads as a clean result rather than a suspicious one.** This corpus
|
||
has now hit the signature four times: a `--time=50` seconds-vs-units bug gave two
|
||
poses the same RMSE to two decimals; a `.tbm` correlation scored −0.004…−0.010
|
||
across nineteen builds; a two-era render comparison reported 0 differing pixels
|
||
because **both binaries had the same md5**; and a build-ordinal error rendered the
|
||
wrong screen while every downstream number validated. The check is mechanical and
|
||
costs seconds: **verify the two inputs actually differ before believing they
|
||
produce the same output** — `md5sum` the binaries, diff the parameter you varied,
|
||
assert the control moved. ⚠️ And do not infer that difference from a proxy:
|
||
`origin/auto/port-p6-audio`'s `ui_layout.rs` differs from the pin by 508 lines and
|
||
is nonetheless **md5-identical to `origin/main`'s**. *Line count is not era.* I
|
||
reached the right conclusion about that branch through exactly that invalid step.
|
||
|
||
* **A shared `CARGO_TARGET_DIR` across two source trees silently serves one
|
||
binary to both.** Cargo fingerprints per source path, so building tree B into a
|
||
directory last written by tree A prints **"Finished" in 0.15 s and changes
|
||
nothing** — the binary on disk still belongs to A. `sylpheed-port` scored their
|
||
harness for hours against a decoder from a tree nobody had named, which
|
||
*happened to be the correct era*: it agreed with their pin by luck, and one
|
||
successful rebuild would have flipped it silently with 74 507 px at stake on
|
||
`title_jp`. ⚠️ **Agreeing by luck is worse than disagreeing**, because nothing
|
||
ever prompts the check. Give each tree its **own** target dir, and prove the
|
||
binaries differ before comparing them — `md5sum` them and re-run a control that
|
||
distinguishes them, at the time of use, not at build time. (The comparison in
|
||
[`ui-resting-pose.md`](structures/ui-resting-pose.md) was audited against this
|
||
after the fact: md5 `7516bdac…` against `8370e0e9…`, separate target dirs, and
|
||
the era control re-run live — it holds. The audit was cheap; not doing it would
|
||
have left a measurement resting on an assumption about a filesystem.)
|
||
|
||
* **A capture taken at an uncontrolled instant is a real measurement of the wrong
|
||
thing** — and the cheap check for it passes. `sylpheed-port`'s harness grabbed
|
||
`main_menu` at t=9.00 in one session and t=8.00 in the next; one keyframe unit
|
||
apart, mid-build-in, is **70 % of the picture**, and it read as "the change broke
|
||
two screens". ⚠️ The instant was **stable within a session and drifted between
|
||
them**, which is the worst form: three consecutive runs are byte-identical, so
|
||
every cheap reproducibility check says "deterministic". Pin the instant
|
||
explicitly; do not infer stability from repeat runs inside one session.
|
||
|
||
**Two defences, and a live capture wants both.** *Prospectively*, gate the grab
|
||
on a signal that the screen has settled — the title's plate pulse, say — and
|
||
record the gate beside the capture. *Retrospectively*, sweep the screen's own
|
||
timeline with `screen render --at` and score the capture against each instant: if
|
||
it lies on a **broad flat minimum with sharp edges**, it was at rest; a sharp
|
||
minimum means it was caught mid-build and the instant is load-bearing. The
|
||
`ptlogo_eff3` adjudication in [`ui-resting-pose.md`](structures/ui-resting-pose.md)
|
||
happens to have both — the capture was gated on the plate pulse, and the `--at`
|
||
sweep (run for a noise scale, not for this) shows a plateau flat to 1.2 RMSE
|
||
across 105 units against edges at 78. The sweep was luck; the entry is here so
|
||
the next one is not.
|
||
|
||
* **A fallback default is an authored value that no reader can see** — and the
|
||
dangerous ones are **in-range**. `sylpheed-port` found `exit_ramp_units`
|
||
defaulting to **24.0**, the exact constant this corpus had *refuted*: the
|
||
authored entry had been deleted as progress, and a
|
||
`timing.get("exit_ramp_units", 24.0)` made the deletion a no-op, in the one
|
||
place a reader checking `authored/` would never look. **Deleting a value does
|
||
not remove it if something supplies it silently.**
|
||
|
||
⚠️ Their 24.0 was at least conspicuous. Sweeping this side for the same shape
|
||
([`data/fallback-fabrication-sweep.txt`](data/fallback-fabrication-sweep.txt))
|
||
found 112 fallback sites, of which two in the pinned `ui_layout.rs` could
|
||
fabricate a quantity — and **both fabricate a value that is legitimate**:
|
||
`(1280, 720)`, which is what every real screen states, and `kf.time.unwrap_or(0)`,
|
||
where 0 is a real keyframe time (pose 0's time *is* 0). An in-range fallback
|
||
cannot be caught downstream by inspecting the output, because the output looks
|
||
exactly like the true case. The only way to know is to **count how often it
|
||
fires**: measured, the design-size fallback fires **0 times in 965 builds**, so
|
||
that number is read rather than invented — which could not have been established
|
||
from any parser output.
|
||
|
||
Sweep for these by listing every fallback and asking *"does this supply a
|
||
quantity, or a sentinel?"* — 0/empty/`Default` and pass-throughs assert nothing;
|
||
a literal that could pass for a measurement is the hazard. Build the sweep so it
|
||
finds a **known** case as its positive control.
|
||
|
||
* **A zero from a detector is worth nothing until the detector is shown able to
|
||
report non-zero — and when that control fails, the failure is often the
|
||
answer.** Counting `ui_layout`'s two in-range fallbacks gave 0 and 0. The
|
||
negative control — ask `pose_at` for a time no build declares — returned **0
|
||
None across 10 906 queries**, so the detector was blind and one of those zeroes
|
||
measured nothing. That failure produced the real result: `pose_at` is **total**,
|
||
its only `None` path is an `is_empty()` guard, and disc-wide **0 of 5 453**
|
||
elements have zero keyframes — so the fallback is unreachable *by construction*,
|
||
which is a stronger statement than "it never fired here". ⚠️ Had the control not
|
||
run, this corpus would have recorded a true conclusion supported by a
|
||
meaningless number, which is the same defect as
|
||
[agreeing by luck](#) and just as invisible.
|
||
|
||
* 📌 **The habit under several of these: reading a PROXY for the thing when the
|
||
thing itself is one command away.** Inferring a decoder era from a **line
|
||
count**; classifying a fallback as harmless by the **spelling** of its type
|
||
name; calling a default a sentinel by **reading** it rather than counting how
|
||
often it fires; taking a build's identity from an **ordinal** rather than the
|
||
entry column. Each time the direct check existed and cost seconds. The tell is
|
||
noticing that what you are about to look at merely *correlates* with what you
|
||
want to know.
|
||
|
||
* **Match the noise floor to the quantity — including which noise actually
|
||
applies.** A margin needs a floor, but the floor must be the one that moves
|
||
*that* margin. Two renders scored against one capture share the capture, so
|
||
capture noise largely **cancels**: measured on the JP title, the absolute scores
|
||
moved 0.001–0.002 between sessions while the **margin** moved 0.001, against an
|
||
in-box capture noise of 0.32. Judging that margin against a whole-frame capture
|
||
spread — a number that was simply to hand — made a non-decisive result look
|
||
decisive, and this corpus published that for part of a day.
|
||
⚠️ Relatedly, `sylpheed-port` verified a harness "reproducible" from an RMSE
|
||
**printed to two decimals** when the residual was 0.0565: **an instrument that
|
||
rounds away the thing being verified cannot verify it.** Check the printed
|
||
precision against the quantity before quoting the number, and prefer comparing
|
||
*frames* to comparing a statistic about them.
|
||
|
||
* **A declared rect can be an ANCHOR, not an extent.** A UI element's placement
|
||
`(x, y)` plus its `w×h` reads like the box it draws in. For a `RATC` parent with
|
||
a nested record it is not: `ptloop01.rat` declares `(441,270)` 200×90 while its
|
||
**leaf** sweeps a 400 px-wide quad whose centre runs x≈921→1041 — 300 px outside
|
||
the parent's box. Measuring "does this element move" over the parent's rect
|
||
returned **0 differing pixels** across two sessions, in a region where *nothing*
|
||
moves, and that zero was published. ⚠️ Before diffing a region to ask whether an
|
||
element animates, confirm the element **draws there** — from a leaf sweep, a draw
|
||
capture, or the rendered quad's own coordinates. A pivot is not a bounding box.
|
||
|
||
* **A lockfile IS the rule, not an obstacle to it.** `run-canary` holds
|
||
`/tmp/xenia-canary.lock` to enforce "one emulator at a time". A `kill -9` orphans
|
||
it, and the obvious unblock — `rm -f` the lock — **also disables the guard for
|
||
every later launch**. Doing that repeatedly left **three emulators live at once**
|
||
on 2026-08-30, all reading the same `/tmp/xenia_pad.txt` and sharing display
|
||
`:98`. A scripted press then reaches *every* instance while `screenshot` grabs
|
||
whichever window is topmost, so "the input was delivered and nothing happened"
|
||
became unfalsifiable — and a finding built on it had to be withdrawn. ⚠️ **Clear
|
||
a stale lock only after confirming zero live instances**, and count them
|
||
(`ps -C xenia_canary --no-headers | wc -l`) rather than trusting that a kill
|
||
landed: a plain `kill` is asynchronous and a `-9` on a stuck process can take
|
||
seconds. **When a guard blocks you, the question is whether the condition it
|
||
guards against is present — not how to remove the guard.**
|
||
|
||
* ⚠️ **`pgrep -f` / `pkill -f` match the shell that runs them.** Already recorded
|
||
here for wait-loops; it has now also killed a cleanup command mid-way and, in a
|
||
third instance, a launcher. Any `-f` pattern that appears in your own command
|
||
line matches your own process. Kill by process **name** (`ps -o pid= -C name`),
|
||
or exclude `$$`. Three instances in one session is not a footnote — reach for
|
||
`-C` first and use `-f` only when the name genuinely is not enough.
|
||
|
||
* **Two paths that share a source are one witness.** Almost every cross-check in
|
||
this project runs *disc → exporter → export*, verified against *disc → our
|
||
reader* — two routes that agree because they read the same bytes with the same
|
||
understanding. When that understanding is wrong they agree anyway, which is how
|
||
this corpus produced a build-ordinal error where "everything still validates", a
|
||
two-era render comparison with the same binary on both sides, and a rate
|
||
"confirmation" that was a prediction 20 % low meeting a measurement 50 % high.
|
||
⚠️ **The chain that counts ends at the oracle**: *disc → exporter → export →
|
||
**the running game***. The one instance this week was the sweep leaves' rotation
|
||
— `rotation_deg` +30 / −45, read from the file, predicting a rotated quad's AABB
|
||
height at 1135.3 and 1301.1 against **1134** and **1303** measured in the draw
|
||
stream, both under 0.2 %. Two angles, two scales, one independent endpoint.
|
||
Before quoting an agreement, ask **where the two paths diverge** — if it is after
|
||
the fact in question, they are one witness wearing two coats.
|
||
|
||
* 📌 **A refuted model is a result, and four of them are a strong one.** The
|
||
leaf's clock ended *undecodable with reach* after frame-locked, wall-clock,
|
||
fixed-wall-clock-sampling and per-UI-drawing-frame were each refuted **by a
|
||
measurement**. That is a firmer statement than any of the four would have been if
|
||
one had happened to fit — because the failure this corpus keeps hitting is a
|
||
model that fits for the wrong reason and nobody checks. Record the closed routes
|
||
with the number that closed each one; a negative with reach is deliverable, and a
|
||
fit without a residual is not.
|
||
|
||
* **A probe whose observation window is shorter than the effect reports a clean
|
||
negative.** Ⓐ on the boot title takes **4–6 s** to reach the menu; a script that
|
||
presses and looks 0.5 s later sees the title and concludes the press was
|
||
dropped — with nothing in its log to say otherwise. `sylpheed-port` hit the same
|
||
shape with a capture that fired before its own script. ⚠️ **Before believing a
|
||
null, check that the window was wider than the latency you are testing for** —
|
||
and where the latency is unknown, sample repeatedly rather than once, so a slow
|
||
effect is distinguishable from no effect.
|
||
|
||
* 📌 **State the number, and state what it is a number OF.** This corpus has now
|
||
produced four instances of one family, and they cost more than any other class of
|
||
error here: a **pivot anchor** read as a drawn extent (a zero measured where
|
||
nothing moves), a **centre track** read as a bounding box, a **cycle length** read
|
||
as a motion duration (a rate 10 % wrong), and **one element's visible span** read
|
||
as the screen's (an 8.5 % "systematic" that did not exist). ⚠️ Two of the four
|
||
arose because the *publisher* of the number never said what it spanned —
|
||
`sylpheed-port` quoted a dwell of 4.28 s across two messages without once saying
|
||
which span it covered, and I quoted 240 units without saying it was one element's.
|
||
Each time the reader reasoned correctly from the only definition available.
|
||
**The fix is cheaper than every check in this file: when you publish a quantity,
|
||
publish its extent in the same breath.** It is the same shape as an observation
|
||
window shorter than the effect — a mismatch between what you are looking at and
|
||
what you believe you are looking at.
|
||
|
||
📌 **And the amendment that explains why this class survives everything else in
|
||
this file** (`sylpheed-port`'s, and it is the sharpest formulation either agent
|
||
reached): **all of them are a failure of a NOUN, not of a number.** Extent,
|
||
bounding box, duration, span, *visible*. In every case the number was correct
|
||
**for something** — what went missing was *which thing*. Every other check here
|
||
tests whether a number is **right**; not one tests whether it is a number **of
|
||
the thing you think**. A fifth instance landed the same day: counting "any
|
||
element with alpha > 0" as *visible*, when the splash builds declare
|
||
`palogo_eff0.prm` at `0xff000000` — full-screen **opaque black**, drawn from t=0
|
||
and showing nothing. Drawn is not visible.
|
||
|
||
* **Hedging in the write-up does not protect the claim you ship in the TOOL.**
|
||
`sylpheed-port` recorded a predicate as "sufficient as observed, not proven
|
||
necessary" in `DECISIONS.md` and simultaneously stated the unhedged version in
|
||
their tool's header, where it was read as fact — the second time they had made
|
||
that exact split, four iterations after fixing it once in another place.
|
||
⚠️ **Checked on this side and found the same thing**: `sylpheed-cli screen
|
||
render --at` told every user *"it is wrong twice over … Prefer `--settle`"*,
|
||
while the corpus records settle-vs-rest as **undecided** — 40.210 against 41.690
|
||
on a live capture, a margin of 1.48 against that instrument's own 1.2 noise
|
||
floor, and `--settle` carrying its own failure mode (25.5 % of elements mid-ramp
|
||
at the settle instant). A recommendation nobody had measured, shipped in the
|
||
interface, hedged only in `docs/re/`. Corrected in the help text itself.
|
||
**The audit is cheap and worth repeating: read your tool's own `--help` as if a
|
||
stranger wrote it, and check every confident sentence against what the corpus
|
||
actually establishes.** Docs are where a claim is *reasoned*; the tool is where
|
||
it is *believed*.
|
||
|
||
* **Fixed code under an unfixed description — and the two are usually within
|
||
twenty lines of each other.** `sylpheed-port` named this and it is narrower and
|
||
more useful than "docs go stale": both of their hits were a *correct* fix sitting
|
||
directly beneath a *refuted* description in the same file, one of them written by
|
||
them two iterations earlier and never looked up at. **It is not drift. It is
|
||
editing at the point of failure without re-reading the frame around it.**
|
||
⚠️ Two on this side, in the crate the port pins: `rest_plateau`'s fallback still
|
||
said *"the last frame carries no time"* — the pre-fix rule — on a branch now
|
||
unreachable (**0 untimed of 24 811 keyframes**), and `rest`'s `lastall` override
|
||
still described itself as *"an independent check on the shifted time reading"*,
|
||
a reading the fix above it **refuted**.
|
||
📌 **The grep is the cheap part**: search for the vocabulary the *old* rule
|
||
needed — here `untimed`, `last frame`, `shifted reading` — because a description
|
||
that survived a fix still speaks the dead rule's language. **And the tell in a
|
||
document is a hedge around something the current reader states exactly**: a `~0`
|
||
or an "approximately" marks where the old reader could not see.
|
||
|
||
* **Corrections are ADDITIVE by default, and that is wrong for a statement.**
|
||
`sylpheed-port` diagnosed this in their own tree after four instances: they
|
||
append a `🔴 CORRECTION` block and leave the original sentence standing above
|
||
it. Right for a *record* — quoting the original is how a change stays visible —
|
||
and wrong for a *statement*, because **a reader takes the first assertion and
|
||
the retraction three lines later has already lost.** ⚠️ Their fix, adopted here:
|
||
keep the quote but **demote it grammatically** — lead with *"what this used to
|
||
say"*, so the false sentence cannot be read as the live one.
|
||
🔴 **The worst form is a HEADING**, which asserts with maximum reach and minimum
|
||
context: `screen-transitions.md` carried `### ❔ The fade-OUT duration is not in
|
||
this field` — false in every sentence beneath it, including an instruction to the
|
||
port to author a value that is **decoded** — standing 78 lines above its own
|
||
correction. A reader scanning headings never reaches the retraction.
|
||
📌 **So audit headings first**: they are the assertions most likely to be read
|
||
and least likely to carry the qualification that would save them.
|
||
|
||
* 🔴 **A stale INSTRUCTION is worse than a stale description, because it fails
|
||
silently and manufactures a false confirmation.** `ui-keyframe-time-unit.md` told
|
||
readers a comparison was *"gated by `SYLPHEED_KF_TIME_SHIFT=1`"* — a variable
|
||
**removed with the record-layout fix and present nowhere in `crates/`**. Anyone
|
||
following it sets something inert, gets default behaviour, and concludes the two
|
||
readings agree. ⚠️ The same shape as `screen-transitions.md` telling the port to
|
||
**author** a value that is decoded. **When sweeping for stale text, rank
|
||
instructions above descriptions**: a wrong description misleads a reader, a wrong
|
||
instruction produces a wrong *result* that looks like evidence.
|
||
📌 **Sweep the surface in BOTH directions.** Documented → does it exist, and
|
||
**parsed → is it documented**. `sylpheed-port` ran the second and found three
|
||
live undocumented flags, one of which (`--no-hold`) plays a screen past its rest
|
||
— *"a capability that exists only in an 11 000-line record is, to anyone reading
|
||
the interface, a capability that does not exist."* The mirror here: **41 env vars
|
||
read by `crates/`, 22 undocumented** — 7 example-only scratch, **15 live in
|
||
`src/`**, all in the mesh and texture lanes, none in the UI path
|
||
([`data/env-var-surface.txt`](data/env-var-surface.txt)). Both directions
|
||
enumerate, so both **complete rather than sample** — which is rare enough in this
|
||
file to be worth choosing sweeps of that shape when one is available.
|
||
⚠️ **And neither direction establishes that the thing WORKS.** They documented
|
||
`--no-hold` and it was inert under an interaction with `--time` — caught only by
|
||
running the example. I verified none of my 15 end to end and have said so rather
|
||
than implying coverage.
|
||
|
||
📌 **And rank SILENT instructions above LOUD ones** (`sylpheed-port`'s
|
||
refinement, from finding all of theirs were the loud kind): a wrong path errors
|
||
out and announces itself; **an inert environment variable returns a clean, wrong
|
||
result**. Only the silent kind manufactures evidence. ⚠️ The silent surface is
|
||
enumerable and therefore **sweepable rather than sampleable** — every env var the
|
||
docs name, checked against the code. Doing that found `SYLPHEED_KF_TIME_SHIFT`
|
||
still live in **five** files after I had fixed one, including a **results-table
|
||
row** and an instruction in `HANDOFF.md`, plus a live gate under a *different
|
||
name* — `SYLPHEED_KF_TIME_LEGACY`, read at `ui_layout.rs:595` — that the docs
|
||
never pointed at. ⚠️ Beware the proxy: absent-from-code also flags
|
||
`SYLPHEED_DISC`, `XENIA_SRC` and `SYLPH_ISO`, container paths the brief sets and
|
||
no code reads. Absent-from-code is necessary, not sufficient.
|
||
📌 And `sylpheed-port`'s generalisation of the heading rule: **an index is an
|
||
amplifier.** Anything that republishes headings — a generated table of contents,
|
||
a summary, `INDEX.md`'s H1-and-Status table — multiplies whatever the heading
|
||
asserts, including what it asserts wrongly. Theirs was republishing three
|
||
withdrawn claims at the top of the file as live findings.
|
||
⚠️ **Denominator, stated because the number is unflattering:** this corpus has
|
||
**2 989 headings**, of which **401** make a negative or absolute assertion. I have
|
||
audited the ones this session touched plus the high-yield intersection with dead
|
||
rule vocabulary. **That is a sample, not a sweep**, and older headings are the
|
||
likelier to be stale for having had more chances to be overturned.
|
||
|
||
* 🔴 **Assert EVERY edit, not most of them.** A three-part patch to a capture
|
||
script asserted two replacements and left the third unchecked. The third
|
||
silently failed, so `WHERE=menu2extras` fell through to the `title` branch and
|
||
the run produced a **well-formed capture of a different transition** — which I
|
||
came close to analysing as the intended one. Same family as the build-ordinal
|
||
error: right-looking output for the wrong object. ⚠️ **What caught it was the
|
||
instrument's own log lacking lines the intended branch prints**, not the data
|
||
looking wrong — the data looked fine. So: assert every replacement, and **have
|
||
each branch announce itself in the log**, so a run that took the wrong path says
|
||
so before its numbers are read.
|
||
|
||
* ⚠️ **"Appears nowhere in `crates/`" is a claim about a TREE, and I stated it
|
||
without one.** I reported `SYLPHEED_KF_TIME_SHIFT` as removed and absent from the
|
||
code; `sylpheed-port` found it **live at `ui_layout.rs:497` on their branch**,
|
||
which carries the stale era. Both true, of different trees. On a project where
|
||
`main` is 145 commits behind and each agent works from a topic branch, *any*
|
||
statement about what the code contains needs its ref attached — the same
|
||
discipline as "state what the number is a number of", applied to scope rather
|
||
than to units.
|
||
|
||
* ⚠️ **A structural limit is a claim, and it needs checking like any other.** I
|
||
recorded that `EXTRAS` could supply only one measurement because *"its sole exit
|
||
is Ⓑ to the menu"*, and called the resulting `n=1` **structural** — a word that
|
||
closes a question. The disc refutes it: build 6 declares **three buttons**
|
||
(`ptbtn11/12/13`, kind `0x3002`), so Ⓐ leaves by another route entirely.
|
||
📌 **"Structural" and "impossible" are the two words most worth distrusting in
|
||
your own notes**, because they retire a question rather than answering it, and
|
||
nothing later re-opens them. The check here cost one `screen info` invocation
|
||
against a claim I had already written into `HANDOFF.md` twice.
|
||
|
||
📌 **And `sylpheed-port`'s corollary, which is the sharper half: distrust them
|
||
hardest when SOMEONE ELSE writes them**, because they arrive without the doubt
|
||
the author would have had. They copied my "EXTRAS is stuck at n=1 — a structural
|
||
limit" out of a message into `DECISIONS.md` as an established fact **while
|
||
holding the file that refuted it** — their own `authored/flow.json`, recording
|
||
`ptbtn11` → `GP_MISSION_SELECT`. The protocol says a message carries no evidence;
|
||
a sentence copied out of one is still a sentence from a message.
|
||
|
||
✅ **Swept this side for the same shape and it is clean** — port-supplied figures
|
||
are attributed in the text (`"port reports 866 keyframes … 0 untimed"`), the
|
||
`ui_layout.rs` comment cites **my own** 0-of-24 811 rather than their 866, and
|
||
their quantisation floor of 0.41 appears in no document of mine at all.
|
||
⚠️ Reach: this tests *attribution wording* and the port-supplied figures I could
|
||
enumerate, not every reliance. 📌 **What protected it was a habit, not vigilance:
|
||
writing the source into the sentence.** That is the third instance of one
|
||
remedy — *state what the number is a number of*, *write the index space into the
|
||
token* (`e10`), *write the source into the claim*. Put the qualifier in the text,
|
||
never in the reader's memory.
|
||
|
||
* 🔴 **Audit the document that defines the objective — it is the one nobody
|
||
audits.** `MISSION.md` is read every iteration by both agents and had **three
|
||
stale section headings**: *"🔴 Emulator-side questions are blocked — the title is
|
||
not reachable here"* (twelve runs reached it that day), *"🟡 Needs one more run —
|
||
a Japanese-locale capture"* describing *"one capture we cannot take"* (taken
|
||
twice, both committed), and *"🔵 Needs a human decision — rotation"* (decided and
|
||
implemented the day it was raised, with a control test in the crate).
|
||
⚠️ Each had been superseded in `HANDOFF.md` and nowhere else. **A document that
|
||
is only ever read for instructions is never read for review** — and the more
|
||
central it is, the more often it is consulted and the less often it is checked.
|
||
📌 Correct the *facts* in such a document and leave its questions and gates
|
||
alone: keeping it true is maintenance, changing what it asks would be
|
||
overstepping.
|
||
|
||
* 📌 **A calibrated instrument can reject its own answer, and should.** Trying to
|
||
name two unidentified screens by correlation gave best fits of RMSE 43 and 46
|
||
with margins of 5.88 and 2.28 — and `which_title_screen.py`'s control already
|
||
establishes that a *true* match scores ~18–20 at margin ~10. Both answers were
|
||
rejected by the calibration the corpus already had. ⚠️ **Without that
|
||
calibration, "best match, margin 5.88" reads like an identification** — a ranked
|
||
list always has a winner, and nothing in the ranking says whether the winner is
|
||
good enough. **Any nearest-match report needs a known-good score beside it**, or
|
||
it will name something every time it is asked.
|
||
|
||
* 🔴 **A refutation that lives only where it was made is not reachable by the
|
||
person about to repeat it.** `REFUTED.md` exists so a grep for your noun finds
|
||
the neighbourhood before you spend an iteration reviving a dead claim. Eight
|
||
claims died in one session, each properly recorded in its own page — and **none
|
||
of them reached that file.** ⚠️ The pages are where a refutation is *argued*;
|
||
the index is where it is *found*. Same split as docs-versus-tool: reasoning
|
||
lives in one place, discovery in another, and only the second one saves anyone.
|
||
📌 The check is mechanical: after withdrawing a claim, grep `REFUTED.md` for its
|
||
noun. If your own noun is not there, you have recorded the death without
|
||
publishing it.
|
||
|
||
* 📌 **A marker an author must PLACE beats a marker a tool must INFER.**
|
||
`sylpheed-port`'s claim register fails their build when a refuted claim is quoted
|
||
without an explicit token, and it caught three live assertions **inside
|
||
corrections they had written themselves** — text that reads as retraction to any
|
||
human. I built the prose equivalent, which infers from neighbourhood language,
|
||
and it does the opposite: it fires on corrections and would miss a revival
|
||
reworded. ⚠️ The reason is structural — an append-only dated log entry and a
|
||
revival are **textually identical**, so no amount of phrasing analysis separates
|
||
*asserted now* from *recorded as believed then*.
|
||
⚠️ **And knowing when to stop tuning is part of it.** Mine went 9 → 2 by adding
|
||
marker phrases; each addition fits the detector to this corpus's habits of
|
||
expression and away from being a test of them. Tuning until it reads zero is
|
||
fitting the instrument to the answer. Left over-reporting, which is the safe
|
||
direction.
|
||
|
||
* 🔴 **A CORRECTION is a new claim, and needs the same check as the claim it
|
||
replaces.** Correcting `MISSION.md`'s stale "emulator-side questions are blocked"
|
||
banner, I wrote that the two items it named were *"unblocked, not answered … both
|
||
need a running menu, neither has been attempted"* — **without reading either
|
||
page**. All three clauses were false: one item had been **resolved** the previous
|
||
day, the other had been **attempted and half-answered**, and its own page records
|
||
that the experiment *"needed the emulator only to boot, not to reach a menu —
|
||
parked behind the title-screen blocker for no reason"*. ⚠️ The failure is
|
||
specific: **replacing a stale status with an unchecked one, in the same edit that
|
||
criticised the document for carrying unchecked status.** `sylpheed-port` wrote a
|
||
dead instruction inside the commit fixing dead instructions; this is the same
|
||
shape. **The urge to correct supplies confidence the correction has not earned** —
|
||
so check a replacement as hard as you checked the thing it replaces, and hardest
|
||
when the edit is *about* checking.
|
||
|
||
* 📌 **Work completed and never indexed is the same failure as a refutation
|
||
argued and never indexed — one level up.** `sylpheed-port` found a milestone whose
|
||
gate had been met "for a very long time" with no gate record: the work existed,
|
||
the artifact existed, the *record* did not. ✅ Audited the Decoder's objective for
|
||
the same shape and it is **clean** — all ten questions cite a result page, every
|
||
`data/` and `captures/` path those pages cite resolves, and the files are
|
||
substantive rather than stubs
|
||
([`data/mission-gate-audit.txt`](data/mission-gate-audit.txt)).
|
||
⚠️ **A clean audit is worth exactly its checks**, so state them: this tests that
|
||
**cited** files **exist** and carry content. It does not test that the data
|
||
supports the claim, and **it cannot see data a page should have cited and did
|
||
not** — a page citing nothing would have passed as "0 missing". Existence and
|
||
substance, never sufficiency.
|
||
|
||
* 📌 **A first count from a new detector is a measurement of the detector.**
|
||
`sylpheed-port`'s formulation, and it now has **four** instances in this corpus
|
||
inside one exchange: my refuted-claim scan 9 → 2 real, their withdrawal hook's 33
|
||
candidates → a few, their `why`-coverage audit 35 → **0** (the 35 were values
|
||
covered by an ancestor key their check only looked for in the same object), and
|
||
my measured-page absence check 3 → **0**. ⚠️ **All four were caught by the same
|
||
cheap habit: inspecting the flagged items before publishing the number.** None
|
||
became a claim, and none would have survived contact with the items themselves.
|
||
**Never report a detector's first count as a finding.**
|
||
|
||
* ⚠️ **And an audit is narrower than its wording.** Checking that every `docs/re/`
|
||
gate cites reference data gave "48 citations, 0 missing" — true, and a statement
|
||
about **one form of evidence**. This corpus carries at least three: committed
|
||
data files, inline tables, and committed disc tests. A page whose evidence is
|
||
`tests/slb_leading_segment_disc.rs` scores zero on a `data/`-path check and is
|
||
fully evidenced. **Name the form you checked, not the property you hope it
|
||
stands for.**
|
||
|
||
## Runtime / emulator
|
||
|
||
* **Look at the PNG** — and check its dimensions.
|
||
* **"Animating" is not "still in a mission".**
|
||
* **Dedup entity enumerations by position value.**
|
||
* **Do not diagnose timing or liveness under gdb.** `ps %cpu` is cumulative.
|
||
* **The `PRESS Ⓐ` glyph counter false-positives on the attract movie by 13×.**
|
||
`title_timing_probe.py`'s plate detector thresholds a green-glyph pixel count
|
||
at 400, and its control checks two committed movie frames that both score 0.
|
||
A real boot disagrees: in one 100 s attract window, **17 frames scored ≥ 400
|
||
and the peak was 5 393** — the movie has green content in the plate region.
|
||
The probe is safe *because its state machine will not look at the glyph until
|
||
the content classifier has already said `title_*`*, not because the threshold
|
||
discriminates. ⚠️ **`glyph()` alone is not a plate detector**; a two-frame
|
||
control over a 3½-minute movie is not a control over that movie.
|
||
* 🔴 **`screen_id.py` cannot see a plate-less title, and calls DIFFICULTY a
|
||
menu.** Both reproduce on committed reference frames:
|
||
|
||
| frame | `screen_id.py` says | should be |
|
||
|---|---|---|
|
||
| `live-title-build4-no-plate.png` | **`other`** | title |
|
||
| `live-title-press-a.png` | `title` | title |
|
||
| `difficulty-screen.png` | **`menu`** | not the main menu |
|
||
|
||
It thresholds on **green** (0.0009 with the plate vs 0.0002 without), so it
|
||
recognises a title only once `PRESS Ⓐ` has faded in — and this corpus's own
|
||
finding is that **the boot title shows build 4 FIRST, plate-less**, for ~2.25 s.
|
||
⚠️ **Any harness that waits for `title` from it can sit through a visible title
|
||
and report nothing** — that is what happened on an `S00A` drive here, 396 s of
|
||
`other` with two spurious `menu` hits, on a run whose audio proved the guest was
|
||
healthy throughout. `newgame_path.sh`, `nav_probe.sh` and `boot_menu.sh` all
|
||
gate on this.
|
||
✅ The zncc-against-committed-frames classifier used for the settle-time screen
|
||
log does not have either defect: 6/6 including both movie frames and
|
||
`difficulty-screen` as negatives, at a 0.85 threshold. ⚠️ At 0.60 it *also*
|
||
called `difficulty-screen` a menu (0.632) — the threshold is doing real work
|
||
and must be controlled, not chosen.
|
||
* **Classify screens by whole-image statistics, not named pixels** — a named
|
||
pixel is only valid while the image sits at a known place, and nothing errors
|
||
when it moves.
|
||
* **Do not poll faster than the guest updates** — it manufactures a clean curve
|
||
out of noise.
|
||
* **A probe that never performs the action will "prove" the action does not
|
||
exist.**
|
||
* **The container's Canary binary can be older than the Canary source tree, and
|
||
the failure mode is a hang, not an error.** After a merge into `sylpheed-re`
|
||
the prebuilt `xenia_canary` had no `log_ui_draws`, no `mem_watch`, no
|
||
`create_profile_if_none` — and an unknown cvar makes xenia open an SDL message
|
||
box before logging is up, which headless is an unexplained freeze. Check before
|
||
trusting a harness flag: `nm -C <binary> | grep cvars::<flag>`, and
|
||
`build-canary Release` if it is missing.
|
||
* **A capture armed *at* a screen only ever sees the steady state.** Anything
|
||
about how a screen is built or animated has to be armed *before* it exists.
|
||
Re-arming every few seconds and keeping every log tiles the approach: each F10
|
||
opens a new numbered file and closes the previous one complete.
|
||
* **A capture stream that opens N seconds after launch will report the boot in
|
||
the wrong order, and nothing errors.** `data/boot-timeline-2026-08-29.tsv`
|
||
opens on the *developer* splash and labels the publisher one 6 s later, which
|
||
reads as `dev → pub` and is the opposite of the boot. The stream had attached
|
||
~7.7 s in and missed the publisher entirely. **The tell was in the file**:
|
||
its first twelve rows are byte-identical to four decimals — one held frame
|
||
sampled twelve times, i.e. the probe joined a screen already in progress rather
|
||
than watching it arrive. If `t = 0` is not the launch, say so in the file; if
|
||
the first rows do not *change*, you did not see the beginning.
|
||
([`boot-order-and-splash-dwell.md`](boot-order-and-splash-dwell.md))
|
||
* **`ADV.wmv` opens with its own SQUARE ENIX card, and it scores 0.75 against the
|
||
publisher splash.** A correlation classifier keyed on
|
||
`live-splash-publisher.png` therefore fires **twice** per boot, ~10 s apart,
|
||
and the second one is a movie frame. Discriminators that work: the real splash
|
||
is *perfectly still* (identical frame statistics for seconds) and scores
|
||
0.93–0.94; the movie card drifts continuously and never passes 0.76 — and its
|
||
wordmark is bloomed and below centre where the splash's is sharp and centred.
|
||
**A threshold that both a screen and a movie frame clear is not a classifier**;
|
||
look at the frame.
|
||
* **Measure animation in submitted frames, not in seconds.** `VdSwap` counts are
|
||
the guest's own frames, so an emulator at 80 % of real time does not move them;
|
||
a stopwatch reading does, silently and by an unknown factor.
|
||
* **~~This game's menus drop d-pad presses shorter than ~0.3 s.~~ WITHDRAWN
|
||
2026-08-28 — the menu WRAPS, and I had not measured that.** The claim came from
|
||
reading a cursor that ended up "one item short"; once wrap-around at both ends
|
||
was measured ([`menu-navigation-semantics.md`](menu-navigation-semantics.md)),
|
||
every one of those press counts is exactly right — four presses at 0.12 s moved
|
||
four steps *through the bottom*, which lands one above where a non-wrapping
|
||
menu would put it. **No press was ever dropped.** The real lesson is the
|
||
general one: *a step count is only readable once you know the topology*, and I
|
||
invented a hardware-flakiness story rather than testing the ends of the list.
|
||
Still true and worth keeping: screenshot after every step and read the cursor,
|
||
rather than trusting arithmetic over the press count.
|
||
* **A screenshot taken right after a transition can catch a screen mid-fade.**
|
||
A grab 2.5 s after Ⓑ returned the game to the title showed the title art with
|
||
no `PRESS Ⓐ BUTTON` plate; one second later the plate was there. That very
|
||
nearly went into the corpus as "the returned title has no plate". Sample a
|
||
changing screen several times before writing down what it does *not* contain.
|
||
* **Do not identify a menu cursor by label brightness.** The obvious oracle —
|
||
"the focused label is the brightest row" — fails on this game's menus, because
|
||
the background art is brighter behind some rows than the highlight is. It
|
||
confidently named the wrong item on a frame whose ring was plainly elsewhere.
|
||
Detect the **focus ring** in the gutter left of the labels instead
|
||
(`tools/re-capture/menu_focus.py`, 254 vs <82 — no threshold tuning needed),
|
||
and look at the PNG before believing either.
|
||
* **`screenshot` samples at 0.5 Hz — it cannot time an animation.** Measured:
|
||
~2 s per grab (an `import` of the root plus an ImageMagick crop). A 0.4 s fade
|
||
falls entirely between two samples, which is why a 40-frame burst across a
|
||
screen change looked like an instant cut. For anything timed, record the
|
||
display instead: `ffmpeg -f x11grab -framerate 30 -video_size <W>x<H> -i
|
||
:98+<X>,<Y> -t <secs>`, then read per-frame statistics off the file. Take the
|
||
geometry from `xwininfo -root -tree`, the same way `bin/screenshot` does.
|
||
* **A screen's brightness curve is not its fade quad.** The incoming screen's own
|
||
elements animate in *after* the transition quad has cleared, so mean luminance
|
||
keeps rising long after the fade is over — 1.47 s against a declared 0.97 s on
|
||
one screen. Time the fade from where the frame is *pure black*, and take the
|
||
ramp itself from the keyframes.
|
||
* **A `sound.pak` entry is not a bank.** Entry windows straddle bank boundaries
|
||
(the leading-region effect), so a naive "walk the RIFFs in this entry" gives
|
||
the tail of the previous bank, then one of your own, then the *next* bank's
|
||
header. It looks like a bank with the wrong number of waves. The tell is a
|
||
`BANK id=` that is not the entry's own number, and the fix is the `seek` packet
|
||
counts — they pin each wave's join exactly, so a straddle can be realigned
|
||
rather than thrown away. 4 of 32 BGM banks look like counterexamples until this
|
||
is applied.
|
||
* **Do not time a video whose start you did not see.** An attract cycle sampled
|
||
from partway through measured "≈85 s", which was used to argue it was not the
|
||
137 s `ADV.wmv`. It was `ADV.wmv`; the sampling began 39 s in. Identify a video
|
||
by **content** — match frames against the candidates and check the matched
|
||
playhead advances monotonically — before reasoning about its duration.
|
||
* **A near-black frame has no signature.** In frame-matching, low-contrast frames
|
||
drive every correlation toward zero and the ranking becomes noise; one control
|
||
frame scored 0.000 and another tied the wrong movie at 0.98. Read a dark
|
||
frame's runner-up as *no evidence*, not as evidence for the runner-up.
|
||
* **A screen that never changes is not necessarily hung — it may be a menu.** A
|
||
90-second screenshot loop that presses nothing will report a perfectly healthy
|
||
`DIFFICULTY` menu as a standing hang, and that reading survived in this corpus
|
||
for months. Before calling a static screen a hang, *look at it*, and press
|
||
something.
|
||
* **Never run `ps -ef` in this container.** Each of the three long-lived
|
||
processes carries the whole loop prompt as its argv, so the listing is tens of
|
||
kilobytes of the prompt you already have. Use `pgrep -x <name>` or
|
||
`ps -o pid=,stat= -C <name>`.
|
||
* **A file extension is not a format.** `sound.pak` is full of `.slb` banks and
|
||
names a `.xgs` project, and neither is an XACT container: the whole 1.08 GB
|
||
archive contains zero `XGSF`, `SDBK` or `WBND` magic, and the executable has no
|
||
XACT string at all. The names came from the authoring tool and survived into the
|
||
shipped data. Check for the magic before committing to a parser for the format
|
||
the extension advertises.
|
||
* **A log-polling probe must compare a COUNT, not test for presence.** Timing an
|
||
operation by waiting for its "done" line in a log gives an instant false
|
||
positive if any earlier run left one there. This produced a confident
|
||
"39.5 fps" that was really 0.1 s of matching a stale line — and it disagreed
|
||
with the true 28.5 fps by enough to have flipped a conclusion. Snapshot
|
||
`log.count(marker)` before starting and wait for it to *increase*.
|
||
* **This container kills long emulator runs.** Twice in one session the
|
||
`xenia_canary` process vanished with **no crash line in its own log** — once
|
||
~50 s into a boot, once ~145 s in at 1.15 GB RSS — while the box sat at
|
||
~1 GB free with swap exhausted. Budget dynamic experiments to fit in ~2 minutes
|
||
of guest time, take the measurement early, and never read a disappearance as a
|
||
guest crash without checking the log tail for one.
|
||
* **When a frame-match will not resolve, sample denser before doubting the
|
||
hypothesis.** Identifying a movie from 5-second screenshots gave contrast-23
|
||
frames, a playhead that would not join up, and a runner-up winning one frame —
|
||
it looked like weak evidence for the wrong film. The same question sampled every
|
||
0.5 s (`ffmpeg x11grab` at 10 fps) answered at **0.999 with a strictly monotone
|
||
playhead**. Sparse sampling does not weaken a signal gracefully; it turns it
|
||
into noise that looks like a different answer.
|
||
* **Check what instrumentation the local build already has before declaring a
|
||
question blocked on tooling.** Two Q8 residuals were written off as needing "an
|
||
emulator whose audio path can be observed". The emulator in this container
|
||
already had `xma_param_probe` — visible in the startup CONFIG DUMP the whole
|
||
time — added by this project for exactly that purpose. Read the cvar dump, or
|
||
`nm -C <binary> | grep cvars::`, before concluding you cannot measure something.
|
||
* **"Strings a function references" is not "arguments a function passes".** A
|
||
loose filter over the strings in a caller produced a tidy-looking screen
|
||
vocabulary; recovering the actual register argument at each call site removed
|
||
half of it, including two names that appeared to be corroborated by independent
|
||
measurement. If the claim is about an argument, simulate the registers — the
|
||
cheap proxy manufactures agreement.
|
||
* **A backward scan for `addi rN, …` misses arguments staged through another
|
||
register.** PPC code often builds a pointer in a scratch register and moves it
|
||
into place later (`addi r27, r11, X` … `mr r5, r27`). A backward search for the
|
||
destination register alone found 7 of 48 sites and missed the two known-good
|
||
ones. Simulate forward over a window instead, tracking `lis`/`addi`/`mr`.
|
||
* **Check a measurement against the WHOLE reference set, not the part you were
|
||
reading.** Two observed BGM stream sizes were recorded as matching "no bank's
|
||
declared waves", which spawned a wrong theory that the decoder gets a window
|
||
rather than a whole wave. They match `BGM_103` exactly — the check had covered
|
||
only the `BGM_0xx` rows of the census, because that is the block that had been
|
||
on screen.
|
||
* **`instructions.function` is unpopulated for most rows in `sylpheed.db`.** A
|
||
query keyed on it returns *nothing* rather than erroring — a `bctr` search
|
||
scoped that way reported "no jump tables" for a function with two known ones.
|
||
Scope by `address between <start> and <end_address>` instead, and gate any such
|
||
query on a function whose answer you already know.
|
||
* **Before testing "state X behaves like this", check that your route actually
|
||
reaches state X.** A test of "does Ⓐ work in phase 4 state 0" was run by
|
||
pressing Ⓑ, on the strength of a decoded `4 → state 0` edge — but the same basic
|
||
block also writes the *phase* field, sending it to phase 2. The test probed the
|
||
wrong state and produced a confident refutation of a live hypothesis. When a
|
||
transition sets more than one field, read the whole block, not the one store you
|
||
were looking for.
|
||
* **A default filter can hide a whole screen, and the corpus will record it as
|
||
absent.** `screen list`/`render` filter on `is_build`, which needs a `.rat`
|
||
child; the developer splash has none, so it never appeared — and a page ended up
|
||
stating it "cannot be rendered at all". It renders fine under `--all`. When two
|
||
pages disagree about whether something exists, run the tool both ways before
|
||
believing either.
|
||
* **A logo that appears twice may be two different things.** The boot shows
|
||
`SQUARE ENIX` at ~2 s and again at ~10 s; the first is the splash screen, the
|
||
second is the intro movie's own opening frame. Reading the capture alone gives
|
||
"three logo screens". Cross-check a repeat against what is *supposed* to be
|
||
playing at that moment before counting it as its own screen.
|
||
* **Do not hard-code an expected element count into a structure scan.** Looking
|
||
for a `.rat` record's keyframes, I required 29 strictly-increasing times because
|
||
a header word read `30`. The records hold **three** keyframes in exactly the
|
||
layout I was testing for, and the over-constrained filter reported the layout as
|
||
refuted. Scan for the *shape* (here: `0x??ffffff` fade words at a constant
|
||
stride) and let the count fall out.
|
||
* **Read the target text before writing a patch pattern for it.** Two iterations
|
||
running, a scripted edit to `HANDOFF.md` failed its assertion because the
|
||
paragraph had been rewrapped since the pattern was written — and both times the
|
||
finding landed in `docs/re/` while the page the port agent reads kept the stale
|
||
version. The commit's file count is the tell: if it is one short, an edit was
|
||
silently dropped.
|
||
* **Two renderers agreeing is not evidence the field is right.** The port's
|
||
composite and `sylpheed-cli screen render` matched on `main_menu` to 3/255 —
|
||
and *both* omitted two elements the game draws, because both read one field
|
||
through one decoder. Agreement between consumers of the same decode measures
|
||
the decode's determinism, not its truth. Only a framebuffer capture is an
|
||
independent check. (Reported by the port agent, 2026-08-28, after a capture
|
||
crop found the missing bracket.)
|
||
* **`./target/debug/<bin>` is STALE in this container — `CARGO_TARGET_DIR` is
|
||
redirected.** The Dockerfile sets `CARGO_TARGET_DIR=/sylph-home/re/target-container`
|
||
so a fresh `cargo build` writes there, while `./target/debug/sylpheed-cli`
|
||
remains whatever was built on the host, hours old. A decoder fix was verified
|
||
against the stale binary and produced byte-identical "before" and "after"
|
||
renders — which reads exactly like "the change had no effect" rather than "you
|
||
ran the old code". Run the binary cargo actually wrote, or `cargo run`.
|
||
* **A pivot-equality test conflates rounding with real breakage.** Checking
|
||
`pivot == texture/2` over `GP_TITLE` flagged 74 % as mismatched, which reads as
|
||
a systemic decode failure. Split by magnitude it is 17 exact, 54 off by ≤ 1 px
|
||
(odd dimensions rounding), and only **24 off by > 8 px** — and those 24 are the
|
||
real finding, concentrated on one element family. Bucket a mismatch by size
|
||
before reporting a rate.
|
||
* **I have now broken the "read the target text first" rule three times.** Each
|
||
time a scripted `HANDOFF.md` edit asserted on a paragraph that had been rewrapped
|
||
by an earlier edit in the same session, and each time the finding landed in
|
||
`docs/re/` while the port's page kept the stale text. Writing the rule down was
|
||
not enough; the working fix is mechanical — `grep`/`sed -n` the target paragraph
|
||
in the same command that patches it, and check the commit's file count.
|
||
* **"The nearest header after the name" is not a name→header mapping.** Looking
|
||
for each sprite's `T8aD` header by searching for its name and taking the next
|
||
`T8aD` returned *the same header for every sprite* — all the names live together
|
||
in the declaration table near the top of the bundle, so "next" is always the
|
||
first one in the file. It failed its own control instantly: different sprites
|
||
reported identical dimensions. Match on something the header itself carries
|
||
(here width × height against the decoded PNGs) rather than on proximity.
|
||
* **`cargo build` passing does not mean `cargo test` compiles.** Adding a field to
|
||
`T8adImage` built the library fine in 1.48 s — and broke two *test-only* struct
|
||
literals, so `cargo test` failed to compile with exit 101. A green build on the
|
||
binary is not a gate for a struct change; run the tests before believing a
|
||
data-structure edit is safe.
|
||
* **Detach long background work with `setsid`, or a tool-call timeout kills it.**
|
||
Three attempts to run the disc-gated test suite in the background died at exit
|
||
143 with an empty log — the timeout's SIGTERM reached the whole process group.
|
||
`setsid nohup cargo test … &` survives, and the run then completes across later
|
||
tool calls. An empty log from a "background" job usually means it was killed,
|
||
not that it produced nothing.
|
||
* **Validate a recommendation before leaving it as advice.** Having concluded a
|
||
question was undecodable from the disc, I named a per-draw GPU capture as the
|
||
next route "because it reads the blend state". It does not — checking the
|
||
capture's own source showed it records textures and vertex attributes and no
|
||
blend registers. A named next step is a claim like any other.
|
||
* **Name the element from the draw's own coordinates before building on it.** A
|
||
skewed draw in a title capture was called "the swoosh" because the swoosh is the
|
||
screen's only diagonal element — an identification by elimination, never checked
|
||
against the draw's NDC extent. It was wrong: the quads span the full screen and
|
||
beyond, the swoosh is a 234-pixel band. Five iterations of analysis pointed at
|
||
the wrong element on the strength of it. Converting the coordinates takes one
|
||
line and should come first.
|
||
* **A census over a bundle's top-level table is not a census over the bundle.**
|
||
The keyframe rotation field read "always zero on this screen" for several
|
||
iterations because every scan walked `GP_TITLE` build 4's **declaration
|
||
table**, and the rotated elements are **nested leaf records** reached through
|
||
an `opt ` link. The bytes were right; the *reach* was wrong, and a negative
|
||
stated without its reach reads like a fact about the disc. Say which region a
|
||
negative covers, and check whether the thing you are looking for lives outside
|
||
it.
|
||
* **Do not assume 4-byte alignment when scanning raw bundle bytes.** A nested
|
||
`RATC` blob starts wherever the parent's chunk stream leaves it — `ptloop01.rat`
|
||
sits at `0xbb5966` — so its 40-byte keyframe blocks are odd-aligned. A scanner
|
||
that filtered candidates on `%4 == 0` found **0/3** of its own control blocks
|
||
and under-counted the corpus by **16 341** blocks, all of them nested. It cost
|
||
nothing to catch, because the control was in the script.
|
||
* **`pkill -f <pattern>` matches the shell running it.** `pkill -f kfscan.py`
|
||
from a `bash -c` whose command line contains `kfscan.py` kills its own shell:
|
||
the tool call returns exit 143/144 and the edit that was queued behind it never
|
||
runs. The same trap makes `pgrep -f` self-report — a "still running? yes" that
|
||
was the shell seeing itself, on a job that had already finished. Use
|
||
`pgrep -x`, or match on a path the current command line does not contain.
|
||
(This is the second `ps`/`pgrep` entry in this file; the first is about
|
||
`ps -ef` dumping the loop prompt.)
|
||
* **Grep a legend and you count the legend.** A sweep for elements with a
|
||
rotation reported "1 element" in every build on the disc — the header line
|
||
`a=alpha r=rot°` matched the ` r=` pattern. A uniform count across
|
||
heterogeneous inputs is the tell. Make the pattern require the *value*
|
||
(` r=-?[0-9]+`), and sanity-check that a known-negative build reports zero.
|
||
* **A pattern over the archives you happened to check is not a negative.** I
|
||
wrote "rotation appears to live only in nested leaf records", correctly scoped
|
||
to the three paks I had swept — and the sweep refuted it on the fourth, within
|
||
the hour, because the alphabet had not reached `GP_DIALOG` yet. Scoping the
|
||
claim was what made it cheap to withdraw, but the better move is to let the
|
||
sweep finish before writing the sentence at all: a negative that is still
|
||
running is not a finding, it is a prediction.
|
||
* **A field that is implemented is not a field that is measured.** The
|
||
pivot-anchored scale term had been in `blit` for months and reasoned about in
|
||
the handoff, and no capture had ever exercised it, because every element anyone
|
||
had looked at was at 100 % scale where the term is identically zero. Look for
|
||
the case that makes a term *large* — here 600 % and 800 % scale, worth 450 px —
|
||
and check it there. A term you cannot distinguish from zero has not been
|
||
verified by any amount of agreement.
|
||
* **Printing a series' minimum and reading it as its range.** I summarised a
|
||
captured alpha series as "constant α ≈ 33" and built a contradiction on it —
|
||
the summary printed `min_alpha` and no maximum, and the series actually ramps
|
||
34 → 255 → 33. The tell was there in the same table: the column beside it said
|
||
*14 distinct colours*, which a constant series cannot have. When a summary
|
||
statistic and a distinct-value count disagree, the summary is wrong.
|
||
* **Calibrate on one element, test on another.** Fitting a declared ramp to a
|
||
capture has two free parameters (rate and offset) and will "succeed" against
|
||
almost anything — my first attempt scored RMS 128/255 and I nearly read the
|
||
numbers rather than noticing the search could not reach the ramp at all. The
|
||
version that means something: fix the clock from element A's ramp, check that
|
||
fix against A's own next landmark, then apply it to element B in the same
|
||
frames with **nothing left to tune**. That is what turned "the shapes look
|
||
different" into "still at 255 nine frames after it should read 32".
|
||
* **Two measurements can both be right and still disagree, when a heuristic sits
|
||
between them.** A change to the keyframe time association is favoured 26× by an
|
||
animation measurement and rejected by a static-render comparison. Both are
|
||
sound: `rest()` picks a pose by *longest dwell*, which is a heuristic layered on
|
||
top of the times, so moving the times moves its tie-breaks. The mistake would
|
||
be to treat one as refuting the other and drop the loser. Name what each
|
||
measurement actually constrains — here *timing* versus *pose selection* — before
|
||
deciding they conflict.
|
||
* **Before believing a render diff refutes a decode, find out which element moved.**
|
||
I reported a 13 % render change as evidence against a keyframe-time hypothesis,
|
||
on a brightness argument about language twins. One element accounted for all of
|
||
it, and that element is a transient flash with **no resting pose** — so the
|
||
difference was our own `rest()` heuristic guessing, and it would have guessed
|
||
under either reading. A whole-image statistic (pixels changed, mean luminance,
|
||
correlation) tells you *that* something moved, never *what*, and an argument
|
||
built on it can be entirely about your own code. Localise the diff to an
|
||
element and read its keyframes first.
|
||
* **A fallback that only runs when its precondition fails is not a fallback.**
|
||
`rest()` picks the longest-dwell keyframe when no plateau exists — but a dwell
|
||
gap is time spent *moving between* two poses, and the only case where an
|
||
endpoint is genuinely held is when the two poses are equal, which is exactly
|
||
the plateau the first path already caught. So the fallback is guaranteed to be
|
||
guessing every time it is reached. When a heuristic's justification is the same
|
||
condition that routes around it, it has no justification.
|
||
* **Siblings adjudicate a rule that a single element cannot.** Deciding what
|
||
`rest()` should return for an element with no held pose looked like it needed a
|
||
capture we do not have. It did not: the developer splash carries three glows
|
||
with identical structure and identical times, differing in one alpha byte, and
|
||
any rule that makes one of them behave completely differently from the other
|
||
two is producing an artefact. Parallel constructions in the same bundle are a
|
||
free control — look for them before concluding a question needs new measurement.
|
||
* **Backgrounding with `&` in a compound command loses the working directory.**
|
||
`cd X && cmd &` followed by more work in the same call left the shell reset, and
|
||
a heredoc two lines later wrote nowhere — while the `echo` after it still
|
||
printed "written". A success message after a failed redirect is not a success.
|
||
Use `(setsid nohup … &)` and keep the file-writing in its own call.
|
||
* **Read the whole function before describing what it does.** I wrote "a
|
||
zero-scale pose paints a 1-pixel sliver" into a tool's docstring, from the
|
||
`.max(1)` in the size arithmetic. Two lines above it, a guard coerced
|
||
`scale == 0` to **100 %**, so the `.max(1)` never saw a zero and the element
|
||
rendered at *full size* — a much larger bug than the one I described. I had
|
||
read the lines I went looking for and stopped.
|
||
* **Never diff a file a background job might still be writing.** A comparison
|
||
loop over an output directory reported `GP_TITLE` build 6 as changed; the pixel
|
||
diff was then all zeros, because `cmp` had read a half-written PNG. Compare
|
||
only after the job signals done, or skip the newest file. A "difference" that
|
||
vanishes on re-examination is usually a race, not a flake.
|
||
* **A `screen list` BUILD index is not a pak ENTRY index.** `GP_TITLE` happens to
|
||
map 1:1 (16 builds, entries 0–15), which is how the assumption survived;
|
||
`GP_DIALOG` does not — its build 0 is **entry 2**. Indexing a pak directly with
|
||
a build number silently reads a different bundle and reports a confident wrong
|
||
answer: a census control asked for the two rotated elements of `GP_DIALOG`
|
||
build 0 and got zero, from a bundle that genuinely has none. `screen list`
|
||
prints the mapping; use it rather than assuming identity.
|
||
* **"There is no flag" is not "there is no way".** I declared a Japanese-locale
|
||
capture impossible in this container because `user_language` is `DECLARE`d and
|
||
never `DEFINE`d, so no cvar exists to pass. That was true and not the question.
|
||
The language is *persisted*: canary builds `XConfig` over
|
||
`<storage_root>/xconfig.settings`, `SetDefaults()` only supplies the value when
|
||
the file has none, and the file is writable. One grep further — for where the
|
||
setting is **stored** rather than where it is **configured** — turned a
|
||
"blocked, needs a human decision" into a two-line edit. When you conclude a
|
||
capability is absent, check the persistence layer before writing it up.
|
||
* **Locate a binary field from struct landmarks, not from a hard-coded offset.**
|
||
`user.language` was found by scanning for `music_volume`'s `0.7f` (a known
|
||
default at a known relative offset), then cross-checking `language == 1` and
|
||
`country == 103` against the emulator's own `SetDefaults()`. Three agreeing
|
||
landmarks, no offset assumed, and the check re-runs every invocation — so the
|
||
tool fails loudly if the layout moves instead of silently patching a
|
||
neighbouring field.
|
||
* **A stale oracle reports the world, not itself.** A 787 s run concluded "the
|
||
game never reached the title". It had, repeatedly: `wait_title.sh` was still
|
||
sampling the single pixel (625,618) that `is_title.py` had already been written
|
||
to replace — a 1280×720 coordinate against a 1279×675 game surface, always
|
||
reading the copyright line. The replacement existed *in the same directory*,
|
||
with a docstring naming the bug. Before believing a negative from a probe,
|
||
check whether something in the toolkit already supersedes it, and run the probe
|
||
against a known-positive capture first — `is_title.py` scores 753 on a real
|
||
title frame and 327 on the main menu, which takes one command to confirm.
|
||
* **Run the control before theorising about the difference.** A Japanese-locale
|
||
run failed to reach the interactive title, and I wrote up the open question as
|
||
"if English reaches it, the difference is the locale". English does not reach
|
||
it either — 75 samples over 734 s, every one a miss. The locale had nothing to
|
||
do with it, and two iterations framed the problem around a variable that was
|
||
never implicated. The control cost one run and would have cost the same one
|
||
iteration earlier.
|
||
* **Log every sample, not just the hit.** The first probe printed nothing until
|
||
it succeeded, so a 787 s failure was indistinguishable from a probe that never
|
||
ran. Printing the oracle's value each tick turns "no title" into "75 samples,
|
||
max glyph 0", which is a measurement — and it is what showed the black-screen
|
||
and attract-movie phases were being sampled correctly all along.
|
||
* **Know when to stop paying for a non-blocking answer.** A capture that would
|
||
settle two 🟡 residuals — neither of which blocks the deliverable — absorbed
|
||
five iterations. Each one produced a real finding (a broken oracle, a wrong
|
||
"impossible", a locale red herring), so none was wasted, but the *question*
|
||
never moved. The signal to stop is not "this is hard", it is "the thing this
|
||
unblocks is not blocking anything". Write down the recipe you built and leave
|
||
it for a session with a reason to spend the time.
|
||
* **Audit what a renderer silently SKIPS, not only what it draws.** `compose` has
|
||
half a dozen `continue` paths, and a sprite-name miss is one of them — an
|
||
element vanishes with no error, which is exactly how the port agent's missing
|
||
bracket happened. `screen render` already prints its omissions; reading that
|
||
list for the five screens that matter took one command and turned up a
|
||
full-screen opaque element dropped on three of them. Any composer with skip
|
||
conditions should be asked to name what it skipped before it is trusted.
|
||
* **An element's declared name is not necessarily its texture's name.** The
|
||
`opt ` link on `pteff05.t32` leads to a `T8aD` registered as `8AX`, so a
|
||
lookup by declared name misses. Before concluding a texture is absent, look at
|
||
the bytes the link actually points at — the name in the declaration table and
|
||
the name the sprite table keys on can differ.
|
||
* **A fit whose residual is large for every model is a broken method, not a
|
||
close call.** Comparing our composite to a capture pixel-wise gave mean abs
|
||
errors of 10–14 for gamma, for a linear scale, for everything — and a
|
||
non-monotonic transfer curve (render 96–127 mapping *brighter* than render
|
||
128–159). The cause was edge misalignment: at correlation 0.947 a bright pixel
|
||
in one image routinely lands on a dark one in the other. Restricting to patches
|
||
that are flat in **both** images dropped the residual to 0.2–1.1. When every
|
||
candidate model fits badly, stop choosing between them and look at what the
|
||
comparison is actually measuring.
|
||
* **Say when a control failed to discriminate, rather than reporting it as a
|
||
pass.** The held-out screen for a tone-curve fit was the developer splash,
|
||
whose flat regions are pure black — every model scored ≈ 0.00 error there. That
|
||
is not corroboration; it is a test with no power, and reporting the 0.00 as
|
||
agreement would have dressed an untested claim as a verified one.
|
||
* **Time your probe against the thing you are probing for.** Four runs concluded
|
||
"the game never reaches the title". `screenshot` costs **10.8 s while xenia is
|
||
running** and **0.117 s once it is killed** — 92× — so a two-grab polling loop
|
||
samples every ~41 s, against a title screen this corpus documents as lasting a
|
||
few seconds. The harness was blinking slower than the event. Before believing a
|
||
negative from a polling loop, measure its interval and compare it to the
|
||
duration of what you are waiting for; and measure the probe's cost *under the
|
||
same load as the run*, because idle timing here was off by two orders of
|
||
magnitude.
|
||
* **Do not change a display setting and a capture behaviour in the same run.**
|
||
`kernel_display_gamma_type = 0` brightens the frame, and `skip_intro.sh`
|
||
classifies movie-vs-static on an *absolute* rmse threshold — so the gamma
|
||
change biased the very classifier the run depended on. Harness thresholds tuned
|
||
on one output configuration are not portable to another.
|
||
* **Fixing the instrument is how you test the explanation that blamed it.** I
|
||
diagnosed four failed runs as "the probe samples slower than the event",
|
||
wrote it up, and withdrew three earlier conclusions on that basis. Building the
|
||
faster probe refuted it: at 100× the sampling density, over 420 unbroken
|
||
seconds, the event still never occurred. The diagnosis was a real defect that
|
||
happened not to be the cause — the most seductive kind, because fixing it feels
|
||
like confirmation. A plausible mechanism that explains a failure is a
|
||
hypothesis, and the fix is its experiment, not its proof.
|
||
* **Ask whether the screen is drawing anything before explaining why a feature of
|
||
it is missing.** Four iterations produced four explanations for "the title is
|
||
not detected" — a stale oracle, the locale, the sampling rate, a one-shot boot
|
||
window — and three of them were refuted in turn. Splitting a raw root grab into
|
||
bands then showed the game surface at **0.08 % non-black, mean 0.07**: it was
|
||
rendering black. The check costs one command and belongs at the *front* of that
|
||
sequence, not after the fourth hypothesis. A detector reporting absence is
|
||
ambiguous between "the feature is not there" and "nothing is there".
|
||
* **A newly found fault does not retroactively explain older failures.** The
|
||
black surface is real and reproducible *in the run where it was measured*.
|
||
Earlier runs in the same session had measurable content (mean 33.1, mean 122.8,
|
||
non-zero frame-to-frame rmse), so the failure mode changed over the session.
|
||
Reaching back to re-explain earlier results with the newest cause would have
|
||
been the fourth over-reach in a row.
|
||
* **Validating a probe on static test images tests its ANALYSIS, not its
|
||
ACQUISITION.** The fast probe's counter was controlled against committed
|
||
captures and matched exactly (753 / 327), which proved the numpy expression
|
||
right and the frame source untested. The source was the broken half: a
|
||
long-lived x11grab stream degrades from 3.98 to 1.60 fps and then freezes,
|
||
repeating one stale frame. The check that catches it is to read the same screen
|
||
with an **independent grabber at the same moment** — `import` said 125.65 where
|
||
the stream said 5.21. Do that during a run, not only at design time.
|
||
* **A dense negative from one instrument is worth less than one cross-check.**
|
||
"2 391 frames, zero hits" reads as overwhelming and collapses to nothing once
|
||
the frames may all be the same frame. Sample count is not evidence of coverage
|
||
unless the samples are known to be independent.
|
||
* **A probe that cross-checks itself turns "no result" into a result.** Three
|
||
successive "the title never appears" claims were withdrawn because the
|
||
instrument was broken each time. The version that finally held prints its own
|
||
reading beside an independent grabber's every 60 s — 9 checks, 8 agreeing to
|
||
within 2 % — so the negative arrives with its own evidence that the frames were
|
||
live. Building the cross-check into the tool costs a few lines and is what
|
||
separates a measurement from a silence.
|
||
* **A hedge in a code comment is an unmeasured claim.** `compose` said the
|
||
derived paint order "reproduces both measured orders up to ties" — a sentence
|
||
that sounds like a result and was neither measured nor kept current: there were
|
||
three measured orders by then, not two. Measuring it took one example program
|
||
and turned a hedge into a bounded number (exact on 4 of 5 bundles; the 5th off
|
||
by 8 pairs, all ties). Grep your own comments for "up to", "roughly",
|
||
"essentially" — each one is a claim nobody has checked.
|
||
* **Count the cases that can actually bite, not the cases that match the
|
||
pattern.** `EXTRAS` has 15 tied pairs in its derived paint order, which reads
|
||
alarming. Only **2** of them overlap, and a tie between non-overlapping
|
||
elements paints identically either way. Reporting 15 would have overstated the
|
||
risk by 7×; the useful number is the one filtered by whether the difference can
|
||
reach a pixel.
|
||
* **An exhaustive field search needs a positive control, or "found nothing" is
|
||
worthless.** Scanning a header for a field that reproduces a measured ordering
|
||
returned zero hits — which could equally mean the field is absent or the scan
|
||
is broken. Running the same scan against a *known* ordering (declaration order)
|
||
returned **64** hits, proving the scan finds ordering fields when they exist.
|
||
Only then is the zero a finding. The control costs four extra lines and turns a
|
||
silence into a negative with reach.
|
||
* **A stale row on the handoff page is worse than a missing one.** The port was
|
||
told SE audio was "undecodable from the disc" while the linked doc had already
|
||
retracted that and located three cues decoding to PCM. The finding landed in
|
||
`docs/re/` and the page the port reads kept the superseded text — the fourth
|
||
time in this corpus. Writing the rule down has not worked, so there is now a
|
||
tool: `tools/re-capture/handoff_lint.py` flags every HANDOFF line that makes a
|
||
strong negative claim and links a doc containing retraction language. It found
|
||
this row, and one benign false positive, on its first run.
|
||
* **Narrow a risk before reporting it, then narrow it again.** "15 tied pairs on
|
||
`EXTRAS`" became 2 (only overlapping ties can paint differently), then 1 (one
|
||
of those two is a `loop*` animation the compositor skips), then "consistent
|
||
with the capture". Each step is a filter that costs one query and changes the
|
||
number by more than an order of magnitude in total. A raw count is almost never
|
||
the number a consumer needs.
|
||
* **Nothing was checking that the docs' cited evidence exists.** A sweep of every
|
||
relative link under `docs/` found **16 broken**, and two of them were the
|
||
figures backing the UI layout decode's headline claim — the port's foundation,
|
||
unreachable from its own page, because a path in `structures/` was written one
|
||
directory too shallow. Eleven were wrong relative depth with the target present;
|
||
five name files that do not exist. Evidence that cannot be opened is not
|
||
evidence, and a link is exactly the kind of thing no one re-reads.
|
||
`tools/re-capture/doc_link_check.py` now does it, and also flags targets that
|
||
resolve to a **zero-byte** file — which looks correct in every listing.
|
||
* **Repair in bulk only when the counts pair.** The fixer rewrote 11 links; the
|
||
checker went from 1 038 resolving / 16 missing to 1 049 / 5. +11 and −11
|
||
against 11 edits is the confirmation that the pass did what it said and touched
|
||
nothing else. A bulk edit without that arithmetic is a hope.
|
||
* **When two candidates carry the same content, compare their DIFFERENCE against
|
||
the oracle, not themselves.** `8AX` (1280×720) and `ptbase` (640×360 at 200 %)
|
||
are the same artwork, so no comparison of either against a capture can separate
|
||
them — every such test had been read as "inconclusive, needs a per-draw
|
||
capture". What separates them is `8AX − upscale(ptbase)`: the detail only one
|
||
of them has. Correlating the capture's residual against *that* answered it
|
||
statically, on two screens, with matched controls.
|
||
* **A ratio that saturates at 1 under noise is not a discriminator.** A pixel-pair
|
||
test cleanly separated upscales (0.00–0.72) from native (0.98) and put the
|
||
capture at 1.01 — apparently decisive. Additive noise raises both terms of the
|
||
ratio equally and drives *any* value toward 1, and fitting a noise term showed
|
||
both hypotheses reproduce the observed numbers. Before believing a ratio, ask
|
||
what it does as noise grows.
|
||
* **Read what a cvar DOES before building an experiment around it.** I planned a
|
||
run to decide whether a measured gamma was "canary's BT.709 output stage",
|
||
by setting `kernel_display_gamma_type = 0` and re-fitting. The cvar is not an
|
||
output stage: it is the value a `kStub` **getter returns to the guest**, which
|
||
the game uses to build its own ramp, and canary applies *that* ramp in the swap
|
||
path. The experiment could never have isolated a stage that does not exist —
|
||
and it would have perturbed the capture harness as a side effect. One grep for
|
||
the cvar's definition replaced a planned emulator run with a better one.
|
||
* **An absence in a log is only evidence if the log would have shown it.** No
|
||
gamma lines appear in any run log here — but kernel exports log at Debug and
|
||
this harness masks Kernel logging entirely (`log_mask = 13`), so their absence
|
||
is guaranteed regardless of what the game did. Check the logging configuration
|
||
before reading silence as a result.
|
||
* **Check what an experiment actually needs before filing it behind a blocker.**
|
||
The gamma question sat parked behind "needs the emulator to reach a menu" for
|
||
several iterations. It needed the emulator only to **boot** — video init, and
|
||
the `VdGetCurrentDisplayGamma` call, happen in the first seconds, long before
|
||
any title screen. A blocker that stops one experiment does not stop every
|
||
experiment in the same area, and it is worth re-reading the parked list against
|
||
what each item really requires rather than against the area it belongs to.
|
||
* **A default value is evidence.** Whether the game writes a gamma ramp looked
|
||
like it needed a GPU trace. It mostly did not: canary initialises the ramp
|
||
table to **identity** and applies it through a shader that is a pure LUT lookup
|
||
with no other transfer. An unwritten ramp is therefore a no-op, and any
|
||
non-identity transfer in the output implies a write. Reading what a field holds
|
||
when nobody has touched it turns "I cannot observe the write" into "the write
|
||
must have happened" — cheaper than instrumenting, though it stays an inference
|
||
and should be labelled one.
|
||
* **Name the weak joint of an inference in the same breath as the conclusion.**
|
||
The chain above assumes our composite reproduces the pre-ramp framebuffer,
|
||
which is the one step that could be wrong. Writing that down beside the
|
||
conclusion — rather than only the supporting facts — is what lets a later
|
||
reader attack it instead of inheriting it.
|
||
* **The startup config dump is the config FILE, not the effective flags.** A run
|
||
passed `--log_mask=12 --log_level=3` and its dump printed `log_mask = 0,
|
||
log_level = 2` — while Kernel Debug logging was demonstrably on, which is how
|
||
that run's finding was obtained. So a dump can neither confirm nor refute a
|
||
command-line override, and reading one as "my flag was ignored" is a mistake I
|
||
nearly made with `trace_gpu_stream`. Verify a flag by its *effect*, not by the
|
||
dump. (This does not undo the earlier `user_language` conclusion: absence of a
|
||
*name* from the dump still shows the cvar is unregistered.)
|
||
* **`kill -9` destroys anything that finalises on shutdown.** Canary starts a GPU
|
||
trace at init but only closes it in `GraphicsSystem::Shutdown()`, so the hard
|
||
kills this session used routinely could never have produced a trace. Before
|
||
concluding a feature is broken, check whether the way you stop the program is
|
||
what discards its output.
|
||
* **Bound a risky experiment from inside, not by watching it.** A boot-time GPU
|
||
trace on a disk at 95 % could have filled it between two tool calls. The runner
|
||
carried its own watchdog that killed the emulator the moment the output passed
|
||
a 2 GiB cap, so the experiment was safe regardless of how coarsely I polled.
|
||
The watchdog never fired, which is the point — it cost nothing and removed the
|
||
need to gamble on timing.
|
||
* **A cvar existing does not mean the feature is compiled in.** `trace_gpu_stream`
|
||
parses, is documented, sets state, and does nothing: the code that opens the
|
||
trace sits behind `#if XE_ENABLE_TRACE_WRITER_INSTRUMENTATION == 1`, which
|
||
`trace_writer.h` ties to `#ifdef NDEBUG` — off in release. Two runs and two
|
||
wrong hypotheses before reading the `#if`. When a switch produces no effect,
|
||
follow the code from the switch to the output and look for a compile-time gate
|
||
before theorising about runtime causes.
|
||
* **Test a compile-time gate against the binary, with a control.** A string that
|
||
exists only inside the guarded block (`_stream.xtr`) settles it in one command:
|
||
0 occurrences in the release binary, **1** in the debug binary. The debug build
|
||
is the control that proves the test can find the string when it is there —
|
||
without it, "0 occurrences" is just as consistent with a bad grep.
|
||
* **`T8aD` headers sit in RATC child order — use that, not the size, to name
|
||
one.** Attributing a sprite header to a sprite name by matching decoded
|
||
dimensions fails whenever two sprites share a size, and `GP_TITLE` build 4 has
|
||
such a pair (`ptlogo_back2eff` / `ptlogo_back2eff5`, both 1133×280) that differ
|
||
in exactly the flag being studied. Header order matches child order — verified
|
||
18/18 on that build against the dimensions as an independent check — so
|
||
ordering resolves what size cannot.
|
||
* **Identical summary statistics are not identical data.** Two same-sized sprites
|
||
reported the same %opaque, %clear and mean alpha to one decimal, which reads as
|
||
"the bundle stores this texture twice". Pixel-comparing them gives max abs diff
|
||
**21**: two different renditions of one image. Three matching summaries over
|
||
300 000 pixels is weak evidence of identity; the comparison costs one line.
|
||
* **A pattern that is perfect on one screen can be near-chance on the disc.** The
|
||
`0x02` bit matched `eff` names 10/10 on `GP_TITLE` build 4, which is exactly
|
||
the sample size that makes a rule feel found. Disc-wide it holds 46.8 % of the
|
||
time — the build's artists simply named their effect sprites consistently. An
|
||
18-element bundle cannot distinguish a format rule from a local naming habit;
|
||
before reporting an implication, run it over the corpus, not the example that
|
||
suggested it.
|
||
* **When an association survives a refuted implication, the counterexamples are
|
||
the finding.** The bit is 3.3× enriched for `eff` names and the sprites that
|
||
break the rule are `pv_loading_ring0`, `pv_loading_light0`–`3`,
|
||
`px_bunk_line` — rings, glows, lights, thin lines. That the exceptions are all
|
||
effect-like artwork *without* the naming convention says more about the field
|
||
than the rule it broke did.
|
||
* **Report a classifier's lift over its base rate, not its accuracy.** The
|
||
`0x02` bit's association with bright-RGB/low-alpha art gives a best single
|
||
threshold of 76.5 % accuracy — which sounds like a finding until you notice
|
||
that always guessing the majority class scores 64.1 %. The lift is 12 points,
|
||
the distributions overlap, and it is a tendency rather than a rule. An accuracy
|
||
quoted without its base rate is not interpretable.
|
||
* **Park a field after N failed hypotheses, and say what was eliminated.** Four
|
||
candidate meanings for one flag bit were each refuted at a cost of roughly an
|
||
iteration apiece, and the bit blocks nothing measurable. Stopping is the right
|
||
call, but only if the negative space is written down — additive blend, name,
|
||
lifetime, premultiplied alpha — so the next attempt starts where this one ended
|
||
rather than at the beginning.
|
||
* **Nothing was checking that a doc's figures match its committed data.** A
|
||
number is written once from a run and then lives in prose that gets edited
|
||
around it; the data file beside it is regenerated independently. All 19
|
||
headline figures across four censuses do currently agree
|
||
(`tools/re-capture/doc_figure_check.py`), which is worth knowing rather than
|
||
assuming — but the checker had to be written **numerically**, because the first
|
||
version grepped for the doc's formatting (`14 709` with a thin space, `33.7`
|
||
rounded from `33.66`) and reported almost every figure as a mismatch. A
|
||
consistency check that fails on formatting will train you to ignore it.
|
||
* **A detached job you never check can outlive many iterations.** Two
|
||
`setsid nohup cargo test … &` runs from earlier iterations were still alive
|
||
**four hours** later, one child at 89 % CPU for 3 h 26 m, holding the load
|
||
average at 14 on 12 cores. `setsid` was added precisely so a tool-call timeout
|
||
could not kill them — which also means nothing kills them. Check that a
|
||
backgrounded run actually exited before launching the next one, and prefer
|
||
`ps -o etime=` over assuming.
|
||
* **Know whether your verification gate can terminate.** `build-reborn test`
|
||
includes a disc test that decodes 166 `.xpr` files (1.4 GB) and had not
|
||
finished after 3 h 26 m of CPU. Every "green run" from it is partial unless the
|
||
suite is stated to have terminated — so report the suite count and elapsed
|
||
state rather than the word "green", which is what I should have been doing all
|
||
session.
|
||
* **"Cannot finish" and "takes an hour" are different claims — measure before
|
||
choosing.** I wrote that the verification gate *cannot terminate*, from having
|
||
watched it run 3 h 26 m. Timing the work directly: 19 of 166 containers exceed
|
||
25 s, `Stage_S02` completes in **144 s**, and one full pass is ~45–60 minutes.
|
||
Nothing hangs. The 3 h 26 m was that hour of work at a load average of 9–14,
|
||
inflated by my own duplicate runs. A slow thing observed under contention looks
|
||
like a stuck thing, and the correction matters: an hour-scale gate can be run
|
||
deliberately, a hung one cannot be run at all.
|
||
* **Separate the question with evidence from the question tangled with it.** The
|
||
keyframe-time reading was held back for several iterations by one objection:
|
||
adopting it changes `rest()` on a single element. But `rest()` reaches the times
|
||
only through a fallback that is unsound whenever it runs, and the shift does not
|
||
fix that fallback either — so the objection was never about the times. Timing
|
||
had three discriminating measurements; pose-selection had a heuristic guessing.
|
||
When a conclusion is blocked, check whether the blocker is actually evidence
|
||
about the same thing.
|
||
* **A predicate over adjacent PAIRS silently misclassifies a one-element list.**
|
||
"Has a plateau" was implemented as *any two adjacent keyframes share a pose* —
|
||
which is false for a single-keyframe element, so 1 502 static elements were
|
||
counted as having a *guessed* rest pose and the published defect rate was 65 %
|
||
too high. The error only surfaced when acting on it: suppressing those elements
|
||
dropped the title's correlation by 0.27, because they include the backgrounds.
|
||
Whenever a rule quantifies over pairs, ask what it says about a list of one.
|
||
* **Acting on a claim is a better test of it than re-reading it.** The
|
||
single-keyframe flaw survived a disc-wide census, a write-up and a handoff row.
|
||
It died the moment the rule was used to change a rendering, because the result
|
||
was visibly worse. If a measurement implies an action, take the action on
|
||
something you can score.
|
||
* **Score a rule where it can actually differ, or you will measure nothing.**
|
||
Three rest-pose rules rendered builds 4, 5 and 6 to *identical* correlations —
|
||
not because they agree, but because the code they change is unreachable on
|
||
those screens. The signal was on the two splashes, the only builds whose
|
||
elements reach the fallback at all. Identical results across variants is a
|
||
clue that the variant is not being exercised, not evidence that the choice does
|
||
not matter.
|
||
* **An argument from symmetry is a prediction, not a refutation.** I killed the
|
||
last-keyframe rule because it treats one of three sibling glows differently,
|
||
which felt like an artefact. Measured, it is the better rule on both screens
|
||
where it applies. Aesthetic expectations about how authored data "should" look
|
||
are worth stating as hypotheses and worth nothing as verdicts.
|
||
* **A blank render is a correlation of NaN, not a low score — notice which.**
|
||
Applying "rest = last keyframe" to every element made both splashes render with
|
||
zero variance, so the correlation was undefined rather than poor. Reading the
|
||
NaN as "the tool failed" would have hidden the result; it *was* the result, and
|
||
the strongest form of it. Check for degenerate output before treating a missing
|
||
number as a broken measurement.
|
||
* **When a model predicts something and the measurement refuses, the model is
|
||
usually incomplete rather than wrong.** The shifted time reading says when each
|
||
pose is reached, which looked like it implied the final pose is the resting
|
||
one. It does not: it says nothing about whether the group is *played to
|
||
completion* while the screen is still up. The exit is the dismissal, so a
|
||
displayed screen never reaches its last keyframe. Both claims survive; what was
|
||
wrong was the step between them that I supplied.
|
||
* **The control is what turns a helpful edit into a finding.** Suppressing the
|
||
`_eff` glows raised both splashes from ≈0.96 to ≈0.998 — on its own that reads
|
||
as "we over-draw glows". Running the same edit on the three screens that settle
|
||
made them **worse** (−0.002, −0.092, −0.107), which is what makes the result
|
||
mean something specific: the over-draw is confined to transient screens, where
|
||
a plateau mid-animation is not evidence the element is on screen at rest. An
|
||
edit that improves one set of cases is only interesting once you have shown it
|
||
damages the cases where it should.
|
||
* **When a model reproduces durations but not positions, the missing piece is an
|
||
origin, not a rate.** Playing the splash timeline matched every element's
|
||
on-screen *length* to within 2 % while placing the elements in the wrong part
|
||
of the run. That pattern names the gap precisely — the rate and the shape are
|
||
right, so what is absent is a per-group start — and it pointed straight at the
|
||
one undecoded word in the group header. (Which was zero, but the diagnosis was
|
||
still what made the next step obvious rather than a search.)
|
||
* **Two elements with identical data and different outcomes is the strongest
|
||
possible evidence that the decision is elsewhere.** `palogo_anima` and
|
||
`palogo_gamearts` carry byte-identical keyframe times; one is drawn for 95
|
||
frames and the other not at all. No amount of re-reading the placement data can
|
||
explain that, and the pair is worth more than a survey — when a hypothesis says
|
||
"the data decides", look for two records that agree and behave differently.
|
||
* **A shared resource address does not identify the resource's owner.** The draw
|
||
log's `tex[base=…]` looked like it would say whether two animation phases came
|
||
from the same bundle. All three splash phases report `0x11C30000` — including
|
||
the publisher splash, which is certainly a *different* bundle. The address is a
|
||
reused upload slot. The control was free and sitting in the same table; without
|
||
it the shared base would have read as proof of a shared bundle.
|
||
* **State the mechanism as a separate claim from the observation.** "Declared
|
||
elements are not what gets drawn" is measured and holds. "Because one bundle
|
||
activates its elements selectively" was an explanation I attached to it, and it
|
||
is not established. Bundling the two let the weaker claim inherit the stronger
|
||
one's evidence.
|
||
* **Ask what the competing hypothesis would REQUIRE on the disc.** Two
|
||
explanations for the splash's disjoint phases looked separable only by a
|
||
capture I could not take, and the capture-side test failed its control. The
|
||
alternative needed a bundle declaring the glows without the logos — a
|
||
four-entry enumeration showed none exists, and the question closed statically.
|
||
A hypothesis that predicts an artefact can be killed by looking for the
|
||
artefact, which is often far cheaper than measuring the behaviour.
|
||
* **Check what a "measured" value was measured *from* before reasoning about
|
||
its limits.** Two things that never co-occur have no observable relative order
|
||
— true, and a real limit on any order read from a *draw capture*. I applied it
|
||
to the splash's paint order and withdrew it hours later: that vector is a read
|
||
of the runtime **child array**, which has a definite order whether or not its
|
||
children are ever drawn together, and the two halves in question also carry
|
||
distinct static layer keys. Both the provenance and an independent static field
|
||
said the order was real. The general trap is not the co-occurrence rule, it is
|
||
applying a source-specific limit to a value from a different source: the word
|
||
"measured" covers several kinds of evidence, and the page that recorded it
|
||
usually says which — `ui-screen-runtime.md` said "child slots" in as many
|
||
words. Read that line before building an argument on top of it.
|
||
|
||
* **A heuristic that is right 99.9 % of the time still has a shape to its
|
||
failures — find it before trusting the field.** RATC child names were read by
|
||
scanning backwards for the last printable run of bytes. That agrees with the
|
||
format's own `opt ` declaration on 17 918 of 17 942 children, which is the kind
|
||
of agreement that stops people looking. The 24 exceptions were not random: all
|
||
24 are the *same* case, a 3-byte binary tail that happens to be printable ASCII
|
||
(`8AX`), and one of them was the full-resolution background of every menu
|
||
screen we care about. Ask what the format *states* before settling for what a
|
||
scan *infers*, especially when the stated version is already decoded elsewhere
|
||
in the same file — `opt ` was being read for button focus links the whole time.
|
||
|
||
* **A `continue` that silently skips is a defect even when the skip is correct.**
|
||
`compose` drops an element whose sprite does not resolve. Two arms above it
|
||
record the name into `missing` first; the `el.sprite.is_none()` arm does not.
|
||
So a screen lost its background and `screen render` still reported "sprites
|
||
that did not resolve: none" — the diagnostic was structurally unable to see it.
|
||
When adding an early-out to a loop that already reports what it discards, make
|
||
it report through the same channel, or it becomes a place findings go to die.
|
||
|
||
* **"It has no name" can mean "it is not a thing that gets named."** Sixty RATC
|
||
children had no `opt ` name block and the open question was whether the block
|
||
was absent or merely outside our search window. It was neither: the sixty are
|
||
*frames*, ten each of six copies of one `.tan` animation, and one `opt ` block
|
||
names the whole run. The give-away was in the data before any hypothesis was —
|
||
the distances back to the nearest tag were an exact arithmetic progression
|
||
(`213 + n·60600`), i.e. ten different records finding the *same* tag. When a
|
||
negative result's measurements come out evenly spaced, the thing you are
|
||
counting is probably not the thing the format counts.
|
||
|
||
* **This container OOM-kills `slb_leading_segment_disc` under default test
|
||
parallelism.** It dies with `signal: 9, SIGKILL` and no assertion — eight
|
||
threads each holding a slice of a ~1.1 GB bank. It is not a regression and not
|
||
a flake, and it reproduces when run alone. `-- --test-threads=1` passes 8/8 in
|
||
20 s. Before believing a SIGKILL in this repo, re-run the suite serially;
|
||
before believing a *pass*, check nothing else heavy was sharing the box.
|
||
⚠️ And budget for `mesh_consistency_disc`: it takes **22 minutes** (1 318 s
|
||
measured, serial) and produces no output while it runs, so `build-reborn test`
|
||
looks hung for a third of an hour. It is not. Two runs were killed for looking
|
||
stuck before it was timed. If the change under test is not in the mesh path,
|
||
`build-reborn t -p <crate>` scopes around it — note that `build-reborn test`
|
||
itself passes `--workspace` and will ignore a `-p`.
|
||
|
||
* **Never measure a file another process is still writing.** `ffprobe` on a
|
||
half-written transcode reported 33 s against a 137 s source — the shape of
|
||
catastrophic truncation, with no error and no warning, and it nearly became a
|
||
filed bug. The tell was the mtime and a climbing packet count, not anything in
|
||
the tool's output. Before comparing an artifact you did not produce, check that
|
||
whoever produces it has finished; across two agents sharing a repo this is a
|
||
race, not an edge case.
|
||
|
||
* **A difference-signal RMS means nothing until the two are aligned.** Comparing a
|
||
transcode against its source gave source RMS −25.3 dB and difference RMS
|
||
−34.2 dB — only ~9 dB down, which looks like a failure. It is inconclusive: a
|
||
one-sample offset makes the difference nearly as loud as the source. Any such
|
||
test needs cross-correlation to align first and an agreed downmix, and only then
|
||
is a pass mark like ">40 dB down" meaningful. Reporting the 9 dB as a result
|
||
would have been a confident wrong number.
|
||
|
||
## A shared `CARGO_TARGET_DIR` makes a worktree build replace the binary you run
|
||
|
||
`CARGO_TARGET_DIR=/sylph-home/re/target-container` is set for the whole container,
|
||
so **every checkout shares one target directory**. Build anything in a
|
||
`git worktree` — the obvious way to render from an old tag as a control — and the
|
||
binary at `$CARGO_TARGET_DIR/release/` is now the *other* checkout's. Cargo then
|
||
considers your main tree fresh and does not rebuild it.
|
||
|
||
It cost three renders here that silently used a CLI with no `--at` flag, and the
|
||
only reason it was caught is that the missing flag was a hard error. **A stale
|
||
binary that merely produces slightly different numbers would have been believed.**
|
||
|
||
After any worktree build, `touch` a source file and rebuild before measuring
|
||
anything — and prefer building the control's binary to an explicit
|
||
`--target-dir` of its own.
|
||
|
||
## `rest()` is one element's last hold, not the settled screen
|
||
|
||
`Element::rest()` picks each element's last **hold** keyframe *independently of
|
||
every other element*, so a composite built from it is not the screen at any moment
|
||
in time — it is a per-element maximum. For a transient this is exactly wrong: a
|
||
two-frame flash's last hold is the flash **peak**, so `rest()` leaves it burning
|
||
forever.
|
||
|
||
Five such flashes stack on the title and saturate the light arc; the band's error
|
||
against the console was 33.22, and 8 581 pixels sat at the clipping level where
|
||
the console has 1 459. Posing every element at one shared instant instead — the
|
||
midpoint of the longest keyframe-free interval — takes those to 11.79 and 1 452.
|
||
|
||
The general trap: **an aggregate computed per-element is not a state of the
|
||
system.** Ask what instant a composite claims to depict, and check that every
|
||
element was asked the same question. See
|
||
[`structures/ui-settle-time.md`](structures/ui-settle-time.md).
|
||
|
||
## A 2D draw's identity is its geometry, not its bound texture
|
||
|
||
The title's sprites **sample large shared texture pages**, so the texture bound to
|
||
a draw identifies a page and not an element. Matching a bound texture's dimensions
|
||
against a decoded sprite's fails silently in both directions, and one pass here
|
||
did both at once:
|
||
|
||
* **false negative** — "none of the five flash sprites is ever drawn". They are
|
||
drawn; they simply never appear as their own texture.
|
||
* **false positive** — "`ptbase2` (640×360) and `pteff04` (1280×720) are drawn in
|
||
frames 75–105". Those frames are the **intro movie**, whose YUV planes and
|
||
target happen to be 640×360 and 1280×720.
|
||
|
||
Re-run against the **quad's vertex rect** in design space and every element
|
||
appears where the disc says it should. Canary's own capture code already carries
|
||
this warning in a comment, and the corpus had already recorded that the settled
|
||
title binds only 1280×768 pages — both were there to be read first.
|
||
|
||
The general shape: **a coincidence of size is not an identification.** Before
|
||
matching on one attribute, ask what else in the frame shares it.
|
||
|
||
## A batched draw merges quads, and the merge can be invisible
|
||
|
||
A GPU draw can carry several quads — `indices=4` is one, `indices=8` two,
|
||
`indices=24` six — and the UI draw log dumps **only the first 8 vertices**. Taking
|
||
min/max over a log line's whole vertex list therefore silently *merges* quads into
|
||
one bounding box.
|
||
|
||
This produced two wrong findings in one session, one of them reported to another
|
||
agent with three alternative explanations "ruled out":
|
||
|
||
* **`ptlogo_back2eff3` "is never drawn by the game".** It is batched with
|
||
`ptlogo_back2eff4`, and because the wipe family is right-aligned, `eff3`
|
||
(788…1196) lies **entirely inside** `eff4` (447…1196). The union is *exactly*
|
||
`eff4`'s extent — so the merged box matched `eff4` to 1 px, `eff3` vanished, and
|
||
nothing looked wrong.
|
||
* **"the developer splash is one composited quad."** `gamearts_eff` and
|
||
`seta_eff` merged into a box that was read as the bounding box of three logos —
|
||
which it could not have been, since it was 259 px tall and they span 421.
|
||
|
||
**Why the checks failed.** Three hypotheses were tested and refuted — sampling
|
||
phase, a draw with no geometry logged, a bad position guess. All three were aimed
|
||
at the wrong failure. In particular the "invisible draw" check counted draws with
|
||
**no** geometry line; the hiding place was draws with **partial** geometry, which
|
||
was never looked for.
|
||
|
||
> 🔴 **Refuting three wrong hypotheses is not evidence for a fourth.** The
|
||
> confidence gained from "I ruled out everything I could think of" is worth
|
||
> exactly as much as the list was complete, and a list of failure modes assembled
|
||
> by the person who built the instrument is the least likely to contain that
|
||
> instrument's own blind spot.
|
||
|
||
Parse vertices in groups of four, one per quad, and **compare the logged quad
|
||
count against `indices / 4`** — `tools/re-capture/quads_per_frame.py` does both and
|
||
warns on the shortfall.
|
||
|
||
⚠️ A related tell that was present and ignored: a merged box carries the *first*
|
||
quad's vertex colour, which made one element's alpha read 255 / 127 / 254 on
|
||
consecutive frames. That non-monotonicity was noticed, written down as "the
|
||
vertex-alpha identity does not generalise", and not chased. **An anomaly you
|
||
explain away is cheaper to chase than to re-derive later.**
|
||
|
||
## Count the batch, not the quads the log happened to print
|
||
|
||
The UI draw log caps its vertex dump at **8 vertices — two quads** — while a draw
|
||
may batch many more (`indices=24` is six). Two consequences, and the second is the
|
||
one that bites:
|
||
|
||
* a bounding box taken across a line's vertices **merges** quads (already recorded
|
||
above, the `eff3` false negative);
|
||
* **which** elements appear in the log is the *first two in the batch*, and that
|
||
set changes as elements fade. On the boot's developer splash the three glows
|
||
occupy the prefix until t=45; the three wordmarks are invisible to the log until
|
||
the glows stop being submitted. Read naively this says "the wordmarks are first
|
||
drawn at frame 140", which is the logging prefix shifting and not the game.
|
||
|
||
That produced two splash spans 7.9 % apart on one boot of one guest — a quantity
|
||
that must be one number. **The fix costs nothing: `indices / 4` is how many quads
|
||
the draw actually holds, and the cap cannot touch it.** Its transitions land
|
||
exactly where the declared count of elements with alpha > 0 changes, which makes
|
||
them free calibration points.
|
||
|
||
> The general form: **when an instrument truncates, the surviving sample is not
|
||
> random — it is the first N, and what falls in the first N is itself a moving
|
||
> function of the thing you are measuring.** A truncated view looks like a
|
||
> complete view of a smaller set.
|
||
|
||
## Before calling a failure unexplained, grep the corpus for its *symptom*
|
||
|
||
`title-a-press-fault.md` spent a session recording that a single Ⓐ faults the guest
|
||
4/4, and closed with *"it does not explain how Q4/Q5 pressed Ⓐ successfully; what
|
||
differs is unfound."*
|
||
|
||
**It was found, and written down twice, before that page existed.**
|
||
|
||
* [`canary-scripted-input-traps.md`](canary-scripted-input-traps.md) §3: *"With no
|
||
profile, Ⓐ **is** handled: the guest calls `XamShowSigninUI` and Xenia pops its
|
||
Sign In dialog"* — with a committed capture.
|
||
* `tools/re-capture/boot_menu.sh`'s header, which explains the swallow **and quotes
|
||
the 8.4 million figure**, and is why that launcher passes
|
||
`--logged_profile_slot_0_xuid`.
|
||
|
||
The fault page searched for the *cause* it had hypothesised — an unimplemented
|
||
instruction, then a wild pointer — and never searched for its own *symptom*, which
|
||
would have hit both immediately.
|
||
|
||
⚠️ **Two lessons, and the second is the expensive one:**
|
||
|
||
1. **Grep for the symptom, not the theory.** "Ⓐ", "signin", "IsUIActive" were all in
|
||
the tree.
|
||
2. 🔴 **Knowledge in a script header is invisible to the document that needs it.**
|
||
`boot_menu.sh` had the mechanism and the magnitude, and no `docs/re/` page linked
|
||
to it. A tool comment is a fine place to explain a flag and a **bad** place to be
|
||
the only record of a finding. If a script comment is carrying a measurement, that
|
||
measurement belongs in `docs/re/` with the script pointing at it.
|
||
|
||
What the later session did add was the **join** — that this known input blackout is
|
||
what drives the guest's unbounded keystroke queue into a failed 128 MB allocation —
|
||
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.
|
||
|
||
## A pixel figure without its region and its threshold is not checkable
|
||
|
||
`plate-pulse-measured.md` published 159 / 714 / 1520 as the plate-absent floor and
|
||
the pulse's two levels. The port agent holds the same capture, tried to reproduce
|
||
the floor, and got 3–5× at every threshold it tried — because the page named
|
||
neither the **region** (whole 1280×720 frame, not a plate crop) nor the
|
||
**predicate** (`(g>130) & (g−r>45) & (g−b>45)`, a three-channel test, not
|
||
`green > N`).
|
||
|
||
⚠️ **This is worse than an obviously incomplete number.** A figure with no stated
|
||
method reads as checkable, so a reader spends real effort failing to reproduce it
|
||
and then has to decide whether the disagreement is theirs or yours.
|
||
|
||
And writing the method down immediately exposed a defect the prose had hidden: the
|
||
floor came from a **1279×675** capture while the pulse came from **1280×720**
|
||
frames — different crops, silently compared. The fix was a same-run, same-geometry
|
||
floor that was in the series all along.
|
||
|
||
**So:** every pixel count states its region and its predicate, and a comparison
|
||
between two counts states that they share a geometry. If they do not, that is a
|
||
finding about the comparison, not a detail.
|
||
|
||
## A fix that overshoots leaves no symptom until something else needs the part it disabled
|
||
|
||
From the port agent, and it generalises past its own case. Its static-overlay path
|
||
was **frozen at the overlay's arrival** — a fix for a different bug that reached too
|
||
far and stopped the overlay's clock entirely. Nothing noticed for a week, because
|
||
nothing needed that clock to advance. The plate pulse is what finally gave it
|
||
something to be wrong about.
|
||
|
||
⚠️ **An over-broad fix does not fail; it goes quiet.** The class of bug to look for
|
||
is not "this is broken" but "this has been correct-by-inactivity since the day
|
||
somebody disabled it". When a fix works by *stopping* something rather than
|
||
correcting it, that is the moment to write down what has been stopped.
|
||
|
||
## A detector that can fire on a single frame will fire on the wrong one
|
||
|
||
The Ⓐ A/B's first pair was **void**, and the reason is worth more than the result.
|
||
The "wait for the title" step tested one frame against a glyph threshold. The intro
|
||
movie throws green flashes of **1 298…5 433** lasting under a second, which clears
|
||
any threshold the title also clears — so both legs pressed Ⓐ into the movie, about
|
||
**6 s before the title appeared**.
|
||
|
||
🔴 **What makes this dangerous is that it looked like it ran.** The presses were
|
||
real and had a real effect: each skipped the rest of the movie, which is exactly
|
||
what the corpus documents Ⓐ doing to a movie. Both legs then reported zero swallow
|
||
and zero crashes — a clean, symmetric, entirely meaningless result. **A void test
|
||
that appears to have run is worse than one that errors**, because nothing prompts
|
||
you to look.
|
||
|
||
It is the same shape `is_title.py` already records for `screen_id.py`, which called
|
||
the SQUARE ENIX logo "title" 151 s into a boot and spent `skip_intro`'s one press
|
||
there. The corpus has now paid for this twice.
|
||
|
||
**The rule: a screen detector matches a *signature over time*, never a single
|
||
frame.** The fixed version requires 12 consecutive samples inside a band the movie
|
||
overshoots — and, crucially, it was **replayed against the void runs' own recorded
|
||
series as its control**, where it declines the flash at 84.8 / 85.5 s and fires at
|
||
93.9 / 94.7 s. A broken run's data is the cheapest possible control for its
|
||
replacement; keep the series.
|
||
|
||
## A demand for reproducibility can surface a defect that is not the one demanded
|
||
|
||
The port agent challenged this corpus's pulse figures as unverifiable — it had the
|
||
capture and could not reproduce the numbers. The literal answer was small: name the
|
||
predicate, and its counts then matched **exactly**.
|
||
|
||
But writing the method down is what exposed the actual defect: the floor came from a
|
||
**1279×675** capture and the pulse from **1280×720** frames, silently compared
|
||
across geometries. Nobody was looking for that.
|
||
|
||
⚠️ **And both sides were wrong at once.** The challenger's counts were the wrong
|
||
measurement (single-channel, plate-crop) *and* the published figure had a real flaw.
|
||
"One of us must be right" was never the shape of it — which is worth remembering
|
||
before spending a round arguing about which.
|
||
|
||
## A rule learned from a burn generalises to cases that LOOK like the burn, not to cases that share its mechanism
|
||
|
||
Contributed by the port agent, and it is the sharpest thing either of us has put in
|
||
this file.
|
||
|
||
This file already carries **two** divisor bugs, both the same shape: a silent input
|
||
sitting in a divisor and attenuating real signal. The lesson taken from them was
|
||
roughly *"be suspicious of dividing by N"*. So when the intro's three streams had to
|
||
be combined, the port summed at **unity** — and its own checker rejected the tree at
|
||
**+2.62 dBFS**.
|
||
|
||
🔴 **The precedent did not transfer, and the surface shape is why it looked like it
|
||
would.** Both cases are "several streams, one output". But:
|
||
|
||
* a BGM bank's two waves are **stems of one signal** — parts that were split apart
|
||
and must be added back;
|
||
* the intro's three streams are **positions in a field** — a stereo downmix weights
|
||
them 0.4142 / 0.2929 / 0.2929, which **sum to one whatever the assignment**, so
|
||
the total is fixed even when the placement is unknown.
|
||
|
||
Divide-by-N is neither right nor wrong in itself. It depends on whether the inputs
|
||
are parts of one *signal* or parts of one *field*, and nothing in the phrase
|
||
"several streams, one output" distinguishes those.
|
||
|
||
⚠️ **The general failure**: a rule extracted from a specific burn tends to be indexed
|
||
by *what the burn looked like* rather than by *why it happened*. It then fires on the
|
||
next thing with the same silhouette — and, worse, feels well-earned while doing it.
|
||
When reaching for a past lesson, state the mechanism it turned on and check that
|
||
mechanism is present, not the resemblance.
|
||
|
||
## An internal check cannot catch a bug that makes the input smaller
|
||
|
||
`resolve_movie_voice_region` truncated the first stream of 17 voice regions for as
|
||
long as it existed, and **every test passed the whole time**. There was nothing for
|
||
them to catch: the region parsed, `to_xma_riffs` returned chunks, the chunks decoded,
|
||
the durations were self-consistent. A missing third of a stream produces *smaller
|
||
valid output*, and no check written against our own output distinguishes that from
|
||
correct output.
|
||
|
||
What caught it was a **number from outside**: the running decoder reports its XMA
|
||
contexts' `byte_size`, and 3 584 000 did not fit in a 3 114 352-byte region. The
|
||
port agent did that arithmetic and refused to use my result until it resolved.
|
||
|
||
⚠️ **The general shape: a defect that removes data is invisible to consistency
|
||
checks and visible only to an external quantity.** Prefer at least one test per
|
||
decoder pinned to something we did not produce — an emulator probe, a header field
|
||
the format declares, a total the container states. `adv_voice_region_holds_all_three_decoded_streams`
|
||
is written that way deliberately, and its comment says so, because the obvious
|
||
"maintenance" of such a test is to re-baseline it against current output, which
|
||
would delete the only thing it was for.
|
||
|
||
📌 And the corollary the port stated better than I did: **it was checkable only
|
||
because the identifier happened to be a byte count.** Had the assignment been indexed
|
||
by something the other side could not measure, it would have been adopted intact.
|
||
When handing over a result, prefer to index it by a quantity the recipient can test.
|
||
|
||
## Erring cautious is not free: over-warning is what makes the next real warning unreadable
|
||
|
||
From the port agent, after two consecutive rounds where its "known incomplete"
|
||
banner fired wrongly — first carrying a message true only for `ADV`, then claiming a
|
||
gap over a chunk that is **93.694 s of exact zeroes**. A dropped *silent* stream is
|
||
not missing content.
|
||
|
||
Both errors were in the **cautious** direction, and that is the point. A false
|
||
warning feels like the safe mistake, so it goes unexamined for far longer than a
|
||
false all-clear would — and the cost is not zero, it is deferred and it lands on the
|
||
one occasion the warning is true. Here that warning is the only thing standing
|
||
between a listener and audio they cannot tell is missing.
|
||
|
||
⚠️ **So a warning needs the same scrutiny as an assertion**, and specifically: check
|
||
what it keys on. The fix was `kept < content_waves` rather than `kept < present`,
|
||
which is the distinction between "we dropped something" and "we dropped something
|
||
that had audio in it".
|
||
|
||
## ✅ A second asset moving the way the mechanism predicts — and what that is worth
|
||
|
||
When the voice-region fix landed, `S00A`'s kept-stream count went **1 → 2**: a chunk
|
||
that had been a *different duration* now matched the others at 93.694 s. That is
|
||
exactly what restoring a truncated first stream predicts, on an asset the fix was
|
||
**not** derived from, and the prediction preceded the observation.
|
||
|
||
⚠️ **It is not independent ground truth** — it is the port's exporter reading this
|
||
crate's fixed output, so a fault in the fix would reproduce. Recorded at that
|
||
strength and no higher. The distinction worth keeping: *a different asset* is real
|
||
evidence about generality; *a different implementation* is what makes it independent,
|
||
and only one of those two was present.
|
||
|
||
## The instrument can be sound, the number correct, and the sentence around it wrong
|
||
|
||
Almost everything else in this file is about a broken or misspecified instrument.
|
||
This one is different, and the port agent named it after hitting it twice in a
|
||
fortnight:
|
||
|
||
* it measured a **3.4 s near-silent seam** in its menu bed — correctly — and wrote
|
||
it up as *"the cost of the missing loop point"*. The seam was real; it was
|
||
produced by **our own loop**, and the game has none. It then reached a
|
||
`BLOCKED.md` entry and a message to me, both carrying the wrong cause.
|
||
* it measured a leading chunk correlating at **r=0.998** with another stream's tail
|
||
— correctly — and called it *a duplicate*. It was a **start-truncated simultaneous
|
||
stream**, and the flush-against-the-end alignment is exactly what truncation
|
||
predicts.
|
||
|
||
Both times the number survived scrutiny and the **attribution** did not.
|
||
|
||
⚠️ **No amount of instrument control catches this.** Controls test whether the
|
||
measurement is faithful; they say nothing about the clause that follows it. The
|
||
defences that do work are different in kind:
|
||
|
||
* **name the alternative explanation explicitly** and say why it is excluded — "a
|
||
seam because we loop wrongly" was never written down as a candidate, so it was
|
||
never rejected;
|
||
* **notice when a measurement is being used to explain something it did not
|
||
measure.** The seam was measured *in our output*; the sentence made a claim about
|
||
*the game*. That step is where the error lives, and it is invisible while the
|
||
number stays in view.
|
||
|
||
📌 A useful smell: a measurement that arrives already attached to a cause, and
|
||
whose cause happens to be the thing you were hoping to justify — a missing field, a
|
||
duplicate worth dropping. Both of these did.
|
||
|
||
## A control easier than the measurement does not bound the measurement's error
|
||
|
||
`menu-bgm-loop-measured.md` located a capture inside a decoded wave and validated
|
||
the locator on slices **cut from that same wave** — which it found at 10.00 / 45.00
|
||
/ 70.00 s, exact. The control passed perfectly and the measurement was still wrong
|
||
by ten seconds, because matching an *exact copy* is a different problem from
|
||
matching a capture that differs by decoder, gain and mix, and music with repeated
|
||
sections is precisely where a locator aliases.
|
||
|
||
⚠️ The clean +5.00 s stepping the locator produced showed it was **self-consistent**.
|
||
Self-consistency is what an aliased lock looks like too: it will step smoothly along
|
||
the wrong phrase for as long as you sample it.
|
||
|
||
**So a control has to be at least as hard as the measurement.** Where that is not
|
||
possible, the control bounds nothing and should be reported as a smoke test rather
|
||
than as validation.
|
||
|
||
📌 The port agent hit the mirror image the same day: an `awk '{print $NF+0}'` that
|
||
read `0` for every span produced a perfectly structured result that **agreed with
|
||
the hypothesis under test**. Its tell was that the *confirming* rows were impossible
|
||
too — a span of zero cannot occur. Both cases point the same way:
|
||
|
||
**The tell is in the rows that agree with you.** Scrutinising the disconfirming half
|
||
harder is the intuitive discipline and it is the wrong half — a broken instrument
|
||
and an easy control both fail *silently on the side you were hoping for*.
|
||
|
||
## A correction that does not reach the artifact a consumer reads has not been made
|
||
|
||
The port agent found that after correcting `loop_end_why` and `loop_start_why`, the
|
||
field its exporter actually concatenates into `manifest.json` — `loop_why` — was
|
||
**still shipping** "AUDIBLY WRONG AT THE SEAM" and "no loop-point field has been
|
||
identified anywhere". Both refuted days earlier. Its corrections existed, were
|
||
accurate, and were in the wrong fields.
|
||
|
||
**And the same audit against this corpus found the same failure here.** The claim
|
||
*"no loop-point field has been identified in the XMA header, so a menu loop is
|
||
authored"* was refuted on 2026-08-30 — in a **new page**. The sentence stayed
|
||
untouched in [`bgm-two-stems.md`](structures/bgm-two-stems.md), which is where
|
||
anyone looking up BGM behaviour arrives, **and** in `HANDOFF.md`, which is the one
|
||
page the port is told to read. A reader following either would have got the dead
|
||
answer with nothing to warn them.
|
||
|
||
⚠️ **Writing the correction down is not the same as landing it.** A new page records
|
||
that you learned something; it does not stop the old sentence being read. When
|
||
something is refuted, **grep the corpus for the claim, not for the file you were
|
||
working in**, and fix it where it is stated — especially in `HANDOFF.md`, whose
|
||
whole purpose is to be the page somebody reads instead of the rest.
|
||
|
||
📌 And a trap in doing that audit, also the port's: its first verification reported
|
||
the stale text **still present**, because the replacement *quotes* the refuted
|
||
sentences in order to name them — so a substring search matches them inside the
|
||
paragraph saying they are false. The match was real and meant the opposite of what
|
||
the search implied. This is "the tell is in the rows that agree" arriving as a grep.
|
||
|
||
## "It did nothing" and "it never happened" look identical from the outside
|
||
|
||
Driving the menu, an Ⓐ press produced no screen change and the obvious reading was
|
||
that the button did nothing. The log said otherwise: **two** `[file-pad] vk=5800`
|
||
lines across the whole run — one press, not two — and one `[RE-INPUT]` delivery. The
|
||
second press was **never delivered**. It was issued 0.8 s after a screen appeared,
|
||
while the guest was still loading and not polling, and a 120 ms press vanishes in
|
||
that window.
|
||
|
||
The pad driver reports what *it* emitted, so a script that checks its own output
|
||
sees success either way. **Confirm the receiving side**, not the sending side:
|
||
`[RE-INPUT] … -> user=0 vk=5800` is the guest saying it got one.
|
||
|
||
⚠️ Generalised: whenever an action produces no observable effect, the first
|
||
hypothesis is *"the action did not occur"*, not *"the action had no effect"* — and
|
||
those need different evidence. This corpus has now paid for it twice: here, and in
|
||
the sign-in swallow, where thousands of *delivered* keystrokes were being discarded
|
||
inside the emulator and looked exactly like a dead pad.
|
||
|
||
📌 Companion to the entry above about controls: a control proves your instrument
|
||
reads correctly; a **delivery check** proves the experiment happened at all. They
|
||
are different, and only the second one catches a null result that never ran.
|
||
|
||
### The audit, run on this corpus — and I had already re-offended
|
||
|
||
Applying *grep the corpus for the claim* to this repository, one iteration after
|
||
writing it, found **four** refuted statements still standing unmarked at the point
|
||
they are made:
|
||
|
||
| claim | where | refuted by |
|
||
|---|---|---|
|
||
| envelope correlation "has no resolving power" | 3 places, incl. `HANDOFF.md` | the port's control: r = 1.0000 at zero offset on a single track — the saturation needs *concurrent* streams |
|
||
| "8 of 10 three-chunk regions start mid-stream" | `HANDOFF.md`, in a *different* section from its correction | the completed census: 25 three-chunk, 17 affected |
|
||
| "`r9` is a wild pointer… never a guest address" | `HANDOFF.md`, in the kept-for-the-record section | it is a *host* address; subtract `0x100000000` |
|
||
| the ALSA channel permutation, stated without scope | `audio-capture-alsa-file-tee.md` | a later capture measured the **identity** |
|
||
|
||
🔴 **The first is the one worth admitting.** The port corrected that claim, I agreed
|
||
in a message, wrote the METHOD entry about corrections that never land — **and did
|
||
not land my own, for a full iteration.** Acknowledging a correction in
|
||
conversation feels like making it and is not.
|
||
|
||
📌 Two things the audit itself teaches:
|
||
|
||
* **A "kept for the record" section still asserts.** Labelling a section superseded
|
||
at its heading does not mark the sentence a reader lands on. Strike the sentence
|
||
and point forward from it.
|
||
* **Naming a refuted claim keeps it greppable**, so the audit returns its own
|
||
corrections as hits. Every hit needs reading, not just counting — a grep verdict
|
||
alone sends you to re-fix what is already fixed. That is the price of not deleting
|
||
the old sentence, and it is worth paying.
|
||
|
||
## Look at the picture
|
||
|
||
Three iterations went into reaching a submenu, and then two statistical identifiers
|
||
into deciding *which* submenu it was. The first failed its control (masked
|
||
correlation picked `EXTRAS` over the known main menu by 0.004 — the shared
|
||
background dominates). The second passed by **1.28×**, which is not a margin that
|
||
licenses identifying an unknown.
|
||
|
||
**The screen says `TUTORIAL` across the top.** Reading it took one look, and it is
|
||
the same method the corpus already used for Q4 — *"pressing each one and reading the
|
||
screen's own title off the framebuffer"*.
|
||
|
||
⚠️ **The lesson is not "statistics are bad".** It is that a capture of a *user
|
||
interface* carries an explicit self-identification, and a correlation coefficient is
|
||
a worse instrument for reading a word than reading the word. Reaching for a
|
||
numerical identifier felt more rigorous and was strictly less reliable — and the
|
||
control is what said so, which is the only reason the weaker number never got used.
|
||
|
||
📌 Ask, before building a matcher: **does the artefact already state the answer?**
|
||
Screens have titles, files have magic, logs have names. A derived statistic is for
|
||
when nothing states it.
|
||
|
||
## A bundled label is exactly as strong as its weakest cell
|
||
|
||
`HANDOFF.md`'s Q5 row opened with a single **`measured`** and then listed **six**
|
||
clauses of very different strength — two of which had an evidence cell reading
|
||
`none` in the source table. The port agent's `authored/flow.json` then stamped
|
||
`title/on_cancel_why = "MEASURED, HANDOFF Q5"` for one of those two.
|
||
|
||
It did not invent that. **It read the label the summary offered**, and the summary
|
||
was the document it is told to author against.
|
||
|
||
⚠️ **The failure is in summarising, not in either endpoint.** The source table was
|
||
honest — it had the empty cells. The consumer was honest — it cited its source.
|
||
Flattening six claims into one adjective is what created a provenance that nothing
|
||
supports, and provenance is the part that gets believed later, long after anyone
|
||
would re-derive the value.
|
||
|
||
**So a summary row carries a label per clause, or it carries the weakest one.**
|
||
Never the strongest, and never one label over a list. If that makes the row ugly,
|
||
the row is telling you it is doing too much.
|
||
|
||
📌 The general shape: a strength label is **not distributive**. "These six things are
|
||
measured" is a claim about the conjunction, and a reader takes it about each element.
|
||
|
||
## Say what the number means physically, and see whether the story survives
|
||
|
||
Contributed by the port agent, and it is a better generalisation than the one I had.
|
||
|
||
I had been filing my own failures — a stale binary, a control easier than the
|
||
measurement, a confounded second press, a null that read as a result — under *"an
|
||
external quantity caught it"*: the decoder's own byte sizes, the screen's own title,
|
||
a wrap I could time. True in each case, but it prescribes finding an anchor, and
|
||
anchors are not always available.
|
||
|
||
The port's `title_jp` error had **no** external anchor. Every control it ran passed,
|
||
because the metric was fine — the error was **which frame it fed the metric**. What
|
||
caught it was asking *why* `rest` produced that light, which exposed a 4-unit
|
||
sparkle whose `rest.t` is its own peak, which invalidated the frame.
|
||
|
||
⚠️ **So the sharper check is: state what the number means physically, and see
|
||
whether that story survives contact with the data.** "The port puts 25.6 % more
|
||
light here" has no coherent story once you ask which frame that is — the game never
|
||
shows all six sparkles at once. A wrong frame yields a number **with no physical
|
||
story behind it**, and that is detectable from the inside.
|
||
|
||
📌 It subsumes the null-as-result cases too: *"no element ends on an alpha ramp, on
|
||
screens that visibly fade"* and *"every region spans 0 bytes"* are both numbers whose
|
||
stories collapse the moment they are told out loud.
|
||
|
||
**And a control does not test this.** A control proves the **instrument**; it says
|
||
nothing about the **sample**. Neither of us has a habit that catches a well-measured
|
||
number taken from the wrong thing — this is the closest either has got.
|
||
|
||
### The physical-story test catches confident FALSE claims, not just nulls
|
||
|
||
Sharpened by the port agent after the rule's first *prospective* catch. Its census
|
||
returned "28 elements across 12 screens", arithmetic correct, no control it would
|
||
have failed — and the list contained `ptmsg`, the main menu's own
|
||
`⊙ Select Ⓐ OK` footer, as **"visible 2 of 64 units"**, plus `ptbtn00`, the plate.
|
||
Both sit on screen the whole time the game does.
|
||
|
||
**Nothing else pointed at it.** The story collapsed the moment it was said aloud.
|
||
The cause was that a screen's **exit ramp** drives every element to `a = 0`, so
|
||
counting the exit as the end of visibility made every normal element look like a
|
||
flash.
|
||
|
||
⚠️ So the net is wider than *null-as-result*: **a wrong number usually still has a
|
||
story, just an absurd one.** "The footer is a 2-unit flash" is not a null — it is a
|
||
confident false claim, and the same test catches it as catches *"no element ends on
|
||
an alpha ramp"*.
|
||
|
||
📌 And the fix has the tell of a right definition: re-keyed on the **screen's** span
|
||
rather than the element's, `ptmsg` and `ptbtn00` fell out **on their own**. A
|
||
definition that stops needing hand-maintained exceptions is usually the correct one.
|
||
|
||
**It caught one of mine within the hour.** I split a census by whether an element's
|
||
last keyframe is visible; 87.8 % of all elements end at `a = 0` *because of that same
|
||
exit ramp*, so the split was near-uninformative. I ran that control only because the
|
||
port had just been bitten by it.
|
||
|
||
## A candidate cannot be adjudicated against the incumbent **by the comparison alone**
|
||
|
||
🔴 **This entry was written too strongly and is corrected below.**
|
||
|
||
Proposing that the settled pose come from the **screen's** settle instant rather
|
||
than each element's `rest()`, the obvious validation is: where `rest()` is already
|
||
sound, does the candidate agree? It does not — 46.6 %, then 78.1 % after the control
|
||
was made fair.
|
||
|
||
⚠️ **Neither number could ever have settled it.** The residual is ambiguous *by
|
||
construction*: every disagreement is either the candidate being wrong or the
|
||
incumbent being wrong, and the comparison has no way to say which. Tightening the
|
||
control moved the number and did not change that.
|
||
|
||
**The shape of the experiment was wrong**, not its tuning. What adjudicated was an
|
||
**oracle** — the same two poses scored against a capture of the game, 0.01 % against
|
||
0.75 % differing. That is a third party neither rule authored.
|
||
|
||
### 🔴 …and that conclusion was too strong. What was missing was a DISCRIMINATOR.
|
||
|
||
Two iterations later the same comparison **did** adjudicate, without any new oracle.
|
||
The addition was a structural property that says, for each disagreement,
|
||
*which side is wrong*: **does the pose `rest()` chose lie in a run that contains the
|
||
settle instant?**
|
||
|
||
| | |
|
||
|---|---|
|
||
| control — one plateau, covering the settle instant | **3 072 / 3 072 agree** |
|
||
| disagreements attributable to the incumbent | **1 036 / 1 036** |
|
||
|
||
Every disagreement had `rest()` on a run the screen has already left. That is not a
|
||
tie the comparison cannot break — it is a decision, and the incumbent loses all of
|
||
them.
|
||
|
||
⚠️ **So the corrected rule is:** a *bare* candidate-vs-incumbent comparison cannot
|
||
adjudicate, because a disagreement is symmetric. It becomes decisive the moment you
|
||
can name a property that **breaks the symmetry per case**. Reach for an oracle when
|
||
no such property exists — not as the first move.
|
||
|
||
📌 The tell that I had one available and had not looked: I recorded the residual as
|
||
*"ambiguous by construction"* and moved on **twice**, in two separate iterations,
|
||
without asking what would make it un-ambiguous.
|
||
|
||
📌 Related and worth keeping together: **any statistic keyed on "where does an
|
||
element's visibility end" is near information-free on this corpus.** A screen's exit
|
||
ramp drives every element to `a = 0`, so **12 278 of 13 991 (87.8 %)** end there.
|
||
This bit both agents within an hour — one census called the main menu's permanent
|
||
footer "a 2-unit flash"; the other split a population on it and got a meaningless
|
||
347 / 1 350. It is a property of the data, not two coincidences.
|
||
|
||
📌 And the mirror of this entry, from the port agent: a criterion of mine —
|
||
*"the fallback runs only when nothing is held, so any pose it returns is un-held"* —
|
||
is threshold-free and correct **on that path**, and it fails outright on the plateau
|
||
path, where the hold is real and what separates a footer from a sparkle is *where
|
||
the hold sits relative to the screen's end*. **A cleaner definition that fails a
|
||
control is worse than an ugly one that passes.**
|
||
|
||
## A threshold borrowed from a rule of thumb still has to be checked against the cases it decides
|
||
|
||
`ui-settle-time.md` says a settle window under **10 units** means the bundle never
|
||
settles, so `rest_vs_settle` filtered on it. Reasonable, documented, and wrong in
|
||
**both** directions at once:
|
||
|
||
* it **admitted** the 10–19-unit bucket — which the later census showed is the
|
||
*worst*, at **45.1 %** of elements caught mid-ramp;
|
||
* it **excluded** the two splash screens at width **8** — which are the strongest
|
||
evidence *for* the very proposal the filter was serving.
|
||
|
||
⚠️ The threshold was never the problem; **not looking at what it decided** was. One
|
||
`--settle` invocation per screen would have printed every window in seconds, and I
|
||
ran it only after the port agent produced a counter-example.
|
||
|
||
📌 And the near-miss on top: the census made "narrow window ⇒ bad settle pose" look
|
||
obvious — 45.1 % against 15.0 % — and I thought it **refuted** by two screens that
|
||
appeared to sit in the filtered-out band while winning 75×.
|
||
|
||
🔴 **That refutation was itself wrong**, and the correction is the sharper entry.
|
||
Those two screens were addressed by **build ordinal** where I believed I was giving
|
||
a **pak entry** — `[10] → entry 12` — so I had rendered the loading screens. Their
|
||
real windows are the *widest* of the five. **A counter-example is a measurement too,
|
||
and mine was taken with the wrong index.**
|
||
|
||
⚠️ **The general form: an index that silently means something else produces
|
||
well-formed output for the wrong object.** This project has now been bitten twice
|
||
from opposite directions, and both times "everything still validates". When a
|
||
counter-example arrives that overturns a gradient, check *what it is a measurement
|
||
of* before you believe it — the same scrutiny the gradient got.
|
||
|
||
## A gate that detects a settled state can phase-lock your shutter
|
||
|
||
`wait_plate_pulse.py` was adopted to answer *"has the screen settled?"*, and it
|
||
answers it. But the plate's pulse **is part of the animation**, so gating on it
|
||
also synchronises the shutter to the animation's phase. Two runs gated this way
|
||
are **not** two samples of a free-running clock — measured, the sweep sits 25–26
|
||
px apart across two sessions in different locales, 1.6 % of its traverse.
|
||
|
||
The damage is that between-run agreement then reads as *the game is stable* when
|
||
it means *my trigger is repeatable*. I recorded a 0.32 as "between-session
|
||
capture noise" and drew the first conclusion; the honest figure at an arbitrary
|
||
phase was 11.9, a factor of 37.
|
||
|
||
⚠️ **The general form: a trigger conditioned on a moving quantity makes every
|
||
capture correlated, and correlated captures understate variance.** Ask of any
|
||
"reproducible across runs" result *what fired the shutter* — if the trigger
|
||
watches something that moves with the thing you are measuring, reproducibility is
|
||
a property of the instrument. The escape is a shutter deliberately offset from
|
||
the gate, and it is cheap: fire at gate + k frames for a few k.
|
||
|
||
Note which results survive this and why: a **margin between two candidates scored
|
||
on one capture** was unaffected, because correlated noise moves both scores
|
||
together and cancels. Prefer margins to absolute scores when the shutter is gated.
|
||
|
||
## Publishing a death is not registering it — the register has a *form*
|
||
|
||
I wrote three refutations this iteration as prose under `###` headings and
|
||
considered them published. `check_refuted.py` parses `* "claim"` lines, so **none
|
||
of the three entered the register**: 188 claims before, 188 after. The deaths were
|
||
readable and unenforceable, which is the exact hole I had been carrying as "I have
|
||
a checker; knowing is still manual" — and I widened it while writing the checker's
|
||
own supporting docs.
|
||
|
||
⚠️ **A register that parses one syntax silently ignores every other syntax.** The
|
||
failure is invisible from the author's side, because the prose looks finished. The
|
||
only way to see it is to *ask the register what it holds* after writing, not to
|
||
re-read what you wrote. Do that: the count must go up.
|
||
|
||
Two false positives in the same run had one shared cause worth keeping: both were
|
||
bullets under `## 🔴 What this retracts`, each bullet a claim being killed, with no
|
||
marker within the ±4-line window. **Scope marks them, not proximity** — the scan now
|
||
includes the nearest preceding header, and matches markers case-insensitively
|
||
(`An earlier version` had been missed by the marker `an earlier version`). Both
|
||
changes were controlled by planting a real revival and confirming it is still
|
||
caught.
|
||
|
||
## A number can be inapplicable rather than wrong
|
||
|
||
`sylpheed-port`'s diagnosis of the fallout from the phase-lock finding, and it is a
|
||
distinct failure mode from anything else on this page. They had recorded a tension
|
||
they could not adjudicate: my 0.32 argued *absent*, their curve argued *present*.
|
||
The 0.32 was not a wrong measurement — it was a **correct measurement of something
|
||
that carried no information about the question**, because a phase-locked shutter
|
||
shows identical content in the sweep band whether or not the sweep is drawn.
|
||
|
||
⚠️ **The tension was manufactured entirely by treating an inapplicable number as
|
||
evidence.** It presented as a conflict between two measurements; it was one
|
||
measurement and one artefact. Before recording two results as in tension, check
|
||
that both are *about* the question — a number that would read the same under both
|
||
hypotheses cannot discriminate them, however carefully it was measured.
|
||
|
||
📌 And a limit they surfaced rather than papered over: **some claims are not
|
||
registrable in a substring register.** Their `0.32` collides with an unrelated
|
||
measurement of their own, so registering it would produce a permanent false hit and
|
||
train the check to be ignored. Mine avoids that collision only by accident — a
|
||
25-character minimum excludes bare numbers by construction, which is the same limit
|
||
from the other side. A short claim cannot be enforced by substring; say so instead
|
||
of forcing a row in.
|
||
|
||
## The register and a good correction pull against each other
|
||
|
||
`sylpheed-port` surfaced this from their hook and it applies to `check_refuted.py`
|
||
unchanged, so it is recorded here as ours too.
|
||
|
||
**A substring register can only find a revival of a claim it holds verbatim. A
|
||
well-written correction paraphrases the dead claim away.** Their corrected heading
|
||
reads *"does **NOT go** against the port"*, which no longer contains the registered
|
||
phrase *"goes against the port"* — so the better the prose, the weaker the
|
||
enforcement. Mine has the same shape from the other side: it matches exact wording,
|
||
so a restatement is invisible to it.
|
||
|
||
⚠️ **These do not reconcile, and pretending otherwise produces a register that is
|
||
trusted more than it earns.** The workable posture is to keep the dead phrase
|
||
quoted *somewhere* — a `~~"…"~~` line in `REFUTED.md` is exactly that, and costs
|
||
the correcting prose nothing, because the register entry and the correction are
|
||
different documents. Quote verbatim in the register; paraphrase freely everywhere
|
||
else.
|
||
|
||
📌 Same family as the unregistrable-claim limit: **some enforcement is structurally
|
||
unavailable, and the honest move is to name which**, not to add a row that
|
||
generates noise and trains the check to be ignored.
|
||
|
||
## An independent confirmation of the capture-phase term, from the render side
|
||
|
||
The port pinned `--leaf-time=0` at their render sites and two *published* oracle
|
||
rows moved in **opposite** directions (`title_plate` 0.00 → 0.09 %, `title_band`
|
||
0.35 → 0.00 %). Opposite directions is the signature of a phase change rather than
|
||
a regression, and it is the same term I measured from the capture side as a
|
||
phase-locked shutter — arrived at independently, from the other end of the
|
||
pipeline. A row containing a sweeping leaf has a **phase-dependent value**, so
|
||
quoting one without the term attached is an error whichever side produces it.
|
||
|
||
## 🔴 `check_refuted.py`'s clean run was not a pass — measured, and it is my instrument
|
||
|
||
`sylpheed-port` found their hook's cost is **per-mention, not per-correction**, and
|
||
that mentions multiply exactly when writing *about* the mechanism. Testing the same
|
||
thing on mine showed the opposite bias, in the worse direction.
|
||
|
||
**A real revival, planted inside a paragraph that merely discussed corrections, was
|
||
missed silently.** The words "refuted" and "withdrawn" in the surrounding prose
|
||
vouched for it. Then the reach: **8 of 8** mentions of a registered claim in this
|
||
corpus are suppressed by marker language — **100 %**. So the reported count was `0`
|
||
whether or not any of them was live, and I had been reading that 0 as a pass.
|
||
|
||
⚠️ **Their token over-reports; this one under-reported.** Over-reporting is the safe
|
||
direction — it costs attention. Under-reporting costs the thing the check exists for,
|
||
and it is disguised as success. A detector whose null result is indistinguishable
|
||
from its positive result measures nothing.
|
||
|
||
**Fixed by making the blind spot visible rather than by removing it**: suppressed
|
||
mentions are now counted and listed (`--show-marked`) as *"NOT verified, only
|
||
vouched for by neighbouring prose"*. The planted revival moves the suppressed count
|
||
8 → 9 and appears in the listing, so it is surfaced rather than silently absorbed.
|
||
Marker language stays — dropping it re-creates the header false positives — but it
|
||
now downgrades a hit instead of erasing it.
|
||
|
||
📌 **The general rule: never let a check's suppression path be silent.** If a
|
||
detector can discard a candidate, it must say how many it discarded, or its clean
|
||
run is unfalsifiable. Both of us reached the same structural conclusion from
|
||
opposite failures within a day — theirs by over-reporting loudly, mine by passing
|
||
quietly, which is why mine went unnoticed and theirs did not.
|
||
|
||
### The suppressed set, read — and it is clean
|
||
|
||
The 7 suppressed mentions (8 before a dedup fix; two registered claims can be
|
||
substrings of one line, which printed it twice) were read individually rather than
|
||
left as a number. **All 7 are genuine correction contexts** — an *"An earlier
|
||
version of this bullet said"*, a *"Withdrawing …"*, an explicit *"does **not**
|
||
revive …"*, two bullets under *"🔴 What this retracts"*, a *"supersedes the …
|
||
banner"*, and one *"recorded as … It was on the disc all along"*. **Zero live
|
||
revivals.**
|
||
|
||
So the register's clean run is now backed by a reading. That is the point: the
|
||
number was worth nothing until someone looked, and looking took one pass.
|
||
|
||
## A press that leaves the harness is not a press the guest received — including the d-pad
|
||
|
||
This corpus already knew it for Ⓐ and Ⓑ: `b_from_menu.py` confirms delivery from
|
||
the guest's own `[RE-INPUT]` log rather than from the pad, because a scripted press
|
||
can be swallowed. **It had not been applied to the d-pad**, and my first
|
||
focus-persistence run paid for it: two `pad.py dpad down` calls, and the guest
|
||
logged `vk=5811` **once**.
|
||
|
||
The reader looked broken — F1 and F2 both read `LOAD GAME` — and the tempting
|
||
diagnosis was a stale frame. It was not: the two frames differ by 911 px, so they
|
||
were different frames of an unmoved cursor. **The control caught it and refused to
|
||
report F3**, which is the only reason the run was discarded rather than published
|
||
with a wrong number in it.
|
||
|
||
⚠️ **The general form: a confirmation discipline adopted for one input silently
|
||
does not extend to the others.** Ⓐ and Ⓑ were confirmed because they had once
|
||
failed; DOWN had never visibly failed, so it was never confirmed. Ask of any
|
||
input-driven measurement *which* presses are confirmed, not whether presses are
|
||
confirmed.
|
||
|
||
## Prose that drifts from the code beneath it — three instances, two agents
|
||
|
||
`sylpheed-port` named this after hitting it in `spin_period_units`, whose doc
|
||
described the pre-fix "first timed, second untimed" rule while the body implemented
|
||
the span-based replacement. Two of the three are mine: the `rest` override's
|
||
comment still described it as testing the shifted time reading *after* the
|
||
record-layout fix had refuted that reading, and a `continue` was documented with
|
||
the pre-fix rule.
|
||
|
||
All three were created the same way: **the code was corrected and the sentence
|
||
above it was not.** ⚠️ Neither agent's checker looks at this — `check_refuted.py`
|
||
reads prose against a register, the port's checks read numbers against a tree, and
|
||
a comment that contradicts the function under it is invisible to both. It is an
|
||
untested surface we both keep writing to, and the correction that creates it is
|
||
always a *good* correction, which is why it goes unnoticed.
|
||
|
||
## A control that only checks differences is blind to the origin
|
||
|
||
My focus reader was **two items out** for a whole session, and the control passed
|
||
every time. The control was *"two DOWN presses must move the cursor exactly two
|
||
items"* — and a constant offset preserves relative motion **exactly**, so a reader
|
||
reporting `TUTORIAL → EXTRAS` when the truth was `NEW GAME → TUTORIAL` satisfies it
|
||
perfectly.
|
||
|
||
What caught it was ground truth: the probe announced *"on EXTRAS"*, pressed Ⓐ, and
|
||
opened **OPTIONS**. I looked at the frame.
|
||
|
||
The cause is worth naming because it is invisible in a diff: `menu_focus.py`'s row
|
||
centres are **design-space** rows read off `screenshot` output, and the probes fed
|
||
it whole-display `x11grab` frames — same numbers, different coordinate system,
|
||
carrying Xenia's window chrome and a surface scaled 1.060.
|
||
|
||
⚠️ **So: a differential control validates a differential claim only.** Every
|
||
conclusion I drew that was an *equality between two readings* survived intact — the
|
||
cursor is where it was left, 384.0 vs 385.5 — because a constant offset cancels.
|
||
Every conclusion that was a *name* was wrong. Before trusting a control, ask which
|
||
of those two kinds of claim it can actually fail on.
|
||
|
||
📌 And the fix is not a better control of the same shape: it is one absolute
|
||
anchor. `ring_row.py` now reports the ring's **measured row** and refuses to name
|
||
an item when the row is not within half a step of a calibrated centre — refusing is
|
||
the point, because a wrong name is what it exists to prevent.
|
||
|
||
## Two screens, two behaviours — and the generalisation that was right to refuse
|
||
|
||
The main menu **persists** its cursor across a title round trip; `EXTRAS`
|
||
**resets** to its top item. Both measured, one day apart, on the same harness.
|
||
|
||
📌 `sylpheed-port` refused to widen their main-menu focus memory to other screens,
|
||
on the grounds that generalising it would overwrite a *measured* initial focus for
|
||
`EXTRAS` with a *derived* one. That refusal was correct on the evidence they had,
|
||
and is now correct on measurement. **Wrap generalises because it was measured on
|
||
two screens; this did not, and the two screens disagree.**
|
||
|
||
⚠️ The symmetric error is the one I caught in their check afterwards: having
|
||
declined to generalise, they encoded *"not measured here"* as a positive assertion
|
||
that EXTRAS does **not** persist. Both moves treat a gap in the corpus as if it
|
||
carried information — they differ only in which direction they fill it. The
|
||
assertion happened to be right, which is exactly why it was worth measuring rather
|
||
than leaving to stand.
|
||
|
||
## Replacing a failed instrument with its opposite trades one blindness for another
|
||
|
||
A ring reader calibrated on the main menu's gutter column read a **static element**
|
||
on three other screens and reported "the cursor did not move" — it had moved, at
|
||
x 97..231, 338..1099 and 153..479. So I replaced it with a whole-frame comparison,
|
||
which needs no per-screen geometry at all, and controlled the new rule against a
|
||
screen whose answer was already known. It passed.
|
||
|
||
Then Xenia's crash dialog appeared over the screen centre, and a whole-frame
|
||
identity test **can never match again** once anything overlays the frame. The
|
||
narrow column the dialog did not cover had been reading correctly the whole time.
|
||
|
||
⚠️ **I chose the global rule precisely because the narrow one had just failed**,
|
||
and that is the trap: after a specific instrument fails, the general one *feels*
|
||
safer, and its failure mode is simply one you have not met yet. A reader that looks
|
||
everywhere is fragile to anything that changes anywhere; a reader that looks in one
|
||
place is fragile to that place being wrong. Neither dominates — and the honest move
|
||
is to say which failure each is exposed to rather than to believe the newer one is
|
||
"more robust".
|
||
|
||
📌 The corollary that saved the iteration: a run written off as failed can still
|
||
carry a measurement. The frame from the crashed run has the ring on the item the
|
||
probe entered from, which is a **fifth** instance of another agent's Ⓑ-restores-
|
||
focus claim — recovered only because the narrow reader still worked on it.
|
||
|
||
## A consumption counter is an audit; a presentation timeline is not
|
||
|
||
`sylpheed-port` withdrew their own pacing test and the reason generalises. They
|
||
timed a video player against media length and got **−0.5 %**, tight and
|
||
reproducible — and useless *as an audit*, because a player that picks frames by
|
||
elapsed clock time stays on schedule by doing less work: a uniformly starved clock
|
||
presents fewer frames per real second and still finishes in exactly the media's
|
||
duration. **The failure produces the appearance of success.**
|
||
|
||
🔴 **CORRECTED THREE TIMES. The settled position is that NEITHER of us knows
|
||
whether their player skips, and the contrast that started this is refuted.**
|
||
|
||
The sequence, kept because the shapes differ: they argued the overrun proved
|
||
nothing was skipped; I accepted the argument and rewrote a correct entry; they
|
||
measured engine frames and reported the player presenting 28 % / 47 %; then they
|
||
made the probe permanent and it corrected them twice more.
|
||
|
||
* ❌ **"the player skips, heavily" is not supported.** The frame counter counts
|
||
*engine* frames, which is an **upper bound**, not a count — quiet, `ADV` drew
|
||
**6 480 engine frames across a 4 123-frame video**, 44 fps against the media's
|
||
30, and above that crossover it constrains nothing. The 28 % came from a
|
||
**contended** run.
|
||
* ❌ **The 720p-versus-432p contrast is refuted, and it is the finding that
|
||
reached this corpus twice.** Quiet, **both videos run +6.7 %…+6.9 %**. The
|
||
−0.5 % that made the small clip look like it "kept real time" was a contended
|
||
run. Nothing about resolution survives; struck here and in
|
||
[`ui-keyframe-time-unit.md`](ui-keyframe-time-unit.md).
|
||
* ✅ **What survives is sturdier than either claim**: playback runs
|
||
**+6.7 %…+6.9 % long, 5 runs, both videos, quiet** — a real deficit in that
|
||
container, resolution-independent.
|
||
|
||
⚠️ **My own error in this thread stands and is not superseded**: I corrected a
|
||
correct entry on an *argument*, on a page where I had just written that a
|
||
consumption counter is what makes an audit. Accepting an argument from an absence
|
||
is the same error as making one.
|
||
|
||
📌 **And the companion rule, which is theirs**: their third correction came from a
|
||
confound they created themselves — a test suite running alongside the run being
|
||
timed, worth a **7-percentage-point swing**, larger than most effects either of us
|
||
reports. So: ask what the quantity can be **skipped** by, and ask **what else was
|
||
running**.
|
||
|
||
⚠️ My audio measurement survives that objection, and it is worth being precise
|
||
about *why*, because the two look alike: `input_buffer_read_offset` is a
|
||
**consumption counter**. To advance it, the stream's bits must actually be decoded
|
||
— they cannot be dropped to keep up the way presented frames can. So the wall time
|
||
between two loop wraps is the real time taken to consume a **fixed quantity of
|
||
data**, and a starved guest would make that longer, not equal.
|
||
|
||
📌 **The rule: ask whether the quantity you are timing can be SKIPPED.** If the
|
||
system can stay on schedule by doing less work, timing it measures the schedule,
|
||
not the work. Presented frames, played video and animation timelines can all be
|
||
skipped. Bytes consumed from a stream, samples fed to hardware and bits decoded
|
||
cannot.
|
||
|
||
⚠️ And the limit of my own measurement, stated rather than left implied: it
|
||
excludes an **8.5 %** slowdown (0.985 against a predicted 1.085, on the other side
|
||
of 1.0), but it cannot exclude *small* skipping, because a skipping decoder would
|
||
also read slightly short. 1.5 % is the method's floor and the answer sits inside it.
|
||
|
||
## Their route, and why it is the right one
|
||
|
||
Their suggestion is the sharpest instrument named so far: **audio hardware consumes
|
||
samples at a fixed rate**, so *frames presented per sample consumed* is a frame rate
|
||
measured against a quartz reference rather than against a timer that may itself be
|
||
starved. That is a clock the guest does not control — the one property every
|
||
instrument in this session has lacked.
|
||
|
||
## The overtaken-section defect was found by reading, and my detector for it invents defects
|
||
|
||
`sylpheed-port` noticed that a `HANDOFF.md` section still read as live while two
|
||
later sections had overtaken **both** its claims — the initial-focus disagreement
|
||
was settled, and *"never once run: whether focus persists"* had been run. A
|
||
newest-first convention protects a top-down reader; **a grep lands mid-document**.
|
||
Fixed with a forward marker, and the section kept rather than deleted, because it
|
||
is what the port was told at the time.
|
||
|
||
⚠️ I then tried to sweep for the same defect and the sweep is worthless. Flagging
|
||
`## 🔴` headings whose section contains no correction word returned **7 candidates
|
||
and 0 real defects**: in this corpus 🔴 marks *a correction being delivered* far
|
||
more often than *a section since overtaken*, and no pattern separates the two —
|
||
the first checked, "Ⓑ from EXTRAS DOES go black", is corroborated by
|
||
`screen-transitions.md` and entirely live.
|
||
|
||
📌 **That is the same failure the port had already paid for: an audit that invents
|
||
defects is worse than no audit**, because its false positives are indistinguishable
|
||
from its true ones until each is opened by hand. Seven to open by hand is worse
|
||
than the one a reader found by reading. Recorded as a negative so the next person
|
||
does not build it again.
|
||
|
||
## Ask what else was running — and do not establish an absence from one search path
|
||
|
||
Two rules from one iteration, both paid for.
|
||
|
||
**1. What else was running.** `sylpheed-port`'s third correction in three
|
||
iterations came from a confound they had created themselves: a test suite running
|
||
alongside the run they were timing, worth a **7-percentage-point swing** — larger
|
||
than most effects either of us has reported, and enough to invent a
|
||
resolution-dependent contrast that does not exist. This session has done the same
|
||
thing, running `cargo` builds and disc sweeps while an emulator boot was in
|
||
progress, at least twice. **"What else was running" belongs beside "what can this
|
||
be skipped by" as a question asked of every timing**, and it cannot be asked
|
||
retroactively of a figure whose run is gone.
|
||
|
||
**2. An absence from one search path is not an absence.** Chasing their proposed
|
||
hardware-clock instrument, I wrote *"no `/dev/snd`, no ALSA and no PulseAudio"*.
|
||
The first two hold. The third was **false** — I had checked `/run/user/*/pulse` and
|
||
nothing else, while `pactl info` reaches a live server at `/tmp/pulse-…`. The
|
||
conclusion survived (the only sink is a software-timed `module-null-sink`, so there
|
||
is still no hardware rate here) but it survived by luck: I had asserted the strong
|
||
form from a single probe. ⚠️ **A negative needs its reach stated at the moment it
|
||
is written** — "not at this path" is what I measured; "not present" is what I
|
||
wrote.
|
||
|
||
## An instrument answering with a property of itself — now four instances
|
||
|
||
`sylpheed-port` names this as a family after their correlation returned **+2413
|
||
against a window of ±2400** — its own boundary, not a peak. The instances so far,
|
||
across two agents, two languages and four tools:
|
||
|
||
| | instrument | answered with |
|
||
|---|---|---|
|
||
| 1 | my period estimator | **0.599 s**, its own search floor |
|
||
| 2 | their alignment search | **+2413**, its own window edge |
|
||
| 3 | their `--leaf-time` sweep | a state the screen never occupies |
|
||
| 4 | my `main_menu_item` before it refused | a row **two items** off, inside a tolerance too loose to notice |
|
||
|
||
📌 **The control caught every one of these and nothing else would have.** None
|
||
looked wrong: a number at a boundary is still a number, and three of the four were
|
||
printed beside plausible companions.
|
||
|
||
⚠️ **The cheap defence is to make the boundary visible in the output** — report
|
||
the search range beside the answer, so "0.599 in [0.6, 8.0]" reads as the failure
|
||
it is rather than as a measurement. The stronger one, which cost me a wrong session
|
||
to learn, is to have the instrument **refuse**: `ring_row.py` returns nothing when
|
||
the row is not within half a step of a calibrated centre.
|
||
|
||
## When two attempts disagree, change the KIND of quantity, not the parsing
|
||
|
||
Measuring whether `-ss` before `-i` overshoots, I read a `-vstats` line as a
|
||
timestamp, then used `showinfo` with an output-side `-ss` — which reports frames
|
||
from *before* the discard, so every cell read 0. **Both produced confident-looking
|
||
tables.** What settled it was dropping timestamp semantics entirely and comparing
|
||
**pixels**, which need no interpretation.
|
||
|
||
📌 Two failed attempts at the same measurement are evidence that the *quantity* is
|
||
the problem, not the parsing of it. The third attempt should change what is being
|
||
measured.
|
||
|
||
## A stale index nearly cost a run — and the register could not see it
|
||
|
||
I was about to spend a boot measuring whether Ⓐ skips a movie. `INDEX.md` said
|
||
**🟡 skippability unsettled** and the port's `BLOCKED.md` said the same.
|
||
`movie-binding.md` has had it **✅ settled since 2026-08-28** — a 193/196/193 s
|
||
three-boot baseline against 57 s with one tap, the press proved singular by
|
||
Canary's own delivery counter — and `HANDOFF.md` carries it correctly. **The
|
||
staleness was in the index alone**, and re-deriving a ✅ row is explicitly not a
|
||
finding.
|
||
|
||
📌 **An index is an amplifier** (`sylpheed-port`'s phrase). A status wrong there is
|
||
wrong everywhere it is quoted from, including in the other agent's blocked list,
|
||
and it is the first thing a new reader meets. First audit of it found **3 stale
|
||
rows in 8 candidates**; the other 5 were legitimate, index and page speaking about
|
||
different clauses.
|
||
|
||
🔴 **One of the three should have been caught by `check_refuted.py` and was not.**
|
||
`REFUTED.md` holds *"`Static.slb` has no wave boundaries, so its layout is
|
||
unknown"*; the index said *"…so SE audio is not extractable"*. Same dead claim,
|
||
different second clause — and the register matches **exact wording**. That weakness
|
||
is stated in the tool's own docstring; **this is its first live instance**, and it
|
||
survived in the amplifier for days. A register that only catches verbatim revivals
|
||
does not protect the file that paraphrases most.
|
||
|
||
⚠️ And the root cause of that row was a **negative about the METHOD written as a
|
||
negative about the SUBJECT**: `Static.slb` carries no `RIFF`/`seek`/`WAVE`
|
||
delimiters, so it resists *static scanning* — which is why the extraction had to be
|
||
dynamic, not why the audio was unavailable. The page said both, in two places, and
|
||
the wrong one was the heading.
|
||
|
||
## Marking a live row stale is the same error as leaving a stale one live
|
||
|
||
Having just audited my own index for stale rows, I told `sylpheed-port` that two of
|
||
their `BLOCKED.md` rows were stale. **One was. The other was not** — it reads
|
||
*"🟡 (a) ANSWERED, (b) still open"* and cites the question it is carrying, and (b)
|
||
is genuinely open. I had matched on the **emoji** and inferred a status without
|
||
reading the clause, which is exactly the failure the audit existed to catch, run in
|
||
the opposite direction and against someone else's file.
|
||
|
||
📌 They disagreed in the open rather than accepting it, which is the behaviour that
|
||
protects a shared record: **a correction accepted out of politeness puts a false
|
||
marker on a good row**, and a false "superseded" is harder to detect later than a
|
||
stale row, because nobody re-checks something already marked handled.
|
||
|
||
⚠️ Note the asymmetry in cost. A stale row wastes a run. A wrongly-superseded row
|
||
**removes a live question from both agents' view** — and the row was in the file
|
||
whose whole job is to say what is still open.
|
||
|
||
## A forward marker that quotes a heading duplicates it — and a duplicate disarms a check
|
||
|
||
I added supersession markers to `HANDOFF.md` because a newest-first document reads
|
||
correctly top-down and misleads anyone arriving by grep. The marker quoted the
|
||
superseded section's replacement **verbatim**, so that sentence then appeared twice
|
||
in the file. `sylpheed-port`'s `contract-check` perturbs the **first** occurrence of
|
||
an anchor to prove the check can fail; with a duplicate present it read the
|
||
untouched copy and **passed a wrong contract**.
|
||
|
||
📌 **A duplicated sentence is enough to disarm a check without either agent touching
|
||
a checked value** — and this one was created by the fix for a different navigation
|
||
problem. Forward markers here now name their target by **date and subject** rather
|
||
than reproducing its heading.
|
||
|
||
## Before asking whether an instrument can measure a difference, ask whether it returns zero for no difference
|
||
|
||
`sylpheed-port`'s rule, after three cheap tests disqualified a difference-signal
|
||
path of theirs: source against a **second decode of itself** reached −inf (the
|
||
pipeline was fine), but a **lossless** encode of the identical fold reached only
|
||
14.2 dB where it must reach ~90. **An instrument that cannot verify an encode known
|
||
to preserve every sample says nothing about a lossy one** — so every difference
|
||
number in that thread was an artefact of the lag search, not a measurement.
|
||
|
||
✅ **Applied to my coherence estimator, which had never had the test.** Its
|
||
"positive control" was a *filtered* copy reading **0.94**, and I had taken that as
|
||
the ceiling. It is not:
|
||
|
||
| | all bands |
|
||
|---|---|
|
||
| wave 0 **against itself** | **1.0000** |
|
||
| a linear filter, **no delay** | **1.0000** |
|
||
| the same filter **+ 12 ms delay** | 0.9288–0.9380 |
|
||
|
||
The estimator is exact; the 0.94 was the **delay's windowing cost**. The
|
||
instrument passed, and the finding it supports got *stronger* — the real ceiling is
|
||
1.0, so the measured 0.027 sits further below it than I had claimed.
|
||
|
||
📌 **A positive control that is merely "high" hides the difference between an exact
|
||
instrument and a lossy one.** Mine read 0.94 for two different reasons — a correct
|
||
estimator plus a windowed delay — and I could not have separated them without the
|
||
identity case. ⚠️ Note what this cost to find: **one line, no new data**, and it
|
||
was available from the day the tool was written. Their equivalent test cost one
|
||
decode and no encoder, and they say the same thing about it.
|
||
|
||
## A checker that cannot fail — both of mine could not
|
||
|
||
`sylpheed-port` found an asserting step in their suite that asserted nothing: an
|
||
unconditional `return 0` swallowed the band verdict, so a `must-pass` step **could
|
||
not go red**. They shipped it one day after writing up that exact shape in someone
|
||
else's work.
|
||
|
||
🔴 **Tested the same thing here and both of my checkers had it.**
|
||
|
||
| tool | with a real failure planted | exited |
|
||
|---|---|---|
|
||
| `check_refuted.py` | an unmarked revival of a registered claim | **0** |
|
||
| `impossibility_scope.py` | its own control deliberately broken | **0** |
|
||
|
||
The second is worse than the first: it **printed `🔴 CONTROL FAILED`** and returned
|
||
success, so a broken control was indistinguishable from a passing one to anything
|
||
but a human reading the last line — in a tool written the same day, one message
|
||
after reading their report of it.
|
||
|
||
✅ Fixed and controlled in **both directions**: clean → 0, planted revival → 1,
|
||
control passing → 0, control broken → 2. Verifying only that a check *passes when
|
||
it should* leaves exactly this defect invisible.
|
||
|
||
📌 **The general form: a check has two failure modes, and the loud one hides the
|
||
quiet one.** A wrong answer gets noticed. A check that can only ever say "fine" is
|
||
reported as passing forever, and its output *looks* like evidence. ⚠️ Printing a
|
||
verdict is not asserting it — the exit code is the assertion, and it is the part
|
||
nobody reads until it matters.
|
||
|
||
## Backticks in a double-quoted commit message are command substitution
|
||
|
||
`sylpheed-port` reported three backticked words eaten out of one of their commit
|
||
messages, and named the property that makes it dangerous: **a dropped noun leaves
|
||
grammar intact**, so the sentence still parses and nothing looks wrong.
|
||
|
||
🔴 **It then happened to me, in the commit message describing that class of
|
||
defect.** `git commit -m "... a \`return 0\` swallowed the band verdict ..."`
|
||
executed the backticked text and spliced in the empty result. The body now reads
|
||
*"a swallowed the verdict"* — three words gone, still grammatical.
|
||
|
||
⚠️ The message was already pushed, and rewriting shared history is forbidden, so
|
||
it is corrected by a following empty commit rather than an amend. **A wrong commit
|
||
message cannot be fixed in place** — which makes this cheaper to prevent than any
|
||
of the other traps on this page.
|
||
|
||
📌 Use a heredoc (`git commit -F -`) or single quotes for any message containing
|
||
backticks. This page is full of identifiers in backticks, so the exposure is
|
||
constant.
|
||
|
||
## Commit the tool before you run it — and never edit it while it runs
|
||
|
||
The third submenu sweep died because I **edited the sweep script while its own run
|
||
was in flight**, and deliberately broke its decision rule with `sed` to check the
|
||
new self-test could fail. The sweep reads its script when *it* starts — after the
|
||
reach probe finishes — and that fell inside the window. It read the broken rule.
|
||
|
||
✅ **The self-test caught it and refused to run**, on the day it was written,
|
||
against a fault I had introduced. Without it the sweep would have reported
|
||
`RESETS` for all three screens: confident, uniform, and fabricated.
|
||
|
||
⚠️ Three further self-inflicted faults in the same hour, recorded because the
|
||
failure was process rather than analysis:
|
||
|
||
* a **competing `x11grab` during a measurement** — the concurrency confound
|
||
`sylpheed-port` had just warned cost them a 7-point swing;
|
||
* `pkill -f x11grab` to clear it, which can kill the running probe's own capture —
|
||
this page already records `pkill -f` matching the caller's shell, biting the same
|
||
way from a different direction;
|
||
* the **restore of the broken file sat as the last line of a command that timed
|
||
out**, so it never ran; recovering with `git checkout` then discarded the entire
|
||
uncommitted rework.
|
||
|
||
📌 **An uncommitted tool is one timed-out command away from being unrecoverable,
|
||
and a tool edited during its own run is not the tool that ran.** Commit first, then
|
||
run. Cheap, and it would have prevented all four.
|
||
|
||
## A harness self-test — and the hole it found in mine on the first run
|
||
|
||
`sylpheed-port` closed this gap first, and named it precisely: their controls
|
||
asserted **failure-on-perturbation**, but nothing asserted that a **broken harness
|
||
reports broken**. Their test feeds the machinery a stub that cannot fail — prints
|
||
"everything is fine", asserts nothing — and requires it to be flagged.
|
||
|
||
✅ **Built the equivalent for `check_refuted.py`, and it found a real hole on its
|
||
first run**: a register that parses **no claims** reported **clean**, forever. That
|
||
is the same shape as their stub, sitting in the tool that guards the shared
|
||
register and whose clean runs both agents lean on. Fixed — it now refuses rather
|
||
than passing.
|
||
|
||
📌 Two details worth copying. **The self-test drives the real machinery as a
|
||
subprocess and reads its actual exit code**; their first version *reasoned* that
|
||
the control would flag the stub — the error this whole thread is about, committed
|
||
inside the tool built to prevent it. And **their exit convention separates the two
|
||
failures that matter**: `0` fine · `1` a real check failed · `2` the harness is
|
||
broken and nothing it reported can be trusted. A single non-zero cannot say which.
|
||
|
||
⚠️ **Filed, not fixed**: `impossibility_scope.py`, `bgm_stem_coherence.py` and
|
||
`ring_row.py` have controls and **no harness self-test**. Shape known, fix cheap,
|
||
not done — recorded so their absence is a stated gap rather than scenery.
|
||
|
||
## "Is the measurement live?" — the control none of my instruments were running
|
||
|
||
`sylpheed-port` closed their last harness gap on exactly this: three controls ran
|
||
every time and **none asked whether the measurement was live**. With an empty band
|
||
list every comparison read 0.0 dB, identity passed, the real pair passed, and only
|
||
the unrelated-movie control failed — reporting a *broken instrument* as a *failed
|
||
check*.
|
||
|
||
🔴 **Applied to `ring_row.py`, which underpins every focus finding here and had no
|
||
self-test at all, it found a defect on the first run.** I had been using
|
||
`main_menu_item(ring_row(f)) is not None` as a **main-menu test**. On a **TITLE**
|
||
frame the gutter carries a bright cluster at y=243 — inside tolerance of row 0 — so
|
||
the title reads as `NEW GAME`.
|
||
|
||
| frame | ring row | named | glyph |
|
||
|---|---|---|---|
|
||
| main menu | 225.5 | `NEW GAME` | 327 |
|
||
| **title** | **243.0** | **`NEW GAME`** | **714** |
|
||
|
||
The glyph counts separate them cleanly; the row alone does not. ⚠️ **It never
|
||
misfired**, because Ⓑ from a submenu goes to the menu and not the title — the test
|
||
was simply weaker than it was being trusted to be, which is the state a self-test
|
||
exists to expose *before* a screen sequence changes and it starts mattering.
|
||
|
||
✅ Fixed with `is_main_menu()`, requiring the row **and** the signature, and the
|
||
self-test asserts the defect it guards plus a **liveness** case: a blanked frame
|
||
must return `None`, not a number.
|
||
|
||
📌 **The general rule, theirs: a control that only compares two things cannot tell
|
||
you the comparison is happening.** Ask separately whether the instrument is
|
||
measuring at all — an empty band list, a blank frame, an empty register. Every one
|
||
of those states makes a checker agreeable rather than wrong.
|
||
|
||
## "A real failure with a fabricated reason" — now three instances, and the expensive one
|
||
|
||
`sylpheed-port` found `check-claims` exiting **1** from a `FileNotFoundError` when
|
||
run from the wrong directory — and in that script's own vocabulary, **1 means "a
|
||
refuted claim is still being asserted"**. A wrong working directory was diagnosed
|
||
as a dirty corpus.
|
||
|
||
The set so far:
|
||
|
||
| | instrument | exit code | what it actually was |
|
||
|---|---|---|---|
|
||
| 1 | my focus reader | passed its differential control | a reader **two items out** |
|
||
| 2 | their `--control` | flagged the stub, exit 2 | anchored at the **wrong document** |
|
||
| 3 | their `check-claims` | exit 1, "corpus dirty" | **wrong directory** |
|
||
|
||
📌 **This is worse than a clean miss, and it is worth saying why.** A missed defect
|
||
leaves you where you were. A real failure with a fabricated reason **sends the
|
||
reader somewhere else entirely**, with the authority of a correct-looking exit
|
||
code — and the time is spent on the wrong thing before anyone doubts the label.
|
||
|
||
⚠️ **The defence is not a better diagnosis but a separate one.** Their three-way
|
||
convention exists for this: `2` means *the harness is broken*, so it can never be
|
||
read as *the corpus is dirty*. Any state a tool can reach that is neither "fine"
|
||
nor "a real finding" needs its own code, and a preflight is cheaper than a
|
||
diagnosis.
|
||
|
||
## Read the other agent's branch, not your checkout's copy of their file
|
||
|
||
I told `sylpheed-port` a row in their `BLOCKED.md` was wrong. **It had been struck
|
||
and corrected for days**, and the correction already contained the exact diagnosis I
|
||
thought I had found independently — the negative bounded to *"the **tables** name no
|
||
screen"*, citing `li r5, 1103` and the byte-for-byte wave match.
|
||
|
||
🔴 **I was reading `docs/port/BLOCKED.md` in my own working tree — last touched
|
||
2026-08-29, 234 commits behind.** Their live file is on `auto/port-p6-audio`, and
|
||
that ref is **already fetched in this checkout**:
|
||
|
||
```
|
||
git show origin/auto/port-p6-audio:docs/port/BLOCKED.md
|
||
```
|
||
|
||
⚠️ **This is the exact mirror of the gap I had been reporting about them**: they
|
||
read `main`'s 926-line `HANDOFF.md` while my current one was on my branch. I
|
||
diagnosed that as a delivery problem needing a human merge — and then made the same
|
||
error in the other direction, with the fix one command away. They had already been
|
||
reading my branch directly (their rows cite my commits by sha); I had not been
|
||
reading theirs.
|
||
|
||
📌 **So the shared-state problem is not one gap but two, and only one of them needs
|
||
a merge.** What a peer *holds* is readable now, from any topic branch, by anyone who
|
||
remembers the ref exists. What a peer must be *told* still needs `main`. Reporting a
|
||
defect in a file you have not read at its head is worse than not reporting it:
|
||
theirs was corrected, so my message asked them to re-fix something already fixed,
|
||
which is the wrongly-superseded failure aimed at a live correction.
|
||
|
||
## A checker inherits the staleness of every file it scans
|
||
|
||
`check_refuted.py` scans all of `docs/`, which includes the files `sylpheed-port`
|
||
authors. **Six of seven of my copies of those are days behind their branch head,
|
||
and one I do not have at all.** So any verdict it reaches about one of their files
|
||
is a verdict about *my copy*.
|
||
|
||
Measured before acting: **zero** of today's hits land in a peer-owned file, so the
|
||
exposure is **latent rather than active**. That is worth stating either way,
|
||
because the failure direction is the false positive — flagging a claim the owner
|
||
has already corrected — and I did exactly that by hand the same day, with their
|
||
live file one `git show` away in a ref already fetched here.
|
||
|
||
⚠️ **Reported, not excluded.** Silently skipping their files would hide the
|
||
exposure, and being behind a peer's topic branch is the normal state — making it an
|
||
error would be scenery within a day. The run now names which peer-owned files were
|
||
judged from a stale copy, and prints the command to read the live one.
|
||
|
||
📌 **The general form: a tool's reach includes the freshness of its inputs, not
|
||
just their content.** A checker with a green light over a stale corpus is reporting
|
||
on a snapshot, and nothing in its output says so unless it is made to. Ask of any
|
||
scan not only *what did it look at* but *how old was what it looked at, and who
|
||
owns it*.
|
||
|
||
## A cross-agent register can flag a phrase that is live and correct in the other corpus
|
||
|
||
Measured, not feared. `sylpheed-port`'s register holds **"1 of 3 streams"** as a
|
||
**dead** claim. The same words appear twice in this corpus — `HANDOFF.md:1635` and
|
||
`voice-three-streams-are-concurrent.md:72` — both reading *"the '1 of 3 streams'
|
||
warning **stands**"*. It is **live and correct here**.
|
||
|
||
⚠️ It is not a revival and not a hygiene failure. **Two corpora used the same words
|
||
for different propositions**, and no amount of care on either side prevents that. I
|
||
cannot tell from the bare phrase whether their dead claim is even the same
|
||
proposition as my live warning, and guessing would be the method-versus-subject
|
||
error in a new costume.
|
||
|
||
📌 **So a cross-agent check must be advisory, and the reason is sharper than
|
||
"noise gets skimmed."** A false positive aimed at another agent does not get
|
||
ignored — **it gets disputed**, and the dispute costs more than the check was worth.
|
||
Their first version counted six hits in my files as failures, applying their
|
||
`[refuted]` token to a corpus that marks corrections its own way; I would have
|
||
argued with it rather than fixing my pages, which is the worst of both outcomes.
|
||
|
||
## Relaying a peer's dead claims creates occurrences of them — measured
|
||
|
||
Their observation, and this corpus supplies the measurement: of **11** occurrences
|
||
of their registered claims in my files, **3 are in the single file I wrote to
|
||
report on their claims**. I produced the effect while documenting it.
|
||
|
||
📌 The cost is **per-mention**, and it now travels **between** agents rather than
|
||
accumulating inside one. Neither of us has a way to write about a dead claim
|
||
without instantiating it, and the volume grows fastest exactly when the two
|
||
corpora are discussing each other's corrections — which is what this week has been.
|
||
|
||
## A claim that carries no weight attracts no scrutiny
|
||
|
||
`sylpheed-port` named this after finding they had copied an unchecked aside of mine
|
||
— *"an EN/JP pair"* — into `authored/flow.json` **twice**, inside the very `why`
|
||
that reads *"my re-derivation confirms the geometry and does not name the screen"*.
|
||
The checked half and the unchecked half were **one sentence apart**, and the
|
||
unchecked one rode along on the credibility of the check beside it.
|
||
|
||
⚠️ **The mechanism is not carelessness — it is the opposite.** Scrutiny goes where
|
||
the weight is. Their re-derivation targeted the load-bearing part *because* it was
|
||
load-bearing; the decoration went unexamined for the same reason. Then it sits in
|
||
an authored file being read as measured.
|
||
|
||
🔴 **Swept this corpus for the shape and found one in the port's own domain.**
|
||
`ui-composable-bundles.md` said a `.prm` element "has no sprite and is **skipped as
|
||
everywhere else**". True of our compositor. **False of the game**: that element is
|
||
`palogo_eff0.prm`, which `ui-forced-backdrop.md` decodes as the full-screen opaque
|
||
black backdrop, **forced first, measured off the running game**. The load-bearing
|
||
claim on that page — a draw order pinned by a disc test and matching the oracle —
|
||
was checked; the aside beside it was not.
|
||
|
||
📌 So this is the method-versus-subject error with a delivery mechanism attached:
|
||
**the aside generalises ("as everywhere else"), which is what turns a statement
|
||
about our tooling into a statement about the disc.** Grep for the generalising
|
||
phrases rather than the claims — `as everywhere else`, `the usual`, `as elsewhere`
|
||
— because the tell is in the aside, not in the subject.
|
||
|
||
## A refutation is exactly as wide as the job the claim was offered for
|
||
|
||
I offered a reading — dialog text baked into language-specific sprites — to explain
|
||
why **63 of 65** adjacent `GP_DIALOG` pairs differ. `sylpheed-port` refuted it *at
|
||
that job*: 26 of the 65 differ in **button count**, which two languages cannot.
|
||
|
||
⚠️ But **37 of the 63 differ without a button-count mismatch**, and for those the
|
||
reading is **unsupported, not refuted**. They had the wider version available and
|
||
would have been believed; they wrote the bound instead. **The temptation runs both
|
||
ways**, and the wider claim is always the more quotable one.
|
||
|
||
## A conclusion resting on two legs, one of which does not reproduce
|
||
|
||
I closed the 37 `GP_DIALOG` pairs with two arguments: adjacent entries carry
|
||
**different stages** (`pzstg10` against `pzstg02`), and their **sprite counts
|
||
differ**, "a different amount of text, not a translation".
|
||
|
||
✅ The first reproduces from `sylpheed-port`'s reader and settles it alone.
|
||
🔴 **The second does not hold**: 12/13 is equal — thirteen title sprites each —
|
||
and it is visible in **my own printed output**, which I had generalised from the
|
||
10/11 example beside it. Our absolute numbers also disagreed (42 vs 34 against my
|
||
20 vs 16) because we counted different things and I never said which I meant.
|
||
|
||
📌 **The shape is what matters: the leg carrying no weight is the one that went
|
||
unchecked** — the same mechanism as the `EN/JP pair` aside, committed *while
|
||
writing up that very failure*. A sufficient argument does not make a second one
|
||
harmless; it makes it unexamined.
|
||
|
||
⚠️ And note the failure mode it creates for a reader: a conclusion with two
|
||
supports reads as *better* evidenced than one with a single support. If one
|
||
support is decorative, the appearance of redundancy is itself the misinformation.
|
||
|
||
## The agreement that a question would stay open was the last thing protecting it
|
||
|
||
Both agents wrote down that the 37-pair bound would stay unresolved because nothing
|
||
rewarded closing it. **That written agreement was the last protection the claim
|
||
had** — two scans closed it, and it went against the reading I had offered.
|
||
|
||
📌 `sylpheed-port`'s framing is the honest one: this worked once, and is not a
|
||
mechanism. It worked because the observation was read as a challenge rather than as
|
||
an excuse, and neither of us can arrange that on purpose.
|
||
|
||
## A leg count is not an independence argument
|
||
|
||
`sylpheed-port` found the tell for decorative legs — **claims that announce their
|
||
own count** ("three routes", "two derivations", "all agree") — and ran it on their
|
||
`audio.json` entry, where two of three legs turned out to be a **disc-to-runtime
|
||
match**, i.e. one comparison. The legs survived, but only because a census
|
||
*excludes alternatives*; the count had been doing the work the exclusion argument
|
||
should have done.
|
||
|
||
🔴 **Ran it here and my DIFFICULTY delivery had the same shape.** I wrote *"decoded,
|
||
three independent routes"*:
|
||
|
||
* the **image** leg says DIFFICULTY is a *dialog* — it names no entry, so alone it
|
||
identifies nothing;
|
||
* the **disc** and **oracle** legs are **one compound argument** — the capture is
|
||
compared *against* the disc's rows.
|
||
|
||
The exclusion scan (zero rival builds disc-wide) is what makes the compound leg
|
||
discriminating, and it is exactly what "three" was taking credit for. Corrected to
|
||
state the reasoning instead of the count.
|
||
|
||
📌 **The general form: a count asserts independence without ever demonstrating it,
|
||
and reads as strength.** Two legs that check each other are one leg. The question
|
||
to ask of any *n*-routes claim is not whether the routes are correct but **whether
|
||
any of them could have come out differently given the others** — which is an
|
||
exclusion argument, and is usually absent.
|
||
|
||
⚠️ **Reach: 1 of 272.** A sweep for leg-count phrasing finds 272 candidates in this
|
||
corpus and I audited the single most load-bearing one. One verified case is not a
|
||
verified set; the other 271 are unaudited, and most are probably fine, which is
|
||
exactly why nobody will check them.
|
||
|
||
## Nothing checks the prose a tool prints or documents beside its own numbers
|
||
|
||
`sylpheed-port` found `verify-capture`'s note saying a capture was *"rendered with
|
||
authored initial focus"* — an assumption nothing had established, sitting under
|
||
their most-quoted residual. Their point: **an assumption in a harness note is
|
||
invisible in a way an assumption in a `why` is not.** `audit-kinds` checks every
|
||
authored value for a citation; nothing checks a tool's own prose.
|
||
|
||
✅ **Swept my printed output and found no instance**: 38 lines assert a screen or
|
||
game fact, and the ones that assert rather than report are computed in the same run
|
||
(`"(nothing moves under this input that is quiet at rest)"` prints only when the
|
||
index is empty). ⚠️ Weak sweep — keyword-matched, printed strings only, and "does
|
||
this assert something the run does not establish" is a judgement, not a test.
|
||
|
||
🔴 **But the class is real here and I have a known instance on the larger surface:
|
||
tool DOCSTRINGS.** `ring_row.py` documented its calibration as
|
||
`capture_y = 49.5 + 1.060 * design_y` — **wrong**, fitted against `menu_focus.py`'s
|
||
approximate rows rather than the disc's. It sat in the file that underpins every
|
||
focus finding, and it was found by accident while chasing something else, not by
|
||
any check.
|
||
|
||
📌 **The surface is bigger than harness notes.** These tools carry long docstrings
|
||
full of factual claims about the game — calibrations, thresholds, what a screen
|
||
does — and **nothing verifies any of it**. A `why` in an authored file at least has
|
||
a convention demanding a citation. A docstring has nothing, is read as authoritative
|
||
by the next reader, and travels with the code.
|
||
|
||
## The register never scanned code — and code is where a retraction fails to land
|
||
|
||
`sylpheed-port` found **three live stale claims in their own source**, each already
|
||
retracted in their log days earlier, and named the rule: *a correction that does not
|
||
reach the artifact a consumer reads has not been made*. A code comment is the worst
|
||
case, because **it sits beside the thing it describes**.
|
||
|
||
🔴 **`check_refuted.py` scanned `docs/` only.** Running it over `tools/` and
|
||
`crates/` for the first time found one here too: `jp_title_session.sh` justified its
|
||
own existence with *"a free-running clock lands somewhere else on a fresh boot"* —
|
||
a claim **I had refuted the day before**, when the plate-pulse gate turned out to
|
||
phase-lock the shutter to 1.6 % of the sweep traverse. The script's rationale rested
|
||
on a premise I had personally killed.
|
||
|
||
✅ Fixed, and the register now scans code behind `--code`. **Controlled three ways**,
|
||
and the middle one is the proof the gap was real: a planted revival in code exits 1
|
||
with `--code`, exits **0 without it**, and 0 again once removed.
|
||
|
||
⚠️ **Their limit is more important than the fix, and it is not closed.** A register
|
||
holds only what has *already been retracted*, so it catches **propagation failures,
|
||
not wrong numbers**. My own worst instance — `ring_row.py`'s calibration, wrong
|
||
because it was fitted against the wrong reference rows — would still not be caught,
|
||
because nothing had retracted it: **nobody knew it was wrong.** This closes the
|
||
class found in their tree and not the one found in mine.
|
||
|
||
## Liveness has a second form: a checker that fails correctly over a fraction of the corpus
|
||
|
||
Every earlier instance in this corpus was a checker that **could not fail**.
|
||
`sylpheed-port` found the other shape: `audit-kinds` **fails correctly** and was
|
||
auditing **16 of 71** authored justifications, never saying so — while its clean
|
||
runs were being quoted as evidence the authored data is grounded. That was a
|
||
statement about a sixth of it.
|
||
|
||
📌 Their formulation is the one to keep: ***"I checked and it was fine"* and *"I
|
||
checked the part that declared itself"* read identically in a log.**
|
||
|
||
✅ Measured the same thing here. `check_refuted.py` covers **83 of 86** refutation-
|
||
shaped bullets — **97 %**, better than theirs and **equally unstated until now**.
|
||
It prints its scope before its verdict.
|
||
|
||
⚠️ **The remaining 3 are deliberate, and forcing them would be worse than the gap.**
|
||
They quote their claim in backticks and are bare identifiers (`+0x29d0`,
|
||
`position = instance − 0x12c`); registering those would match every live mention of
|
||
the same offset. Both agents landed on the same rule independently: **report the
|
||
ratio, do not demand it be 1** — a counter that must be satisfied invites
|
||
mislabelling, which is a worse failure than an honest gap.
|
||
|
||
## An answer the port must author still needs a citation — and the thing to cite is the question
|
||
|
||
`sylpheed-port`'s rule, from finding an `authored` value whose `why` said *"ask the
|
||
RE agent"* without naming where the question is recorded: **a pointer with no
|
||
destination**. Their formulation is the one that transfers — *without a citation,
|
||
an invented value and a placeholder for a measurement read identically*, which is
|
||
the whole distinction the label exists to carry.
|
||
|
||
🔴 **Measured the analogue here.** This corpus's equivalents are the deliveries
|
||
classified **measured** or **undecodable, with reach** — where the mission says the
|
||
port authors by hand and *must know it is authoring*. Of **57** `HANDOFF.md`
|
||
sections asserting one of those, **9 cite nothing openable — 84 %**.
|
||
|
||
Two are legend sections that need none. But one is a **measurement**: *"Ⓑ from
|
||
`EXTRAS` DOES go black"*, delivered as an inline frame table with no file cited —
|
||
while `data/fade-four-transitions.txt`, which carries that leg and eight others,
|
||
**was committed the whole time**. Exactly their `loop_why`. Citation added.
|
||
|
||
📌 **And the mechanism they name is the one worth carrying: a blind spot that
|
||
correlates with quality is invisible by construction.** Their unlabelled entries
|
||
were not the sloppy ones — they were so well-evidenced that nobody thought to mark
|
||
them. Both audits were measuring **self-declaration, not grounding**, and a
|
||
well-evidenced claim is exactly the one that never declares itself.
|
||
|
||
### Tested their mechanism here — it does not reproduce, and the real predictor is different
|
||
|
||
`sylpheed-port` sharpened the blind-spot finding to *"well-argued prose never cited
|
||
anything — the detail is what made it look sourced"*, with three `why` fields of
|
||
1 041–1 402 characters, all detailed, all uncited.
|
||
|
||
❌ **That does not reproduce in this corpus.** Of 57 `HANDOFF.md` sections
|
||
asserting measured/undecodable/authored, the cited ones have a **median of 2 502
|
||
characters** and the uncited **2 386** — indistinguishable. Length and care do not
|
||
predict citation here.
|
||
|
||
✅ **The predictor is RECENCY:**
|
||
|
||
| date | cited | uncited | rate |
|
||
|---|---|---|---|
|
||
| 2026-08-29 | 19 | 5 | **79 %** |
|
||
| 2026-08-30 | 22 | 1 | **96 %** |
|
||
| 2026-08-31 | 5 | 0 | **100 %** |
|
||
|
||
⚠️ **And the obvious caveat, which weakens it as evidence of a habit:** the
|
||
improvement coincides with this exchange, so the norm becoming salient is part of
|
||
what produced the trend. It is not evidence of a durable practice — only that the
|
||
uncited residue is old.
|
||
|
||
📌 **The distinction that matters is what each mechanism implies.** Theirs is
|
||
**generative**: a blind spot correlated with quality keeps producing new instances,
|
||
because the well-evidenced claim never declares itself. Mine is a **legacy
|
||
residue** — finite, concentrated in the oldest deliveries, and closable by a
|
||
one-time backfill. **Same symptom, different prognosis**, and reading their
|
||
diagnosis onto my corpus would have implied work that is not needed and missed work
|
||
that is.
|
||
|
||
## A record layout is only decidable at the table's boundaries
|
||
|
||
`sylpheed-port` found the gap in their own rule: the fourth unchecked thing of mine
|
||
to reach their authored data was a **structure** — a field order — not a decoration.
|
||
*"The claims that go unchecked are the ones that carry no weight"* did not cover it,
|
||
because **a wrong field order looks like a fact**, and a later reader builds on it.
|
||
It carried no weight only by luck.
|
||
|
||
So I built the control that should have existed when I published
|
||
`{handler, id, name_ptr}` — and **the obvious version does not work**:
|
||
|
||
| alignment | records type-plausible |
|
||
|---|---|
|
||
| published `{id, name_ptr, handler}` | 70/70 |
|
||
| shifted −1 | **69/70** |
|
||
| shifted +1 | **69/70** |
|
||
|
||
🔴 **The interior carries no information about phase.** A homogeneous repeated table
|
||
has the same field types in sequence — id, name, handler, id, name, handler — so
|
||
**any window starting on a field boundary type-checks**. Verifying "every record
|
||
looks sane" confirms a wrong alignment just as readily as a right one.
|
||
|
||
✅ **Only the boundaries discriminate.** A shifted reading must consume a word from
|
||
*outside* the table at one end, and that word does not obey the field's type. It is
|
||
exactly how the original error surfaced: under the shift, record 0's "handler" was
|
||
`0x10000000` — the word sitting before the table. Two-sided and now asserted: the
|
||
published alignment survives at both edges, both shifts fail.
|
||
|
||
📌 **The general rule: for any repeated structure, the evidence for the field order
|
||
lives at the first and last record.** Everything in between is compatible with every
|
||
phase, and checking it is the reassurance that feels like verification.
|
||
|
||
## An interior consistency check is satisfied by any internally consistent reading
|
||
|
||
`sylpheed-port` aimed my boundary finding at a control of mine and it landed. My
|
||
`+0x08` loop-length page rests on a falsifier: *an animation cannot restart before
|
||
its own last pose, so a wrong reading should produce violations, and none exist*.
|
||
|
||
🔴 **It does not identify `+0x08`.** Reproduced from my own reader over every pak:
|
||
|
||
| offset | violations | exact `== max t` |
|
||
|---|---|---|
|
||
| `+0x04` | **0 — passes** | **0.0 %** |
|
||
| `+0x08` | 0 | 49.6 % |
|
||
| `+0x0c` | 1 287 | 11.8 % |
|
||
|
||
A wrong reading one word left produces no violations either. **The discriminator is
|
||
the exactness statistic the page presents as secondary** — `+0x08` matches exactly
|
||
in half the records, `+0x04` in none.
|
||
|
||
📌 **Second time this week with the weight on the wrong leg**, and both have the
|
||
same shape: a *count* taking credit for an exclusion argument, then a *falsifier*
|
||
taking credit for an exactness statistic. **In both, the real discriminator was
|
||
sitting beside it, described as a formality.**
|
||
|
||
⚠️ Their statement of the general rule is sharper than my boundary version, which
|
||
does not transfer to a per-record header: **an interior consistency check is
|
||
satisfied by any reading that is internally consistent — and "internally
|
||
consistent" is what a wrong offset into a regular structure usually is.** The
|
||
boundary rule is the special case where the structure's edges break that regularity.
|
||
|
||
## A denominator mismatch hides behind an agreeing numerator
|
||
|
||
Two agents, one statistic, and the disagreement was **entirely in the denominator**:
|
||
`1643/1781 = 92.3 %` against `1643/3311 = 49.6 %`. **Neither of us was wrong about
|
||
the disc.**
|
||
|
||
🔴 **Two wrong explanations were offered for the gap before the right one.** Mine
|
||
first: I said my scan "requires a timed keyframe" — it does not, because `.max()`
|
||
returns `Some(0)` rather than `None`. Then `sylpheed-port`'s reconciliation, which
|
||
I adopted: that the extra 1 530 are *"questions never asked"* with no content.
|
||
**Also wrong, and they corrected it themselves.** Measured: **0** records on this
|
||
disc lack a timed keyframe; all 1 530 are **static** — timed, every pose at t = 0.
|
||
A static record still declares a cycle length, so a nonzero `+0x08` against a
|
||
largest time of 0 is a **real disagreement, not an absent one**, and the 49.6 % is
|
||
a defensible statistic over a different population rather than an artefact.
|
||
|
||
📌 **`sylpheed-port`'s diagnosis of why it stayed invisible is the transferable
|
||
part: the numerator agreed to the unit.** We both looked at **1 643** and neither
|
||
noticed we were dividing it differently. An agreeing numerator reads as agreement,
|
||
and a shared number is the last place either party looks for a discrepancy.
|
||
|
||
⚠️ **Both halves needed a qualifier neither carried.** 92.3 % is *of the records
|
||
where the question is meaningful*, not *of nested records* — quoted bare on both
|
||
sides for two days, including into a shipped doc comment. **A population-scoped
|
||
statistic reported without its population is the same shape as a negative reported
|
||
without its reach**, and this corpus already had a rule for the second.
|
||
|
||
### Three rounds, one number, and every disagreement about interpretation
|
||
|
||
The sequence is worth keeping as a shape. I corrected an argument; they corrected
|
||
my denominator; they then corrected their own characterisation of what was in it.
|
||
**Every step was checkable in one scan**, and each of us stated an interpretation
|
||
confidently while only the number had been measured.
|
||
|
||
📌 **The numbers never disagreed** — 1 643, 3 311, 1 781, 0 % — through all three
|
||
rounds. Every disagreement was about **what they were counting**. That is the
|
||
cheaper failure and I suspect the more common one: agreeing figures feel like
|
||
agreement, and neither party re-examines a quantity they both accept.
|
||
|
||
⚠️ Nothing the port depends on moved at any point: `+0x08` matches exactly wherever
|
||
the largest time is nonzero, `+0x04` is 0 % under either denominator, and the offset
|
||
stands on both scans. **Three rounds of correction over an interpretation that was
|
||
never load-bearing** — which is also why it was safe to keep pulling.
|
||
|
||
## A log line is a summary someone wrote; reading it as the observation is a substitution
|
||
|
||
Mid-run I concluded my menu detector had failed in `ja`, because the log showed
|
||
**glyph 11654** far outside the 250–420 band. It had not: the JP menu detects at
|
||
**320** against English's **327**, both in band — the 11654 was a **later phase**. I
|
||
diagnosed from the log line instead of opening the capture.
|
||
|
||
📌 `sylpheed-port` placed it beside the harness-note finding and the pairing is
|
||
right: **an assumption in a harness note is invisible, and a log line is a summary
|
||
someone wrote.** Reading either as the observation is the same substitution — a
|
||
description of the evidence standing in for the evidence.
|
||
|
||
⚠️ The cost here was small only because I checked before publishing. The capture was
|
||
one `Read` away the whole time, and the wrong diagnosis would have gone into a data
|
||
file as "the detector is locale-specific" — a plausible, tidy, false instrument
|
||
finding that nothing downstream would have questioned.
|
||
|
||
## An instrument that refuses is safe and can still cost you the run
|
||
|
||
`ring_row.py` carries `ROW0 = 225.5`, `SPACING = 79.25`, measured off **x11grab**
|
||
frames. On 2026-08-31 the same live main menu, grabbed with the `screenshot`
|
||
wrapper (1279×675), reads its rows at **180.5 / 419.5 / 502.0** — `ROW0` is
|
||
**45 px out, 0.57 of a step**.
|
||
|
||
The module behaved *correctly*: `main_menu_item()` refuses anything further than
|
||
half a step from a predicted row, so it declined rather than naming the wrong
|
||
item, and `is_main_menu()` returned **`False` on a real main menu**. That is the
|
||
good failure — the earlier version of this bug returned an item **two out** and
|
||
was only caught by ground truth ("the probe said EXTRAS and OPTIONS opened").
|
||
|
||
But a refusal is not free. A run gated on `is_main_menu()` concludes *"not the
|
||
menu"* while sitting on the menu, and there is nothing in its output to
|
||
distinguish that from the game genuinely not being there. **The lesson is not
|
||
"add a tolerance"** — widening it re-opens the wrong-item failure. It is that a
|
||
calibration belongs to a *capture path*, and a module that serves two paths needs
|
||
two calibrations selected by frame size, not one set of numbers that is right for
|
||
one caller and blind for the other.
|
||
|
||
Recorded rather than fixed: three rows from one session are not a calibration,
|
||
and other tools share these constants.
|
||
|
||
## The boot can take three times the budget a capture script allows
|
||
|
||
`menu_draw_capture.sh` and its relatives wait **420 s** for the title and then
|
||
report `NEVER REACHED THE TITLE`. On 2026-08-31 that fired at 424 s — and the
|
||
emulator, left running, was **at the settled title minutes later**, took a single
|
||
Ⓐ, and went to the main menu on the first try.
|
||
|
||
So the script's negative was about its own deadline, not about the game. Worse,
|
||
its classifier had reported `menu` at t=241/252 s and `flight` at t=331 s, all of
|
||
them attract-movie frames, so the log *looks* like a run that saw things.
|
||
|
||
Two things follow. **A timeout is a measurement of the timeout**, and a run that
|
||
ends on one has produced no evidence about the game — this corpus already has
|
||
three withdrawn *"the title never appears"* claims for the same reason. And
|
||
**leaving the emulator up after a failed script is worth doing**: the run above
|
||
was rescued by attaching to it, gating on the plate pulse and tapping Ⓐ by hand,
|
||
which cost one minute against a twenty-minute reboot.
|
||
|
||
## A truncating instrument does not report that it truncated
|
||
|
||
Canary's UI draw capture printed the first **8 vertices** of each draw. A UI quad
|
||
is 4 vertices, so a batched draw showed **two** of its elements and dropped the
|
||
rest — silently, with a well-formed line and no ellipsis.
|
||
|
||
The consequence was not a missing row in a table. `EXTRAS`' 24-index additive
|
||
draw holds **six** sprites, so `ptframe4`, `pteff21`, `pteff22` and `pteff23`
|
||
appeared in **no draw on any screen**, which reads as *the game does not draw
|
||
these*. The port then measured those four as the worst elements on that screen
|
||
and asked what blend they used — and the answer had been inside a draw already
|
||
captured, one line above the truncation.
|
||
|
||
**A cap that hides data is worse than a long line.** The rule that would have
|
||
caught it: when an instrument reports "this element never appears", check its
|
||
limits before believing the game. And a cap should print that it capped.
|
||
|
||
⚠️ The same log had already been used to write *"every element on the two screens
|
||
is covered except one"*. That sentence was wrong by four, and it was wrong in the
|
||
reassuring direction.
|
||
|
||
## A stop condition that cannot be reached is not a stop condition
|
||
|
||
Walking the main menu to `EXTRAS` by counting presses failed — a press was
|
||
dropped and the cursor landed one item short. The fix was "press ⬇ until the
|
||
cursor stops moving", which needs no item count.
|
||
|
||
**The main menu wraps.** The cursor never stops moving, so the loop's termination
|
||
condition was *unreachable* and it only ever exited by exhausting its iteration
|
||
budget. It ended on `EXTRAS` anyway — because a second press was dropped, and the
|
||
drop happened to cancel one lap of the wrap. Two independent accidents cancelling.
|
||
|
||
⚠️ **The first version of that same loop was worse**: it compared two readings,
|
||
got the same row twice because the first press was dropped, concluded "the cursor
|
||
has stopped" while sitting on the **first** item, and pressed Ⓐ on `NEW GAME`.
|
||
|
||
The general shape: a stop test that cannot distinguish *"at the end"* from *"the
|
||
input was lost"* is the press-counting bug wearing a different hat, and on a
|
||
wrapping list it is not a test at all. What saved both runs is worth stating
|
||
separately, because it is the actual discipline:
|
||
|
||
**Verify the state you measured, never the actions you took.** Every capture here
|
||
was preceded by a screenshot that was looked at. The navigation was wrong twice
|
||
and the measurement was never in doubt, because nothing downstream trusted the
|
||
button presses.
|