# 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 ```bash .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. ```bash 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.