Files
manga-recap-pipeline/caveats/speaker-attribution.md
T
kami a965077e6b Do not stamp som_face on a mark that paired to nobody
_set_of_mark labels a detected face `unknown` when gated pairing matched it to no
present character. An answer pointing at that mark grounds nothing, yet it carried
som_face, the highest-trust provenance. All 7 som_face lines in the first 36
panels of the rerun were this case. Same defect class as the fake tail label.

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

72 lines
4.2 KiB
Markdown

# speaker-attribution
Limits found by cross-checking the 2026-08-11 chapter run against the panel images.
## Nothing attributes a speaker in a multi-character panel {#tail-is-not-geometry}
The false `tail` label is gone (`decisions/speaker-attribution.md#no-fake-tail`). What replaced it is a
refusal, not an answer: with two or more characters present, every speech line now returns `unknown`.
On a chapter like this one that costs 31 of 81 speech lines their speaker. The narration then falls back
to a `generic-handle`. That is the honest floor, and it is not the fix.
The measurement that forced it, on job `778297bc`, chapter `7c944dd4`. Three two-character panels were
checked against the art. All three are wrong, each with the two speakers swapped:
| panel key | line | truth | pipeline |
| --- | --- | --- | --- |
| `p010.png` | "…definitely an Egen guy, Seonho!" | the woman | Seonho, the person addressed |
| `p010.png` | "Y-you think so?" | Seonho | Choi Haeseon |
| `p012.png` | "Want me to send you the link?" | the woman | the man |
| `p059.png` | "If team leader Choi says it, it must be true." | the man | Choi Haeseon |
The last row needs no image: the line refers to Choi in the third person and is attributed to Choi.
The grounded path exists and almost never fires. Only 2 of 81 speech lines got `som_face`, because
attribution marks need `face_detect` boxes that survive `_pair_faces_to_present`, and these webtoon
close-ups rarely produce them. Inference, not measured: the face detector was not instrumented.
`worker_vision.py:356` already carries the `ponytail:` note that multi-character attribution needs
per-balloon geometry. `bubble_detect.py:9` records that the `det`/`seg` heads carry balloon fill and
tail tips and are unused.
**Revisit trigger:** the share of narrated lines with a named speaker is the Phase 1 headline metric
(`ROADMAP.md`). The 30% read on this run counted attributions the sample says are wrong. The next run
will read lower and will be the first honest number. Raising it means binding a balloon to a speaker
by tail geometry, using the unused `det`/`seg` heads.
## One character id covers two different women {#identity-over-merge}
`character_afa7623b` is stored as "black bob, white sweater" and is assigned both to that person
(`p059.png`) and to the brown-bob green-top coworker (`p010.png`, `p012.png`). It took 25 of the 26
identity assignments in the chapter, against 113 detected people. Coverage is 23%.
**Revisit trigger:** any work on the identity Tier-2 decider. A single id absorbing a whole chapter is
the signature to watch for.
## The character registry carries five weeks of wrong names {#registry-pollution}
The registry holds 53 characters for manga `ef105a86`, 41 of them unnamed, with "Kei" three times and
"Kanade" twice. Kei, Kanade, Zen, Rico, K3, and Watanabe occur zero times in this chapter's text. Only
Haeseon and Seonho do. `/stage/clear` leaves the per-manga registry intact by design, so every rerun
inherits the whole pile.
Duplicate rows also make a correct name unresolvable. This manga holds `Choi Haeseon`, `Seonho` with
aliases `["Lim Seonho", "Seonho"]`, and a separate `Lim Seonho`. An answer of "Lim Seonho" matches two
rows, so `normalize_speaker` returns candidates and raises `ambiguous-speaker` instead of binding. The
pipeline read the name correctly and still cannot name the speaker.
**Revisit trigger:** before any run that is meant to produce a clean baseline. Either scope the
registry to a chapter or add a reviewed reset. Merging the duplicate rows needs the reversible-merge
design first (`caveats/audit-open.md#destructive-reconcile`).
## One invented word still halts the chapter {#one-word-halts-chapter}
The multi-word name failure is fixed (`decisions/speaker-attribution.md#multiword-cast-names`). The
blast radius it exposed is not. `run_stage_script` retries a rejected beat once, then raises, so a
single unsupported token ends the run at that beat. On job `778297bc` one of the 29 lost beats cited
`['Blur']`, an onomatopoeia the model invented. The verifier was right, and the whole chapter still
stopped.
**Revisit trigger:** the next `unsupported-proper-noun` halt that is a true positive. The likely answer
is to flag the beat for review and continue, which is `#136` gate work, not a verifier change.