Record that 2d's worked examples no longer exist
The registry reset deleted Lim Seonho and character_afa7623b, so there is nothing to merge or split until the rerun mints a new set. What was done instead is the safety net for that rerun, since reconcile runs inside it: a merge retires the losing row rather than deleting it, and records which assignments moved. Half-closes caveats/audit-open.md#destructive-reconcile. The unmerge path and the split stay unwritten on purpose, with the revisit trigger named. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+63
@@ -396,3 +396,66 @@ worker down. Both workers were dead for two minutes before `/health` caught it.
|
||||
|
||||
Not run: the GPU cycle. `has_face` and the NONE mint are both unproven on real panels and now land in the
|
||||
same run.
|
||||
|
||||
## 2026-08-12, fourth session, continued — identity 2c, extras versus cast
|
||||
|
||||
Asked: "fix extra-vs-cast?"
|
||||
|
||||
Traced the three places that read `vision["characters"]` raw before changing anything. That corrected an
|
||||
inference made earlier in the session. `build_scene` already drops an unassigned detection from
|
||||
`characters` and `present` (`worker_scene.py:63`), so extras never reached the cast list at all.
|
||||
|
||||
The leak was their ACTIONS. `actions` was built from every detection, and that list is what the script
|
||||
prompt renders and what the correctness verifier uses as evidence. So a background extra's "standing at the
|
||||
window" arrived as a fact about the panel with no character attached, and the verifier confirmed it,
|
||||
because the action really was in the blob. That is a second mechanism behind the invented-narration
|
||||
complaints in item 3, independent of the model inventing anything.
|
||||
|
||||
Gated two consumers on `has_face is False`, matching the enrollment gate's semantics exactly:
|
||||
`worker_scene`'s `actions`/`action`, and `service._beat`, which picks the director's "who" from the first
|
||||
three detections and falls back to an action when a detection has no name.
|
||||
|
||||
Left `service._present_characters` ungated on purpose. It builds the dialogue stage's candidate speakers
|
||||
and the set-of-mark boxes. An extra picked as speaker already resolves to unknown, not to a wrong name, so
|
||||
the failure is contained. And the gate's cost lands hardest there, since a character drawn from behind has
|
||||
no face box and gating would delete a real speaker from the only list that can attribute their line.
|
||||
`decisions/identity-bbox.md#extras-gate-consumers`.
|
||||
|
||||
Checks: `worker_scene self-check ok` with three cases (cast action survives, faceless dropped, missing key
|
||||
survives), 115 passed on homesrv. Deployed: image rebuilt, `_beat` verified inside the container, scene
|
||||
worker restarted, `./check_stale.sh` clean. Committed `ca46617` and `8b27aec`.
|
||||
|
||||
Still not run on a GPU. Three changes now ride the same cycle: `has_face`, the NONE mint, and this.
|
||||
|
||||
## 2026-08-12, fourth session, continued — identity 2d, merge and split
|
||||
|
||||
Asked: "2d? merge and split?"
|
||||
|
||||
Checked the registry before planning anything, and 2d as written is stale. The registry reset earlier today
|
||||
deleted both worked examples. There is no `Lim Seonho` to merge into, `character_afa7623b` does not exist,
|
||||
and the current registry is 8 rows with one named character (`Seonho`). Nothing to merge or split until the
|
||||
rerun mints a new set.
|
||||
|
||||
So the useful work was the safety net for that rerun, since `reconcile` runs inside it. The caveat's cost
|
||||
line was the reason: one bad merge was unrecoverable without rebaselining the whole manga, and the cycle
|
||||
about to run includes a merge pass over embeddings nobody has seen yet.
|
||||
|
||||
`merge_characters` no longer deletes the loser. It sets `merged_into = keeper`, so the row keeps its
|
||||
embedding, description and gender, and it stamps every repointed assignment with
|
||||
`method = merged_from:<loser_id>` in `identity_assignment_sources`. That reuses a free-form column on a
|
||||
table that already existed rather than adding a merge log. `source` is left alone, so a reviewer's `manual`
|
||||
assignment keeps its veto in `assign_identity` after being repointed.
|
||||
|
||||
Roster readers filter `merged_into IS NULL`, including the name-dedup in `create_character`, which would
|
||||
otherwise fold new crops back into a character reconcile had retired. Lookup by id does not filter, because
|
||||
an assignment or a narration reference may still point at a merged id.
|
||||
|
||||
Two existing assertions asserted the old destructive behaviour (`test_db.py:235`, `test_merge_refs.py:37`)
|
||||
and were rewritten, not deleted: the invariant changed on purpose.
|
||||
|
||||
Checks: 116 passed on homesrv, up from 115. Additive `ALTER TABLE` through the existing `init_db` migration
|
||||
block, verified on the live database (`merged_into` present, 0 rows merged). Committed `00096cc`.
|
||||
|
||||
Deliberately not built: the unmerge path and the split. No wrong merge has been observed since the crops
|
||||
were fixed, so the consumer of these records waits for one. The forward case is partly covered by 2b, since
|
||||
a resolver NONE now mints instead of folding a stranger into the nearest match.
|
||||
|
||||
Reference in New Issue
Block a user