# Track B Semantic Debt Roadmap (v1)

Date: 2026-05-16
Status: Routing/boundary spec — implementation 0
Supersedes: none (5월 14일 visual-reliability-routing-map.md = Track A 9-case 영역, 본 문서 = Track B 의미 판단 debt 영역)

## 1. Purpose + Scope

### 1.1 본 문서의 본질

본 spec 는 **routing/boundary spec** 이며, 구현 spec 아님:
- code 변경 0
- 12 area (8 사용자/Codex + 4 신규 보강) 의 scope / audit row / fix direction / cost / dependency / risk 명시
- Tier 1/2/3 우선순위 + cross-cutting 결함 그룹
- closed area 재분류 정책 (5월 14일 audit 의 잘못된 "closed" 분류 정정)
- 다음 area 진입 시 boundary 명시 의무

### 1.2 Track 구분

본 프로젝트의 visual reliability hardening 은 두 **independent track** 으로 분리:

**Track A — 9-case visual failure remediation** (`docs/superpowers/specs/2026-05-14-visual-reliability-routing-map.md`):
- 9 visual failure case 의 책임 경계 + future area
- 4 future area: `area-character-pose-state-reference` / `area-large-prop-vehicle-identity` / `area-information-surface` / `area-id-policy-framing-extension`
- 각 case 는 image-level 결함 분류

**Track B — semantic 판단 debt 제거** (본 문서):
- code regex / substring / closed-list 기반 의미 판단 → LLM emit structured SOT 전환
- 4 강제 gate ([[feedback_llm_based_judgment]]) — Semantic Regex Ban / Prompt Closed-List Ban / Structured SOT Required / No Silent Fallback
- 8 사용자 area + 4 신규 보강 = 12 area

**현재 상태**: Track A 일시 중지, Track B 진행 중 (사용자 결정).

두 트랙이 만나는 지점: `area-id-policy-framing-extension` (Track A) ⊃ `body_part_focus / focus_scope` (Track B Area #1 의 일부).

### 1.3 Audit Sources

본 문서의 input:

| Source | 위치 | 결함 수 | 발견 시점 |
|---|---|---|---|
| 1차 — Codex code-side | `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-map.md` | 18 (P0-1~P0-7 + P1-1~P1-6 + P2-1~P2-6) | 2026-05-13 |
| 1차 — Codex prompt-side | `docs/visual-reliability-audit/2026-05-14-prompt-hygiene-v1-spec.md` | 11 (P-1~P-3 + §6 도메인 5) | 2026-05-13 |
| 2차 — 사용자 인벤토리 | external memory `session_20260514_semantic_regex_prompt_pollution_pivot.md` | 32 (code 18 + prompt 11 + LLM 3) | 2026-05-14 |
| 3차 — 본 audit (5월 14일) | `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/` (5 file) | 32 + 신규 19 (#19 + ADD-6~11 + L-4~L-7) | 2026-05-15 |
| **4차 — 전수조사 LLM audit** | **`backend/tests/_audit_outputs/semantic_string_debt/full_20260516_0105/` (6 file, untracked)** | **194 (production 94 + active prompt 100, 양 tsv 모두 header 없이 첫 줄부터 data row)** | **2026-05-16** |
| 4차 — Codex 8-area roadmap | (외부, 사용자 메시지로 전달) | 8 area + schema 예시 | 2026-05-16 |

**4차 superset**: 5월 14일 audit (51 항목) 의 약 4배. 신규 발견 영역 7+:
- `background_chain_planning / background_classify / floor_plan_prompt` (A001-A005, A031)
- `shot_extract / shot_validator` 시간 연결어 closed list (A064, A068, A082)
- `detail_steps` 색감-감정 매핑 (P034)
- `prompt_service` `_classify_label` 9-branch substring (P084-P087)
- `scene_extractor_v2` split anchor exact substring (P078-P080)
- `scene_director` closed list (A047) — 영상통화/CCTV/홀로그램/원격 조종/빙의
- `visual_world_rules` schema description vs system.md enum drift (A096-A100)

**4차 반전**: `semantic_contract_router.py` (Patch B-min closed area, commit `f2682d7`) 의 `IMMOBILIZED_GAZE = frozenset({"dead", "unconscious", "severely_injured"})` 가 본 audit 에서 **G1 (gaze_target overload)** 의 핵심 site (P066) 로 재발견. 5월 14일 audit 의 "closed area do-not-touch" 분류 잘못. 본 문서 §11 closed area 재분류 참조.

## 2. Closed Area (이미 완료, 4 area)

본 area 진입 시 절대 변경 X, 단 §11 의 재분류 항목은 예외.

| # | Area | Closure commit | 결과 |
|---|---|---|---|
| C-1 | Prompt Hygiene v1 | `91d1dfd` (push, 10 commit) | P-2 / P-3 / P-3b / P-4 / P-5 / P-6 (line 45-78 만) fix. P-1 (`entity_extractor_legacy`) orphan 분리. |
| C-2 | framing_scale enum SOT v1 | `53dd180` (push, 25 commit) | shot_staging v11 + framing_scale.py helper + close × ref_usage matrix. Codex APPROVED_WITH_MINOR. |
| C-3 | close × ref_usage matrix v1 | `53dd180` 의 일부 (`scene_reference_service.py:883` 현재 working tree, 도입 commit 시점 line 별도) | close + zoom_in_detail allow / 그 외 RefContractError. |
| C-4 | zoom_in_detail source provenance | `772fcd4` (push, 18 commit) | helper 6-step + Layer 3 invariant + coordinator `bytes_source_kind` annotator. Codex iter 1 fix-up 1. |

## 3. 결함 분포 정량 분석

### 3.1 Production code (94 finding)

| Verdict | Count | 비율 |
|---|---|---|
| CONFIRMED | 58 | 61.7% |
| LOW_SCHEMA_OR_CONTRACT | 26 | 27.7% |
| FP_OR_ALLOWED | 8 | 8.5% |
| LEGACY_OR_ORPHAN | 2 | 2.1% |

| Category | Count | 본질 |
|---|---|---|
| semantic_string_judgment | **36** | open-world semantic 을 code regex/substring 으로 판단 (gate 1 위반) |
| schema_or_enum_drift | 20 | enum 강제 안 됨 (description-only / type:string drift) |
| blind_string_mutation | **18** | `.replace()` / `re.sub()` 가 prompt body 에 작용 (gate 4 silent SOT 변조) |
| scenario_dependent_prompt | 13 | code 안 한국어 시나리오 leak / 작품 고유명사 / 도메인 nomenclature |
| llm_closed_list_instruction | 5 | code 가 closed phrase list 정의 (LLM-facing) |
| scenario_dependent_code | 1 | code 분기 자체가 시나리오 의존 |

### 3.2 Active prompt (100 finding)

| Verdict | Count | 비율 |
|---|---|---|
| CONFIRMED | 78 | 78.0% |
| LOW_SCHEMA_OR_CONTRACT | 20 | 20.0% |
| LEGACY_OR_ORPHAN | 2 | 2.0% |

| Category | Count | 본질 |
|---|---|---|
| llm_closed_list_instruction | **39** | LLM 에 closed phrase list 가르침 (gate 2 위반) |
| scenario_dependent_prompt | **21** | 시나리오 leak (Hygiene v1 closure 후에도 21 site 잔존) |
| semantic_string_judgment | 17 | LLM 에게 string pattern 매칭 instruction (gate 1 LLM-side counterpart) |
| blind_string_mutation | 12 | LLM 에게 target/suggestion replace 가르침 (gate 4 LLM-side counterpart) |
| schema_or_enum_drift | 10 | schema description vs prompt vs code drift |

### 3.3 종합

- **194 notable finding** (production 94 + prompt 100, 양 tsv 모두 header 없이 first-line data)
- **136 CONFIRMED** = 즉시 fix 대상 (production 58 + prompt 78)
- **46 LOW_SCHEMA** = 후순위 (post Tier 1)
- 5월 14일 audit (51 항목) 대비 **약 4배 superset**

## 4. Cross-cutting 결함 그룹 (G1-G6)

8-area roadmap 으로 mapping 되기 전, 결함의 본질적 그룹화:

### 4.1 G1 — `gaze_target` field overload (6+ code site + 2 prompt site)

| Site | row ID | snippet |
|---|---|---|
| `backend/app/core/asset_readiness.py:435-440` | P001 | `gaze in ("dead", "severely_injured", "unconscious")` |
| `backend/app/core/steps/image_steps.py:665-666` | P013 | `gaze = ca.get("gaze_target", "") ... if gaze in self.STATE_DESCRIPTIONS` |
| `backend/app/core/steps/image_steps.py:638-642` | P014 | `STATE_DESCRIPTIONS = { "dead": "...", "severely_injured": "...", "unconscious": "..." }` |
| `backend/app/core/steps/detail_steps.py:251-310` | P031 | `_STATE_VARIANT_GAZE_VALUES = ("unconscious", "dead", "severely_injured")` |
| `backend/app/modules/semantic_contract_router.py:22-107` | P066 | `IMMOBILIZED_GAZE: frozenset[str] = frozenset({"dead", "unconscious", "severely_injured"})` |
| `backend/app/services/scene_reference_service.py:932-988` | P091 | `ca.get("gaze_target", "") in ("unconscious", "dead", "severely_injured")` |
| `prompts/_base/shot_staging/11.../schema.json:30` | A074 | `gaze_target: ..., 'unconscious', 'dead', 'severely_injured'` (description, non-enforced) |
| `prompts/_base/shot_staging/11.../system.md:121-123` | A077 | `눈을 감고 있거나 의식이 없으면: "closed" 또는 "unconscious"` |

**본질**: `gaze_target` 가 시선 방향 (`looks_at_X / off_screen / camera_facing / closed`) + character state (`unconscious / dead / severely_injured`) **두 차원 overload**. shot_staging schema description 자체가 두 의미 mix. 5+ consumer 가 state token 비교로 routing.

**Patch B-min closure (commit `f2682d7`) 의 한계**: Patch B-min 가 IMMOBILIZED_GAZE 를 활용하는 wiring (sanitizer 우회) 추가. 단 G1 의 본체 (overload 자체) 는 미해결. 5월 14일 audit 가 `semantic_contract_router` 를 closed-area 로 잘못 분류.

**Fix direction** (Area #2 spec commit `30b62f8`+ 안 closure — 2026-05-17, final shape):
- `gaze_direction_kind` enum (closed-set, 8-entry: `camera / down / up / distant / closed_eyes / off_screen / looks_at_character / looks_at_object`) — 시선 방향 종류만 (Q1 closure: `closed`→`closed_eyes`, `looks_at_entity`→`looks_at_character`)
- `gaze_target_id` registered short_id only (`^C\d{2,3}$` character / `^(P|B)\d{2,3}$` object, `gaze_direction_kind == "looks_at_*"` 시 required, Q7 closure — free string / O## outlook / canonical name / noun fallback 모두 금지)
- `subject_state` enum (4-entry: `alive / unconscious / dead / severely_injured`) — gaze 와 별개 차원 (Q2 closure: `alive_active`/`alive_immobilized` 폐기, immobility = 별도 차원 character_state element)

**enum / freeform 혼합 차단** — `looks_at_<id>` 같이 enum 안에 dynamic id placeholder 포함 절대 금지 (gate 1/2 위반 risk). 관계 종류는 enum, 대상 ID 는 별도 field.

consumer 8 site enum re-read (W1-W9 closure — semantic_contract_router + asset_readiness + image_steps + detail_steps + scene_consistency_step + scene_reference_service + render_prompt_card + shot_visibility Path 1).

### 4.2 G2 — ID/outlook reference policy (partial-subject rendering) — body_part_focus / face close-up 은 symptom (4 code site + 6 prompt site)

| Site | row ID | snippet |
|---|---|---|
| `backend/app/core/visible_entities_validator.py:139-161` | P035 | `_FACE_CLOSE_UP_PATTERNS` (2 regex) + `_is_face_close_up()` |
| `backend/app/core/visible_entities_validator.py:212-231` | P036 | `t.lower() in prompt_lower` (body_part_focus_rule.trigger_phrases) |
| `backend/app/core/steps/render_prompt_card.py:1056-1075` | P023 | `body_part_focus_rule.trigger_phrases = list(_ID_BODY_PART_TRIGGERS)` (4-tuple) + `close_framing_face_phrasing` (6 forbidden + 4 recommended) |
| `backend/app/core/steps/render_prompt_card.py:1187-1191` | P023 | `"triggered by 'focus on / close on / tight on / detail on' phrasing"` |
| `backend/app/core/steps/render_prompt_card.py:1494-1498` | P022 | `"substitution": "replace the common-noun person reference inside fixed_elements[i].description ... with the matched C## or C##O##"` |
| `prompts/_base/scene_detail/24.../system.md:41-44` | A039 | `body_part_focus_rule.trigger_phrases (focus on / close on / tight on / detail on + body part)` |
| `prompts/_base/scene_detail/24.../system.md:45-48` | A039 | `close_framing_face_phrasing.forbidden_phrases` 6-entry inject |
| `prompts/_base/scene_detail/24.../system.md:119` | A040 | `fixed_elements[i].description 안 보통명사 인물 ... 매핑이 id_policy 안에 존재 시 해당 보통명사를 C##/C##O## 로 치환` |
| `prompts/_base/scene_detail/24.../system.md:357-361` | (A042 인접) | `**C## 규칙 준수**: 클로즈업에서는 C## 금지, 보통명사 "a hand", "fingers", "lips"로` + `**"Focus on C##'s <body part>" 패턴 절대 금지**` |
| `prompts/_base/scene_extractor_v2/18.../turn_scene_detail.md:34-38` | A053 | `얼굴/형태 식별 불가 인물 — short_id 사용 금지: 실루엣, 그림자, 창문 반사, 역광, 안개 속 등으로 인물의 얼굴이나 신체 형태를 식별할 수 없는 경우 C##O## short_id를 사용하지 마세요` |

**본질**: **subject 가 ID + outlook 으로 표현될 것인지, 보통명사 + descriptor 로 해야 할 것인지의 reference policy 결정** 이 prompt phrase substring (`focus on / close on`) + regex (`_FACE_CLOSE_UP_PATTERNS`) + LLM-facing closed list (6 forbidden phrasing) 로 분산. body part noun list (face / eye / hand / object / 손 / 발 / 입술) 가 prompt + code 양쪽 cross-cut — 단 noun list 자체가 결함 본체 아님 (**body part / face close-up 은 결함의 symptom, 본체 = reference policy SOT 부재**).

**Fix direction (Codex 사용자 안)**: `subject_reference_policy[]` LLM emit array 신설 — producer (LLM) 가 per-subject 결정:

```jsonc
{
  "subject_reference_policy": [
    {
      "subject_id": "C01",                    // C## or C##O##
      "outlook_id": "O02",                    // optional, ID 의 outlook 부분
      "render_scope": "whole_subject | partial_subject | obscured_subject | represented_subject",
      "reference_policy": "id_and_outlook | base_id_only | generic_descriptor",
      "reason": "..."                         // 사람 진단용 짧은 사유
    }
  ]
}
```

기본값 `id_and_outlook`. body part 일부 / 식별 불가 / 표현 surface 의 인물만 LLM 이 `generic_descriptor` 선언. code 는 substring 매칭 X, array 만 consume.

### 4.3 G3 — Visibility / physical presence routing (3 code site + 1 prompt dual-sync gap)

| Site | row ID | snippet |
|---|---|---|
| `backend/app/modules/pipeline/shot_visibility.py:37-445` | P063 | `_KOREAN_GAZE_STEMS, _KOREAN_FRAMING_NOUNS, _BODY_PART_NOUNS, _OFFSCREEN_PHRASES, detect_gaze_pattern_exclusions, detect_offscreen_drift` (6 lexicon + 4 regex) |
| `backend/app/modules/pipeline/shot_director.py:182-199` | P056 | `excluded_map = detect_gaze_pattern_exclusions(desc, name_to_char_id) ... ls["visible_entity_ids"] = [sid for sid in ve_before if sid not in excluded_ids]` (mutation) |
| `prompts/_base/shot_director/5.../system.md:31-49` | A076 | `Gaze-target close-up 패턴, 명시적 off-camera/off-screen phrase, 차단(blocking) 패턴, Reaction-only 패턴` (4 closed pattern bundle) |
| `prompts/_base/scene_extractor_v2/18.../turn_scene_detail.md:105-109` | A055 | `visible_entities 주의사항: 이 씬의 화면에 물리적으로 존재하는 대상만 넣으세요` (instruction) |

**자기 모순**: `shot_visibility.py:22-24` docstring 가 "auto-fix 안 함 — visible 리스트 변조가 silent SOT 변조" 명시하면서 `shot_director.py:188-190` 가 실제 변조.

**Dual-sync gap**: prompt instruct 하는 blocking 패턴 (`차단/막다/가리다/block/obstruct`) 이 code lexicon regex 부재 → silent miss.

**Fix direction**: shot_director schema 에 `visibility_decisions[]` LLM emit field 신설:

```jsonc
{
  "visibility_decisions": [
    {
      "entity_id": "C02",
      "frame_presence": "in_frame | off_frame | represented | mentioned_only",
      "physical_presence": "present | absent | represented",
      "reason": "..."
    }
  ]
}
```

code 는 visible 리스트를 mutate X, structured field 불일치만 fail-fast (또는 drift diagnostic). lexicon → drift diagnostic only (raise → log).

### 4.4 G4 — Blind string mutation (production 18 + prompt 12 = 30 site)

production 의 18 site 중 representative 10:
- `t2i_review.py:383-454` (P065) — target/suggestion `.replace()` (G6 = Area #6 본체)
- `outlook_dedup.py:288-300` (P053) — `t2i_v.replace(remove_marker, keep_marker)`
- `outlook_merger.py:97-105` (P051) — `t2i.replace(f"[{old_name}]", f"[{new_name}]")`
- `scene_validator.py:222-236` (P060) — `_clean_prompt` re.sub
- `scene_reference_service.py:111-130` (P090) — `_re.sub(pattern, replacement, ...)`
- `prompt_service.py:296-301` (P086) — `re.sub(r"In a (low angle|...)\s*(frame|composition|shot|view)\s*", "", cleaned)`
- `scene_extractor_v2.py:817-822` (P080) — `var["t2i_prompt"] = current_t2i.rstrip() + " " + suffix`
- `detail_steps.py:2865-2870` (P033) — `re.sub(r"focus on\s+'s", "focus on the figure's", prompt)`
- `entity_lister.py:199-371` (P050) — `type_prompt.replace("scene_count", "shot_count")`
- `coordinator.py:718-719` (P094) — `if shot_name and shot_name.lower() not in var_t2i.lower(): var_t2i = f"[Camera: {shot_name}] {var_t2i}"`

**일부는 closed-world (template substitution / marker rename)** — gate 1/4 위반 아님. 단 다수가 prompt body 에 작용 → over-replace risk.

**본 문서의 boundary**: G4 의 본체 = Area #6 (T2I review mutation redesign). 다른 site 는 area 별 spec 진입 시 case-by-case 판단 — closed-world template substitution (예: `entity_lister.replace("scene_count", "shot_count")`) 은 keep, prompt body mutation (예: `detail_steps.py:2865 focus on rewrite`) 은 폐기.

### 4.5 G5 — Scenario leak / 도메인 nomenclature 분산 (production 13 + prompt 21 = 34 site)

Hygiene v1 closure 후 잔존 + 신규 발견:

production 13 (representative 6):
- `image_steps.py:638-642` (P014/P015) — `STATE_DESCRIPTIONS` 한국 시나리오 prose
- `entity_extractor_v2_legacy.py:72` (P047) — `entity_type description = "character|location|prop"`
- `outlook_dedup.py:136-145` (P054) — `"검은정장1"과 "검은정장2"는 다를 수 있음`
- `scene_validator.py:144` (P059) — `"동녘(강의원)" 같은 표현 → 동녘의 몸만 있고, 강의원은 원격에서 조종 중`
- `reference_image_generator.py:61-98` (P070) — `"포박 상태", "현대 한국/근미래 한국 기준의 현실적 기본 복장"`
- `prompt_service.py:368-369` (P087) — `"'from the reference', 'from Reference image N' 같은 표현은 절대 새로 만들지 마세요 (phantom guard 충돌)"`

active prompt 21 (representative 8):
- `entity_all/4.../character.md:30` (A014) — `(이무기, 구미호, 요괴화, 뱀파이어 등)`
- `entity_extract_v4/8.../prop.md:22-26` (A016) — `수트, 우주복, 갑옷, 제복, 의상, 입는 장치나 로봇`
- `entity_extractor_v2/9.../turn0_style.md:17-23` (A022) — `조선시대, 한국 서울, 현대 한국 도시 + 미래 연구시설`
- `lvm_prompts/2.../style_rules_generator.md:5-9` (A028) — `조선시대, 한국/일본/미국, 한옥, 한복`
- `outlook_extractor/11.../phase2.md:12-13` (A029) — `변신, 갑옷 착용, 피의갑옷`
- `scene_director/8.../system.md:7-24` (A047) — `교차편집/몽타주... 영상통화, CCTV, 방송 화면, 홀로그램, VR, 원격 조종/빙의`
- `t2i_visual_converter/v4/system.md:46-49` (A093) — `지하 극저온 저장 시설, 투명 원통형 캡슐, 산업용 파이프, 발광 장치들이 늘어선 어두운 시설 복도`
- `visual_world_rules/6.../rules_schema.json:20` (A097) — `예: A의 영혼이 B의 몸에 전이된 경우 A는 물리적 존재가 아님`

**본 문서의 boundary**: Area #7 (Prompt hygiene v2) 의 본체. 단 별도 wave (코드 SOT 정리와 분리 — G5 는 prompt-only 가 90%).

### 4.6 G6 — closed-list LLM instruction (production 5 + prompt 39 = 44 site)

prompt 39 site 가 다수. 8-area cross-cut:
- shot_extract / shot_validator 시간 연결어 (A064, A068, A082) → **Area #9 (신규) Action segment SOT**
- background_chain / classify outdoor/indoor (A001-A005) → Area #8
- floor_plan_prompt 색깔 매핑 (A031) → Area #8
- scene_consistency 전신/zoom 기준 (A037) → Area #4
- scene_director 영상통화/CCTV/홀로그램 (A047) → Area #7 또는 visual_world_rules SOT
- shot_dependency_t2i schema enum drift (A063) → **Area #12 (신규)**
- shot_staging directionality_class (A078) — Area C closure 이미 존재, 본 문서 외
- t2i_review close-framing tag list (A088) → Area #6
- t2i_review phantom phrase list (A089) → Area #5
- variation_recommender hardcoded examples (A095) → Area #7
- visual_world_rules SOT vs schema description drift (A096-A100) → Area #7 또는 별도 visual_world_rules area

## 5. 12 Area 정의

### 5.1 Area #1 — ID/outlook reference policy SOT

**G2 본체**. body_part_focus 는 본 area 의 표면 일부.

| Field | Value |
|---|---|
| audit row | code: P022, P023, P035, P036 / prompt: A039, A040, A042, A053 |
| 본질 | "subject 가 ID + outlook 으로 표현되어야 하는가, 보통명사 + descriptor 로 해야 하는가" 결정의 SOT 분산 (prompt phrase + code regex + LLM-facing closed list) |
| Fix scope | shot_staging v12 에 `shots[].items.subject_reference_policy[]` LLM emit array 신설 (final shape: `subject_id` + `policy_type` (`identity_reference` only) + `policy` enum (`id_and_outlook_required` / `base_id_required` / `generic_descriptor_allowed`) + `reason`). consumer 5 site enum read via `subject_reference_policy.py` helper SOT. |
| 4 layer | Producer (shot_staging schema + system.md instruction; default_model = "gpt" / provider: openai — `step_manifest.py:591` 정합, CLAUDE.md "scene_director 만 gemini-pro 강제" 정합) / Helper (`subject_reference_policy.py` 신설) / Consumer (visible_entities_validator + render_prompt_card body_part_focus + scene_detail) / Prompt (scene_detail v25 + scene_extractor_v2 turn_scene_detail rewrite) |
| Cost | medium-large (4-6 commit + cascade) |
| Dependency | depends-on framing_scale enum SOT v1 (✓ closed). prerequisite of L-5 / #16 (audit `00-index.md` §6.3) |
| Closed area boundary | `keep_elements.py` (Area D-next-min closed) / `frame_spatial_contract.py` (closed) / `framing_scale.py` (closed C-2) — 모두 do-not-touch |
| Risk | scope creep (cross-cut 4 file). scope guard 의무: visible_entities_validator + render_prompt_card body_part_focus + scene_detail L-5 영역 + scene_extractor_v2 turn_scene_detail face-obscured 만. 다른 area 와 묶지 말 것. |
| 사용자 명시 보정 (2026-05-15) | enum noun-list 함정 차단 — `face / eye / hand / object` 같은 body part noun 금지. **intent / target class 추상화** (예: `whole_subject / partial_subject / obscured_subject / represented_subject` × `id_and_outlook / base_id_only / generic_descriptor`) |

**진입 시 spec 단계에서 결정 의무 5 항목**:
1. enum shape + cardinality (사용자 보정: intent class 추상화)
2. schema 위치 (shot_staging vs render_prompt_card vs id_policy)
3. required 조건 (close framing 한정 vs 모든 framing)
4. legacy fallback 정책 (`staging=None` 류 graceful 분기)
5. 제거 대상 정확한 grep list (`_FACE_CLOSE_UP_PATTERNS` callsite + L-5 영역 line 41-48 + line 119 + line 156 + line 357-361 + render_prompt_card body_part_focus_rule + close_framing_face_phrasing inject)

### 5.2 Area #2 — State / gaze 분리

**G1 본체**. 가장 광범위 cross-cut (6+ code site).

| Field | Value |
|---|---|
| audit row | code: P001, P013, P014, P015, P031, P066, P091 / prompt: A074, A077 |
| 본질 | `gaze_target` field 가 시선 방향 + character state 두 차원 overload. 5+ consumer 가 state token literal 비교. |
| Fix scope | shot_staging schema 분리 — `gaze_direction_kind` enum (closed-set, 8-entry) + `gaze_target_id` registered short_id only (`^C\d{2,3}$` character / `^(P|B)\d{2,3}$` object, conditional required when kind ∈ `looks_at_*`) + `subject_state` enum (4-entry) 3 field. enum / freeform 혼합 차단 (gate 1/2). consumer 8 site enum re-read. semantic_contract_router IMMOBILIZED_GAZE 폐기 (subject_state enum 직접 consume). |
| 4 layer | Producer (shot_staging v13 schema + system.md gaze section rewrite, 3 field 분리) / Helper 2 module (`subject_state.py` + `gaze_direction.py` 신설, closed-world enum + dispatch helper `resolve_visible_character_target`) / Consumer 8 site (semantic_contract_router + asset_readiness + image_steps + detail_steps + scene_consistency_step + scene_reference_service + render_prompt_card + shot_visibility Path 1) / Prompt (shot_staging v13 system.md gaze section rewrite) |
| Cost | **large** — cross-cut 가장 광범위 + Patch B-min closed area 재진입 |
| Dependency | independent. 단 shot_staging schema 변경 → Area #1 과 같은 producer (shot_staging) 손대므로 wave 분리 또는 묶음 결정 필요 (사용자 결정사항 §8.1) |
| Closed area boundary | semantic_contract_router (Patch B-min) 의 `IMMOBILIZED_GAZE` 폐기 = closure 메모 wording 정정 의무 (§11) |
| Risk | (a) Patch B-min 의 sanitizer wiring 영향 — `SEMANTIC_PRIMARY_MODES = ("none", "pose_locked", "immobilized")` enum 재정의 시 sanitizer constraints 영향. (b) STATE_DESCRIPTIONS dict (image_steps.py:638-642) 의 한국어 prose mapping → subject_state enum + helper `SUBJECT_STATE_VISUAL_DESCRIPTOR` / `get_visual_descriptor` SOT 이관 (Q6 closure, commit `c9b537a` W4) |

**진입 시 spec 단계에서 결정 의무** (Area #2 spec commit `30b62f8`+ 안 closure — 2026-05-17):
1. 3 field shape (Q1+Q2 closure):
   - `gaze_direction_kind` enum: `camera / down / up / distant / closed_eyes / off_screen / looks_at_character / looks_at_object` (8-entry, Q1 closure)
   - `gaze_target_id` shape: registered short_id only — `^C\d{2,3}$` (character) / `^(P|B)\d{2,3}$` (object), `gaze_direction_kind == "looks_at_*"` 시 required (Q7 closure)
   - `subject_state` enum: `alive / unconscious / dead / severely_injured` (4-entry, Q2 closure — alive_active/alive_immobilized 폐기, immobility 는 별도 차원)
2. backwards compat (Q4 closure): shot_staging **v13 신설** + 3-way sync (manifest 4→5 / registry 2.5.0→2.6.0 / prompt_dep v12→v13) — production fresh-run only, transition = schema_version mismatch fail-fast
3. semantic_contract_router 재진입 정책 (Q5 closure): IMMOBILIZED_GAZE 즉시 폐기 + Rule 1 source = `subject_state` + shot_visibility Path 1 흡수 (commit `861e9de` W3)
4. STATE_DESCRIPTIONS prose mapping 처리 (Q6 closure): helper `SUBJECT_STATE_VISUAL_DESCRIPTOR` constants (alive 제외, `get_visual_descriptor("alive") = AppError`) — image_steps.py:638-642 STATE_DESCRIPTIONS dict 폐기 (commit `c9b537a` W4)

### 5.3 Area #3 — Visibility / physical presence SOT

**G3 본체**. shot_director visible_entity_ids post-process mutation 폐기 + shot_director prompt v6 rewrite + scene_context_loader Path 1/2 split. visibility schema 신설은 v1 scope 밖(deferred by policy).

**Status: closed (2026-05-18, v1 closure)** — W0-W4 atomic execution 완료. W2 mutation 권한 박탈 (shot_director.py:182-201) + W1 prompt v6 (Korean grammar / 4 closed pattern bundle 제거) + W3 Path 1/2 함수 split (`detect_offscreen_drift_structured` blocking-eligible + `detect_offscreen_drift_proximity_diagnostic` diagnostic-only). schema 신설 (`visibility_decisions[]`) = deferred by policy (Q1 closure — schema 자동 진입 X, post-W2 logger.warning mismatch trigger 시 separate follow-up). closure verdict = "not demonstrably unsafe; post-W2 audit log monitoring required" (사용자 BLOCKING 조건 3 준수). §11 closed area table entry 참조.

| Field | Value |
|---|---|
| audit row | code: P056, P063 / prompt: A055, A076, A083 |
| 본질 | shot_visibility.py 6 lexicon + 4 regex 가 LLM emit visible_entity_ids 를 후처리 변조 (shot_director.py:188-190). 자기 모순 docstring (`shot_visibility.py:22-24`). |
| Fix scope | Area #3 v1: shot_director.py mutation 권한 박탈, 기존 excluded_offscreen_entity_ids audit field 유지, shot_visibility lexicon → diagnostic only, shot_director prompt v6로 4 closed pattern bundle 제거, scene_context_loader Path 1/2 split. visibility_decisions[] schema 신설은 post-closure trigger 시 separate follow-up only. |
| 4 layer | Producer (shot_director prompt v6 + existing visible_entity_ids SOT, schema unchanged) / Helper (shot_visibility diagnostics + split drift helpers) / Consumer (shot_director.py no mutation + scene_context_loader Path 1 raise / Path 2 warning) / Prompt (shot_director system.md v6 rewrite, 4 closed pattern bundle 폐기) |
| Cost | **large** — mutation 폐기 + lexicon → drift only + schema 신설 + dual-sync gap fix |
| Dependency | independent. 단 일부 G1 (gaze_target overload) 와 부분 겹침 — shot_director 가 gaze 사용 시 G2 후 진입 권장 (또는 분리 spec 으로 G2 결과 consume) |
| Closed area boundary | `shot_director frame-visible SOT closure` (commit `fe105ea`, 2026-05-13) — single LLM A1 통일 보존, mutation 폐기는 그 closure 의 **다음 step** 으로 정합 |
| Risk | (a) Korean lexicon 의 production miss / false-positive 빈도 verification 의무 (canary log) — drift diagnostic only 로 격하 시 false-fail 0 보장. (b) shot_director 가 G2 (gaze_target) 와 같은 producer — wave 분리 결정 의무 |

### 5.4 Area #4 — Scene consistency element scope ✓ closed C-4 (Tier 2 #1, 2026-05-18)

| Field | Value |
|---|---|
| Status | **✓ closed C-4** — `docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md` + plan + W0-W4 atomic execution + Codex per-wave APPROVED. |
| Closure scope | P019 / A037 / A038 (in-scope). P020 (analysis_summary backward-compat shim) + P021 (시나리오 의존 enumeration broad prompt hygiene) carry — Area #7 primary owner 유지. |
| audit row | code: P019 (closed) / P020 (carry) / P021 (carry — Area #7) / prompt: A037 (closed), A038 (closed) |
| 본질 | scene_consistency v6 의 `_ELEMENT_ID_CLOSE_REGEX` + `_DESCRIPTION_CLOSE_KEYWORDS` + `_classify_framing` element-level close/full classifier — semantic regex/keyword inference. |
| Fix applied | `fixed_elements[].element_scope: "full" \| "close"` enum required (v7 schema + prompt). helper trio 폐기 (residue gate strict 0). `_detect_framing_conflicts` enum 직접 비교 rewrite (KeyError + AppError fail-fast). render_prompt_card `_FIXED_ELEMENT_REQUIRED_KEYS` 9→10 cascade. cp invalidation (schema_version 2→3). |
| Cost | medium (actual range: 7 atomic commits = spec + plan + W0-W4, W4 amend 1회) |
| Dependency | depends-on framing_scale enum SOT v1 (✓ closed C-2). framing_scale spec line 58 deferred row #17 가 본 area 로 routed — 완료. |
| Closed area boundary | `framing_scale.py` (closed C-2) — 호출 0 (element_scope vs framing_scale 차원 분리 보존). |
| Risk (resolved) | element_id opaque 전환 — LLM emit string preservation, deterministic re-keying 0. |

### 5.5 Area #5 — Reference phrase / phantom guard replacement ✓ closed C-5 (Tier 2 #2, 2026-05-18+)

| Field | Value |
|---|---|
| Status | **✓ closed C-5 (v1)** — `docs/superpowers/specs/2026-05-18-area-5-reference-phrase-phantom-guard-replacement-design.md` + plan + W0-W4 atomic execution + Codex per-wave APPROVED (W3 NEEDS_REVISION_BLOCKING C1+C2 흡수 + W3 fix-up-2 IMPORTANT 1 isinstance gate 흡수). |
| audit row | code: P006 (primary) / prompt: A058, A089 (primary). related (handled by Area #11): P084-P087 (`prompt_service._classify_label`) — 본 area 외 |
| 본질 | `ref_contract_validator.py:47-457` 의 `_CHARACTER_TOKENS / _BACKGROUND_TOKENS / _OBJECT_TOKENS` (3 noun list) + `classify_from_the_reference` 30/60자 window nearest-token classifier. "from the reference" phrase 의 character/background/object 분류가 token rfind 로 결정. |
| Fix scope (v1 적용) | producer (scene_detail v26) emit `reference_phrase_kinds: array<enum [character|background|prop]>` sidecar (per-variation). validator step 6 = sidecar exact compare (legacy prompt-prose classifier 폐기). 13 legacy identifier atomic delete (W2). caller cascade = build_scene_attached_refs 4-tuple + single path unpack + variation path direct read + isinstance/None/missing gate (No Silent Fallback). 4 prompt sync (scene_image v4 / t2i_review v5 / render_prompt_card / prompt_service). **`prompt_service._classify_label` 9 inner substring 은 Area #11 primary owner — 본 area 외**. |
| Cost | medium |
| Dependency | independent (audit `00-index.md` §6.3 graph) |
| Closed area boundary | `attached_refs / render_contracts.required_refs` (Area B-min closed, commit `e400e9c`) — consumer 보존, validator step 6 만 변경 |
| Risk (post-closure) | producer schema v26 강제 (No Silent Fallback) — stale v25 cp 가 sidecar 없이 들어오면 RefContractError 또는 typed failure dict. caller cascade ensures fail-fast at boundary. prompt-side closed list 모두 폐기, principle-only constraints. |
| Closure verify (W4) | 7 residue gate PASS (production 4 + active prompt 3) + 5 canary PASS (3 kind + empty + strict violation, NO VLM). full W3+W4 cascade subset 263 PASS. |

### 5.6 Area #6 — T2I review mutation redesign

| Field | Value |
|---|---|
| audit row | code: P065 / prompt: A085, A086, A087, A088, A089, A090, A091 |
| 본질 | `t2i_review.py:383-454` 의 `target.replace()` blind mutation. LLM emit `target -> suggestion` 으로 prompt body 치환. dual-sync — `t2i_review/scene_system.md:31-91` 의 6 issue type + closed phrase pattern list 가 prompt-side 짝. |
| Fix scope | `target/suggestion` mutation 폐기 + LLM emit `{item_id, issue_code, regenerate_required: bool, hint_diagnostic: str}` 만. code 는 regenerate trigger 만. patch ID / span position 도입 시 mutation 유지 가능. |
| Cost | medium-large |
| Dependency | independent. 단 prompt-side closed phrase list (A088 close-framing tag, A089 phantom phrase) 는 Area #1 (G2) / Area #5 와 일부 겹침 — boundary 명시 의무 |
| Closed area boundary | Patch A 3-tier defense (commit `ade21b6`) — t2i_review fan-out 차단 보존 (item_id 별 처리 유지) |
| Risk | regenerate trigger only 전환 시 운영 cost 증가 (재생성 비용). vs blind replace 의 over-replace risk trade-off |

### 5.7 Area #7 — Prompt hygiene v2

**G5 본체** + 일부 G6.

| Field | Value |
|---|---|
| audit row | A006, A010, A014-A016, A022-A024, A027, A029-A030, A032, A034, A047, A050-A057, A065-A070, A093, A096-A100 (25+ row) |
| 본질 | Hygiene v1 (P-2/P-3/P-4/P-5/P-6) 후 잔존 시나리오 leak + 도메인 nomenclature 분산. scene_extractor_v2 turn_scene_detail / shot_director / scene_consistency / visual_world_rules / background-floor-plan prompts 전부 cross-cut. |
| Fix scope | active prompt 전체의 scenario-specific examples / closed noun lists 중립화. 단 코드 SOT 정리와 섞지 말고 prompt-only wave 로 분리. |
| Cost | **large** (25+ row, 광범위 prompt 다수) |
| Dependency | independent. 단 Area #1 / #2 / #3 의 prompt-side counterpart (scene_detail / shot_staging / shot_director) 는 해당 area 안에서 처리 — Area #7 의 scope 와 분리 |
| Closed area boundary | Hygiene v1 (commit `91d1dfd`) — P-1 ~ P-6 fix 보존 |
| Risk | 광범위 prompt rewrite — version bump 다수 + DB row override / file fallback 의무 4-point sync (5월 14일 audit `04-` 참조) |
| Sub-area 후보 (분할 가능) | (a) entity_extractor / outlook_extractor / scene_director / lvm_prompts 시나리오 leak 만 / (b) visual_world_rules SOT 일원화 (rules_schema.json:9 description 6-token + system.md:51 10-token enum drift, A096-A100) / (c) shot_extract / shot_validator Korean grammar leak / (d) t2i_visual_converter / scene_generator 작품 고유명사 |

- **Sub-area (b) Phase 1 — Area #7a (visual_world_rules SOT 일원화 + scene_director A047 흡수)**: **closed (2026-05-19+, W1-W3c 5 commits: `54fe057` W1 producer / `b2765a7` W2 consumer / `e6c0f0f` W3a residue / `50cb85b` W3b canary / `0a2e2b4` W3c closure, push `d0410eb`)**. In-scope = A047/A096/A097/A098. Carry follow-up = Area #7b (11-site cascade, closed 2026-05-19+ — Phase 2 entry below) + Area #7c (t2i_review placeholder) + Area #7d (cinematography dual-site) + Carry-A099 (director_notes prose) + Carry-A100 (t2i_context demonym) + Carry-P021 (scene_consistency, source unresolved).
- **Sub-area (b) Phase 2 — Area #7b (visual_world_rules downstream prompt cascade)**: **closed (2026-05-19+, W6 closure commit `c92d460` through W6 = 26 commits since `d0410eb`, 후속 range-review fix-up commits 가능 — final pushed range/count recorded in external memory after push; W6 commit 시점 push 보류 → Codex APPROVED_FOR_PUSH 후 즉시 push origin main)**. In-scope = audit `02-` §11.2 row 9 site (D-1 entity_all/character.md + D-3 entity_relation/system.md + D-4 entity_extractor_v2/system.md + ADD-6 entity_extractor_v2/turn0_style.md + ADD-8 outlook_extractor/phase1.md (line 16 audit-verbatim + line 24 current-active-promoted) + ADD-9 outlook_extractor/phase2.md + ADD-10 scene_verify/system.md + ADD-11 scene_detail/system.md (line drift 327 → 473) + row 11 shot_extract/user.md (line drift 33 → 49)). **D-2 entity_character_list (row 2) = 변경 0 boundary preserve** (owner taxonomy 5-element 분류, sha256 anchor `4ca95ca996...`). 7 new prompt dirs / 9 modified prompt files / 24 byte-identical sibling files / 12 affected STEP_MANIFEST entries (10 modified-file-bound + 2 sibling-only shared-module). Wave commits: W1 `95688d9` Group E entity (+ plan amend 3-7 + spec amend 5-6 narrow stack) / W2 `50f15f0` Group O outlook (+ plan amend 8-10 + spec amend 7-9 narrow scene_detail 4-point sync exemption singular → plural 2 → plural 5 files) / W3 `5060254` Group S scene (+ fix-up 1 `75d4f3a` + fix-up 2 `403c5ef` current-contract docstring narrow) / W4 `313f1b6` residue gate 21 PASS (+ fix-up 1 `844cde9` `빙의/합체` full legacy phrase form sync) / W5 `531e67f` canary 44 PASS no live LLM + NO VLM (+ fix-up 1 `fe7e55e` C3 entry-existence contract wording sync + function rename) / W6 `c92d460` closure (spec status + spec §5.6 C3 wording sync + spec §11 + roadmap §5.7 + audit §13 + audit §11.2 row 11 Status). 4-Gate Boundary Doctrine inline (Semantic Regex Ban / Prompt Closed-List Ban refined as full-phrase ban only / Structured SOT Required / No Silent Fallback). **NO VLM hard constraint**. Carry follow-up = Area #7c (t2i_review placeholder) + Area #7d (cinematography dual-site) + Carry-A099 / Carry-A100 / Carry-P021.
- **Area #7c (t2i_review v6 placeholder example abstraction — Track B Tier 3 #3)**: **closed (2026-05-19+, W3 closure commit `600993b` — W1-W3 atomic 3 wave commit + spec drafting 2 commit + plan drafting 2 commit = 7 commits total in range `e751e72..600993b`; 후속 range-review fix-up commits 가능 — final pushed range/count recorded in external memory after push; W3 closure commit 시점 push 보류 → Codex APPROVED_FOR_PUSH 후 즉시 push origin main)**. In-scope = audit `02-` §5 P-6 (P-6 v6 follow-up Phase 2 hygiene, Hygiene v1 commit `91d1dfd` 1차 abstraction 후 잔존 concrete prime). 8 lines/sites = 5 scene (`scene_system.md:31/32/33/39/40`) + 1 keep-abstract (`scene_system.md:60-61`) + 2 entity (`entity_system.md:33/34`). 7 strict residue catalog (exact legacy phrase membership, closed-world only — `subject's hands` / `feet visible at lower frame edge with floor below` / `full silhouette including head and feet visible` / `sits hunched in the left background` / `a hand reaching from the right edge holding a small object` / `'security guard'` / `Asian / Korean 인종 형용사`). 1 new prompt dir (v7 major bump `7.202605190201` 보존, Area #6 v6 boundary preserve, v6 dir `6.202605181200/` 변경 0). 2 prompt file modified (`scene_system.md` + `entity_system.md`) + 2 schema sibling byte-identical (`scene_schema.json` + `entity_schema.json` sha256 match v6→v7). 1 W2 integrated test file (`backend/tests/integration/test_area_7c_t2i_review_placeholder_hygiene.py` 14 PASS in 0.12s, no live LLM + NO VLM + no regex semantic). 3 W3 closure docs file (본 spec frontmatter status closed + spec §11 Closure section append + 본 roadmap §5.7 본 bullet append + audit `02-prompt-side-hygiene-audit.md` §5 P-6 row status marker + §14 Area #7c Closure section append). audit §11.2 row 추가 X (Codex spec iter 2/3 정합 — VWR downstream cascade 아님, §5 P-6 row owner). Wave commits: spec drafting `5118e5e` v1 + `1032dbc` amend 1 / plan drafting `1d41801` v1 + `3bf7c22` amend 1 / W1 `426d959` producer atomic (4 file / +249 line / 7 strict residue + 1 keep-abstract 8 site replacement, spec §2 Codex iter 2 verbatim wording) / W2 `df751dd` integrated test atomic (5 verify gate: residue 7 strict + schema sibling sha256 2 + load_prompt/load_schema 4 stem + STEP_MANIFEST schema_version preservation + `_resolve_stem_in_pack` 4 stem v7 source-path proof; 14 PASS / +205 line, v6/v7 schema byte-identical blind spot 보완) / W3 `600993b` closure docs atomic (3 file path-limited / +128/-9 line). STEP_MANIFEST["t2i_review"].schema_version == 1 preservation + load_prompt/load_schema 4 stem latest v7 activation. 4-Gate Boundary Doctrine + closed-world exact residue contract + TEMPLATE ONLY doctrine + NO VLM hard constraint. Carry follow-up post #7c = Area #7d (cinematography closed-list SOT dual-site `variation_recommender/v2/system.md` + `scene_extractor_v2/19.*/turn_scene_detail.md:87-91`) / Carry-A100 (VWR system.md t2i_context demonym redesign V8+) / Carry-A099 (VWR system.md director_notes prose redesign V8+) / Carry-P021 (scene_consistency 7 enumeration broad, source unresolved).
- **Sub-area (e) cinematography closed-list SOT dual-site**: **closed (2026-05-19+, W1-W4 atomic — W1 producer / W2 E6 prompt_service regex / W3 integrated test / W4 closure docs; range review/push gate pending at W4 closure commit time — Codex APPROVED_FOR_PUSH 후 즉시 push origin main, final pushed range/count = external memory only)**. In-scope = dual-site (`variation_recommender/v2/system.md` + `scene_extractor_v2/20.202605190631/turn_scene_detail.md`) + E6 mandatory (`prompt_service.py:347-352` 7-token cinematography stripping regex 폐기). 9 strict residue R1-R9 closed-world exact phrase membership. 1 new prompt dir v20 major bump `20.202605190631/` (5 file = 2 modified + 3 byte-identical sibling) + 1 v2 narrow edit + 1 schema-description narrow + 1 prompt_service.py E6 regex 폐기 + 1 W3 integrated test (18 PASS, 5 gate) + 4 W4 closure docs. Wave commits: spec drafting `e0cf96d` v1 + `424c8e9` amend 1 narrow / plan drafting `b5a1e84` v1 + `489361f` amend 1 narrow / W1 `6cc4933` producer atomic / W2 `5b63b89` E6 regex 폐기 atomic / plan amend 2 `8eef6f7` narrow (§5.3 Gate 4 schema path-navigation) / W3 `9139bc9` integrated test atomic / plan amend 3 `bd8c54a` narrow (§5.5 (d) AST-based check) / W4 closure-docs wave (docs-only closure commit; exact hash recorded by git log/range review, not embedded in the same commit). carrier shape preserve obligatory (`camera_effect` string + `_VARIATION_ITEM_SCHEMA` shape + `scene_variation_service` consumer + `i2i_editor` dispatch). dual-owner fully fixed claim X (Area #7d v1 scope), 후속 Carry-D7d-1 resolved by W1 `05af1d5` + W2 closure-docs — scene_detail primary `camera_effect` description aligned with Area #7d fallback description policy (scene_detail/28.202605190927). 4-Gate Doctrine + closed-world exact residue contract + TEMPLATE ONLY + NO VLM + standalone token global ban 엄금. Carry follow-up post #7d = Carry-D7d-1 resolved by W1 `05af1d5` + W2 closure-docs / Carry-D7d-2 conditional W2 outcome → W2 preferred 채택 → carry 없음 확정 / Carry-A099 resolved by W1/W2 + W3 closure-docs — director_notes prose hard-prime examples abstracted / Carry-A100 resolved by W1-W4 (Option B-prime: v9 prompt-pack bump `9.202605191334`, system.md line 102 narrow + rules_schema.json:40 description-only abstraction; structured emit / field-shape migration follow-up deferred) / Carry-P021 resolved by W1-W4 — scene_consistency v7 system.md hard-prime examples abstracted (v8 prompt-pack `8.202605191744`).

- **C8 — Area #7 잔여 sub-area marathon (a)/(c)/(d) + code carry**: **closed (2026-05-20+, W1a-W5 8-wave 10-commit, push range `e23ae86..HEAD` — W5 range review `APPROVED_FOR_PUSH` 후 push origin main, 실제 hash git log/external memory 기록)**. In-scope = index.html C8 **25-site disposition**: FIX 21 (sub-area (a) entity_all/entity_extract_v4/entity_filter/entity_extractor_v2/outlook_extractor/location_consistency + (c) shot_extract/shot_essence_extraction/shot_selection/scene_extractor_v2 + (d) t2i_visual_converter/background_master_plan/floor_plan_prompt 13 prompt-pack + code carry 5 file entity_steps/outlook_dedup/scene_validator/reference_image_generator/render_prompt_card) / KEEP 2 (Site 16 background_chain_render palette checklist / Site 21 render_prompt_card `_ID_ETHNICITY_COMPONENTS`·`_ID_AGE_BANDS` G4.3 SOT) / SPLIT 1 (Site 20 render_prompt_card `camera_frame_rule.applies_when` FIX + `_SPATIAL_CAMERA_*` canary KEEP) / DEFER 1 (Site 19 scene_consistency_step P020 prefix shim — checkpoint migration 설계 필요). Wave commits: W1a-1 `dc06ac1` / W1a-2 `b227672` / W1a-3 `c0fc5f7` / W1b `a3037b6` / W2a `ef2fa91` / W2b `589b7b1` / W3a `7c5ab8a` / W4a `dab5980` / W4b `b2f06b8` / W5 closure docs. 닫힌 enumeration·시나리오 leak → generic semantic principle 추상화, 신규 schema/producer/mechanism 0. code-path constant 3 module (t2i_visual_converter/background_master_plan/floor_plan_prompt) PROMPT_DIR/PROMPT_VERSION code 상수 bump. code carry 5 file carrier-shape 보존 prose 치환. `version_registry` provenance sync = 기존 entry 보유 module 한정 (신규 entry 0). `test_c8_area7_residual_hygiene.py` G-test 53 PASS. NO VLM / no live LLM / no semantic regex. Known carry (C8 scope 외) = shot_schema.json OpenAI strict 위반 (C10/dedicated SchemaStrict) + `prompt_service.replace_entity_ids` camera-angle prefix strip pre-existing failure (C8 무관 out-of-scope) + `outlook_extractor.py:44` docstring 작품 고유명사 (audit 25-site 미열거 out-of-scope). **C8 closure = roadmap §5.7 Area #7 sub-area (a)/(c)/(d) + code carry 잔여 전부 처리 → Area #7 전체 closure.**

### 5.8 C4 (Area #8) — Background / floor-plan semantic classifier ✓ closed (Track B Tier β #7, 2026-05-20)

**G6 의 신규 영역** — closure complete.

| Field | Value |
|---|---|
| Status | **✓ closed C4** (2026-05-20+) — `docs/fix-critical-1/index.html` C4 section. spec `docs/superpowers/specs/2026-05-20-c4-background-classifier-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c4-background-classifier-v1-implementation.md` + W1-W5 5-wave atomic 실행 + Codex per-wave APPROVED. audit row P043 + A001/A002/A003/A004/A005/A033/A034 (`triage_report.md` full_20260516_0105). |
| 본질 (closed) | indoor/outdoor · skip_chain · room-count 판단이 LLM-facing closed-list reasoning (prompt 안 닫힌 enumeration) + code-side semantic substring 매칭. `background_chain_planning.py:151-154` location 이름 양방향 substring 매칭 (P043) / `background_chain_planning/4` SKIP DECISION·node-state·`skip_chain` description 닫힌 예시 (A001-A004) / `background_classify/3` indoor/outdoor 한국어 keyword 닫힌 목록 (A005) / `location_floor_plan/3` room-count 한국어 토큰 cue + slash-zone 예시 (A033/A034). |
| Fix applied | **옵션 B (narrow, C9/C6 pattern) — 신규 producer 미신설** (Codex C4 entry sanity: 각 step 이 이미 structured SOT emit `is_indoor`/`skip_chain` bool + D6 `entity_canon.location.space_profile` SOT/validator 존재 → 신규 `location_space_profile.py` 는 중복 + routing risk 증폭). P043 = substring fallback 폐기 → exact·L-id 실패 시 `ValueError` fail-loud (W1 `2c018f3`). A001-A004 = `background_chain_planning` v5 prompt-pack (W2 `7c9a605`). A005 = `background_classify` v4 (W3 `4bf2c72` + fix-up 1 `1130cf9`). A033/A034 = `location_floor_plan` v4 (W4 `ddcd115`). 닫힌 enumeration → generic semantic principle 추상화. `PROMPT_VERSION` bump (bcp 4→5 / bclassify 3→4 / lfp 3→4). `test_c4_background_classifier.py` G1-G12 신설. |
| Boundary | **A031** (`floor_plan_prompt/4/system.md:10-13` 색/glyph 매핑) = boundary-reviewed **KEEP** — schematic diagram 의 deterministic rendering convention, open-world semantic classifier 아님, `floor_plan_prompt` 변경 0. **A020** (`entity_extractor_v2` `allowed_space_keys`) = C4 scope 제외 (deferred — roadmap §5.8 audit row 미포함, file-fallback latest v10 vs `version_registry` v9, D6 `location.space_profile` SOT 와 묶인 큰 영역, C8/C10 carry). `background_chain_planning` (lifecycle deprecated + applicability disabled) / `location_floor_plan` (lifecycle deprecated) — active latest prompt/code residue 만 좁게 처리, step_manifest lifecycle/applicability entry 변경 0. 세 step `SCHEMA_VERSION` 불변. |
| Cost | medium (narrow prompt hygiene + code 1 site — 신규 producer schema 미채택으로 medium-large→medium 축소). 5-wave. |
| Closure verify | W1-W5 Gate 전수 PASS. 백엔드 전체 회귀 5 failed (pre-existing — `test_analysis_dispatch_service`/`test_prompt_service`/`test_text_cleanup` ×3, clean HEAD `16abb40` git stash 대조 확정) / 4077 passed / 37 skipped. C4 신규 failure 0. NO VLM. Codex W1-W4 per-wave APPROVED (W3 per-wave `NEEDS_REVISION_NARROW_1` → fix-up 1 → re-review APPROVED). |

### 5.9 C5 (Area #9) — Action segment / still-moment prompt hygiene ✓ closed (Track B Tier β #8, 2026-05-20)

**G6 의 한국어 grammar leak** — closure complete.

| Field | Value |
|---|---|
| Status | **✓ closed C5** (2026-05-20+) — `docs/fix-critical-1/index.html` C5 section (Area #9). spec `docs/superpowers/specs/2026-05-20-c5-action-segment-sot-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c5-action-segment-sot-v1-implementation.md` + W1-W4 atomic execution + Codex per-wave APPROVED. audit row A042 + A064 + A068 + A082 + A083 (triage_report.md, full_20260516_0105). |
| 본질 (closed) | shot 추출/검증 + scene_detail re-frame 의 "한 shot = 한 찰나" 원칙이 한국어/영어 시간 연결어 닫힌 목록 + 이동·접촉 동사 lexicon + 신체 부위/동작 동사 lexicon 으로 LLM 에게 grammar/lexical 매칭으로 주입 — Prompt Closed-List Ban 위반. shot description 에 routing 하는 code regex 는 0. |
| Fix applied | **옵션 B narrow** (Codex C5 entry sanity — 신규 `action_segment[]` structured schema NO-GO: code consumer 0 → write-only dead schema, index.html 원안 superseded). 3 prompt-pack 의 닫힌 lexicon → generic semantic principle 추상화 — W1 `shot_extract` v13 (시간 연결어, A064/A068) / W2 `shot_validator` v6 (시간 연결어·locomotion·active-contact·visible-human-action, A082/A083) / W3 `scene_detail` v32 (dynamic verb, A042) + 4-point version cascade. `version_registry` 3 module provenance sync (`shot_extractor` 2.2.0 / `shot_validator` 1.5.0 / `scene_detail_composer` 1.32.0). `test_c5_action_segment_sot.py` G1-G10 (12 test). |
| Boundary preserve | A069 (`shot_extract` 외모·연령 변화 닫힌 목록) = C5 scope 외, C8 Area #7 sub-area (c) carry. `shot_validator` active contact freeze contract + characters/character_ids fail-fast contract + scene_detail mid-action freeze 예시 = byte 보존. schema 구조 (`shot_schema.json`/`validator_schema.json`/`detail_schema.json`) byte-identical, `SCHEMA_VERSION` 전부 불변. |
| Cost | medium (3 prompt-pack 추상화 + 4-point cascade, 4-wave). 신규 schema 0. |
| Closure verify | W1 `cfb9184` / W2 `086ab0a` / W3 `2f41467` + W3 fix-up 1 `3d901cc` / W4 closure docs. 백엔드 전체 회귀 5 failed 전부 pre-existing baseline / C5 신규 failure 0. NO VLM. Codex per-wave APPROVED + W1-W4 range review. W1 OQ blocker (`shot_schema.json` v13 미통합, `OPTION_1_APPROVED`) — `characters` required 누락 OpenAI strict 위반은 별도 carry (C8/C10). |

### 5.10 C6 (Area #10) — detail_steps 색감-감정 closed-list 폐기 ✓ closed (Track B Tier β #5, 2026-05-20)

**G6 의 code-side scenario leak** — closure complete.

| Field | Value |
|---|---|
| Status | **✓ closed C6** (2026-05-20+) — `docs/fix-critical-1/index.html` C6 section (Area #10). spec `docs/superpowers/specs/2026-05-20-c6-detail-steps-color-emotion-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c6-detail-steps-color-emotion-v1-implementation.md` + W1-W2 atomic execution + Codex per-wave APPROVED. audit row P034 (`triage_report.md:94`, full_20260516_0105). |
| 본질 (closed) | `backend/app/core/steps/detail_steps.py:2327` (audit/roadmap 의 `:2286-2291` 은 stale) — `긴장=어둡고 대비 강한, 슬픔=탈색/청색, 분노=적색 등` 한국어 감정→색감 closed-list 매핑 1줄. `[조명/색감 판단]` code-built user_prompt instruction 안 Prompt Closed-List Ban 위반 (code 안 시나리오 의존 creative classifier). |
| Fix applied | line 2327 closed-list 줄을 generic instruction 으로 치환 — `"- 색감은 beat의 정서와 씬 분위기에서 직접 derive하고, 특정 정서에 고정 색조를 대응시키도록 강요하지 마세요"`. emotion-drives-color 의도 보존, 특정 감정→색 고정 매핑 제거. 옵션 (b) `color_palette_intent` enum 미채택 — scene_detail schema 의 `camera_effect` free-string 이 이미 색감 capture (`"closed-list 강제 X"` design intent, enum 신설 시 충돌 + Cost small 불일치). `test_scene_detail_analyze_one.py` C6 regression test 2건 (runtime user_prompt G1-G4 + source canary G5). |
| Boundary preserve | 형제 줄 `:2326` 시간대/색온도 + `:2328` 조명 방향 (객관적 촬영 범주, audit 미flag) byte-for-byte 불변. C1 perception_mode (`detail_steps.py:2248-2254` + `perception_mode.py:29-41` `_PERCEPTION_GUIDES`) 변경 0. scene_detail prompt-pack v30 / `detail_schema.json` / `version_registry` / `STEP_MANIFEST` / version artifact 변경 0. |
| Cost | small (단일 site — code 1줄 치환 + test 2건, 2-wave). |
| Closure verify | W1 `9f64928` 2 file modify (48+/1-). Gate W1.1-W1.5 PASS — 백엔드 4058 passed / 5 failed 전부 pre-existing (clean HEAD `c5d4520` git stash baseline 대조 확정). NO VLM. Codex W1 per-wave APPROVED_FOR_W2_ENTRY. |

### 5.11 Area #11 — prompt_service `_classify_label` 9-branch substring ✓ closed C-11 (Tier 2 #3, 2026-05-18+)

**G6 의 ref label substring routing** — Tier 2 #3 closure complete.

| Field | Value |
|---|---|
| audit row | P084, P085, P086, P087 (5월 14일 audit #19 + 본 audit 가 재발견) |
| 본질 (closed) | `services/prompt_service.py:75-116` 의 10-branch substring routing 폐기. producer (scene_reference_service.py) 가 LabeledRefPayload sidecar (4 parallel list — labeled_refs / ref_roles / ref_role_metadata / attached_meta) emit, consumer (`resolve_ref_roles(payload)`) 는 11-enum ref_roles 만 dispatch. substring matching 0. |
| Fix scope (v1 적용) | (1) `LabeledRefPayload` frozen dataclass + `make_labeled_ref_payload` factory (9 fail-fast: 4 isinstance + 3 length parity + 1 enum value + 1 non-dict metadata). (2) `REF_ROLE_VALUES` 11 enum (outfit_ref_explicit / outfit_ref_inline / previous_shot_same_frame_zoomed / previous_shot_same_room / previous_shot_continuity / background_chain_ref / character_ref / character_state_ref / prop_ref / background_general / fallback). (3) `resolve_ref_roles(payload)` 11-enum dispatch — substring branch 0. (4) `scene_reference_service.resolve_refs_for_prompt[_set]` LabeledRefPayload return + 8 producer append site ref_role emit. (5) `build_prev_shot_background_ref` 3-tuple → 5-tuple (ref_usage → ref_role 매핑). (6) `build_image_index` 4-tuple → 6-tuple (3 parallel list passthrough). (7) `build_final_scene_prompt(t2i, payload, ...)` signature cascade. (8) 3-path cascade (single helper + batch + variation) — coordinator 모든 path payload 경유. (9) W4 cleanup: `_classify_label` / `_is_explicit_character_ref_label` / `_IMAGE_N_PAREN_HEADER_RE` / `_IMAGE_N_BARE_PREFIX_RE` / `_HEADER_CHARACTER_TAGS` / `_BARE_LABEL_CHARACTER_PREFIXES` 모두 폐기. |
| Cost | medium-large (W1 factory + W2 atomic 3-file 282/-95 line production switch + W3 9-file 474/-401 test cascade + W4 cleanup + canary 17 + residue gate 8). |
| Dependency | Area #5 v1 closure (phantom guard sidecar) 정합 보존 — `reference_phrase_kinds` sidecar 와 `ref_roles` sidecar 독립적 parallel array, validator step 6 cross-check 영향 0. |
| Closed area boundary | Area #5 v1 phantom guard SOT (commit `2817f2d` W3) — producer `reference_phrase_kinds` array 의 step 6 cross-check 분기 유지. |
| Risk (post-closure) | producer (scene_reference_service.py) 가 8 append site 모두 ref_role + ref_role_metadata 동반 emit — site 1 누락 시 `make_labeled_ref_payload` length parity gate 가 RefRoleError fail-fast. consumer cascade 도 LabeledRefPayload attribute read — 정합 깨지면 AttributeError fail-fast. |
| Closure verdict | Codex iter 4 W1/W2/W2 fix-up/W3/W3 fix-up/W4 entry consultation 5 round APPROVED. 208 PASS (W3 scope) + 25 PASS (W4 canary 17 + residue gate 8). NO VLM. |

### 5.12 C7 (Area #12) — shot_dependency_t2i subject_kind structured signal ✓ closed (Track B Tier β #4, 2026-05-20)

**G2 의 다른 instance** (closed area 보호).

| Field | Value |
|---|---|
| Status | **✓ closed C7** (2026-05-20+) — `docs/fix-critical-1/index.html` C7 section (Area #12). spec `docs/superpowers/specs/2026-05-20-c7-shot-dependency-subject-kind-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c7-shot-dependency-subject-kind-v1-implementation.md` + W1-W2 atomic execution + Codex per-wave APPROVED. audit row A059/A060/A061/A063 (5월 16일 full audit triage, untracked artifact). |
| 본질 | `shot_dependency_t2i` producer 의 `keep_elements[]` entry — `kind` 는 schema enum `{environment, static_prop}` strict 이나 `label` string 안 인물/신체 단어 금지는 prompt instruction only (code/schema enforcement 0). `system.md:148` false `"fail-fast 거부"` claim + `:156` 11-lexicon ban list non-enforced + schema description ↔ system.md drift. |
| Fix applied | v8 prompt-pack — `keep_elements[].subject_kind` structured signal enum `{non_human_visual_element, human_or_character_reference}` required field 신설 (producer LLM explicit emit) + `validate_keep_elements_entry()` 가 subject_kind enum 소비 + `human_or_character_reference` fail-fast (routing layer 안내). `system.md` false claim → subject_kind 기반 TRUE 진술 정정 + 11-lexicon ban 폐기 + schema description cleanup. version cascade — `MODULE_VERSIONS` 1.4.0→1.5.0 / `prompt_dependency` v8 / `STEP_MANIFEST` schema_version 3→4 / `scene_context_loader` envelope 3→4. |
| Boundary preserve | Area D-next-min (commit `5f3da38`) — `KEEP_ELEMENT_KINDS = {environment, static_prop}` + `validate_keep_elements_entry()` 의 `kind` enum check 본체 변경 0. `subject_kind` 는 orthogonal 차원 추가 (kind = 환경/소품 axis, subject_kind = 인물/비인물 axis). `_LEGACY_SCHEMA_BUMP_ALLOWLIST` 변경 0. code-side lexicon/substring validator 미추가 ([[feedback_llm_based_judgment]] Semantic Regex Ban). |
| Cost | small (2-wave — W1 atomic full implementation / W2 closure docs). |
| Closure verify (commit chain) | W1 `c8d2391` / W1 fix-up 1 `e4ee3ed` / W2 closure commit. |

### 5.13 C1 — perception_mode enum SOT ✓ closed (Track B Tier α #1, 2026-05-20, fix-critical-1 신규 area)

| Field | Value |
|---|---|
| Status | **✓ closed C1** (2026-05-20+) — `docs/fix-critical-1/index.html` C1 section 신규 area (roadmap 원 12 area 미포함, fix-critical-1 persistent guide 추가). spec `docs/superpowers/specs/2026-05-20-c1-perception-mode-enum-sot-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c1-perception-mode-enum-sot-v1-implementation.md` + W1-W4 atomic execution + Codex per-wave APPROVED. |
| 본질 | `shot_staging` schema `perception_mode` = `type:string` (JSON enum 강제 0, `mirror` description 부재) + `render_prompt_card.py` consumer 4-tuple literal subset 비교 + `detail_steps.py` 6-key dict (mirror 부재) generic fallback. arbitrary string silent miss + 3-way drift. |
| Fix applied | shot_staging v14 `perception_mode` JSON enum 8-token 강제 (`mirror` 추가) + `backend/app/core/perception_mode.py` helper 신설 (`PERCEPTION_MODES` + `REPRODUCTION_PERCEPTION_MODES` strict subset + `_PERCEPTION_GUIDES` non-direct 7-key + 2-stage check fail-fast) + render_prompt_card `is_reproduction_perception()` consume + detail_steps `get_perception_guide()` consume (local map 폐기) + scene_detail v29 consumer prompt helper SOT cross-reference. |
| Boundary preserve | Area C (directionality_class enum SOT) 변경 0 — `_ALLOWED_DIRECTIONALITY_CLASSES` + `_REPRODUCTION_SURFACE_CLASSES` + fail-fast + shot_staging directionality_class 5-enum. |
| Cost | medium (W1 producer+helper / W2 consumer switch / W3 scene_detail v29+integrated test / W4 closure docs). |
| Closure verify (commit chain) | W1 `4655741` / W2 `c486993` / W3 `cfc0347` / W4 closure commit. |

### 5.14 C2 — owned_object_usage[] echo ✓ closed (Track B Tier α #2, 2026-05-20, fix-critical-1 신규 area)

| Field | Value |
|---|---|
| Status | **✓ closed C2** (2026-05-20+) — `docs/fix-critical-1/index.html` C2 section 신규 area (roadmap 원 12 area 미포함, fix-critical-1 persistent guide 추가). spec `docs/superpowers/specs/2026-05-20-c2-owned-object-usage-echo-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c2-owned-object-usage-echo-v1-implementation.md` + W1-W4 atomic execution + Codex per-wave APPROVED. |
| 본질 | `scene_detail_owned_judge` LLM 이 redraw verb closed whitelist 16 + anchor/reference phrase examples + 5-step priority closed list 로 owned 객체 redraw 여부 판정. verdict `redraw_violation` = hard fail. 새 verb 누락 silent miss / 의도외 verb over-trigger. 4-Gate Prompt Closed-List Ban 위반. |
| Fix applied | scene_detail v30 `t2i_variations[].owned_object_usage[]` required echo field 신설 (`{owned_token, usage_kind enum [redraw/anchor/absent], source_phrase}`) + system.md OWNED OBJECT USAGE ECHO instruction + owned sentinel v2 (`owned_usage_hash` 4th hash + `compute_owned_usage_hash` + `validate_owned_object_usage_coverage` + `assert_owned_usage_hash_matches` + `assert_close_framing_absent_echo`) + scene_detail_owned_judge v4 prompt-pack (verb whitelist 폐기 → echo-verify-only judge) + `run_owned_judge` owned_object_usage echo cross-check plumbing. |
| Boundary preserve | verdict enum (`redraw_violation`/`anchor_reference`) + `has_redraw_violation` semantics 변경 0. t2i_prompt body shape 변경 0 (owned_object_usage = sidecar structured evidence). C1 perception_mode helper + Area C directionality 변경 0. scene_detail_owned_judge version_registry entry invent X. |
| Cost | medium-large (W1 producer schema+prompt / W2 sentinel v2+consumer / W3 judge v4+plumbing+integrated test / W4 closure docs). |
| Closure verify (commit chain) | W1 `eb8343c` / W2 `55f54ab` / W3 `bc05dc7` / W4 closure commit. |

### 5.15 C3 — detail_steps focus rewrite 폐기 ✓ closed (Track B Tier α #3, 2026-05-20, fix-critical-1 신규 area)

| Field | Value |
|---|---|
| Status | **✓ closed C3** (2026-05-20+) — `docs/fix-critical-1/index.html` C3 section 신규 area (roadmap 원 12 area 미포함, fix-critical-1 persistent guide 추가). spec `docs/superpowers/specs/2026-05-20-c3-detail-steps-focus-rewrite-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c3-detail-steps-focus-rewrite-v1-implementation.md` + W1-W2 atomic execution + Codex per-wave APPROVED. |
| 본질 | `detail_steps.py:2872-2882` scene_detail post-process cleanup loop 이 모든 t2i variation 에 무조건 3-regex substitution (`\s{2,}` collapse + orphan 소유격 → semantic 구절 삽입). G4 §4.4/§225 가 본 site 를 "prompt body mutation → 폐기" 분류. orphan 의 발생원 = VE-violation 강제 제거 strip 2 site (`pure_remove` t2i_prompt / `bad_in_sfp` representative_moment) 가 bare-ID 만 strip → 후행 소유격 잔존. (audit 01 §7 Excluded 가 본 cleanup 을 "Closed ID syntax cleanup" benign 으로 분류했으나 §225 가 재분류 — audit 01 #10 `t2i_review` 와는 별건.) |
| Fix applied | OQ option (b) upstream token-complete fix — `_strip_invalid_sids()` module-level helper 신설 (무효 closed-world SID + 후행 소유격 + 인접 공백 token-complete 제거, `subn` no-match no-op, semantic 재삽입 0) + VE-violation 강제 제거 2 site 를 helper 호출로 교체 + cleanup loop 전체 폐기. `test_c3_detail_steps_focus_rewrite.py` G1-G7 신설. fail-fast (option a) 미채택 — VE-violation 강제 제거 graceful degradation 보존. |
| Boundary preserve | `_check_prompts`/`_extract_base`/`_ve_pattern`/`replace_map` detector·variant-resolution path 변경 0. scene_detail prompt-pack/schema/version/STEP_MANIFEST/version_registry/cp 변경 0 (output shape 불변). |
| Cost | small (W1 helper+2-site+cleanup 폐기+regression test 1 atomic / W2 closure docs). |
| Closure verify (commit chain) | W1 `4740b03` / W2 closure commit. |

### 5.16 C9 — scene_detail Rule B body-light verb closed list 추상화 ✓ closed (Track B Tier β #6, 2026-05-20, fix-critical-1 신규 area)

**audit 03 L-7 의 LLM-side closed verb list** — closure complete.

| Field | Value |
|---|---|
| Status | **✓ closed C9** (2026-05-20+) — `docs/fix-critical-1/index.html` C9 section. spec `docs/superpowers/specs/2026-05-20-c9-scene-detail-body-light-verb-v1-design.md` + plan `docs/superpowers/plans/2026-05-20-c9-scene-detail-body-light-verb-v1-implementation.md` + W1-W2 atomic execution + Codex per-wave APPROVED. audit 03 L-7 (`03-llm-side-heuristic-audit.md:127-132`, 본 audit 단독 신규 finding). |
| 본질 | `prompts/_base/scene_detail/<latest>/system.md` 의 `## 조명·색조가 신체를 변형하지 않게 (Rule B)` 섹션이 빛/색이 신체에 작용하는 closed verb list (`cut/slice/split/carve/bisect` — quoted-comma form + slash form 2회) + forbidden phrasing 예시 5건 + recommended phrasing 예시 5건 + recommended verb list (`falls on / washes / reflects on / catches on / pools on / glows across`) = 4개 닫힌 enumeration 을 producer LLM 에 주입. LLM 이 그 토큰 집합만 좁게 회피 — 닫힌 목록이 전수라는 착각. Track B Prompt Closed-List Ban 위반 (pure LLM-side, code/schema 소비자 0). |
| Fix applied | scene_detail v31 prompt-pack — Rule B 섹션의 4개 닫힌 enumeration + sub-header 3개를 단일 generic semantic principle 1문단으로 추상화 ("빛/색은 표면에 머무는 효과로 묘사, 신체를 물리적으로 변형·절단하듯 쓰지 마라"). 닫힌 영문 토큰 목록·예문 목록 0, 의도 보존. header + WHY 문단 byte-identical 보존. 옵션 (a) 예시 전폐 (C6 closed-list 전폐 precedent 정합). version cascade 4-point — `SCENE_DETAIL_PROMPT_VERSION` `31.202605200805` / `MODULE_VERSIONS["scene_detail_composer"]` `1.31.0` / `prompt_dependency` `scene_detail/v31` / v31 디렉토리. `test_c9_scene_detail_body_light_verb.py` G1-G7 신설. |
| Boundary preserve | `detail_schema.json` v30→v31 byte-identical (sha256 동일) — `SCENE_DETAIL_SCHEMA_VERSION` / `STEP_MANIFEST["scene_detail"]["schema_version"]` 12 변경 0. `detail_steps.py` code 로직 / C6 색감 instruction 변경 0. system.md 의 무관 섹션 — 실루엣 평면 cutout 규칙 + windshield slice framing 예시 (`cut`/`slice` 부분 문자열) **string boundary preserve** (v31 에서 Rule B 축약으로 줄번호는 위로 이동하나 문자열 보존). C1·C2·C3·C6·C7 변경 0. v30 이하 prompt-pack 디렉토리 변경 0. |
| Cost | small (2-wave — W1 v31 prompt-pack + version cascade 4-point + alignment test 5 file + C9 regression test 1 atomic / W2 closure docs). |
| Closure verify (commit chain) | W1 `04016da` (10 file, 963+/80-) — Gate W1.1 C9 test 7 PASS / W1.2 alignment 5 file 99 PASS / W1.3 scene_detail·detail_steps 210 PASS / W1.4 residue assertion OK / W1.5 백엔드 5 failed = clean HEAD `81bde22` git stash baseline 동일 (C9 신규 failure 0). W2 closure commit. NO VLM. Codex W1 per-wave APPROVED_FOR_W2_ENTRY. 함정 — alignment occurrence 실제 16 (plan §2.3 의 14 는 `latest_major == "30"` assert 2건 누락, W1 broad scan 보정). |

## 6. Dependency Graph

```
[Closed C-1~C-4 — 보존]
- Hygiene v1                          (commit 91d1dfd)
- framing_scale enum SOT v1           (commit 53dd180)
- close × ref_usage matrix v1         (commit 53dd180)
- zoom_in_detail source provenance    (commit 772fcd4)

──────────────────────────────────────────────────────────────────────
Tier 1 — Cross-cutting cancer (가장 시급, 3 area)
──────────────────────────────────────────────────────────────────────

[Area #1 ID/outlook reference policy SOT]
  depends-on: framing_scale enum SOT v1 (✓)
  prerequisite of: L-5 / #16 (audit 00-index §6.3)
  shot_staging or render_prompt_card schema 1 array field
  consumer 5 site (visible_entities + render_prompt_card + scene_detail + scene_extractor turn_scene_detail)
  cost: medium-large (4-6 commit)

[Area #2 State / gaze 분리]
  cross-cut: 6 code site + 2 prompt site (G1)
  shot_staging schema 3 field 분리 (gaze_direction_kind + gaze_target_id + subject_state)
  consumer: asset_readiness + image_steps + detail_steps + semantic_contract_router + scene_reference_service
  cost: large
  ↑ shot_staging schema 변경 → Area #1 과 같은 producer
    결정 의무: bundle vs sequential (사용자 결정사항 §8.1)

[Area #3 Visibility / physical presence]
  cross-cut: 3 code site + 1 prompt dual-sync gap (G3)
  shot_director schema visibility_decisions[] 신설
  shot_visibility lexicon → drift diagnostic only
  cost: large
  ↑ Area #2 결과 consume 가능 (gaze 사용 site) — 분리 spec 권장

──────────────────────────────────────────────────────────────────────
Tier 2 — 자연 후속 (4 area, mostly independent — #5/#11 overlap)
──────────────────────────────────────────────────────────────────────

[Area #4 Scene consistency element scope]
  depends-on: framing_scale enum SOT v1 (✓)
  fixed_elements schema framing_scope / subject_extent 추가
  cost: medium

[Area #5 Reference phrase / phantom guard]
  ref_contract_validator classify_from_the_reference → attached metadata
  cost: medium
  ↗ Area #11 (prompt_service _classify_label) 과 일부 겹침

[Area #6 T2I review mutation redesign]
  t2i_review .replace() → structured patch ID / regen-trigger only
  cost: medium-large

[Area #11 prompt_service _classify_label]
  10-branch substring → producer-side enum
  cost: medium

──────────────────────────────────────────────────────────────────────
Tier 3 — 별도 wave (5 area, prompt-only 또는 신규)
──────────────────────────────────────────────────────────────────────

[Area #7 Prompt hygiene v2]
  25+ active prompt site
  cost: large
  Sub-area 분할 권장 (a/b/c/d 4 wave)

[Area #8 Background / floor-plan classifier]
  신규 영역 (background_chain_planning + background_classify + floor_plan_prompt)
  location_space_profile / building_membership / persistent_architecture 신설
  cost: medium-large

[Area #9 Action segment SOT]
  신규 영역 (shot_extract + shot_validator)
  action_segment[] LLM emit structured
  cost: medium

[Area #10 detail_steps 색감-감정 매핑]
  단일 site, code 폐기 또는 enum 흡수
  cost: small

[Area #12 shot_dependency_t2i schema description drift]
  closed area (Area D-next-min) schema description 만 정리
  cost: small
```

## 7. Tier 1/2/3 우선순위 (cost × risk × dependency)

### 7.1 Tier 1 — 즉시 (cross-cutting cancer, 3 area)

| 순서 옵션 | 장점 | 단점 |
|---|---|---|
| (a) Sequential: #1 → #2 → #3 | scope 좁음, framing_scale 후 자연 후속, 각 area atomic | 6-9 wave 필요, 총 cost large |
| (b) Bundle: #1+#2 한 wave | shot_staging schema 한 번 변경, cascade 한 번 | scope 폭발 위험, Tier 1 risk 증대 |
| (c) Sequential + parallel: #1 → (#2, #3 분리 spec) | #2/#3 가 shot_staging vs shot_director 다른 producer | producer 분리 명확, 단 #2 의 semantic_contract_router 재진입과 #3 의 mutation 폐기 동시 진행 시 검증 분량 증가 |

**권장 = (a) Sequential**. 이유:
- framing_scale 의 직접 후속 = #1 (L-5 / #16 unblock)
- #2 = Patch B-min closed area 재진입 (semantic_contract_router 재분류) — wording 정정 + closure 메모 amend 의무 → 별도 wave 적정
- #3 = shot_director mutation 폐기 = 큰 architecture 변경 → 별도 wave

**사용자 결정사항** (§8.1): Tier 1 진입 순서 (a/b/c) + 본 routing map commit 후 진입 의무.

### 7.2 Tier 2 — 자연 후속 (4 area, mostly independent)

대부분 independent. 단 **#5 / #11 overlap = sequencing 결정 의무**:
- #4 (element scope) — framing_scale 후속, 사용자 권장 순서 #2. independent.
- #5 (phantom guard) — `ref_contract_validator classify_from_the_reference` 본체. cost medium.
- #11 (prompt_service _classify_label) — `_classify_label` 9-branch substring 본체 (P084-P087 primary owner). cost medium.
- #6 (t2i_review mutation) — independent, cost medium-large.

**#5 ↔ #11 overlap**: 둘 다 ref label / phrase classifier 영역. Codex P006 (ref_contract_validator) 와 P084-P087 (prompt_service) 가 같은 "ref label semantic 분류" 의 다른 layer. 권장 sequencing:
- (옵션 1) #11 먼저 — producer-side label format closed-syntax 강제 → #5 의 token list 폐기 시 consumer 안전
- (옵션 2) #5 먼저 — phantom guard 본체 fix → #11 진입 시 producer label format 결정 시 consumer (validator) 영향 최소
- (옵션 3) bundle — 같은 wave 진행 (단 cost / scope 폭발 risk)

권장 = (옵션 1) — producer first. 사용자 결정 의무 (Tier 2 진입 시).

### 7.3 Tier 3 — 별도 wave (5 area)

- #7 (Prompt hygiene v2) — 별도 wave 의무 (코드 SOT 정리와 분리), sub-area 분할
- #8 (Background classifier) — 신규 영역, 별도 진입
- #9 (Action segment SOT) — 신규 영역, 별도 진입
- #10 (색감-감정) — small, 임의 시점 진입
- #12 (shot_dependency_t2i drift) — small, closed area 재진입 시 wording 정정

## 8. 사용자 결정사항 (3)

### 8.1 Tier 1 진입 순서

옵션 (a/b/c, §7.1 참조). 본 문서 권장 = (a) Sequential. 사용자 명시 결정 후 area #1 brainstorming 진입.

### 8.2 본 routing map commit 정책

#### 8.2.1 Spec 자체 commit 옵션

- (i) **Commit + push** — 본 spec 을 git 보존, 다른 area 진입 시 cross-ref 의무
- (ii) **Commit only (push 보류)** — 사용자 검토 후 push
- (iii) **External memo only** — git 미보존, MEMORY.md 만

권장 = (i) Commit + push. 5월 14일 routing-map.md 와 동일 정책 (commit `1a59452`). 본 spec 의 Tier 1 결정 + 12 area boundary 가 다른 area 진입 시 cross-cut 위험 차단.

#### 8.2.2 audit output (`backend/tests/_audit_outputs/semantic_string_debt/full_20260516_0105/`) 처리 옵션

본 spec 가 untracked audit output dir 의 6 file (1.4MB) 을 evidence 로 의존 (§3 결함 분포 + §15 파일 구조). commit + push 시 audit output 의 reproducibility 보장 정책 결정 의무:

- (a) **Full commit** — audit output dir 전체 (1.4MB) git 추가. binary-like (jsonl + tsv + snippet md) 부담 + 향후 audit run 시 dir 누적 (이전 calibration / 실패 run 도 보존).
- (b) **`triage_report.md` 만 commit** — 사람 요약본 47KB. 결함 분포 + must-hit verification + 194 row 표 보존. 본 spec 의 evidence 핵심 충족, file 크기 작음.
- (c) **External evidence (no commit)** — spec 안에 "본 spec 의 evidence = local-only audit output, repo artifact 아님. reproducibility = `backend/tests/tools/semantic_string_debt_llm_audit.py` 재실행" 명시. spec 자체가 distilled report 역할.

**권장 = (b) `triage_report.md` 만 commit**. 근거:
- spec 의 §3 결함 분포 + §10 cross-cut 표 의 모든 숫자가 triage_report.md 에서 도출
- file 크기 작음 (47KB), git history 부담 0
- 향후 audit run 의 잔여 파일 (jsonl / candidates.tsv / snippets.md) 은 local 보존
- §15 파일 구조 명시 update 의무 — `triage_report.md = tracked, 그 외 = local`

(b) 채택 시 spec wording update + triage_report.md 별도 commit (path-limited add).

### 8.3 Closed area 재분류 정책 (§11 참조)

`semantic_contract_router` (Patch B-min closed) 가 Area #2 의 G1 일부로 재분류. 옵션:
- (i) Patch B-min closure 메모 wording 정정 (external memory) + 본 spec §11 정정 표 명시
- (ii) Area #2 spec 안에서 재진입 + closure 메모 amend
- (iii) 별도 "Closed Area Re-classification Wave" spec 작성 (다른 잘못 closed 분류 + 한 번에 정리)

권장 = (i) + (ii). 본 spec §11 가 재분류 표 명시 + Area #2 spec 진입 시 closure 메모 amend.

## 9. Do Not Implement Patterns (5월 14일 routing-map carry + 신규 보강)

### 9.1 5월 14일 routing-map carry (5)

1. **`frame_spatial_contract` scope 확장 금지** — Area frame-spatial-contract closed (commit `2885f8c`). soft phrase diagnostic 유지, hard 승격 절대 금지.
2. **`keep_elements` character 재도입 금지** — Area D-next-min closed (commit `5f3da38`). `KEEP_ELEMENT_KINDS = {environment, static_prop}` 외 확장 금지.
3. **`render_contracts` dimension 추가 신중** — Area B closed (commit `e400e9c`). `visual_identity` 외 dimension 추가는 별도 area spec 의무.
4. **9 case 동시 구현 금지** — Routing Map §4 carry. 9 visual failure case 를 한 번에 fix 시도 시 scope 폭발.
5. **regex semantic 판단 도입 금지** — 사용자 명시 정책 ([[feedback_llm_based_judgment]] gate 1). 새 `_NOUNS / _TOKENS / _KEYWORDS / _PHRASES` 식별자 추가 (open-world visual / story semantic classifier 목적) 금지.

### 9.2 본 spec 신규 보강 (5)

6. **본 spec 의 다른 area fix 와 동시 진행 금지** — 한 번에 한 area 만. 사용자 명시 (2026-05-14): "한 번에 다 고치지 말 것 — scope 폭발 위험".
7. **본 spec supersede 금지** — 5월 14일 routing-map.md (Track A) + 5월 14일 audit 5 file + Codex 1차 두 input 문서 모두 보존. 본 spec 는 consolidates only.
8. **noun-list enum 함정 금지** — body part / room name / 한국어 시나리오 noun 을 enum 으로 만들지 말 것. **intent / target class 추상화** 의무 (사용자 보정 2026-05-15, Area #1 진입 시 적용).
9. **closed area 재분류 시 wording 정정 의무** — 본 spec §11 의 재분류 항목 (semantic_contract_router) 진입 시 closure 메모 amend + 본 spec §11 update 의무. silent re-entry 금지.
10. **prompt-only wave 분리 의무 (Area #7)** — code SOT 정리 area (#1/#2/#3 등) 안에 prompt hygiene fix 묶지 말 것. Hygiene v2 별도 wave + sub-area 분할.

## 10. Cross-cutting 결함 그룹 → Area mapping 표

| 그룹 | 결함 site count | 1차 area | cross-cut area |
|---|---|---|---|
| G1 (gaze_target overload) | 6 code + 2 prompt | **#2** | A074/A077 → schema 분리 시 #2 안에서 처리 |
| G2 (body_part_focus) | 4 code + 6 prompt | **#1** | scene_extractor turn_scene_detail (A053) → #1 scope 안 |
| G3 (visibility mutation) | 3 code + 1 prompt dual-sync | **#3** | A076 (shot_director gaze pattern) → #3 안 |
| G4 (blind string mutation) | production 18 + prompt 12 | **#6** (t2i_review) | 다른 18 site = case-by-case 판단 (closed-world template OK, prompt body mutation 폐기) |
| G5 (scenario leak) | production 13 + prompt 21 | **#7** | sub-area 분할 (4 wave 권장) |
| G6 (closed-list LLM instruction) | production 5 + prompt 39 | 다수 area cross-cut | #1/#4/#5/#6/#7/#8/#9 모두 |

## 11. Closed Area 재분류

5월 14일 audit 의 잘못된 "closed area do-not-touch" 분류 정정:

| Area | 5월 14일 audit 분류 | 본 spec 재분류 | 근거 |
|---|---|---|---|
| `semantic_contract_router` (Patch B-min, commit `f2682d7`) | **closed area** ([[session_20260514_semantic_regex_prompt_pollution_pivot]] §결론 "frame_spatial_contract / D-next-min 같은 closed 구조 흔들지 말 것" 적용 잘못) | **closed (2026-05-17, Area #2 W3 안 해결 완료)** | Patch B-min wiring closed (commit `f2682d7`). G1 본체 (gaze_target overload) Area #2 W3 (commit `861e9de`) 안 해결 완료 — IMMOBILIZED_GAZE 폐기 + Rule 1 source 변경 (`subject_state` enum 직접 consume) + shot_visibility Path 1 흡수. 외부 memory closure 메모 wording 정정 의무 (W9 controller-side). |
| Area #2 (State / Gaze Separation, G1 본체) | **pending / brainstorm 진입 의무** | **closed (2026-05-17, W9 commit 본 closure)** | W1-W9 atomic execution 완료 — shot_staging v13 (3 field 분리) + 8 consumer migration + helper SOT 2 module (`subject_state.py` + `gaze_direction.py`) + Patch B-min Rule 1 재진입 + E1/E1b/E2/E3 residue gate strict 0 hits + 사용자 명시 4 test file 35 PASS. Closure verify (commit chain): W1 `fb516e1` / W2 `54ca894` / W3 `861e9de` / W4 `c9b537a` / W5 `4017656` / W6 `88a8154` / W7 `780d591` / W8a `1a5a531` / W8b `eeeb835` / W8c `950b604` / W8d `74b2ffa` / W9 closure commit. |
| Area #3 (Visibility / Physical Presence SOT v1, G3 본체) | **pending (Tier 1 #3, last Tier 1)** | **closed (2026-05-18, W4 closure commit)** | W0-W4 atomic. mutation 권한 박탈 (shot_director.py:182-201) + prompt v6 (Korean grammar bundle 제거 / 4 closed pattern bundle 폐기) + Path 1/2 함수 split (`detect_offscreen_drift_structured` blocking-eligible + `detect_offscreen_drift_proximity_diagnostic` diagnostic-only). schema 신설 = deferred by policy (Q1 closure, post-closure trigger 시 separate follow-up per spec §7). 4 closure criteria PASS (W1 residue 9 + W2 mutation pattern 1 + W3 legacy function name 1 + W4 canary Path 1/2 2 + S12_Shot4 skip per cp-only). closure verdict = "not demonstrably unsafe; post-W2 audit log monitoring required". Closure verify (commit chain): W0 spec `32210e5` / plan `7197667` / audit `b259480` / cleanup `62c8f99` / W1 prompt `8beec62` + fix-up `e57d57b` + `a262ceb` + `92ef673` / W2 main `d7bf651` + guard hardening `211903d` / W3 split `dab3dee` / W4 closure commit. |
| Area #5 (Reference phrase / phantom guard replacement, Tier 2 #2) | **pending (Tier 2 #2)** | **closed C-5 (2026-05-18+, W4 closure commit)** | W0-W4 atomic. producer sidecar SOT v1: `reference_phrase_kinds: array<enum [character|background|prop]>` per-variation emit (scene_detail v26 producer schema + prompt v26). validator step 6 = sidecar exact compare (legacy classifier 폐기). 13 legacy identifier atomic delete (W2). caller cascade = build_scene_attached_refs 4-tuple + single path unpack + variation path direct read + isinstance/None/missing gate (No Silent Fallback). 4 prompt sync (scene_image v4 / t2i_review v5 / render_prompt_card / prompt_service). 7 residue gate PASS (production 4 + active prompt 3) + 5 canary PASS (3 kind + empty + strict violation). Codex per-wave iter: W2 NEEDS_REVISION_MINOR M1 (test stale classifier wording) → W2 fix-up `cdeb3c3` → APPROVED_FOR_W3. W3 NEEDS_REVISION_BLOCKING C1 (helper silent fallback) + C2 (variation silent fallback) → W3 fix-up `c6d1cdb`. W3 fix-up NEEDS_REVISION_MINOR IMPORTANT 1 (list(raw) masking non-list) → W3 fix-up-2 `20ab02d` → APPROVED_FOR_W4. closure verdict = sidecar SOT 적용 완료, No Silent Fallback 4-point (helper/variation + missing/None/non-list). NO VLM. Closure verify (commit chain): W0 spec `eab4032` + amend `d5f24e5` / plan `b04892a` / W1 prompt v26 producer + cp invalidation + fix-up x2 / W2 validator step 6 rewrite + 13 identifier delete `71f253a` + fix-up `cdeb3c3` / W3 production cascade `4853c7b` + fix-up `c6d1cdb` + fix-up-2 `20ab02d` / W4 closure commit. |
| Area #11 (prompt_service `_classify_label` 9-branch substring → 11-enum LabeledRefPayload, Tier 2 #3) | **pending (Tier 2 #3)** | **closed C-11 (2026-05-18+, W4 closure commit)** | W1-W4 atomic. Producer-side LabeledRefPayload (4 parallel list frozen dataclass + `make_labeled_ref_payload` factory 9 fail-fast: 4 isinstance + 3 length parity + 1 enum value + 1 non-dict metadata) + `REF_ROLE_VALUES` 11 enum. consumer `resolve_ref_roles(payload)` 11-enum dispatch (substring branch 0). `scene_reference_service.resolve_refs_for_prompt[_set]` 2-tuple → payload return. `build_prev_shot_background_ref` 3-tuple → 5-tuple (ref_usage → ref_role). `build_image_index` 4-tuple → 6-tuple (3 parallel list passthrough). `build_final_scene_prompt(t2i, payload, ...)` signature cascade. 3-path cascade (single + batch + variation) coordinator 모두 payload 경유. W4 cleanup: `_classify_label` / `_is_explicit_character_ref_label` / `_IMAGE_N_PAREN_HEADER_RE` / `_IMAGE_N_BARE_PREFIX_RE` / `_HEADER_CHARACTER_TAGS` / `_BARE_LABEL_CHARACTER_PREFIXES` 모두 폐기 (production substring matching 0). W3 test cascade 76 fail → 0 (label_routing 33 substring → 18 enum-dispatch rewrite + 8 file 모든 unpack cascade). 8 residue gate (production 4 negative + 2 positive cascade + 2 helper definition zero) + 17 canary (11 enum dispatch + 4 fail-fast + 1 full-pipeline + 1 sanity) = 25 PASS. Codex per-wave iter: W1 APPROVED / W2 atomic switch → NEEDS_REVISION_MINOR (plan expected fail set 230 vs 실측 76 정정) → W2 plan amend × 2 `42a555c` `c0b9ca4` → APPROVED. W3 cascade → NEEDS_REVISION_MINOR (stale 3-tuple wording 13 hit + PASS count 정정) → W3 fix-up × 2 `10084c4` `74fb5d5` → APPROVED. W4 entry consultation → APPROVED (Q1 dead code 폐기 / Q2 별도 신규 file / Q3 atomic single commit). closure verdict = substring routing 완전 폐기, 4-gate compliance, 3-path cascade 정합, Area #5 closure 정합 보존. NO VLM. Closure verify (commit chain): W1 `92f7186` / W2 `48dc256` + plan amend `42a555c` + `c0b9ca4` / W3 `35f9e8a` + fix-up `10084c4` + `74fb5d5` / W4 closure commit (dead code cleanup + canary 17 + residue gate 8 + roadmap update + closure memo). |

다른 closed area (보존):
- `frame_spatial_contract` (commit `2885f8c`) — 본 spec Do Not #1
- `keep_elements` (commit `5f3da38`, Area D-next-min) — 본 spec Do Not #2 + #12 (description drift 만 정리, 본체 보존)
- `render_contracts visual_identity` (commit `e400e9c`, Area B-min) — 본 spec Do Not #3
- `framing_scale.py` (commit `53dd180`, C-2) — 본 spec C-2
- `close × ref_usage matrix v1` (commit `53dd180` 의 일부) — C-3
- `zoom_in_detail source provenance` (commit `772fcd4`, C-4) — 본 spec C-4
- **Area #1 ID/outlook reference policy SOT** (W1-W8a closure commit `747af7e`; full range W1-W8b = 19 commits, [[session_20260516_area_1_id_outlook_reference_policy_sot_v1_closure]]) — body_part_focus_rule + close_framing_face_phrasing sub-field 폐기 + `id_policy.subject_reference_policy[]` per-subject SOT 신설 (shot_staging v12 Producer / `subject_reference_policy.py` Helper / scene_detail v25 + scene_extractor_v2 v19 Prompt). 4 layer atomic closure.

**재분류 절차** (Area #2 진입 시):
1. Patch B-min closure 메모 ([[session_20260512_patch_b_implementation]]) 의 "Patch B-min closed" wording 정정 — "Patch B-min wiring 완료, 단 G1 본체 (gaze_target overload) Area #2 carry"
2. 본 spec §11 update — "재분류 완료" 표기
3. Area #2 spec 의 Closed Area Boundary 항목에 "semantic_contract_router 재진입 history" 명시

## 12. Verification Backlog

본 spec 가 production 측정 없이 결정 불가한 항목:

### 12.1 G1 / Area #2 검증 의무

- shot_staging v11 운영 dataset 의 `gaze_target = "unconscious / dead / severely_injured"` 분포 (production canary log)
- semantic_contract_router IMMOBILIZED_GAZE Rule 1 의 production trigger 빈도
- STATE_DESCRIPTIONS prose mapping (image_steps.py:638-642) 의 production usage (한국어 prose 가 LLM emit 으로 흡수 가능한지)

### 12.2 G2 / Area #1 검증 의무

- `_FACE_CLOSE_UP_PATTERNS` 의 production trigger 빈도 (canary)
- body_part_focus_rule.trigger_phrases substring 매칭의 production 빈도
- subject_reference_policy[] 의 LLM 분류 정확도 (intent class 추상화 가능성)

### 12.3 G3 / Area #3 검증 의무

- shot_visibility lexicon 의 production miss / false-positive 빈도
- visibility_decisions[] LLM emit 정확도 (frame_presence + physical_presence 분류)
- prompt dual-sync gap 의 silent miss 빈도 (`차단/막다/가리다/block/obstruct` blocking 패턴)

### 12.4 G4 / Area #6 검증 의무

- t2i_review target/suggestion blind replace 의 over-replace 빈도 (production canary)
- regenerate trigger only 전환 시 운영 비용 증가 추정

### 12.5 G5 / Area #7 검증 의무

- 25+ active prompt 의 DB row override / file fallback 매트릭스 (5월 14일 audit `04-` 의 11 module 매트릭스 superset)
- visual_world_rules SOT (rules_schema.json:9 vs system.md:51) 의 production drift 빈도

### 12.6 G6 / Area #8 + #9 검증 의무

- background_chain_planning skip_chain 결정의 production 분포 (indoor / outdoor / detached open)
- shot_extract / shot_validator 시간 연결어 발견 빈도 (production 시나리오에서 segment count 검증 필요성)

## 13. 함정 / Lesson learned

### 13.1 5월 14일 audit 의 함정 (carry)

본 spec 에서 그대로 적용:

1. (carry) **메모 보유 + 위반** — feedback_llm_based_judgment gate 1 (Semantic Regex Ban) 메모 보유하면서 옵션 first + Recommended 로 위반 옵션 제시. **다음 area 진입 시 feedback 메모 must read**.
2. (carry) **scope guard 핑계** — "small spec 원칙" 으로 본질 회피. scope 좁히는 것 ≠ 위반 허용.
3. (carry) **cross-cutting cancer 인지 못함** — close 만 보고 audit 자체 안 함. 본 spec 가 12 area 통합 구조 명시 → 동일 실수 차단.
4. (carry) **사용자 인벤토리도 incomplete** — 5월 14일 인벤토리 32 → 본 audit 194 superset. 추가 grep 의무.
5. (carry) **shot_visibility 자기 모순** — docstring `:22-24` "auto-fix 안 함" 명시하면서 `shot_director.py:188-190` 가 실제 변조. 본 spec Area #3 본체.
6. (carry) **prompt_loader DB 우선 + file fallback latest** — file-only audit 미흡. 운영 active prompt 검증은 DB row 확인 필수.
7. (carry) **prompt + code dual sync 의무** — `t2i_review/scene_system.md` phrase + `_SPATIAL_SHARED_ANCHOR_KEYWORDS` 같이 LLM-facing prompt + code-side keyword 양쪽 sync.

### 13.2 5월 15일 / 16일 신규 함정

8. **audit 결과 재발견 의무** — 5월 14일 audit 의 "closed area" 분류가 본 audit 에서 재발견 (semantic_contract_router). 새 audit 진입 시 이전 closed area 분류도 verify 의무.
9. **noun-list enum 함정 차단** — body part / room name / 한국어 시나리오 noun 을 enum 으로 만들면 다시 어휘 폭발. **intent / target class 추상화** 의무 (Area #1 의 핵심 보정).
10. **"분석해" ≠ "spec 작성해"** — 사용자가 audit / large-context 진단 요청 시 brainstorming 좁은 spec 진입 즉시 시도 금지. 종합 분석 우선. 본 case = 2026-05-16 격분 사례, [[feedback_audit_analysis_vs_spec_entry]] memo 신설.
11. **8-area roadmap 의 dependency map 의무** — 사용자 / Codex roadmap 받았을 때 audit 결과로 dependency + 우선순위 + 누락 / 보강 / 반전 평가 의무. roadmap 무비판 흡수 금지.
12. **cross-cutting 결함 그룹 (G1-G6) 명시 의무** — area 별 진입 전 G 그룹 cross-cut 매핑 의무. 단일 site fix 가 다른 area 영향 차단.
13. **closed area 재분류 wording 정정 의무** — Patch B-min 같이 "wiring 만 완료" 한 area 를 "closed" 로 분류한 경우, 재진입 시 closure 메모 wording 정정 + roadmap §11 update 의무.

## 14. 다음 진입점

### 14.1 즉시 결정 (사용자, §8 항목 3)

1. Tier 1 진입 순서 (a/b/c)
2. 본 routing map commit 정책 (i/ii/iii)
3. Closed area 재분류 정책 (i/ii/iii)

### 14.2 다음 area spec 진입 (Tier 1 권장 순서 = (a) sequential)

1. **Area #1 ID/outlook reference policy SOT** — 본 spec closure 후 즉시. brainstorming skill invoke + spec 단계 §5.1 의 5 결정 의무.
2. **Area #2 State / gaze 분리** — Area #1 closure 후. shot_staging schema 변경 + semantic_contract_router 재진입.
3. **Area #3 Visibility / physical presence** — Area #2 closure 후 (또는 분리 spec).

### 14.3 Tier 2 / Tier 3 진입

Tier 1 closure 후 사용자 결정. 사용자 권장 순서 (2026-05-15) 와 본 spec dependency graph 종합:
- Tier 2 = #4 ✓ closed C-4 (2026-05-18) → #5 ✓ closed C-5 (2026-05-18+) → #11 ✓ closed C-11 (2026-05-18+) → #6
- Tier 3 = #7 (sub-area 분할) / #8 / #9 / #10 / #12 (임의 순서)

Tier 2 #3 (Area #11) closure 후 진입점 = Tier 2 #4 (Area #6 T2I review mutation redesign). 사용자/Codex 의논 의무.

## 15. 파일 구조

```
docs/
├── superpowers/specs/
│   ├── 2026-05-14-visual-reliability-routing-map.md           (Track A 9-case routing)
│   ├── 2026-05-15-prompt-hygiene-v1-spec.md                   (C-1 closure)
│   ├── 2026-05-15-framing-scale-enum-sot-v1-design.md         (C-2 closure)
│   ├── 2026-05-15-zoom-in-detail-source-provenance-design.md  (C-4 closure)
│   └── 2026-05-16-track-b-semantic-debt-roadmap-design.md     (본 문서)
└── visual-reliability-audit/
    ├── 2026-05-14-semantic-string-routing-debt-map.md          (Codex 1차 code-side, 보존)
    ├── 2026-05-14-prompt-hygiene-v1-spec.md                    (Codex 1차 prompt-side, 보존)
    ├── 2026-05-14-nine-case-remediation-roadmap.md             (별개 영역, cross-ref)
    └── 2026-05-14-semantic-string-routing-debt-audit/          (5월 14일 audit, 보존)
        ├── 00-index.md
        ├── 01-code-side-regex-audit.md
        ├── 02-prompt-side-hygiene-audit.md
        ├── 03-llm-side-heuristic-audit.md
        └── 04-db-row-verification.md

backend/tests/_audit_outputs/semantic_string_debt/full_20260516_0105/  (untracked, 5월 16일 audit)
├── triage_report.md                          (사람 요약본 — 본 spec 의 1차 input)
├── findings.jsonl                            (LLM raw finding 전체)
├── findings.md                               (raw finding markdown)
├── candidates.tsv                            (audit candidate 목록)
├── production_app_findings.tsv               (production 94 row tsv)
├── production_app_findings_with_snippets.md  (production + snippet)
├── active_prompt_findings.tsv                (prompt 100 row tsv)
└── active_prompt_findings_with_snippets.md   (prompt + snippet)
```

## 16. Completion Criteria

본 routing map 가 완료된 것으로 간주되는 조건:

- [x] 5월 16일 전수조사 결과 (194 finding) 분포 명시 (§3)
- [x] Cross-cutting 결함 그룹 G1-G6 정의 + site mapping (§4 + §10)
- [x] 12 area 정의 (8 사용자 + 4 신규 보강) + scope / audit row / fix direction / cost / dependency / risk (§5)
- [x] Dependency graph (§6) + Tier 1/2/3 우선순위 (§7)
- [x] 사용자 결정사항 3 명시 (§8)
- [x] Do Not Implement patterns 5 carry + 5 신규 보강 (§9)
- [x] Closed area 재분류 정책 (§11) — semantic_contract_router 반전 명시
- [x] Verification Backlog 6 영역 (§12)
- [x] 함정 / Lesson learned 13 (§13) — 5월 14일 carry 7 + 5월 15/16 신규 6
- [x] 다음 진입점 (§14) — Tier 1 권장 순서 + Area #1 진입 결정 의무
- [x] 파일 구조 (§15) — 5월 14일 audit / 5월 16일 audit / 본 spec / Track A routing 분리

## 관련 문서

- Track A routing: `docs/superpowers/specs/2026-05-14-visual-reliability-routing-map.md`
- 5월 14일 audit: `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/00-index.md`
- 5월 16일 전수조사: `backend/tests/_audit_outputs/semantic_string_debt/full_20260516_0105/triage_report.md` (untracked)
- Closed area: `docs/superpowers/specs/2026-05-15-{prompt-hygiene-v1-spec,framing-scale-enum-sot-v1-design,zoom-in-detail-source-provenance-design}.md`
- 정책 메모: external `~/.claude/projects/-Users-manta-Documents-Projects-TheRoad-I1/memory/feedback_llm_based_judgment.md` (4 강제 gate) + `feedback_subagent_model_opus.md` + `feedback_audit_analysis_vs_spec_entry.md` (본 spec 작성 사례 학습)
