---
title: Carry-A100 — VWR system.md t2i_context demonym redesign V8+ / V9 bump implementation plan (v1)
date: 2026-05-19+
status: closed (Carry-A100 v1 W1-W4 closed at W4 closure-docs commit, 2026-05-19+; Codex Q0-light + 1st-3rd narrow re-review 흡수 + 4th narrow re-review APPROVED_FOR_PLAN + plan quality iter 1 NEEDS_REVISION_MINOR 4 IMPORTANT + 2 MINOR 흡수 narrow amend 1 + plan quality iter 2 NEEDS_REVISION_NARROW N-1/N-2/N-3 흡수 narrow amend 2 + plan quality iter 3 APPROVED_FOR_EXECUTION_WITH_TEXT_FIXES 5 text fix inline 흡수 + W1/W2/W3 per-wave APPROVED + W4 closure-docs atomic + W1-W4 range review)
spec_ref: docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-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
prerequisites:
  - Spec v1 APPROVED_FOR_PLAN (Codex spec quality re-review + 3rd narrow re-review N-1/N-2/N-3 absorb + 4th narrow re-review verdict; status draft, closed only at W4 closure-docs commit).
  - Area #7a v1 closed (push `d0410eb`) — VWR producer SOT boundary preserve.
  - Area #7b v1 closed (push `e751e72`) — VWR downstream cascade boundary preserve.
  - Area #7c v1 closed (push `62aa2ef`) — t2i_review placeholder abstraction pattern + `Asian/Korean` downstream cleanup boundary (cross-cut X with A100).
  - 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`) — v8 prompt-pack anchor 직접 prerequisite; director_notes section line 57-84 preserve.
non_supersedes:
  - Carry-P021 (scene_consistency 7 enumeration broad, source unresolved).
  - Future Carry-A100-structured (`t2i_context: string` → `object` field-shape migration).
---

# Carry-A100 — VWR system.md t2i_context demonym redesign V8+ / V9 bump implementation plan (v1)

## 1. Purpose + Spec Reference

본 plan = Carry-A100 spec (status draft, Codex 4 round narrow re-review 흡수 후 `APPROVED_FOR_PLAN`; status closed only at W4 closure-docs commit) 의 W1 A099 test compat + W2 v9 producer + W3 A100 integrated test + W4 closure docs wave 실행 contract. spec §1-§11 fully 참조 (본 plan 안 spec 본문 재기술 0, ambiguity 제거 위한 inline command + Codex 명시 narrow guard 만 포함).

**Spec 참조 key index** (본 plan 작성 시 cross-reference, edit 0 의무):
- spec §1.2 In-scope = v9 prompt pack 2 file + A099 test compat narrow modification + W3 A100 integrated test + W4 closure docs.
- spec §1.3 Out-of-scope = 6 narrow guard + Carry-A099 boundary preserve + carrier shape preserve + STEP_MANIFEST schema_version=1 preserve + 8 direct reader 변경 0 + standalone token global ban X.
- spec §2 W0 evidence inventory (W0.1 inventory memo reference).
- spec §3 Sync Contract (6-row table, prompt-pack activation + STEP_MANIFEST verify only).
- spec §4.1 W1 (A099 test compat atomic).
- spec §4.2 W2 (v9 producer prompt-pack atomic + exact After text).
- spec §4.3 W3 (A100 integrated test atomic + 7 Gate).
- spec §4.4 W4 (closure docs atomic + in-place REPLACE §10).
- spec §5 Wave Plan Alternatives (Option β rejected/conditional fallback).
- spec §6 Test Contract (G1-G7 + test mechanism + marker-wrapped strict residue constants).
- spec §7 4-Gate Boundary Doctrine.
- spec §8 Strict Residue Catalog (R1-R5, marker-wrapped).
- spec §9 Allowed/Forbidden Claim.
- spec §10 Closure (in-place REPLACE at W4; no self-hash literal).
- spec §11 References + Codex iter verdict trace.

## 2. Plan Iter Trace

- **iter 0** (본 plan session, strategy 본 instance proposed + Codex MCP 의논 예정): Codex spec 4th narrow re-review verdict `APPROVED_FOR_PLAN` + plan drafting guidance (Option α 4-wave + marker-wrapped strict residue constants + exact After text + scene_detail-style 4-point sync claim 금지 + CONTINUE_THIS_SESSION + W1 execution 전 session health re-check 의무).
- **iter 1** (plan quality round, 본 plan 작성 후 Codex 의논): pending.

## 3. W1 Implementation Atomic Wave — Carry-A099 test compat (Option α primary)

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

**(W1.0.a) Codex re-discuss session health + W1 entry sanity** (Codex 4th narrow re-review verdict 정합 — "Re-check session health before W1 execution, especially if plan drafting plus review pushes the session beyond the 50% close-check threshold"):
- 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.1 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.1.2 정합)

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

#### 3.2.1 Edit operations

본 W1 의 4 narrow edit 항목 (Codex 3rd narrow re-review N-3 정합):

**(a) Unused import 제거 (Codex 3rd narrow re-review N-3 정합)**:
- Line 19: `from app.modules.prompt_loader import get_active_version, get_effective_source` 전체 삭제.
- Rationale: historical pin refactor 후 unused (lint/readability hygiene).

**(b) `_v8_dir()` helper historical pin (spec §4.1.2 (a)-1 정합)**:
- Line 22-23 직후 (VWR_V7_DIR 상수 다음) `VWR_V8_DIR` 상수 신설:
  ```python
  VWR_V8_DIR = REPO_ROOT / "prompts/_base/visual_world_rules/8.202605191102"
  ```
- Line 39-44 `_v8_dir()` 함수 본문 refactor:
  - Before: `get_effective_source("visual_world_rules", "system", db=None)` resolution + `Path(file_cand["path"]).resolve().parent` 흐름.
  - After: `return VWR_V8_DIR` literal historical pin only (active resolution dependency 폐기).

**(c) Module docstring + function docstring rewording (spec §4.1.2 (a)-2 정합)**:
- Line 9 module docstring 안 `"Gate 6 (G1): v8 active source-path proof via get_effective_source + get_active_version (module sanity) + schema-specific NEW_DIR/rules_schema.json existence (Codex plan amend 1 N-3 Option 2 정합)."` → `"Gate 6 (G1): historical v8 closure anchor proof via literal VWR_V8_DIR pin + schema-specific VWR_V8_DIR/rules_schema.json existence (Carry-A100 W1 historical pin refactor 정합)."` substitute.
- Line 94-95 + 96-99 function docstring 안 `"active v8 source-path proof"` (전체 phrase) → `"historical v8 closure anchor proof"` substitute (2 site).

**(d) `test_gate_6_v8_active_source_path_proof` function name rename + body refactor (spec §4.1.2 (a)-3 정합)**:
- Function name: `test_gate_6_v8_active_source_path_proof` → `test_gate_6_v8_historical_closure_anchor_proof`.
- Function body line 94-112 refactor:
  - Before: `get_effective_source` + `get_active_version` 호출 + 반환 path/version assertion.
  - After:
    - `assert _v8_dir() == VWR_V8_DIR` (historical pin proof).
    - `schema_file = VWR_V8_DIR / "rules_schema.json"` + `assert schema_file.is_file()` (schema stem-specific file existence).
    - `assert "/visual_world_rules/8.202605191102" in str(schema_file)` (path string contains historical literal).
  - `get_effective_source` + `get_active_version` import + 호출 모두 폐기.

### 3.3 W1 Pre-Commit Verify Gates (4 check, spec §4.1.3 정합)

**(a) Path-limited modification scope check** (Codex narrow amend 1 IMPORTANT 2 정합 — global `git status --short` ONLY gate = untracked artifact policy 충돌, path-limited form 사용):
```bash
# Path-limited diff verify (W1 target file only)
git diff --stat backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 1 file modified (~10-15 line insertion + ~5-10 line deletion).

# Path-limited status verify (target path only)
git status --short -- backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: " M backend/tests/integration/test_carry_a099_director_notes_abstraction.py".

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

**(b) Unused import 제거 verify (Codex 3rd narrow re-review N-3)**:
```bash
grep -c "from app.modules.prompt_loader import" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 0 (전체 제거).
grep -c "get_effective_source\|get_active_version" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 0 (호출 전체 제거).
```

**(c) Historical pin 적용 verify**:
```bash
grep -c "VWR_V8_DIR = REPO_ROOT" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 1 (constant 신설).
grep -c "8.202605191102" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 2+ (1 in VWR_V8_DIR const + 1+ in test_gate_6 assertion).
grep -c "active v8 source-path proof" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 0 (전체 substitute).
grep -c "historical v8 closure anchor proof" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 2+ (docstring 2 site).
grep -c "test_gate_6_v8_historical_closure_anchor_proof" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 1 (function rename).
grep -c "test_gate_6_v8_active_source_path_proof" backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Expected: 0 (function rename, before form 폐기).
```

**(d) Pytest A099 + Area #7a inherited + visual_context_helper direct consumer regression check** (Codex narrow amend 1 IMPORTANT 1 정합):
```bash
cd backend
.venv/bin/pytest \
  tests/integration/test_carry_a099_director_notes_abstraction.py \
  tests/test_visual_world_rules.py \
  tests/integration/test_area_7a_no_drift.py \
  tests/integration/test_area_7a_residue_gate.py \
  tests/services/test_visual_context_helper.py \
  -v --tb=short
cd ..
# Expected (live count verified):
# - test_carry_a099_director_notes_abstraction.py = 6 PASS (Gate 1-6 modified; Gate 6 = historical closure anchor proof).
# - test_visual_world_rules.py = 3 PASS (Area #7a W3a residue, A100 impact 0).
# - test_area_7a_no_drift.py = 8 PASS (Area #7a W3b canary, A100 impact 0).
# - test_area_7a_residue_gate.py = 7 PASS (Area #7a W3a residue gate, A100 impact 0).
# - test_visual_context_helper.py = 9 PASS (t2i_context direct consumer surface, A100 impact 0).
# - Total: 33 PASS, 0 FAIL.
```

**Manual gate boundary**: 본 (a)-(d) 4 check = manual pre-commit verification gates, repo pre-commit hooks 와 별개.

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

```bash
git add backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# Path-limited post-stage verify (Codex narrow amend 1 IMPORTANT 2)
git diff --cached --name-only
# Expected (exact match with expected path list):
# backend/tests/integration/test_carry_a099_director_notes_abstraction.py
# (1 file, W1 = test-only narrow modification, 0 out-of-scope.)
```

**Commit message format**:
```
W1(carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1): Carry-A099 test compat — historical v8 pin (1 file: test_carry_a099_director_notes_abstraction.py modified _v8_dir() helper + docstring rewording + unused import 제거 + test_gate_6 rename)

- unused `from app.modules.prompt_loader import get_active_version, get_effective_source` import 제거 (line 19, Codex 3rd narrow re-review N-3 정합)
- `VWR_V8_DIR = REPO_ROOT / "prompts/_base/visual_world_rules/8.202605191102"` literal historical pin constant 신설
- `_v8_dir()` helper (line 39-44): get_effective_source active resolution → literal historical pin only (active resolution dependency 폐기)
- Module docstring + function docstring (line 9, 94-99): "active v8 source-path proof" → "historical v8 closure anchor proof" substitute
- `test_gate_6_v8_active_source_path_proof` → `test_gate_6_v8_historical_closure_anchor_proof` function rename + body refactor (literal pin assertion + schema stem-specific file existence)

Pre-commit verify (Codex IMPORTANT 1 정합): 4 gate PASS — path-limited modification scope + unused import 제거 + historical pin 적용 + pytest 33 PASS (A099 6 + Area #7a inherited 18 [3+8+7] + visual_context_helper 9 direct consumer, A100 impact 0).

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 4th narrow re-review APPROVED_FOR_PLAN + plan iter APPROVED_FOR_EXECUTION.
```

### 3.5 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 33 test PASS evidence.
- Codex verdict 예상 = `APPROVED_FOR_W2_ENTRY` or `NEEDS_REVISION_NARROW`.

## 4. W2 Implementation Atomic Wave — v9 producer prompt-pack

### 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**:
```bash
UTC=$(date -u +%Y%m%d%H%M)
NEW_DIR_V9="prompts/_base/visual_world_rules/9.${UTC}"
export UTC NEW_DIR_V9  # subprocess (Python -c) 안 inherit 의무, Carry-A099 N-5 narrow doctrine 정합
echo "Carry-A100 W2 NEW_DIR_V9 = $NEW_DIR_V9"
# Expected: 9.202605XXXX 형식, 8.202605191102 보다 후행 (시간 단조 증가).
```

**중요**: `export UTC NEW_DIR_V9` = §4.3(f) Python subprocess 안 inherit 의무 ([[session_20260519_carry_a099_v1_closure]] N-5 doctrine 정합).

**(W2.0.c) git status hygiene** (Codex narrow amend 1 IMPORTANT 2 정합):
```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, spec §4.2.2-§4.2.4 정합)

#### 4.2.1 New v9 prompt pack dir (site 1-2)

```bash
mkdir -p "$NEW_DIR_V9"
# Site 1: system.md (copy from v8 first, then narrow modify line 102)
cp prompts/_base/visual_world_rules/8.202605191102/system.md "$NEW_DIR_V9/system.md"
# Site 2: rules_schema.json (copy from v8 first, then narrow modify line 40 description)
cp prompts/_base/visual_world_rules/8.202605191102/rules_schema.json "$NEW_DIR_V9/rules_schema.json"
```

#### 4.2.2 system.md line 102 narrow edit (spec §4.2.3 exact After text)

**Substitution scope**: line 102 only (line 98 / 100 / 101 / 103 / 104 / 106-110 / 112 / 114 byte-equal preserve from v8; line 57-84 director_notes section byte-equal preserve from v8 — Carry-A099 boundary canary).

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

본 W2 의 line 102 substitution = exact `before` substring → `after` substring (closed-world only, semantic regex X, fixed-string sed/awk OR Python `str.replace` OR Edit tool exact match):

`before` (current v8 line 102 full line — exact form 인용 = spec §2.2 HISTORICAL AUDIT TRAIL marker block 안에서만; 본 plan 안 reference only): residue R1 + R2 + R3 + R4 모두 한 line 안 포함. W2 execution 시 Edit tool exact match input string = spec §2.2 marker block 안 line 102 quote 그대로 사용.

`after` (spec §4.2.3 exact After text):
```
- 시나리오 또는 인물별 outlook/character evidence에 명시된 인구학 단서의 반영 원칙 (명시되지 않은 인물에 단일 region default 인구학 표기를 강제하지 않는다)
```

Substitution rationale (R1-R5 reference, marker-wrapped literal in spec §8 only):
- `인구학 단서` = abstract category descriptor (replaces R3 ethnicity-nationality conflation Korean phrase).
- `시나리오 또는 인물별 outlook/character evidence에 명시된 경우` = outlook/evidence-first scenario-agnostic policy (replaces R4 single-region 가정 Korean clause).
- `(명시되지 않은 인물에 단일 region default 인구학 표기를 강제하지 않는다)` = default-coerce 강제 X 명시 (replaces R2 default-coerce example form).
- 예시 form 완전 제거 (Codex Q0-light Q2 (a) verdict — R1 literal angle-bracket placeholder + R2 example form 모두 live prompt 안 X). Underscore-escape variant 도 live prompt 안 X.

#### 4.2.3 rules_schema.json:40 description narrow edit (spec §4.2.4 exact After text)

**Substitution scope**: line 40 only (다른 field shape/description + line 42 required list + line 43 additionalProperties false byte-equal preserve from v8).

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

`before` (current v8 line 40 full line — exact form 인용 = spec §2.3 HISTORICAL AUDIT TRAIL marker block 안에서만; 본 plan 안 reference only): residue R5 포함 single-line schema description. W2 execution 시 Edit tool exact match input string = spec §2.3 marker block 안 line 40 quote 그대로 사용.

`after` (spec §4.2.4 exact After text, Codex 권고 wording 정합):
```
"t2i_context": {"type": "string", "description": "T2I 프롬프트용 시각 스타일 요약 (영어 2~3문장, 인물별 시각적 인구학 단서가 명시된 경우의 반영 원칙 + 색감/조명/질감 톤 + 장르 무드. 구체적 지명/장소/건축양식 열거 금지)"}
```

#### 4.2.4 STEP_MANIFEST + prompt_loader source-path verify-only (site 3-4, no code edit)
- `backend/app/core/step_manifest.py:141` `visual_world_rules.schema_version=1` = no edit (Codex IMPORTANT 3 정합 — shape unchanged, description-only).
- `_version_sort_key` / `load_prompt` / `load_schema` source-path resolution 자동 — `9.${UTC}` prefix latest active 됨.

#### 4.2.5 Boundary preserve (No edit obligatory)
- `prompts/_base/visual_world_rules/8.202605191102/` (v8, Carry-A099 anchor, 변경 0).
- `prompts/_base/visual_world_rules/7.202605181540/` (v7, Area #7a anchor, 변경 0).
- 8 direct reader file (visual_context_helper / entity_steps / beat_shot_steps / detail_steps / outlook_steps / t2i_review / shot_staging + test fixtures, spec §2.4) = 변경 0.
- `backend/app/core/step_manifest.py` (verify-only).
- `backend/tests/integration/test_carry_a099_director_notes_abstraction.py` (W1 modified at commit, W2 변경 0).
- Area #7a / #7b / #7c / #7d / Carry-D7d-1 / Carry-A099 closure boundary preserve.

### 4.3 W2 Pre-Commit Verify Gates (7 check, spec §4.2.5 정합)

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

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

**(c) director_notes section preserve canary (spec G7, Carry-A099 boundary)**:
```bash
# v9 system.md line 57-84 director_notes section content byte-equal from v8
DIFF=$(diff <(sed -n '57,84p' prompts/_base/visual_world_rules/8.202605191102/system.md) <(sed -n '57,84p' "$NEW_DIR_V9/system.md"))
[ -z "$DIFF" ] && echo "OK director_notes section (line 57-84) byte-equal v8 → v9 (Carry-A099 boundary canary)" || { echo "FAIL: director_notes section drift v8 → v9 (Carry-A099 boundary 위반)"; echo "$DIFF"; exit 1; }
```

**(d) R1-R5 residue absence in v9 system.md + rules_schema.json (spec G3)**:

<!-- HISTORICAL AUDIT TRAIL — BEGIN (5-item strict residue catalog; literal phrases below are historical residue exact strings for grep test-constant use only, not live prompt content per Codex 2nd narrow re-review guard 3) -->

```bash
SYS="$NEW_DIR_V9/system.md"
SCH="$NEW_DIR_V9/rules_schema.json"

# R1-R4 in system.md
for R in \
  "<region-derived demonym>" \
  'All human characters are <region-derived demonym> unless stated otherwise.' \
  "인물의 기본 국적/인종" \
  "시나리오의 region 에서 도출된 demonym"; do
  hits=$(grep -cF -- "$R" "$SYS")
  [ "$hits" -eq 0 ] || { echo "FAIL R-id residue in system.md: $R (hits=$hits)"; exit 1; }
done
echo "OK R1-R4 residue absent in $SYS"

# R5 in rules_schema.json
R5="기본 국적/인종 + 색감/조명/질감 톤 + 장르 무드"
hits=$(grep -cF -- "$R5" "$SCH")
[ "$hits" -eq 0 ] || { echo "FAIL R5 residue in rules_schema.json: $R5 (hits=$hits)"; exit 1; }
echo "OK R5 residue absent in $SCH"
```

<!-- HISTORICAL AUDIT TRAIL — END -->

**(e) New abstract wording presence (spec G4)**:
```bash
SYS="$NEW_DIR_V9/system.md"
SCH="$NEW_DIR_V9/rules_schema.json"

# system.md line 102 new wording
SYS_NEW="시나리오 또는 인물별 outlook/character evidence에 명시된 인구학 단서의 반영 원칙"
SYS_HIT=$(grep -cF -- "$SYS_NEW" "$SYS")
[ "$SYS_HIT" -ge 1 ] && echo "OK system.md new wording hit ($SYS_HIT)" || { echo "FAIL: no new wording in system.md"; exit 1; }

# rules_schema.json:40 new description
SCH_NEW="인물별 시각적 인구학 단서가 명시된 경우의 반영 원칙"
SCH_HIT=$(grep -cF -- "$SCH_NEW" "$SCH")
[ "$SCH_HIT" -ge 1 ] && echo "OK rules_schema.json new description hit ($SCH_HIT)" || { echo "FAIL: no new description in rules_schema.json"; exit 1; }
```

**(f) Carrier shape preserve (spec G5, 3-point)**:
```bash
cd backend && .venv/bin/python -c "
import sys, json, os
sys.path.insert(0, '.')

repo_root = os.path.abspath(os.path.join(os.getcwd(), os.pardir))
new_dir = os.environ.get('NEW_DIR_V9', '')
schema_path = os.path.join(repo_root, new_dir, 'rules_schema.json') if new_dir else None
assert schema_path and os.path.isfile(schema_path), f'schema file missing: {schema_path}'

with open(schema_path, 'r', encoding='utf-8') as f:
    schema = json.load(f)

# Point 1: t2i_context.type == 'string'
t2i_ctx = schema['properties']['t2i_context']
assert t2i_ctx['type'] == 'string', f't2i_context.type drift: {t2i_ctx[\"type\"]}'
# Point 2: 't2i_context' in required
required = schema.get('required', [])
assert 't2i_context' in required, f't2i_context missing from required: {required}'
# Point 3: additionalProperties == false
assert schema.get('additionalProperties') == False, f'additionalProperties drift: {schema.get(\"additionalProperties\")}'
print(f'OK carrier shape preserve (3-point): type=string + required + additionalProperties=false')
" && cd ..
```

**(g) STEP_MANIFEST schema_version preserve + active source-path proof (spec G1+G6, Codex IMPORTANT 3 정합)**:
```bash
cd backend && .venv/bin/python -c "
import sys, os
sys.path.insert(0, '.')
from app.core.step_manifest import STEP_MANIFEST
from app.modules.prompt_loader import get_effective_source, get_active_version

# G6: STEP_MANIFEST preserve
assert STEP_MANIFEST['visual_world_rules']['schema_version'] == 1, (
    f'STEP_MANIFEST drift: {STEP_MANIFEST[\"visual_world_rules\"][\"schema_version\"]}'
)
print('OK STEP_MANIFEST schema_version=1 preserve')

# G1: active prompt v9 source-path proof
src = get_effective_source('visual_world_rules', 'system', db=None)
file_cand = src.get('candidates', {}).get('file')
assert file_cand is not None, 'no file candidate for visual_world_rules/system'
fpath = str(file_cand.get('path', ''))
fver = str(file_cand.get('version', ''))
assert fver.startswith('9.'), f'visual_world_rules/system version drift: {fver} (expected 9.* prefix)'
assert '/visual_world_rules/9.' in fpath, f'visual_world_rules/system path drift: {fpath}'
print(f'OK active prompt source-path: version={fver} path={fpath}')

# G1 (module-version sanity)
module_ver = get_active_version('visual_world_rules', 'rules_schema', db=None)
assert module_ver is not None and module_ver.startswith('9.'), (
    f'visual_world_rules module active-version drift: {module_ver} (expected 9.* prefix)'
)
print(f'OK module active-version sanity: {module_ver}')

# Schema-specific path proof (Carry-A099 N-5 doctrine 정합: repo_root join 의무)
repo_root = os.path.abspath(os.path.join(os.getcwd(), os.pardir))
new_dir = os.environ.get('NEW_DIR_V9', '')
schema_path = os.path.join(repo_root, new_dir, 'rules_schema.json') if new_dir else None
assert schema_path and os.path.isfile(schema_path), f'schema-specific existence proof FAIL: {schema_path}'
assert '/visual_world_rules/9.' in schema_path, f'schema-specific path proof FAIL: {schema_path}'
print(f'OK schema-specific path proof: {schema_path}')
" && cd ..
```

### 4.4 W2 Targeted Pytest (W1-modified A099 + Area #7a inherited + visual_context_helper direct consumer)

```bash
cd backend
.venv/bin/pytest \
  tests/integration/test_carry_a099_director_notes_abstraction.py \
  tests/test_visual_world_rules.py \
  tests/integration/test_area_7a_no_drift.py \
  tests/integration/test_area_7a_residue_gate.py \
  tests/services/test_visual_context_helper.py \
  -v --tb=short
cd ..
# Expected: ALL 33 PASS (A099 6 historical pin preserved + Area #7a inherited 18 [3+8+7] + visual_context_helper 9 direct consumer regression, A100 impact 0).
# NO VLM + no live LLM + closed-world exact membership only.
```

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

```bash
git add "$NEW_DIR_V9/system.md" "$NEW_DIR_V9/rules_schema.json"
# Path-limited post-stage verify (Codex narrow amend 1 IMPORTANT 2)
git diff --cached --name-only
# Expected (exact match with expected path list, 2 entries):
# prompts/_base/visual_world_rules/9.${UTC}/rules_schema.json
# prompts/_base/visual_world_rules/9.${UTC}/system.md
# (2 file, W2 = prompt-pack producer + schema-description-only, 0 out-of-scope.)
```

**Commit message format**:
```
W2(carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1): t2i_context demonym redesign — visual_world_rules v9 (2 file: system.md t2i_context section line 102 narrow + rules_schema.json:40 description-only narrow)

- visual_world_rules/9.${UTC}/system.md modified (line 102 t2i_context section narrow edit; literal angle-bracket placeholder + 예시 form 완전 제거 + Korean phrase abstract lift + outlook/evidence-first wording; director_notes section line 57-84 byte-equal preserve from v8 — Carry-A099 boundary canary)
- visual_world_rules/9.${UTC}/rules_schema.json modified (line 40 description-only narrow edit; Korean phrase abstract lift; carrier shape preserve = type:string + required + additionalProperties false)
- STEP_MANIFEST['visual_world_rules']['schema_version'] == 1 preserve (no edit, shape unchanged)
- system prompt source-path proof via get_effective_source + module active-version sanity via get_active_version + schema-specific path proof via NEW_DIR_V9/rules_schema.json existence (Carry-A099 N-3 정합, 모듈 active-version sanity check + 스키마 stem-specific file 존재성 분리)

Pre-commit verify (Codex IMPORTANT 3 정합): 7 gate PASS — UTC + 2 file count + director_notes section byte-equal canary (Carry-A099 boundary) + R1-R5 residue 0 + new abstract wording presence (system.md + schema) + carrier shape 3-point preserve + STEP_MANIFEST + active source-path proof.

Targeted pytest: A099 6 PASS (historical pin preserved) + Area #7a inherited 18 PASS [3+8+7] + visual_context_helper 9 PASS (direct consumer) — Total 33 PASS, 0 FAIL.

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

Codex APPROVED_FOR_W2_ENTRY + spec 4th narrow re-review APPROVED_FOR_PLAN + plan iter APPROVED_FOR_EXECUTION.
```

### 4.6 W2 Codex per-wave review
- W2 commit 후 즉시 Codex per-wave review 의무.
- Codex live verify: §4.2 2 file + §4.3 7 pre-commit gate PASS + §4.4 33 test PASS evidence.
- Codex verdict 예상 = `APPROVED_FOR_W3_ENTRY` or `NEEDS_REVISION_NARROW`.

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

### 5.1 Pre-W3 Entry Sanity (Codex re-discuss)
- W2 per-wave review APPROVED_FOR_W3_ENTRY 후만 W3 진입.

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

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

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

```python
"""Carry-A100 — VWR system.md t2i_context demonym + rules_schema.json:40 description abstraction integrated test.

7 Gate verify (closed-world exact phrase membership only):
- Gate 1 (G1): v9 active source-path proof via get_effective_source + get_active_version + schema-specific path existence.
- Gate 2 (G2): v9 dir file count == 2 (system.md + rules_schema.json).
- Gate 3 (G3): R1-R5 strict residue absence (closed-world full-phrase membership, marker-wrapped test constants).
- Gate 4 (G4): new abstract wording presence (system.md line 102 + rules_schema.json:40 description, fixed-string).
- Gate 5 (G5): carrier shape preserve (3-point: t2i_context.type == 'string' + 't2i_context' in required + additionalProperties == False).
- Gate 6 (G6): STEP_MANIFEST['visual_world_rules']['schema_version'] == 1 preserve.
- Gate 7 (G7): director_notes section preserve canary (v9 line 57-84 ≡ v8 line 57-84 byte-equal substring, Carry-A099 boundary).

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

import json
from pathlib import Path

from app.core.step_manifest import STEP_MANIFEST
from app.modules.prompt_loader import get_active_version, get_effective_source


REPO_ROOT = Path(__file__).resolve().parents[3]
VWR_V8_DIR = REPO_ROOT / "prompts/_base/visual_world_rules/8.202605191102"


# HISTORICAL AUDIT TRAIL — BEGIN (5-item strict residue catalog; literal phrases below are
# historical residue exact strings for closed-world test-constant use only, not live prompt
# content per Codex 2nd narrow re-review guard 3).
R1_R5_STRICT = [
    "<region-derived demonym>",
    'All human characters are <region-derived demonym> unless stated otherwise.',
    "인물의 기본 국적/인종",
    "시나리오의 region 에서 도출된 demonym",
    "기본 국적/인종 + 색감/조명/질감 톤 + 장르 무드",
]
# HISTORICAL AUDIT TRAIL — END

NEW_WORDING_SYSTEM = "시나리오 또는 인물별 outlook/character evidence에 명시된 인구학 단서의 반영 원칙"
NEW_WORDING_SCHEMA = "인물별 시각적 인구학 단서가 명시된 경우의 반영 원칙"


def _v9_dir() -> Path:
    src = get_effective_source("visual_world_rules", "system", db=None)
    file_cand = src.get("candidates", {}).get("file")
    assert file_cand is not None, "no file candidate for visual_world_rules/system"
    fpath = Path(file_cand["path"]).resolve()
    return fpath.parent


def test_gate_1_v9_active_source_path_proof():
    """G1: v9 active prompt-pack source-path proof via get_effective_source + get_active_version."""
    src = get_effective_source("visual_world_rules", "system", db=None)
    file_cand = src.get("candidates", {}).get("file")
    assert file_cand is not None
    assert str(file_cand["version"]).startswith("9."), file_cand["version"]
    assert "/visual_world_rules/9." in str(file_cand["path"]), file_cand["path"]

    module_ver = get_active_version("visual_world_rules", "rules_schema", db=None)
    assert module_ver and module_ver.startswith("9."), module_ver

    v9 = _v9_dir()
    schema_file = v9 / "rules_schema.json"
    assert schema_file.is_file(), f"schema-specific file existence FAIL: {schema_file}"
    assert "/visual_world_rules/9." in str(schema_file), f"schema-specific path FAIL: {schema_file}"


def test_gate_2_v9_file_count():
    """G2: v9 dir 안 file count == 2."""
    v9 = _v9_dir()
    files = sorted([p.name for p in v9.iterdir() if p.is_file()])
    assert files == ["rules_schema.json", "system.md"], files


def test_gate_3_r1_r5_residue_absent_in_v9():
    """G3: 5 strict R-id full-phrase membership hit 0 in v9 system.md (R1-R4) + rules_schema.json (R5)."""
    v9 = _v9_dir()
    sys_md = (v9 / "system.md").read_text(encoding="utf-8")
    sch_json = (v9 / "rules_schema.json").read_text(encoding="utf-8")
    for idx, residue in enumerate(R1_R5_STRICT[:4], start=1):
        assert residue not in sys_md, f"R{idx} residue present in v9 system.md"
    assert R1_R5_STRICT[4] not in sch_json, "R5 residue present in v9 rules_schema.json"


def test_gate_4_new_abstract_wording_presence():
    """G4: new abstract wording present in v9 system.md + rules_schema.json description."""
    v9 = _v9_dir()
    sys_md = (v9 / "system.md").read_text(encoding="utf-8")
    sch_json = (v9 / "rules_schema.json").read_text(encoding="utf-8")
    assert NEW_WORDING_SYSTEM in sys_md, "new system.md wording absent"
    assert NEW_WORDING_SCHEMA in sch_json, "new rules_schema.json description absent"


def test_gate_5_carrier_shape_preserve():
    """G5: rules_schema.json carrier shape preserve (3-point: type=string + required + additionalProperties=false)."""
    v9 = _v9_dir()
    schema = json.loads((v9 / "rules_schema.json").read_text(encoding="utf-8"))
    t2i_ctx = schema["properties"]["t2i_context"]
    assert t2i_ctx["type"] == "string", f"t2i_context.type drift: {t2i_ctx['type']}"
    assert "t2i_context" in schema.get("required", []), f"t2i_context missing from required: {schema.get('required')}"
    assert schema.get("additionalProperties") is False, f"additionalProperties drift: {schema.get('additionalProperties')}"


def test_gate_6_step_manifest_schema_version_preserve():
    """G6: STEP_MANIFEST['visual_world_rules']['schema_version'] == 1 preserve."""
    assert STEP_MANIFEST["visual_world_rules"]["schema_version"] == 1


def test_gate_7_director_notes_section_preserve_canary():
    """G7: v9 line 57-84 director_notes section content ≡ v8 line 57-84 (byte-equal substring, Carry-A099 boundary canary).
    
    Carry-A099 W1 anchor preservation: v9 안 director_notes section content 는 v8 안 same range 와 byte-equal.
    """
    v9 = _v9_dir()
    v9_lines = (v9 / "system.md").read_text(encoding="utf-8").splitlines()
    v8_lines = (VWR_V8_DIR / "system.md").read_text(encoding="utf-8").splitlines()
    v9_section = "\n".join(v9_lines[56:84])  # line 57-84 (0-indexed [56:84])
    v8_section = "\n".join(v8_lines[56:84])
    assert v9_section == v8_section, "director_notes section drift v8 → v9 (Carry-A099 boundary 위반)"
```

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

**(a) Path-limited new file scope** (Codex narrow amend 1 IMPORTANT 2 정합):
```bash
# Path-limited untracked file check
git status --short -- backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py
# Expected: "?? backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py" (W3 신규 file).

# Global tree state = known untracked preserve verify (W2 commit 후 working tree clean preserve except 본 W3 신규 + known untracked artifact)
git diff --name-only
# Expected: 0 modified file (W2 commit 후 clean).
```

**(b) Test mechanism verify (no live LLM + NO VLM + no regex semantic)**:
```bash
grep -c "import.*LLM\|import.*vlm\|import.*openai\|import.*anthropic" backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py
# Expected: 0 (no LLM/VLM import).
grep -cE "re\.(search|match|findall)" backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py
# Expected: 0 (no regex semantic).
```

**(c) Marker-wrapped strict residue verify (Codex 2nd narrow re-review guard 3 정합)**:
```bash
grep -c "HISTORICAL AUDIT TRAIL — BEGIN" backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py
# Expected: 1 (marker block 안 R1_R5_STRICT 상수 wrap).
grep -c "HISTORICAL AUDIT TRAIL — END" backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py
# Expected: 1.
```

**(d) Pytest W3 + W1-modified A099 + Area #7a inherited + visual_context_helper direct consumer regression check** (Codex narrow amend 1 IMPORTANT 1 정합):
```bash
cd backend
.venv/bin/pytest \
  tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py \
  tests/integration/test_carry_a099_director_notes_abstraction.py \
  tests/test_visual_world_rules.py \
  tests/integration/test_area_7a_no_drift.py \
  tests/integration/test_area_7a_residue_gate.py \
  tests/services/test_visual_context_helper.py \
  -v --tb=short
cd ..
# Expected:
# - test_carry_a100_t2i_context_demonym_abstraction.py = 7 PASS (Gate 1-7).
# - test_carry_a099_director_notes_abstraction.py = 6 PASS (historical pin preserved, A100 impact 0).
# - Area #7a inherited 3 test = 18 PASS (3+8+7, A100 impact 0).
# - test_visual_context_helper.py = 9 PASS (t2i_context direct consumer surface, A100 impact 0).
# - Total: 40 PASS, 0 FAIL.
```

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

```bash
git add backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py
# Path-limited post-stage verify (Codex narrow amend 1 IMPORTANT 2)
git diff --cached --name-only
# Expected (exact match):
# backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py
# (1 new file staged, 0 out-of-scope.)
```

**Commit message format**:
```
W3(carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1): integrated test atomic — 7 gate verify

- backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py 신규 (7 Gate G1-G7 verify)
- Gate 1 G1: v9 active prompt-pack source-path proof (get_effective_source + get_active_version + schema-specific path)
- Gate 2 G2: v9 dir file count == 2
- Gate 3 G3: R1-R5 strict residue absence (marker-wrapped test constants, closed-world full-phrase)
- Gate 4 G4: new abstract wording presence (system.md + rules_schema.json)
- Gate 5 G5: carrier shape preserve (3-point: type=string + required + additionalProperties=false)
- Gate 6 G6: STEP_MANIFEST schema_version=1 preserve
- Gate 7 G7: director_notes section preserve canary (v9 line 57-84 ≡ v8 line 57-84, Carry-A099 boundary)

Pre-commit verify: 4 gate PASS — path-limited new file scope + no LLM/VLM/regex semantic + marker-wrapped strict residue + pytest 40 PASS (W3 7 + W1-modified A099 6 + Area #7a inherited 18 + visual_context_helper 9 direct consumer).

NO VLM. no live LLM. closed-world exact phrase membership only. standalone token global ban X. Marker-wrapped strict residue constants (test constants for producer-surface residue checks, not live prompt wording).

Codex APPROVED_FOR_W3_ENTRY + spec 4th narrow re-review APPROVED_FOR_PLAN + plan iter APPROVED_FOR_EXECUTION.
```

### 5.5 W3 Codex per-wave review
- W3 commit 후 즉시 Codex per-wave review 의무.
- Codex live verify: §5.2 1 file + §5.3 4 pre-commit gate PASS + §5.4 40 test PASS evidence.
- Codex verdict 예상 = `APPROVED_FOR_W4_ENTRY` or `NEEDS_REVISION_NARROW`.

## 6. W4 Implementation Atomic Wave — Closure docs (range review + push gate)

### 6.1 Pre-W4 Entry Sanity (Codex re-discuss + session health)
- W3 per-wave review APPROVED_FOR_W4_ENTRY 후만 W4 진입.
- Session health check 의무 (50%+ Codex close 의논 doctrine 정합 시 close+handoff).

### 6.2 W4 File Operations (path-limited per Codex non-blocking note + Codex narrow amend 1 MINOR 2 정합)

**path-limited scope** (Codex 4th narrow re-review non-blocking note 정합 — spec §10 = in-place REPLACE; audit 02/roadmap/history docs = narrow append/update where local structure calls for it; **7 repo-local docs / 8 logical edit sites**):

1. **본 spec frontmatter** `status: draft (...)` → `status: closed (...)`.
2. **본 spec §10 closure section in-place REPLACE** (heading 이미 존재; append X; pending placeholder section 전체 replace; no self-hash literal in W4 commit body; final pushed range/count = external memory only).
3. **본 plan frontmatter** `status: draft (...)` → `status: closed (...)`.
4. **Roadmap §5.7 narrow append** (`docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md:387-390` 범위 안 narrow append, local structure calls for append per Codex non-blocking note):
   ```
   Carry-A100 resolved by W1-W4 (Option B-prime: v9 prompt-pack bump, system.md line 102 narrow + rules_schema.json:40 description-only abstraction; structured emit / field-shape migration follow-up deferred).
   ```
5. **Audit 02 narrow update** (`docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md`):
   - §11.3 + §13 + §14 + line 311 A100 row Status 변경 = `closed (Carry-A100 W1-W4, 2026-05-19+)` form (narrow append/update per local structure).
   - 본 audit 안 §15 (또는 next available section) 안 Carry-A100 Closure section 신설 (W3/W6 후속 area pattern 정합).
6. **Area #7a v1 spec narrow update** (`docs/superpowers/specs/2026-05-18-area-7a-visual-world-rules-sot-v1-design.md` line 73 / 109 / 414 / 418 / 434 — Carry-A100 status `Carry-A100 resolved by W1-W4 (2026-05-19+)` narrow update).
7. **Area #7b v1 spec narrow update** (`docs/superpowers/specs/2026-05-19-area-7b-vwr-cascade-downstream-v1-design.md` line 31 / 110 / 130 / 571 / 716 — Carry-A100 status 동일 narrow update).
8. **Carry-A099 v1 spec carry table narrow update** (`docs/superpowers/specs/2026-05-19-carry-a099-vwr-system-md-director-notes-prose-redesign-v1-design.md` 안 carry priority context line — Carry-A100 status 동일 narrow update).

**No edit obligatory (W4 boundary preserve)**:
- prompts/_base/visual_world_rules/9.${UTC}/ (W2 commit time pinned).
- backend/tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py (W3 commit time pinned).
- backend/tests/integration/test_carry_a099_director_notes_abstraction.py (W1 commit time pinned).
- 8 direct reader file 변경 0.
- W0.1 inventory memo + Q1-Q7 outline = untracked (W4 안 git add X, untracked preserve per Carry-A099 lineage doctrine).

### 6.3 W4 §10 in-place REPLACE template (Codex 3rd narrow re-review N-2 정합)

**Before** (spec drafting time pending placeholder section):
```
## 10. Closure section (pending W4)

본 §10 = W4 closure-docs wave 안 in-place REPLACE 의무 (...). W4 commit body 안 self-hash literal 0 (...). W4 closure-docs wave exact hash recorded by git log/range review; no self-hash literal in the W4 commit body. Final pushed range/count = external memory only after push (...).
```

**After** (W4 closure commit time, in-place REPLACE — no self-hash literal):
```
## 10. Closure section (W4 closure-docs wave, 2026-05-19+)

본 Carry-A100 v1 = closed at W4 closure-docs commit.

### Wave atomic commit trace (4 commits, no self-hash literal — exact hash recorded by git log/range review)
- W1 — Carry-A099 test compat atomic (`test_carry_a099_director_notes_abstraction.py` historical v8 pin + unused import 제거 + test_gate_6 rename; 33 PASS — A099 6 + Area #7a inherited 18 + visual_context_helper 9 direct consumer).
- W2 — v9 producer prompt-pack atomic (`prompts/_base/visual_world_rules/9.${UTC}/` 2 file: system.md line 102 narrow + rules_schema.json:40 description-only narrow; carrier shape preserve + STEP_MANIFEST schema_version=1 preserve).
- W3 — Carry-A100 integrated test atomic (`test_carry_a100_t2i_context_demonym_abstraction.py` 신규 7 Gate G1-G7).
- W4 — Closure docs atomic (본 in-place REPLACE + roadmap §5.7 narrow append + audit 02 §11.3/§13/§14 + line 311 A100 row + Area #7a/#7b spec narrow + Carry-A099 spec carry table).

### Final pushed range/count = external memory only after push ([[feedback_push_no_user_ask]] 정합, pre-claim 0).

### Doctrine reaffirm
- 4-Gate Boundary Doctrine inline (Semantic Regex Ban / Closed-List Ban refined full-phrase only / Structured SOT Required partial / No Silent Fallback).
- NO VLM hard constraint.
- Closed-world exact full-phrase membership only.
- Standalone token global ban X.
- TEMPLATE ONLY + post-Carry-D7d-1 fix-up 1 + post-Carry-A099 N-5 + Codex 3rd narrow re-review N-1 doctrine.

### Carry follow-up post Carry-A100
- Carry-P021 (scene_consistency 7 enumeration broad, source unresolved) — Tier 4 deferred.
- Future Carry-A100-structured (`t2i_context: string` → `object` field-shape migration) — major carry / area follow-up.
```

### 6.4 W4 Pre-Commit Verify Gates (5 check)

**(a) Path-limited scope check** (Codex narrow amend 1 IMPORTANT 2 + MINOR 2 정합, 7 repo-local docs / 8 logical edit sites):
```bash
# Path-limited diff verify (7 expected files)
CLOSURE_DOCS=(
  docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md
  docs/superpowers/plans/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-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-7a-visual-world-rules-sot-v1-design.md
  docs/superpowers/specs/2026-05-19-area-7b-vwr-cascade-downstream-v1-design.md
  docs/superpowers/specs/2026-05-19-carry-a099-vwr-system-md-director-notes-prose-redesign-v1-design.md
)
git diff --name-only -- "${CLOSURE_DOCS[@]}"
# Expected: 7 files (all 7 CLOSURE_DOCS entries; 8 logical edit sites — Carry-A100 spec frontmatter + §10 = 2 logical sites in 1 file, 다른 6 file = 1 site each).

# Global tree state = known untracked preserve check only (W3 commit 후 working tree clean preserve, untracked artifact preserve)
git diff --name-only | sort
# Expected: 본 7 CLOSURE_DOCS entries만 (path-limited match).
```

**(b) Spec §10 in-place REPLACE verify**:
```bash
grep -c "## 10. Closure section (pending W4)" docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md
# Expected: 0 (pending placeholder 전체 replace).
grep -c "## 10. Closure section (W4 closure-docs wave" docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md
# Expected: 1 (new closure heading).
```

**(c) No self-hash literal in W4 commit body (Codex 3rd narrow re-review N-1 정합)**:
- W4 commit message body 안 literal commit hash 0 (W4 자체 hash + 이전 W1/W2/W3 hash 모두 명시 X). Exact hash = git log/range review recorded.

**(d) Carry-A100 spec/plan marker-excluded scan 0 + W4 added-lines no new angle-bracket literals** (Codex narrow re-review 2nd round N-2 정합 — gate semantics 분리):

```bash
# Part 1 — Carry-A100 spec + plan marker-excluded scan = 0 hit obligatory (R1/R2 literal angle-bracket forms 만 marker block 안에서 등장; 다른 위치 = 0)
A100_DOCS=(
  docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md
  docs/superpowers/plans/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-implementation.md
)
A100_HITS=0
for F in "${A100_DOCS[@]}"; do
  HITS=$(awk '/HISTORICAL AUDIT TRAIL — BEGIN/{skip=1; next} /HISTORICAL AUDIT TRAIL — END/{skip=0; next} !skip' "$F" | grep -cE '<[a-zA-Z][^>]*>')
  A100_HITS=$((A100_HITS + HITS))
  if [ "$HITS" -gt 0 ]; then
    echo "FAIL Carry-A100 marker-excluded scan hit ($HITS) in $F:"
    awk '/HISTORICAL AUDIT TRAIL — BEGIN/{skip=1; next} /HISTORICAL AUDIT TRAIL — END/{skip=0; next} !skip' "$F" | grep -nE '<[a-zA-Z][^>]*>' | head -3
  fi
done
[ "$A100_HITS" -eq 0 ] && echo "OK Carry-A100 spec/plan marker-excluded scan = 0 hit" || { echo "FAIL Carry-A100 marker-excluded scan total hits = $A100_HITS"; exit 1; }

# Part 2 — W4 introduced outside-marker angle-bracket literals = 0 obligatory (marker-aware authoritative check)
#
# Codex narrow amend (W4 mid-execution Part 2 marker-aware fix, 2026-05-19+, Codex W4 mid-execution NEEDS_PLAN_AMEND_PART2_FIRST verdict 흡수):
# 기존 raw `git diff --cached -U0 ^+ grep` mechanical check 는 marker-wrapped R1/R2 literals 가 포함된 Carry-A100 spec/plan
# 이 untracked → staged transition 시 over-count (every line is `+`, HISTORICAL AUDIT TRAIL marker block 안 content 포함).
# Codex narrow amend 2 N-2 intent + Codex W4 guard "no NEW outside marker blocks" 정합 = marker-block-stripped HEAD
# vs staged diff per file, grep added lines (`^>`) only. Raw added-line grep = non-authoritative diagnostic only.

CLOSURE_DOCS=(
  docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md
  docs/superpowers/plans/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-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-7a-visual-world-rules-sot-v1-design.md
  docs/superpowers/specs/2026-05-19-area-7b-vwr-cascade-downstream-v1-design.md
  docs/superpowers/specs/2026-05-19-carry-a099-vwr-system-md-director-notes-prose-redesign-v1-design.md
)

# Authoritative pass/fail = per-file marker-block-stripped HEAD vs staged diff, grep added lines for `<[a-zA-Z][^>]*>` literal form.
# Stripped-content diff catches remove+add net-zero swaps (stronger than marker-excluded count delta).
TOTAL_NEW_HITS=0
for F in "${CLOSURE_DOCS[@]}"; do
  HEAD_STRIP=$(git show "HEAD:$F" 2>/dev/null | awk '/HISTORICAL AUDIT TRAIL — BEGIN/{skip=1; next} /HISTORICAL AUDIT TRAIL — END/{skip=0; next} !skip')
  STAGED_STRIP=$(git show ":$F" | awk '/HISTORICAL AUDIT TRAIL — BEGIN/{skip=1; next} /HISTORICAL AUDIT TRAIL — END/{skip=0; next} !skip')
  NEW_HITS=$(diff <(echo "$HEAD_STRIP") <(echo "$STAGED_STRIP") | grep '^>' | grep -cE '<[a-zA-Z][^>]*>')
  TOTAL_NEW_HITS=$((TOTAL_NEW_HITS + NEW_HITS))
  if [ "$NEW_HITS" -gt 0 ]; then
    echo "FAIL W4 introduced $NEW_HITS new outside-marker angle-bracket literals in $F:"
    diff <(echo "$HEAD_STRIP") <(echo "$STAGED_STRIP") | grep '^>' | grep -nE '<[a-zA-Z][^>]*>' | head -5
  fi
done
[ "$TOTAL_NEW_HITS" -eq 0 ] && echo "OK W4 introduced 0 new outside-marker angle-bracket literals (marker-aware stripped-content diff, authoritative; CLOSURE_DOCS scope)" || {
  echo "FAIL W4 total new outside-marker angle-bracket literals = $TOTAL_NEW_HITS"
  exit 1
}

# Diagnostic only (non-authoritative): raw added-line grep over staged diff (intentionally over-counts marker-wrapped R1/R2 literals when newly-staged-from-untracked Carry-A100 spec/plan are part of the commit).
RAW_ADDED_HITS=$(git diff --cached -U0 -- "${CLOSURE_DOCS[@]}" | grep '^+' | grep -v '^+++' | grep -cE '<[a-zA-Z][^>]*>')
echo "Diagnostic only (non-authoritative): raw added-line grep hits = $RAW_ADDED_HITS (over-counts marker-wrapped R1/R2 in newly-staged-from-untracked Carry-A100 spec/plan; authoritative pass/fail = stripped-content diff above)"

# Part 3 — Inventory/reporting only (not pass/fail): 7-file full marker-excluded scan baseline (pre-existing legacy hits 허용)
echo "--- Inventory only (Codex N-2 정합, pass/fail X) ---"
TOTAL_BASELINE=0
for F in "${CLOSURE_DOCS[@]}"; do
  HITS=$(awk '/HISTORICAL AUDIT TRAIL — BEGIN/{skip=1; next} /HISTORICAL AUDIT TRAIL — END/{skip=0; next} !skip' "$F" | grep -cE '<[a-zA-Z][^>]*>')
  TOTAL_BASELINE=$((TOTAL_BASELINE + HITS))
  echo "  $F : $HITS legacy hits"
done
echo "Total 7-file legacy baseline hits = $TOTAL_BASELINE (inventory only; pre-existing legacy 허용 in roadmap/audit/Area/Carry-A099 spec; Carry-A100 spec/plan = 0 obligatory verified in Part 1; W4 added-lines = 0 obligatory verified in Part 2)."
```

**(e) Pytest re-run (range review precursor)** (Codex narrow amend 1 IMPORTANT 1 정합):
```bash
cd backend
.venv/bin/pytest \
  tests/integration/test_carry_a100_t2i_context_demonym_abstraction.py \
  tests/integration/test_carry_a099_director_notes_abstraction.py \
  tests/test_visual_world_rules.py \
  tests/integration/test_area_7a_no_drift.py \
  tests/integration/test_area_7a_residue_gate.py \
  tests/services/test_visual_context_helper.py \
  -v --tb=short
cd ..
# Expected: 40 PASS, 0 FAIL (W3 commit time 정합 + visual_context_helper direct consumer surface).
```

### 6.5 W4 Path-Limited git add + Commit

```bash
# Path-limited add (7 repo-local docs / 8 logical edit sites)
git add docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md
git add docs/superpowers/plans/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-implementation.md
git add docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md
git add docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md
git add docs/superpowers/specs/2026-05-18-area-7a-visual-world-rules-sot-v1-design.md
git add docs/superpowers/specs/2026-05-19-area-7b-vwr-cascade-downstream-v1-design.md
git add docs/superpowers/specs/2026-05-19-carry-a099-vwr-system-md-director-notes-prose-redesign-v1-design.md
git status --short
# Expected: 7 file staged (path-limited closure docs).
# 0 out-of-scope.
```

**Commit message format** (no self-hash literal in body — Codex 3rd narrow re-review N-1 정합):
```
W4(carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1): closure docs atomic — 7 file path-limited (spec frontmatter status closed + spec §10 in-place REPLACE + plan frontmatter + roadmap §5.7 + audit 02 §11.3/§13/§14 + line 311 A100 row + Area #7a/#7b spec narrow + Carry-A099 spec carry table)

- Carry-A100 spec frontmatter status closed
- Carry-A100 spec §10 closure section in-place REPLACE (pending placeholder 전체 replace; no self-hash literal; final pushed range/count = external memory only)
- Carry-A100 plan frontmatter status closed
- Roadmap §5.7 narrow append (Sub-area (b) Phase 1+/Phase 2+/Area #7c/#7d/Carry-A099 post 안 Carry-A100 resolved bullet)
- Audit 02 §11.3 + §13 + §14 + line 311 A100 row Status update + §15 Carry-A100 Closure section 신설
- Area #7a v1 spec line 73 + 109 + 414 + 418 + 434 Carry-A100 status narrow update
- Area #7b v1 spec line 31 + 110 + 130 + 571 + 716 Carry-A100 status narrow update
- Carry-A099 v1 spec carry priority context Carry-A100 status narrow update

Pre-commit verify: 5 gate PASS — path-limited scope + spec §10 in-place REPLACE + no self-hash literal + Carry-A100 spec/plan marker-excluded scan 0 + W4 added lines introduce 0 new literal angle-bracket forms (CLOSURE_DOCS scope; roadmap/audit/Area/Carry-A099 spec pre-existing legacy 허용, inventory only) + pytest 40 PASS.

NO VLM. no live LLM. closed-world exact phrase membership only. standalone token global ban X. Marker-wrapped strict residue constants. Carry-A100 spec/plan = literal angle-bracket form 0 outside HISTORICAL AUDIT TRAIL marker blocks; W4 added lines introduce 0 new literal angle-bracket forms.

Codex APPROVED_FOR_W4_ENTRY + spec 4th narrow re-review APPROVED_FOR_PLAN + plan iter APPROVED_FOR_EXECUTION.
```

### 6.6 W4 Codex per-wave review + range review + push gate
- W4 commit 후 즉시 Codex per-wave review 의무.
- W4 per-wave APPROVED 후 W1-W4 range review (Codex APPROVED_FOR_PUSH 의무).
- Push 시 사용자 ask 0 ([[feedback_push_no_user_ask]] 정합).

```bash
# W1-W4 range commit list verify (Codex live verify 안 본 instance 가 송신)
git log --oneline $(git merge-base HEAD origin/main)..HEAD
# Expected: 4 commits (W1 + W2 + W3 + W4).
```

## 7. Plan Iter Quality Round 1 (본 plan drafting 완료, Codex 의논 의무)

본 §7 = 본 plan 완성 후 Codex plan quality iter 1 review request 안 명시 항목 (사용자 plan drafting guidance 정합 + Codex narrow amend 1 MINOR 1 + 2 정합):
- Line count: **본 plan post-narrow-amend-2 ~940 line (length accepted due to 4-wave + inline bash/Python -c commands + W3 embedded test body + Codex narrow amend 1 IMPORTANT 1-4 + MINOR 1-2 inline absorption + Codex narrow amend 2 N-1/N-2/N-3 inline absorption)** — Codex MINOR 1 정합 정정 (plan drafting initial self-report "670-690 line target" stale; 1st quality iter pre-amend self-report "863 line" stale; 2nd quality iter post-amend-1 self-report "924 line" stale).
- Section structure: §1 Purpose + §2 Plan Iter Trace + §3 W1 + §4 W2 + §5 W3 + §6 W4 + §7 본 + §8 (placeholder substitution + session health) + §9 References.
- W1-W4 command/gate summary: 본 §3-§6 안 inline bash + Python -c command + commit message + per-wave Codex review schedule.
- Exact file scope:
  - W1 = 1 file modify (`test_carry_a099_director_notes_abstraction.py`).
  - W2 = 2 file new (`prompts/_base/visual_world_rules/9.${UTC}/{system.md,rules_schema.json}`).
  - W3 = 1 file new (`test_carry_a100_t2i_context_demonym_abstraction.py`).
  - W4 = **7 repo-local docs / 8 logical edit sites** (Carry-A100 spec frontmatter + Carry-A100 spec §10 in-place REPLACE = 2 logical sites in 1 file; 다른 6 file = 1 site each — 본 plan frontmatter / roadmap §5.7 / audit 02 §11.3+§13+§14+line 311+§15 신설 / Area #7a spec / Area #7b spec / Carry-A099 spec; Codex MINOR 2 정합).
- Placeholder-substitution gate: §6.4 (d) Carry-A100 spec/plan marker-excluded scan 0 + W4 added-lines new angle-bracket 0; 7 CLOSURE_DOCS scan = inventory only (Codex IMPORTANT 4 + narrow amend 2 N-2 정합 — Part 1 A100 spec/plan zero pass/fail / Part 2 W4 added-lines executable check zero pass/fail / Part 3 7-file legacy baseline reporting only).
- Session health estimate: 현재 약 55-60% (W0 + outline + 2 round W0+outline narrow re-review + revision + spec v1 + 2 round spec re-review + spec N-1/N-2/N-3 revision + plan v1 + 3 round plan quality iter review + narrow amend 1 + narrow amend 2). W1 (~5-7%) + W2 (~5-7%) + W3 (~5-7%) + W4 (~5-10%) + per-wave Codex review (~3-5% each) = ~30-40% additional usage. **55%+ doctrine 진입 시점 — Codex CLOSE_HANDOFF_W1_FRESH 권고 정합 (W1-W4 execution 다음 fresh session)**.

## 8. Placeholder + Doctrine Gates (Codex narrow re-review 누적 흡수)

### 8.1 Placeholder doctrine
- **Live plan body**: `9.UTC_TIMESTAMP` (design-time placeholder) + `9.${UTC}` (W2 controller shell variable) 형태만 사용. Literal angle-bracket placeholder (R1 form) 재방출 0.
- **Historical R1-R5 literal**: explicit `<!-- HISTORICAL AUDIT TRAIL — BEGIN/END -->` marker block 안에서만 (본 plan §4.3 (d) bash gate block + spec §8 catalog table). Test code 안 R1_R5_STRICT list 도 marker block comment 안 wrap.
- **Underscore-escape variant**: live prompt 안 X. plan body 안 X (Codex Q0-light Q2 (a) verdict).

### 8.2 Doctrine reaffirm
- **Gate 1 Semantic Regex Ban**: pre-commit gate + W3 test code 모두 fixed-string `grep -F` / `str.__contains__` / `not in` membership only.
- **Gate 2 Prompt Closed-List Ban refined full-phrase only**: residue contract = exact 5-item full-phrase. Standalone word global ban X.
- **Gate 3 Structured SOT Required**: v1 = partial (abstraction + description-only). Field-shape migration = Future Carry-A100-structured.
- **Gate 4 No Silent Fallback**: t2i_context `string required additionalProperties false` preserve. 8 direct reader empty pass-through 패턴 preserve.
- **NO VLM hard constraint**.
- **TEMPLATE ONLY + post-Carry-D7d-1 fix-up 1 + post-Carry-A099 N-5 + Codex 3rd narrow re-review N-1/N-2 doctrine**: literal angle-bracket placeholder 재방출 outside marker blocks X. Spec §10 in-place REPLACE (heading 이미 존재; append X). No self-hash literal in W4 commit body.

### 8.3 Session health doctrine
- W1 entry 전 Codex re-discuss session usage check 의무.
- 50%+ Codex close 의논 ([[feedback_session_50pct_codex_close_check]] 정합).

## 9. References

- **Spec**: `docs/superpowers/specs/2026-05-19-carry-a100-vwr-system-md-t2i-context-demonym-redesign-v1-design.md` (4 round narrow re-review absorbed, APPROVED_FOR_PLAN).
- **W0.1 inventory artifact** (untracked, reference only): `docs/superpowers/specs/2026-05-19-carry-a100-w0-1-inventory.md`.
- **Q1-Q7 outline artifact** (untracked, reference only): `docs/superpowers/specs/2026-05-19-carry-a100-q1-q7-outline.md`.
- **Active VWR pack (v8, Carry-A099 anchor)**: `prompts/_base/visual_world_rules/8.202605191102/`.
- **W1 modify target**: `backend/tests/integration/test_carry_a099_director_notes_abstraction.py` (113 line, historical pin refactor).
- **Codex iter verdict trace**:
  - Q0-light: `NEEDS_REVISION_NARROW_N1_THEN_PROCEED_TO_W0_INVENTORY_AND_Q1_Q7_OUTLINE`.
  - 1st narrow re-review (W0+outline): `NEEDS_REVISION_MINOR` IMPORTANT 1/2/3 + MINOR 1.
  - 2nd narrow re-review (W0+outline post-revision): `APPROVED_FOR_SPEC_V1_DRAFT_WITH_NARROW_GUARDS` (6 guards).
  - 3rd narrow re-review (spec v1): `NEEDS_REVISION_NARROW` N-1/N-2/N-3.
  - 4th narrow re-review (spec v1 post-revision): `APPROVED_FOR_PLAN` + non-blocking note (audit 02/roadmap narrow append OK, spec §10 in-place REPLACE).
- **Roadmap**: `docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md:387-390` (Track B §5.7).
- **Audit 02**: `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md:311` (A100 row + §11.3/§13/§14 carry follow-up).
- **Pre-Carry-A100 closure**: [[session_20260519_carry_a099_v1_closure]] (origin/main HEAD `146401c`).
- **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]] + [[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]] + [[next_session_carry_a100_q0_light]].
