---
title: Carry-P021 — Scene Consistency Prompt Hygiene v1 implementation plan (v1)
date: 2026-05-20
status: closed (Carry-P021 v1 W1-W4 closed at W4 closure-docs commit, 2026-05-20+; Codex spec quality 5 round + plan-entry sanity APPROVED_FOR_PLAN_V1_DRAFT_FRESH_WITH_NARROW_GUARDS + plan quality iter 1-3 narrow stack + iter 4 APPROVED_FOR_EXECUTION + W1/W2/W3 per-wave APPROVED + W4 closure-docs atomic; final pushed range/count = external memory only after push, post-W4 range review verdict 별도 recording per Codex amend 1 IMPORTANT 2 fix + G-6)
spec_ref: docs/superpowers/specs/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md (status draft, closed only at W4 closure-docs commit)
roadmap_ref: docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md §5.7 Area #7 carry follow-up (Track B Tier 4 carry post #7a/#7b/#7c/#7d/Carry-D7d-1/Carry-A099/Carry-A100)
prerequisites:
  - Spec v1 APPROVED_FOR_PLAN (Codex spec quality round 5 final amend 3 narrow re-review iter 4 verdict; status draft, closed only at W4 closure-docs commit).
  - Area #4 v1 closed (2026-05-18) — code-side classifier 폐기 완료. Area #4 boundary preserve (producer code `scene_consistency_step.py` 변경 0).
  - Area #7a v1 closed (push `d0410eb`) — abstraction pattern reference. VWR producer 변경 0 boundary preserve.
  - Area #7b v1 closed (push `e751e72`) — 11-site cascade pattern reference. 본 carry 영향 0.
  - Area #7c v1 closed (push `62aa2ef`) — placeholder example abstraction pattern reference.
  - Area #7d v1 closed (push `b9c610e`) — dual-site cascade pattern reference.
  - Carry-D7d-1 v1 closed (push `05d5265`) — TEMPLATE ONLY fix-up 1 doctrine source.
  - Carry-A099 v1 closed (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 v1 closed (push `0f24492`) — demonym/인구학 abstraction wording lineage pattern donor + 4-wave structure donor (W1 A099 test compat / W2 v9 producer / W3 A100 integrated test / W4 closure docs path-limited).
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 변경 / JSON example structured schema generation) — 본 v1 scope X, major carry follow-up.
---

# Carry-P021 — Scene Consistency Prompt Hygiene v1 implementation plan (v1)

## 1. Purpose + Spec Reference

본 plan = Carry-P021 spec (status draft, Codex spec quality round 5 final `APPROVED_FOR_PLAN + CLOSE_HANDOFF_PLAN_FRESH`; status closed only at W4 closure-docs commit) 의 W1 test_prompt_versions.py historical cleanup + W2 v8 producer prompt-pack + version_registry sync + W3 Carry-P021 integrated test + W4 closure docs wave 실행 contract. spec §1-§13 fully 참조 (본 plan 안 spec 본문 재기술 0, ambiguity 제거 위한 inline command + Codex 명시 narrow guard 만 포함).

**Spec 참조 key index** (본 plan 작성 시 cross-reference, edit 0 의무):
- spec §1.1 Purpose = scene_consistency v7 system.md hard-prime example phrases + demographic default instruction narrow abstraction (v8 prompt-pack 신규 dir).
- spec §1.2 In-scope = scene_consistency v8 신규 prompt-pack dir 2 file + version_registry 3 logical edits + test_prompt_versions.py W1 historical cleanup + W3 integrated test + W4 closure docs.
- spec §1.3 Out-of-scope = 12 narrow guard 모두 명시 + Future Carry-P021-structured deferred.
- spec §1.4 4-Gate Boundary Doctrine 적용 table.
- spec §2 W0 evidence inventory (W0.2 + 본 session direct read verify).
- spec §2.1.1 Strict R catalog marker-wrapped (R1-R6 + JS1/JS2a/JS2b/JS3 + 2 optional).
- spec §3 Sync Contract (8-row table, prompt-pack 2 file new + version_registry 3 logical edits + STEP_MANIFEST verify-only + producer code rewrite 0 + source-path proof via `get_effective_source` dict).
- spec §4 W1 Implementation Contract (commit boundary + 5 edit operation + 4 pre-commit verify gate + targeted pytest).
- spec §5 W2 Implementation Contract (commit boundary + 2 file new + 1 file modify 3 logical edits + 8 pre-commit verify gate + targeted pytest).
- spec §6 W3 Implementation Contract (commit boundary + 1 file new + G1-G7 7 Gate + 3 pre-commit verify gate + targeted pytest).
- spec §7 W4 Implementation Contract (commit boundary + 5 repo-local docs + TEMPLATE ONLY doctrine + final pushed range/count external memory + 3 pre-commit verify gate).
- spec §8 Test/Gate Contract (G1-G7 enumeration + STRICT_RESIDUES single constant + marker-excluded scan + closed-world full-phrase + standalone token global ban X + test anchor preservation).
- spec §9 Doctrine (4-Gate + NO VLM + closed-world + standalone token global ban X + marker-wrapped + TEMPLATE ONLY + 4채널 fact source + field-shape migration deferred + Workflow doctrine).
- spec §10 Allowed/Forbidden Claim.
- spec §11 Traps / provenance / carry follow-up (Tier 1-3 inherited + Carry-A099/A100 lineage + 본 carry N-A1~N-A7 + N-A spec-1~5).
- spec §12 Closure (deferred to W4 closure-docs wave, in-place REPLACE template per Carry-A100 spec §10 doctrine).
- spec §13 References (W0.2 + outline + direct surfaces + tests + Area #4 spec + roadmap + audit 02 + Carry-A099/A100 spec lineage donor + memory).

## 2. Plan Iter Trace

- **iter 0** (본 plan session, strategy 본 instance proposed + Codex MCP 의논): Codex plan-entry sanity verdict `APPROVED_FOR_PLAN_V1_DRAFT_FRESH_WITH_NARROW_GUARDS` (7 narrow guards: G-1 explicit plan-quality stop + G-2 prose/runtime placeholder separation + G-3 placeholder target 3-way 분리 + G-4 W4 marker-aware staged-content gate + G-5 5-doc path-limited + G-6 W4 commit body self-hash + final pushed range/count external memory + W1/W2/W3/W4 wave guards).
- **iter 1** (plan quality round, 본 plan 작성 후 Codex 의논): pending. Plan v1 draft 완료 후 Codex plan quality iter 1 review request 의무 (Codex G-1 정합) — W1 execution 전 plan `APPROVED_FOR_EXECUTION` 의무.

## 3. W1 Implementation Atomic Wave — test_prompt_versions.py historical cleanup

### 3.1 Pre-W1 Entry Sanity (Codex re-discuss + git status hygiene)

**(W1.0.a) Codex re-discuss session health + W1 entry sanity** (Codex G-1 정합):
- Plan v1 draft 완료 + Codex plan quality iter 1 `APPROVED_FOR_EXECUTION` verdict 후만 W1 진입.
- W1 entry 직전 Codex MCP 의논 — session usage check + W1 commit risk re-confirm (test-only narrow modification, no prompt/code/production change).
- Codex `APPROVED_FOR_W1_ENTRY` (또는 `CLOSE_HANDOFF_W1_FRESH`) verdict 후만 W1 진입.

**(W1.0.b) git status hygiene**:
```bash
git status --short
# Expected: 본 carry scope 외 file modification 0.
# 본 carry scope 외 untracked file (audit output dir / 본 W0.2 inventory + Q1-Q7 outline + 본 spec/plan = untracked, W4 closure path-limited add only) = git add 대상 X 의무.
# Working branch = main.
```

### 3.2 W1 File Operations (1 file modify, spec §4.2 정합)

**path-limited scope**: `backend/tests/test_prompt_versions.py` (1 file, modify only).

#### 3.2.1 Edit operations (5 narrow edit per spec §4.2 (a)-(e))

**(a) Helper rename + literal historical pin** (spec §4.2 (a)):
- 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 안 보존).
- After form:
  ```python
  def _scene_consistency_v7_historical_dir() -> Path:
      """historical v7 디렉토리 literal pin — Area #4 W1 anchor (Carry-P021 W1 transitioned to historical pin, v8 active)."""
      return REPO_ROOT / "prompts" / "_base" / "scene_consistency" / "7.202605181210"
  ```

**(b) Line 10 comment narrow append** (spec §4.2 (b)):
- Line 10 `# 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 prompt-pack by Carry-P021)`.
- Note (Codex amend 1 IMPORTANT 1 fix): W1 target file (`backend/tests/test_prompt_versions.py`) 는 W4 substitution scope 외 (5 closure docs only) — W1 line 10 comment 안 design-time dir placeholder (예: `8.202605191744` underscore form) 사용 X. closure docs (5 file) 안에서만 underscore form 의 closure-doc substitute target 사용 + W4 placeholder substitution gate 안 actual W2 dir name으로 substitute (Codex G-2 + G-3 정합).

**(c) 3 test rename + 3 helper 호출 site rename 흡수** (spec §4.2 (c) + Codex V3 OQ-6 expansion 흡수, 본 session direct verify 3 사용 site):
- **Site #1** — 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 (active loader proof → historical v7 anchor proof; element_scope presence + enum + system.md key clause preserve).
- **Site #2** — 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 v7 anchor A037 closed-list signature 0 proof).
- **Site #3** — 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 v7 anchor A038 element_id opaque proof).

**(d) Existing assertions preserve except active-loader claim** (spec §4.2 (d) + Codex W1 guard 정합):
- element_scope presence (`"element_scope" in item_props`) preserve.
- `["full", "close"]` enum (`item_props["element_scope"]["enum"] == ["full", "close"]`) preserve.
- `"element_scope" in system_text` preserve.
- `"element_scope 결정 (필수 emit)" in system_text` preserve.
- `FORBIDDEN_PROMPT_PATTERNS` regex absence (`not re.search(pattern, system_text)`) preserve.
- `"opaque snake_case" in system_text` preserve.
- `"암시하지 말" in system_text or "암시하지말" in system_text` preserve.
- **Note**: 본 assertion 들 = active-loader-agnostic; v8 활성화 후에도 historical pin v7 안 동일하게 PASS 의무 (v7 system.md = 변경 0, historical pin 유지).
- behavioral change 0. test count = live collect 결과 모두 PASS 의무.

**(e) sha256 byte-identical anchor gate W1 X** (spec §4.2 (e) + Codex W1 guard 정합):
- sha256 canary 추가 X (W1 = behavioral change 0).
- Schema byte-identical canary 는 W2 pre-commit verify gate (g) + W3 G5 안 보존 (Carry-A099/A100 lineage 정합 — W2/W3 안 schema sha256 verify, W1 안 X).

### 3.3 W1 Pre-Commit Verify Gates (5 check = 4 spec §4.4 gates + 1 Codex amend 1 IMPORTANT 1 fix target-placeholder gate per amend 2 N-1)

**(a) Helper symbol 완전 historical 전환** (spec §4.4 (a)):
```bash
grep -n "_scene_consistency_v7_dir\b" backend/tests/test_prompt_versions.py
# Expected: exit 1 (no match outside _scene_consistency_v7_historical_dir form, helper symbol 완전 historical 전환).
helper_hits=$(grep -c '_scene_consistency_v7_dir\b' backend/tests/test_prompt_versions.py 2>/dev/null; true); helper_hits=${helper_hits:-0}
[ "$helper_hits" -eq 0 ] && echo "OK helper symbol completely historical" || { echo "FAIL: stale helper symbol still present"; exit 1; }
# Note (Codex amend 3 N-5 fix): grep -c on 0 hits outputs "0" + exit 1; original `|| echo 0` form caused "0\n0" capture bug. Fixed via `; true` sequencing + `${var:-0}` defaulting per Codex amend 3 N-5 safe-count pattern.
```

**(b) Literal historical pin presence** (spec §4.4 (b)):
```bash
grep -F '"prompts" / "_base" / "scene_consistency" / "7.202605181210"' backend/tests/test_prompt_versions.py
# Expected: exit 0 (helper body literal pin substring).
hits=$(grep -cF '"prompts" / "_base" / "scene_consistency" / "7.202605181210"' backend/tests/test_prompt_versions.py)
[ "$hits" -ge 1 ] && echo "OK literal historical pin present ($hits)" || { echo "FAIL: literal historical pin missing"; exit 1; }
```

**(c) 3 test rename presence** (spec §4.4 (c)):
```bash
grep -nE 'def test_prompt_v7_historical_(loader_anchor|no_closed_framing_list|no_element_id_suffix_guide)' backend/tests/test_prompt_versions.py
# Expected: 3 hit.
hits=$(grep -cE 'def test_prompt_v7_historical_(loader_anchor|no_closed_framing_list|no_element_id_suffix_guide)' backend/tests/test_prompt_versions.py)
[ "$hits" -eq 3 ] && echo "OK 3 test rename present" || { echo "FAIL: rename count $hits != 3"; exit 1; }

# old form 폐기 verify
old_hits=$(grep -cE 'def test_prompt_v7_(active_loader_matches_file|no_closed_framing_list|no_element_id_suffix_guide)\b' backend/tests/test_prompt_versions.py)
[ "$old_hits" -eq 0 ] && echo "OK old test names absent" || { echo "FAIL: old test name still present ($old_hits)"; exit 1; }
```

**(d) Existing assertions preserve regression — targeted pytest entire file ALL PASS** (spec §4.4 (d) + 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 회피):
```bash
backend/.venv/bin/pytest backend/tests/test_prompt_versions.py -v --tb=short
# Expected: file 안 all test def collect + ALL PASS (live collect 결과 ~18 test def: v7 3 renamed + v6 2 historical + scene_detail v14 4 + shot_staging v10/v12 + scene_detail v23 + scene_extractor_v2 v19 + manifest entries 등). 모두 preserve, behavioral change 0.
```

**(e) `8.202605191744` design-time placeholder absence in W1 target file** (Codex amend 1 IMPORTANT 1 fix — W1 target = W4 substitution scope 외, 5 closure docs only):
```bash
hits=$(grep -cF '8.202605191744' backend/tests/test_prompt_versions.py 2>/dev/null; true); hits=${hits:-0}
[ "$hits" -eq 0 ] && echo "OK W1 target file 안 8.202605191744 design-time placeholder absent" || { echo "FAIL: W1 target file 안 design-time placeholder leaked ($hits hits)"; exit 1; }
```

**Manual gate boundary** (spec §4.4 정합 + Codex amend 1 IMPORTANT 1 fix): 본 (a)-(e) 5 check = manual pre-commit verification gates, repo pre-commit hooks 와 별개. Hook output 가 본 manual gates 를 대체하지 않음.

### 3.4 W1 Targeted Pytest (spec §4.5 정합)

```bash
backend/.venv/bin/pytest backend/tests/test_prompt_versions.py -v --tb=short
# Expected: ALL PASS.
```

### 3.5 W1 Path-Limited git add + Commit

**path-limited add scope** (1 file, 0 file out-of-scope):
```bash
git add backend/tests/test_prompt_versions.py
git diff --cached --name-only
# Expected (exact match with expected path list):
# backend/tests/test_prompt_versions.py
# (1 file, W1 = test-only narrow modification, 0 out-of-scope.)

git status --short -- backend/tests/test_prompt_versions.py
# Expected: " M backend/tests/test_prompt_versions.py".

# Global status check (known untracked preserved verify only)
git status --short | head -10
# Expected: known untracked artifact preserve (W0.2 inventory + Q1-Q7 outline + 본 spec/plan 기타 untracked); W1 target 외 modified/staged 0.
```

**Commit message format** (spec §4.1 정합):
```
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)

- _scene_consistency_v7_dir() (line 14-18) → _scene_consistency_v7_historical_dir() function rename + body refactor (active glob resolution 폐기 + literal pin "prompts/_base/scene_consistency/7.202605181210")
- 3 helper 호출 site (line 35/48/58) rename 흡수 (test_prompt_v7_active_loader_matches_file body + test_prompt_v7_no_closed_framing_list body + test_prompt_v7_no_element_id_suffix_guide body)
- 3 test rename: test_prompt_v7_active_loader_matches_file → test_prompt_v7_historical_loader_anchor (line 34) + test_prompt_v7_no_closed_framing_list → test_prompt_v7_historical_no_closed_framing_list (line 46) + test_prompt_v7_no_element_id_suffix_guide → test_prompt_v7_historical_no_element_id_suffix_guide (line 56)
- Body docstring rewording from active loader proof to historical anchor proof
- Line 10 comment narrow append (Carry-P021 W1 historical pin transitioned to v8 active prompt-pack by Carry-P021; W1 target = W4 substitution scope 외, design-time dir placeholder 사용 X per Codex amend 1 IMPORTANT 1 fix)
- Existing assertions preserve (element_scope presence + enum + system.md key clause + FORBIDDEN_PROMPT_PATTERNS regex absence + opaque snake_case + 암시하지 말)
- No sha256 canary in W1 (Codex W1 guard 정합 — schema byte-identical canary = W2 gate (g) + W3 G5)

Pre-commit verify (5 gate = 4 spec §4.4 gates + 1 Codex amend 1 IMPORTANT 1 target-placeholder gate per amend 2 N-1): helper symbol completely historical + literal historical pin present + 3 test rename present + old test names absent + pytest entire file ALL PASS + 8.202605191744 design-time placeholder absent in W1 target file.

Targeted pytest (spec §4.5): `backend/.venv/bin/pytest backend/tests/test_prompt_versions.py -v --tb=short` — N tests, N PASS, 0 FAIL (W1 execution 시 실측 N 값 commit body 안 기록 의무).

NO VLM. no live LLM. closed-world exact phrase membership only. standalone token global ban X.

Codex APPROVED_FOR_W1_ENTRY (W1 entry sanity round) + spec quality round 5 final APPROVED_FOR_PLAN + plan quality iter 1 APPROVED_FOR_EXECUTION.
```

### 3.6 W1 Codex per-wave review

- W1 commit 후 즉시 Codex per-wave review 의무.
- Codex live verify: §3.2 1 file edit + §3.3 4 pre-commit gate PASS + §3.4 N test PASS evidence.
- Codex verdict 예상 = `APPROVED_FOR_W2_ENTRY` or `NEEDS_REVISION_NARROW`.

## 4. W2 Implementation Atomic Wave — v8 producer prompt-pack + version_registry sync

### 4.1 Pre-W2 Entry Sanity (Codex re-discuss + UTC resolution + git status hygiene)

**(W2.0.a) Codex re-discuss + W2 entry sanity**:
- W1 per-wave review `APPROVED_FOR_W2_ENTRY` 후만 W2 진입.

**(W2.0.b) UTC timestamp resolution + new dir name** (Codex G-2 + G-3 정합 — runtime command block `8.${UTC}` shell var form OK):
```bash
UTC=$(date -u +%Y%m%d%H%M)
NEW_DIR="prompts/_base/scene_consistency/8.${UTC}"
export UTC NEW_DIR  # Python subprocess (`os.environ.get('NEW_DIR')`) 안 inherit 의무, Carry-A099 N-5 narrow doctrine 정합
echo "Carry-P021 W2 NEW_DIR = $NEW_DIR"
# Expected: 8.202605XXXX 형식, 7.202605181210 보다 후행 (시간 단조 증가).
```

**중요** (Carry-A099 N-5 doctrine 정합): `export UTC NEW_DIR` = §4.3(g) Python subprocess (`os.environ.get('NEW_DIR')`) 안 inherit 의무. export 미실행 시 schema-specific existence proof gate 가 silent fail (empty path → `os.path.isfile('')` False).

**(W2.0.c) git status hygiene** (Codex G-5 + Carry-A100 W2 narrow doctrine 정합):
```bash
# W2 scope 외 modification 0 verify (path-limited check, W1 commit 후 working tree clean preserve)
git diff --name-only
# Expected: 0 modified file (W1 commit 후 clean).
# Known untracked artifact = preserve (git add 대상 X).
```

### 4.2 W2 File Operations (2 file new + 1 file modify 3 logical edits, spec §5.2 정합)

#### 4.2.1 New v8 prompt-pack dir (2 file new)

```bash
mkdir -p "$NEW_DIR"
# (a) schema.json byte-identical copy first
cp prompts/_base/scene_consistency/7.202605181210/schema.json "$NEW_DIR/schema.json"
# (b) system.md copy first, then narrow modify
cp prompts/_base/scene_consistency/7.202605181210/system.md "$NEW_DIR/system.md"
```

#### 4.2.2 system.md narrow abstraction (spec §5.2.1 (c) — R1-R6 + JS1/JS2a/JS2b/JS3 narrow abstraction)

**Substitution scope** (closed-world exact substring replacement):

본 W2 의 narrow edit = exact `before` substring → `after` substring (spec §2.1.1 marker block 안 R1-R6 + JS1/JS2a/JS2b/JS3 정확 wording 인용; 본 plan 안 reference only — Codex N-A3 marker block-only doctrine + post-Carry-D7d-1 fix-up 1 강화 + Carry-A100 N-1 정합).

**R1 line 13 abstraction** (rest state example):
- `before`: spec §2.1.1 marker block R1 wording (line 13 전체 `예 (rest state):` 블록).
- `after`: 블록 전체 제거 + R1 후속 abstract clause를 line 11 ~ line 12 abstract clause 안 흡수 (예: line 11 protective preserve + line 12 line 12 directly above 안 `원문에 명시된 inactive/restful pose는 구체 자세, 팔다리 위치, 시선 상태 그대로 기록한다` clause 흡수 — Carry-A099 lineage abstract process wording 정합).

**R2 line 14 abstraction** (specific localized condition example):
- `before`: spec §2.1.1 marker block R2 wording (line 14 전체).
- `after`: 블록 전체 제거 + abstract clause 흡수 (`원문에 명시된 localized 인물 상태는 원문 묘사 그대로 기록하고 LLM 추론으로 확장하지 않는다`).

**R3 line 18 abstraction** (shattered-window example):
- `before`: spec §2.1.1 marker block R3 wording (line 18 전체).
- `after`: 블록 전체 제거 + abstract clause 흡수 (`원문에 명시된 환경 상태(창문/문/벽/조명 등)는 원문 묘사 그대로 기록한다`).

**R4 line 22 abstraction** (bedsheet example):
- `before`: spec §2.1.1 marker block R4 wording (line 22 전체).
- `after`: 블록 전체 제거 + abstract clause 흡수 (`원문에 명시된 소품 위치/상태는 원문 묘사 그대로 기록한다`).

**R5 line 58 abstraction** (concrete posture example, Codex V3 OQ-2 strict residue constant boundary 정합):
- `before`: spec §2.1.1 marker block R5 strict residue wording — quoted English concrete posture phrase only (Korean rule label + 분석 원칙 preserve, Codex N-A4 정합).
- `after`: Korean rule label `5. **구체적 자세/위치**: "lying down" 같은 모호한 표현 금지` preserve + 후속 clause abstract lift (`"lying down" 같은 모호한 표현 대신 원문에 명시된 자세/팔다리 위치/시선 상태를 그대로 기록한다`).

**R6 line 61 abstraction** (demographic default instruction, Codex V3 OQ-3 default pin Carry-A100 lineage 정합):
- `before`: spec §2.1.1 marker block R6 wording (line 61 전체 `8. **인종/국적 명기**: 인물 묘사 시 인종/국적을 반드시 포함`).
- `after`: `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 + Carry-A099 director_notes prose redesign lineage 정합):
- `before`: spec §2.1.1 marker block 안 line 89-110 JSON example block 전체 (placeholder-free abstract labels, demographic/default posture prose 0, opaque element_id naming guidance only).
- `after`: 블록 전체 제거 + abstract schema skeleton 변환 (예: section heading 안 `각 fixed_element 는 schema 안 모든 required field 를 jsonschema 형태로 emit. element_id 는 opaque snake_case, demographic/default posture prose 0, scope/framing intent 는 element_scope 필드에만 기록.`).

**Preserve obligatory** (spec §5.2.1 정합):
- line 11 protective negative wording (`원문이 묘사한 상태만 기록. 장르 편향으로 상처·혈흔을 임의 추가 금지`) preserve.
- 분석 원칙 1-10 안 abstract guidance preserve (R5 abstraction wording 만 narrow substitute).
- 고정 요소 유형 1-3 section preserve (`character_state` / `environment_state` / `persistent_prop` heading + abstract guidance).
- element_scope 결정 (필수 emit) section preserve (Area #4 v7 instruction core).
- Evidence and inference disclosure (per fixed_element) section preserve.

#### 4.2.3 `backend/app/core/version_registry.py` 3 logical edits (1 file modify, spec §5.2.2 정합)

**Site 1 line 36**: `MODULE_VERSIONS["scene_consistency"]: "2.5.0"` → `"2.6.0"`:
- `before`: `"scene_consistency": "2.5.0",         # 2026-05-18 — v7 prompt (Area #4): element_scope enum required ("full" | "close") — fixed_elements item 에 element_scope SOT. code-side close/full inference helper trio 폐기. closed-list reasoning + element_id suffix guide 폐기. 옛 v6 cp invalidation.`
- `after`: `"scene_consistency": "2.6.0",         # 2026-05-20 — Carry-P021: v8 prompt — scene_consistency v7 system.md hard-prime examples abstracted. content-only abstraction, schema byte-identical, schema_version=3 preserve. Area #4 boundary preserve (producer code 변경 0).`
- Note (Codex amend 1 IMPORTANT 1 fix): W2 target code file (`backend/app/core/version_registry.py`) 는 W4 substitution scope 외 (5 closure docs only) — Site 1 after comment 안 design-time dir placeholder (예: `8.202605191744` underscore form) 사용 X. closure docs (5 file) 안에서만 underscore form 의 closure-doc substitute target 사용. v8 prompt-pack dir name reference 필요 시 W2 execution 시점 actual `$NEW_DIR` shell var resolve된 runtime literal로 inline comment 추가 가능 (default = omit, Codex amend 1 IMPORTANT 1 fix 정합).

**Site 2 line 130**: `_MODULE_INFO["scene_consistency"]["prompt_dependency"]: "scene_consistency/v7"` → `"scene_consistency/v8"`:
- `before`: `        "prompt_dependency": "scene_consistency/v7",`
- `after`: `        "prompt_dependency": "scene_consistency/v8",`

**Site 3 line 131**: `_MODULE_INFO["scene_consistency"]["updated_at"]: "2026-05-18"` → `"2026-05-20"`:
- `before`: `        "updated_at": "2026-05-18",`
- `after`: `        "updated_at": "2026-05-20",  # Carry-P021 v8 prompt — hard-prime examples abstracted`

#### 4.2.4 Boundary preserve (No edit obligatory)
- `prompts/_base/scene_consistency/7.202605181210/` (archive preserve, 변경 0 — Carry-A099/A100 lineage 정합).
- `backend/app/core/steps/scene_consistency_step.py` (Area #4 SOT producer code, 변경 0 boundary — `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).
- `backend/app/core/step_manifest.py` (scene_consistency entry verify-only, 변경 0 — schema_version=3 preserve + 12 sub-field preserve).
- `backend/tests/test_prompt_versions.py` (W1 modified at W1 commit, W2 변경 0).
- `backend/tests/unit/test_scene_consistency_schema_v7.py` (literal historical pin, 변경 0).
- `backend/tests/unit/test_scene_consistency_schema_v6.py` (v6 historical pin, 변경 0).
- 20+ unrelated consumer (≥12 file, spec §2.6 category 4) 변경 0.
- Area #4 / #7a / #7b / #7c / #7d / Carry-D7d-1 / Carry-A099 / Carry-A100 closure boundary preserve.

### 4.3 W2 Pre-Commit Verify Gates (9 check = 8 spec §5.4 gates + 1 Codex amend 1 IMPORTANT 1 fix target-placeholder gate per amend 2 N-1)

**(a) UTC + new dir verify** (spec §5.4 (a)):
```bash
[ -d "$NEW_DIR" ] && echo "OK new dir: $NEW_DIR" || { echo "FAIL new dir missing"; exit 1; }
```

**(b) New dir file count = 2** (spec §5.4 (b)):
```bash
count=$(ls "$NEW_DIR" | wc -l | tr -d ' ')
[ "$count" -eq 2 ] || { echo "FAIL: file count $count != 2"; exit 1; }
ls "$NEW_DIR" | sort
# Expected: schema.json + system.md
echo "OK 2 file exact in $NEW_DIR"
```

**(c) schema.json sha256 byte-identical from v7** (spec §5.4 (c)):
```bash
S7=$(shasum -a 256 prompts/_base/scene_consistency/7.202605181210/schema.json | cut -d' ' -f1)
S8=$(shasum -a 256 "$NEW_DIR/schema.json" | cut -d' ' -f1)
[ "$S7" = "$S8" ] && echo "OK schema.json sha256 match v7=$S7 v8=$S8" || { echo "DRIFT: schema.json sha mismatch v7=$S7 v8=$S8"; exit 1; }
```

**(d) STRICT_RESIDUES 10-id absence in v8 system.md** (spec §5.4 (d) + Codex β-narrow + Carry-A099 G4 lineage 정합):

본 (d) gate exact residue wording = spec §2.1.1 marker block 안 strict R catalog (R1-R6 + JS1/JS2a/JS2b/JS3) 인용; 본 plan 안 R-id reference only (Codex N-A3 marker block-only doctrine 정합).

```bash
SYS="$NEW_DIR/system.md"
hits=0
# R1-R6 + JS1/JS2a/JS2b/JS3 10 strict residue (exact wording = spec §2.1.1 marker block 안)
# fixed-string scan obligatory (`rg -F` / `grep -cF` only, semantic regex X)
# spec §2.1.1 marker block 안 R1 wording / R2 wording / R3 wording / R4 wording / R5 strict (quoted English posture phrase only) / R6 wording / JS1 wording / JS2a wording / JS2b wording / JS3 wording each → grep -cF in $SYS == 0
# (실제 grep 명령 substring = spec §2.1.1 marker block 안 인용; 본 plan body 안 재방출 X — Codex G-2 + N-A3 정합)
# Pseudocode:
# for residue in $STRICT_RESIDUES_TUPLE; do
#   c=$(grep -cF -- "$residue" "$SYS")
#   [ "$c" -eq 0 ] || { echo "FAIL R-id residue: $residue (hits=$c)"; hits=1; }
# done
# [ "$hits" -eq 0 ] && echo "OK STRICT_RESIDUES 10-id absent in $SYS" || exit 1
```

**Note**: W2 pre-commit gate (d) 실제 실행 시 spec §2.1.1 marker block 안 exact STRICT_RESIDUES tuple 안 10 strict residue wording 각각 `grep -cF` 호출. 본 plan body 안 quoted exact wording 재방출 0 (Codex N-A3 doctrine 정합 — marker block-only). W3 G3 test 와 동일 STRICT_RESIDUES single constant 활용 (Codex N-6 정합).

**(e) New abstract wording presence** (spec §5.4 (e) + Codex V3 OQ-3 default pin Carry-A100 lineage 정합):
```bash
SYS="$NEW_DIR/system.md"

# R6 abstraction Korean lead clause (full-phrase membership)
R6_LEAD="8. **시각적 인구학 단서 반영**:"
R6_HIT=$(grep -cF -- "$R6_LEAD" "$SYS")
[ "$R6_HIT" -ge 1 ] && echo "OK R6 lead clause hit ($R6_HIT)" || { echo "FAIL: no R6 lead clause in $SYS"; exit 1; }

# R6 abstraction Korean second clause (Carry-A100 lineage default-coerce 강제 X)
R6_SECOND="명시되지 않은 인물에 default 인구학 표기를 강제하지 않는다"
R6_SEC_HIT=$(grep -cF -- "$R6_SECOND" "$SYS")
[ "$R6_SEC_HIT" -ge 1 ] && echo "OK R6 second clause hit ($R6_SEC_HIT)" || { echo "FAIL: no R6 second clause in $SYS"; exit 1; }

# R1-R5 abstraction Korean clause (process wording)
R1_R5="원문에 명시된 inactive/restful pose는 구체 자세"
R1R5_HIT=$(grep -cF -- "$R1_R5" "$SYS")
[ "$R1R5_HIT" -ge 1 ] && echo "OK R1-R5 abstract clause hit ($R1R5_HIT)" || { echo "FAIL: no R1-R5 abstract clause in $SYS"; exit 1; }
```

**(f) version_registry 3 logical edits sync** (spec §5.4 (f) + Carry-A099 N-5 cwd-relative lesson + Codex W2 guard 정합):
```bash
cd backend && .venv/bin/python -c "
import sys
sys.path.insert(0, '.')
from app.core.version_registry import MODULE_VERSIONS, _MODULE_INFO

# Site 1 MODULE_VERSIONS bump
assert MODULE_VERSIONS['scene_consistency'] == '2.6.0', (
    f\"Site 1 drift: MODULE_VERSIONS[scene_consistency]={MODULE_VERSIONS['scene_consistency']}\"
)
print('OK Site 1 MODULE_VERSIONS == 2.6.0')

# Site 2 prompt_dependency sync
assert _MODULE_INFO['scene_consistency']['prompt_dependency'] == 'scene_consistency/v8', (
    f\"Site 2 drift: prompt_dependency={_MODULE_INFO['scene_consistency']['prompt_dependency']}\"
)
print('OK Site 2 prompt_dependency == scene_consistency/v8')

# Site 3 updated_at sync
assert _MODULE_INFO['scene_consistency']['updated_at'] == '2026-05-20', (
    f\"Site 3 drift: updated_at={_MODULE_INFO['scene_consistency']['updated_at']}\"
)
print('OK Site 3 updated_at == 2026-05-20')
" && cd ..
```

**(g) Active-version resolution via loader source-path proof** (spec §5.4 (g) + Codex W2 guard 정합 — Carry-A099 G1 lineage Codex IMPORTANT 3 정합 + Codex amend 1 IMPORTANT 1 fix — `get_effective_source()` returns dict + `.md` stem only + schema sibling separation):
```bash
cd backend && .venv/bin/python -c "
import os
import sys
from pathlib import Path
sys.path.insert(0, '.')
from app.modules.prompt_loader import get_effective_source

# System prompt source-path proof via get_effective_source dict shape
src = get_effective_source('scene_consistency', 'system', db=None)
file_cand = src['candidates']['file']
assert file_cand is not None, 'no file candidate for scene_consistency/system'
fver = str(file_cand['version'])
fpath = str(file_cand['path'])
assert fver.startswith('8.'), f'scene_consistency/system version drift: {fver} (expected 8.* prefix)'
assert '/scene_consistency/8.' in fpath, f'scene_consistency/system path drift: {fpath}'
print(f'OK active system source-path: version={fver} path={fpath}')

# Schema source-path proof = system path sibling schema.json existence (separation per N-A6)
# 'get_effective_source(\"scene_consistency\", \"schema\")' 사용 X (.md stem only, schema.md 찾음 — schema.json source-path proof X).
# 'load_prompt' / 'load_schema' = content-load smoke only, source-path proof X.
# 'get_active_version' = module-level active-version, schema stem source-path proof X.
system_path = Path(fpath)
schema_path = system_path.parent / 'schema.json'
# Carry-A099 N-5 cwd-relative lesson: 본 script = backend cwd, fpath 는 이미 absolute path (prompt_loader 가 PROMPTS_BASE 기준 resolution).
assert schema_path.is_file(), f'schema-specific file existence FAIL: {schema_path}'
assert '/scene_consistency/8.' in str(schema_path), f'schema-specific path FAIL: {schema_path}'
print(f'OK schema-specific path proof: {schema_path}')
" && cd ..
```

**(h) STEP_MANIFEST schema_version preserve** (spec §5.4 (h)):
```bash
cd backend && .venv/bin/python -c "
import sys
sys.path.insert(0, '.')
from app.core.step_manifest import STEP_MANIFEST
assert STEP_MANIFEST['scene_consistency']['schema_version'] == 3, (
    f\"STEP_MANIFEST drift: {STEP_MANIFEST['scene_consistency']['schema_version']}\"
)
print('OK STEP_MANIFEST schema_version=3 preserve')
" && cd ..
```

**(i) `8.202605191744` design-time placeholder absence in W2 target code/test files** (Codex amend 1 IMPORTANT 1 fix — W2 target code = W4 substitution scope 외, 5 closure docs only):
```bash
W2_TARGETS=(backend/app/core/version_registry.py "$NEW_DIR/system.md" "$NEW_DIR/schema.json")
TOTAL=0
for f in "${W2_TARGETS[@]}"; do
  hits=$(grep -cF '8.202605191744' "$f" 2>/dev/null; true); hits=${hits:-0}
  TOTAL=$((TOTAL + hits))
  [ "$hits" -eq 0 ] || echo "FAIL: W2 target $f 안 design-time placeholder leaked ($hits hits)"
done
[ "$TOTAL" -eq 0 ] && echo "OK W2 target files 안 8.202605191744 design-time placeholder absent" || { echo "FAIL: W2 design-time placeholder total $TOTAL hits"; exit 1; }
```

**Manual gate boundary** (Codex amend 1 IMPORTANT 1 fix): 본 (a)-(i) 9 check = manual pre-commit verification gates, repo pre-commit hooks 와 별개.

### 4.4 W2 Targeted Pytest (spec §5.5 정합)

```bash
cd backend
.venv/bin/pytest \
  tests/test_prompt_versions.py \
  tests/test_step_manifest_v3.py \
  tests/test_manifest_fields.py \
  tests/test_step_catalog.py \
  tests/test_sync_v3.py \
  tests/unit/test_g3_2_manifest_dag.py \
  tests/unit/test_scene_consistency_schema_v7.py \
  -v --tb=short
cd ..
# Expected: ALL PASS (prompt/version + manifest/version-registry + v7 schema historical regression).
```

### 4.5 W2 Path-Limited git add + Commit

**path-limited add scope** (3 file = 2 new + 1 modify):
```bash
git add "$NEW_DIR/system.md" "$NEW_DIR/schema.json" backend/app/core/version_registry.py
git diff --cached --name-only
# Expected (exact match with expected path list):
# backend/app/core/version_registry.py
# prompts/_base/scene_consistency/8.${UTC}/schema.json
# prompts/_base/scene_consistency/8.${UTC}/system.md
# (3 file, W2 = prompt-pack + version_registry sync, 0 out-of-scope.)

git status --short | head -10
# Expected: known untracked artifact preserve; W2 target 외 modified/staged 0.
```

**Commit message format** (spec §5.1 정합):
```
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)

- prompts/_base/scene_consistency/8.${UTC}/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 + 분석 원칙 1-10 abstract guidance + 고정 요소 유형 1-3 section + element_scope 결정 section + Evidence and inference disclosure section 모두 preserve)
- prompts/_base/scene_consistency/8.${UTC}/schema.json byte-identical copy from v7 (sha256 match)
- backend/app/core/version_registry.py 3 logical edits:
  Site 1 line 36 MODULE_VERSIONS["scene_consistency"]: "2.5.0" → "2.6.0" + Area #4 anchor comment narrow append (Carry-P021 hard-prime example abstraction)
  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"
- STEP_MANIFEST["scene_consistency"]["schema_version"] == 3 preserve (no edit, spec §5.2.4 + §6.6 Codex V3 OQ-5 정합)
- SCENE_CONSISTENCY_SCHEMA_VERSION == 3 preserve (no edit, Area #4 boundary 정합)
- scene_consistency_step.py 변경 0 (Area #4 SOT producer code boundary preserve)
- Active prompt source-path proof via get_effective_source dict + schema sibling existence (Carry-A099 G1 lineage + Codex amend 1 IMPORTANT 1 + W2 guard 정합 — load_prompt / load_schema / get_effective_source on schema stem 사용 X)

Pre-commit verify (9 gate = 8 spec §5.4 gates + 1 Codex amend 1 IMPORTANT 1 target-placeholder gate per amend 2 N-1): UTC + file count 2 + sha256 byte-identical + STRICT_RESIDUES 10-id 0 hit + abstract wording presence + version_registry 3 sync + active source-path proof + STEP_MANIFEST preserve + 8.202605191744 design-time placeholder absent in W2 target files.

Targeted pytest (spec §5.5): `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` — N tests, N PASS, 0 FAIL.

W1 commit reference: {W1_HASH} (1 file modify, test_prompt_versions.py historical cleanup).

NO VLM. no live LLM. closed-world exact phrase membership only. standalone token global ban X. Future Carry-P021-structured deferred.

Codex APPROVED_FOR_W2_ENTRY (W2 entry sanity round) + W1 per-wave APPROVED_FOR_W2_ENTRY + plan iter 1 APPROVED_FOR_EXECUTION.
```

**Note** (Codex G-6 정합): commit body 안 `{W1_HASH}` = W1 commit 직후 실제 git rev-parse 로 substitute (controller-substitute target, underscore form). 본 plan body 안 literal angle-bracket form X.

### 4.6 W2 Codex per-wave review

- W2 commit 후 즉시 Codex per-wave review 의무.
- Codex live verify: §4.2 3 file (2 new + 1 modify) + §4.3 8 pre-commit gate PASS + §4.4 N test PASS evidence.
- Codex verdict 예상 = `APPROVED_FOR_W3_ENTRY` or `NEEDS_REVISION_NARROW`.

## 5. W3 Implementation Atomic Wave — Carry-P021 integrated test

### 5.1 Pre-W3 Entry Sanity (Codex re-discuss)

**(W3.0.a) Codex re-discuss + W3 entry sanity**:
- W2 per-wave review `APPROVED_FOR_W3_ENTRY` 후만 W3 진입.

**(W3.0.b) git status hygiene**:
```bash
git diff --name-only
# Expected: 0 modified file (W2 commit 후 clean).
# Known untracked artifact = preserve (git add 대상 X).
```

### 5.2 W3 File Operations (1 file new, spec §6.2 정합)

**path-limited scope**: `backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py` (1 file, new).

**Test file structure** (7 Gate G1-G7, no live LLM + NO VLM + no regex semantic + no standalone token global ban + single STRICT_RESIDUES marker-wrapped):

```python
"""Carry-P021 — Scene Consistency Prompt Hygiene v1 integrated test.

7 Gate verify (closed-world exact phrase membership only):
- G1: Active v8 source-path proof (get_effective_source dict + sibling schema.json existence, separation per N-A6).
- G2: v8 file count 2 (system.md + schema.json).
- G3: STRICT_RESIDUES marker-wrapped 10 strict R-id absence in v8 system.md (single constant per Codex N-6).
- G4: ABSTRACT_PRESENCE_CLAUSES tuple presence in v8 system.md (R6 lead + R6 second + R1-R5 process clause, exact fixed-string only per Codex W3 guard).
- G5: Schema sha256 byte-identical canary v7 == v8.
- G6: version_registry 3 logical edits sync (Site 1/2/3) + STEP_MANIFEST schema_version=3 preserve + SCENE_CONSISTENCY_SCHEMA_VERSION=3 preserve (Area #4 boundary canary).
- G7: v7 historical canary (dir + 2 file existence + schema sha256 length 64 computability smoke per Codex W3 guard).

NO VLM + no live LLM + no regex semantic + no standalone token global ban.
"""

import hashlib
from pathlib import Path

from app.core.step_manifest import STEP_MANIFEST
from app.core.steps.scene_consistency_step import SCENE_CONSISTENCY_SCHEMA_VERSION
from app.core.version_registry import MODULE_VERSIONS, _MODULE_INFO
from app.modules.prompt_loader import get_effective_source


REPO_ROOT = Path(__file__).resolve().parents[3]
SC_V7_DIR = REPO_ROOT / "prompts" / "_base" / "scene_consistency" / "7.202605181210"


# <!-- HISTORICAL AUDIT TRAIL — BEGIN -->
# STRICT_RESIDUES single constant per Codex outline N-6 정합.
# 10 strict ids: R1-R6 (system.md line 13/14/18/22/58/61) + JS1/JS2a/JS2b/JS3 (system.md line 89-110 JSON example sub-anchors).
# Exact quoted wording = spec §2.1.1 marker block 안 인용; 본 test file = closed-world test constants reference only.
# Marker block 외부 (test name / docstring / 다른 변수) exact residue 재방출 0 (Codex N-A3 doctrine + post-Carry-D7d-1 fix-up 1 강화 정합).
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 strict: 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 -->


# ABSTRACT_PRESENCE_CLAUSES per spec §6.2 G4 + Codex V3 OQ-3 default pin Carry-A100 lineage 정합.
# Exact fixed-string clauses only, no semantic regex (Codex W3 guard 정합).
ABSTRACT_PRESENCE_CLAUSES = (
    # R6 abstraction Korean lead clause
    '8. **시각적 인구학 단서 반영**:',
    # R6 abstraction Korean second clause (Carry-A100 lineage default-coerce 강제 X)
    '명시되지 않은 인물에 default 인구학 표기를 강제하지 않는다',
    # R1-R5 abstraction Korean clause (process wording)
    '원문에 명시된 inactive/restful pose는 구체 자세',
)


def _v8_dir() -> Path:
    """v8 active dir resolution via get_effective_source source-path proof (separation per N-A6)."""
    src = get_effective_source("scene_consistency", "system", db=None)
    file_cand = src["candidates"]["file"]
    assert file_cand is not None, "no file candidate for scene_consistency/system"
    fpath = Path(file_cand["path"]).resolve()
    return fpath.parent


def _sha256(path: Path) -> str:
    return hashlib.sha256(path.read_bytes()).hexdigest()


def test_gate_1_active_v8_source_path_proof():
    """G1: Active v8 source-path proof via get_effective_source dict + sibling schema.json existence (separation per N-A6 + Codex amend 1 IMPORTANT 1 fix)."""
    src = get_effective_source("scene_consistency", "system", db=None)
    file_cand = src["candidates"]["file"]
    assert file_cand is not None
    # System prompt source-path proof
    assert str(file_cand["version"]).startswith("8."), file_cand["version"]
    assert "/scene_consistency/8." in str(file_cand["path"]), file_cand["path"]
    # Schema proof = system path sibling schema.json existence (separation)
    # get_effective_source('scene_consistency', 'schema') 사용 X (.md stem only, schema.md 찾음 — schema.json source-path proof X)
    # load_prompt / load_schema = content-load smoke only, source-path proof X
    # get_active_version = module-level active-version, schema stem source-path proof X
    system_path = Path(file_cand["path"])
    schema_path = system_path.parent / "schema.json"
    assert schema_path.is_file(), f"schema sibling existence FAIL: {schema_path}"
    assert "/scene_consistency/8." in str(schema_path), f"schema path FAIL: {schema_path}"


def test_gate_2_v8_file_count_2():
    """G2: v8 dir file count = 2 (system.md + schema.json)."""
    v8_dir = _v8_dir()
    files = sorted(p.name for p in v8_dir.iterdir() if p.is_file())
    assert files == ["schema.json", "system.md"], f"unexpected v8 file list: {files}"


def test_gate_3_strict_residues_absent_in_v8_system_md():
    """G3: STRICT_RESIDUES marker-wrapped 10 strict R-id full-phrase membership hit 0 in v8 system.md."""
    v8_system = _v8_dir() / "system.md"
    text = v8_system.read_text(encoding="utf-8")
    for residue in STRICT_RESIDUES:
        assert residue not in text, f"strict residue still present in v8 system.md: {residue!r}"


def test_gate_4_abstract_wording_presence_in_v8_system_md():
    """G4: ABSTRACT_PRESENCE_CLAUSES tuple presence in v8 system.md (exact fixed-string, no semantic regex per Codex W3 guard)."""
    v8_system = _v8_dir() / "system.md"
    text = v8_system.read_text(encoding="utf-8")
    for clause in ABSTRACT_PRESENCE_CLAUSES:
        assert clause in text, f"required abstract wording missing in v8 system.md: {clause!r}"


def test_gate_5_schema_sha256_byte_identical_from_v7():
    """G5: schema.json sha256 byte-identical canary v7 == v8 (Carry-A099 G3 + Carry-A100 G5 lineage)."""
    v7_schema = SC_V7_DIR / "schema.json"
    v8_schema = _v8_dir() / "schema.json"
    assert _sha256(v7_schema) == _sha256(v8_schema)


def test_gate_6_version_registry_3_logical_edits_and_step_manifest_preserve():
    """G6: version_registry 3 logical edits sync + STEP_MANIFEST schema_version=3 preserve + SCENE_CONSISTENCY_SCHEMA_VERSION=3 preserve (Codex V3 OQ-5 + Area #4 boundary canary 정합)."""
    # 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)
    assert SCENE_CONSISTENCY_SCHEMA_VERSION == 3


def test_gate_7_v7_historical_canary():
    """G7: v7 historical canary — dir + 2 file existence + schema sha256 length 64 computability smoke (Codex amend 1 MINOR 2 fix + W3 guard 정합 — no pinned hash literal in test, optional expected hash pin at execution time)."""
    assert SC_V7_DIR.is_dir(), f"v7 historical dir missing: {SC_V7_DIR}"
    v7_system = SC_V7_DIR / "system.md"
    v7_schema = SC_V7_DIR / "schema.json"
    assert v7_system.is_file(), f"v7 historical system.md missing"
    assert v7_schema.is_file(), f"v7 historical schema.json missing"
    # sha256 length 64 computability smoke (no pinned hash literal in test source — W3 execution 시 optional expected hash pin 추가 가능)
    v7_schema_sha256 = _sha256(v7_schema)
    assert len(v7_schema_sha256) == 64
```

### 5.3 W3 Pre-Commit Verify Gates (3 check, spec §6.4 정합)

**(a) Test file existence** (spec §6.4 (a)):
```bash
test -f backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py && echo "OK test file exists" || { echo "FAIL: test file missing"; exit 1; }
```

**(b) STRICT_RESIDUES marker-wrapped** (spec §6.4 (b) + Carry-A100 N-2 marker-aware doctrine 정합):
```bash
TEST_FILE="backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py"
b_hits=$(grep -cF "HISTORICAL AUDIT TRAIL — BEGIN" "$TEST_FILE")
e_hits=$(grep -cF "HISTORICAL AUDIT TRAIL — END" "$TEST_FILE")
[ "$b_hits" -ge 1 ] && [ "$e_hits" -ge 1 ] && echo "OK STRICT_RESIDUES marker-wrapped (BEGIN=$b_hits END=$e_hits)" || { echo "FAIL: marker block missing"; exit 1; }
```

**(c) Targeted pytest 7 Gate ALL PASS** (spec §6.4 (c)):
```bash
backend/.venv/bin/pytest backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py -v --tb=short
# Expected: 7 tests, 7 PASS, 0 FAIL.
```

### 5.4 W3 Targeted Pytest + Full Pytest Canary

**W3 primary** (1 file, 7 Gate):
```bash
backend/.venv/bin/pytest backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py -v --tb=short
# Expected: 7 PASS.
```

**W3 regression** (W2 bundle + W3 신규):
```bash
cd backend
.venv/bin/pytest \
  tests/test_prompt_versions.py \
  tests/test_step_manifest_v3.py \
  tests/test_manifest_fields.py \
  tests/test_step_catalog.py \
  tests/test_sync_v3.py \
  tests/unit/test_g3_2_manifest_dag.py \
  tests/unit/test_scene_consistency_schema_v7.py \
  tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py \
  -v --tb=short
cd ..
# Expected: ALL PASS.
```

**W3 optional full canary** (Carry-P021 outline §2.7 optional default — full pytest, W4 closure 전 권장):
```bash
cd backend && .venv/bin/pytest tests -q && cd ..
# Expected: ALL PASS (20+ unrelated consumer category 4 impact 0 verify).
```

### 5.5 W3 Path-Limited git add + Commit

```bash
git add backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py
git diff --cached --name-only
# Expected: 1 file staged.
git status --short | head -10
# Expected: known untracked artifact preserve; W3 target 외 modified/staged 0.
```

**Commit message format** (spec §6.1 정합):
```
W3(carry-p021-scene-consistency-prompt-hygiene-v1): integrated test atomic — 7 gate verify (1 file new)

- backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py (file-level new, 1 file)
- G1: active v8 source-path proof via get_effective_source dict + sibling schema.json existence (separation per N-A6; load_prompt / load_schema / get_effective_source on schema stem 사용 X — Codex amend 1 IMPORTANT 1 fix 정합)
- G2: v8 file count 2 (system.md + schema.json)
- G3: STRICT_RESIDUES marker-wrapped 10 strict R-id (R1-R6 + JS1/JS2a/JS2b/JS3) full-phrase residue absence in v8 system.md (single constant per Codex N-6)
- G4: ABSTRACT_PRESENCE_CLAUSES tuple (R6 lead + R6 second + R1-R5 process clause) presence in v8 system.md (exact fixed-string only per Codex W3 guard, no semantic regex)
- G5: schema.json sha256 byte-identical canary v7 == v8 (Carry-A099 G3 + Carry-A100 G5 lineage)
- G6: version_registry 3 logical edits sync (Site 1 MODULE_VERSIONS == 2.6.0 + Site 2 prompt_dependency == scene_consistency/v8 + Site 3 updated_at == 2026-05-20) + STEP_MANIFEST schema_version=3 preserve + SCENE_CONSISTENCY_SCHEMA_VERSION=3 preserve (Area #4 boundary canary)
- G7: v7 historical canary (dir + 2 file existence + schema sha256 length 64 computability smoke per Codex amend 1 MINOR 2 fix + W3 guard — no pinned hash literal)

Pre-commit verify (Codex spec §6.4 3 gate): test file existence + STRICT_RESIDUES marker-wrapped (HISTORICAL AUDIT TRAIL BEGIN/END) + targeted pytest 7 Gate ALL PASS.

Targeted pytest (spec §6.4 (c) + W3 regression): `backend/.venv/bin/pytest backend/tests/integration/test_carry_p021_scene_consistency_prompt_abstraction.py -v --tb=short` — 7 tests, 7 PASS, 0 FAIL + W2 bundle regression ALL PASS + optional full pytest canary.

W1 commit reference: {W1_HASH} (1 file modify, test_prompt_versions.py historical cleanup).
W2 commit reference: {W2_HASH} (2 file new + 1 file modify 3 logical edits, v8 producer prompt-pack + version_registry sync).

NO VLM. no live LLM. closed-world exact phrase membership only. no semantic regex. standalone token global ban X.

Codex APPROVED_FOR_W3_ENTRY (W3 entry sanity round) + W2 per-wave APPROVED_FOR_W3_ENTRY + plan iter 1 APPROVED_FOR_EXECUTION.
```

**Note** (Codex G-6 정합): commit body 안 `{W1_HASH}` / `{W2_HASH}` = controller-substitute target (underscore form). 본 plan body 안 literal angle-bracket form X.

### 5.6 W3 Codex per-wave review

- W3 commit 후 즉시 Codex per-wave review 의무.
- Codex live verify: §5.2 1 file new + §5.3 3 pre-commit gate PASS + §5.4 7 Gate + regression bundle PASS evidence.
- Codex verdict 예상 = `APPROVED_FOR_W4_ENTRY` or `NEEDS_REVISION_NARROW`.

## 6. W4 Implementation Atomic Wave — closure docs

### 6.1 Pre-W4 Entry Sanity (Codex re-discuss + W3 dir name resolution)

**(W4.0.a) Codex re-discuss + W4 entry sanity**:
- W3 per-wave review `APPROVED_FOR_W4_ENTRY` 후만 W4 진입.

**(W4.0.b) W2 dir name resolution + W2 commit hash resolution** (Codex G-3 정합 — placeholder target 3-way 분리):
```bash
# Runtime W2 dir name resolve (closure-doc substitute target)
W2_DIR_NAME=$(ls -1 prompts/_base/scene_consistency/ | grep -E "^8\\." | sort | tail -n 1)
[ -n "$W2_DIR_NAME" ] || { echo "FAIL: W2 v8 dir missing"; exit 1; }
echo "W4 substitution target W2_DIR_NAME = $W2_DIR_NAME"

# Optional: W2 commit hash resolve (commit body cross-reference target, W4 commit body 안 self-hash 0 — Codex G-6)
W2_COMMIT_HASH=$(git log --format=%H -1 --grep "W2(carry-p021-scene-consistency-prompt-hygiene-v1)" 2>/dev/null || echo "")
[ -n "$W2_COMMIT_HASH" ] && echo "W2_COMMIT_HASH = $W2_COMMIT_HASH" || echo "WARN: W2 commit hash unresolved (acceptable if W4 separate)"

# 3-way placeholder targets:
# (a) runtime NEW_DIR = $NEW_DIR (W2.0.b) — shell var only, prose body 안 X
# (b) closure-doc substitute target = $W2_DIR_NAME (= 8.UTC_TIMESTAMP_actual) — 본 plan body underscore form "8.W2_COMMIT_UTC" 의 substitute
# (c) W4 commit body cross-reference = $W2_COMMIT_HASH (placeholder "{W2_HASH}" 의 substitute)
```

**(W4.0.c) git status hygiene** (Codex G-5 + Carry-A100 W4 narrow doctrine 정합):
```bash
git diff --name-only
# Expected: 0 modified file (W3 commit 후 clean).
# Known untracked artifact = preserve (git add 대상 X).
```

### 6.2 W4 File Operations (5 repo-local docs + external memory, spec §7.2 + Codex G-5 정합)

**path-limited git add scope (5 file)**:

#### 6.2.1 (a) 본 spec frontmatter + §12 in-place REPLACE (Codex W4 guard 정합)

`docs/superpowers/specs/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 + Codex W4 guard "Spec §12 must be in-place REPLACE, not append" 정합):
  - §12.1 Status + Closure Anchor — `Status: closed (2026-05-20+)`. Atomic commits 명시 (W1 1 file modify + W2 2 file new + 1 file modify 3 logical edits + W3 1 file new + W4 5 file path-limited). Parent baseline `0f24492`. Wave commits + final pushed range/count = external memory only after push (Codex G-6 정합).
  - §12.2 Wave Commit Table — 4 row (W1/W2/W3/W4). `W1_COMMIT` / `W2_COMMIT` / `W3_COMMIT` placeholder = W4 commit 시점 staged content 안 actual hash로 replace (W4 file ops 단계 안 substitute, W4 commit 자체에 embed). W4 row 안 W4 exact hash 는 W4 commit 시점 written X (W4 hash 는 W4 commit 전 unknowable + W4 commit body 자체에 W4 hash embed X 의무 per Codex G-6); W4 exact hash 는 W4 commit 후 git log / range review 안에서만 recorded + external memory only. 본 §12.2 W4 row staged content 안 design-time `W4-COMMIT` slug 등 placeholder form 자체 잔존 X 의무 (typographic hyphen variant 명기 — 본 plan body 안 doctrine description 만 hyphen 사용, actual gate scan은 underscore form per §6.5.2 (c-3)) — W4 cell wording = `recorded by git log/range review after W4 + external memory only` 등 narrative form (per Codex amend 2 N-4 fix + amend 1 IMPORTANT 2 fix + G-6 정합).
  - §12.3 Gate Result — G1 ~ G7 모두 `PASS` (W3 pytest 결과 7 PASS evidence).
  - §12.4 Closure Verdict — Codex iter rounds 본 carry cumulative recording (spec quality 5 round + plan-entry sanity 1 round + plan quality iter 1 + W1/W2/W3/W4 per-wave + W1-W4 range review).
  - §12.5 함정 신규 — base = §11.3 N-A1~N-A7 + N-A spec-1~5 + 본 W1-W4 execution 안 신규 발견 함정 (W4 closure 시점 enumeration).
  - §12.6 Carry Follow-up Post Carry-P021 — §11.4 정합 (Future Carry-P021-structured + Future Carry-A099/A100-structured).

#### 6.2.2 (b) 본 plan frontmatter + closure marker narrow append

`docs/superpowers/plans/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-implementation.md`:
- frontmatter `status: draft` → `status: closed (Carry-P021 v1 W1-W4 closed at W4 closure-docs commit, 2026-05-20+; Codex spec quality 5 round + plan-entry sanity APPROVED_FOR_PLAN_V1_DRAFT_FRESH_WITH_NARROW_GUARDS + plan quality iter 1 narrow + W1/W2/W3 per-wave APPROVED + W4 closure-docs atomic; final pushed range/count = external memory only after push, post-W4 range review verdict 별도 recording per Codex amend 1 IMPORTANT 2 fix + G-6)`.
- 본 plan §7 closure marker narrow append (외부 closure narrative referencing external memory only, no self-hash literal per Codex G-6).

#### 6.2.3 (c) Roadmap §5.7 narrow append (Carry-A099/A100 lineage most-current carry-follow-up bullet only per Carry-A100 N-5)

`docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md` §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.W2_COMMIT_UTC).
```
Note: prose body 안 `8.W2_COMMIT_UTC` underscore form ONLY (Codex G-2 정합); W4 placeholder substitution gate 안 actual W2 dir name으로 substitute (Codex G-3 정합).

#### 6.2.4 (d) Audit 02 narrow update + §16 신설

`docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md`:
- §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 정합):
  - Closure title + status closed + atomic commits enumeration (W1/W2/W3/W4 path-limited 5 file external memory only) + scope = **prompt-side hygiene only** (Codex W4 guard 정합 — Area #4 code-side work 가 P021 part 아님 명시; full scene_consistency structured migration claim 금지).
  - Allowed wording: `Carry-P021 resolved by W1-W4 — scene_consistency v7 system.md hard-prime examples abstracted (v8 prompt-pack 8.W2_COMMIT_UTC). content-only abstraction, schema byte-identical, Area #4 producer code 변경 0, Future Carry-P021-structured deferred`.
  - Forbidden wording (spec §10.2): `scene_consistency structured SOT complete` / `element_id opaque UUID migration complete` / `Area #4 (Prompt Hygiene v2) closure complete` / `all scene_consistency prompt hygiene risk fixed` / `field-shape migration complete` / `JSON example structured schema generation complete`.

#### 6.2.5 (e) Area #4 spec §1.5/§2.3/§3.2/§7.1/§10.2 narrow update

`docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md`:
- §1.5 carry table row P021 Disposition column narrow update (`Disposition: resolved by Carry-P021 W1-W4 — prompt-side hygiene only (content-only abstraction); code-side classifier closure preserve`).
- §2.3 Q3 P021 scope wording narrow update (`Carry-P021 (prompt hygiene narrow) resolved at 2026-05-20+; Area #4 code-side classifier preserve`).
- §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 per N-A7 정합.
- §10.2 Non-claim P021 wording narrow update.

#### 6.2.6 (f) External memory (non-git, git add 대상 X, Codex G-5 정합)

- MEMORY.md update — Carry-P021 v1 closure entry 추가 + 카테고리 cross-reference + carry priority post 정합.
- session memo (`memory/session_20260520_carry_p021_v1_closure.md`) 신설 — Codex iter trace cumulative + atomic commits + 함정 신규 + carry priority post (Future Carry-P021-structured + Future Carry-A099/A100-structured).
- next session entry resolve `memory/next_session_carry_p021_plan_v1_drafting.md` (해소됨 marker).
- **Final pushed range/count = external memory only** (Codex G-6 정합; W4 commit body 안 self-hash + final pushed range/count 0).

**W0.2 inventory memo + Q1-Q7 outline = untracked reference artifacts** unless W4 closure 시 path-limited git add only — 본 carry default = untracked preserve (Carry-A100 N-6 lineage 정합).

### 6.3 W4 Pre-Commit Placeholder Substitution Gate (Codex G-4 marker-aware staged-content lesson + Carry-A099 §5.2 pattern + Carry-A100 plan §6.4(d) Part 2 marker-aware narrow amend in-flight lesson 정합)

**Rule**: W4 closure commit 직전, 5 repo-local closure docs 안 live `8.W2_COMMIT_UTC` placeholders 모두 actual W2 dir name (`$W2_DIR_NAME`, W4.0.b resolve) 으로 substitute. HISTORICAL AUDIT TRAIL / TEMPLATE ONLY marker block 안 placeholder = substitute X (marker 보존).

**Substitution mechanism** (Carry-A099 §5.2 + Carry-A100 marker-aware doctrine 정합):
```bash
W2_DIR_NAME=$(ls -1 prompts/_base/scene_consistency/ | grep -E "^8\\." | sort | tail -n 1)
[ -n "$W2_DIR_NAME" ] || { echo "FAIL: W2 v8 dir missing"; exit 1; }
echo "W4 substitution W2_DIR_NAME = $W2_DIR_NAME"

CLOSURE_DOCS=(
  docs/superpowers/specs/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md
  docs/superpowers/plans/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-implementation.md
  docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md
  docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md
  docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md
)

for f in "${CLOSURE_DOCS[@]}"; do
  [ -f "$f" ] || { echo "FAIL: closure doc missing: $f"; exit 1; }
  TMP="${f}.tmp.carry-p021"
  awk -v repl="$W2_DIR_NAME" '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; print; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; print; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; print; next}
    /end TEMPLATE ONLY/{flag=0; print; next}
    {
      if (!flag) {
        gsub(/8\.W2_COMMIT_UTC/, repl)
      }
      print
    }
  ' "$f" > "$TMP"
  mv "$TMP" "$f"
done
echo "OK W4 placeholder substitution applied (marker block preserved)"
```

**Verify gate (working-tree authoritative, pre-stage)** — Codex amend 1 IMPORTANT 3 fix + G-4 marker-aware doctrine 정합:

본 §6.3 gate = working-tree level pass/fail (substitution 직후, §6.4 working-tree pre-commit verify 이전 + §6.5 path-limited git add 이전). Staged-content re-verify gate (substitution target staged + new literal angle-bracket delta) = §6.5 inline 의무 실행 (post-stage authoritative per Codex amend 1 IMPORTANT 3+4 fix).

```bash
# (1) Authoritative gate (working-tree, pre-stage): marker-block-stripped working-tree content 안 substitution target hit 0
TOTAL_AUTH=0
for f in "${CLOSURE_DOCS[@]}"; do
  body=$(awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ' "$f")
  hits=$(echo "$body" | grep -cF '8.202605191744' 2>/dev/null; true); hits=${hits:-0}
  TOTAL_AUTH=$((TOTAL_AUTH + hits))
  [ "$hits" -eq 0 ] || echo "FAIL authoritative gate (working-tree): $f outside-marker literal hits=$hits"
done
[ "$TOTAL_AUTH" -eq 0 ] && echo "OK W4 substitution target gate (working-tree marker-stripped hit 0)" || { echo "FAIL authoritative (working-tree): total $TOTAL_AUTH hits"; exit 1; }

# (2) Diagnostic gate (informational only): raw working-tree grep
echo "--- Diagnostic: raw working-tree grep (informational only) ---"
grep -nF '8.202605191744' "${CLOSURE_DOCS[@]}" | head -20 || echo "No raw working-tree hits"
echo "--- end diagnostic ---"
```

**Note** (Codex amend 1 IMPORTANT 3 fix + G-4 정합): 본 §6.3 = working-tree authoritative pass/fail gate (pre-stage). Staged-content re-verify (substitution target staged + new literal angle-bracket delta pass/fail) = §6.5 inline post-stage gate 의무 실행 (sub-gates c-1 + c-2 + d). Raw added-line grep = diagnostic only (not pass/fail per Carry-A100 plan §6.4(d) Part 2 marker-aware narrow amend in-flight lesson 정합).

### 6.4 W4 Pre-Commit Verify Gates (4 check, spec §7.5 정합 + Codex amend 1 IMPORTANT 3+4 + G-5 path-limited 정합)

본 §6.4 = working-tree level pre-commit verify gates (status closed grep + audit §16 grep) 만. **Staged-content split gates** (substitution target staged + new literal angle-bracket delta pass/fail) = §6.5 inline 의무 실행 (post-stage, `git add` 후 commit 이전, per Codex amend 1 IMPORTANT 3 fix flow narrative).


**(a) 본 spec status closed** (spec §7.5 (a) + Codex W4 guard "Spec §12 must be in-place REPLACE, not append" 정합):
```bash
grep -nF "status: closed" docs/superpowers/specs/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md
# Expected: 1 hit (frontmatter line).

# §12 in-place REPLACE verify — pending placeholder 0 hit
grep -cF "PENDING" docs/superpowers/specs/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md
# Expected: §12 안 PENDING placeholder 0 (in-place REPLACE complete; spec body 다른 곳 PENDING 단어 사용 0 expected).
```

**(b) Audit 02 §16 Closure section presence** (spec §7.5 (b)):
```bash
grep -nF "## 16. Carry-P021 Closure" docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md
# Expected: 1 hit (§16 heading).

# Audit 02 prompt-side hygiene only scope verify (Codex W4 guard 정합 — Area #4 code-side claim 0)
grep -cE "(Area #4 code-side|code-side classifier).*(complete|closed by Carry-P021)" docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md
# Expected: 0 (Audit 02 안 Area #4 code-side closure claim 0; prompt-side hygiene only).
```

**(c) Working-tree marker-stripped bracket inventory** (post-substitution, pre-stage informational + diagnostic, Codex amend 1 IMPORTANT 4 fix — split gates 안 working-tree level inventory only; pass/fail split gates = §6.5 inline post-stage 의무):
```bash
# Working-tree level inventory (marker-stripped) — legacy bracket preserve verify (Carry-A100 N-7 lineage)
TOTAL_WT_BRACKET=0
for f in "${CLOSURE_DOCS[@]}"; do
  body=$(awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ' "$f")
  hits=$(echo "$body" | grep -cE '[<][A-Za-z][A-Za-z_ -]+[>]' 2>/dev/null; true); hits=${hits:-0}
  TOTAL_WT_BRACKET=$((TOTAL_WT_BRACKET + hits))
  echo "INFO: $f working-tree marker-stripped bracket-form count=$hits (legacy preserve verify, pass/fail = §6.5 inline staged delta gate)"
done
echo "Working-tree marker-stripped bracket-form total: $TOTAL_WT_BRACKET (informational only; pass/fail = §6.5 inline staged delta gate per Codex amend 1 IMPORTANT 4 fix)"
```

**(d) Pre-stage hint — working-tree level new literal angle-bracket inventory vs HEAD** (informational only, Codex amend 1 IMPORTANT 4 fix — pre-stage hint, pass/fail equivalent = §6.5 inline staged delta gate):
```bash
# Pre-stage hint (informational): working-tree marker-stripped vs HEAD marker-stripped bracket count delta
for f in "${CLOSURE_DOCS[@]}"; do
  head_stripped=$(git show "HEAD:$f" 2>/dev/null | awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ')
  wt_stripped=$(awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ' "$f")
  head_b=$(echo "$head_stripped" | grep -cE '[<][A-Za-z][A-Za-z_ -]+[>]' 2>/dev/null; true); head_b=${head_b:-0}
  wt_b=$(echo "$wt_stripped" | grep -cE '[<][A-Za-z][A-Za-z_ -]+[>]' 2>/dev/null; true); wt_b=${wt_b:-0}
  delta=$((wt_b - head_b))
  echo "INFO: $f working-tree bracket delta vs HEAD: HEAD=$head_b WT=$wt_b delta=$delta (informational; staged pass/fail = §6.5 inline)"
done
```

**Manual gate boundary** (Codex amend 1 IMPORTANT 3+4 fix): 본 §6.4 (a)-(d) 4 check = working-tree level pre-commit verify gates (informational/inventory + status closed + audit §16 verify). **Staged-content split pass/fail gates = §6.5 inline 의무 실행** (`git add` 후 commit 이전, post-stage authoritative).

### 6.5 W4 Path-Limited git add + Inline Staged-Content Split Gates + Commit (Codex amend 1 IMPORTANT 3+4 fix — flow narrative: substitution → working-tree authoritative → working-tree pre-commit → path-limited stage → staged-content split pass/fail gates → commit)

#### 6.5.1 Path-Limited git add (5 docs, Codex G-5 정합)

**path-limited add scope** (5 file, 0 file out-of-scope):
```bash
git add \
  docs/superpowers/specs/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md \
  docs/superpowers/plans/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-implementation.md \
  docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md \
  docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md \
  docs/superpowers/specs/2026-05-18-area-4-scene-consistency-element-scope-v1-design.md
git diff --cached --name-only
# Expected: 5 file staged.
git status --short | head -10
# Expected: known untracked artifact preserve (W0.2 inventory + Q1-Q7 outline 등 = git add 대상 X per Carry-A100 N-6 lineage); W4 target 외 modified/staged 0.
```

#### 6.5.2 Inline Staged-Content Split Gates (post-stage authoritative pass/fail, Codex amend 1 IMPORTANT 3+4 fix + G-4 marker-aware doctrine 정합)

**(c-1) Substitution target staged re-verify** (post-stage, substitution target staged content 안 hit 0 pass/fail):
```bash
TOTAL_SUB=0
for f in "${CLOSURE_DOCS[@]}"; do
  staged_body=$(git show ":$f" 2>/dev/null | awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ')
  hits=$(echo "$staged_body" | grep -cF '8.202605191744' 2>/dev/null; true); hits=${hits:-0}
  TOTAL_SUB=$((TOTAL_SUB + hits))
  [ "$hits" -eq 0 ] || echo "FAIL substitution target staged re-verify: $f hits=$hits"
done
[ "$TOTAL_SUB" -eq 0 ] && echo "OK substitution target staged re-verify (post-stage hit 0)" || { echo "FAIL substitution target staged: total $TOTAL_SUB hits"; exit 1; }
```

**(c-2) New literal angle-bracket added-line gate** (PASS/FAIL — marker-stripped HEAD vs marker-stripped staged content, diff -u added-line scan per Codex amend 2 N-2 fix — count delta false-pass on remove+add swaps 회피):
```bash
TOTAL_NEW_BRACKET=0
TMPDIR_W4=$(mktemp -d)
trap "rm -rf $TMPDIR_W4" EXIT
for f in "${CLOSURE_DOCS[@]}"; do
  safe_name=$(echo "$f" | tr '/' '_')
  head_tmp="$TMPDIR_W4/${safe_name}.head"
  staged_tmp="$TMPDIR_W4/${safe_name}.staged"
  git show "HEAD:$f" 2>/dev/null | awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ' > "$head_tmp"
  git show ":$f" 2>/dev/null | awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ' > "$staged_tmp"
  # diff -u marker-stripped HEAD vs marker-stripped staged content; scan added lines (^+ excluding ^+++) for new outside-marker bracket form
  added_bracket=$(diff -u "$head_tmp" "$staged_tmp" 2>/dev/null | grep -E '^\+[^+]' | grep -cE '[<][A-Za-z][A-Za-z_ -]+[>]' 2>/dev/null; true); added_bracket=${added_bracket:-0}
  if [ "$added_bracket" -gt 0 ]; then
    echo "FAIL new outside-marker bracket-form added in $f: $added_bracket added line(s) with bracket form"
    TOTAL_NEW_BRACKET=$((TOTAL_NEW_BRACKET + added_bracket))
  else
    echo "OK $f no new outside-marker bracket-form added (legacy preserve + remove-only OK)"
  fi
done
rm -rf "$TMPDIR_W4"
[ "$TOTAL_NEW_BRACKET" -eq 0 ] && echo "OK new literal angle-bracket added-line gate (W4-introduced 0 outside-marker bracket forms via diff -u scan, remove+add swap-safe per Codex amend 2 N-2 fix)" || { echo "FAIL new literal angle-bracket: total $TOTAL_NEW_BRACKET added lines with bracket form"; exit 1; }
```

**Note** (Codex amend 1 IMPORTANT 4 + amend 2 N-2 fix 정합): pre-existing legacy angle-bracket literals (Carry-A100 N-7 lineage) 는 marker-stripped HEAD baseline에 포함됨; 본 (c-2) gate = W4 add 안 new outside-marker bracket form 도입 시만 fail. diff -u 기반 added-line scan = count delta 가 아닌 line-level added-set scan — remove+add swap 시 (legacy bracket A 제거 + new bracket B 추가) count delta = 0 false-pass 회피 (B added line이 grep에 match → FAIL).

<!-- HISTORICAL AUDIT TRAIL — BEGIN (W4 gate (c-3) executable spec + Note + commit body template references, self-reference marker per N-A spec-1 lineage doctrine — plan body literal `W4_COMMIT` slug self-match 회피) -->
**(c-3) `W4_COMMIT` slug staged-removal gate** (PASS/FAIL — W4 §12 in-place REPLACE 후 staged closure docs 안 `W4_COMMIT` slug 0 hit verify per Codex amend 3 N-6 fix; W4 commit body self-hash 금지 + W4 cell wording narrative form per amend 2 N-4 fix doctrine 연장):
```bash
TOTAL_W4_SLUG=0
for f in "${CLOSURE_DOCS[@]}"; do
  staged_body=$(git show ":$f" 2>/dev/null | awk '
    /HISTORICAL AUDIT TRAIL.*BEGIN/{flag=1; next}
    /HISTORICAL AUDIT TRAIL.*END/{flag=0; next}
    /TEMPLATE ONLY.*BEGIN/{flag=1; next}
    /end TEMPLATE ONLY/{flag=0; next}
    !flag
  ')
  hits=$(echo "$staged_body" | grep -cF 'W4_COMMIT' 2>/dev/null; true); hits=${hits:-0}
  TOTAL_W4_SLUG=$((TOTAL_W4_SLUG + hits))
  [ "$hits" -eq 0 ] || echo "FAIL W4_COMMIT slug staged-removal: $f hits=$hits"
done
[ "$TOTAL_W4_SLUG" -eq 0 ] && echo "OK W4_COMMIT slug staged-removal (post-in-place-REPLACE hit 0 per Codex amend 3 N-6 fix; W4 cell wording = narrative recorded-after-W4 form per amend 2 N-4)" || { echo "FAIL W4_COMMIT slug: total $TOTAL_W4_SLUG hits"; exit 1; }
```

**Note** (Codex amend 3 N-6 fix): spec §12.2 Wave Commit Table 안 pre-W4 template form `W4_COMMIT (pending)` placeholder slug 존재 — W4 in-place REPLACE 시 W1/W2/W3 placeholder는 actual hash로 substitute, W4 placeholder는 narrative form (`recorded by git log/range review after W4 + external memory only`) 으로 replace. 본 (c-3) gate = W4 staged content 안 `W4_COMMIT` slug 잔존 0 hit verify (final pushed range/count = external memory only doctrine 정합, W4 commit body self-hash 금지 guard 연장 per amend 1 IMPORTANT 2 + G-6).
<!-- HISTORICAL AUDIT TRAIL — END (W4 gate (c-3) executable spec) -->

**(d) Raw added-line grep — diagnostic only** (Codex G-4 정합, not pass/fail):
```bash
echo "--- Diagnostic: raw added-line grep for design-time placeholders (informational only) ---"
git diff --cached -U0 -- "${CLOSURE_DOCS[@]}" | grep -E '^\+.*(8\.W2_COMMIT_UTC|[<][A-Za-z][A-Za-z_ -]+[>])' | head -20 || echo "No raw added-line hits"
echo "--- end diagnostic ---"
```

#### 6.5.3 Commit (post-stage gates ALL PASS 후 의무)

**Commit message format** (spec §7.1 정합 + Codex G-6 정합 — W4 commit body 안 self-hash + final pushed range/count 0):
```
W4(carry-p021-scene-consistency-prompt-hygiene-v1): closure docs atomic — 5 file path-limited (spec frontmatter status closed + spec §12 in-place REPLACE + plan frontmatter + roadmap §5.7 + audit 02 §11.3/§13/§14/§15 + §16 신설 + Area #4 spec §1.5/§2.3/§3.2/§7.1/§10.2 narrow)

- 본 spec frontmatter status draft → closed + §12 in-place REPLACE (12.1 Status + 12.2 Wave Commit Table + 12.3 Gate Result + 12.4 Closure Verdict + 12.5 함정 신규 + 12.6 Carry Follow-up, Carry-A100 spec §10 in-place REPLACE doctrine 정합)
- 본 plan frontmatter status draft → closed + §7 closure marker narrow append (external closure narrative, no self-hash literal)
- roadmap §5.7 narrow append: Carry-P021 resolved by W1-W4 — scene_consistency v7 system.md hard-prime examples abstracted (Carry-A099/A100 lineage most-current carry-follow-up bullet only per N-5)
- audit 02 §11.3 line 317 + §13 line 382 + §14 line 437 + §15 line 475 Carry-P021 rows narrow update + §16 신설 Carry-P021 Closure section (prompt-side hygiene only per Codex W4 guard — Area #4 code-side claim 0, full scene_consistency structured migration claim 0)
- Area #4 v1 spec §1.5 carry table P021 Disposition narrow update + §2.3 Q3 P021 scope wording narrow update + §3.2 Out-of-scope rows P021 Disposition 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, N-A7 정합) + §10.2 Non-claim P021 wording narrow update

W1 commit reference: {W1_HASH} (1 file modify, test_prompt_versions.py historical cleanup).
W2 commit reference: {W2_HASH} (2 file new + 1 file modify 3 logical edits, v8 producer prompt-pack + version_registry sync).
W3 commit reference: {W3_HASH} (1 file new, integrated test 7 Gate G1-G7 ALL PASS).

W4 staged-content split gates PASS (per §6.5.2 inline post-stage gates): (c-1) substitution target staged re-verify (8.202605191744 marker-stripped staged hit 0) + (c-2) new literal angle-bracket added-line gate (marker-stripped HEAD vs staged diff -u added-line scan, remove+add swap-safe per amend 2 N-2) + (c-3) W4-COMMIT slug staged-removal (post-in-place-REPLACE hit 0 per amend 3 N-6; hyphen variant in description, underscore form in actual gate scan) + (d) raw added-line grep diagnostic only (Codex G-4).
W4 path-limited 5 repo-local docs only (external memory non-git per Codex G-5).

Final pushed range/count = external memory only (Codex G-6 정합; W4 commit body 안 self-hash + final pushed range/count 0).

Codex iter trace post W3: W3 per-wave APPROVED. W1-W4 range review + push = post-W4 event (range-review verdict + push result = external memory only after push per Codex amend 1 IMPORTANT 2 fix + G-6 정합; W4 commit body 자체에 future state preclaim X).

NO VLM. closed-world exact phrase membership only. standalone token global ban X. Future Carry-P021-structured deferred.
```

**Note** (Codex G-6 정합): `{W1_HASH}` / `{W2_HASH}` / `{W3_HASH}` = controller-substitute target (underscore form, after each commit exists). `{W4_HASH}` 또는 final pushed range = W4 commit body 안 absent (external memory only after push).

### 6.6 W1-W4 Range Review + Push Gate

**Codex range review (W1+W2+W3+W4)** 의무:
- live verify (Codex 직접 read 의무, 4채널 fact source 명시):
  - W1 commit: 1 file modify (test_prompt_versions.py helper rename + 3 site rename + 3 test rename).
  - W2 commit: 2 file new (v8 system.md + schema.json) + 1 file modify (version_registry.py 3 logical edits).
  - W3 commit: 1 file new (integrated test, 7 Gate G1-G7).
  - W4 commit: 5 file path-limited (spec + plan + roadmap + audit 02 + Area #4 spec).
  - Active source-path proof: `get_effective_source("scene_consistency", "system", db=None)` returns `candidates.file.path` containing `/scene_consistency/8.` prefix + `candidates.file.version` starts `8.` + sibling `schema.json` existence (separation per N-A6).
  - Targeted pytest re-run ALL PASS (W2 bundle + W3 7 Gate + optional full pytest canary).
  - W4 staged-content split gates evidence (§6.5.2 inline post-stage): (c-1) marker-stripped staged content `8.202605191744` fixed-string hit 0 + (c-2) marker-stripped HEAD vs staged diff -u added-line scan for new bracket form 0 (remove+add swap-safe per amend 2 N-2) + (c-3) marker-stripped staged content `W4-COMMIT` slug hit 0 (per amend 3 N-6 fix; hyphen typographic variant in plan body doctrine description, actual gate uses underscore form) + (d) raw added-line diagnostic only per Codex G-4.
- Codex verdict 예상 = `APPROVED_FOR_PUSH` (직접 push) or `NEEDS_REVISION_MINOR` (narrow fix-up).

**Push gate** (Codex `APPROVED_FOR_PUSH` 후 즉시, 사용자 ask 0):
```bash
git push origin main
# Final pushed range external memory only: pre-W1 HEAD..W4 HEAD (W4 commit body + 본 plan body 안 self-hash literal X — Codex G-6 정합).
```

- 사용자 ask 0 ([[feedback_push_no_user_ask]] 정합).
- /clear ONLY post-push session reset ([[feedback_session_reset_clear_not_exit]]).
- final pushed range/count = external memory only (MEMORY.md + session_20260520_carry_p021_v1_closure.md 신설).

## 7. Doctrine (spec §9 정합 inline reaffirm)

본 plan = spec §9 doctrine 정합 inline 재반복 X (spec 참조). 본 plan 안 doctrine 적용 정합 의무 site:

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

- **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 (STRICT_RESIDUES marker-wrapped single constant). 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 (field-shape migration) deferred.
- **Gate 4 No Silent Fallback**: Producer code `_detect_framing_conflicts` element_scope 직접 read + KeyError schema violation fail-fast preserve (Area #4 boundary). `call_structured` jsonschema validation 실패 시 retry 자동 trigger preserve.

### 7.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.

### 7.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 (exact fixed-string clauses, Codex W3 guard 정합 — no semantic regex).
- `import re` ban (W3 test).
- W2 pre-commit gate (d)/(e) = `grep -cF` (fixed string) only.

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

§7.1 Gate 2 + spec §8.5 정합. abstract category descriptor 안 자연 사용 보존.

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

spec §9.5 + spec §8.2/§8.3 정합 + 다음 적용 site:
- **본 plan body 안 literal angle-bracket placeholder forms 사용 X** (Codex G-2 정합): 본 plan §3-§6 모든 prose body 안 placeholder = underscore form (`8.W2_COMMIT_UTC` / `{W1_HASH}` / `{W2_HASH}` / `{W3_HASH}` / `{W4_HASH}`) only. literal angle-bracket form (예: angle-bracketed UTC design-time form) = formal `<!-- HISTORICAL AUDIT TRAIL — BEGIN/END -->` marker block 외부 사용 금지.
- **Runtime command block 안 `8.${UTC}` shell var form 사용 OK** (Codex G-2 정합): 본 plan §4.0.b + §4.2.1 + §4.5 etc. 안 shell command block `8.${UTC}` 형식은 runtime shell var, design-time placeholder 아님.
- **STRICT_RESIDUES tuple = W3 test file HISTORICAL AUDIT TRAIL marker block 안 only** (§5.2): test name / docstring / 다른 변수 안 quoted residue 재방출 0. spec §2.1.1 marker block 안 exact wording 인용 — 본 plan body 안 R-id reference only.
- **§6.4 (c)/(d) + §6.5.2 (c-2)/(d) grep regex literal angle-bracket form self-referential bug avoidance** (Codex amend 1 IMPORTANT 4 fix 흡수, Carry-A099/A100 lineage self-referential bug doctrine 정합): bare `[<]...[>]` form regex literal 사용 X — character class escape form (`[<][A-Za-z][A-Za-z_ -]+[>]`) 사용으로 본 plan body 안 grep regex literal이 staged-content scan 시 self-match 회피 (W4 staged delta gate가 본 plan 자체 grep regex literal을 false-positive 신규 outside-marker bracket form으로 detect 안 함).

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

spec §7.3 + §9.6 정합 + 다음 추가 doctrine 적용:
- **W4 commit body 안 self-hash + final pushed range/count 사용 X** (Codex G-6 정합): §6.5 commit message format 안 `W1_HASH` / `W2_HASH` / `W3_HASH` reference allowed (after each commit exists), `W4_HASH` 또는 final pushed range = external memory only.
- **본 plan body 안 spec/plan self-reference placeholder slug 사용 X**: explicit hash literal + external memory only suffix 의무.
- **Legacy 타 area closure verify chain 안 `본 commit` mentions**: 5-file path-limited scope 안 valid 시 retroactive `closure commit` semantic substitute (Area #7c/#7d 함정 1 정합).

### 7.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 의논 안).
- 본 plan drafting = (B) Codex spec quality 5 round APPROVED_FOR_PLAN + plan-entry sanity APPROVED_FOR_PLAN_V1_DRAFT_FRESH_WITH_NARROW_GUARDS 흡수 + (C) 본 session direct verify (10 source) + (A) Codex plan-entry sanity ask 송신.

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

spec §9.8 정합:
- `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.

### 7.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]]).
- **plan v1 draft 완료 후 Codex plan quality iter 1 review request 의무 + W1 execution 전 plan APPROVED_FOR_EXECUTION 의무** (Codex G-1 정합).

## 8. References + Carry Follow-up

### 8.1 References (spec §13 정합 inline)

- Spec final: `docs/superpowers/specs/2026-05-20-carry-p021-scene-consistency-prompt-hygiene-v1-design.md` (status closed post-W4, Codex spec quality 5 round APPROVED_FOR_PLAN + plan-entry sanity APPROVED_FOR_PLAN_V1_DRAFT_FRESH_WITH_NARROW_GUARDS).
- W0.2 inventory + Q1-Q7 outline (untracked): `docs/superpowers/specs/2026-05-19-carry-p021-q1-q7-outline.md`.
- scene_consistency v7 prompt-pack: `prompts/_base/scene_consistency/7.202605181210/` (2 file, abstraction target).
- v8 prompt-pack (W2 신규): `prompts/_base/scene_consistency/8.W2_COMMIT_UTC/` (W4 closure 시 actual W2 dir name으로 substitute).
- 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-18, :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 신규, 7 Gate G1-G7).
- 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)`.
- 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 + §16 (W4 신설)`.
- 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 plan donor: `docs/superpowers/plans/2026-05-19-carry-a099-vwr-system-md-director-notes-prose-redesign-v1-implementation.md` (prose abstraction lineage, atomic wave structure pattern donor).
- Carry-A100 v1 plan donor: `docs/superpowers/plans/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-implementation.md` (4-wave structure + marker-aware doctrine + TEMPLATE ONLY donor).
- Pre-Carry-P021 closure: [[session_20260519_carry_a100_v1_closure]] (origin/main HEAD `0f24492`).
- 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]] + [[session_20260520_carry_p021_spec_v1_drafting_closure]] + [[next_session_carry_p021_plan_v1_drafting]].

### 8.2 Carry Follow-up Post Carry-P021 (spec §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 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.

### 8.3 Closure Boundary (spec §10 정합)

- **Allowed claim** (Codex β-narrow + V3 OQ-3 verbatim, spec §10.1):
  > `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.`
- **Allowed closure-doc wording** (spec §10.3):
  - `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`
- **Forbidden claims** (Codex β-narrow + 4 narrow guard, spec §10.2):
  - `scene_consistency structured SOT complete`
  - `element_id opaque UUID migration complete`
  - `element_type enum expansion complete`
  - `Area #4 (Prompt Hygiene v2) closure complete`
  - `all scene_consistency prompt hygiene risk fixed`
  - `field-shape migration complete`
  - `JSON example structured schema generation complete`
  - **Area #4 code-side closure complete (P021 part)** (Codex W4 guard 정합 — Audit 02 §16 안 Area #4 code-side claim 0)
