Files
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

94 lines
4.6 KiB
Markdown

# HANDOFF, 2026-08-13 (ninth session)
Live state is in `NEXT.md`. This file is only what this session did. The previous handoff is in
`JOURNAL.md`.
## Asked
Get up to speed from the eighth handoff, pick the next work, then commit to `master`. Then: can the
merged-panel bug be fixed.
## Result
No GPU work. No stage ran. `master` is at `bc19f9e` and pushed, plus the crop fix below still to commit.
`ARCHITECTURE.md` step 0, the measurement spine, is built for the character half and its DoD is met.
## Landed
| what | where |
| --- | --- |
| `eval/chapter-truth.json`, 38 labelled occurrences | new file |
| purity and fragmentation, plus a `--selftest` | `audit_registry.py` |
| a short slice is absorbed, not dropped | `worker_crop.py:slice_webtoon` |
| the design, 4 sections | `decisions/measurement-spine.md` |
### Step 0, the measurement spine
```
truth: 38 labelled occurrences, 38 matched an assignment at IoU >= 0.5, 0 unmatched
LIM SEONHO [b1dd5659] lead 14/16 = 0.88 = baseline (wrong: photo_of_lead 1, chibi_of_lead 1)
character_2b1b12a1 woman_a 13/13 = 1.00 = baseline
Seonho [f0d4e901] woman_b 7/9 = 0.78 = baseline (wrong: woman_a 2)
fragmentation lead 1, woman_a 2, woman_b 1 all = baseline
```
Rows key on page-space geometry. Purity is the largest share of one true person in a cluster.
Fragmentation is the count of ids holding one person. So neither needs a `character_id`. The file
survives the re-crop and the `/characters/reset` that the fifth cycle runs. That was the handoff's
open ordering trap.
`NEXT.md` said 2 of woman B's 9 crops were really woman A and never said which. They are `panel_order`
31 and 33, identified from `p030` and `p032`.
### The crop fix, answering "can we fix the merged panels bug"
There is no merged-panel bug. `_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 real defect was one line up. A segment under `min_seg=64` was skipped outright, so the 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 would report a bbox 62px short of the page span. Every page-space mapping across it would then be
wrong by that much, silently. The 62px held the credits line at `p_050.png` row 338. `slice_webtoon` now
absorbs a short band into its neighbour (`decisions/measurement-spine.md#slices-tile-the-strip`).
### Audit fixes, all pre-existing
- 20 characters counted where 14 are live and 6 are merge losers kept on purpose
- the assignment spread keyed on `name`, so the two characters named `Seonho` summed into one line of 11
- the default worked example was `panel_index` 7, a panel vision skips. `NEXT.md`'s "panel 7" is
`panel_order` 7, one lower, the office shot with 6 detections
- nothing about skipped panels. 41 of 116 are `skip=True`, four checked and all four correct
## Open
- **Step 0's dialogue half.** 30 lines with their true speaker, typed
`visible | offscreen | narrator | unknown`. `dialogue` is an empty array in the truth file. It needs
the chapter watched panel by panel, because no per-line speaker truth exists anywhere to transcribe.
- **28 of 122 dialogue lines sit on skipped panels**, which hold no character at all. 23% of dialogue
cannot resolve to a visible speaker under any linker. This is the measured case for `offscreen` as a
fourth `speaker_ref` kind, and it is not built.
- The eighth handoff's five unapplied audit findings are all still unapplied, `gemma.py` first.
## Checks
```bash
.venv/bin/python audit_registry.py --selftest # IoU match, greedy tie-break, purity maths
.venv/bin/python worker_crop.py # the slice must tile the strip with no hole
ruff check . # All checks passed
```
The live audit ran against `/data/manga.db` in `manga-orchestrator` and reproduced every baseline number.
Both files must be inside the container and a rebuild drops them, recipe in `AGENTS.md`.
## Next command
The fifth GPU cycle, unchanged as the next pipeline work, and now measurable on both sides. The GPU is
idle. The workers are **down**, so it starts with `./start_workers.sh` then `./check_stale.sh`.
`slice_webtoon` changed, so the re-crop is now mandatory rather than merely planned, and
**clear `s3://panels/<manga>/<chapter>/panels/` first** or `crop_webtoon` keeps the old images.
Run the audit after the cycle and compare against `= baseline`. Expect the panel count to drop and one
panel to grow by 62px. A row printed as `unmatched` means the detection moved more than half its area.