port: check the five MODDING rules, and label the generated files in the asset tree

MODDING.md calls modding a constraint on the exporter TODAY and nothing verified
it -- the same shape as the black hold, skipped[], stop_bed and --focus. All five
rules pass, so check-modding is a guard rather than a fix, and it is proved able
to fail: a stripped .cmd header, a bogus.bmp, and one orphaned PNG each exit 1.

It found one thing: the .cmd encode-cache sidecars sat in the modder-facing tree
with nothing saying what they were. They now carry a header. The header is
excluded from the cache key so rewording it does not re-encode four minutes of
video, and the sidecar is refreshed whenever its text differs rather than only on
re-encode -- otherwise a header change could never reach an existing export.

Also partly answers my own question to the Decoder: there is no general
capture-path floor, because the port matches live-title-press-a at 0.00093%
full-frame and 0.000% across the band. The 0.301% is specific to that pair.

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 02:46:26 +00:00
parent e811bb99e2
commit 606eee8f23
3 changed files with 189 additions and 2 deletions

View File

@@ -6161,3 +6161,62 @@ say so, or the next person tunes toward it.
and all three were blocked by the harness, not by the capture: an overlay posed at
t=9 that drew nothing, a `--focus=` overwritten on every menu entry, and a banded
comparison that did not exist.
## `MODDING.md` had five rules and no check. Now it has one, and all five pass
`MODDING.md` opens by calling modding *a constraint on the exporter **today**,
not a later feature*. Nothing verified it. That is the shape this port keeps
finding — a rule stated, believed and unexercised: the black hold implemented and
never called, `ScreenView.skipped` written and never read, `stop_bed` provided and
never used, `--focus` parsed and overwritten on every menu entry.
`tools/port/check-modding` covers all five. Every one passes today, so it is a
**guard, not a fix**: its value is that the next thing to break one says so.
| rule | check | result |
|---|---|---|
| 1 — one asset, one file | every referenced sprite present, none orphaned, no split names | **174 / 174**, exact |
| 2 — recognisable names | no hex or hash-shaped filenames | none |
| 3 — modern formats | extensions confined to json/png/ogg/ogv (+ sidecars) | clean |
| 4 — base and overrides | `data/mods` gitignored *and* read by the exporter | both |
| 5 — provenance | every generated JSON carries a `source` | 17 / 17 |
### It is proved to fail
A check that has never failed has not been shown to work — the lesson from
`check-capture`, which once passed a file with 36 % holes punched through it. Three
controls, each failing correctly with a non-zero exit:
* a `.cmd` sidecar with its header stripped → rule 3;
* a `bogus.bmp` in the sprite tree → rule 3;
* one orphaned PNG → rule 1, *"174 referenced, 175 present"*.
### The one thing it found: an unlabelled generated file in the asset tree
The two `.cmd` encode-cache sidecars sat beside the `.ogv`s in the modder-facing
tree with no line saying what they were — a bare ffmpeg command next to a video
reads as something to edit or delete. They now carry a header stating that they
are generated, are not assets, and that the way to change a video is an override
under `data/mods/`.
Two details worth keeping:
* the header is **excluded from the cache key**, so rewording it does not
re-encode four minutes of video. A cache that punishes documentation gets
documented once and never again.
* the sidecar is now refreshed whenever its **text** differs, not only when a
re-encode happens. It used to be written inside the `!fresh` branch — which
meant a header change could never reach an existing export, because nothing
that reads the header triggers the write that updates it. The explanation would
have been correct in the source and absent on disc. Confirmed: two consecutive
exports, 20 s and 19 s, header present, no re-encode.
### And a question I asked the Decoder that I could partly answer myself
Last iteration I asked whether the 0.301 % between two of their captures implies a
**capture-path floor on every comparison in the corpus**. It does not, and I had
the evidence already: the port matches `live-title-press-a.png` at **0.00093 %**
full-frame and **0.000 %** across the band. A general floor could not coexist with
either number. So the 0.301 % is specific to the attract band capture, and my
0.010.2 % rows are not sitting on a hidden floor. ⚠️ What that does *not* settle
is why those two frames differ — still theirs, and still worth an answer.