Files
manga-recap-pipeline/decisions/measurement-spine.md
T
kami c19a726455 Stop dropping strip pixels, so panel bboxes tile the page
Answering whether the caption merge breaks the page-space key in
eval/chapter-truth.json. It does not. _merge_plan only groups adjacent
fragments and slice_webtoon cuts at gutter midpoints, so a vstacked panel's
[x, y0, w, sum(heights)] is the exact page region.

The defect is one line up. slice_webtoon skipped any segment shorter than
min_seg instead of absorbing it, so this chapter's 116 panels have a 62px hole
between panel_order 70 and 71 and lose 18px at the strip's end. A merge
spanning that hole reports a bbox 62px short of the page span it covers, and
every consumer mapping a detection back to the page is then wrong by that much,
silently. The 62px held the credits line, found at p_050.png row 338.

A short band is now held and absorbed by the next segment, or by the previous
one when it is last. min_seg still suppresses a tiny panel and no strip pixel
is discarded. The self-check asserts the bboxes tile the strip end to end.

Checks: worker_crop.py self-check passes and fails on the old code, where the
first band starts at 49 instead of 0. ruff check . exits 0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 23:41:11 +04:00

75 lines
4.5 KiB
Markdown

# The measurement spine
`eval/chapter-truth.json` plus the purity and fragmentation section of `audit_registry.py`. This is
`ARCHITECTURE.md` step 0, and nothing below it in that build order is measurable without it.
## The truth file keys on page-space geometry {#truth-is-page-geometry}
**Closed, 2026-08-13.** Reproduces the baseline on the 19:44 run of 2026-08-12.
A truth row cannot name a `panel_id` or a `character_id`. A re-crop remints panel ids, and
`/characters/reset` remints character ids. The fifth cycle does both, so a truth file keyed on either
would die the moment it was first used.
Each row carries `[x1, y1, x2, y2]` in page space, which is the panel's `bbox` offset plus the
detection box. The page strip is the fetched artifact and does not change when panels are re-sliced, so
the key survives. `audit_registry.py:_score` matches a row to an assignment on the same page at
`IOU_MIN = 0.5`, greedily, best overlap first, each row and each assignment used once.
The 19:44 `panel_order`, `local_id` and `character_id` are kept per row under `from_19_44`, for
debugging only. Nothing matches on them.
## A slice under `min_seg` is absorbed, not dropped {#slices-tile-the-strip}
**Closed, 2026-08-13.** `worker_crop.slice_webtoon`, checked in its `__main__`.
The page-space key above needs the panel bboxes to tile the strip. They did not. `slice_webtoon` skipped
any segment shorter than `min_seg`, so its pixels reached nothing and the y chain gained a hole. On the
2026-08-12 chapter it happened twice. 62px went missing between `panel_order` 70 and 71, holding the
credits line `글 | H2J · 그림 | 이루리다`, and 18px at the bottom of the strip.
62px is small and that content was worthless, which is why it went unnoticed for the whole project. The
rule is not harmless. The same threshold drops a 62px caption. `merge_faceless_captions` vstacks
adjacent fragments, so a merge spanning a hole reports a bbox 62px shorter than the page span it covers.
Every consumer mapping a detection back to the page is then wrong by that much, silently.
A short band is now held and absorbed by the next segment. The last band is absorbed by the previous one.
`min_seg` still does its job, which is to suppress a tiny panel, and no strip pixel is discarded.
The self-check asserts the bboxes tile the strip end to end and that no panel is under `min_seg`.
## Purity is a share, so it never names an id {#purity-is-id-free}
**Closed, 2026-08-13.**
Purity of a cluster is the largest share of one true person inside it. The lead's 16 assignments hold
14 of him, so 0.88, and the truth file never has to say which id he was. Fragmentation of a person is
the number of clusters holding their occurrences. Woman A has 15 occurrences over 2 ids, so 2.
So both numbers survive a reset. The definitions in `ARCHITECTURE.md` were not explicit about that.
A cluster is reported under its dominant person. Every other person in it prints as a `wrong:` line,
which is where the photograph and the chibi show up on the lead.
The `baseline` block in the truth file holds the 19:44 numbers, and each printed line says
`= baseline` or the delta. That makes step 0's DoD a check rather than an eyeball.
## The truth is 38 assignments, and holds no dialogue yet {#truth-scope-is-38}
**Open, 2026-08-13.** The character half is done, the dialogue half is not written.
The eyeball pass covered three characters, 38 of the run's 60 assignments. The other 10 characters were
never checked and carry no truth row. The audit prints them as out of scope rather than as correct.
Anything claiming chapter-wide accuracy off this file is overreaching.
The prose in `NEXT.md` left two rows unnamed. They were identified on 2026-08-13 by re-cropping `p030`
and `p032`: `panel_order` 31 and 33 on woman B's id are both woman A. That closes the recorded
arithmetic of 7 correct and 2 wrong, and it is why woman A's fragmentation is 2.
One judgement is recorded in the file rather than hidden. The chibi of woman B at `panel_order` 28
counts as her, because it is a stylised rendering of the subject. The chibi of the lead at
`panel_order` 20 does not, because it is a drawing inside the scene. `not_people` names the second kind.
`ARCHITECTURE.md` also asks for 30 dialogue lines with their true speaker, typed
`visible | offscreen | narrator | unknown`. `dialogue` is an empty array. No such pass exists, because
`NEXT.md` records no per-line speaker truth. Writing it means watching the chapter panel by panel. The
audit prints nothing about speakers until it is filled.