Draft v1 - 2026-05-22 - read-only analysis plus implementation plan
C10 Screen Presence Reconciliation
이 문서는 S15_Shot5에서 드러난 visible_entity_ids와
shot_staging.character_angles의 발산을 C10 장기 방향과 연결해 정리한다.
목적은 당장 막힌 scene_detail contract violation을 작은 실험으로 해소하면서,
향후 중간 상태 구조화와 agentic editing layer가 어떤 데이터 모델을 필요로 하는지 판단하는 것이다.
Executive Verdict
Phase 0 + Phase 1을 먼저 진행하는 방향은 맞다. 단, 이번 작업은 새 schema를 먼저 추가하는 C10 본체가 아니라 "기존 구조 신호를 이용한 deterministic reconciliation" 실험으로 제한한다.
즉시 수정의 핵심은 다음 한 줄이다.
C## is in shot_director.visible_entity_ids AND shot_staging.character_angles is non-empty AND C## is absent from shot_staging.character_angles AND C## is not the POV character AND camera_direction has explicit off-screen language => downgrade that subject's identity policy to generic_descriptor_allowed inside build_render_prompt_card() Name proximity near the off-screen phrase is confidence/provenance only, not a hard gate.
이 방식은 C01을 강제로 T2I prompt에 넣게 하지 않는다. 대신 "후보 집합에는 있으나 실제 프레임에는 없는/부재로 연출된 인물"로 조정해, LLM과 validator가 같은 정책을 보게 한다.
Observed Failure
| Item | Evidence | Meaning |
|---|---|---|
| Failed step | scene_detail, S15_Shot5 |
LLM omitted C01, validator raised subject_reference_policy.base_id_missing. |
| shot_director | visible_entity_ids=["C02","C01"], description says Hyesu shouts toward Suriyoung's back. |
C01 was treated as part of the shot-level subject set. |
| shot_staging | camera_direction says "off-screen direction where 수리영 has run" and "the absence". |
Later staging describes C01 as absent/off-screen, not drawable foreground/background identity. |
| character_angles | Only C02/Hyesu appears. C01/Suriyoung is absent. | Given schema wording, membership is the usable in-frame signal. |
| subject_reference_policy | [] |
Falls back to DEFAULT_POLICY=id_and_outlook_required, so C01 base ID becomes mandatory. |
Operational note: current diagnosis must use live DB/checkpoints/artifacts specified by the run. Local SQLite files are not a source of truth for this project unless explicitly stated otherwise.
Code And Prompt Evidence
| Evidence | Path | Impact |
|---|---|---|
| Default subject policy | backend/app/core/subject_reference_policy.py:28 |
Missing policy defaults to id_and_outlook_required. |
| Generic policy behavior | backend/app/core/subject_reference_policy.py:53-55 |
generic_descriptor_allowed disables base/outlook requirements. |
| Forward base-ID validator | backend/app/core/visible_entities_validator.py:469-488 |
Raises only when the subject's policy has base_required=True. |
| Canonical-name validator | backend/app/core/visible_entities_validator.py:530-557 |
Even after downgrade, using "수리영" without an ID can still fail. Phase 1 must account for this. |
| Card builder choke point | backend/app/core/steps/render_prompt_card.py:3514-3539 |
Policy override belongs before normalize_subject_reference_policy_items(). |
| Name map threading gap | backend/app/core/steps/render_prompt_card.py:3451-3475 |
build_render_prompt_card() currently has no name_by_short_id input, so Phase 1 must thread the map through card inputs. |
| Name map source | backend/app/core/steps/scene_context_loader.py:71-72 |
SceneContextLoader already prebuilds ctx.name_by_short_id, so no worker-thread DB query is needed. |
| Asset requirements consumes policy map | backend/app/core/steps/render_prompt_card.py:3569-3577 |
Override before this point keeps reference requirements aligned. |
| Shot staging schema | prompts/_base/shot_staging/15.202605201730/schema.json:21-45 |
character_angles is for visible characters, excluding POV. |
| Gaze off-screen is not visibility | prompts/_base/shot_staging/15.202605201730/schema.json:30-37 |
off_screen means eye direction outside frame, not subject outside frame. |
| Current Path 1 miss | backend/app/modules/pipeline/shot_visibility.py:316-395 |
Requires looks_at_character and gaze_target_id, so S15 misses. |
| Current Path 2 only logs | backend/app/core/steps/scene_context_loader.py:493-504 |
S15-style proximity drift is diagnostic only and cannot reconcile policy. |
What Must Not Be Done
- Do not treat
gaze_direction_kind="off_screen"as an off-screen subject signal. - Do not add
no_id_requirednow. It duplicates validator behavior ofgeneric_descriptor_allowed. - Do not mutate staging only inside
detail_steps._analyze_one. Verify/recompute paths would not necessarily see the same policy. - Do not run the detector only at call sites and pass a precomputed ID set into the builder. That risks silent skips when a call path is missed.
- Do not hard-block this case in
SceneContextLoaderfirst. This is a resolvable producer divergence, not a fatal corrupt checkpoint. - Do not introduce VLM or image-based judgment for this fix. The signal is already in structured/text checkpoint data.
Immediate Files
- Phase 0/1 execution plan: concrete implementation sequence, tests, gates, and risk controls.
- C10 roadmap: how this experiment informs the longer structured-state and agentic editing direction.