---
title: C6 — detail_steps 색감-감정 closed-list 폐기 (generic instruction) v1 (fix-critical-1 Tier β #5)
date: 2026-05-20+
status: closed (C6 v1 W1-W2 atomic execution 완료 2026-05-20+ — Codex per-wave APPROVED; §10 Closure 참조)
roadmap_ref: docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md (Track B §5.10 Area #10) + docs/fix-critical-1/index.html C6 section (locked persistent guide)
fix_critical_doc_ref: docs/fix-critical-1/index.html C6 section (lines 911-965)
audit_ref: backend/tests/_audit_outputs/semantic_string_debt/full_20260516_0105/triage_report.md:94 (P034 — CONFIRMED P2 llm_closed_list_instruction) + production_app_findings_with_snippets.md:1918
prerequisites:
  - C1 perception_mode enum SOT v1 (closed 2026-05-20+) — perception_mode boundary preserve (detail_steps.py:2248-2254 consume + perception_mode.py:29-41 helper-owned `_PERCEPTION_GUIDES`). 변경 0.
  - C2 owned_object_usage[] echo v1 / C3 detail_steps focus rewrite v1 / C7 shot_dependency_t2i subject_kind v1 (closed 2026-05-20+, origin/main HEAD `c5d4520`) — HEAD anchor. 변경 0.
non_supersedes:
  - C9 L-7 body-light verb / C4 #8 background classifier / C5 #9 action segment SOT / C8 #7 잔여 sub-area split / C10 future structured carries.
---

# C6 — detail_steps 색감-감정 closed-list 폐기 v1

## 1. Purpose + Scope

### 1.1 Purpose

**audit P034 + roadmap §5.10 (Area #10)**: `backend/app/core/steps/detail_steps.py` 의 scene_detail per-shot user_prompt 조립 코드 안 `[조명/색감 판단]` instruction block 에 **한국어 감정 → 시각 색감 closed-list 매핑** 한 줄이 하드코딩되어 있다. audit triage row P034 (`triage_report.md:94`, CONFIRMED P2, kind=`llm_closed_list_instruction`):

```
- 감정에 맞는 색감(긴장=어둡고 대비 강한, 슬픔=탈색/청색, 분노=적색 등)
```

audit why: *"hardcoded semantic mapping of emotions to specific visual styles. This functions as a closed-list classifier that biases the LLM's creative decisions for arbitrary scenarios."*

이 줄은 producer LLM (scene_detail) 에게 `긴장→어둡고 대비 강한`, `슬픔→탈색/청색`, `분노→적색` 이라는 **고정 매핑**을 주입한다 — 시나리오마다 다른 정서·톤을 code 안 closed-list 가 선점하는 Track B **Prompt Closed-List Ban** 위반 (4-Gate). 동일 작품-비의존 원칙 (CLAUDE.md "작품 고유명사 코드/프롬프트에 넣지 말 것" 의 정서적 변형).

본 spec v1 = **closed-list 매핑 한 줄을 generic instruction 으로 치환** — emotion-drives-color 라는 *의도* 는 보존하되, 특정 감정→색 *고정 매핑* 을 code 에서 제거한다. Codex C6 entry sanity (`APPROVED_FOR_SPEC_DRAFTING`, 본 session) 의 narrow scope guard 흡수.

### 1.2 In-scope

- **`detail_steps.py:2327` 단일 줄 치환** — emotion→color closed-list 줄을 generic instruction (특정 감정→색 매핑 미주입) 으로 교체. bullet 형식 (`"- ...\n"`) 유지 — 형제 줄 2326/2328 과 정합.
- **C6 regression test 신설** — `backend/tests/core/test_scene_detail_analyze_one.py` 에 신규 test function 추가 (별도 test 파일 신설 아님 — Codex preferred). `call_structured` mock + `_analyze_one` 실행 + `mock_call.call_args.kwargs["user_prompt"]` 검사. **W1 동일 commit** (code edit + 그 canary 동시 landing).
- **W2 closure docs atomic**.

### 1.3 Out-of-scope (Codex C6 entry sanity scope guard 흡수)

- **옵션 (b) `color_palette_intent` enum 신설 — 기각** (§3.1). scene_detail 출력 schema `prompts/_base/scene_detail/30.202605200303/detail_schema.json:15` 에 이미 `camera_effect` 필드 (free string, description = `"카메라 구도 + 색감 (필수, 시나리오 derivation; closed-list 강제 X)"`) 가 색감 의도를 capture 한다. enum 신설은 (1) 그 free-string carrier 의 `"closed-list 강제 X"` design intent 와 정면 충돌, (2) detail_schema bump + version cascade + prompt-pack 신규 + test cascade 를 유발해 roadmap 의 `Cost small (단일 site)` 와 불일치.
- **scene_detail prompt-pack / schema / version**: v30 prompt-pack (`prompts/_base/scene_detail/30.202605200303/`), `detail_schema.json`, `SCENE_DETAIL_SCHEMA_VERSION`, `SCENE_DETAIL_PROMPT_VERSION`, `STEP_MANIFEST`, `version_registry.py` (`scene_detail` v30 / `1.30.0`), cp `schema_version` — **모두 변경 0**. C6 = code 안 user_prompt instruction string 1줄 변경 only, output shape 불변.
- **형제 instruction 줄 (boundary preserve)**: `detail_steps.py:2326` `"- 시간대(낮/밤/새벽/석양), 자연광/인공광, 색온도(따뜻한/차가운)\n"` + `:2328` `"- 핵심 인물/물체에 대한 조명 방향(역광/사광/정면광)\n\n"` — audit 미flag. 시간대·색온도·조명 방향은 **객관적 물리/촬영(cinematography) 범주** (scenario-independent, 정해진 사진 차원) 이지 감정→색 같은 scenario-dependent creative classifier 가 아니다. **변경 0**.
- **C1 perception_mode boundary**: `detail_steps.py:2248-2254` (`perception` consume + `get_perception_guide()` 호출) + `backend/app/core/perception_mode.py:29-41` helper-owned `_PERCEPTION_GUIDES` mapping — `_PERCEPTION_GUIDES` 값 안에 색감 언급 (`비현실적 색감`, `탈색된 색감` 등) 이 있으나 이는 **perception_mode (지각 모드) 영역** 으로 C6 (감정→색 closed-list) 와 차원이 다르다. fix-critical-1 index.html line 963 의 C1 boundary 줄번호 (`2223-2230`) 는 C1 closure 후 stale — 현재 위치는 `2248-2254` + `perception_mode.py:29-41`. **C6 변경 0** (boundary preserve).
- **`[조명/색감 판단]` block 의 header (`:2324`) / 도입 줄 (`:2325`)**: 유지 — block 자체 폐기 아님, closed-list 줄만 generic 치환.
- **`detail_steps.py:2257` `f"조명/색감: {light}\n"`**: `light` 변수 (shot_staging `lighting_mood`) 의 data interpolation — closed-list 아님, C6 무관 변경 0.
- **system.md v30 색감/조명 가이드** (Rule B 조명·색조 line 70-96 등): producer prompt-pack 영역, C6 미포함 변경 0.
- **VLM / live LLM / semantic regex**: 모두 ban.
- **C1·C2·C3·C7 변경 사항 / C4·C5·C8·C9·C10**: 별도 area.

## 2. W0 Evidence Inventory (live, HEAD `c5d4520`)

### 2.1 Violation site — `detail_steps.py:2324-2328` `[조명/색감 판단]` block

`SceneDetailStep._analyze_one()` (def `:1906`) 안 v4 shot-based mode 분기에서 `user_prompt += (...)` 로 조립되는 instruction block (`:2317-2329`):

```python
user_prompt += (
    "[카메라 포커싱]\n"
    ...                                                              # :2318-2323
    "[조명/색감 판단]\n"                                               # :2324
    "beat의 상태 변화와 씬 분위기를 고려하여 t2i_prompt에 조명과 색감을 반영하세요:\n"  # :2325
    "- 시간대(낮/밤/새벽/석양), 자연광/인공광, 색온도(따뜻한/차가운)\n"               # :2326
    "- 감정에 맞는 색감(긴장=어둡고 대비 강한, 슬픔=탈색/청색, 분노=적색 등)\n"        # :2327 ← C6 TARGET
    "- 핵심 인물/물체에 대한 조명 방향(역광/사광/정면광)\n\n"                        # :2328
)
```

| 줄 | 내용 | 분류 |
|----|------|------|
| `:2324` | `[조명/색감 판단]` header | 유지 |
| `:2325` | 도입 — "조명과 색감을 반영하세요" | 유지 (generic, 매핑 없음) |
| `:2326` | 시간대 / 자연광·인공광 / 색온도 | **boundary preserve** — 객관적 물리/촬영 범주 |
| `:2327` | **감정→색 closed-list** (긴장=.../슬픔=.../분노=...) | **C6 TARGET — generic 치환** |
| `:2328` | 조명 방향 (역광/사광/정면광) | **boundary preserve** — 객관적 촬영 범주 |

- block 은 system.md prompt-pack 이 아닌 **code 안에서 동적 조립되는 user_prompt instruction** — 즉 schema/prompt-pack 무관 code-side string.
- 위반은 `:2327` 단 한 줄. 나머지 4줄 불변.

### 2.2 Stale line number 정정 (4-layer source map)

| Layer | source | 명시 줄번호 | 실제 (HEAD `c5d4520`) |
|-------|--------|------------|----------------------|
| L1 | `docs/fix-critical-1/index.html` C6 (line 925) | `detail_steps.py:2305` | **`:2327`** (STALE) |
| L2 | roadmap §5.10 (line 427) | `detail_steps.py:2286-2291` | **`:2324-2328`** block, 위반 `:2327` (STALE) |
| L3 | `triage_report.md:94` P034 | `detail_steps.py:2286-2291` | **`:2324-2328`** (STALE) |
| L3' | `production_app_findings_with_snippets.md:1918` P034 snippet | `:2286-2291` | 동일 STALE |
| — | `index.html` line 963 C1 boundary 줄 | `detail_steps.py:2223-2230` | **`:2248-2254`** + `perception_mode.py:29-41` (C1 closure 후 STALE) |

W2 closure docs 에서 fix-critical-1 index.html C6 marker 갱신 시 실제 줄번호로 정정 (false source mapping 방지).

### 2.3 Test surface — `test_scene_detail_analyze_one.py`

`backend/tests/core/test_scene_detail_analyze_one.py` (443 line) 에 `_analyze_one` 단위 테스트가 이미 존재. 정착된 패턴:

```python
with patch("app.core.steps.detail_steps.call_structured") as mock_call:
    mock_call.return_value = _mock_llm_result(["ok"])
    step._analyze_one(SAMPLE_SEG, SAMPLE_SHOT, minimal_ctx, system="sys", schema={})
user_prompt = mock_call.call_args.kwargs["user_prompt"]
assert "[교차 샷 고정 요소]" in user_prompt
```

`test_analyze_one_injects_fixed_elements_into_user_prompt` (`:168`) 가 `_analyze_one` 실행 후 `user_prompt` 를 검사하는 직접 precedent. `[교차 샷 고정 요소]` (`detail_steps.py:2203`) 검증이 통과하므로 동일 v4 분기 안 `[조명/색감 판단]` block (`:2324-2328`) 도 `minimal_ctx` 경로에서 user_prompt 에 포함됨. C6 W1 test = 이 파일에 신규 function 추가 (`call_structured` mock → `_analyze_one` → `user_prompt` 검사).

### 2.4 audit / production test 참조

`[조명/색감 판단]` block / `감정에 맞는 색감` literal 을 참조하는 production test 0건 (grep 결과 audit artifact `production_app_findings_with_snippets.md` 외 0). closed-list 줄 치환에 따른 기존 test 회귀 surface 없음.

## 3. OQ Resolution (Codex C6 entry sanity 흡수)

### 3.1 OQ-C6 — fix 옵션 결정 (audit/roadmap 옵션 a/b/c)

**결정: 옵션 (a)/(c) hybrid — generic instruction 치환. (b) 기각.**

- **(a) 폐기 (LLM 색감 자유 결정)** + **(c) prompt template generic 이동**: 본 site 가 이미 code-built prompt instruction string 이므로 (a) 와 (c) 는 본질적으로 동일 — closed-list 매핑을 제거하고 generic instruction 만 남긴다. 채택. emotion-drives-color 의도는 도입 줄 `:2325` 와 치환 줄에 generic 형태로 보존, 특정 매핑만 제거.
- **(b) `color_palette_intent` enum 흡수**: 기각. (1) `detail_schema.json:15` `camera_effect` free string 이 이미 `"closed-list 강제 X"` 정책으로 색감 의도를 capture — enum (= 닫힌 list) 신설은 이 carrier 의 design intent 와 정면 충돌. (2) enum 신설 = detail_schema bump + `version_registry` (`scene_detail` v30→v31 / `1.30.0`→`1.31.0`) + prompt-pack 신규 디렉토리 + `STEP_MANIFEST` schema_version + test cascade — roadmap §5.10 의 `Cost small (단일 site)` / `Dependency independent` 와 불일치. Codex entry sanity 가 명시 승인. (doc 의 `"(b) Codex 권장"` 은 `camera_effect` 존재 미인지 상태 권고로 판단 — 재고 확정.)

### 3.2 OQ-C6-2 — 치환 wording

**결정: emotion-drives-color 의도 보존 + 특정 매핑 미주입 generic bullet.**

치환 줄 (W1 확정, Codex spec review preferred cleaner variant 흡수):

```python
"- 색감은 beat의 정서와 씬 분위기에서 직접 derive하고, 특정 정서에 고정 색조를 대응시키도록 강요하지 마세요\n"
```

- bullet 형식 (`"- ...\n"`) 유지 — 형제 줄 2326/2328 과 정합, 3-bullet 구조 보존.
- `긴장`/`슬픔`/`분노` 등 구체 감정 예시 토큰 미포함 + 감정→색 고정 매핑 미포함 — closed-list 0. (generic word `색감`/`정서` 는 design 상 잔존 — 이것이 emotion-drives-color *의도* 의 보존이다.)
- "색감은 ... 정서와 씬 분위기에서 직접 derive" = emotion-drives-color 의도 보존 — audit 가 문제삼은 것은 *고정 매핑* 이지 색감을 정서에서 끌어오라는 *의도* 가 아님. cleaner variant 는 도입 줄 `:2325` ("조명과 색감을 반영하세요") 와의 의미 중복도 감소시킨다 (Codex spec review WORDING).

### 3.3 OQ-C6-3 — test 배치

**결정: `test_scene_detail_analyze_one.py` 에 신규 function 추가 (별도 파일 신설 X).**

- Codex entry sanity preferred — `call_structured` mock + `mock_call.call_args.kwargs["user_prompt"]` 검사 패턴이 이 파일에 이미 정착 (§2.3).
- 별도 integration residue gate 도 acceptable 하나, audit artifact 의 historical literal 로 인한 broad false positive 위험.
- **source-level residue canary 는 `backend/app/core/steps/detail_steps.py` 한 파일로 path-scoped** — docs/audit history 제외. C6 regression test 자체가 old residue literal (`긴장=어둡고 대비 강한` 등) 을 absence-assert 대상으로 품게 되므로, 어떤 manual grep 이든 docs/audit history 와 **신규 test 파일** 을 제외하거나 split-string 상수 (`"긴장=" + "어둡고 대비"` 형태) 를 써야 한다 — test 파일 self-hit 방지 (Codex spec review IMPORTANT 1).

## 4. Invariants

### 4.1 No closed-list mapping invariant
치환 후 `detail_steps.py` source 와 runtime user_prompt 어디에도 감정→색 고정 매핑 (`긴장=어둡고 대비`, `슬픔=탈색`, `슬픔=청색`, `분노=적색`) 잔존 0.

### 4.2 Intent-preserve invariant
emotion-drives-color *의도* 는 보존 — 치환 줄은 색감을 정서/분위기에서 derive 하라는 generic 지시를 유지하되 특정 매핑을 주입하지 않는다.

### 4.3 Boundary line preserve invariant
`detail_steps.py:2326` (시간대/색온도) + `:2328` (조명 방향) instruction 줄은 글자 단위 불변. `[조명/색감 판단]` header (`:2324`) + 도입 줄 (`:2325`) 도 불변.

### 4.4 Output shape / version 불변 invariant
`t2i_variations` / scene_detail 출력 key·구조·schema 불변. prompt-pack / `detail_schema.json` / `SCENE_DETAIL_SCHEMA_VERSION` / `SCENE_DETAIL_PROMPT_VERSION` / `STEP_MANIFEST` / `version_registry` / cp `config_hash` 변경 0.

### 4.5 C1 boundary preserve invariant
`detail_steps.py:2248-2254` perception_mode consume + `perception_mode.py:29-41` `_PERCEPTION_GUIDES` 변경 0.

### 4.6 NO VLM / no live LLM invariant
C6 코드·테스트 어디에도 VLM 의존 / live LLM 호출 없음. C6 regression test = `call_structured` mock + source-level canary only.

### 4.7 No-enum invariant
C6 는 `color_palette_intent` 등 어떤 신규 schema field / enum 도 추가하지 않는다 — code-side prompt string 1줄 치환만.

## 5. W1-W2 Implementation Plan

### 5.1 W1 — closed-list 줄 치환 + C6 regression test (2 file modify, 1 atomic commit)

code edit 와 그 canary (G1-G5) 를 **동일 commit** 으로 묶는다 — code-only commit 금지.

**W1-A 대상**: `backend/app/core/steps/detail_steps.py` (modify)

**W1.1 — line 2327 치환**:
```python
# before (:2327)
"- 감정에 맞는 색감(긴장=어둡고 대비 강한, 슬픔=탈색/청색, 분노=적색 등)\n"
# after
"- 색감은 beat의 정서와 씬 분위기에서 직접 derive하고, 특정 정서에 고정 색조를 대응시키도록 강요하지 마세요\n"
```
나머지 block 4줄 (`:2324`/`:2325`/`:2326`/`:2328`) 불변.

**W1-B 대상**: `backend/tests/core/test_scene_detail_analyze_one.py` (modify — 신규 function 추가)

**W1.2 — C6 regression test 신설** — 신규 test function (예: `test_analyze_one_color_instruction_drops_emotion_closed_list`). `call_structured` mock + `_analyze_one` 실행 + `user_prompt` 검사 + `detail_steps.py` source-level canary. Gate G1-G5 (§7). no live LLM, NO VLM. 기존 file 명명/패턴 정합.

**W1 gate**:
- 신규 test PASS.
- `test_scene_detail_analyze_one.py` 전수 PASS (회귀 0).
- detail_steps / scene_detail 관련 test 전수 PASS.
- 백엔드 전체 회귀 — pre-existing failure 제외 동일 (clean HEAD `c5d4520` 대조; C7 closure 기록 = 5 pre-existing failure: text_cleaner ImportError / analysis_dispatch_service / prompt_service).
- repo-root cwd, `PYTHONPATH=backend backend/.venv/bin/python -m pytest` 의무.
- W1 = `detail_steps.py` modify + `test_scene_detail_analyze_one.py` modify → 1 atomic commit.

### 5.2 W2 — Closure docs atomic (path-limited)

- 본 spec frontmatter `status` → closed + §10 Closure 기재.
- C6 plan frontmatter `status` → closed + plan Closure section.
- roadmap `2026-05-16-track-b-semantic-debt-roadmap-design.md` §5.10 Area #10 → C6 closed entry (인접 C7 §5.12 의 Status/Fix applied/Boundary preserve/Cost/Closure verify 형식 정합).
- `docs/fix-critical-1/index.html` C6 marker — badge ✓ CLOSED + priority list C6→CLOSED / C9→NEXT + priority matrix row 5 status + **stale 줄번호 정정** (`:2305` → `:2327`).
- audit closure note — `triage_report.md` 는 git 추적되나 audit run 이 생성한 **generated audit-output** 이다 (`git ls-files` 확인). W2 는 generated audit output 을 변형하지 않는다 (explicit 선택 시에만 예외 — 본 v1 은 미선택). closure marker 대상 = tracked **narrative docs only** — roadmap §5.10 + fix-critical-1 index.html C6 + audit `02-prompt-side-hygiene-audit.md` / `03-llm-side-heuristic-audit.md` 의 carry follow-up 줄 (C6 항목) 갱신. audit `01-code-side-regex-audit.md` 에는 P034 row 가 없으므로 audit 01 marker 대상 아님 (C7 의 audit 01 §6 marker 와 다른 점). `production_app_findings_with_snippets.md` 는 untracked artifact — closure 대상 아님.
- **W2 self-hash 금지** — closure docs 안 W2 자체 commit hash literal 없음. "W1-W2" / "W2 closure commit" wording. 실제 hash 는 push 후 external memory 기록.

**W2 gate**: closure docs 정합 + W1-W2 range review.

## 6. Boundary Preserve

- `detail_steps.py:2326` 시간대/색온도 줄 + `:2328` 조명 방향 줄 + `:2324` header + `:2325` 도입 줄 — 변경 0.
- `detail_steps.py:2257` `f"조명/색감: {light}\n"` data interpolation — 변경 0.
- C1 perception_mode (`detail_steps.py:2248-2254` + `perception_mode.py:29-41` `_PERCEPTION_GUIDES`) — 변경 0.
- scene_detail prompt-pack v30 / `detail_schema.json` (`camera_effect` 포함) / 모든 version artifact — 변경 0.
- C2 owned path·sentinel / C3 `_strip_invalid_sids` helper / C7 keep_elements subject_kind — 변경 0.

## 7. Test Gates (G1-G5)

| Gate | 내용 |
|------|------|
| **G1** | closed-list residue 부재 — `_analyze_one` runtime `user_prompt` 에 `긴장=어둡고 대비`, `슬픔=탈색`, `분노=적색` substring 0. |
| **G2** | generic 치환 wording 존재 — runtime `user_prompt` 에 치환 줄 안정 substring marker (`특정 정서에 고정 색조를 대응시키도록`) 포함. 줄 전체 byte-for-byte assert 아님 (wording 동결 의도 아님 — Codex spec review). |
| **G3** | boundary 2326 보존 — runtime `user_prompt` 에 `색온도(따뜻한/차가운)` 포함 (시간대/색온도 줄 불변). |
| **G4** | boundary 2328 보존 — runtime `user_prompt` 에 `역광/사광/정면광` 포함 (조명 방향 줄 불변) + `[조명/색감 판단]` header 포함 (block 폐기 아님). |
| **G5** | source-level canary — `backend/app/core/steps/detail_steps.py` **한 파일** source 에 `긴장=어둡고 대비 강한` / `슬픔=탈색/청색` / `분노=적색` literal 0. canary 는 detail_steps.py 만 read — 신규 test 파일·docs·audit history 미포함 (test 파일은 absence-assert 위해 동 literal 을 품으므로 §3.3 split-string / path-scope guard 적용). |

## 8. Risk + Open Issues

- **R1 — 치환 줄과 도입 줄 `:2325` 의 의미 중복**: 도입 줄 `:2325` 가 이미 "조명과 색감을 반영하세요" 이므로 치환 줄과 약한 의미 중복 가능. cleaner variant ("색감은 ... beat의 정서와 씬 분위기에서 직접 derive ...") 채택으로 중복은 감소 (Codex spec review WORDING). 형제 3-bullet 구조 (`:2326`/`:2327`/`:2328`) 보존을 위해 bullet 자체는 유지 — block 구조 깨짐 방지. 의도된 결과.
- **R2 — generic 치환의 producer 영향**: closed-list 제거 후 producer LLM 이 감정→색 derivation 을 스스로 한다 — Track B "code 가 creative decision 을 선점하지 않는다" 원칙상 의도된 결과. `camera_effect` free-string + system.md v30 색감/조명 가이드가 producer-side 품질을 받친다. W1 백엔드 회귀로 downstream exact-match 의존 부재 확인.
- **OQ-잔여**: 없음 — Codex C6 entry sanity 5개 질문 모두 resolve (§3, §1.3, §2.2).

## 9. Doctrine references

- [[feedback_llm_based_judgment]] — 4-Gate. C6 = **Prompt Closed-List Ban** 적용 (감정→색 closed-list 매핑 폐기). open-world semantic (정서→색조) 판단은 producer LLM 소관, code 는 매핑 미주입.
- [[feedback_no_vlm_dependency]] — NO VLM. C6 코드·테스트 VLM 의존 0.
- [[feedback_codex_mcp_discussion_workflow]] / [[feedback_codex_mcp_claude_mcp_response_trigger]] — 매 wave Codex MCP per-wave review, tmux-bridge raw typing + prefix/suffix.
- [[feedback_no_user_ask_codex_only]] — OQ·결정 사용자 ask 0, Codex MCP 의논.
- [[feedback_channel_separation_4way]] — 4채널 fact source 구분.
- [[project_fix_critical_1_persistent]] — fix-critical-1 Tier β #5, C6 → C9 priority.

## 10. Closure (2026-05-20+)

### 10.1 W1-W2 commit chain
- **W1 `9f64928`** — `detail_steps.py:2327` 감정→색 closed-list 한 줄을 generic instruction (`"- 색감은 beat의 정서와 씬 분위기에서 직접 derive하고, 특정 정서에 고정 색조를 대응시키도록 강요하지 마세요\n"`) 으로 치환 + `test_scene_detail_analyze_one.py` C6 regression test 2건 append (G1-G4 runtime user_prompt + G5 source canary). 2 file modify, 48+/1-. block sibling 4줄 `:2324`/`:2325`/`:2326`/`:2328` byte-for-byte 불변.
- **W2 closure commit** — closure docs atomic 6 docs (spec/plan status closed + roadmap §5.10 + fix-critical-1 index.html C6 marker + audit 02/03 carry follow-up 줄).

### 10.2 Gate result
- W1.1+W1.2 — `test_scene_detail_analyze_one.py` 17 passed / 1 skipped (신규 C6 test 2건 PASS, 회귀 0).
- W1.3 — detail_steps/scene_detail regression 203 passed / 0 failed.
- W1.4 — source canary `Gate W1.4 OK` (old closed-list literal 3종 부재 + generic 치환 줄 + block header + boundary 2326/2328 존재).
- W1.5 — 백엔드 전체 4058 passed / 5 failed / 37 skipped. 5 failure 전부 pre-existing — clean HEAD `c5d4520` git stash baseline 재실행 동일 5건 fail 확정 (test_analysis_dispatch_service / test_prompt_service / test_text_cleanup ImportError ×3, C7 closure 기록과 일치). C6 유발 신규 failure 0.

### 10.3 Codex review trace
C6 entry sanity `APPROVED_FOR_SPEC_DRAFTING` → spec review `NEEDS_REVISION_NARROW` (BLOCKING/NARROW 1 §5.2 `triage_report.md` tracked 사실 정정 + IMPORTANT 1 grep scope guard + WORDING cleaner variant) → spec amend 1 (6 sites) → re-review `APPROVED_FOR_PLAN` → plan review `APPROVED_FOR_EXECUTION` (1-pass) → W1 entry sanity `GO_FOR_W1_ATOMIC_EXECUTION` → W1 per-wave `APPROVED_FOR_W2_ENTRY` → W1-W2 range review.

### 10.4 함정 / lesson learned
- **N-1** — spec §5.2 가 `triage_report.md` 를 untracked 로 전제 (false). `git ls-files` 확인 결과 tracked (audit run 이 생성한 generated audit-output). closure marker 대상 = tracked narrative docs only (roadmap / fix-critical-1 / audit 02·03 carry line), generated audit output 미변형. `production_app_findings_with_snippets.md` 는 실제 untracked.
- **N-2** — C6 regression test 가 old residue literal 을 absence-assert 하므로 test 파일 source 가 joined literal 을 품으면 manual grep self-hit. split-string 상수 (`"긴장=" + "..."`) 로 회피 — test + Gate W1.4 heredoc 양쪽 적용. G5 source canary 는 `detail_steps.py` 한 파일 path-scoped.
- **N-3** — fix-critical-1 index.html (`:2305`) / roadmap·audit (`:2286-2291`) 줄번호 전부 stale — 실제 site `:2327`. index.html line 963 C1 boundary 줄번호 (`:2223-2230`) 도 C1 closure 후 stale (실제 `:2248-2254` + `perception_mode.py:29-41`). W2 index.html marker 에서 site 줄번호 정정.

### 10.5 carry priority post-C6
C9 L-7 body-light verb (다음 진입) → C4 #8 background classifier → C5 #9 action segment SOT → C8 #7 잔여 sub-area split → C10 future structured carries.
