---
title: Carry-P021 — Scene Consistency Prompt Hygiene v1 Design
date: 2026-05-20
status: closed
roadmap_ref: docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md §5.7 Area #7 (Track B Tier 4 carry follow-up post #7a/#7b/#7c/#7d/Carry-D7d-1/Carry-A099/Carry-A100, audit 02 §11.3/§13/§14/§15 line 317 + line 382 + line 437 + line 475 Carry-P021 scene_consistency 7 enumeration broad source unresolved)
prerequisites:
  - Area #4 (scene_consistency element_scope SOT v1, closed 2026-05-18) — code-side classifier 폐기 완료. Area #4 spec §1.5/§2.3/§3.2/§7.1/§10.2 안 P021 = Area #7 carry / partial-neutral only / closure 선언 X 명시. §7.1 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17` (Area #7 spec 진입 시 closure 의무) — 본 spec §11 provenance 안 명시.
  - Area #7a (visual_world_rules SOT v1, closed 2026-05-19, push `d0410eb`) — abstraction pattern reference. VWR producer 변경 0 boundary preserve.
  - Area #7b (VWR downstream prompt cascade v1, closed 2026-05-19+, push `e751e72`) — 11-site cascade pattern reference. 본 carry 영향 0.
  - Area #7c (t2i_review v6 placeholder example abstraction v1, closed 2026-05-19+, push `62aa2ef`) — placeholder example abstraction pattern reference.
  - Area #7d (cinematography closed-list SOT dual-site v1, closed 2026-05-19+, push `b9c610e`) — dual-site cascade pattern reference.
  - Carry-D7d-1 (scene_detail v28 description align v1, closed 2026-05-19+, push `05d5265`) — TEMPLATE ONLY fix-up 1 doctrine source.
  - Carry-A099 (VWR system.md director_notes prose redesign V8 v1, closed 2026-05-19+, push `146401c`) — prose abstraction lineage pattern donor (process wording presence gate / closed-world full-phrase membership / standalone token global ban X / sha256 byte-identical / marker-wrapped strict residues).
  - Carry-A100 (VWR system.md t2i_context demonym redesign V8+/V9 v1, closed 2026-05-19+, push `0f24492`) — demonym/인구학 abstraction wording lineage pattern donor (시각적 인구학 단서 반영 wording / outlook/character evidence first 원칙 / marker block 외부 underscore-escape variant 금지 / W4 closure docs path-limited 7 file pattern).
non_supersedes:
  - Area #4 (scene_consistency code-side regex 폐기) — producer code `scene_consistency_step.py` 변경 0 boundary preserve.
  - Area #7a / #7b / #7c / #7d — 모두 VWR / t2i_review / cinematography 별도 carry 영역. 본 carry 영향 0.
  - Carry-A099 / Carry-A100 / Carry-D7d-1 — 별도 carry, 본 carry 영향 0.
  - Future Carry-P021-structured (`element_id` opaque UUID / `element_type` enum 확장 / `element_scope` enum 확장 / `applies_to_shots` schema 변경 등 field-shape migration) — 본 v1 scope X, major carry follow-up.
related:
  - docs/superpowers/specs/2026-05-19-carry-p021-q1-q7-outline.md (approved outline, primary reference, Codex amend 3 final round 6 APPROVED_FOR_SPEC_V1_DRAFT)
  - docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md (Area #4 spec, §1.5/§2.3/§3.2/§7.1/§10.2 carry boundary, §7.1 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17`)
  - prompts/_base/scene_consistency/7.202605181210/ (active v7 prompt-pack, abstraction target)
  - backend/app/core/version_registry.py:36, :130, :131 (W2 sync target, 3 logical edits)
  - backend/app/core/step_manifest.py:655-678 (scene_consistency entry, verify-only)
  - backend/app/core/steps/scene_consistency_step.py:36-48, :117-128 (Area #4 producer code SOT, 변경 0 boundary)
  - backend/tests/test_prompt_versions.py:14-17, :35, :48, :58 (W1 helper rename target, 3 사용 site)
  - backend/tests/unit/test_scene_consistency_schema_v7.py:8-11 (literal historical pin, 변경 0)
  - docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md (W4 closure docs target — §11.3 line 317 + §13 line 382 + §14 line 437 + §15 line 475 Carry-P021 rows)
  - docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/01-code-side-regex-audit.md (#17 P1-6 = Area #4 closed code-side dependency reference only)
---

# Carry-P021 — Scene Consistency Prompt Hygiene v1 Design

## 1. Purpose + Scope

### 1.1 Purpose

Area #4 (scene_consistency element_scope SOT v1, 2026-05-18 closed) 는 producer code 안 `_ELEMENT_ID_CLOSE_REGEX` + `_DESCRIPTION_CLOSE_KEYWORDS` + `_classify_framing` 폐기 + LLM emit `element_scope` enum SOT 전환을 완료했다. 그러나 Area #4 spec §1.5/§2.3/§3.2/§7.1/§10.2 verbatim 명시:

> "P021 (system.md L9/L14/L17/L46 시나리오 의존 enumeration) 는 **Area #7 (Prompt Hygiene v2) primary owner**. v1 partial neutral 허용 범위 (W1 prompt v7 rewrite 시): A037/A038 rewrite 가 같은 section (system.md L24-L113) 을 건드림 → incidental cleanup 가능. 시나리오 의존 noun (사망/부상/혈흔 etc.) 만 abstract phrasing 으로 변경 가능. **'P021 closure' 선언 X** — Area #7 가 primary owner 유지."

Area #4 spec §7.1 carry table 안 marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17` (Area #7 spec 진입 시 closure 의무) 가 P021 provenance 로 남아 있다.

본 carry v1 = **scene_consistency v7 prompt-pack hard-prime example phrases + demographic default instruction 의 narrow abstraction (v8 prompt-pack 신규 dir)** (Codex β-narrow PROCEED, α docs-only stale close REJECT / γ broad close REJECT). `fixed_elements` carrier contract (schema, element_scope enum, applies_to_shots minItems:2 등) preserve, schema byte-identical, producer code (`scene_consistency_step.py`) 변경 0, STEP_MANIFEST schema_version=3 preserve.

Codex V3 allowed claim wording:

> `scene_consistency v7 system.md hard-prime English prose example phrases (R1-R5) + demographic default instruction (R6) + JSON example block (JS1/JS2a/JS2b/JS3) were abstracted to remove closed-list semantic hard-prime examples while preserving the existing fixed_elements carrier contract.`

### 1.2 In-scope (Codex β-narrow + 4 narrow guards 흡수)

- **scene_consistency v8 신규 prompt-pack dir**: `prompts/_base/scene_consistency/8.UTC_TIMESTAMP/` (2 file new — `system.md` modified + `schema.json` byte-identical sibling per Codex V3 OQ-1 Option A pin + Carry-A099/A100 lineage 정합):
  - `system.md` modified (line 13/14/18/22/58/61 R1-R6 narrow abstraction + line 89-110 JSON example block 전체 제거 + abstract schema skeleton 변환 per Codex V3 OQ-1 Option A pin; line 11 protective negative wording preserve obligatory; 분석 원칙 1-10 안 abstract guidance + 고정 요소 유형 1-3 section preserve obligatory; final self-questioning sentence X — Carry-A099/A100 lineage 와 다름).
  - `schema.json` byte-identical copy from `7.202605181210/schema.json` (sha256 match obligatory, Codex β-narrow + outline §2.1.2 description pollution 0 verify 흡수).
- **`backend/app/core/version_registry.py` 3 logical edits** (W2 sync target, Codex β-narrow + Codex outline N-3 정합 + Codex V3 OQ-5 verify):
  - Site 1 — `:36` `MODULE_VERSIONS["scene_consistency"]: "2.5.0"` → `"2.6.0"` (narrow semver minor bump, content-only example abstraction = backward-compat per Codex OQ-4 resolved verdict).
  - Site 2 — `:130` `_MODULE_INFO["scene_consistency"]["prompt_dependency"]: "scene_consistency/v7"` → `"scene_consistency/v8"`.
  - Site 3 — `:131` `_MODULE_INFO["scene_consistency"]["updated_at"]: "2026-05-18"` → `"2026-05-20"` (KST drafting date, Codex V2 정합).
- **`backend/tests/test_prompt_versions.py` W1 test-compat historical cleanup** (Codex V3 OQ-6 expansion 흡수):
  - helper `_scene_consistency_v7_dir()` → `_scene_consistency_v7_historical_dir()` rename + literal pin `REPO_ROOT / "prompts" / "_base" / "scene_consistency" / "7.202605181210"`.
  - 3 사용 site rename 흡수 — **line 35 (`test_prompt_v7_active_loader_matches_file` body) + line 48 (`test_prompt_v7_no_closed_framing_list` body) + line 58 (`test_prompt_v7_no_element_id_suffix_guide` body)** = 본 session direct verify 3 곳 (outline §2.4 line 48/58 외 line 35 추가 발견, OQ-6 expansion 흡수 명시).
  - 3 test rename — `test_prompt_v7_active_loader_matches_file` → `test_prompt_v7_historical_loader_anchor` + `test_prompt_v7_no_closed_framing_list` → `test_prompt_v7_historical_no_closed_framing_list` + `test_prompt_v7_no_element_id_suffix_guide` → `test_prompt_v7_historical_no_element_id_suffix_guide` (active loader proof → historical anchor proof).
  - Existing assertions preserve (Codex V3 OQ-6 명시) — element_scope presence + `["full", "close"]` enum + `element_scope 결정 (필수 emit)` system.md presence + FORBIDDEN_PROMPT_PATTERNS regex absence + `opaque snake_case` system.md presence + `암시하지 말` system.md presence 모두 preserve.
  - docstring 안 active wording → historical pin wording rewording (예: `Area #4 W1 — element_scope SOT prompt v7 regression` → `Area #4 W1 — element_scope SOT prompt v7 historical anchor (Carry-P021 W1 transitioned to historical pin)`).
  - sha256 byte-identical anchor gate W1 X (Codex V3 OQ-6 명시) — sha256 gate는 W3 G5 안 보존.
- **W3 integrated test** (file-level new, no live LLM + NO VLM + no regex semantic per Codex β-narrow + 4-Gate Boundary Doctrine):
  - `backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py` (7 Gate G1-G7 verify, Carry-A099/A100 lineage 정합).
- **W4 closure docs** (path-limited 5 repo-local docs + external memory, Codex V4 정합 + Carry-A099/A100 lineage; Codex amend 2 IMPORTANT 1 fix — line 69 §1.2 in-scope bullet W4 count residue 정정):
  - 본 spec frontmatter `status: draft` → `status: closed` + §12 in-place replace.
  - Carry-P021 plan (drafting closure, frontmatter status narrow).
  - Roadmap §5.7 Sub-area (b) Phase 1+/Phase 2+ post-Carry-A100 carry follow-up bullet narrow append `Carry-P021 resolved by W1-W4 — scene_consistency v7 system.md hard-prime examples abstracted (v8 prompt-pack `8.202605191744`)`.
  - Audit 02 §11.3 line 317 + §13 line 382 + §14 line 437 + §15 line 475 Carry-P021 rows narrow update `Carry-P021 resolved by W1-W4`.
  - Audit 02 §16 신설 Carry-P021 Closure section (Carry-A099/A100 lineage §15 신설 정합).
  - Area #4 v1 spec §1.5/§2.3/§3.2/§7.1/§10.2 narrow update — Carry-P021 status `Area #7 carry, partial neutral 후 closure 선언 X` → `resolved by Carry-P021 W1-W4`. §7.1 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17` Status column narrow update (`resolved by Carry-P021 W3 G3 STRICT_RESIDUES marker-wrapped catalog`).

### 1.3 Out-of-scope (Codex V3 OQ resolve + 4 narrow guard 흡수)

- **`fixed_elements` field carrier shape change**: `element_id` opaque snake_case / `element_type` enum 3 entry / `element_scope` enum 2 entry / `applies_to_shots` minItems:2 / `description`/`source_facts`/`visual_inferences`/`creative_decisions`/`confidence` enum 모두 preserve. Schema shape migration X.
- **`schema.json` description-only wording change**: byte-identical default lock (Codex β-narrow + outline §2.1.2 description pollution 0 verify 흡수). Current schema description 자체는 generic enough, hard-prime 부재. Schema description change = open option X unless new concrete finding + Codex re-approve scope.
- **STEP_MANIFEST `scene_consistency` entry full body 변경** (Codex V3 OQ-5 verify-only 정합): `step_manifest.py:655-678` 12 sub-field (label/category/order/default_model/provider/depends_on/fan_out/applicability/step_type/lifecycle/resume_sensitive/allow_partial_downstream) + `schema_version: 3` 모두 preserve. W2 W3 안 file edit 0. W3 test = `STEP_MANIFEST["scene_consistency"]["schema_version"] == 3` verify only (Codex V3 OQ-5 명시).
- **`SCENE_CONSISTENCY_SCHEMA_VERSION` constant 변경**: `scene_consistency_step.py:40` `SCENE_CONSISTENCY_SCHEMA_VERSION = 3` preserve. Content-only example abstraction = field-shape migration 아님 (schema_version preserve canary).
- **Producer code (`scene_consistency_step.py`) 변경 0** (Codex β-narrow + Area #4 boundary 정합): `:36-48` Area #4 SOT comment block + `:51-68` `_normalize_applies_to_shots` + `:71-140` `_detect_framing_conflicts` element_scope 직접 read + KeyError schema violation fail-fast 모두 preserve. W1-W4 안 file edit 0.
- **Replacement prose = new closed-list category inventory**: enumerated category example (예: fixed list `rest_state / wound_state / window_damage / bedsheet_position` 등) 금지. 본 spec 안 process wording 으로 추상화 — `원문에 명시된 inactive/restful pose 또는 localized 환경/소품 상태는 구체 자세/위치/형태 그대로 기록하고, 시나리오 의존 특정 noun(부상/혈흔/창문 형태 등)을 prompt-pack 안 hard-prime 예시로 박지 않는다`. Illustrative design note 사용 시 closed taxonomy 아님 explicit 명시 (Codex V3 OQ-1 Option A pin 정합).
- **Standalone token global ban**: `East Asian`, `body_pose_canonical`, `character_state`, `인종`, `국적`, `상처`, `혈흔` 등 single token / fragment global ban X (Codex V3 OQ-3 + Carry-A100 lineage 정합). abstract category descriptor 안 자연 사용 보존, residue gate = full-phrase membership only.
- **20+ test file 대규모 rewrite** — Codex 4 category 안 unrelated consumers (≥12 files: `test_render_prompt_card.py` / `test_evidence_normalize.py` / `test_consumer_verify_completion.py` / `test_scene_detail_analyze_one.py` / `test_scene_analysis_dto.py` / `test_scene_consistency_canary_w4.py` / `test_scene_consistency_status.py` / `test_verify_completion.py` / `test_w6_prompt_injection.py` / `test_evidence_consumer_wiring.py` / `test_scene_reference_service.py` / `test_area_d_next_shot_dependency_t2i.py`) 변경 0. W1-W3 atomic 안 영향 0 기대.
- **`tests/unit/test_scene_consistency_schema_v7.py` 변경 0** (outline §2.4 + 본 session direct verify 확인): 이미 literal pin `"7.202605181210"` (line 10), Carry-A099 `_v8_dir()` 변환 패턴과 다름.
- **`tests/unit/test_scene_consistency_schema_v6.py` 변경 0** (v6 historical pin 정합).
- **DB row override**: 본 carry W1-W3 안 prompt DB row write 0 (Carry-A099/A100 lineage 정합).
- **Field-shape migration** (`element_id` opaque snake_case → opaque UUID / `element_type` enum 확장 / `element_scope` enum 확장 / `applies_to_shots` minItems 변경 / JSON example structured schema generation 등) = **Future Carry-P021-structured** deferred (major carry / future area follow-up, Codex β-narrow 명시).
- **VLM / live LLM / semantic regex / standalone-token residue gates** — 모두 ban (4-Gate Boundary Doctrine).
- **TEMPLATE ONLY / self-reference rule applies from spec v1 onward**: no literal angle-bracket placeholders outside marker blocks ([[session_20260519_carry_d7d_1_v1_closure]] fix-up 1 강화 doctrine + [[session_20260519_carry_a100_v1_closure]] N-1 정합).

### 1.4 4-Gate Boundary Doctrine 적용 ([[feedback_llm_based_judgment]] 정합)

| Gate | Rule | 본 carry 적용 |
|---|---|---|
| Gate 1 Semantic Regex Ban | open-world semantic 판단 code regex X | W3 test 안 semantic regex 0. R1-R6 + JS1/JS2a/JS2b/JS3 = full-phrase membership only (`str.__contains__` / `rg -F`). Producer code (`scene_consistency_step.py`) 변경 0 = Area #4 closed-world enum 직접 비교 preserve. |
| Gate 2 Prompt Closed-List Ban refined full-phrase only | full-phrase ban; standalone token global ban X | 10 strict R-id + 2 optional full-phrase ban (marker-wrapped catalog 안). 시나리오 의존 noun 추상화. abstract category descriptor 안 standalone word (`East Asian`, `body_pose_canonical`, `character_state`, `인종`, `국적`, `상처`, `혈흔`) 자연 사용 보존 (Codex V3 OQ-3 정합). |
| Gate 3 Structured SOT Required | partial remediation in v1 | v1 = scene_consistency v7→v8 prompt-pack content abstraction only (carrier `fixed_elements` schema preserve). Structured SOT completion claim X — Future Carry-P021-structured (element_id opaque UUID / element_type enum 확장 등) deferred. Area #4 producer code element_scope enum SOT preserve. |
| Gate 4 No Silent Fallback | silent default 추가 X | Producer code `_detect_framing_conflicts` element_scope 직접 read + KeyError schema violation fail-fast (`scene_consistency_step.py:117-128`) preserve. v8 prompt-pack 안 abstract instruction 으로 LLM emit element_scope 강제. `call_structured` jsonschema validation 실패 시 retry 자동 trigger preserve. |

## 2. W0 Evidence Inventory (live, 본 instance 2026-05-20)

### 2.1 Active scene_consistency pack (claude direct read verified, 본 session)

- Latest dir = `prompts/_base/scene_consistency/7.202605181210/` (2 file: `system.md` 110 line + `schema.json` 76 line).
- `system.md` candidate residue anchors **R1-R6 + JS1/JS2a/JS2b/JS3 + 2 optional JS-opt** = line 13/14/18/22/58/61 + line 89-110 (W0.2 inventory verified, Codex spot-check confirmed + 본 session direct line-by-line verify 일치).
- `system.md` line 11 protective negative wording = `원문이 묘사한 상태만 기록. 장르 편향으로 상처·혈흔을 임의 추가 금지` (preserve obligatory, outline §2.1.1 N-1B 흡수 Codex 정합 + 본 session direct verify).

#### 2.1.1 Strict R catalog (marker-wrapped, single STRICT_RESIDUES constant per Codex β-narrow + outline §2.1.1 N-5 흡수 정합)

Closed-world test constants reference only; marker block 외부 = R-id reference only (Codex V3 OQ-2 명시).

<!-- HISTORICAL AUDIT TRAIL — BEGIN -->
- **line 11 (non-R protective reference, preserve target)**: `원문이 묘사한 상태만 기록. 장르 편향으로 상처·혈흔을 임의 추가 금지` — protective negative wording, abstraction target X (Codex outline N-1B 흡수, hard-prime 증명 X 시 preserve).
- **line 13** R1: `예 (rest state): "a young person resting on a sofa, curled on the left side, one arm tucked under the cheek, eyes closed, a light blanket draped over the shoulder"` — hard-prime English prose example, abstraction target.
- **line 14** R2: `예 (specific localized condition described in text): "a figure seated against a wall, head tilted back, eyes closed, a small bandage wrapped around the left wrist" — 원문에 해당 상태가 명시된 경우만` — hard-prime English prose + Korean caveat (exact-match testing 시 whole line membership).
- **line 18** R3: `예: "the left pane of the window is shattered with jagged glass edges remaining in the frame"` — hard-prime English prose, abstraction target.
- **line 22** R4: `예: "a crumpled white bedsheet hanging off the bed edge, touching the floor"` — hard-prime English prose, abstraction target.
- **line 58** R5: STRICT_RESIDUES constant value = quoted English concrete posture phrase only (Codex V3 OQ-2 정합) — `lying face-down on the wooden floor, left arm extended forward, right knee slightly bent`. The full line `5. **구체적 자세/위치**: "lying down" 같은 모호한 표현 금지 → "lying face-down on the wooden floor, left arm extended forward, right knee slightly bent"` is the audit-historical line; only the inner quoted concrete posture phrase is the strict residue target. Korean rule label + 분석 원칙 1-10 안 abstract guidance preserve.
- **line 61** R6: `8. **인종/국적 명기**: 인물 묘사 시 인종/국적을 반드시 포함` — demographic default instruction (Carry-A100 lineage demonym redesign 정합 — `반드시 포함` → `명시된 단서 반영 원칙` abstraction; full-phrase residue target).
- **line 89-110** JSON sub-anchors (Codex V3 OQ-1 Option A pin = JSON example block 전체 제거 + abstract schema skeleton 변환):
  - **JS1**: `description: "an East Asian person lying motionless on the left side, left arm bent near the face, eyes closed"`
  - **JS2a**: `S## action: 'A figure lies motionless on the floor.'` (source_facts split sub-anchor)
  - **JS2b**: `scene heading: NIGHT, small interior room` (source_facts split sub-anchor)
  - **JS3**: `left-side recumbent pose (text only specifies motionless, not orientation)` (visual_inferences sub-anchor)
  - **JS-opt-1**: `body_pose_canonical` (element_id, Option A pin 후 JSON example 전체 제거 시 optional, abstract schema skeleton 변환 시 X).
  - **JS-opt-2**: `element_scope='full' to anchor body silhouette across selected shots` (creative_decisions, Option A pin 후 optional).
<!-- HISTORICAL AUDIT TRAIL — END -->

**STRICT_RESIDUES single constant** (Codex outline N-6 정합, single constant 안 10 strict ids R1-R6 + JS1/JS2a/JS2b/JS3 모두 포함; 옛 ambiguous `R1_R6_STRICT + JS1_JS3_STRICT` 분리 명명 폐기). exact wording 정의 = 상기 marker block 안 only. marker block 외부 = R-id reference only.

### 2.2 Producer code (Area #4 SOT, 변경 0 boundary per Codex β-narrow)

- `backend/app/core/steps/scene_consistency_step.py:36-48`: Area #4 v7 element_scope LLM emit SOT comment block (v6 regex+keyword+classifier trio 폐기 anchor). `SCENE_CONSISTENCY_SCHEMA_VERSION = 3` (line 40) preserve.
- `:51-68`: `_normalize_applies_to_shots` (applies_to_shots → int set normalization, 변경 0).
- `:71-140`: `_detect_framing_conflicts` element_scope 직접 read + KeyError schema violation fail-fast (Gate 4) preserve. `s1 = e1["element_scope"]` / `s2 = e2["element_scope"]` direct enum read (line 119-120), AppError invalid enum (line 121-128), legacy metadata key `framings` preserve.

### 2.3 Schema (`schema.json` 76 line) byte-identical preserve list (Codex β-narrow + outline §2.1.2 description pollution 0 verify)

Preserve obligatory (structured SOT, byte-identical 권장):
- `element_type` enum `["character_state", "environment_state", "persistent_prop"]` (line 23)
- `element_scope` enum `["full", "close"]` (line 35)
- `confidence` enum `["high", "medium", "low"]` (line 61)
- `applies_to_shots` minItems 2 (line 41)
- `required` 10 field (line 65-69)
- `additionalProperties false` (line 70)

9 description-only field abstract OK (pollution 0 verified): element_id / character_name / description / element_scope / applies_to_shots / source_facts / visual_inferences / creative_decisions / confidence — 모두 closed-world abstract instruction, hard-prime example phrase 0.

### 2.4 Version registry / step_manifest production wiring

#### 2.4.1 `version_registry.py` 3 logical edit (W2 sync target, claude direct read verify 완료)

- **Site 1** — `:36` `MODULE_VERSIONS["scene_consistency"]: "2.5.0"` (Area #4 anchor comment preserve) → `"2.6.0"` (narrow semver minor bump, Codex outline N-3 + OQ-4 resolved verdict 정합 + W2 안 line 36 inline comment narrow append `Carry-P021 hard-prime example abstraction`).
- **Site 2** — `:130` `_MODULE_INFO["scene_consistency"]["prompt_dependency"]: "scene_consistency/v7"` → `"scene_consistency/v8"`.
- **Site 3** — `:131` `_MODULE_INFO["scene_consistency"]["updated_at"]: "2026-05-18"` → `"2026-05-20"` (KST drafting date, Codex V2 정합) + optional inline comment narrow append `Carry-P021`.

#### 2.4.2 `step_manifest.py:655-678` scene_consistency entry (verify-only, Codex V3 OQ-5 정합)

- 12 sub-field 모두 preserve: `label: "씬 시각적 일관성"` / `category: "analysis"` / `order: 19.9` / `default_model: "gemini-pro"` / `provider: "gemini"` / `schema_version: 3` (line 666) / `depends_on: [...]` / `fan_out: False` / `applicability: "always"` / `step_type: "transform"` / `lifecycle: "active"` / `resume_sensitive: True` / `allow_partial_downstream: False`.
- W2 안 file edit 0 (Codex V3 OQ-5 명시 `verify-only, not a W2 edit target`).
- W3 test 안 `STEP_MANIFEST["scene_consistency"]["schema_version"] == 3` verify only (Codex V3 OQ-5 명시 default).

### 2.5 Hardcoded test pin (Carry-A099 lineage 정합 + Codex outline 정정)

- `backend/tests/unit/test_scene_consistency_schema_v7.py:8-11`: 이미 literal historical pin `"7.202605181210"` 사용 — **active-to-historical helper 전환 필요 X** (Carry-A099 `_v8_dir()` 변환 패턴과 다름, 이미 historical pin 정합). 9 jsonschema validate test 모두 preserve.
- `backend/tests/unit/test_scene_consistency_schema_v6.py`: v6 historical pin 정합, 변경 0.
- `backend/tests/test_prompt_versions.py` W1 영향 site (Codex V3 OQ-6 expansion 흡수, **본 session direct verify 3 사용 site**):
  - `:7` `V6_DIR = REPO_ROOT / "prompts" / "_base" / "scene_consistency" / "6.202605031033"` (v6 historical literal pin, 변경 0).
  - `:10` `# Area #4 W1 — scene_consistency v7 (element_scope SOT)` (Area #4 anchor reaffirm, W1 안 narrow append `# (Carry-P021 W1 historical pin)`).
  - `:11` `SC_BASE = REPO_ROOT / "prompts" / "_base" / "scene_consistency"`.
  - `:14-18` `_scene_consistency_v7_dir()` helper — **active glob resolution, v8 활성화 시 stale wording** (W1 rename target).
  - `:34` `test_prompt_v7_active_loader_matches_file` — **W1 rename + body docstring rewording target**.
  - `:35` `_scene_consistency_v7_dir()` 사용 site #1 (`test_prompt_v7_active_loader_matches_file` body).
  - `:46` `test_prompt_v7_no_closed_framing_list` — **W1 rename + body docstring rewording target**.
  - `:48` `_scene_consistency_v7_dir()` 사용 site #2 (`test_prompt_v7_no_closed_framing_list` body).
  - `:56` `test_prompt_v7_no_element_id_suffix_guide` — **W1 rename + body docstring rewording target**.
  - `:58` `_scene_consistency_v7_dir()` 사용 site #3 (`test_prompt_v7_no_element_id_suffix_guide` body).
  - `:67` `test_scene_consistency_v6_system_has_4_fields` (v6 historical, 변경 0).
  - `:72` `test_scene_consistency_v6_system_blocks_legacy_output` (v6 historical, 변경 0).
  - `:77-89` `TestEvidenceFieldsInPrompts` 안 scene_detail v14 tests (변경 0).

### 2.6 Test impact 4 category mapping (Codex outline §2.5 정합)

1. **Direct prompt/version tests** (W1 영향, 1 file): `test_prompt_versions.py` (3 helper 사용 site rename + 3 test rename + literal historical pin).
2. **Schema historical tests** (변경 0, 2 file): `tests/unit/test_scene_consistency_schema_v7.py` (literal pin) + `test_scene_consistency_schema_v6.py`.
3. **Manifest/version registry tests** (W2 영향 + W3 verify, 5 file): `tests/test_step_manifest_v3.py` + `test_manifest_fields.py` + `test_step_catalog.py` + `tests/unit/test_g3_2_manifest_dag.py` + `test_sync_v3.py` — version_registry `"2.5.0"` / `"2.6.0"` hardcode + `schema_version 3` preserve verify.
4. **Unrelated consumers** (변경 0, ≥12 file): `test_render_prompt_card.py` / `test_evidence_normalize.py` / `test_consumer_verify_completion.py` / `test_scene_detail_analyze_one.py` / `test_scene_analysis_dto.py` / `test_scene_consistency_canary_w4.py` / `test_scene_consistency_status.py` / `test_verify_completion.py` / `test_w6_prompt_injection.py` / `test_evidence_consumer_wiring.py` / `test_scene_reference_service.py` / `test_area_d_next_shot_dependency_t2i.py` — W1-W3 atomic 안 영향 0 기대.

### 2.7 Minimal pytest bundle (Codex outline N-7 흡수)

- **W1 bundle**: `backend/.venv/bin/pytest backend/tests/test_prompt_versions.py -v --tb=short` (primary, helper rename + historical pin).
- **W2 bundle**: `backend/.venv/bin/pytest backend/tests/test_prompt_versions.py backend/tests/test_step_manifest_v3.py backend/tests/test_manifest_fields.py backend/tests/test_step_catalog.py backend/tests/test_sync_v3.py backend/tests/unit/test_g3_2_manifest_dag.py backend/tests/unit/test_scene_consistency_schema_v7.py -v --tb=short` (prompt/version + manifest/version-registry + v7 schema historical regression).
- **W3 bundle**: `backend/.venv/bin/pytest backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py -v --tb=short` (W3 신규 integrated test) + W2 bundle 전체 regression.
- **20+ unrelated consumer (category 4)**: W1-W3 안 enumeration required X (변경 0이라 W1-W3 atomic 안 영향 0 기대). Optional canary = W4 closure 전 `pytest backend/tests -q` (full pass 권장, blocker 발견 시 W4 차단 + 재 amend).

## 3. Sync Contract (v8 prompt-pack + version_registry 3 logical edits + STEP_MANIFEST verify-only + production code rewrite 0)

| # | site | scope | action |
|---|---|---|---|
| 1 | `prompts/_base/scene_consistency/8.202605191744/system.md` | new dir file 1 | line 13/14/18/22/58/61 R1-R6 narrow abstraction + line 89-110 JSON example block 전체 제거 + abstract schema skeleton 변환 (Codex V3 OQ-1 Option A pin). line 11 protective + 분석 원칙 1-10 abstract guidance + 고정 요소 유형 1-3 section preserve. |
| 2 | `prompts/_base/scene_consistency/8.202605191744/schema.json` | new dir file 1 | byte-identical copy from `7.202605181210/schema.json` (sha256 match obligatory, Codex β-narrow + outline §2.1.2 description pollution 0 verify + Carry-A099 G3 lineage 정합). |
| 3 | `backend/app/core/version_registry.py:36` Site 1 | 1 line modify | `MODULE_VERSIONS["scene_consistency"]: "2.5.0"` → `"2.6.0"` + line 36 inline comment narrow append (`Carry-P021 hard-prime example abstraction`). |
| 4 | `backend/app/core/version_registry.py:130` Site 2 | 1 line modify | `_MODULE_INFO["scene_consistency"]["prompt_dependency"]: "scene_consistency/v7"` → `"scene_consistency/v8"`. |
| 5 | `backend/app/core/version_registry.py:131` Site 3 | 1 line modify | `_MODULE_INFO["scene_consistency"]["updated_at"]: "2026-05-18"` → `"2026-05-20"` + optional inline comment narrow append. |
| 6 | `backend/app/core/step_manifest.py:655-678` | verify-only | scene_consistency entry 12 sub-field + `schema_version: 3` 모두 preserve (no edit, Codex V3 OQ-5 명시). |
| 7 | `backend/app/core/steps/scene_consistency_step.py:36-140` | verify-only | Area #4 SOT producer code 변경 0 (`SCENE_CONSISTENCY_SCHEMA_VERSION = 3` preserve + element_scope LLM emit SOT preserve + `_normalize_applies_to_shots` preserve + `_detect_framing_conflicts` enum 직접 read fail-fast preserve). |
| 8 | System prompt source-path proof via `get_effective_source` dict + schema sibling existence proof + optional `load_schema` content smoke (Codex amend 1 IMPORTANT 1/2 fix) | verify-only | `get_effective_source("scene_consistency", "system", db=None)` returns dict `{"candidates": {"file": {"version": "8.202605191744", "path": ".../scene_consistency/8.202605191744/system.md"}, ...}}`. Schema proof = system path sibling `schema.json` file existence + path substring `/scene_consistency/8.` (`get_effective_source()` `.md` stem only, schema source-path proof X). `load_prompt`/`load_schema` = content-load smoke only, source-path proof X. plain lexicographic sort tail 위험 회피 (Carry-A099 G1 lineage Codex IMPORTANT 3 정합). |

## 4. W1 Implementation Contract (1 atomic commit) — test_prompt_versions.py historical cleanup

### 4.1 Commit boundary

- Single atomic commit — `test_prompt_versions.py` 1 file modify (helper rename + 3 사용 site rename 흡수 + 3 test rename + body docstring rewording). prompt-pack 변경 0, production code 변경 0.
- Commit subject: `W1(carry-p021-scene-consistency-prompt-hygiene-v1): test_prompt_versions.py historical cleanup — _scene_consistency_v7_dir() → _scene_consistency_v7_historical_dir() + 3 test rename historical anchor (1 file modify, behavioral change 0)`

### 4.2 File operations (1 file modify)

`backend/tests/test_prompt_versions.py`:

- **(a) helper rename + literal pin**: line 14-18 `_scene_consistency_v7_dir()` → `_scene_consistency_v7_historical_dir()` function rename + body refactor — active glob resolution 폐기 + literal pin `REPO_ROOT / "prompts" / "_base" / "scene_consistency" / "7.202605181210"` 반환. existing assertion `assert v7_dirs, "scene_consistency v7 디렉토리 없음"` 폐기 (literal pin = 디렉토리 존재 강제 X, file-level path existence test는 W3 integrated test G7 안 보존).
- **(b) line 10 comment narrow append**: `# Area #4 W1 — scene_consistency v7 (element_scope SOT)` → `# Area #4 W1 — scene_consistency v7 (element_scope SOT) — Carry-P021 W1 historical pin (transitioned to v8 active in `8.202605191744`).
- **(c) 3 test rename + 3 사용 site rename 흡수** (Codex V3 OQ-6 expansion 흡수, **본 session direct verify 3 사용 site**):
  - line 34 `test_prompt_v7_active_loader_matches_file` → `test_prompt_v7_historical_loader_anchor` + body line 35 `v7_dir = _scene_consistency_v7_dir()` → `v7_dir = _scene_consistency_v7_historical_dir()` + docstring rewording from active loader proof to historical anchor proof (element_scope presence + enum + system.md key clause preserve).
  - line 46 `test_prompt_v7_no_closed_framing_list` → `test_prompt_v7_historical_no_closed_framing_list` + body line 48 `v7_dir = _scene_consistency_v7_dir()` → `v7_dir = _scene_consistency_v7_historical_dir()` + docstring rewording (A037 closed-list signature 0 historical anchor proof).
  - line 56 `test_prompt_v7_no_element_id_suffix_guide` → `test_prompt_v7_historical_no_element_id_suffix_guide` + body line 58 `v7_dir = _scene_consistency_v7_dir()` → `v7_dir = _scene_consistency_v7_historical_dir()` + docstring rewording (A038 element_id opaque historical anchor proof).
- **(d) Existing assertions preserve** (Codex V3 OQ-6 명시): element_scope presence (`"element_scope" in item_props`) + `["full", "close"]` enum (`item_props["element_scope"]["enum"] == ["full", "close"]`) + `"element_scope" in system_text` + `"element_scope 결정 (필수 emit)" in system_text` + `FORBIDDEN_PROMPT_PATTERNS` regex absence (`not re.search(pattern, system_text)`) + `"opaque snake_case" in system_text` + `"암시하지 말" in system_text or "암시하지말" in system_text` 모두 preserve. behavioral change 0.
- **(e) sha256 byte-identical anchor gate W1 X** (Codex V3 OQ-6 명시): sha256 gate는 W3 G5 안 보존, W1 안 추가 X.

### 4.3 Out-of-scope (W1)

- v6 historical (line 7 `V6_DIR` + line 67 `test_scene_consistency_v6_system_has_4_fields` + line 72 `test_scene_consistency_v6_system_blocks_legacy_output`) 변경 0.
- `tests/unit/test_scene_consistency_schema_v7.py` (literal historical pin 이미 OK) 변경 0.
- v8 prompt-pack 생성 X (W2 안).
- production code 변경 0.
- 분류 4 category 안 unrelated consumer (≥12 file) 변경 0.

### 4.4 Pre-commit verify gate (W1, 4 check)

- **(a) Helper rename**: `grep -n "_scene_consistency_v7_dir\b" backend/tests/test_prompt_versions.py` exit 1 (no match outside `_scene_consistency_v7_historical_dir` form, helper symbol 완전 historical 전환).
- **(b) Literal historical pin presence**: `grep -F '"prompts" / "_base" / "scene_consistency" / "7.202605181210"' backend/tests/test_prompt_versions.py` exit 0 (helper body literal pin substring).
- **(c) 3 test rename presence**: `grep -nE 'def test_prompt_v7_historical_(loader_anchor|no_closed_framing_list|no_element_id_suffix_guide)' backend/tests/test_prompt_versions.py` 결과 3 hit.
- **(d) Existing assertions preserve regression** (Codex amend 1 IMPORTANT 3 + amend 2 MINOR 1 fix — old nine-test count wording drift 정정, live collect 기준 actual test def count; backticked literal grep-gate confusion 회피): targeted pytest `backend/.venv/bin/pytest backend/tests/test_prompt_versions.py -v --tb=short` 전체 file ALL PASS. file 안 test def count = live collect 결과 (실측 ~18 test def: v7 3 renamed + v6 2 historical + scene_detail v14 4 + 기타 prompt_versions tests). 모두 preserve.

### 4.5 Targeted pytest (W1)

`backend/.venv/bin/pytest backend/tests/test_prompt_versions.py -v --tb=short` — ALL PASS 의무.

## 5. W2 Implementation Contract (1 atomic commit) — v8 producer prompt-pack + version_registry sync

### 5.1 Commit boundary

- Single atomic commit — `prompts/_base/scene_consistency/8.202605191744/system.md` + `schema.json` (2 file new) + `backend/app/core/version_registry.py` (1 file modify, 3 logical edits).
- Commit subject: `W2(carry-p021-scene-consistency-prompt-hygiene-v1): v8 producer prompt-pack + version_registry sync — system.md hard-prime example abstraction + schema.json byte-identical + 3 logical edits (2 file new + 1 file modify)`

### 5.2 File operations

#### 5.2.1 v8 prompt-pack 신규 dir (2 file new)

- **(a) `mkdir -p prompts/_base/scene_consistency/8.${UTC}`** (where `UTC=$(date -u +%Y%m%d%H%M)`).
- **(b) `cp prompts/_base/scene_consistency/7.202605181210/schema.json prompts/_base/scene_consistency/8.${UTC}/schema.json`** (byte-identical, sha256 match obligatory).
- **(c) `cp prompts/_base/scene_consistency/7.202605181210/system.md prompts/_base/scene_consistency/8.${UTC}/system.md`**; then modify:
  - **R1 line 13 abstraction** (`예 (rest state): "a young person resting on..."` → preserve generic abstract clause `원문에 명시된 inactive/restful pose는 구체 자세, 팔다리 위치, 시선 상태 그대로 기록한다` 안 흡수, 예 (rest state) 블록 전체 제거).
  - **R2 line 14 abstraction** (`예 (specific localized condition described in text): "a figure seated..."` 전체 제거 + `원문에 명시된 localized 인물 상태는 원문 묘사 그대로 기록하고 LLM 추론으로 확장하지 않는다` clause 흡수).
  - **R3 line 18 abstraction** (`예: "the left pane of the window is shattered..."` 전체 제거 + `원문에 명시된 환경 상태(창문/문/벽/조명 등)는 원문 묘사 그대로 기록한다` clause 흡수).
  - **R4 line 22 abstraction** (`예: "a crumpled white bedsheet..."` 전체 제거 + `원문에 명시된 소품 위치/상태는 원문 묘사 그대로 기록한다` clause 흡수).
  - **R5 line 58 abstraction** (Codex V3 OQ-2 strict residue constant boundary 정합) — quoted English concrete posture phrase `lying face-down on the wooden floor, left arm extended forward, right knee slightly bent` 전체 제거. Korean rule label `5. **구체적 자세/위치**: "lying down" 같은 모호한 표현 금지` preserve + 후속 clause abstract lift (예: `"lying down" 같은 모호한 표현 대신 원문에 명시된 자세/팔다리 위치/시선 상태를 그대로 기록한다`).
  - **R6 line 61 abstraction** (Codex V3 OQ-3 default pin Carry-A100 lineage 정합) — 전체 줄 `8. **인종/국적 명기**: 인물 묘사 시 인종/국적을 반드시 포함` → `8. **시각적 인구학 단서 반영**: 시나리오 또는 인물별 outlook/character evidence에 명시된 인구학 단서는 element description에 반영한다. 명시되지 않은 인물에 default 인구학 표기를 강제하지 않는다.`
  - **JS1/JS2a/JS2b/JS3 + JS-opt-1/JS-opt-2** line 89-110 JSON example block 전체 제거 + abstract schema skeleton 변환 (Codex V3 OQ-1 Option A pin) — placeholder-free abstract labels, demographic/default posture prose 0, opaque element_id naming guidance only.
  - **Preserve obligatory**: line 11 protective negative wording (`원문이 묘사한 상태만 기록. 장르 편향으로 상처·혈흔을 임의 추가 금지`) + 분석 원칙 1-10 안 abstract guidance + 고정 요소 유형 1-3 section + element_scope 결정 (필수 emit) section (Area #4 v7 instruction core) + Evidence and inference disclosure (per fixed_element) section.

#### 5.2.2 `backend/app/core/version_registry.py` 3 logical edits (1 file modify)

- **Site 1 line 36**: `MODULE_VERSIONS["scene_consistency"]: "2.5.0"` → `"2.6.0"` + inline comment narrow append (예: `# 2026-05-20 — Carry-P021: scene_consistency v7→v8 prompt hygiene (hard-prime example abstraction) — content-only, schema byte-identical, schema_version=3 preserve.`).
- **Site 2 line 130**: `_MODULE_INFO["scene_consistency"]["prompt_dependency"]: "scene_consistency/v7"` → `"scene_consistency/v8"`.
- **Site 3 line 131**: `_MODULE_INFO["scene_consistency"]["updated_at"]: "2026-05-18"` → `"2026-05-20"` + optional inline comment narrow append.

### 5.3 Out-of-scope (W2)

- `backend/app/core/steps/scene_consistency_step.py` 변경 0 (Area #4 boundary preserve).
- `backend/app/core/step_manifest.py` 변경 0 (Codex V3 OQ-5 명시).
- v7 prompt-pack `prompts/_base/scene_consistency/7.202605181210/` 변경 0 (historical preservation).
- DB row override X.
- `tests/unit/test_scene_consistency_schema_v7.py` (literal historical pin) 변경 0.

### 5.4 Pre-commit verify gate (W2, 8 check)

- **(a) UTC timestamp resolution + new dir name**: `UTC=$(date -u +%Y%m%d%H%M); NEW_DIR="prompts/_base/scene_consistency/8.${UTC}"; test -d "$NEW_DIR"`.
- **(b) New dir 2 file count**: `test "$(ls $NEW_DIR | wc -l)" -eq 2`; exact = `system.md` + `schema.json`.
- **(c) `schema.json` sha256 byte-identical from v7**: `[ "$(shasum -a 256 prompts/_base/scene_consistency/7.202605181210/schema.json | cut -d' ' -f1)" = "$(shasum -a 256 $NEW_DIR/schema.json | cut -d' ' -f1)" ]`.
- **(d) STRICT_RESIDUES 10-id absence in v8 system.md**: 10 strict residue R1-R6 + JS1/JS2a/JS2b/JS3 (§2.1.1 marker block 안 exact quoted strings) — exact full-phrase membership hit 0. plain shell helper = `hits=0; for residue in "..."; do if rg -n -F "$residue" "$NEW_DIR/system.md"; then hits=1; fi; done; test "$hits" -eq 0`. closed-world `rg -F` fixed-string only (Codex β-narrow + Carry-A099 G4 lineage 정합).
- **(e) New abstract wording presence in v8 system.md** (Codex V3 OQ-3 default pin 정합, Carry-A100 lineage): R6 abstraction Korean lead clause `8. **시각적 인구학 단서 반영**:` + `명시되지 않은 인물에 default 인구학 표기를 강제하지 않는다` 각각 1 hit (full-phrase membership) + R1-R5 abstraction Korean clauses 각각 1 hit. `rg -n -F` 명시 wording substring presence.
- **(f) version_registry 3 logical edits sync**: Python verify `from app.core.version_registry import MODULE_VERSIONS, _MODULE_INFO; assert MODULE_VERSIONS["scene_consistency"] == "2.6.0"; assert _MODULE_INFO["scene_consistency"]["prompt_dependency"] == "scene_consistency/v8"; assert _MODULE_INFO["scene_consistency"]["updated_at"] == "2026-05-20"` (Carry-A100 N-5 cwd-relative path lesson 정합, `cd backend && python` 시 repo_root resolution 의무).
- **(g) Active-version resolution via loader source-path proof** (Carry-A099 G1 lineage Codex IMPORTANT 3 정합 + Codex amend 1 IMPORTANT 1 fix — `get_effective_source()` returns dict + `.md` stem only + schema sibling separation): `from app.modules.prompt_loader import get_effective_source; from pathlib import Path; src = get_effective_source("scene_consistency", "system", db=None); file_cand = src["candidates"]["file"]; assert file_cand["version"].startswith("8."); assert "/scene_consistency/8." in file_cand["path"]; system_path = Path(file_cand["path"]); schema_path = system_path.parent / "schema.json"; assert schema_path.is_file(); assert "/scene_consistency/8." in str(schema_path)`. `get_effective_source("scene_consistency", "schema")` 사용 X (`.md` stem only, `schema.md` 찾음 — `schema.json` source-path proof 아님). `load_prompt`/`load_schema` = content-load smoke only, source-path proof X.
- **(h) STEP_MANIFEST schema_version preserve**: `from app.core.step_manifest import STEP_MANIFEST; assert STEP_MANIFEST["scene_consistency"]["schema_version"] == 3`.

### 5.5 Targeted pytest (W2)

`backend/.venv/bin/pytest backend/tests/test_prompt_versions.py backend/tests/test_step_manifest_v3.py backend/tests/test_manifest_fields.py backend/tests/test_step_catalog.py backend/tests/test_sync_v3.py backend/tests/unit/test_g3_2_manifest_dag.py backend/tests/unit/test_scene_consistency_schema_v7.py -v --tb=short` — ALL PASS 의무.

## 6. W3 Implementation Contract (1 atomic commit) — Carry-P021 integrated test

### 6.1 Commit boundary

- Single atomic commit — `backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py` (1 file new). production code 변경 0, prompt-pack 변경 0.
- Commit subject: `W3(carry-p021-scene-consistency-prompt-hygiene-v1): integrated test atomic — 7 gate verify (1 file new)`

### 6.2 New test file scope

`backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py`:

#### G1 — Active v8 source-path proof (Carry-A099/A100 G1 lineage + Codex outline N-2 정정 흡수)

```python
from pathlib import Path
from app.modules.prompt_loader import get_effective_source

def test_gate_1_active_v8_source_path_proof():
    # System prompt source-path proof via get_effective_source dict
    # (returns dict, `.md` stem only — Codex amend 1 IMPORTANT 1 fix).
    src = get_effective_source("scene_consistency", "system", db=None)
    file_cand = src["candidates"]["file"]
    assert file_cand["version"].startswith("8.")
    assert "/scene_consistency/8." in file_cand["path"]
    # Schema proof = system path sibling schema.json existence
    # (separation — `get_effective_source("schema")` 사용 X, `.md` stem only).
    system_path = Path(file_cand["path"])
    schema_path = system_path.parent / "schema.json"
    assert schema_path.is_file()
    assert "/scene_consistency/8." in str(schema_path)
```

**Out-of-scope** (Codex amend 1 IMPORTANT 1 fix):
- `prompt_loader.load_prompt` (prompt text 반환) ≠ source-path proof.
- `prompt_loader.load_schema` (schema content 반환) = content-load smoke only, source-path proof X.
- `get_active_version` (module-level active-version) ≠ schema stem source-path proof.
- `get_effective_source("scene_consistency", "schema", db=None)` ≠ schema source-path proof (`.md` stem only, `schema.md` 찾음 not `schema.json`).
- 본 G1 안 모두 사용 X (Carry-A099/A100 N-3 lesson + Codex outline N-2 + amend 1 IMPORTANT 1 정합).

#### G2 — v8 file count 2

```python
def test_gate_2_v8_file_count_2():
    v8_dir = _resolve_v8_dir()  # via source-path proof, not glob
    files = sorted(p.name for p in v8_dir.iterdir() if p.is_file())
    assert files == ["schema.json", "system.md"]
```

#### G3 — STRICT_RESIDUES marker-wrapped absence (10 strict R-id, single constant)

```python
# <!-- HISTORICAL AUDIT TRAIL — BEGIN -->
STRICT_RESIDUES = (
    # R1 — system.md:13 (v7), hard-prime rest-state example
    'a young person resting on a sofa, curled on the left side, one arm tucked under the cheek, eyes closed, a light blanket draped over the shoulder',
    # R2 — system.md:14 (v7), hard-prime localized bandage example
    'a figure seated against a wall, head tilted back, eyes closed, a small bandage wrapped around the left wrist',
    # R3 — system.md:18 (v7), hard-prime shattered-window example
    'the left pane of the window is shattered with jagged glass edges remaining in the frame',
    # R4 — system.md:22 (v7), hard-prime bedsheet example
    'a crumpled white bedsheet hanging off the bed edge, touching the floor',
    # R5 — system.md:58 (v7), hard-prime concrete posture phrase (Codex V3 OQ-2: quoted English phrase only)
    'lying face-down on the wooden floor, left arm extended forward, right knee slightly bent',
    # R6 — system.md:61 (v7), demographic default instruction (full-phrase, Carry-A100 lineage)
    '8. **인종/국적 명기**: 인물 묘사 시 인종/국적을 반드시 포함',
    # JS1 — system.md:95 (v7), JSON example description
    'an East Asian person lying motionless on the left side, left arm bent near the face, eyes closed',
    # JS2a — system.md:99 (v7), JSON example source_facts
    "S## action: 'A figure lies motionless on the floor.'",
    # JS2b — system.md:100 (v7), JSON example source_facts heading
    'scene heading: NIGHT, small interior room',
    # JS3 — system.md:103 (v7), JSON example visual_inferences
    'left-side recumbent pose (text only specifies motionless, not orientation)',
)
# <!-- HISTORICAL AUDIT TRAIL — END -->

def test_gate_3_strict_residues_absent_in_v8_system_md():
    v8_system = _resolve_v8_dir() / "system.md"
    text = v8_system.read_text()
    for residue in STRICT_RESIDUES:
        assert residue not in text, f"strict residue still present in v8 system.md: {residue!r}"
```

**Doctrine** (Codex V3 OQ-3 + Carry-A100 lineage 정합):
- **Standalone token global ban X**: `East Asian` / `body_pose_canonical` / `character_state` / `인종` / `국적` / `상처` / `혈흔` 단독 global ban 금지. abstract category descriptor 안 자연 사용 보존, residue gate = full-phrase membership only.
- **Single `STRICT_RESIDUES` constant**: 옛 ambiguous `R1_R6_STRICT + JS1_JS3_STRICT` 분리 명명 폐기 (Codex outline N-6 정합).
- **Marker block 외부 exact residue 재방출 X**: STRICT_RESIDUES tuple = HISTORICAL AUDIT TRAIL marker 안 only. test name / docstring / 다른 변수 안 quoted residue 재방출 0 (post-Carry-D7d-1 fix-up 1 강화 doctrine + Carry-A100 N-1 정합).

#### G4 — New abstract wording presence (Codex V3 OQ-3 default pin Carry-A100 lineage)

```python
ABSTRACT_PRESENCE_CLAUSES = (
    # R6 abstraction Korean lead clause
    '8. **시각적 인구학 단서 반영**:',
    # R6 abstraction Korean second clause (Carry-A100 lineage)
    '명시되지 않은 인물에 default 인구학 표기를 강제하지 않는다',
    # R1-R5 abstraction Korean clause (process wording)
    '원문에 명시된 inactive/restful pose는 구체 자세',
)

def test_gate_4_abstract_wording_presence_in_v8_system_md():
    v8_system = _resolve_v8_dir() / "system.md"
    text = v8_system.read_text()
    for clause in ABSTRACT_PRESENCE_CLAUSES:
        assert clause in text, f"required abstract wording missing in v8 system.md: {clause!r}"
```

**No enumerated taxonomy** (Codex outline §6.1 정합, Carry-A099 G5 lineage): `category: [rest_state, wound_state, window_damage, bedsheet_position]` 등 closed-list taxonomy emit 강제 wording 금지. process wording only.

#### G5 — Schema sha256 byte-identical canary (Carry-A099 G3 + Carry-A100 G5 lineage)

```python
import hashlib

def _sha256(path):
    return hashlib.sha256(path.read_bytes()).hexdigest()

def test_gate_5_schema_sha256_byte_identical_from_v7():
    v7_schema = REPO_ROOT / "prompts" / "_base" / "scene_consistency" / "7.202605181210" / "schema.json"
    v8_schema = _resolve_v8_dir() / "schema.json"
    assert _sha256(v7_schema) == _sha256(v8_schema)
```

#### G6 — version_registry 3 logical edits sync + STEP_MANIFEST preserve (Codex V3 OQ-5 정합)

```python
def test_gate_6_version_registry_3_logical_edits_and_step_manifest_preserve():
    from app.core.version_registry import MODULE_VERSIONS, _MODULE_INFO
    from app.core.step_manifest import STEP_MANIFEST
    # Site 1 MODULE_VERSIONS bump
    assert MODULE_VERSIONS["scene_consistency"] == "2.6.0"
    # Site 2 prompt_dependency sync
    assert _MODULE_INFO["scene_consistency"]["prompt_dependency"] == "scene_consistency/v8"
    # Site 3 updated_at sync (Codex outline N-10 흡수 — Site 3 updated_at verify 추가)
    assert _MODULE_INFO["scene_consistency"]["updated_at"] == "2026-05-20"
    # STEP_MANIFEST schema_version preserve (Codex V3 OQ-5 default: verify-only)
    assert STEP_MANIFEST["scene_consistency"]["schema_version"] == 3
    # SCENE_CONSISTENCY_SCHEMA_VERSION constant preserve (Area #4 boundary)
    from app.core.steps.scene_consistency_step import SCENE_CONSISTENCY_SCHEMA_VERSION
    assert SCENE_CONSISTENCY_SCHEMA_VERSION == 3
```

#### G7 — v7 historical canary (Carry-A099 lineage)

```python
def test_gate_7_v7_historical_canary():
    v7_dir = REPO_ROOT / "prompts" / "_base" / "scene_consistency" / "7.202605181210"
    assert v7_dir.is_dir()
    v7_system = v7_dir / "system.md"
    v7_schema = v7_dir / "schema.json"
    assert v7_system.is_file()
    assert v7_schema.is_file()
    # v7 historical schema.json sha256 computability smoke (Codex amend 1 MINOR 2 fix —
    # sha256 length 64 only, no pinned hash literal in spec; W3 execution 시 optional
    # expected sha256 pin 추가 가능).
    v7_schema_sha256 = _sha256(v7_schema)
    assert len(v7_schema_sha256) == 64  # sha256 hex length smoke
```

### 6.3 Doctrine

- **no live LLM + NO VLM + no regex semantic + no standalone token global ban** (Codex β-narrow + 4-Gate Boundary Doctrine).
- **closed-world exact phrase membership only** (str.__contains__ / `assert ... in text` / `assert ... not in text`).
- **single STRICT_RESIDUES constant marker-wrapped** (HISTORICAL AUDIT TRAIL `<!-- ... -->` block). marker block 외부 exact residue 재방출 X.
- **4-Gate Boundary Doctrine inline** (§9.1 정합).

### 6.4 Pre-commit verify gate (W3, 3 check)

- **(a) Test file existence**: `test -f backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py`.
- **(b) STRICT_RESIDUES marker-wrapped**: `grep -nF "HISTORICAL AUDIT TRAIL — BEGIN" backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py && grep -nF "HISTORICAL AUDIT TRAIL — END" backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py` (Carry-A100 N-2 marker-aware doctrine 정합).
- **(c) Targeted pytest**: `backend/.venv/bin/pytest backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py -v --tb=short` 7 Gate ALL PASS.

### 6.5 Out-of-scope (W3)

- Production code 변경 0.
- prompt-pack 변경 0.
- W2 bundle regression 별도 (W3 commit 후 full pytest canary).

## 7. W4 Implementation Contract (1 atomic commit) — closure docs

### 7.1 Commit boundary

- Single atomic commit — path-limited 5 repo-local docs (Codex amend 1 IMPORTANT 4 fix — file count drift 정정: 본 spec + plan + roadmap + audit 02 + Area #4 spec = 5 repo-local docs; external memory non-git, file count 아님; Carry-A099/A100 lineage 정합).
- Commit subject: `W4(carry-p021-scene-consistency-prompt-hygiene-v1): closure docs atomic — 5 file path-limited`

### 7.2 Closure docs scope (5 repo-local docs + external memory)

- **(a) 본 spec `2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md` frontmatter `status: draft` → `status: closed` + §12 in-place replace** (heading 이미 존재; append X; pending placeholder 전체 replace; Carry-A100 spec §10 in-place REPLACE doctrine 정합).
- **(b) Carry-P021 plan (`docs/superpowers/plans/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-implementation.md`) frontmatter `status: draft` → `status: closed` + plan §N closure marker narrow append** (drafting closure, Carry-A099/A100 plan lineage 정합).
- **(c) Roadmap `docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md` §5.7 Sub-area (b)** narrow append `Carry-P021 resolved by W1-W4 — scene_consistency v7 system.md hard-prime examples abstracted (v8 prompt-pack `8.W2_COMMIT_UTC`)` (Carry-A099/A100 lineage most-current carry-follow-up bullet only).
- **(d) Audit 02 `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md`** narrow update:
  - §11.3 line 317 carry table row Status column 추가 (`Status: closed by Carry-P021 (2026-05-20+)`).
  - §13 line 382 Area #7b carry-list bullet Carry-P021 status narrow update (`resolved by W1-W4`).
  - §14 line 437 Area #7c carry-list bullet Carry-P021 status narrow update.
  - §15 line 475 Carry-A100 carry-list bullet Carry-P021 status narrow update.
  - §16 신설 Carry-P021 Closure section (Carry-A099 §11.3/§13/§14 + Carry-A100 §15 신설 lineage 정합).
- **(e) Area #4 v1 spec `docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md`** narrow update:
  - §1.5 carry table row P021 Disposition column narrow update (`resolved by Carry-P021 W1-W4`).
  - §2.3 Q3 P021 scope wording narrow update.
  - §3.2 Out-of-scope rows P021 Disposition column narrow update.
  - §7.1 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17` Status column narrow update (`resolved by Carry-P021 W3 G3 STRICT_RESIDUES marker-wrapped catalog`) + `Carry Marker` column note narrow update.
  - §10.2 Non-claim P021 wording narrow update.
- **(f) External memory (non-git)**: MEMORY.md + 본 carry session memo + Carry priority 정합 update.

**W0.1 inventory + Q1-Q7 outline = untracked reference artifacts** unless plan explicitly decides commit (Carry-A099 7 narrow guard 5 lineage 정합).

### 7.3 TEMPLATE ONLY doctrine + W4 self-hash literal X (Carry-A100 N-1/N-2/N-3 + Carry-D7d-1 fix-up 1 강화 doctrine)

- 본 spec body 안 design-time placeholder = `8.W2_COMMIT_UTC` (underscore form W2_COMMIT_UTC placeholder per post-Carry-D7d-1 fix-up 1 강화 doctrine). literal angle-bracketed UTC design-time form 또는 angle-bracketed W2 commit hash design-time form = formal `<!-- HISTORICAL AUDIT TRAIL — BEGIN/END -->` marker block 외부 사용 금지 (Codex amend 3 IMPORTANT fix — line 511 self-referential placeholder doctrine drift 정정).
- W4 commit body 안 self-hash literal 0 (Carry-A100 W4 closure docs 정합).
- 본 spec §12 in-place replace 시 heading 이미 존재 + append X + pending placeholder 전체 replace (Carry-A100 spec §10 in-place REPLACE doctrine 정합).
- Roadmap / audit / Area #4 spec narrow update 시 base-to-W4 range design-time placeholder prose 안 angle-bracket form 사용 X — explicit hash 직접 기입 + range wording explicit (post-Carry-A100 W3 fix-up 1 narrow doctrine 정합; Codex amend 3 IMPORTANT fix — line 514 self-referential placeholder doctrine drift 정정).

### 7.4 Final pushed range/count

- W1-W4 range review = Codex APPROVED_FOR_PUSH 의무 후 즉시 push origin main (사용자 ask 0, [[feedback_push_no_user_ask]] 정합).
- final pushed range/count = external memory only (W4 commit body 안 embedded X — self-reference 회피).

### 7.5 Pre-commit verify gate (W4, 3 check)

- **(a) 본 spec status closed**: `grep -nF "status: closed" docs/superpowers/specs/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md`.
- **(b) Audit 02 §16 Closure section presence**: `grep -nF "## 16. Carry-P021 Closure" docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md`.
- **(c) Marker-aware diff**: STAGED file 안 marker-excluded literal angle-bracket placeholder absence (Carry-A100 plan §6.4(d) Part 2 marker-aware narrow amend in-flight lesson 정합).

## 8. Test/Gate Contract

### 8.1 G1-G7 verify gate enumeration (W3 integrated test, §6.2 정합)

| Gate | Scope | Implementation |
|---|---|---|
| G1 | Active v8 source-path proof (Carry-A099/A100 G1 lineage + Codex amend 1 IMPORTANT 1 fix) | `get_effective_source("scene_consistency", "system", db=None)` returns dict + `src["candidates"]["file"]["version"].startswith("8.")` + path contains `/scene_consistency/8.` + system path sibling `schema.json` existence (schema proof separation — `get_effective_source("schema")` 사용 X, `.md` stem only) |
| G2 | v8 file count 2 | `v8_dir.iterdir()` = `["schema.json", "system.md"]` |
| G3 | STRICT_RESIDUES marker-wrapped absence (10 strict R-id, single constant) | tuple membership check `for residue in STRICT_RESIDUES: assert residue not in v8_system_text` |
| G4 | New abstract wording presence (Codex V3 OQ-3 + Carry-A100 lineage) | `for clause in ABSTRACT_PRESENCE_CLAUSES: assert clause in v8_system_text` (no enumerated taxonomy) |
| G5 | Schema sha256 byte-identical canary (Carry-A099 G3 + Carry-A100 G5 lineage) | `_sha256(v7_schema) == _sha256(v8_schema)` |
| G6 | version_registry 3 logical edits sync + STEP_MANIFEST preserve (Codex V3 OQ-5 정합) | `MODULE_VERSIONS["scene_consistency"] == "2.6.0"` + `_MODULE_INFO["scene_consistency"]["prompt_dependency"] == "scene_consistency/v8"` + `_MODULE_INFO["scene_consistency"]["updated_at"] == "2026-05-20"` + `STEP_MANIFEST["scene_consistency"]["schema_version"] == 3` + `SCENE_CONSISTENCY_SCHEMA_VERSION == 3` |
| G7 | v7 historical canary (Carry-A099 lineage + Codex amend 1 MINOR 2 fix) | `prompts/_base/scene_consistency/7.202605181210/` dir + 2 file existence + v7 schema.json sha256 computability smoke (length 64; W3 execution 시 optional expected hash pin 추가 가능) |

### 8.2 STRICT_RESIDUES single constant marker-wrapped (Codex β-narrow + outline N-6 정합)

- **Single constant**: `STRICT_RESIDUES` tuple 안 10 strict R-id 모두 포함 (R1-R6 + JS1/JS2a/JS2b/JS3). 옛 ambiguous `R1_R6_STRICT + JS1_JS3_STRICT` 분리 명명 폐기.
- **Marker wrapping**: `<!-- HISTORICAL AUDIT TRAIL — BEGIN -->` ~ `<!-- HISTORICAL AUDIT TRAIL — END -->` block 안 only (W3 test file source + 본 spec §2.1.1 + 본 spec §6.2 G3 code block).
- **Marker block 외부 = R-id reference only** (예: `R1`, `R2`, ..., `JS3`). exact wording 재방출 0.

### 8.3 Marker-excluded scan rules

- **Marker-excluded scan**: 본 spec body 안 STRICT_RESIDUES 정확 wording (예: `lying face-down on the wooden floor, left arm extended forward, right knee slightly bent`) 의 marker block 외부 substring presence = 0 (Carry-A100 N-1/N-2 marker-aware doctrine + Carry-A099 fix-up 1 doctrine 정합).
- **Scan tool**: `rg -F` fixed-string only + manual marker-aware diff (예: `awk '/HISTORICAL AUDIT TRAIL — BEGIN/,/HISTORICAL AUDIT TRAIL — END/' ${file}` exclude block).
- **W4 closure docs 안 marker-aware narrow amend**: STAGED state only verify (Carry-A100 plan §6.4(d) Part 2 marker-aware narrow amend in-flight lesson 정합).

### 8.4 Closed-world full-phrase membership only

- W3 test code 안 `import re` ban (semantic regex 0).
- W3 residue gate code 안 substring `in` operator + tuple membership only (`for r in STRICT_RESIDUES: assert r not in text`).
- W3 abstract wording presence code 안 substring `in` operator + tuple membership only.

### 8.5 Standalone token global ban X (Codex V3 OQ-3 + Carry-A100 lineage 정합)

- Standalone words: `East Asian`, `body_pose_canonical`, `character_state`, `인종`, `국적`, `상처`, `혈흔`, `lying`, `motionless`, `eyes closed`, `floor`, `wall`, `window`, `bedsheet` 등 single token / fragment global ban X.
- Abstract category descriptor 안 standalone word 자연 사용 보존 (process wording).
- Residue constants 안 Korean parenthetical comment 포함 X (예: `(← 시나리오 의존 noun + 사건)`). exact quoted strings only (Carry-A099 §7.2 lineage 정합).

### 8.6 Test anchor preservation

- `tests/unit/test_scene_consistency_schema_v7.py` 9 PASS preserve (변경 0).
- `tests/unit/test_scene_consistency_schema_v6.py` 변경 0 preserve.
- `tests/test_prompt_versions.py` (W1 rename 후) 전체 file PASS preserve (Codex amend 1 IMPORTANT 3 + amend 2 MINOR 1 fix — old nine-test count wording drift 정정, live collect 기준 actual test def count; backticked literal grep-gate confusion 회피).
- `tests/test_step_manifest_v3.py` + `test_manifest_fields.py` + `test_step_catalog.py` + `test_sync_v3.py` + `tests/unit/test_g3_2_manifest_dag.py` (manifest/version registry 5 file) 변경 0 + W2 후 ALL PASS canary.

## 9. Doctrine (4-Gate + NO VLM + closed-world + standalone token global ban X + TEMPLATE ONLY + 4채널 fact source)

### 9.1 4-Gate Boundary Doctrine ([[feedback_llm_based_judgment]] 정합)

§1.4 table 정합 + 다음 추가 doctrine:

- **Gate 1 Semantic Regex Ban**: W3 test code `import re` ban (Carry-A099 Gate 1 lineage 정합). residue gate = substring membership only.
- **Gate 2 Prompt Closed-List Ban refined full-phrase only**: 10 strict R-id full-phrase ban. standalone token global ban X (Codex V3 OQ-3). abstract category descriptor 안 standalone word 보존 (`East Asian`, `body_pose_canonical`, `character_state`, `인종`, `국적`, `상처`, `혈흔` 자연 사용).
- **Gate 3 Structured SOT Required (partial v1)**: v1 = scene_consistency v7→v8 prompt-pack content abstraction only (carrier `fixed_elements` schema preserve). Structured SOT completion claim X — Future Carry-P021-structured (`element_id` opaque UUID / `element_type` enum 확장 / `element_scope` enum 확장 / `applies_to_shots` minItems 변경 / JSON example structured schema generation 등) deferred.
- **Gate 4 No Silent Fallback**: Producer code `_detect_framing_conflicts` element_scope 직접 read + KeyError schema violation fail-fast preserve. v8 prompt-pack 안 abstract instruction LLM emit element_scope 강제. `call_structured` jsonschema validation 실패 시 retry 자동 trigger preserve.

### 9.2 NO VLM hard constraint ([[feedback_no_vlm_dependency]] 정합)

- W1-W4 검증/테스트 안 VLM 사용 0. production image generation pipeline (T2I) 정상 module 정상 사용 무관.
- residue gate (G3) + abstract wording presence (G4) + schema sha256 (G5) + version_registry sync (G6) + v7 historical canary (G7) 모두 schema/text/manifest verification only.

### 9.3 Closed-world full-phrase membership ([[feedback_llm_based_judgment]] Gate 1 정합)

- 10 strict R-id `STRICT_RESIDUES` tuple membership only.
- ABSTRACT_PRESENCE_CLAUSES tuple membership only.
- `import re` ban (W3 test).
- audit-verbatim + current-active-promoted inventory split (Area #7b lineage 정합) — 본 carry 모든 R-id = audit-verbatim (v7 system.md hard-prime example).

### 9.4 Standalone token global ban X (Codex V3 OQ-3 precision guard)

§8.5 정합. abstract category descriptor 안 자연 사용 보존.

### 9.5 Marker-wrapped strict residues + STRICT_RESIDUES single constant + post-Carry-D7d-1 fix-up 1 강화 doctrine

§8.2 + §8.3 정합 + post-Carry-D7d-1 fix-up 1 강화 doctrine ([[session_20260519_carry_d7d_1_v1_closure]] 함정 2 정합):

- **`never re-emit literal angle-bracketed forms outside marker blocks`**: spec/plan/test 본문 안 angle-bracket placeholder form (angle-bracketed UTC design-time form / angle-bracketed W2 commit hash design-time form / base-to-W4 range design-time placeholder 등) = formal `<!-- HISTORICAL AUDIT TRAIL — BEGIN/END -->` marker block 외부 사용 금지 (Codex amend 3 IMPORTANT fix — line 603 self-referential placeholder doctrine drift 정정).
- **Underscore-escape variant도 live spec 안 X** (Carry-A100 N-1 정합): `UTC_TIMESTAMP` / `W2_COMMIT` / `W2_COMMIT_UTC` underscore form은 controller-substitute target only.

### 9.6 TEMPLATE ONLY + W4 self-reference + Substitution self-referential bug + Legacy 본 commit retroactive escape

§7.3 정합 + 다음 추가 doctrine ([[session_20260519_area_7c_v1_closure]] + [[session_20260519_carry_a099_v1_closure]] + [[session_20260519_carry_a100_v1_closure]] lineage):

- **Spec body 안 design-time placeholder slug**: controller-substitute target only. spec 안 doctrine description block 안 placeholder mention 시 HISTORICAL AUDIT TRAIL marker wrap + interior underscore variant escape 의무 (W4 closure 시 적용).
- **W4 closure docs body 안 self-reference placeholder slug 사용 X**: explicit hash literal + "final pushed range/count = external memory only" suffix 의무.
- **Legacy 타 area closure verify chain 안 `본 commit` mentions**: 6-file path-limited scope 안 valid 시 retroactive `closure commit` semantic substitute (Area #7c/#7d 함정 1 정합).

### 9.7 4채널 fact source 명시 ([[feedback_channel_separation_4way]] 정합)

- (A) claude→codex 송신 / (B) codex→claude 응답 / (C) claude direct read / (D) claude→user 보고 — 매 fact 별 channel anchor 명시 의무 (W1-W4 진행 + Codex 의논 안).
- 본 spec drafting = (C) 본 session direct verify fact + (B) Codex amend 3 final round 6 + Codex V1-V6 verdict 흡수 + (A) 본 session Codex 의논 prompt 흡수.

### 9.8 Field-shape migration deferred (Future Carry-P021-structured)

- `element_id` opaque snake_case → opaque UUID migration = Future.
- `element_type` enum 3 entry 확장 (예: `lighting_state` 추가) = Future.
- `element_scope` enum 2 entry 확장 (예: `partial` 추가) = Future.
- `applies_to_shots` schema 변경 (minItems 변경 등) = Future.
- JSON example structured schema generation = Future.
- Major carry / future area follow-up.

### 9.9 Workflow doctrine

- Codex first 모든 결정 단계 ([[feedback_codex_mcp_discussion_workflow]]).
- subagent dispatch = opus ([[feedback_subagent_model_opus]]).
- raw typing 5-step `mcp__tmux-bridge__*` ONLY ([[feedback_codex_mcp_claude_mcp_response_trigger]]).
- session 50%+ rule + push 후 = Codex 의논 의무 ([[feedback_session_50pct_codex_close_check]]).
- push destructive = Codex APPROVED_FOR_PUSH 후 즉시 사용자 ask 0 ([[feedback_push_no_user_ask]]).
- /clear ONLY (`/exit` 금지, [[feedback_session_reset_clear_not_exit]]).
- audit / large-context 종합 진단 시 brainstorming 좁은 spec 진입 즉시 시도 금지 ([[feedback_audit_analysis_vs_spec_entry]]).

## 10. Allowed and forbidden closure claims

### 10.1 Allowed claim wording (Codex β-narrow + V3 OQ-3 verbatim)

> `scene_consistency v7 system.md hard-prime English prose example phrases (R1-R5) + demographic default instruction (R6) + JSON example block (JS1/JS2a/JS2b/JS3) were abstracted to remove closed-list semantic hard-prime examples while preserving the existing fixed_elements carrier contract.`

### 10.2 Forbidden claim wording (Codex β-narrow + 4 narrow guard)

- ❌ `scene_consistency structured SOT complete` (Future Carry-P021-structured deferred).
- ❌ `element_id opaque UUID migration complete` (Future).
- ❌ `element_type enum expansion complete` (Future).
- ❌ `Area #7 (Prompt Hygiene v2) closure complete` (본 carry = Carry-P021 narrow scope, broader Prompt Hygiene v2 carry preservation).
- ❌ `all scene_consistency prompt hygiene risk fixed` (process wording lift, residue gate audit-verbatim only).
- ❌ `field-shape migration complete` (Future).
- ❌ `JSON example structured schema generation complete` (Future).

### 10.3 Allowed closure-doc wording (W4 audit 02 + roadmap + Area #4 spec narrow update)

- ✅ `Carry-P021 resolved by W1-W4 — scene_consistency v7 system.md hard-prime examples abstracted (v8 prompt-pack 8.W2_COMMIT_UTC)`
- ✅ `Status: closed by Carry-P021 (2026-05-20+)`
- ✅ `resolved by Carry-P021 W3 G3 STRICT_RESIDUES marker-wrapped catalog` (Area #4 spec §7.1 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17` Status update).

## 11. Traps / provenance / carry follow-up

### 11.1 Tier 1-3 carry 함정 (reference inherit per Area #7a/#7b/#7c/#7d/Carry-D7d-1/Carry-A099/Carry-A100 closure memos)

top 8 Tier 1 carry 함정 + Tier 2/3 inherited 함정 = 본 carry plan review 시 implementation scope 가 해당 함정을 건드리면 inline 재 enumeration 의무.

1. Plan template cascade enumeration defect → BLOCKING pre-step #1 cascade grep 의무.
2. Wording iteration cascade → BLOCKING pre-step #2 강제.
3. tmux-bridge MCP raw typing 5-step (양방향 trigger).
4. 사용자 결정 ask 전 Codex 의논 의무 (memory rule 7a strict, [[feedback_codex_mcp_discussion_workflow]] 정합).
5. VLM 절대 금지 ([[feedback_no_vlm_dependency]]).
6. Closure wording allowed / forbidden 분리 spec 의무 (§10 정합).
7. Push gate strict (Codex 의논 후 즉시 진행, 사용자 ask 0).
8. Roadmap §5.X stale wording carry.
9-16. Area #1/#2/#3 carry 함정 inherited (Area #4 spec §11.3 정합) — plan review 시 implementation scope 가 건드리면 inline 재 enumeration 의무.

### 11.2 Carry-A099/A100 lineage 함정 reference inherit + summary

**Carry-A099 함정 (5 신규 + inherited)** ([[session_20260519_carry_a099_v1_closure]] §10.11 정합):
- N-5 W1 Python gate cwd-relative path bug (`cd backend && python -c "..."` 안 `NEW_DIR` 이 backend cwd 안에서 `backend/prompts/...` 로 resolve) — Fix doctrine: `repo_root = os.path.abspath(os.path.join(os.getcwd(), os.pardir))` join 의무.
- N-1 docstring contract drift (`5 Gate verify` wording vs 실제 6 test 함수 sync 누락) — Fix doctrine: test docstring contract = actual test count 글자-단위 sync 의무.

**Carry-A100 함정 (7 신규 + inherited)** ([[session_20260519_carry_a100_v1_closure]] §10.11 정합):
- N-1 plan §3.2.1 (c) substitute target wording vs file actual substring 어순 mismatch — Option α runtime fix file substring 사용 + W1 commit body 명시.
- N-2 plan §6.4 (d) Part 2 mechanical over-eager raw `git diff --cached -U0 ^+ grep` for newly-staged-from-untracked spec/plan — Option β marker-aware stripped-content diff in-flight amend.
- N-3 audit duplicate carry-list §13+§14 Edit unique-match conflict — `replace_all=true` 활용.
- N-4 plan §6.4 (d) Part 2 unstaged-vs-staged 7-hit discrepancy — Part 2 STAGED state only verify 의무.
- N-5 roadmap §5.7 multi-site narrow update precedent — most-current carry-follow-up bullet only.
- N-6 untracked artifact preserve W0.1 + outline = reference-only.
- N-7 pre-existing legacy angle-bracket literals in CLOSURE_DOCS — narrow update site = "clean" alternative rows.

### 11.3 Carry-P021 신규 함정 N-A1 ~ N-A7 (Codex V4 명시 + 본 session direct verify 신규 발견)

- **N-A1 Area #4 closure boundary inheritance**: Area #4 (2026-05-18, push) 는 producer code 안 `_ELEMENT_ID_CLOSE_REGEX` / `_DESCRIPTION_CLOSE_KEYWORDS` / `_classify_framing` 폐기 + LLM emit `element_scope` enum SOT 전환을 완료했으나 P021 prompt hygiene (system.md L9/L14/L17/L46 시나리오 의존 enumeration) 는 **closure 선언 X** (Area #4 spec §1.5/§2.3/§3.2/§7.1/§10.2 verbatim). 본 carry = scene_consistency prompt-pack content abstraction 만 처리, code-side classifier complete claim X.
- **N-A2 `test_prompt_versions.py` 3 helper use sites (line 35/48/58)**: outline §2.4 line 48/58 외 line 35 추가 발견 (본 session direct verify, Codex V3 OQ-6 expansion 흡수). W1 안 3 사용 site 모두 helper rename 흡수 의무. line 35 누락 시 helper symbol partial transition + active glob resolution stale wording 잔존 risk.
- **N-A3 Exact residue strings marker block-only doctrine**: STRICT_RESIDUES tuple = HISTORICAL AUDIT TRAIL marker 안 only. test name / docstring / 다른 변수 / spec body / plan body 안 quoted residue 재방출 0 (post-Carry-D7d-1 fix-up 1 강화 + Carry-A100 N-1/N-2 정합). marker-excluded residue scans 의무 (`awk '/HISTORICAL AUDIT TRAIL/,/HISTORICAL AUDIT TRAIL/'` exclude block + `rg -F` substring scan). only explicit standalone-token-ban examples (`East Asian` / `body_pose_canonical` 등) 안 marker block 외부 reference allowed.
- **N-A4 R5 strict test constant = quoted concrete posture phrase only** (Codex V3 OQ-2 verdict 정합): system.md:58 line 전체 (Korean rule label + 분석 원칙 + prose) 가 audit-historical line이나 STRICT_RESIDUES strict test constant = quoted English concrete posture phrase `lying face-down on the wooden floor, left arm extended forward, right knee slightly bent` ONLY. Korean rule label + 분석 원칙 abstract guidance preserve. 전체 line 58 = useful abstract guidance, 제거 대상 X. Risk if missed: G3 test 가 entire line 58 strict check 시 useful guidance 까지 ban → R5 abstraction wording lift 시 abstract clause 까지 G3 false-positive trigger.
- **N-A5 version_registry 3 logical edits (Site 1/2/3 분리)**: outline N-3 흡수 — `version_registry.py` 3 logical edit 시 file count = 1 (1 file modify), logical edit count = 3 (Site 1 line 36 MODULE_VERSIONS + Site 2 line 130 prompt_dependency + Site 3 line 131 updated_at). 분리 표기 의무 — file count = logical edit count = 3 표기 시 Codex N-3 false-positive trigger.
- **N-A6 Source-path proof = `get_effective_source` dict + system path substring + schema sibling existence** (Codex outline N-2 + amend 1 IMPORTANT 1 정합): `get_effective_source()` returns dict `{"candidates": {"file": {"version": ..., "path": ...}, ...}}` and only handles `.md` stem (i.e., `name="system"` finds `system.md`, `name="schema"` would find `schema.md` not `schema.json`). Schema source-path proof = system path sibling `schema.json` file existence + path substring check (separation). `prompt_loader.load_prompt` (prompt text 반환) ≠ source-path proof. `prompt_loader.load_schema` (schema content 반환) = content-load smoke only, source-path proof X. `get_active_version` (module-level active-version) ≠ schema stem source-path proof. `get_effective_source("scene_consistency", "schema")` ≠ schema source-path proof (`.md` stem only). G1 안 모두 사용 X. Carry-A099 G1 lineage Codex IMPORTANT 3 정합 (plain shell `ls + sort` lexicographic tail 위험 회피).
- **N-A7 Area #4 spec §7.1 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17`** (Codex V4 명시): Area #4 spec §7.1 안 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17 (carry, 최종 closure 는 Area #7)` 존재. **본 marker = P021 provenance hint, blindly implement 의무 X** (Codex V4 명시 `cite as P021 provenance, not implemented blindly as an old test name`). 본 carry W3 G3 STRICT_RESIDUES marker-wrapped catalog 가 effective closure mechanism. W4 closure docs 시 Area #4 spec §7.1 안 carry marker Status column narrow update (`resolved by Carry-P021 W3 G3 STRICT_RESIDUES marker-wrapped catalog`) 의무.

### 11.4 Carry priority post Carry-P021

1. **Future Carry-P021-structured** (`element_id` opaque UUID / `element_type` enum 확장 / `element_scope` enum 확장 / `applies_to_shots` minItems 변경 / JSON example structured schema generation 등 field-shape migration) — major carry / future area follow-up.
2. **Future Carry-A099-structured** (`director_notes` `array of string` → `array of object` 구조화 migration per Codex plan amend 2 N-3 fix — bracket gate noise 회피) — major area, separate.
3. **Future Carry-A100-structured** (`t2i_context: string` → `object {default_demographic_policy, tone, genre}` field-shape migration) — major carry / future area follow-up.

## 12. Closure

### 12.1 Status + Closure Anchor

Status: **closed (2026-05-20+)**.

Atomic commits 본 carry: W1 test_prompt_versions.py historical cleanup (1 file modify) + W2 v8 producer prompt-pack + version_registry sync (2 file new + 1 file modify 3 logical edits) + W3 integrated test (1 file new) + W4 closure docs (5 file path-limited + external memory non-git).

Parent baseline: `0f24492` (Carry-A100 W4 closure).

Final pushed range/count = recorded in external memory only after APPROVED_FOR_PUSH + push (live closure docs 안 push-complete pre-claim 0, W4 commit body 안 self-hash 0, [[feedback_push_no_user_ask]] 정합).

### 12.2 Wave Commit Table

| Wave | Commit | Stat | Scope |
|---|---|---|---|
| W1 test_prompt_versions historical cleanup atomic | `b03b65f` | 1 file modify (helper rename + 3 사용 site rename + 3 test rename + body docstring rewording) | `backend/tests/test_prompt_versions.py` |
| W2 v8 producer prompt-pack + version_registry sync atomic | `96834f0` | 2 file new + 1 file modify (3 logical edits) | `prompts/_base/scene_consistency/8.202605191744/system.md` + `schema.json` + `backend/app/core/version_registry.py:36/:130/:131` |
| W3 integrated test atomic | `da700c8` | 1 file new | `backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py` (7 Gate G1-G7) |
| W4 closure docs atomic | recorded by git log/range review after W4 + external memory only | 5 file path-limited | 본 spec + carry plan + roadmap + audit 02 + Area #4 spec narrow updates |

### 12.3 Gate Result

- G1 Active v8 source-path proof: **PASS** (W3 `test_gate_1_active_v8_source_path_proof` PASS — `get_effective_source` returns `version=8.202605191744` + path `/scene_consistency/8.202605191744/system.md` + sibling `schema.json` existence verified).
- G2 v8 file count 2: **PASS** (W3 `test_gate_2_v8_file_count_2` PASS — v8 dir = `[schema.json, system.md]`).
- G3 STRICT_RESIDUES 10-id residue absence: **PASS** (W3 `test_gate_3_strict_residues_absent_in_v8_system_md` PASS — R1+R2+R3+R4+R5+R6+JS1+JS2a+JS2b+JS3 모두 0 hit in v8 system.md).
- G4 New abstract wording presence: **PASS** (W3 `test_gate_4_abstract_wording_presence_in_v8_system_md` PASS — R6 lead clause + R6 second clause + R1-R5 process clause all hit ≥ 1).
- G5 Schema sha256 byte-identical: **PASS** (W3 `test_gate_5_schema_sha256_byte_identical_from_v7` PASS — v7/v8 schema.json sha256 = `d9ed6040dd6342f51452034703e6692503543c54349efcd990f22478dfca0a19`).
- G6 version_registry 3 logical edits sync + STEP_MANIFEST + SCENE_CONSISTENCY_SCHEMA_VERSION preserve: **PASS** (W3 `test_gate_6_version_registry_3_logical_edits_and_step_manifest_preserve` PASS — MODULE_VERSIONS=2.6.0 + prompt_dependency=scene_consistency/v8 + updated_at=2026-05-20 + STEP_MANIFEST schema_version=3 + SCENE_CONSISTENCY_SCHEMA_VERSION=3).
- G7 v7 historical canary: **PASS** (W3 `test_gate_7_v7_historical_canary` PASS — v7 dir + `system.md` + `schema.json` existence + schema sha256 length 64 computability smoke).

W3 targeted pytest: 7 tests, 7 PASS, 0 FAIL, 0.16s. W3 regression bundle (W2 bundle + W3 신규): 106 tests, 106 PASS, 0 FAIL, 0.30s.

### 12.4 Closure Verdict

Codex iter rounds 본 carry cumulative:
- **직전 spec drafting session (5 round)**: spec-entry sanity APPROVED_FOR_SPEC_V1_DRAFT_WITH_NARROW_GUARDS + iter 1 NEEDS_REVISION_MINOR (IMPORTANT 1-4 + MINOR 1-2 + N-A6) + amend 1 narrow 13 sites + iter 2 NEEDS_REVISION_NARROW (W4 6→5 residue + get_effective_schema_source wording + 9 test total literal cleanup) + amend 2 narrow 4 sites + iter 3 NEEDS_REVISION_NARROW (literal angle-bracket placeholder doctrine drift 3 lines) + amend 3 narrow 3 sites + iter 4 APPROVED_FOR_PLAN.
- **직전 plan drafting session (5 round)**: plan-entry sanity APPROVED_FOR_PLAN_V1_DRAFT_FRESH_WITH_NARROW_GUARDS + iter 1 NEEDS_REVISION_NARROW (4 IMPORTANT) + amend 1 narrow +116 line + iter 2 NEEDS_REVISION_NARROW (4 narrow N-1~N-4) + amend 2 narrow +5 line + iter 3 NEEDS_REVISION_NARROW (2 IMPORTANT N-5/N-6) + amend 3 narrow +22 line + iter 4 APPROVED_FOR_EXECUTION.
- **본 execution session**: W1 entry sanity APPROVED_FOR_W1_ENTRY + W1 per-wave APPROVED_FOR_W2_ENTRY + W2 per-wave APPROVED_FOR_W3_ENTRY + W3 per-wave APPROVED_FOR_W4_ENTRY + W4 per-wave + W1-W4 range review = post-W4 event (verdict recorded by Codex range review + external memory only after push).

### 12.5 함정 신규 (본 carry v1)

Base = §11.3 N-A1~N-A7 + 직전 spec drafting session N-A spec-1~5 + 직전 plan drafting session N-amend-1~11.

본 execution session 안 신규 함정 (Carry-P021 specific):
- **N-exec-1 bash working directory drift** (W2 path-limited git add): `cd backend && pytest` 시 cwd shifts to backend/. 후속 git add `$NEW_DIR/system.md` failed with `/system.md outside repository`. Fix: 매 wave 시작 시 `cd /Users/manta/Documents/Projects/TheRoad-I1` (or explicit repo-root path). `git reset HEAD` to undo partial stage from wrong cwd, then re-stage from repo root.
- **N-exec-2 W2 dir name UTC dimension**: `UTC=$(date -u +%Y%m%d%H%M)` snapshotted at W2.0.b runtime; closure docs (W4) 안 actual W2 dir name (`8.202605191744`) hard-coded directly (not via shell var). Plan §6.3 substitution gate (awk-based) handles this automatically — closure-doc body `8.W2_COMMIT_UTC` underscore placeholder → actual dir name.

### 12.6 Carry Follow-up Post Carry-P021

§11.4 정합:
1. **Future Carry-P021-structured** (`element_id` opaque UUID / `element_type` enum 확장 / `element_scope` enum 확장 / `applies_to_shots` minItems 변경 / JSON example structured schema generation 등 field-shape migration) — major carry / future area follow-up.
2. **Future Carry-A099-structured** (`director_notes` `array of string` → `array of object` 구조화 migration per Codex plan amend 2 N-3 fix) — major area, separate.
3. **Future Carry-A100-structured** (`t2i_context: string` → `object {default_demographic_policy, tone, genre}` field-shape migration) — major carry / future area follow-up.

## 13. References

- **W0.2 inventory + Q1-Q7 outline (untracked)**: `docs/superpowers/specs/2026-05-19-carry-p021-q1-q7-outline.md` (291 line, approved by Codex amend 3 final round 6 APPROVED_FOR_SPEC_V1_DRAFT + CLOSE_HANDOFF_SPEC_FRESH).
- **scene_consistency v7 prompt-pack**: `prompts/_base/scene_consistency/7.202605181210/` (2 file, abstraction target).
- **3 direct surfaces**:
  - `backend/app/core/version_registry.py:36, :130, :131` (W2 3 logical edits target).
  - `backend/app/core/step_manifest.py:655-678` (verify-only, schema_version 3 preserve).
  - `backend/app/core/steps/scene_consistency_step.py:36-140` (Area #4 SOT, 변경 0 boundary).
- **Tests**:
  - `backend/tests/test_prompt_versions.py:14-17, :35, :48, :58` (W1 helper rename + 3 사용 site rename target).
  - `backend/tests/unit/test_scene_consistency_schema_v7.py:8-11` (literal historical pin, 변경 0).
  - `backend/tests/unit/test_scene_consistency_schema_v6.py` (v6 historical pin, 변경 0).
  - `backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py` (W3 신규).
- **Area #4 v1 spec**: `docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md:§1.5/§2.3/§3.2/§7.1/§10.2` (P021 carry boundary + §7.1 carry marker `test_prompt_v7_no_scenario_specific_noun_in_l9_l17`).
- **Roadmap**: `docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md §5.7 Sub-area (b)` (Track B Tier 4 carry follow-up post-Carry-A100).
- **Audit 02**: `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md:§11.3 line 317 + §13 line 382 + §14 line 437 + §15 line 475` Carry-P021 rows.
- **Audit 01**: `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/01-code-side-regex-audit.md:#17 P1-6` (Area #4 closed code-side dependency reference only).
- **Carry-A099 v1 spec (lineage pattern donor)**: `docs/superpowers/specs/2026-05-19-carry-a099-vwr-system-md-director-notes-prose-redesign-v1-design.md` (prose abstraction lineage, 12 sections pattern donor).
- **Carry-A100 v1 spec (lineage pattern donor)**: `docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md` (demonym/인구학 abstraction wording lineage donor, marker doctrine + TEMPLATE ONLY).
- **Pre-Carry-P021 closure**: [[session_20260519_carry_a100_v1_closure]] (origin/main HEAD `0f24492`).
- **Codex iter trace (직전 session)**: Q0-light β-narrow PROCEED + W0.2 inventory APPROVED_FOR_Q1_Q7_OUTLINE_WITH_NARROW_CORRECTIONS + outline review NEEDS_REVISION_NARROW N-1~N-7 + amend 1 re-review NEEDS_REVISION_NARROW N-1A/N-1B/N-4/N-5/N-6/N-7/N-8 + amend 2 re-review NEEDS_REVISION_NARROW N-9/N-10/N-11 + amend 3 final re-review APPROVED_FOR_SPEC_V1_DRAFT + CLOSE_HANDOFF_SPEC_FRESH.
- **Codex iter trace (본 session)**: round 1 spec-entry sanity 의논 → APPROVED_FOR_SPEC_V1_DRAFT_WITH_NARROW_GUARDS (V1/V2/V3 OQ-2~7 resolve + V4 N-A1~N-A7 traps + V5 12-section spec body structure + V6 session health proceed for spec v1 drafting + one review).
- **Memory references**: [[feedback_llm_based_judgment]] + [[feedback_no_vlm_dependency]] + [[feedback_codex_mcp_discussion_workflow]] + [[feedback_codex_mcp_claude_mcp_response_trigger]] + [[feedback_subagent_model_opus]] + [[feedback_push_no_user_ask]] + [[feedback_session_50pct_codex_close_check]] + [[feedback_session_reset_clear_not_exit]] + [[feedback_audit_analysis_vs_spec_entry]] + [[feedback_channel_separation_4way]] + [[session_20260519_area_7a_v1_closure]] + [[session_20260519_area_7b_v1_closure]] + [[session_20260519_area_7c_v1_closure]] + [[session_20260519_area_7d_v1_closure]] + [[session_20260519_carry_d7d_1_v1_closure]] + [[session_20260519_carry_a099_v1_closure]] + [[session_20260519_carry_a100_v1_closure]] + [[next_session_carry_p021_spec_v1_drafting]].
