port: implement their masking rule; it does not transfer, and my phase term was too small

Their rule -- score inside a region excluding free-running elements and measure
the residual there -- implemented with the mask derived by measurement: five leaf
phases per screen, union of what moves. Free-running area is 3.68% on title, 1.63%
extras, 1.32% main_menu, 0.00% on both splashes.

The control fails. On extras, a 1% threshold masks 9.3% of the frame and removes
only ~16% of the phase term (1.7343 -> 1.4569). The rule is sound but conditional:
their free-running element is a localised pulsing plate they can crop out, mine is
a wide translucent sweep whose contribution is thin and spread. It cannot be cut
out without cutting out the picture.

And they were right that my ~1.0 was too small. In verify-capture's own metric the
term is 5.56 on title, 3.78 main_menu, 3.73 extras, 0.00 on the splashes. My
earlier figure came from a greyscale metric over a narrower phase range -- computed
one way, quoted as if it applied another.

The consequence sorts my oracle rows: the splashes carry no free-running element,
so 2.17 and 3.05 mean what they say; title at 14.16 carries +/-5.56, larger than
the spread between any two of my rows. Those rows are usable for regression at a
fixed pin and not for absolute comparison.

Recorded as a limit, not fixed: no pin removes it, since the term is the game's own
animation sampled at one instant by the capture.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
Sylpheed port agent
2026-08-30 16:06:52 +00:00
parent 7fe318356c
commit 1707bfbc85

View File

@@ -9,7 +9,7 @@ dies, which is what this file is for.
<!-- INDEX: generated by tools/port/index-decisions -- do not hand-edit -->
178 sections. Search this before re-deriving anything.
179 sections. Search this before re-deriving anything.
* [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28)
* [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28)
@@ -189,6 +189,7 @@ dies, which is what this file is for.
* [The leaf phase was an arbitrary choice; the capture turns out to determine it](#the-leaf-phase-was-an-arbitrary-choice-the-capture-turns-out-to-determine-it)
* [Cross-checking their leaf reading against my export — it reconciles](#cross-checking-their-leaf-reading-against-my-export--it-reconciles)
* [Replicating the phase result on the title — it fails, and the failure is the finding](#replicating-the-phase-result-on-the-title--it-fails-and-the-failure-is-the-finding)
* [Their masking rule, implemented — and it does not transfer to my screens](#their-masking-rule-implemented--and-it-does-not-transfer-to-my-screens)
<!-- /INDEX -->
## P0 — the exporter, 2026-08-28
@@ -10168,3 +10169,60 @@ corpus keeps naming, and it would silently improve every future number.
capture includes an irreducible capture-phase term of up to **~1.0 RMSE**, larger
than most margins I have quoted from those rows. `title` at 14.16 is not 0.22
"worse" than it could be — 13.94 is not more correct, it is differently posed.
## Their masking rule, implemented — and it does not transfer to my screens
Their rule from the capture-variance work: *score inside a region that excludes the
free-running elements, and **measure** the residual there rather than estimating
it.* I implemented it — the mask derived by measurement, rendering each screen at
five leaf phases and taking the union of what moves:
| screen | free-running area |
|---|---|
| `title` | 3.68 % |
| `extras` | 1.63 % |
| `main_menu` | 1.32 % |
| both splashes | **0.00 %** |
🔴 **The control fails.** Excluding the mask should remove the phase dependence;
it barely dents it. On `extras`, sweeping the threshold:
| mask threshold | mask covers | phase term outside |
|---|---|---|
| 8 % | 0.7 % | 1.7343 |
| 4 % | 1.6 % | 1.6393 |
| 2 % | 5.5 % | 1.5254 |
| **1 %** | **9.3 %** | **1.4569** |
Masking **9.3 %** of the frame removes **~16 %** of the term. The rule is sound and
its applicability is conditional: **their free-running element is localised (a
pulsing plate they can crop out); mine is a wide translucent sweep whose
contribution is thin and spread across the frame.** You cannot cut it out without
cutting out the picture.
### ⚠️ And my ~1.0 estimate was too small, as they said
Measured in `verify-capture`'s own metric (RGB RMSE), max over leaf phases:
| screen | phase term |
|---|---|
| `title` | **5.56** |
| `main_menu` | 3.78 |
| `extras` | 3.73 |
| `publisher_logo`, `developer_logos` | **0.00** |
My earlier ~1.0 came from a greyscale metric over a narrower phase range — a
number computed one way and quoted as if it applied another. Theirs is 4.566
whole-frame on the JP title; mine land at 3.75.6 on the same footing.
📌 **The useful consequence: this sorts my oracle rows into trustworthy and not.**
The splashes carry **no** free-running element, so `publisher_logo` 2.17 and
`developer_logos` 3.05 are absolute numbers that mean what they say. `title` at
14.16 carries **±5.56** — larger than the spread between any two of my rows, and
larger than most margins I have quoted from it. Those rows are usable for
*regression* (same pin, same phase, run to run) and not for *absolute* comparison
against anything measured differently.
⚠️ Recorded as a limit, not fixed. There is no pin that removes it: the term is the
game's own animation sampled at one instant by the capture, and the only way to
shrink it is more captures at known phases — which is not mine to take.