Files
manga-recap-pipeline/HANDOFF.md
T
kami 491dad1c67 Ship each crop's embedding so a resolver NONE can mint
Two identity fixes, neither yet run on a GPU.

has_face, the extras gate: fixing the bbox coordinate space made extras worse,
because crops finally landed on their subjects and a background extra bound to
the lead at 1.00. /vision stamps has_face per character using face_detect and
_pair_faces_to_present, so containment and its margin match the speaker path.
Identity skips has_face is False before it crops or embeds. Fails open on a
missing or raising detector, and gates on `is False` so an older vision blob
behaves as before.

The NONE mint: /identity/resolve now writes each crop's embedding to the crop's
key with a .npy suffix and returns emb_uri. The orchestrator cannot compute an
embedding of its own (siglip and gemma cannot both be resident), which is why it
was clearing a deliberate NONE instead of minting an anonymous character.

Also: audit_registry.py, and the tmux respawn-window trap, which
leaves a bare shell rather than re-running the window command.

decisions/identity-bbox.md#face-gates-enrollment
decisions/identity-bbox.md#none-mints-an-anonymous-character

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 19:08:38 +04:00

5.8 KiB

HANDOFF, 2026-08-12 (third session of the day)

Live state is in NEXT.md. This file is only what this session did. The previous handoff is in JOURNAL.md.

Asked

Move on from the chapter rebuild. Scope chosen mid-session: reset the registry, rerun vision, identity and reconcile only, inspect, then decide about the ~80 minutes downstream. After the inspection the user chose to fix extras-versus-cast before running downstream.

Result

The identity rebaseline ran and the numbers moved a long way. One code change on top of it is written and self-checked but not yet proven on a GPU run.

                        before        stale run      after
x2 past panel width     47/113        46/110         0/110
coords exactly on 1000  21            27             1
max y2                  1000          1000           2307
characters              19            8              8
coverage                26/113 = 23%  77/110 = 70%   77/110 = 70%
top character's share   96% Haeseon   47%            47%

Choi Haeseon, which held 25 of 26 assignments, is gone from the registry. Panel 7 against the art:

box who before after
[457, 657, 642, 937] Seonho, foreground nothing Seonho
[669, 591, 763, 822] the colleague, unnamed in the story Choi Haeseon 0.9 character_f7a4fd
[428, 386, 496, 526] background extra extra as cast none
[34, 414, 122, 564] background extra extra as cast none
[498, 386, 568, 533] background extra extra as cast character_d72710 0.94
[31, 554, 94, 728] background extra Lim Seonho Seonho 1.00

The run that did not count

The first full cycle completed 116/116/20 and reproduced the defect exactly. The fix was not wrong, it was not loaded:

vision worker started                 12:00:09
worker_vision.py modified             12:11:35
8113bdf, carrying _bbox_to_pixels      12:16:22

Python binds a module once, at process start. The stage reported success and the orchestrator recorded no error. Cost: one vision + identity + reconcile cycle and a second registry reset to undo the 8 characters it minted. decisions/identity-bbox.md#stale-worker-invalidates.

./check_stale.sh now compares every running worker's start time against its module mtime and exits non-zero. Mutation-tested. Run it before any stage run meant to prove a code change.

Written this session

  • db.reset_registry + POST /characters/reset (confirm=true). /stage/clear spares characters by design (db.py:790), so nothing could rebaseline the registry. Also clears identity_assignment_sources, which no stage clear touches and where a leftover manual row makes assign_identity refuse the next model assignment (db.py:663). Covered by test_db.py:TestResetRegistry. Orchestrator, committed on homesrv, image rebuilt.
  • check_stale.sh, audit_registry.py (runs inside manga-orchestrator, already docker cp'd).
  • has_face, the extras gate. This is the part not yet proven. Fixing the coordinate space made extras worse. With crops finally on their subjects, an extra bound to the lead at 1.00. /vision stamps has_face per character using face_detect + _pair_faces_to_present, so containment and its margin are the rules the speaker path already uses. worker_identity.py skips has_face is False before it crops or embeds. Fails open on a missing or raising detector, and gates on is False so an older vision blob behaves as before. decisions/identity-bbox.md#face-gates-enrollment.

Checks

.venv/bin/python worker_vision.py      # includes the has_face gate + both fail-open paths
.venv/bin/python worker_identity.py
./check_stale.sh                       # exits non-zero if a worker predates its file
cd /home/kami/docker-apps/manga-infra/orchestrator && python3 -m pytest -q --ignore=test_api.py   # 115 passed, on homesrv

Next command

The has_face gate has never run on a GPU. Restart vision and identity, reset, rerun, and check whether the two wrong bindings on panel 7 disappear without taking Seonho with them.

cd /home/kami/Programs/n8n-worker && ./check_stale.sh     # restart anything it flags
J=778297bc-e7ce-439d-91b5-8a027060d17f; M=ef105a86-4b7e-4ac4-b45c-b7d83b8f5b5e
/usr/bin/ssh kami@192.168.1.104 "curl -s -X POST http://127.0.0.1:9090/characters/reset -H 'Content-Type: application/json' -d '{\"manga_id\":\"$M\",\"confirm\":true}'"
/usr/bin/ssh kami@192.168.1.104 "curl -s -X POST http://127.0.0.1:9090/stage/clear -H 'Content-Type: application/json' -d '{\"job_id\":\"$J\",\"stage\":\"vision\"}'"
for S in vision identity reconcile; do /usr/bin/ssh kami@192.168.1.104 "curl -s --max-time 5400 -X POST http://127.0.0.1:9090/stage/run -H 'Content-Type: application/json' -d '{\"job_id\":\"$J\",\"stage\":\"$S\"}'"; done
/usr/bin/ssh kami@192.168.1.104 "docker exec manga-orchestrator python3 /app/audit_registry.py 7c944dd4-e972-42c7-ba60-9f6939548e80 6"

Watch for coverage collapsing. 70% is the number to beat. A gate that abstains too hard shows up there before it shows up on panel 7. Restart the identity worker after every reset: it caches the known list in-process and only invalidates on enrollment.

Gone

The rebuilt chapter.mp4 and all 49 clips were deleted by the cascade from /stage/clear vision. The user chose not to keep a copy. Nothing downstream of reconcile exists for this job now.

Traps confirmed again

  • A stage reporting completed 116/116 says the code ran, not that the current code ran.
  • The SSHFS mount at /mnt/server/home/kami was absent and needed remounting by the user, since the mountpoint needs root.
  • The orchestrator image bakes its source. Editing the repo on homesrv does nothing until docker compose up -d --build orchestrator.
  • rtk grep searches files, not stdin. Piping into it silently searches the repo instead.