# review-codex-1 수정 계획서 보강판 (Codex)

> 기준일: 2026-04-21
> 원본 문서: `docs/review-codex-1/11-fix-plan.md`
> 근거 문서: `docs/review-codex-1/01~10`
> 목적: 원본 계획서의 이슈 맵과 우선순위는 유지하되, 실제 실행 가능성이 더 높도록 순서, 품질 게이트, 병렬 범위, PR 분할 기준을 재정의한다.

---

## 0. 결론

원본 `11-fix-plan.md`는 이미 좋은 계획서다. 범위가 넓고, 실측 수치를 기반으로 하고, 문서/백엔드/프런트/테스트/제품 관점을 한 문서 안에 묶었다는 점은 유지해야 한다.

보강이 필요한 부분은 세 가지다.

1. **Phase 완료 조건이 서로 다른 종류의 작업을 너무 크게 묶고 있다.**
   특히 `P2 완료 = repo 전체 pytest green`은 현재 구조상 과하다. 이미지/variation 응답 drift 일부는 `P4` 이후에야 안정적으로 닫히기 때문이다.
2. **대형 리팩토링 항목의 PR slicing과 rollback 기준이 부족하다.**
   `scene_image_service.py` 5-way split, `steps.py` route 축소, frontend hotspot 분해는 "한 번에 크게" 가면 회귀 범위를 읽기 어렵다.
3. **일부 프런트/테스트 작업은 더 앞당겨 병렬화할 수 있다.**
   `F32` 테스트 harness, `F29/F30` 저위험 lint blocker 제거는 `P4` 완료까지 기다릴 필요가 없다.

이 보강판의 핵심 판단은 다음과 같다.

- 원본의 `F01~F32` 문제 분류는 유지한다.
- 원본의 `P0 -> P6` 큰 순서도 유지한다.
- 다만 운영 관점에서 실제로는 **7개의 실행 wave와 6개의 프로그램 gate**로 관리해야 한다.
- `repo-wide green`은 조기 phase 종료 조건이 아니라 **후반부 프로그램 gate**로 옮겨야 한다.
- frontend는 "대형 컴포넌트 분해"보다 먼저 **테스트 harness와 lint blocker 제거**를 착수해야 한다.

---

## 1. 원본 계획서 리뷰

### 1.1 강점

| 항목 | 평가 | 코멘트 |
|---|---|---|
| 범위 커버리지 | 강함 | 문서, 런타임, 테스트, 제품 목표까지 모두 포함한다. |
| 증거 기반 | 강함 | `637/56/2/1`, `987.79 kB`, `77 errors`, step 49개 등 현재 기준선이 실측에 맞다. |
| 우선순위 감각 | 강함 | 문서 정합 -> 실행 경로 수렴 -> startup/test -> projection -> 이미지 분해 -> 프런트 정리의 큰 방향은 타당하다. |
| 위험 인식 | 보통 이상 | 높은 리스크 작업을 별도 표시했다. |
| 문서 가치 | 강함 | 팀이 "무엇이 문제인가"를 공유하기에 충분하다. |

### 1.2 보강 필요 지점

| 항목 | 현재 상태 | 보강 방향 |
|---|---|---|
| phase exit 정의 | 일부가 과도하게 큼 | phase gate와 program gate를 분리한다. |
| 테스트 전략 | full pytest green이 너무 이른 시점에 배치됨 | backend lane을 core/startup/image/full로 분리한다. |
| frontend 착수 시점 | P5가 너무 뒤에 몰려 있음 | `F32`, `F29`, `F30`은 조기 병렬 트랙으로 이동한다. |
| 대형 리팩토링 방식 | 5-way split 등 big-bang 표현이 강함 | facade-first, extract-second, cleanup-last 순으로 나눈다. |
| 병렬 전략 | 가능하다고만 적혀 있음 | write set 기준으로 병렬 허용 범위를 명시한다. |
| rollback 기준 | 암묵적 | 각 wave마다 "같이 하지 말 것"과 rollback 포인트를 둔다. |

### 1.3 유지해야 할 판단

다음 판단은 원본 그대로 유지하는 것이 맞다.

1. `P0`를 먼저 수행해야 한다. 지금 저장소는 문서와 실제 구현의 숫자/계약이 다르기 때문에, 여기서 기준선을 잠그지 않으면 이후 작업이 계속 엇나간다.
2. `/analyze`와 `/steps/run-all` 이중화는 가장 먼저 줄여야 한다. 공개 API 계약이 둘이면 운영 진단도 둘로 갈라진다.
3. startup/test coupling은 `P4`, `P5`보다 먼저 정리해야 한다. 그렇지 않으면 대형 리팩토링의 회귀를 신뢰성 있게 측정할 수 없다.
4. projection failure 가시화는 제품 신뢰성 관점에서 별도 phase로 다뤄야 한다.
5. `P6`는 delivery-critical path가 아니라 제품화 backlog로 두는 것이 맞다.

### 1.4 수정해야 할 판단

다음은 원본에서 가장 먼저 수정해야 하는 운영 판단이다.

1. **`P2 완료 = repo-wide pytest 0 failed`는 제거한다.**
   이 조건은 `F19`의 image/variation cluster까지 포함하면 `P4`와 강하게 결합된다.
2. **`F19`는 하나의 phase가 아니라 cluster별로 분해해야 한다.**
   문서/manifest drift, startup coupling, text/variation drift, image API drift는 서로 다른 시점에 닫혀야 한다.
3. **`F32`는 `P5`의 마지막이 아니라 중간 안전망으로 앞당긴다.**
   테스트가 없는 상태에서 `SceneVariationCard.tsx`와 `Entities.tsx`를 쪼개면 검증 비용이 너무 커진다.
4. **`F22/F23/F24`는 "파일 수 줄이기"보다 "공식 진입점 고정"이 먼저다.**
   facade를 먼저 고정하지 않으면 호출자와 테스트가 계속 흔들린다.

---

## 2. 이 보강판의 실행 원칙

### 2.1 고정 원칙

1. **Repair before redesign**  
   먼저 현재 계약을 고정하고, 그 다음 구조를 더 예쁘게 만든다.

2. **One runtime boundary change per PR**  
   한 PR 안에서 바꾸는 런타임 경계는 하나만 허용한다.

3. **Gate by lane, not by hope**  
   phase 종료는 "느낌상 안정적"이 아니라 lane 단위 검증으로 판단한다.

4. **Facade first**  
   대형 서비스 분해는 facade를 먼저 고정하고, 내부 구현을 빼내는 순서로 진행한다.

5. **Docs are part of done**  
   계약을 바꿨다면 문서와 generated baseline도 같은 PR에서 같이 갱신한다.

### 2.2 정의된 완료 기준

각 wave의 완료는 아래 네 조건을 동시에 만족해야 한다.

1. 코드 변경 완료
2. 해당 wave 전용 검증 lane green
3. 관련 문서 또는 generated baseline 갱신
4. rollback 포인트가 명시됨

### 2.3 이번 보강판에서 새로 도입하는 관리 단위

- `Wave`: 실제 구현 작업 묶음
- `Gate`: 다음 wave로 넘어가기 위한 프로그램 수준 통과 조건
- `Lane`: 테스트/검증 실행 단위

---

## 3. 강화된 프로그램 구조

### 3.1 원본 F 이슈를 wave로 재배치

| Wave | 대응 범위 | 핵심 목적 |
|---|---|---|
| Wave 0 | `F01~F07` | 사실표와 문서 기준선 잠금 |
| Wave 1 | `F08~F12`, `F20`, `F21` | 공개 분석 경로와 step orchestration 수렴 |
| Wave 2 | `F13~F18` | startup/config/bootstrap 경계 분리 |
| Wave 3 | `F19` cluster A/B/C, `F32`, `F29`, `F30` | 테스트 lane 정규화와 frontend 안전망 확보 |
| Wave 4 | `P3` 전체 | projection/sync 실패 가시화 |
| Wave 5 | `F22~F25`, `F19` cluster D | 이미지 도메인 2차 분해와 image lane 안정화 |
| Wave 6 | `F26~F28`, `F31`, `F32` 확장 | frontend hotspot 분해와 성능/품질 마감 |
| Wave 7 | `P6` | 제품/운영 고도화 백로그 구체화 |

### 3.2 프로그램 gate

| Gate | 통과 조건 | 의미 |
|---|---|---|
| `G0` | 문서 숫자와 generated manifest가 일치 | 이제부터 "현재 상태"를 한 목소리로 말할 수 있음 |
| `G1` | 프런트 분석 시작 경로 단일화, `STEP_MANIFEST` 직접 소비 축소 | 런타임 계약 수렴 완료 |
| `G2` | import-time DB side effect 제거, lifespan 전환, insecure default fail-fast | startup 경계가 통제 가능해짐 |
| `G3` | backend core/startup lane green, frontend smoke lane 생성 | 대형 분해 전에 최소 안전망 확보 |
| `G4` | projection failure가 API/UI에서 보임, repair 경로 존재 | 운영 관측성 확보 |
| `G5` | image lane green, facade 정리 완료, full backend regression green | 대형 backend 구조 변경 종료 |
| `G6` | frontend lint green, smoke/hook tests green, build 경고 허용 수준 정리 | 배포 가능성 판단 지점 |

### 3.3 release 관점에서의 의미

- `G3` 통과: 내부 팀이 기능을 계속 쓰면서 refactor를 이어갈 수 있는 상태
- `G4` 통과: 운영 중 silent stale 상태를 줄일 수 있는 상태
- `G6` 통과: 파일럿 또는 외부 사용 검토가 가능한 상태

---

## 4. Wave 상세 계획

### 4.1 Wave 0 - 사실표 lock

- 대응 이슈: `F01~F07`
- 목적: 문서, manifest, 테스트 결과가 같은 숫자를 가리키도록 고정한다.
- 핵심 산출물:
  - `backend/scripts/dump_step_manifest.py`
  - `docs/architecture/_step_manifest.generated.md`
  - subset 결과와 repo 전체 결과를 분리한 품질 섹션
  - `architecture-refactor-final` 상단 아카이브 배너
- 검증:
  - `python backend/scripts/dump_step_manifest.py | diff - docs/architecture/_step_manifest.generated.md`
  - `rg "36단계|48단계" docs/architecture docs/architecture-refactor-final docs/product-roadmap-discussion.md`
- 병렬 가능:
  - step manifest generator 작성
  - 문서 교정
  - archive/banner 정리
- 같이 하지 말 것:
  - step manifest 의미를 바꾸는 런타임 변경
  - `/analyze` 제거 같은 API refactor
- exit:
  - `G0` 통과

### 4.2 Wave 1 - 공개 계약 수렴

- 대응 이슈: `F08`, `F09`, `F10`, `F11`, `F12`, `F20`, `F21`
- 목적: 분석 시작 경로와 step orchestration 소비 경로를 단일화한다.
- 핵심 산출물:
  - frontend의 공식 분석 시작 훅 단일화
  - `/analyze`, `/reanalyze-scenes`는 thin shim + deprecated metadata만 유지
  - `StepRunner`와 `steps.py`가 `step_catalog` 중심으로 소비
  - `_needs_presync` 하드코딩 제거, manifest metadata화
  - `clean_text`, `VariationRecommender` compat drift 정리
- 권장 순서:
  1. 새 공식 훅 또는 service 추가
  2. 호출자 전환
  3. legacy shim 축소
  4. manifest metadata 승격
  5. `steps.py` route/service 분리
- 검증:
  - `rg "/analyze|/reanalyze-scenes" frontend/src`
  - `rg "STEP_MANIFEST" backend/app/core/step_runner.py backend/app/api/v1/steps.py`
  - core step 테스트와 target API smoke
- 병렬 가능:
  - frontend call-site 전환
  - `step_catalog` accessor 보강
- 순차 강제:
  - `_needs_presync` metadata 추가 후 route/service 교체
  - `steps.py` 축소는 catalog 소비 정리 후 진행
- 같이 하지 말 것:
  - `main.py` lifespan refactor
  - image response shape 변경
- exit:
  - `G1` 통과

### 4.3 Wave 2 - startup/config 경계 정리

- 대응 이슈: `F13`, `F14`, `F15`, `F16`, `F17`, `F18`
- 목적: import와 초기화, 개발 편의와 운영 정책, runtime과 bootstrap을 분리한다.
- 핵심 산출물:
  - `main.py`의 import-time `init_db()` 제거
  - `on_event("startup")`에서 lifespan으로 전환
  - default user bootstrap CLI 분리
  - `ConfigDict` 전환
  - `ENVIRONMENT=prod` fail-fast 보안 정책
  - `test_pipeline_e2e`의 startup coupling 제거
- 검증:
  - `python -c "import app.main"` 시 side effect 없음
  - startup 관련 deprecation warning 제거
  - `backend/tests/test_pipeline_e2e.py` green
- 병렬 가능:
  - `ConfigDict` 전환
  - bootstrap CLI 작성
- 순차 강제:
  - lifespan 전환 이후 fixture 정리
  - prod fail-fast는 CI/dev env 확인 후 병합
- 같이 하지 말 것:
  - `steps.py` 대형 refactor와 동일 PR
  - image service 분해와 동일 PR
- exit:
  - `G2` 통과

### 4.4 Wave 3 - 테스트 lane 정규화와 frontend 안전망

- 대응 이슈: `F19` cluster A/B/C, `F32`, `F29`, `F30`
- 목적: 테스트 실패를 해석 가능한 lane으로 나누고, frontend refactor를 지탱할 최소 안전망을 만든다.
- `F19` 재분류:
  - cluster A: step count/order/manifest drift
  - cluster B: scene/outlook/entity legacy contract drift
  - cluster C: text cleanup/variation constructor drift
  - cluster D: image API/response shape drift -> Wave 5로 이관
- 핵심 산출물:
  - backend lane 분리: `core`, `startup`, `image`, `full`
  - cluster A/B/C 정리 또는 제거
  - `vitest` + `RTL` 기반 smoke/hook lane
  - `useEventSource.ts` 삭제 또는 제품 경로 통합
  - `ImageGalleryModal.tsx`의 `set-state-in-effect` 정리
- 검증:
  - backend `core` lane green
  - backend `startup` lane green
  - frontend `npm run test` 최소 smoke green
  - frontend lint에서 `set-state-in-effect` 0
- 병렬 가능:
  - backend test cluster 정리
  - frontend test harness 구축
  - 저위험 lint blocker 제거
- 같이 하지 말 것:
  - 대형 frontend hotspot 분해
  - image service extraction
- exit:
  - `G3` 통과

### 4.5 Wave 4 - projection/sync 관측성 강화

- 대응 범위: 원본 `P3`
- 목적: checkpoint 성공과 DB projection 실패를 운영에서 구별 가능하게 만든다.
- 핵심 산출물:
  - `SceneStillSyncService` 분해
  - `sync_status`와 error detail 저장
  - repair endpoint
  - frontend 상태 배지
- 검증:
  - sync 실패가 API 응답과 UI에서 보임
  - repair API로 재동기화 가능
  - projection stale이 silent 상태로 남지 않음
- 병렬 가능:
  - backend sync refactor
  - frontend badge 반영
- 같이 하지 말 것:
  - image domain 대형 분해와 동일 PR
- exit:
  - `G4` 통과

### 4.6 Wave 5 - 이미지 도메인 2차 분해

- 대응 이슈: `F22`, `F23`, `F24`, `F25`, `F19` cluster D
- 목적: 이미지 도메인의 공식 진입점을 먼저 고정하고, 이후 내부 구현을 분리한다.
- 핵심 판단:
  - `scene_image_service.py` 5-way split은 가능하지만, 한 번에 끝내려 하면 회귀 해석이 어려워진다.
  - 따라서 `facade 고정 -> 내부 함수 이동 -> dead shim 제거 -> 테스트 갱신` 순서가 맞다.
- 권장 하위 단계:
  1. `F25` dead code 제거
  2. `scene_image_service.py` facade 인터페이스 고정
  3. variation/validation/persistence/provenance 내부 이동
  4. `image_service.py` shim 호출자 정리
  5. `reference_image_service.py` generation/edit/persistence 분리
  6. image lane 테스트와 response shape 재고정
- 검증:
  - image/variation lane green
  - facade 외 호출자 없음
  - `scene_image_service.py`, `image_service.py`, `reference_image_service.py`가 각자 좁은 책임만 가짐
- 병렬 가능:
  - `reference_image_service` 분리
  - image lane 테스트 재작성
- 순차 강제:
  - facade 고정 전 호출자 대규모 정리 금지
  - response shape freeze 전 frontend variation editor 변경 금지
- 같이 하지 말 것:
  - `SceneVariationCard.tsx` 대형 분해
  - `/images` API 응답 스키마 변경과 call-site refactor를 같은 PR에 넣기
- exit:
  - `G5` 통과

### 4.7 Wave 6 - frontend hotspot 분해와 성능 마감

- 대응 이슈: `F26`, `F27`, `F28`, `F31`, `F32` 확장
- 목적: frontend의 대형 파일과 정적 품질 부채를 마감한다.
- 핵심 산출물:
  - `SceneVariationCard.tsx` 분해
  - `Entities.tsx`, `EpisodeStills.tsx` 타입/에러 정리
  - code splitting 및 lazy route 도입
  - frontend smoke를 hook/component 테스트까지 확장
- 권장 순서:
  1. test harness가 있는 상태에서 hotspot 분해
  2. 타입/에러 통합
  3. route/component split
  4. 최종 lint 정리
- 검증:
  - `npm run lint` green
  - `npm run test` green
  - `npm run build` warning 해석 가능 수준
- 병렬 가능:
  - `Entities.tsx`
  - `EpisodeStills.tsx`
  - code splitting
- 같이 하지 말 것:
  - backend image response shape 변경
  - startup/config 변경
- exit:
  - `G6` 통과

### 4.8 Wave 7 - 제품/운영 고도화

- 대응 범위: 원본 `P6`
- 목적: 현업이 신뢰하고 수정 가능한 제품 흐름을 만든다.
- 핵심 산출물 후보:
  - provenance timeline
  - snapshot/restore UX
  - 작업자 중심 HiTL
  - cross-episode canon
- 성격:
  - delivery-critical path가 아니다.
  - 인터뷰나 운영 피드백을 기반으로 backlog화해야 한다.

---

## 5. Lane 설계

### 5.1 backend lane

| Lane | 목적 | 예시 검증 범위 |
|---|---|---|
| `B0-docs` | 문서와 generated baseline 정합 | manifest dump, docs drift 검색 |
| `B1-core` | manifest/catalog/step orchestration | `test_step_manifest_v3.py`, `test_step_catalog.py`, applicability, step execution service |
| `B2-startup` | app lifecycle, fixture, bootstrap | `test_pipeline_e2e.py`, startup 관련 fixture |
| `B3-image` | variation/image API와 response shape | `test_images_api.py`, `test_variation_pipeline.py`, image 서비스별 테스트 |
| `B4-full` | 저장소 전체 회귀 | `pytest backend/tests -q` |

### 5.2 frontend lane

| Lane | 목적 | 예시 검증 범위 |
|---|---|---|
| `F0-static` | lint/ts 품질 | `npm run lint` |
| `F1-smoke` | 주요 페이지 렌더와 기본 상호작용 | dashboard, episodes, episode detail, stills |
| `F2-hooks` | mutation/query invalidation | `useStillMutations`, `useRunAllSteps` |
| `F3-build` | bundle/build 상태 | `npm run build` |

### 5.3 이 보강판의 중요한 수정

원본 계획서와 달리, 이 보강판은 아래를 분명히 한다.

1. `B4-full` green은 `Wave 2`가 아니라 `Wave 5` 종료 지점에 둔다.
2. `F1-smoke`와 `F2-hooks`는 `Wave 3`부터 만든다.
3. `F0-static`의 최종 green은 `Wave 6`이지만, `set-state-in-effect` 같은 구조 위반은 `Wave 3`에서 먼저 제거한다.

---

## 6. 병렬 실행 지침

### 6.1 병렬 허용 원칙

병렬 작업은 "기능적으로 독립"보다 **write set이 분리**되어야 한다.

### 6.2 권장 병렬 묶음

| 병렬 묶음 | 허용 이유 |
|---|---|
| Wave 0 문서 교정 + manifest generator | 런타임 코드와 충돌하지 않음 |
| Wave 1 frontend call-site 전환 + backend catalog accessor 보강 | 파일 셋이 거의 겹치지 않음 |
| Wave 2 config/bootstrap 정리 + startup fixture 정리 | 관련성은 높지만 write set 분리가 가능함 |
| Wave 3 backend test cluster 정리 + frontend test harness | repo 하위 트리가 완전히 다름 |
| Wave 4 backend sync 가시화 + frontend badge | 계약만 고정되면 병렬 가능 |
| Wave 5 reference 분리 + image lane 테스트 갱신 | facade가 고정된 이후 가능 |
| Wave 6 `Entities.tsx` + `EpisodeStills.tsx` | 컴포넌트 write set 분리 가능 |

### 6.3 병렬 금지 묶음

| 금지 조합 | 이유 |
|---|---|
| `steps.py` refactor + `main.py` lifecycle 변경 | 실패 원인을 분리하기 어려움 |
| image facade 변경 + frontend variation editor 분해 | 응답 스키마와 UI 상태 둘 다 흔들림 |
| startup fail-fast 보안 변경 + CI 환경 미정 상태 | red 원인 판별이 어려움 |
| legacy shim 삭제 + 호출자 마이그레이션 미완료 | 회귀가 즉시 발생함 |

---

## 7. PR 분할 권장안

원본 계획서의 공수 감각은 대체로 맞지만, 리뷰/문서/회귀 확인까지 포함하면 PR 단위는 더 잘게 쪼개는 편이 안전하다.

| PR | 범위 | 예상 gate |
|---|---|---|
| PR-01 | Wave 0 전체: manifest generator + 문서 교정 | `G0` |
| PR-02 | frontend 분석 시작 경로 단일화 | Wave 1 일부 |
| PR-03 | `step_catalog` accessor 보강 + `StepRunner` direct import 제거 | Wave 1 일부 |
| PR-04 | `_needs_presync` metadata화 + `steps.py` service 분리 | `G1` |
| PR-05 | lifespan 전환 + import-time side effect 제거 | Wave 2 일부 |
| PR-06 | bootstrap CLI + `ConfigDict` + prod fail-fast | `G2` |
| PR-07 | backend test lane 분리 + `F19` cluster A/B/C 정리 | Wave 3 일부 |
| PR-08 | frontend `vitest`/RTL + `F29/F30` | `G3` |
| PR-09 | projection sync status/repair API | `G4` |
| PR-10 | `F25` dead code 제거 + image facade scaffolding | Wave 5 일부 |
| PR-11 | `scene_image_service` 내부 추출 | Wave 5 일부 |
| PR-12 | `reference_image_service` 내부 추출 + image lane 정리 | `G5` |
| PR-13 | frontend hotspot 분해 | Wave 6 일부 |
| PR-14 | code splitting + lint 마감 | `G6` |

---

## 8. 수정된 완료 기준

### 8.1 phase exit와 program gate를 구분해야 하는 이유

원본 계획서에서 가장 위험한 부분은, phase 하나가 너무 많은 종료 조건을 동시에 떠안고 있다는 점이다.

예를 들어:

- `P2`는 lifecycle, bootstrap, config, insecure default, startup test, repo full green까지 묶여 있다.
- 그러나 repo full green에는 image/variation drift가 남아 있어 `P4`와 결합된다.

따라서 이 보강판은 아래처럼 바꾼다.

| 기존 판단 | 수정 판단 |
|---|---|
| `P2 완료 = full pytest green` | `P2 완료 = lifecycle/config/startup lane green`, full green은 `G5` |
| `P5 시작은 P4 완료 후` | frontend safety lane은 `Wave 3`에서 먼저 시작 |
| `scene_image_service 5-way split` | `facade 고정 -> 내부 추출 -> 테스트 재고정` 3단계 |
| `lint 0`는 P5의 단일 목표 | 구조 위반 제거는 조기, 전체 lint green은 최종 |

### 8.2 revised effort

| Wave | 원본 감각 | 보강판 감각 |
|---|---|---|
| Wave 0 | 2~3일 | 2~3일 |
| Wave 1 | 5.5일 | 4~6일 |
| Wave 2 | 6.5일 | 3~4일 |
| Wave 3 | 원본에 분산 | 5~7일 |
| Wave 4 | 3일 | 3~4일 |
| Wave 5 | 11.5일 | 12~15일 |
| Wave 6 | 10.5일 | 6~8일 |
| 총합 | 약 42일 | 약 35~47일 |

설명:

- `Wave 2`가 짧아진 것은 `F19` 대부분을 분리했기 때문이다.
- `Wave 3`가 새로 생기면서 test normalization 비용이 명시화됐다.
- `Wave 5`는 facade-first/추출/테스트 재고정까지 포함하므로 여전히 가장 비싸다.

---

## 9. 최우선 착수 순서

### 9.1 바로 시작할 6개 작업

1. `F01~F07`을 원본 계획대로 먼저 닫고 `G0`를 만든다.
2. frontend의 `/analyze` call-site를 `/steps/run-all` 기준으로 수렴시킨다.
3. `StepRunner`와 `steps.py`의 `STEP_MANIFEST` 직접 소비를 줄이고 `_needs_presync`를 metadata로 올린다.
4. `main.py`의 import-time side effect와 startup bootstrap을 분리한다.
5. backend test lane을 `core/startup/image/full`로 나눈다.
6. frontend `vitest`/RTL와 `F29/F30` 저위험 lint blocker를 먼저 넣는다.

### 9.2 아직 시작하면 안 되는 작업

1. `scene_image_service.py` 5-way split
2. `SceneVariationCard.tsx` 대형 분해
3. image API response shape 재설계
4. `P6` 성격의 제품 UX 확장

이 네 가지는 각각 의미가 있지만, `G3` 이전에 시작하면 회귀 비용이 커진다.

---

## 10. 최종 권고

원본 `11-fix-plan.md`는 폐기할 문서가 아니다. 오히려 문제 목록과 우선순위의 기반 문서로 유지하는 편이 맞다. 다만 실제 실행은 이 보강판처럼 관리해야 한다.

핵심만 남기면 아래 다섯 문장으로 요약된다.

1. 원본의 `F01~F32` 분류는 유지한다.
2. 운영상 실제 실행은 `P0~P6`가 아니라 `Wave 0~7`과 `G0~G6`로 관리한다.
3. `repo-wide pytest green`은 조기 목표가 아니라 후반부 gate다.
4. frontend는 테스트 harness와 구조 위반 제거를 먼저 시작해야 한다.
5. 이미지 도메인 분해는 facade-first 없이 크게 들어가면 실패 확률이 높다.

---

_이 문서는 `11-fix-plan.md`를 대체하려는 것이 아니라, 그 계획서를 실제로 실행 가능한 프로그램 계획으로 보강하기 위해 작성한 병행 문서다._
