c19a726455
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>
75 lines
4.5 KiB
Markdown
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.
|