---
title: C7 — shot_dependency_t2i subject_kind structured signal v1 implementation plan (fix-critical-1 Tier β #4)
date: 2026-05-20+
status: closed (C7 v1 W1-W2 complete — Codex per-wave APPROVED + W1-W2 range review APPROVED_FOR_PUSH)
spec_ref: docs/superpowers/specs/2026-05-20-c7-shot-dependency-subject-kind-v1-design.md (status APPROVED_FOR_PLAN — amend 1 BLOCKING 1 + IMPORTANT 1 흡수)
roadmap_ref: docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md §5.12 (Area #12)
fix_critical_doc_ref: docs/fix-critical-1/index.html C7 section (lines 821-908)
prerequisites:
  - C7 spec v1 APPROVED_FOR_PLAN (Codex spec re-review 2026-05-20+ — amend 1 BLOCKING 1 scene_context_loader hard gate + IMPORTANT 1 scene_checkpoint_loaders empty keep_elements 흡수).
  - C3 detail_steps focus rewrite 폐기 v1 closed (origin/main HEAD `1e8cc2a`) — HEAD anchor. C3 `_strip_invalid_sids` 변경 0.
non_supersedes:
  - C6 #10 / C9 L-7 / C4 #8 / C5 #9 / C8 #7 / C10 (fix-critical-1 잔여 area).
---

# C7 — shot_dependency_t2i subject_kind structured signal v1 implementation plan

## 1. Purpose + Spec Reference

C7 = `shot_dependency_t2i` producer 의 `keep_elements[]` entry 에 `subject_kind` structured signal (enum `non_human_visual_element` / `human_or_character_reference`) 신설 → producer LLM 이 인물/비인물 여부를 explicit emit, code 가 enum 소비 + `human_or_character_reference` fail-fast. prompt 의 비-enforced 11-lexicon ban + false "fail-fast 거부" claim 폐기.

- spec: `docs/superpowers/specs/2026-05-20-c7-shot-dependency-subject-kind-v1-design.md` §1-§10.
- **2-wave** (spec §3.3): **W1** = producer v8 prompt-pack(2 new) + version cascade·consumer envelope(3 modify) + code consume(1 modify) + test(2 modify + 1 new + blast radius) — 1 atomic commit. **W2** = closure docs atomic.
- HEAD anchor = `1e8cc2a` (origin/main, C3 v1 closed).
- 2-wave 근거: `subject_kind` schema-required + code consume + 11-lexicon 제거가 W1 단일 atomic 으로 동시 landing 해야 Codex narrow guard #2 ("11-lexicon 은 schema-required AND consumed 후 제거") 충족 — spec §3.3.

## 2. Plan Iter Trace

- iter 0 (2026-05-20+): plan v1 drafting.

## 3. W1 — producer v8 prompt-pack + version cascade + code consume + test (1 atomic commit)

### 3.1 Pre-W1 Entry Sanity

- W1 진입 전 Codex W1 entry sanity 받을 것 (file edit 0 상태에서 송신).
- 진입 직전 read: 승인된 spec + 본 plan + W1 대상 파일 현재 상태 (line drift 확인 — old_string anchor 가 현 HEAD `1e8cc2a` 와 일치하는지): `shot_dependency_t2i/7.202605151200/{schema.json, system.md}`, `keep_elements.py`, `version_registry.py`, `step_manifest.py`, `scene_context_loader.py`, `test_area_d_next_shot_dependency_t2i.py`, `test_scene_context_loader_load_dependencies.py`.
- HEAD = `1e8cc2a` verify. `git diff --stat` clean (tracked).
- **W1_UTC 확정** — 진입 시 `date -u +%Y%m%d%H%M` 실행 → v8 dir 명 `8.<W1_UTC>` 고정 (C2 N-exec-2 / Carry-P021 N-exec-2 lesson — UTC dimension runtime 확정, closure docs 가 actual value 사용).

### 3.2 W1 File Operations (1 atomic commit)

| op | file | wave-part |
|----|------|-----------|
| new | `prompts/_base/shot_dependency_t2i/8.<W1_UTC>/schema.json` | W1-A |
| new | `prompts/_base/shot_dependency_t2i/8.<W1_UTC>/system.md` | W1-A |
| modify | `backend/app/core/version_registry.py` | W1-B |
| modify | `backend/app/core/step_manifest.py` | W1-B |
| modify | `backend/app/core/steps/scene_context_loader.py` | W1-B |
| modify | `backend/app/core/keep_elements.py` | W1-C |
| modify | `backend/tests/services/test_area_d_next_shot_dependency_t2i.py` | W1-D |
| modify | `backend/tests/unit/test_scene_context_loader_load_dependencies.py` | W1-D |
| new | `backend/tests/integration/test_c7_shot_dependency_subject_kind.py` | W1-D |
| modify | `backend/tests/services/test_scene_checkpoint_loaders.py` | W1-D (blast radius) |
| modify | `backend/tests/services/test_scene_reference_service.py` | W1-D (blast radius) |
| modify | (W1 regression baseline-diff 가 추가로 드러내는 subject_kind-caused failure file) | W1-D (blast radius) |

v7 dir (`7.202605151200/`) 보존 — 덮어쓰기 0 (CLAUDE.md 프롬프트 파일 관리 규칙).

### 3.3 W1-A — producer v8 prompt-pack (`prompts/_base/shot_dependency_t2i/8.<W1_UTC>/`)

v8 dir 신설. `schema.json` / `system.md` 는 v7 (`7.202605151200/`) copy 기반 + 아래 delta.

**W1-A.1 — `schema.json`** (v7 copy + 3 edit):

- **SA-1** — keep_elements item `properties` 에 `subject_kind` 추가 (현 v7 `:34-44` `label`/`kind` properties 블록):
```json
                      "subject_kind": {
                        "type": "string",
                        "enum": ["non_human_visual_element", "human_or_character_reference"],
                        "description": "Explicit subject classification of this entry. non_human_visual_element: the label describes environment or a non-human object. human_or_character_reference: the label describes a person, character, or body. keep_elements may only carry non_human_visual_element entries; a human_or_character_reference entry is rejected — person/character state is routed to scene_consistency, character_state_variant, and semantic_contract_router, not keep_elements."
                      }
```
  `required` → `["label", "kind", "subject_kind"]` (현 v7 `:45`). `additionalProperties: false` (현 v7 `:46`) 유지.
- **SA-2** — keep_elements `kind` description (현 v7 `:42`) 의 `PERSON/CHARACTER/BODY descriptions are FORBIDDEN — character state ... not keep_elements.` prose 제거 → `subject_kind` cross-ref: `"environment: walls, floors, furniture layout, lighting, background structure. static_prop: non-human objects (tools, bags, documents, photos, broken items, etc.). See subject_kind for the person / non-person classification of this entry."`. keep_elements `label` description (현 v7 `:37`) 의 `no person/character/body descriptions` 절 제거 (subject_kind 담당) — 나머지 wording 보존.
- **SA-3** — `ignore_elements` description (현 v7 `:28`) 의 closed-list 열거 정리: `"No add/replace/adjust instructions. No conditional phrasing (no 'if...', 'when...', 'only if')."` → `"State only definite descriptions of what to ignore — no editing directives and no conditional phrasing (see system.md ignore_elements rules)."`. behavior 불변.

**W1-A.2 — `system.md`** (v7 copy + edit E1-E6):

- **E1** — `### 출력 shape` (현 v7 `:128-132`) — `각 entry 는 {label, kind} 형태` → `{label, kind, subject_kind} 형태` + field 목록에 `subject_kind` (enum 2개) 추가.
- **E2** — `### subject_kind 결정 (필수 emit)` subsection 신설 (출력 shape 직후) — producer 가 각 keep_elements entry 의 인물/비인물 여부를 정직하게 분류·emit; keep_elements 는 `non_human_visual_element` 만 담음; 인물/캐릭터 묘사면 `human_or_character_reference` 로 분류하되 keep_elements 에 넣지 말고 별도 layer (scene_consistency / character_state_variant / semantic_contract_router) 책임임을 명시.
- **E3** — `:148` false claim 정정 — `다음 label 패턴은 enum 위반으로 fail-fast 거부됩니다:` → `다음 label 패턴은 subject_kind=human_or_character_reference 로 분류되어 keep_elements 에서 fail-fast 거부됩니다:` (code 가 실제 그렇게 동작 — §3.5 W1-C 정합, 따라서 더 이상 false 아님).
- **E4** — `:156` 11-lexicon ban list (`human / person / character / body / figure / man / woman / detective / prisoner / child / person silhouette 등 인물 지칭 어떠한 단어도 label 에 포함 금지.`) **삭제** → `인물·캐릭터를 지칭하는 label 은 subject_kind=human_or_character_reference 로 정직하게 분류하고 keep_elements 에 넣지 마세요 — keep_elements 는 subject_kind=non_human_visual_element entry 만 담습니다.` 로 교체.
- **E5** — `### 작성 규칙` (현 v7 `:158-164`) — `:161` `kind 값은 위 2개 중 정확히 하나 — 그 외 값 금지 (immobilized_character / character / pose 등 enum 외 값 절대 금지).` 의 괄호 열거 제거 → `kind 값은 schema 의 kind enum 2종 (environment / static_prop) 중 정확히 하나.`. `:163` `label 에 인물 지칭 단어 (...) 포함 금지.` → `label 이 인물/캐릭터/신체를 지칭하면 그 entry 의 subject_kind 는 human_or_character_reference — keep_elements 에 넣지 말 것.`.
- **E6** — `:149-154` ❌ 예시 6개 — `kind` 만 있는 entry literal 을 `subject_kind` 포함 형태로 갱신하거나, "이런 label 은 subject_kind=human_or_character_reference 로 분류되어 거부됨" illustration 으로 재서술. `environment`/`static_prop` 정의·예시 (현 v7 `:134-145`, `:166-176`) 는 ≥3회 유지 (B6-형 test 정합).
- 잔여 invariant — v8 system.md 전체에 false enforcement claim 0 (G8), `immobilized_character` 단어 ≤1회 (B6 정합 — E5 에서 괄호 열거 제거 시 0회 가능, ≤1 만족).

### 3.4 W1-B — version cascade + consumer envelope (3 modify)

**W1-B.1 — `version_registry.py`**:
- `MODULE_VERSIONS["shot_dependency_t2i"]` (현 `:39`) `"1.4.0"` → `"1.5.0"` + 주석 — `2026-05-20 — C7: keep_elements[].subject_kind structured signal 신설 (인물/비인물 enum). v8 prompt + schema_version=4.` 류.
- `_MODULE_INFO["shot_dependency_t2i"]` (현 `:141-144`) `prompt_dependency` `"shot_dependency_t2i/v7"` → `"shot_dependency_t2i/v8"` + `updated_at` `"2026-05-15"` → W1 날짜 (`2026-05-20`).

**W1-B.2 — `step_manifest.py`**:
- `STEP_MANIFEST["shot_dependency_t2i"]["schema_version"]` (현 `:757`) `3` → `4`.
- 인접 주석 (현 `:751-756`) 에 C7 줄 추가 — `C7 (2026-05-20) — keep_elements[] subject_kind required field 추가 (output shape change). v8 cp 는 schema_version=4. shot_dependency_t2i 는 _LEGACY_SCHEMA_BUMP_ALLOWLIST 밖 → v7 cp resume BLOCK, 운영자 force.` 류. `_LEGACY_SCHEMA_BUMP_ALLOWLIST` (현 `:71`) **변경 0**.

**W1-B.3 — `scene_context_loader.py`** (Codex spec review BLOCKING 1):
- `_load_dependencies()` envelope gate — 현 `:129` `if schema_v != 3:` → `if schema_v != 4:`.
- 현 `:132-140` `AppError` message — `expected 3 (Area D-next-min bump — keep_elements kind enum 2종, immobilized_character 폐기).` → `expected 4 (C7 bump — keep_elements[] subject_kind required field).`; legacy 안내에 `v7 (schema_version 3)` 을 force re-run 대상으로 포함 (기존 v5/v6 안내 보존 + v7 추가).
- method docstring (현 `:112-120`) 의 `schema_version=3` / `v7 schema` 언급 → v8 / `schema_version=4` 정합 정정.
- **불변**: 제어 흐름 (envelope mismatch → `raise AppError`), error code `step.scene_context_loader.legacy_keep_elements_cp`, status_code 409, 이어지는 entry-level `validate_keep_elements()` 호출 (현 `:158-163`).

### 3.5 W1-C — code consume (`backend/app/core/keep_elements.py`, 1 modify)

- **CC-1** — `KEEP_ELEMENT_SUBJECT_KINDS` frozenset 신설 (`KEEP_ELEMENT_KINDS` 현 `:24-26` 직후):
```python
KEEP_ELEMENT_SUBJECT_KINDS: frozenset[str] = frozenset({
    "non_human_visual_element", "human_or_character_reference",
})
```
- **CC-2** — `validate_keep_elements_entry()` presence check (현 `:57`) — `if "label" not in entry or "kind" not in entry:` → `if "label" not in entry or "kind" not in entry or "subject_kind" not in entry:`. message 의 `sorted(entry.keys())` 출력은 그대로 (3-key 누락 모두 안내).
- **CC-3** — `kind` enum check (현 `:76-84`) **직후** `subject_kind` 검사 2단 추가:
```python
    if entry["subject_kind"] not in KEEP_ELEMENT_SUBJECT_KINDS:
        raise AppError(
            code=error_code,
            message=(
                f"{label_source}: keep_elements entry.subject_kind must be one of "
                f"{sorted(KEEP_ELEMENT_SUBJECT_KINDS)}, got {entry['subject_kind']!r}"
            ),
            status_code=400,
        )
    if entry["subject_kind"] == "human_or_character_reference":
        raise AppError(
            code=error_code,
            message=(
                f"{label_source}: keep_elements entry has subject_kind="
                f"'human_or_character_reference' (label={entry['label']!r}) — "
                f"keep_elements carries only non-human visual elements "
                f"(environment / static_prop). Person/character references are "
                f"routed to scene_consistency.character_state, "
                f"character_state_variant, and semantic_contract_router."
            ),
            status_code=400,
        )
```
- **CC-4** — module docstring (현 `:1-16`) 의 `schema v7` → `schema v8`; `KEEP_ELEMENT_KINDS 는 2종` 설명에 `subject_kind` 1줄 추가 (인물/비인물 enum). legacy-v5 str message (현 `:121-126`) 의 `v7 (1→3)` 언급 — 정확성 위해 `v8 (schema_version 4)` 로 갱신 (선택, behavior 불변).
- **불변**: `KEEP_ELEMENT_KINDS` frozenset, `kind` enum check 본체, `isinstance(entry, dict)` / `label isinstance(str)` check, `validate_keep_elements()` list 순회 + legacy-v5 str branch.

### 3.6 W1-D — test (2 modify + 1 new + blast radius)

**W1-D.1 — `test_area_d_next_shot_dependency_t2i.py`** (modify):
- **B1** (`test_b1_v7_schema_kind_enum_matches_single_sot`, 현 `:39-61`) — dir filter `startswith("7.")` → `startswith("8.")`; test 명 `v7` → `v8`; `kind` enum == `KEEP_ELEMENT_KINDS` assertion 보존 + `subject_kind` enum == `KEEP_ELEMENT_SUBJECT_KINDS` + `required == {label, kind, subject_kind}` assertion 추가.
- **B2** (`:68-105`) — `test_b2_validate_entry_rejects_malformed` parametrize 의 valid-except-one entry 에 valid `subject_kind` 추가 (그래야 의도한 위반만 trigger — `subject_kind` 누락 시 "missing required keys" 로 먼저 fail). `test_b2_validate_entry_accepts_valid` 의 4 entry 에 `subject_kind: "non_human_visual_element"` 추가. parametrize 에 신규 케이스 — `subject_kind` 누락 → "missing required keys", invalid `subject_kind` → "subject_kind must be one of", `human_or_character_reference` → routing message.
- **B3** (`:125-233`) — `_shape_violation_payload` / valid keep_elements payload 의 entry 에 `subject_kind` 추가 (의도된 위반 케이스는 위반만 남기고 나머지 field 정상화).
- **B4** (`test_b4_step_manifest_schema_version_three`, 현 `:240-248`) — test 명 `_three` → `_four`, assertion `== 3` → `== 4`, message wording 갱신.
- **B5** (`test_b5_version_registry`, 현 `:255-261`) — `MODULE_VERSIONS["shot_dependency_t2i"] == "1.4.0"` → `"1.5.0"`; `prompt_dependency == "shot_dependency_t2i/v7"` → `"/v8"`; `updated_at == "2026-05-15"` → W1 날짜.
- **B6** (`test_b6_v7_system_md_lists_enum_two`, 현 `:268-286`) — dir filter `startswith("7.")` → `"8."`; test 명 `v7` → `v8`; `environment`/`static_prop` ≥3 assertion 보존; `immobilized_character` ≤1 assertion 보존 (E5 에서 괄호 열거 제거 → 0회 → ≤1 만족).
- **B7** (`:293-326`) — legacy immobilized entry 에 valid `subject_kind` 추가 (kind enum 위반에 도달하도록). `immobilized_character` 거부 의도 보존.

**W1-D.2 — `test_scene_context_loader_load_dependencies.py`** (modify, Codex spec review BLOCKING 1):
- module docstring (현 `:1-17`) 의 `schema_version != 3` / `schema_version 3` contract 문구 → `4` 정정.
- happy path — `test_v7_valid_cp_returns_dependencies` (현 `:64-85`) / `test_v7_valid_empty_keep_elements_passes` (현 `:88-104`) — cp `schema_version` `3` → `4`; 전자의 keep_elements 2 entry 에 `subject_kind: "non_human_visual_element"` 추가. test 명 `v7` → `v8` 권장.
- shape-violation test — `test_v7_cp_legacy_string_keep_elements_raises` / `_missing_keep_elements_key_raises` / `_invalid_kind_enum_raises` / `_legacy_immobilized_character_kind_raises` / `_missing_label_field_raises` (현 `:168-268`) — cp envelope `schema_version` `3` → `4` (envelope gate 가 먼저 raise 안 하도록); `_invalid_kind_enum_raises` / `_legacy_immobilized_character_kind_raises` 의 entry 에 valid `subject_kind` 추가 (의도한 kind 위반 도달).
- **신규 test** — `test_v7_cp_schema_version_3_raises_as_legacy` — `schema_version: 3` cp → `AppError` `step.scene_context_loader.legacy_keep_elements_cp` (accepted = 4 전환 증명, BLOCKING 1 G9 정합).
- legacy v5/v6 raise test — `test_v5_cp_missing_schema_version_raises` / `_schema_version_1_raises` / `test_v6_cp_schema_version_2_raises_as_legacy` (현 `:111-160`) — accepted 가 `!= 4` 이므로 absent/1/2 모두 그대로 raise — **변경 0** (보존).
- `test_t2i_cp_empty_dependencies_falls_back` (현 `:290-306`) — `schema_version` `3` → `4` (dependencies empty 라 envelope check skip, 기능 무관하나 일관성).

**W1-D.3 — `test_c7_shot_dependency_subject_kind.py`** (new) — G1-G9 (spec §7). no live LLM, NO VLM — `validate_keep_elements_entry` helper unit + v8 `schema.json`/version source canary + `scene_context_loader._load_dependencies` envelope behavioral test (G9). `test_c{1,2,3}_*` 명명 정합. 구성:
- G1 valid 비인물 entry (environment + static_prop) 통과.
- G2 `subject_kind: "human_or_character_reference"` → `AppError`, message 에 `scene_consistency`/`character_state_variant`/`semantic_contract_router` 포함.
- G3 `subject_kind` 누락 → `AppError` `"missing required keys"`.
- G4 invalid `subject_kind` → `AppError` `"subject_kind must be one of"`.
- G5 invalid `kind` (`immobilized_character`) 여전히 `AppError` `"must be one of"` + `KEEP_ELEMENT_KINDS == {environment, static_prop}`.
- G6 v8 `schema.json` keep_elements item — `subject_kind` enum == `KEEP_ELEMENT_SUBJECT_KINDS`, `required == [label, kind, subject_kind]`, `additionalProperties == false`, `kind` enum == `KEEP_ELEMENT_KINDS`.
- G7 version cascade — `STEP_MANIFEST schema_version == 4`, `MODULE_VERSIONS == "1.5.0"`, `get_module_info` `prompt_dependency == "shot_dependency_t2i/v8"`, v8 dir 존재, `_LEGACY_SCHEMA_BUMP_ALLOWLIST == frozenset({"entity_t2i"})`.
- G8 v8 `system.md` residue canary — false `"fail-fast 거부됩니다"` 단독 claim 부재 (E3 정정 wording `subject_kind=human_or_character_reference 로 분류되어` 와 동반된 것만), 11-lexicon ban list 부재 (`detective`/`prisoner` 등 lexicon 나열 문장 0), `subject_kind` emit instruction 존재; v8 `schema.json` `ignore_elements` description 에 `'only if'` literal 부재.
- G9 `scene_context_loader._load_dependencies()` — `_FakeRunner` 활용 (test_scene_context_loader 패턴), v8 cp (`schema_version: 4` + `subject_kind` 포함 keep_elements) 통과 / v7 cp (`schema_version: 3`) → `AppError` `legacy_keep_elements_cp`.
- **G8 canary 자기-trip 회피** (C3 N-1 lesson) — test 파일 안 / spec·plan docstring 안에 G8 가 "부재" 로 검사하는 literal (`fail-fast 거부됩니다` 단독, 11-lexicon 나열) 을 검사 대상 문자열로만 두고 prose 로 풀어쓰지 말 것. canary 대상 literal 은 변수/주석 최소화.

**W1-D.4 — blast radius** (subject_kind required 도입으로 `validate_keep_elements*` 경로 타는 기존 test fail):
- grep 결과 (validate-path 호출 hit) — `test_scene_checkpoint_loaders.py` (26 hit, `load_shot_dependency_map` 경유) + `test_scene_reference_service.py` (8 hit, `validate_keep_elements` 2 site 경유) = **확정 정정 대상** — keep_elements entry fixture 에 `subject_kind` 추가 (validation 통과 의도 entry) / 의도된 위반 test 는 위반만 남김.
- 비-대상 (validate 경로 미경유 — consumer 가 re-validate 안 함): `test_detail_steps_keep_elements.py` / `test_forward_zoom_targets.py` / `test_render_prompt_card*.py` / `test_g4_1_card_consumer_wiring.py` / `test_prompt_service_label_routing.py` (validate-path hit 0) — subject_kind 부재로 fail 안 함, 정정 불필요. W1 regression 으로 재확인.
- **W1 gate 가 authoritative** — 3.7 Gate W1.6 백엔드 전체 회귀 + clean HEAD `1e8cc2a` git stash 대조 (C3 N-4 패턴) 로 subject_kind-caused failure 전수 식별 → 전부 정정 후 commit. pre-existing failure 와 분리.

### 3.7 W1 Pre-commit Gate

repo-root cwd (`/Users/manta/Documents/Projects/TheRoad-I1`) 에서 실행. 모든 gate = 프로젝트 venv python + `PYTHONPATH=backend` (system python app import fail — C1/C2/C3 N-exec 정합). `cd backend` cwd drift 금지 (Carry-P021 N-exec-1).

```bash
# Gate W1.1: v8 prompt-pack dir + 2 file 존재
PYTHONPATH=backend backend/.venv/bin/python - <<'PY'
from pathlib import Path
import glob
dirs = sorted(glob.glob("prompts/_base/shot_dependency_t2i/8.*"))
assert dirs, "v8 dir 부재"
d = Path(dirs[-1])
assert (d / "schema.json").exists() and (d / "system.md").exists(), "v8 schema/system 부재"
print("Gate W1.1 OK", d.name)
PY

# Gate W1.2: keep_elements helper — KEEP_ELEMENT_SUBJECT_KINDS + subject_kind validation
PYTHONPATH=backend backend/.venv/bin/python - <<'PY'
from app.core.keep_elements import KEEP_ELEMENT_SUBJECT_KINDS, validate_keep_elements_entry
from app.core.errors import AppError
assert KEEP_ELEMENT_SUBJECT_KINDS == frozenset({"non_human_visual_element", "human_or_character_reference"})
# human_or_character_reference fail-fast
try:
    validate_keep_elements_entry(
        {"label": "unconscious man", "kind": "static_prop", "subject_kind": "human_or_character_reference"},
        label_source="gate", error_code="x")
    raise SystemExit("FAIL: human_or_character_reference 통과")
except AppError as e:
    assert "semantic_contract_router" in str(e.message)
# valid 통과
validate_keep_elements_entry(
    {"label": "wooden bench", "kind": "environment", "subject_kind": "non_human_visual_element"},
    label_source="gate", error_code="x")
print("Gate W1.2 OK")
PY

# Gate W1.3: version cascade
PYTHONPATH=backend backend/.venv/bin/python - <<'PY'
from app.core.step_manifest import STEP_MANIFEST, _LEGACY_SCHEMA_BUMP_ALLOWLIST
from app.core.version_registry import MODULE_VERSIONS, get_module_info
assert STEP_MANIFEST["shot_dependency_t2i"]["schema_version"] == 4
assert MODULE_VERSIONS["shot_dependency_t2i"] == "1.5.0"
assert get_module_info("shot_dependency_t2i")["prompt_dependency"] == "shot_dependency_t2i/v8"
assert _LEGACY_SCHEMA_BUMP_ALLOWLIST == frozenset({"entity_t2i"}), "allowlist 변경됨"
print("Gate W1.3 OK")
PY

# Gate W1.4: C7 integrated test G1-G9 전수 PASS
PYTHONPATH=backend backend/.venv/bin/pytest backend/tests/integration/test_c7_shot_dependency_subject_kind.py -q

# Gate W1.5: keep_elements / shot_dependency / scene_context_loader / scene_reference / scene_checkpoint 회귀
PYTHONPATH=backend backend/.venv/bin/pytest backend/tests -k "keep_elements or shot_dependency or scene_context_loader or scene_reference or scene_checkpoint_loaders or area_d_next" -q

# Gate W1.6: 백엔드 전체 회귀 — clean HEAD 1e8cc2a baseline 대조
#   subject_kind-caused failure 전수 정정 후, 잔여 failure = pre-existing 만 (C3 closure 시 5 pre-existing 확인).
PYTHONPATH=backend backend/.venv/bin/pytest backend/tests -q
```

- Gate W1.6 의 신규 failure 가 C7 변경 기인이면 commit 금지 → blast radius 정정. clean HEAD `1e8cc2a` 를 `git stash` 후 동일 명령으로 baseline failure set 확보 → diff 로 pre-existing 분리 (C3 N-4 패턴). pre-existing 으로 C3 closure 가 기록한 5 failure (text_cleaner 등 C7 무관) 와 일치 확인.
- Gate W1.1-W1.5 전부 PASS + W1.6 = pre-existing 만 → W1 commit.

### 3.8 W1 Commit + per-wave Codex review

- commit message: `W1(c7-shot-dependency-subject-kind-v1): keep_elements[].subject_kind structured signal — v8 prompt-pack(schema+system) + schema_version 3→4 + version_registry v8 + scene_context_loader envelope + validate_keep_elements_entry consume + C7 test G1-G9 + blast radius (N file)`
- staged: §3.2 표의 파일만 `git add` 명시 경로 (global `git add -A`/`.` 금지 — untracked audit output noise 다수).
- commit 후 Codex W1 per-wave review 송신 → `APPROVED_FOR_W2_ENTRY` 받고 W2 진입.

## 4. W2 — Closure docs atomic

### 4.1 Pre-W2 Entry Sanity

- W1 per-wave `APPROVED_FOR_W2_ENTRY` 후 진입. W2 = closure docs only — code/test/prompt 변경 0.

### 4.2 W2 File Operations (4 docs, path-limited)

| op | file |
|----|------|
| modify | `docs/superpowers/specs/2026-05-20-c7-shot-dependency-subject-kind-v1-design.md` |
| modify | `docs/superpowers/plans/2026-05-20-c7-shot-dependency-subject-kind-v1-implementation.md` |
| modify | `docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md` |
| modify | `docs/fix-critical-1/index.html` |

### 4.3 W2 closure docs 내용

1. **spec** — frontmatter `status` → closed + §10 Closure (commit chain / Gate result / Codex review trace / 함정 / carry priority post-C7).
2. **plan** — frontmatter `status` → closed + §5 Closure.
3. **roadmap** — §5.12 Area #12 entry 를 closed 형식으로 갱신 (§5.13/5.14/5.15 C1/C2/C3 정합 — Status closed / 본질 / Fix applied / Boundary preserve / Closure verify commit chain).
4. **fix-critical-1 index.html** — C7 marker: badge `✓ CLOSED` + 진입순서 list `C7 → CLOSED` / `C6 → NEXT` + priority matrix row 4 status + C7 section closure note.
5. **audit doc marker** — A059-A063 는 untracked full_20260516 triage 출처 (tracked-file marker 의무 없음, spec §5.2). W2 가 tracked `docs/visual-reliability-audit/.../01-code-side-regex-audit.md` / `02-prompt-side-hygiene-audit.md` 에 shot_dependency_t2i row 존재 여부 grep → 있으면만 closure inline note (C3 N-5 패턴 — audit area 번호 ≠ 실제 site, 실제 위치 확인 후 marker). 없으면 roadmap §5.12 + fix-critical-1 C7 가 tracked closure marker.
- **W2 self-hash 금지** (C2 N-W4-2 / C3 정합) — closure docs 안 W2 자체 commit hash literal 없음. "W1-W2" / "W2 closure commit" wording. W1 hash 는 W1 commit 후 확정 — 기재 가능. W2 hash 는 push 후 external memory 기록.

### 4.4 W2 Pre-commit Gate

```bash
# Gate W2.1: closure docs staged 만 (code/test/prompt 변경 0)
git diff --cached --name-only   # §4.2 표의 4 docs (+ audit doc, 해당 시) 만

# Gate W2.2: W2 self-hash 부재 — closure docs 안 W2 commit hash literal 0 (wording "W1-W2"/"W2 closure commit")

# Gate W2.3: C7 integrated test 재확인 (backend 무변경)
PYTHONPATH=backend backend/.venv/bin/pytest backend/tests/integration/test_c7_shot_dependency_subject_kind.py -q
```

### 4.5 W2 Commit + W1-W2 range review + push

- commit message: `W2(c7-shot-dependency-subject-kind-v1): closure docs atomic — spec/plan status closed + roadmap §5.12 + fix-critical-1 C7 marker (path-limited)`
- commit 후 Codex W1-W2 range review 송신 → `APPROVED_FOR_PUSH`.
- `APPROVED_FOR_PUSH` 시 사용자 ask 0 즉시 push ([[feedback_push_no_user_ask]]).
- push 후 §5 Closure / external memory 기록 + Codex pane `clear` 요청.

## 5. Closure

**C7 v1 W1-W2 closed (2026-05-20+).** 전체 closure 종합 = spec §10.

### Commit chain
- **W1** `c8d2391` — producer v8 prompt-pack + version cascade + scene_context_loader envelope + `validate_keep_elements_entry` subject_kind consume + C7 test G1-G9 + blast radius (11 files, 726+/130-).
- **W1 fix-up 1** `e4ee3ed` — scene_context_loader `keep_elements_missing_key` message `schema v7`→`v8` (Codex W1 per-wave non-blocking residue).
- **W2** — closure docs atomic (spec/plan status closed + roadmap §5.12 + fix-critical-1 C7 marker + audit 01 §6 #15 closure note).

### Gate result
W1 Pre-commit Gate W1.1-W1.5 PASS (C7 integration G1-G9 9 passed, targeted 회귀 204 passed). W1.6 백엔드 전체 회귀 4056 passed — 잔여 5 failure 는 clean HEAD `1e8cc2a` baseline 동일 pre-existing (C7 무관, git stash 대조). C7 유발 신규 failure 0.

### Codex review trace
plan review `APPROVED_FOR_EXECUTION` → W1 ENTRY SANITY `APPROVED_TO_ENTER` → (fresh 세션) W1 entry sanity recheck `GO_FOR_W1_ATOMIC_EXECUTION` → W1 per-wave `APPROVED_FOR_W2_ENTRY` (non-blocking residue 1 → W1 fix-up 1) → W1-W2 range review `APPROVED_FOR_PUSH`.

### 함정
spec §10 함정 N-exec-1~3 참조 — W1.6 baseline 대조 효율화 / v8 prompt 예시 3-field 일관성 / plan §3.4 미열거 site (keep_elements_missing_key message) grep 의무.

### carry priority post-C7
fix-critical-1 진입 순서 LOCKED — 다음 = **C6 #10 detail_steps 색감-감정** (Tier β #5, roadmap §5.10).

## 6. Doctrine references

- [[feedback_llm_based_judgment]] — 4-Gate. C7 = Structured SOT Required (`subject_kind` enum emit) + Semantic Regex Ban (code-side lexicon validator 금지) + No Silent Fallback (`human_or_character_reference` fail-fast).
- [[feedback_no_vlm_dependency]] — NO VLM. C7 코드·테스트 VLM 의존 0.
- [[feedback_codex_mcp_discussion_workflow]] / [[feedback_codex_mcp_claude_mcp_response_trigger]] — 매 wave Codex per-wave review, tmux-bridge raw typing + prefix/suffix.
- [[feedback_no_user_ask_codex_only]] — OQ·결정 사용자 ask 0, Codex MCP 의논.
- [[feedback_push_no_user_ask]] — `APPROVED_FOR_PUSH` 즉시 push.
- [[feedback_channel_separation_4way]] — 4채널 fact source 구분.
- [[project_fix_critical_1_persistent]] — fix-critical-1 Tier β #4, C7 → C6 priority.
