---
title: C6 — detail_steps 색감-감정 closed-list 폐기 v1 implementation plan (fix-critical-1 Tier β #5)
date: 2026-05-20+
status: closed (C6 v1 W1-W2 atomic execution 완료 2026-05-20+ — Codex per-wave APPROVED; §5 Closure 참조)
spec_ref: docs/superpowers/specs/2026-05-20-c6-detail-steps-color-emotion-v1-design.md (status APPROVED_FOR_PLAN)
roadmap_ref: docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md (Track B §5.10 Area #10)
fix_critical_doc_ref: docs/fix-critical-1/index.html C6 section
prerequisites:
  - C6 spec v1 APPROVED_FOR_PLAN (Codex spec amend 1 re-review — BLOCKING/NARROW 1 §5.2 + IMPORTANT 1 grep scope + WORDING cleaner variant 흡수; status closed only at W2 closure-docs commit).
  - C1 perception_mode enum SOT v1 / 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 / C4 #8 / C5 #9 / C8 #7 / C10 (fix-critical-1 잔여 area).
---

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

## 1. Purpose + Spec Reference

C6 = `detail_steps.py:2327` 의 한국어 감정→색감 closed-list 매핑 (`긴장=어둡고 대비 강한, 슬픔=탈색/청색, 분노=적색 등`) 한 줄을 generic instruction 으로 치환. spec OQ-C6 = (a)/(c) hybrid generic — emotion-drives-color *의도* 보존, 특정 감정→색 *고정 매핑* 제거. 옵션 (b) `color_palette_intent` enum 기각 (schema 의 `camera_effect` free-string 이 이미 색감 capture, `"closed-list 강제 X"` design intent).

- spec: `docs/superpowers/specs/2026-05-20-c6-detail-steps-color-emotion-v1-design.md` §1-§10.
- 2-wave: **W1** = `detail_steps.py` modify + `test_scene_detail_analyze_one.py` modify (1 atomic commit — code edit + 그 canary 동시 landing) / **W2** = closure docs atomic.
- HEAD anchor = `c5d4520` (origin/main, C7 v1 closed).
- schema / prompt-pack / version artifact 변경 0 (spec §1.3 / §4.4).

## 2. Plan Iter Trace

- iter 0 (2026-05-20+): plan v1 drafting.
- iter 1 (2026-05-20+): Codex plan review `APPROVED_FOR_EXECUTION` (1-pass, amend 0) — W1.1 old/new 줄 / W1.2 test 설계 (minimal_ctx block 도달 + function-local import) / split-string self-hit 방지 / W2 6-doc scope 모두 승인. narrow execution guard (W1 staged = exactly 2 file) 흡수.

## 3. W1 — line 2327 치환 + C6 regression test

### 3.1 Pre-W1 Entry Sanity

- W1 진입 전 Codex W1 entry sanity 받을 것 (file edit 0 상태에서 송신).
- 진입 직전 read: 승인된 spec + 본 plan + `detail_steps.py` 현재 상태 (line drift 확인 — line 2327 anchor 가 현 HEAD `c5d4520` 와 일치하는지) + `test_scene_detail_analyze_one.py` 현재 상태.
- HEAD = `c5d4520` verify.

### 3.2 W1 File Operations (2 file modify, 1 atomic commit)

| op | file |
|----|------|
| modify | `backend/app/core/steps/detail_steps.py` |
| modify | `backend/tests/core/test_scene_detail_analyze_one.py` |

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

### 3.3 detail_steps.py — line 2327 치환 (W1.1)

`SceneDetailStep._analyze_one()` 안 `[조명/색감 판단]` block (`:2324-2328`) 의 단일 줄 치환. old (현 `:2327`, 16-space indent — `user_prompt += (` block 안 string literal):

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

new:

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

- block 의 나머지 4줄 (`:2324` header / `:2325` 도입 / `:2326` 시간대·색온도 / `:2328` 조명 방향) **글자 단위 불변**.
- bullet 형식 (`"- ...\n"`) 유지 — 형제 줄 2326/2328 정합, 3-bullet 구조 보존.
- line 2327 literal 은 file 내 유일 (grep 확인) — Edit old_string 유일성 OK.

### 3.4 test_scene_detail_analyze_one.py — C6 regression test (W1.2)

`backend/tests/core/test_scene_detail_analyze_one.py` 끝 (현 `:443` 이후) 에 신규 section header + 2 test function append. 기존 section 구조 (`# N) ...`) 비파괴. no live LLM, NO VLM.

**self-hit 방지** (spec §3.3 / Codex spec review IMPORTANT 1): test 가 old residue literal 을 absence-assert 하므로 split-string 상수 (`"긴장=" + "..."`) 를 써 test 파일 source 가 joined literal 을 품지 않게 한다. append 내용:

```python


# ──────────────────────────────────────────────────────────────────────
# N) C6 — [조명/색감 판단] 감정→색 closed-list 폐기 (fix-critical-1 Tier β #5)
# ──────────────────────────────────────────────────────────────────────


def test_analyze_one_color_instruction_drops_emotion_closed_list(step, minimal_ctx):
    """C6: [조명/색감 판단] block 의 감정→색 closed-list 폐기 — generic instruction.

    audit P034 — detail_steps.py:2327 의 감정→색 고정 매핑(긴장=.../슬픔=.../분노=...)
    제거 + generic instruction 치환 회귀 가드. old residue 는 split-string 상수로
    검사 (test 파일 self-hit 방지, spec §3.3).
    """
    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"]

    # G1 — closed-list residue 부재 (감정→색 고정 매핑)
    assert ("긴장=" + "어둡고 대비") not in user_prompt
    assert ("슬픔=" + "탈색") not in user_prompt
    assert ("분노=" + "적색") not in user_prompt
    # G2 — generic 치환 wording 존재 (안정 substring marker)
    assert "특정 정서에 고정 색조를 대응시키도록" in user_prompt
    # G3 — boundary 2326 보존 (시간대/색온도 줄)
    assert "색온도(따뜻한/차가운)" in user_prompt
    # G4 — boundary 2328 보존 (조명 방향 줄) + block header
    assert "역광/사광/정면광" in user_prompt
    assert "[조명/색감 판단]" in user_prompt


def test_analyze_one_color_instruction_source_has_no_emotion_closed_list():
    """C6 G5 — detail_steps.py source 한 파일에 감정→색 closed-list literal 0.

    path-scoped canary — detail_steps.py 만 read (신규 test 파일·docs·audit
    history 미포함, spec §7 G5). old literal 은 split-string 으로 검사.
    """
    from pathlib import Path

    import app.core.steps.detail_steps as _detail_steps_mod

    src = Path(_detail_steps_mod.__file__).read_text(encoding="utf-8")
    assert ("긴장=" + "어둡고 대비 강한") not in src
    assert ("슬픔=" + "탈색/청색") not in src
    assert ("분노=" + "적색") not in src
```

- `step` / `minimal_ctx` / `SAMPLE_SEG` / `SAMPLE_SHOT` / `_mock_llm_result` 는 이미 file 내 정의 (fixture / module-level) — 재사용.
- `[조명/색감 판단]` block 은 `_analyze_one` 의 `if shot_info:` → `if staging:` 경로 안 무조건 append. `minimal_ctx.staging_map = {"1_1": {...}}` 이 `if staging:` 진입 보장 — block 도달 (G4 의 `"[조명/색감 판단]" in user_prompt` 가 자체 검증).
- G5 의 `from pathlib import Path` / `import ... _detail_steps_mod` 는 function-local import — module-level import 줄 무변경 (최소 footprint).

### 3.5 W1 Pre-commit Gate

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

```bash
# Gate W1.1: C6 신규 test 2건 PASS
PYTHONPATH=backend backend/.venv/bin/python -m pytest backend/tests/core/test_scene_detail_analyze_one.py -q -k "color_instruction"

# Gate W1.2: test_scene_detail_analyze_one.py 전수 PASS (회귀 0)
PYTHONPATH=backend backend/.venv/bin/python -m pytest backend/tests/core/test_scene_detail_analyze_one.py -q

# Gate W1.3: detail_steps / scene_detail 관련 regression
PYTHONPATH=backend backend/.venv/bin/python -m pytest backend/tests -k "detail_steps or scene_detail" -q

# Gate W1.4: 치환 증명 — executable assertion (grep -c 0-hit exit 1 false-fail 회피, python assert)
PYTHONPATH=backend backend/.venv/bin/python - <<'PY'
from pathlib import Path
src = Path("backend/app/core/steps/detail_steps.py").read_text(encoding="utf-8")
# old closed-list literal 부재 (split-string — 본 gate heredoc self-hit 방지)
assert ("긴장=" + "어둡고 대비 강한") not in src, "감정→색 closed-list 잔존(긴장)"
assert ("슬픔=" + "탈색/청색") not in src, "감정→색 closed-list 잔존(슬픔)"
assert ("분노=" + "적색") not in src, "감정→색 closed-list 잔존(분노)"
# generic 치환 줄 존재 + block header / boundary 줄 보존
assert "특정 정서에 고정 색조를 대응시키도록" in src, "generic 치환 줄 부재"
assert "[조명/색감 판단]" in src, "block header 손실"
assert "색온도(따뜻한/차가운)" in src, "boundary 2326 손실"
assert "역광/사광/정면광" in src, "boundary 2328 손실"
print("Gate W1.4 OK")
PY

# Gate W1.5: 백엔드 전체 회귀 (pre-existing failure 제외 동일 — C7 closure 기록 = 5 pre-existing
#            failure: text_cleaner ImportError / analysis_dispatch_service / prompt_service, C6 무관)
PYTHONPATH=backend backend/.venv/bin/python -m pytest backend/tests -q
```

- Gate W1.4 가 AssertionError 없이 `Gate W1.4 OK` 출력해야 W1 commit 가능.
- Gate W1.5 의 신규 failure 가 C6 변경 기인이면 commit 금지 → 원인 수정. pre-existing 여부는 clean HEAD `c5d4520` git stash 대조로 확정.

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

- commit message: `W1(c6-detail-steps-color-emotion-v1): detail_steps.py:2327 감정→색 closed-list 폐기 — generic instruction 치환 + C6 regression test (2 file modify)`
- staged: `backend/app/core/steps/detail_steps.py` + `backend/tests/core/test_scene_detail_analyze_one.py` 만 (`git add` 명시 경로 — global add 금지).
- 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 변경 0.

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

| op | file |
|----|------|
| modify | `docs/superpowers/specs/2026-05-20-c6-detail-steps-color-emotion-v1-design.md` |
| modify | `docs/superpowers/plans/2026-05-20-c6-detail-steps-color-emotion-v1-implementation.md` |
| modify | `docs/superpowers/specs/2026-05-16-track-b-semantic-debt-roadmap-design.md` |
| modify | `docs/fix-critical-1/index.html` |
| modify | `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/02-prompt-side-hygiene-audit.md` |
| modify | `docs/visual-reliability-audit/2026-05-14-semantic-string-routing-debt-audit/03-llm-side-heuristic-audit.md` |

generated audit-output (`triage_report.md`) 미변형 / `production_app_findings_with_snippets.md` (untracked) 미포함 (spec §5.2).

### 4.3 W2 closure docs 내용

1. **spec** — frontmatter `status` → closed + §10 Closure (commit chain / Gate result / Codex review trace / 함정).
2. **plan** — frontmatter `status` → closed + §5 Closure.
3. **roadmap** — §5.10 Area #10 → C6 closed entry (인접 C7 §5.12 의 Status / Fix applied / Boundary preserve / Cost / Closure verify 형식 정합).
4. **fix-critical-1 index.html** — C6 marker: badge `✓ CLOSED` + priority list `C6 → CLOSED` / `C9 → NEXT` + priority matrix row 5 status 갱신 + **stale 줄번호 정정** (현재 site row 의 `detail_steps.py:2305` → `:2327`).
5. **audit 02** (`02-prompt-side-hygiene-audit.md`) — carry follow-up 줄 의 C6 항목 갱신 (C6 closed 반영).
6. **audit 03** (`03-llm-side-heuristic-audit.md`) — carry follow-up 줄 의 C6 항목 갱신 (C6 closed 반영).

- **W2 self-hash 금지** — closure docs 안 W2 자체 commit hash literal 없음. "W1-W2" / "W2 closure commit" wording. W1 hash 는 W1 commit 후 확정 — closure docs 에 W1 hash 기재 가능. W2 hash 는 push 후 external memory 기록.

### 4.4 W2 Pre-commit Gate

```bash
# Gate W2.1: closure docs 6 file staged 만 (code/test 변경 0)
git diff --cached --name-only   # 위 6 docs 만

# Gate W2.2: W2 self-hash 부재 — closure docs 안 W2 commit hash literal 0
#            (W2 commit 전이라 hash 미존재 — wording "W1-W2"/"W2 closure commit" 확인)

# Gate W2.3: backend 무변경 재확인 (venv python + PYTHONPATH)
PYTHONPATH=backend backend/.venv/bin/python -m pytest backend/tests/core/test_scene_detail_analyze_one.py -q -k "color_instruction"
```

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

- commit message: `W2(c6-detail-steps-color-emotion-v1): closure docs atomic — spec/plan status closed + roadmap §5.10 + fix-critical-1 C6 marker + audit 02/03 carry follow-up (6 docs 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` 요청 (controller(claude %1) 세션 대상 — claude 는 자기 세션만, [[feedback_never_clear_codex_session]]).

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

C6 v1 W1-W2 atomic execution 완료. 종합 closure (commit chain / Gate / Codex trace / 함정 N-1~N-3) = spec `2026-05-20-c6-detail-steps-color-emotion-v1-design.md` §10.

- **W1 `9f64928`** — `detail_steps.py:2327` 감정→색 closed-list 폐기 + generic instruction 치환 + `test_scene_detail_analyze_one.py` C6 regression test 2건 (2 file modify, 48+/1-). Codex per-wave `APPROVED_FOR_W2_ENTRY`.
- **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). Codex W1-W2 range review.
- Gate W1.1-W1.5 PASS — 백엔드 4058 passed / 5 failed 전부 pre-existing (clean HEAD `c5d4520` git stash baseline 대조 확정).
- plan iter trace = §2 (iter 1 Codex plan review 1-pass APPROVED_FOR_EXECUTION, amend 0).

## 6. Doctrine references

- [[feedback_llm_based_judgment]] — 4-Gate (Prompt Closed-List Ban). C6 = 감정→색 closed-list 매핑 폐기.
- [[feedback_no_vlm_dependency]] — NO VLM. C6 코드·테스트 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 β #5, C6 → C9 priority.
