# 2026-05-18 — Area #4: Scene Consistency Element Scope SOT v1 Implementation Plan

**Spec**: `docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md` (commit `b92c101`, 632 line)
**Track**: Track B — Semantic Debt Roadmap, Tier 2 (first wave), Area #4 (G2.2 element-level scope)
**Date**: 2026-05-18
**Commit range expected**: 5 atomic (W0 optional + W1 + W2 + W3 + W4) on top of `b92c101` → push gate
**Codex iter 3 verdict (spec)**: APPROVED_FOR_PLAN
**Codex iter (plan structure)**: 권고 흡수 — atomic per wave + inline BLOCKING per wave + cascade enumeration with grep commands

---

## §1. Overview

본 plan 은 spec §2 Decision Summary (Q1-Q7) 의 element_scope SOT v1 을 5 wave 로 implement 한다. 모든 wave 는 **atomic 1 commit** (Codex 권고 C — red commit 분리 X). 각 wave 내부 6 step (test/grep marker → fail verify → impl → pass → wave regression → atomic commit).

**Plan 외부 의존**:
- spec `b92c101` (632 line, 12 section)
- Codex 의논 결과 — 모든 결정 사전 흡수
- 사용자 hard rule 7a (memory rule 7a maximally strict — push/scope inflation 도 둘이 결정, 사용자 ask = 심각한 버그만)

**4 Gate 의무 (각 wave 적용)**:
- Gate 1 Semantic Regex Ban
- Gate 2 Prompt Closed-List Ban
- Gate 3 Structured SOT Required
- Gate 4 No Silent Fallback

---

## §2. BLOCKING Pre-step (Tier 2 5 항목 의무 적용)

본 plan execution 진입 전 BLOCKING pre-step 5 항목 (`memory/next_session_area_4_scene_consistency_element_scope_brainstorm.md` §"Tier 2 plan BLOCKING 5 pre-step"):

### §2.1 Cascade grep pre-step (Tier 1 lesson #1 강제)

본 plan §3 cascade enumeration table 이 baseline. 각 wave 의 implement step 직전 추가 grep 확인 의무 (W3 fixture cascade 특히).

### §2.2 Canonical principle mapping table (Tier 1 lesson #2 강제)

spec §7 canonical mapping table 을 plan execution 동안 참조. canonical clause 변경 시 plan 본문도 inline 업데이트 의무.

### §2.3 Residue gate scope definition (production / active prompt / docs 분리)

`§9 Residue gate scope` 참조. strict 0 범위 = production code + active prompt v7. docs/architecture / specs/history / archived fixture 는 보존.

### §2.4 No VLM rule inline (hard constraint)

모든 wave 의 모든 step 에서 VLM 호출 / VLM-as-judge / VLM-derived ground truth 0. canary fixture 도 deterministic code/text 만.

### §2.5 tmux trigger checklist

- 매 wave commit 후 Codex MCP pane (%0) tmux_message + Enter
- Codex review 응답 polling
- review 결과 흡수 후 다음 wave 진입
- 양방향 trigger 의무 (memory rule 7)

---

## §3. Cascade Enumeration Table (spec §8 확장 — actual grep commands)

### §3.1 Cascade grep commands (W3 pre-step 의무 실행)

```sh
# Production code surface
rg -n "fixed_elements|element_scope|_detect_framing_conflicts|is_scene_result_consumer_safe|_FIXED_ELEMENT_REQUIRED_KEYS|_classify_framing|_ELEMENT_ID_CLOSE_REGEX|_DESCRIPTION_CLOSE_KEYWORDS" backend/app

# Active tests
rg -n "fixed_elements|element_scope|_detect_framing_conflicts|_classify_framing|_FIXED_ELEMENT_REQUIRED_KEYS|is_scene_result_consumer_safe" backend/tests \
  | grep -v "_audit_outputs\|_archive"
```

### §3.2 Production code 9 file classification (Codex 권고 D)

| Category | File | Read/Write | W ownership | Planned change |
|---|---|---|---|---|
| **Producer/Schema** | `backend/app/core/dto/scene_analysis.py:51` | DTO `fixed_elements_by_scene: Dict[int, List[Dict]]` | W1 | element_scope pass-through DTO 변경 0 (Dict 안 새 field 자동) |
| **Producer/Schema** | `backend/app/core/version_registry.py:36,129-131` | `MODULE_VERSIONS["scene_consistency"] = "2.4.0"` + `_MODULE_INFO[scene_consistency]` | W1 | `"2.5.0"` + `prompt_dependency = "scene_consistency/v7"` + `updated_at = "2026-05-18"` |
| **Producer/Schema** | `backend/app/core/step_manifest.py:654-740` | `STEP_MANIFEST["scene_consistency"]["schema_version"]: 2` | W1 | `schema_version: 3` |
| **Validator/Helper** | `backend/app/core/steps/scene_consistency_step.py:40,65-180` | `SCENE_CONSISTENCY_SCHEMA_VERSION = 2` + 3 helper + `_detect_framing_conflicts` | W1 (constant) + W2 (helper) | `= 3` + helper 3 삭제 + `_detect_framing_conflicts` body enum 비교 rewrite |
| **Validator/Helper** | `backend/app/core/steps/scene_consistency_step.py:183-206` | `is_scene_result_consumer_safe` (consumer gate single source) | W2 (body 변경 0, internal call enum 비교) | signature 보존 |
| **Consumer gate** | `backend/app/core/steps/scene_context_loader.py:223,235` | `from app.core.steps.scene_consistency_step import is_scene_result_consumer_safe` + call | W3 | **변경 0** (signature 보존 의무) |
| **Strict shape validator** | `backend/app/core/steps/render_prompt_card.py:2853-2963` | `_FIXED_ELEMENT_REQUIRED_KEYS` 9-field tuple + `_assert_continuity_elements_used_shape` docstring | W3 | **9→10 field** + docstring 9→10 + `element_scope` 추가 (Codex iter 3 권고 1 — BLOCKING) |
| **Pass-through reader** | `backend/app/core/steps/detail_steps.py:369-2178` | `_derive_fixed_elements_for_shot` + 다수 reader (line 369/384/583/618/639/712/727/1547/1653/2094-2178/2477) | W3 (pass-through) | element_scope pass-through, schema validation 통과 의무 |
| **Pass-through reader** | `backend/app/modules/semantic_contract_router.py:81,111-128` | Rule 2 `character_name` only | W3 (pass-through) | element_scope pass-through |
| **Pass-through reader** | `backend/app/core/steps/_evidence_helpers.py:55-71` | `_normalize_scene_consistency_result` (4-field default normalize) | W3 (pass-through) | element_scope 신규 normalize 불요 (LLM emit, missing 시 schema fail) |

### §3.3 Active tests 24 file classification

| Category | File | W ownership | Planned change |
|---|---|---|---|
| **Validator unit** | `tests/core/steps/test_scene_consistency_validator.py` | W2 | `_classify_framing` test 17개 삭제. `_detect_framing_conflicts` 6 test enum 비교 rewrite + 신규 enum-based test 5+ (close/full overlap detect / equal scope no conflict / missing scope AppError / 다른 element_type 무시 / character_state 만 대상) |
| **Schema v6** | `tests/unit/test_scene_consistency_schema_v6.py` | W1 | **신규 `tests/unit/test_scene_consistency_schema_v7.py`** 작성. v6 file 보존 (legacy reference, 변경 X) |
| **Status** | `tests/core/steps/test_scene_consistency_status.py` | n/a | element_scope 와 별개, 변경 0 |
| **Manifest** | `tests/test_step_manifest_v3.py`, `test_sync_v3.py`, `test_prompt_versions.py`, `test_manifest_fields.py`, `test_step_catalog.py`, `tests/unit/test_g3_2_manifest_dag.py` | W1 | scene_consistency v6→v7 update + schema_version 2→3 update |
| **Consumer verify** | `tests/core/test_consumer_verify_completion.py` | n/a | gate signature 보존 → 변경 0 |
| **Continuity card** | `tests/unit/test_render_prompt_card.py`, `test_render_prompt_card_integration.py`, `test_render_prompt_card_hash.py` | W3 | `_FIXED_ELEMENT_REQUIRED_KEYS` 9→10 cascade + fixture element_scope 추가 |
| **G4 cascade lift** | `tests/unit/test_g4_2_background_binding_lift.py`, `test_g4_3_id_policy_lift.py`, `test_g4_4_continuity_lift.py`, `test_g4_5a_spatial_lift.py` | W3 | fixture fixed_elements entries 에 element_scope 추가 |
| **G4 integration** | `tests/integration/test_g4_1_card_consumer_wiring.py`, `test_g4_2_bg_binding_integration.py`, `test_g4_3_id_policy_integration.py`, `test_g4_4_continuity_integration.py`, `test_g4_5a_spatial_integration.py` | W3 | fixture element_scope 추가 |
| **Subject reference E2E** | `tests/integration/test_subject_reference_policy_e2e.py` | W3 | Area #1 closure E2E, fixture element_scope 추가 |
| **Evidence consumer** | `tests/integration/test_evidence_consumer_wiring.py` | W3 | fixture element_scope 추가 |
| **Evidence normalize** | `tests/unit/test_evidence_normalize.py` | W3 | element_scope normalize 보존 verify |
| **DTO** | `tests/core/test_scene_analysis_dto.py` | n/a | DTO 변경 0 → 변경 0 |
| **Scene detail** | `tests/core/test_scene_detail_analyze_one.py`, `test_d6_scene_detail_chain_unchanged.py` | W3 | fixture element_scope 추가 |
| **Continuity alignment** | `tests/prompts/test_scene_detail_continuity_alignment.py` | W3 | element_scope 포함 verify (필요 시) |
| **Semantic contract router** | `tests/unit/test_semantic_contract_router.py` | n/a (pass-through) | element_scope 무시 = 변경 0 (단 fixture element_scope 포함 시 pass-through OK verify) |

### §3.4 No-change boundary (Codex 권고 D)

**변경 금지 (archived fixtures + audit outputs)**:
- `backend/tests/fixtures/_archive/g4_6_2026-05-16-area-1/s1_shot5_scene_detail.json`
- `backend/tests/fixtures/_archive/g4_6_2026-05-16-area-1/s2_shot4_scene_detail.json`
- `backend/tests/_audit_outputs/semantic_string_debt/**/*` (모든 audit history)

→ archived fixture 는 v6 reproduction reference 보존. active test 가 v7 schema fixture 필요 시 archive 수정 금지, current test fixture/copy 별도 작성.

---

## §4. W0 — Pre-W2 Cascade Baseline (Read-only, Optional)

### §4.1 Goal

production fixture / cp 안 fixed_elements 의 현재 `_classify_framing(element)` 결과 baseline 캡처 → W2 helper 폐기 후 element_scope LLM emit 과 비교 ground truth.

### §4.2 Sub-task

1. **Pre-step**: `backend/db.sqlite` 또는 production cp file 존재 확인 (`ls backend/tests/_audit_outputs/area_4_w0/` not yet exists)
2. **Read-only instrumentation**: 옛 v6 cp 안 fixed_elements load (production write 0)
3. **Artifact 작성**:
   - cp present → `backend/tests/_audit_outputs/area_4_w0/classifier_baseline.jsonl` + `summary.md`
   - cp absent → `docs/superpowers/specs/2026-05-18-area-4-w0-classifier-baseline.md` with `NO_CP_AVAILABLE` finding (Codex 권고 B)

### §4.3 Skip condition (Codex 권고 B)

- W0 skip → W2/W3 진입 가능 (deterministic unit/canary tests 의존)
- W0 skip 시 schema/field decision 재오픈 X
- W0 skip 시 markdown summary file (NO_CP_AVAILABLE finding) 필수 commit
- **W0 temporary instrumentation 0** (no production file edit, no patch revert overhead — 권고 Codex 권고 B)

### §4.4 Verify

- W0 artifact (jsonl + summary.md) OR markdown NO_CP_AVAILABLE — 둘 중 하나 존재
- production code unchanged (`git status backend/app` clean)

### §4.5 Atomic commit message template

```
docs(area-4-scene-consistency-element-scope-sot-v1): W0 — classifier baseline {output|NO_CP_AVAILABLE}

production cp 안 fixed_elements 의 v6 _classify_framing 결과 baseline {filename}.
W2 helper 폐기 후 element_scope LLM emit 과 비교 ground truth.
read-only instrumentation. production code unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
```

---

## §5. W1 — Producer Schema v7 + Prompt v7

### §5.1 Goal

scene_consistency v7 producer setup — element_scope required field 신설, prompt closed-list reasoning 폐기. cp invalidation 메커니즘 활성화.

### §5.2 Inline BLOCKING (Codex 권고 E — 각 wave 본문 inline 의무)

**BLOCKING (W1)**: active prompt v7 system.md 본문 = spec §6.2 verbatim block. 신체 부위 closed-list (`손/손목/...`) / `_close_up`/`_wrist` suffix example **재도입 절대 금지**. Codex iter 1 C1 결함 회피.

### §5.3 Sub-task (6 step atomic per Codex 권고 C)

1. **Test/grep marker**:
   - `tests/unit/test_scene_consistency_schema_v7.py` 신규 작성 (v6 file 보존, copy + adapt)
     - test: valid scene + element_scope full/close pass
     - test: missing element_scope → ValidationError
     - test: element_scope 외 enum 값 → ValidationError
     - test: element_scope null → ValidationError
   - `test_prompt_v7_active_loader_matches_file` + `test_prompt_v7_no_closed_framing_list` + `test_prompt_v7_no_element_id_suffix_guide` 신규.
   - **`FORBIDDEN_PROMPT_PATTERNS` (Codex plan iter 1 I1 fix — old closed-list signature 만 금지, individual Korean body-part noun 단독 출현 허용)**:

     ```python
     FORBIDDEN_PROMPT_PATTERNS = [
         r"_close_up",
         r"_wrist",
         r"전신형.*확대형|확대형.*전신형",
         r"손[·/]손목[·/]이마[·/]눈[·/]입[·/]목",
         r"손목[·/]이마[·/]눈",
     ]
     ```
2. **Fail verify**: `pytest backend/tests/unit/test_scene_consistency_schema_v7.py` → fail (file 없음 / fixture 없음)
3. **Implementation**:
   - `prompts/_base/scene_consistency/7.YYYYMMDDHHMM/` 신설 (timestamp = commit 시점)
   - `schema.json` v7: spec §4.1 diff verbatim (element_scope required + description abstract)
   - `system.md` v7: spec §6.1 rewrite + §6.2 verbatim instruction block + §6.1 P021 partial neutral
   - `scene_consistency_step.py:40`: `SCENE_CONSISTENCY_SCHEMA_VERSION = 3`
   - `step_manifest.py:660-680`: `STEP_MANIFEST["scene_consistency"]["schema_version"] = 3`
   - `version_registry.py:36`: `MODULE_VERSIONS["scene_consistency"] = "2.5.0"` (next semver)
   - `version_registry.py:129-131`: `prompt_dependency = "scene_consistency/v7"` + `updated_at = "2026-05-18"`
4. **Pass verify** (Codex plan iter 1 I2 fix — prompt residue test 소유 파일 명시): `pytest backend/tests/unit/test_scene_consistency_schema_v7.py tests/test_prompt_versions.py tests/test_step_manifest_v3.py` → PASS. `test_prompt_versions.py` owns `test_prompt_v7_active_loader_matches_file`, `test_prompt_v7_no_closed_framing_list`, and `test_prompt_v7_no_element_id_suffix_guide` (별도 file 작성 X, prompt_versions test 안 추가).
5. **Wave regression**: `pytest backend/tests/unit/test_scene_consistency_schema_v6.py` → PASS (보존). manifest test cascade (`test_sync_v3.py`, `test_manifest_fields.py`, `test_step_catalog.py`, `test_g3_2_manifest_dag.py`) PASS.
6. **Atomic commit**:

```
feat(area-4-scene-consistency-element-scope-sot-v1): W1 — producer schema v7 + prompt v7 (element_scope enum required + closed-list reasoning 폐기)

prompts/_base/scene_consistency/7.YYYYMMDDHHMM/:
- schema.json: element_scope: "full" | "close" required (additionalProperties:false)
- system.md: §6.2 verbatim instruction (closed-list / Korean grammar / _close_up suffix 0)
- partial neutral (P021 incidental cleanup, Area #7 primary owner 유지)

scene_consistency_step.py:40 SCENE_CONSISTENCY_SCHEMA_VERSION = 2 → 3 (cp invalidation)
step_manifest.py: scene_consistency schema_version 2 → 3
version_registry.py: MODULE_VERSIONS "2.4.0" → "2.5.0" + prompt_dependency v6 → v7 + updated_at 2026-05-18

신규 test_scene_consistency_schema_v7.py (v6 file 보존, legacy reference).

Codex iter 1 C1 fix: §6.2 verbatim only — 신체 부위 closed-list / _close_up/_wrist suffix example 재도입 금지.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
```

---

## §6. W2 — Helper Removal + Validator Enum Rewrite

### §6.1 Goal

`_classify_framing` + `_ELEMENT_ID_CLOSE_REGEX` + `_DESCRIPTION_CLOSE_KEYWORDS` 폐기. `_detect_framing_conflicts` body 만 enum 직접 비교로 rewrite. signature/return shape 보존.

### §6.2 Inline BLOCKING

**BLOCKING (W2-1)**: `_detect_framing_conflicts` body = spec §5.2 verbatim snippet:
- `e1["element_scope"]` / `e2["element_scope"]` (KeyError fail-fast, Gate 4)
- `if s1 not in ("full", "close") or s2 not in ("full", "close"): raise AppError(code="step.contract_violation.scene_consistency.element_scope", ...)` (invalid enum fail-fast)
- `"framings"` legacy metadata key 보존 (rename 0, Codex iter 1 I2)

**BLOCKING (W2-2)**: residue grep verify = `hits=0; for token in ...; if rg -n -F "$token" backend/app; then hits=1; fi; done; test "$hits" -eq 0` 형태 (Codex iter 2 I-1 fix). `&& exit 1` form 금지.

### §6.3 Sub-task (6 step atomic)

1. **Test/grep marker**:
   - `tests/core/steps/test_scene_consistency_validator.py` rewrite:
     - 삭제: `_classify_framing` 직접 호출 17 test (test_classify_framing*, test_classify_framing_does_not_false_positive*, test_classify_framing_no_false_positive*, test_classify_framing_close_pattern_word_boundary)
     - `_detect_framing_conflicts` 6 test → enum 비교로 rewrite (현재 `_classify_framing(e)` 의존 제거)
     - 신규 5+ test:
       - `test_detect_framing_conflicts_close_full_overlap_violation`
       - `test_detect_framing_conflicts_equal_scope_no_violation` (full+full overlap clean)
       - `test_detect_framing_conflicts_invalid_enum_raises_apperror`
       - `test_detect_framing_conflicts_missing_element_scope_raises_keyerror`
       - `test_detect_framing_conflicts_ignores_non_character_state`
       - `test_framings_metadata_key_preserved` (legacy key 보존, Codex iter 1 I2)
2. **Fail verify**: helper 삭제 전 새 test 추가 → `pytest tests/core/steps/test_scene_consistency_validator.py::test_detect_framing_conflicts_invalid_enum_raises_apperror` → fail (해당 동작 코드 없음)
3. **Implementation**:
   - `scene_consistency_step.py:65-72`: `_ELEMENT_ID_CLOSE_REGEX = re.compile(...)` 블록 삭제
   - `scene_consistency_step.py:73-80`: `_DESCRIPTION_CLOSE_KEYWORDS = (...)` 블록 삭제
   - `scene_consistency_step.py:103-120`: `_classify_framing` 함수 삭제
   - `scene_consistency_step.py:123-180`: `_detect_framing_conflicts` body 만 spec §5.2 verbatim snippet 로 rewrite (signature 보존, `"framings"` legacy key 보존)
   - line 6: `import re` 의 사용처가 helper 폐기 후 0 일 가능성 — `import re` 제거 (다른 사용 verify 의무)
4. **Pass verify**: `pytest tests/core/steps/test_scene_consistency_validator.py` → 신규 test 모두 PASS
5. **Wave regression**:
   - `tests/core/steps/test_scene_consistency_status.py` → PASS (status field 별개)
   - `tests/core/test_consumer_verify_completion.py` → PASS (gate signature 보존)
   - **Residue gate (Codex iter 2 I-1 fix)**:
     ```sh
     hits=0
     for token in _classify_framing _ELEMENT_ID_CLOSE_REGEX _DESCRIPTION_CLOSE_KEYWORDS; do
       if rg -n -F "$token" backend/app; then
         hits=1
       fi
     done
     test "$hits" -eq 0
     # expected: exit 0
     ```
6. **Atomic commit**:

```
refactor(area-4-scene-consistency-element-scope-sot-v1): W2 — helper 폐기 + _detect_framing_conflicts enum 직접 비교 rewrite

scene_consistency_step.py:
- L65-72 _ELEMENT_ID_CLOSE_REGEX 삭제 (Gate 1)
- L73-80 _DESCRIPTION_CLOSE_KEYWORDS 삭제 (Gate 1)
- L103-120 _classify_framing 삭제 (semantic regex inference 폐기)
- L123-180 _detect_framing_conflicts body rewrite — spec §5.2 verbatim:
  * e1["element_scope"] (KeyError fail-fast, Gate 4)
  * invalid enum → AppError (step.contract_violation.scene_consistency.element_scope)
  * "framings" legacy metadata key 보존 (Codex iter 1 I2)

test_scene_consistency_validator.py:
- _classify_framing 직접 호출 test 17 삭제
- _detect_framing_conflicts test 6 enum 비교로 rewrite
- 신규 5+ enum-based test (overlap/equal/invalid/missing/non-character_state/framings key 보존)

Residue gate verify (Codex iter 2 I-1 fix): hits=0 form, helper substring backend/app 0 occurrence.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
```

---

## §7. W3 — Consumer Migration + Strict Shape Validator + Fixture Cascade

### §7.1 Goal

`render_prompt_card.py:_FIXED_ELEMENT_REQUIRED_KEYS` 9-field → 10-field (element_scope 추가). pass-through reader 변경 0 (schema validation 통과 의무). fixture cascade — 20+ test file 의 fixed_elements entries 에 element_scope 추가.

### §7.2 Inline BLOCKING (Codex iter 3 권고 1 — 별도로 강조)

**BLOCKING (W3-1)**: `render_prompt_card.py:2853-2858` `_FIXED_ELEMENT_REQUIRED_KEYS` tuple 에 `"element_scope"` 추가 의무 (9-field → 10-field). docstring (`render_prompt_card.py:2932-2934`) "9-field per item" → "10-field per item" 정정.

**BLOCKING (W3-2)**: `is_scene_result_consumer_safe` signature 보존 의무. `scene_context_loader.py:223,235` import path **변경 0**. 함정 19 (signature drift) 회피.

**BLOCKING (W3-3)**: archived fixture (`tests/fixtures/_archive/g4_6_2026-05-16-area-1/*.json`) **변경 금지**. v6 reproduction reference 보존.

### §7.3 Sub-task (6 step atomic)

1. **Pre-step (Tier 1 lesson #1 cascade grep)**: §3.1 grep command 재실행 → file list classify confirm
2. **Test/grep marker**:
   - `tests/unit/test_render_prompt_card.py`: 10-field shape 검증 test 신규 + 기존 fixture migration
   - `_assert_continuity_elements_used_shape` coverage 신규 test (필요시)
   - Fixture migration test: 각 g4_X test 의 fixed_elements entries 에 element_scope 추가
3. **Fail verify**: fixture migration 전 `pytest tests/unit/test_render_prompt_card.py` → fail (10-field validator expects element_scope, fixture 9-field)
4. **Implementation**:
   - `render_prompt_card.py:2853-2858`: `_FIXED_ELEMENT_REQUIRED_KEYS` tuple 끝에 `"element_scope"` 추가
   - `render_prompt_card.py:2932-2934`: docstring "9-field per item" → "10-field per item"
   - `scene_context_loader.py`: 변경 0 (verify only)
   - `detail_steps.py`, `semantic_contract_router.py`, `_evidence_helpers.py`: 변경 0 (pass-through)
   - Fixture migration (20+ active test file 의 fixed_elements entries 에 element_scope 추가):
     - `tests/integration/test_subject_reference_policy_e2e.py`
     - `tests/integration/test_evidence_consumer_wiring.py`
     - `tests/integration/test_g4_1_card_consumer_wiring.py`
     - `tests/integration/test_g4_2_bg_binding_integration.py`
     - `tests/integration/test_g4_3_id_policy_integration.py`
     - `tests/integration/test_g4_4_continuity_integration.py`
     - `tests/integration/test_g4_5a_spatial_integration.py`
     - `tests/unit/test_render_prompt_card.py`, `test_render_prompt_card_integration.py`, `test_render_prompt_card_hash.py`
     - `tests/unit/test_g4_2_background_binding_lift.py`, `test_g4_3_id_policy_lift.py`, `test_g4_4_continuity_lift.py`, `test_g4_5a_spatial_lift.py`
     - `tests/unit/test_evidence_normalize.py`
     - `tests/core/test_scene_detail_analyze_one.py`
     - `tests/core/test_d6_scene_detail_chain_unchanged.py`
     - `tests/prompts/test_scene_detail_continuity_alignment.py`
     - `tests/unit/test_semantic_contract_router.py` (필요시 pass-through fixture)
5. **Pass verify**:
   - `pytest backend/tests/unit backend/tests/integration backend/tests/core backend/tests/prompts` → PASS (B1-B5 unrelated baseline 제외)
   - `_FIXED_ELEMENT_REQUIRED_KEYS` 10-field validator coverage PASS
6. **Atomic commit**:

```
test(area-4-scene-consistency-element-scope-sot-v1): W3 — render_prompt_card 10-field shape + fixture cascade migration (element_scope 추가)

render_prompt_card.py:
- L2853-2858 _FIXED_ELEMENT_REQUIRED_KEYS 9-field → 10-field (element_scope 추가, Codex iter 1 I3)
- L2932-2934 _assert_continuity_elements_used_shape docstring 9 → 10

is_scene_result_consumer_safe signature 보존. scene_context_loader.py import path 변경 0 (함정 19).

Fixture cascade migration (20+ active test file): fixed_elements entries 에 element_scope 추가:
- integration: subject_reference_policy_e2e, evidence_consumer_wiring, g4_1~g4_5a
- unit: render_prompt_card*, g4_2~g4_5a_lift, evidence_normalize, semantic_contract_router
- core: scene_detail_analyze_one, d6_scene_detail_chain_unchanged
- prompts: scene_detail_continuity_alignment

archived fixture (_archive/g4_6_2026-05-16-area-1/*) 변경 금지 (v6 reproduction reference 보존, 함정 20).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
```

---

## §8. W4 — Closure + Canary + Residue + Roadmap

### §8.1 Goal

deterministic closure: schema strict + cp invalidation + residue gate strict 0 + canary fixture 3 시나리오 PASS. roadmap §5.4 update + framing_scale spec line 58 "✓ closed C-4" 표기. closure memo write.

### §8.2 Inline BLOCKING

**BLOCKING (W4-1)**: residue grep = `hits=0; for ...; if rg ...; then hits=1; fi; done; test "$hits" -eq 0` form (Codex iter 2 I-1 fix). `&& exit 1` form 금지.

**BLOCKING (W4-2)**: monitoring trigger 0 (spec §10.3) — Area #3 식 open-ended post-W2 audit log monitoring **불필요**. deterministic closure 만 (schema/version/residue/canary).

### §8.3 Sub-task (6 step atomic)

1. **Pre-step**: W1-W3 commit 모두 완료 verify (`git log --oneline -4`)
2. **Test/grep marker**:
   - Canary fixture 3 시나리오 (`backend/tests/_audit_outputs/area_4_w4/canary_*.jsonl`):
     - `canary_1_full_close_overlap.jsonl` — full + close overlap → `_detect_framing_conflicts` returns non-empty
     - `canary_2_separated_shots.jsonl` — applies_to_shots 겹치지 않음 → returns empty
     - `canary_3_old_v6_cp_force_rerun.jsonl` — schema_version 2 cp → manifest mismatch → 강제 v7 retry verify (Codex plan iter 1 I3 fix — deterministic 조건 명시): tmp checkpoint/cp with `schema_version: 2` and scene_consistency fixed_elements missing `element_scope`; current manifest/schema_version = 3. Assert stale cp is rejected/not reused and v7 path is invoked (`call_structured` mock called or `cp_mismatch`/retry marker observed). No production DB write.
   - Canary fixture replay test: `tests/core/steps/test_scene_consistency_canary_w4.py` (신규)
3. **Fail verify**: 신규 canary test → 일부 case fail (W4 implementation 전 cp invalidation 미확인)
4. **Implementation**:
   - Canary fixture 3 작성 (tmp file or in-memory fixture — 함정 21 deterministic 보장)
   - Canary test 실행 verify
   - **Residue gate strict check** (production code + active prompt + docs):

     ```sh
     # (a) production code — helper substring strict 0
     hits=0
     for token in _classify_framing _ELEMENT_ID_CLOSE_REGEX _DESCRIPTION_CLOSE_KEYWORDS; do
       if rg -n -F "$token" backend/app; then
         hits=1
       fi
     done
     test "$hits" -eq 0

     # (b-d) active prompt v7 — suffix / closed-list residue strict 0 (Codex plan iter 1 C1 fix — `&& exit 1 || true` form 폐기, hits=0 strict)
     hits=0
     if rg -n -F '_close_up' prompts/_base/scene_consistency/7.*; then
       hits=1
     fi
     if rg -n '전신형.*확대형|확대형.*전신형' prompts/_base/scene_consistency/7.*/system.md; then
       hits=1
     fi
     if rg -n '손[·/]손목[·/]이마[·/]눈[·/]입[·/]목|손목[·/]이마[·/]눈' prompts/_base/scene_consistency/7.*/system.md; then
       hits=1
     fi
     test "$hits" -eq 0
     ```

   - Roadmap §5.4 update: `docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md` Area #4 row → closure 표기 ("✓ closed C-4 (Tier 2 #1)" 같은 marker)
   - framing_scale spec line 58 update: `docs/superpowers/specs/2026-05-15-framing-scale-enum-sot-v1-design.md:58` 의 deferred row → "✓ closed C-4" 표기
   - audit doc historical reference (`docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/{00-index,01-code-side-regex-audit}.md`) — historical reference 보존, closure marker 추가 가능
5. **Pass verify**:
   - Canary test 3 PASS
   - Residue gate (a)(b)(c)(d) 모두 exit 0
   - `pytest backend/tests` overall PASS (B1-B5 baseline 제외)
6. **Atomic commit + closure memo write**:

```
docs(area-4-scene-consistency-element-scope-sot-v1): W4 — closure + canary + residue + roadmap §5.4 update

4 closure criteria PASS:
- C1: scene_consistency v7 schema strict + cp invalidation (schema_version 2→3) 강제 v7 rerun
- C2: helper substring backend/app 0 occurrence (hits=0 form)
- C3: active prompt v7 — _close_up suffix / 전신형/확대형 closed-list reasoning / 신체 부위 closed-list 0
- C4: canary fixture 3 — full+close overlap conflict / separated no conflict / old v6 cp force rerun

Canary fixture (backend/tests/_audit_outputs/area_4_w4/):
- canary_1_full_close_overlap.jsonl
- canary_2_separated_shots.jsonl
- canary_3_old_v6_cp_force_rerun.jsonl

Roadmap update:
- specs/2026-05-16-track-b-semantic-debt-roadmap-design.md §5.4 → ✓ closed C-4 (Tier 2 #1)
- specs/2026-05-15-framing-scale-enum-sot-v1-design.md:58 → ✓ closed C-4

monitoring trigger 0 (Codex 권고 — Area #3식 open-ended monitoring 불요). deterministic closure 만.

Closure verdict (spec §10.1 verbatim):
"Area #4 closure complete when scene_consistency v7 producer emits required structured element_scope; code no longer infers close/full from element_id or description; consumer defense remains active and compares element_scope directly; active prompt contains no full/zoom closed phrase list or _close_up suffix guide; cp invalidation/version bump forces v7 rerun; residue gates and canary fixtures pass. No VLM-based validation used."

Non-claim (spec §10.2): P020 status shim 미해결 / P021 broad prompt hygiene 미해결 (Area #7) / shot-level framing_scale 변경 0 / Area #5 미해결.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
```

### §8.4 Closure memo (W4 commit 직후 작성)

Memory file: `memory/session_20260518_area_4_scene_consistency_element_scope_sot_v1_closure.md` — Track B Tier 2 첫 area closure 종합. 다음 area 진입점 (Tier 2 next) 결정 Codex 의논.

---

## §9. Residue Gate Scope Definition

### §9.1 Strict 0 (production code + active prompt)

**Production code** (`backend/app`):
- `_classify_framing` — substring 0
- `_ELEMENT_ID_CLOSE_REGEX` — substring 0
- `_DESCRIPTION_CLOSE_KEYWORDS` — substring 0

verify form (Codex iter 2 I-1):
```sh
hits=0
for token in _classify_framing _ELEMENT_ID_CLOSE_REGEX _DESCRIPTION_CLOSE_KEYWORDS; do
  if rg -n -F "$token" backend/app; then
    hits=1
  fi
done
test "$hits" -eq 0
```

**Active prompt** (`prompts/_base/scene_consistency/7.*`):
- `_close_up` substring 0 (A038 suffix guide 폐기)
- `전신형.*확대형` / `확대형.*전신형` Korean closed-list reasoning 0 (A037)
- `손/손목/이마/눈/입/목` 등 신체 부위 closed-list 0 (Codex iter 1 C1 guard)

### §9.2 보존 (변경 금지)

- `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/**` — historical audit reference 보존
- `docs/superpowers/specs/2026-05-15-framing-scale-enum-sot-v1-design.md:58` — line 58 의 deferred row content 만 "✓ closed C-4" 표기로 update, 나머지 historical 보존
- `backend/tests/fixtures/_archive/g4_6_2026-05-16-area-1/*.json` — v6 reproduction reference 보존
- `backend/tests/_audit_outputs/semantic_string_debt/**` — audit history 변경 X
- `backend/tests/unit/test_scene_consistency_schema_v6.py` — legacy reference 보존 (W1 신규 v7 file 별도 작성, v6 변경 0)
- `prompts/_base/scene_consistency/2.*~6.*` — 이전 version directory 보존

### §9.3 plan-side residue (closure memo 작성 시 verify)

W4 commit 후 plan 자체의 stale wording 점검 — closure memo 작성 시 plan file 안 "expected fail" / "TODO" / "WIP" 등 잔존 metadata 0 confirm.

---

## §10. Commit Message Templates (Atomic 1 Commit per Wave)

각 wave 별 commit message 본문은 §4.5/§5.6/§6.3/§7.3/§8.3 의 verbatim template 사용. 공통:

- subject line < 100 char
- `Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>` trailer 의무 (CLAUDE.md spec)
- atomic 1 commit per wave — Codex 권고 C (red commit 분리 X)
- `--no-verify` / `--no-gpg-sign` 금지 (사용자 hard rule)

---

## §11. No VLM Rule Inline

모든 wave 의 모든 step 에서 [[feedback_no_vlm_dependency]] hard constraint 적용:

- W0: cp/fixture read-only, VLM 호출 0
- W1: prompt v7 text instruction, VLM 0
- W2: helper 폐기 + code structured field 비교, VLM 0
- W3: fixture migration text edit, VLM 0
- W4: canary fixture deterministic code/text, VLM 0
- Closure verdict 검증: 정적 code/test 만, VLM-as-judge 0

Production image generation pipeline (T2I) 의 정상 사용은 본 area 와 무관 — 본 area 의 의사 결정 / 검증 회로에 VLM 의존 0.

---

## §12. Execution Handoff / Codex Review Checklist

### §12.1 Codex 권고 3 항목 reminder (Codex iter 3 권고, plan-level)

W1-W4 inline BLOCKING 중복 박힌 항목 final reminder:

1. **render_prompt_card `_FIXED_ELEMENT_REQUIRED_KEYS` 9→10 cascade** (W3-1) — Codex iter 1 I3 fix. 9-field 유지 시 v7 contract 검증 불가.
2. **Residue shell command `hits=0` 형태 사용 의무** (W2 + W4) — Codex iter 2 I-1 fix. `&& exit 1` form 절대 금지 (no-hit 시 false-fail).
3. **Active prompt v7 = §6.2 verbatim only** (W1) — Codex iter 1 C1 fix. 신체 부위 closed-list / `_close_up`/`_wrist` suffix example 재도입 금지.

### §12.2 Codex review per wave (plan execution 의무)

각 wave commit 후 Codex MCP pane (%0) review 요청 의무:

- W0 commit (skip 시 NO_CP_AVAILABLE markdown commit) → Codex review (W0 instrumentation read-only verify)
- W1 commit → Codex review (schema v7 + prompt v7 verbatim verify + 4 Gate matrix)
- W2 commit → Codex review (helper 삭제 + enum 비교 verify + residue gate)
- W3 commit → Codex review (10-field strict shape + fixture cascade verify)
- W4 commit → Codex range review W1-W4 (closure verdict + Non-claim + residue gate + canary)

매 commit 후 양방향 tmux trigger 의무 (memory rule 7).

### §12.3 push gate (Codex range review APPROVED 후)

Codex W1-W4 range review APPROVED_FOR_PUSH 시 자체 결정 push (사용자 ask X — push 도 둘이 결정, memory rule 7a maximally strict). NEEDS_REVISION 시 fix-up wave.

### §12.4 함정 (spec §11.3 carry + 본 plan execution 신규)

spec §11.3 의 함정 16+6 carry. 본 plan execution 특이 함정:

- **F-1 (W1 prompt version timestamp)**: prompt directory name 의 timestamp = commit 시점 minute level (예: `7.202605181430`). Pre-commit `date +%Y%m%d%H%M` 확정 후 directory 명명, schema_version 상수와 별개.
- **F-2 (W2 import re cleanup)**: helper 삭제 후 `import re` 사용처 0 일 가능성 — `scene_consistency_step.py:4` `import re` 사용 verify, 사용 0 시 제거.
- **F-3 (W3 fixture cascade 누락)**: §3.3 의 24 active test file 외에 fixed_elements fixture 가 있는 다른 test 발견 시 — `git grep -l "fixed_elements" backend/tests | xargs grep -l "element_scope" -L` 같은 inverse grep 으로 추가 file 확인 의무.
- **F-4 (W4 canary fixture deterministic)**: cp file 의존 canary 가 test isolation 위반 → tmp file 또는 in-memory fixture 사용 (함정 21).
- **F-5 (W4 roadmap update timing)**: roadmap update commit 이 W4 atomic 안 — separate W5 commit 만들지 X (Codex 권고 atomic).

### §12.5 외부 review reference

- spec: `docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md` (`b92c101`)
- Area #1 closure (pattern donor): `memory/session_20260516_area_1_id_outlook_reference_policy_sot_v1_closure.md`
- Area #2 closure (pattern donor): `memory/session_20260517_area_2_state_gaze_separation_closure.md`
- Area #3 closure (pattern donor): `memory/session_20260518_area_3_visibility_physical_presence_sot_v1_closure.md`
- Track B roadmap §5.4: `docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md:332-342`
- framing_scale spec line 58 (prerequisite ✓): `docs/superpowers/specs/2026-05-15-framing-scale-enum-sot-v1-design.md:58`
- Codex 의논 workflow rule: `memory/feedback_codex_mcp_discussion_workflow.md` (2026-05-18 strict 화)
- No VLM hard constraint: `memory/feedback_no_vlm_dependency.md`
- LLM-based judgment 4 gate: `memory/feedback_llm_based_judgment.md`
