# HANDOFF, 2026-08-12/13 (seventh session) Live state is in `NEXT.md`. This file is only what this session did. The previous handoff is in `JOURNAL.md`. ## Asked "go" on item 1 of the previous plan, then a fourth GPU cycle. Then "commit and let's figure out how to deal with the 2b1b". Then a long architecture message, "mind turning the architecture in docs?", plus a question about panel merging before cropping. Then "well, I'd like the merge to be wired actually. and then 3 of your fixes." ## Result Item 1 written, run on a GPU, committed. Naming diagnosed from a real dialogue run and three fixes written against it. The crop merge wired. `ARCHITECTURE.md` written. Nothing has run on a GPU since 20:25 UTC. ## Committed and proven on a GPU `a386e9d` here, `2daaa84` in the orchestrator. **The resolver gallery is the live cast, not cosine's top-k** (`decisions/identity-bbox.md#cast-is-the-gallery`). `tracklets.cast_gallery` builds it from `get_known_characters`, gender-compatible, named first, `GALLERY_CAP = 10`, re-read per tracklet. The `if s.get("candidates")` guard is gone, so a crop with an empty cosine top-k now reaches the resolver. `worker_vision.REF_BUDGET = 12` spreads reference images, `max(1, min(3, 12 // n))` apiece. Fourth cycle, 19:44-19:52 UTC: vision 116/116 3m55s, identity 116/116 2m44s, reconcile 20/20 44s. Ran with the span cap and `GENERIC` tokenizer, which had never touched a GPU either. | metric | 18:07 run | 19:44 run | | --- | --- | --- | | detections | 119 | 119 | | assignments | 68 | 60 | | coverage | 57% | 50% | | tracklets / crops | 12 / 64 | 33 / 72 | | lead's assignments | 36 | 16 | | characters after reconcile | 18 | 14 | | minted / cleared | -- | 10 / 12 | Coverage fell because gemma clears 12 crops instead of naming them wrongly. Checked by eye and confirmed by the user. The lead's 16 are 14 him plus 2 art-in-art. `character_2b1b12a1` holds 13, all correct. `character_f0d4e901` holds 9, of which 2 are `2b1b12a1`. ## Measured, then fixed Dialogue ran 116/116 in 5m57s at 20:19 UTC to test the naming path. Six claims, three defects: ``` p040 character_2b1b12a1 "Choi Haeseon" caption 1.00 -> NOT promoted p010 character_b1dd5659 "Lim Seonho" caption 1.00 -> conflict flag p047 character_b1dd5659 "Seonho" address 0.90 -> conflict flag p011 character_f0d4e901 "Seonho" address 1.00 -> PROMOTED (wrong body) p026 character_f0d4e901 "Seonho" address 1.00 -> PROMOTED (wrong body) p110 character_028d4a49 "Haeseon" address 1.00 -> already named ``` ## Written, tested, NOT run on a GPU Orchestrator, committed `2927927`, `db.add_name_claim` + `decisions/identity-naming.md`: - `alias_groups`: one name's word set inside another's is the same name, longer wins - `STRONG_EVIDENCE` gains `caption` at confidence >= 0.9 - a name held by another live character refuses to promote, files `name-already-taken` Here, committed `97cb483`: - `merge_faceless_captions` wired into both crop endpoints. It existed and was never called. - `ARCHITECTURE.md`, the target shape from the user's design, each section carrying what exists today. ## Not started - **The head/body split is not fixed.** The wired merge only folds a fragment with text and no face. A body fragment has no dialogue, so `_merge_plan` leaves it solo. No evidence gathered on how often it happens. - The three cheap items from `ARCHITECTURE.md`: a `plane` field per detection, same-panel co-presence as a weak cannot-link, `offscreen` as a fourth `speaker_ref` kind. - `caveats/audit-open.md#gallery-cap-drops-the-unnamed`: the cap fired at `p097` (16 -> 10) and `p109` (11 -> 10) and dropped exactly the freshly minted anonymous rows. ## Checks ```bash .venv/bin/python worker_vision.py # ok, including the reference-budget asserts .venv/bin/python worker_crop.py # ok ./check_stale.sh # exit 0 before the cycle /usr/bin/ssh kami@192.168.1.104 "cd /home/kami/docker-apps/manga-infra/orchestrator && python3 tracklets.py && python3 test_name_binding.py && python3 -m pytest -q --ignore=test_api.py" # 121 passed ``` Each new assert was confirmed to fail with its fix disabled. ## Next command Re-crop and run the fifth cycle. **Clear the panels prefix first** or the merge will not take effect: `crop_webtoon` skips an upload when the key exists. ```bash cd /home/kami/Programs/n8n-worker && ./check_stale.sh # restart crop, it is stale after the wiring /usr/bin/ssh kami@192.168.1.104 "cd /home/kami/docker-apps/manga-infra/orchestrator && docker compose up -d --build orchestrator" J=778297bc-e7ce-439d-91b5-8a027060d17f; M=ef105a86-4b7e-4ac4-b45c-b7d83b8f5b5e; C=7c944dd4-e972-42c7-ba60-9f6939548e80 /usr/bin/ssh kami@192.168.1.104 "mc rm --recursive --force homesrv/panels/$M/$C/panels/" /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}'" # honour restart_identity_worker: 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\":\"crop\"}'" for S in crop vision identity reconcile dialogue; do /usr/bin/ssh kami@192.168.1.104 "curl -s --max-time 7200 -X POST http://127.0.0.1:9090/stage/run -H 'Content-Type: application/json' -d '{\"job_id\":\"$J\",\"stage\":\"$S\"}'"; done ``` Expect: fewer than 116 panels, `2b1b12a1` named `Choi Haeseon`, no `conflicting-name-claims` on the lead, and a `name-already-taken` flag where the female `Seonho` used to be. ## Traps confirmed or found - **`crop_webtoon` skips an upload when the key exists.** Right for a resume, silently wrong after any slicing change. Clear `s3://panels///panels/` before re-cropping. - Restart a worker with `tmux send-keys -t manga-workers: C-c`, then re-send the launch line from `start_workers.sh` with its `MIOPEN_ENV` prefix. A `pgrep` kill matches the calling shell. - `POST /characters/reset` returns `restart_identity_worker: true`. Honour it. - `docker compose up --build orchestrator` drops any `docker cp`'d script, `audit_registry.py` included. - A heredoc piped into `docker exec` over `/usr/bin/ssh` produces no output. `scp` the file, `docker cp` it, then run it. - `panel_order` and the panel filename differ by one: `panel_order` 10 is `p009.png`. - The contact-sheet script that found the identity errors is `sheet.py` in the session scratchpad, not committed. It reads `assigns.json` dumped from `identity_assignments` and pulls crops from `manga//characters/_crops/`.