Two traps this run paid for. ring_row.py's ROW0/SPACING are x11grab constants. On a /sylph-home/re/shots/shot-0001.png grab of the same live main menu the rows read 180.5/419.5/502.0 -- ROW0 is 45 px out, 0.57 of a step. The module refused rather than naming the wrong item, which is the good failure, and is_main_menu() therefore returned False ON A REAL MAIN MENU. A run gated on it would conclude 'not the menu' while sitting on the menu. Not recalibrated: three rows from one session are not a calibration and other tools share the constants; the module now says so where the numbers are. menu_draw_capture.sh's 420 s title deadline fired, and the emulator left running was at the settled title minutes later, took one A, and reached the menu first try. A timeout is a measurement of the timeout. Leaving the emulator up after a failed script rescued this run for one minute against a twenty-minute reboot. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wuu56cE8vJGTBtn1ppsk8v
3341 lines
208 KiB
Markdown
3341 lines
208 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.
|