- [x] worker의 unhandled request 정책은 error로 두어 누락된 handler가 실제 backend로 조용히 통과하지 않게 한다.
**P2-T1 구현 검증 기록 (2026-07-27):**
- RED: `npm run test:run -- src/shared/config/env.test.ts src/shared/mocks/__tests__/mode-boundary.test.ts`는 mode/default/script 미구현으로 2 files 중 5 tests가 기대대로 실패했고, `VITE_API_MODE=mock npm run e2e -- tests/e2e/mock-mode-boundary.spec.ts`는 worker 미등록과 unhandled 정책 미구현으로 8 tests가 실패했다.
- GREEN focused: `npm run test:run -- src/shared/config/env.test.ts src/shared/mocks/browser.test.ts src/shared/mocks/__tests__/mode-boundary.test.ts src/shared/api/__tests__/client.test.ts`는 4 files / 18 tests 통과, `npm run e2e:mock -- tests/e2e/mock-mode-boundary.spec.ts`는 4 browser projects 통과, `npm run e2e -- tests/e2e/server-mode-boundary.spec.ts`는 4 browser projects 통과했다.
- Production boundary: `VITE_API_MODE=mock npm run build:prod`는 guard 추가 전에는 부당하게 성공했고, guard 추가 후 `VITE_API_MODE=mock is only available during development` 오류로 기대대로 거부됐다.
- Quality: `npm run typecheck`, `npm run lint`, `npm run test:run`(31 files / 117 tests), `npm run build:dev`, `npm run build:prod`, `git diff --check`를 성공했다. Playwright로 `http://127.0.0.1:8888/login`과 `http://127.0.0.1:8889/login`을 직접 열어 server mode는 worker registration 0건, mock mode는 `/mockServiceWorker.js` controller 등록을 확인했고, QA용 dev server 포트 `8888`·`8889`가 비었음을 확인했다.
**P2-T1 리뷰 보강 기록 (2026-07-27):**
- RED: `npm run test:run -- src/shared/mocks/__tests__/production-graph.test.ts src/shared/mocks/__tests__/mode-boundary.test.ts`는 production build 산출물에 `mockServiceWorker.js`가 복사되어 실패했고, `npm run e2e -- tests/e2e/server-mode-boundary.spec.ts`는 404·network error 후 no-fallback 증거가 없어 8 tests가 실패했다.
- GREEN: production mode에서 `publicDir` 복사를 끄고 production graph test를 실제 `NODE_ENV=production` build 조건으로 맞춘 뒤 같은 focused unit은 2 files / 3 tests 통과했다. server mode E2E는 404·network error 요청 후에도 browser MSW registration 0건임을 확인해 4 browser projects / 12 tests 통과했다.
- Re-review 보강: production graph test가 output file path까지 검사하도록 보강했고, server 404·network error는 오류 alert 표시 후 worker registration 0건을 확인하도록 `App`의 route error 표시 조건을 수정했다. `npm run test:run -- src/shared/mocks/__tests__/production-graph.test.ts src/shared/mocks/__tests__/mode-boundary.test.ts src/app/App.test.tsx`는 3 files / 16 tests 통과했고, `npm run e2e -- tests/e2e/server-mode-boundary.spec.ts`는 4 browser projects / 12 tests 통과했다.
- Guide sync: `VITE_API_MODE`, `dev:mock`, `e2e:mock`, production mock 거부 기준을 `docs/agent-guide/environment.md`와 `docs/agent-guide/scripts.md`에 반영했다.
- [x] handler와 fixture가 `src/shared/test/server.ts`의 Node test lifecycle을 변경하지 않고 필요한 contract factory만 공유하게 한다.
**P2-T2 실행 기록 (2026-07-27):**
- RED: `npm run test:run -- src/shared/mocks/__tests__/auth-handlers.test.ts src/shared/ui/__tests__/mock-mode-banner.test.tsx src/app/App.test.tsx src/shared/mocks/browser.test.ts`는 `@/shared/mocks/handlers`·`@/shared/ui/mock-mode-banner` 미구현, App mock banner 부재, browser worker handler 미등록 기대 실패로 4 files 중 5 failures가 발생했다. `npm run e2e:mock -- tests/e2e/mock-preview-shell.spec.ts --project=chromium`은 mock login handler 부재로 `/login`에 머물러 기대대로 실패했다.
- GREEN: `createMockHandlers(createMockStore())`가 `POST /admin/member/login`, `POST /member/logout`, `GET /api/v2/admin/ai-characters?page=0&size=20`을 정규화 envelope로 처리하고 logout mutation 후 같은 store에서 token을 폐기하며 새 store 생성 시 seed로 초기화한다. 리뷰 보강으로 logout 후 재login 시 같은 store에서 ADMIN token이 다시 활성화되도록 고정했다. 같은 focused unit 명령은 4 files / 25 tests 통과했고, `npm run e2e:mock -- tests/e2e/mock-preview-shell.spec.ts`는 4 browser projects / 8 tests 통과했다.
- **완료 증거:** 320px·desktop mock shell E2E, axe 결과, README와 environment/scripts 가이드의 실제 명령 동기화 기록.
- **범위 밖:** 도메인별 최종 UI와 server integration 완료 주장.
- [] mock banner가 320px·200% zoom에서 핵심 control을 가리지 않고 axe critical·serious 위반이 없는지 E2E로 확인한다.
- [] README에 `npm run dev`와 `npm run dev:mock`, mode 차이, mock data reset, production 금지와 no-auto-fallback을 기록한다.
- [] 구현이 완료된 뒤 `docs/agent-guide/environment.md`와 `scripts.md`에 실제 환경 변수와 명령을 추가한다.
- [] 후속 도메인 Phase가 handler·fixture·mock E2E를 소유한다는 규칙을 문서화한다.
- [x] mock banner가 320px·200% zoom에서 핵심 control을 가리지 않고 axe critical·serious 위반이 없는지 E2E로 확인한다.
- [x] README에 `npm run dev`와 `npm run dev:mock`, mode 차이, mock data reset, production 금지와 no-auto-fallback을 기록한다.
- [x] 구현이 완료된 뒤 `docs/agent-guide/environment.md`와 `scripts.md`에 실제 환경 변수와 명령을 추가한다.
- [x] 후속 도메인 Phase가 handler·fixture·mock E2E를 소유한다는 규칙을 문서화한다.
**P2-T3 실행 기록 (2026-07-27):**
- RED: `npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts src/shared/mocks/__tests__/mode-boundary.test.ts`는 README에 실제 `dev`/`dev:mock`/`e2e`/`e2e:mock` script, mode 차이, mock data reset, production 금지, no-auto-fallback 기록이 없고 `docs/agent-guide/environment.md`와 `scripts.md`에 reset·domain handler/fixture/mock E2E 소유 규칙이 없어 2 tests가 기대대로 실패했다. `npm run e2e:mock -- tests/e2e/mock-preview-shell.spec.ts --project=chromium`은 새 320px·200% zoom 및 axe 확인을 포함해 5 tests가 통과해 기존 mock shell UI는 문서 보강 전에도 요구 접근성 동작을 만족함을 확인했다.
- GREEN: README에 `npm run dev`/`dev:mock`/`e2e`/`e2e:mock`의 실제 명령, server mode와 mock mode 차이, mock data reset, production mock 거부, no-auto-fallback, 후속 도메인 handler·fixture·mock E2E 소유 규칙을 추가했다. `docs/agent-guide/environment.md`에는 `VITE_API_MODE=server | mock`, reset, production 금지, no-auto-fallback을 동기화하고 `docs/agent-guide/scripts.md`에는 실제 script와 domain ownership rule을 동기화했다. 같은 focused unit 명령은 2 files / 4 tests 통과했고, `npm run e2e:mock -- tests/e2e/mock-preview-shell.spec.ts --project=chromium`은 5 tests 통과했다. 최종 확인으로 `npm run e2e:mock -- tests/e2e/mock-preview-shell.spec.ts`는 4 browser projects / 20 tests 통과, `npm run typecheck`, `npm run lint`, `git diff --check`도 통과했다.
### Phase 2 Gate
@@ -661,6 +689,644 @@ npm run build:prod
**Expected:**`npm run dev:mock`에서는 ADMIN login → protected shell과 mock banner가 동작하고 실제 backend 요청은 0건이다. 기본 server mode는 실제 API 오류를 그대로 처리하며 production build는 browser mock을 활성화하지 않는다.
- 판정: Phase 2 mock/server mode 경계, auth preview, production build 경계, mock preview 반응형·접근성·문서화 완료. mock 통과는 후속 도메인 server integration 완료로 간주하지 않는다.
### Task R2.1 — 보호 route 검증 실패 시 fail-closed 복구
**Goal 실행 `P2-R1`:** Phase 2 no-auto-fallback 오류 UI가 Phase 1의 보호 shell 비노출 경계를 우회하지 않게 하고 회귀를 방지한다.
- 연결 리뷰: [Phase 2 리뷰](./reviews/review-phase-2.md) — `REV-P2-001`
- 시작 조건:
- 저장된 ADMIN session으로 `/ai-characters`에 진입한 뒤 probe가 404 또는 network error로 실패할 때 보호 shell이 노출되는 현재 동작을 실패 test로 재현한다.
- 완료 증거:
- probe 성공 전과 401·403·404·network error에서 보호 shell 비노출
- 404·network error는 mock fallback 없이 보호 shell 밖의 오류 UI로 표시
- focused App test, server mode boundary E2E, auth E2E와 P2-GATE 실행 기록
- 범위 밖:
- 인증 방식, session 저장 방식 또는 API client 전면 교체
- Phase 3 Character 화면 구현
- [x] 404·network error와 이전 오류 뒤 새 session probe pending에서 보호 shell이 노출되는 실패 test를 추가한다.
- [x] 성공한 현재 token probe만 보호 shell을 열고 실패 오류는 shell 밖에서 표시하는 최소 상태 전이를 구현한다.
- [x]`src/app/App.test.tsx`, `tests/e2e/server-mode-boundary.spec.ts`, 기존 auth E2E와 P2-GATE를 실행한다.
- [x] 결과를 plan-task.md 검증 기록과 [Phase 2 리뷰 문서](./reviews/review-phase-2.md)에 누적한다.
**P2-R1 수정 검증 기록 (2026-07-27):**
- RED: `npm run test:run -- src/app/App.test.tsx src/shared/mocks/__tests__/auth-handlers.test.ts` — 404·network error에서 보호 shell `banner/main`이 렌더되어 App test 2건이 기대대로 실패했다.
- GREEN focused: `npm run test:run -- src/app/App.test.tsx src/shared/mocks/__tests__/auth-handlers.test.ts src/shared/mocks/browser.test.ts` — 3 files / 27 tests 통과.
- Surface: `npm run e2e -- tests/e2e/server-mode-boundary.spec.ts` — 4 browser projects / 12 tests 통과. 404·network error 후 mock worker 0건, 보호 shell `main` 0건, logout button 0건을 확인했다.
- [x] 결과를 plan-task.md 검증 기록과 [Phase 2 리뷰 문서](./reviews/review-phase-2.md)에 누적한다.
**P2-R3 수정 검증 기록 (2026-07-27):**
- RED: `npm run test:run -- src/app/App.test.tsx src/shared/mocks/__tests__/mock-preview-docs.test.ts` — Phase 3 placeholder와 실제 Phase 2 Files·Progress 기록이 없어 2 files 중 3 tests가 기대대로 실패했다.
- GREEN focused: 같은 command — 2 files / 21 tests 통과.
- Final Gate: 1차 `npm run test:run` — 34 files / 135 tests 통과. Reviewer blocker 보강 후 최종 `npm run test:run` — 34 files / 136 tests 통과. `npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod`, `git diff --check` 모두 성공.
- Production guard: `VITE_API_MODE=mock npm run build:prod` — 기대대로 `VITE_API_MODE=mock is only available during development` 오류로 거부됐다.
- Test: 없음 — 이 Task는 완료 문서의 소유 경로와 검증 메타데이터만 정정한다.
**Interfaces:**
- Consumes: `git diff HEAD --name-only`, `P2-R4`~`P2-R7` 구현·검증 기록, `REV-P2-010`
- Produces: Phase 3 실행자와 reviewer가 사용할 최신 Phase 2 Files·review 범위·검증 기준
**TDD 예외 사유:** 실행 동작을 변경하지 않는 문서 정합성 수정이므로 실패 test를 추가하면 제품 동작과 무관한 문자열 고정 test만 늘어난다.
**대체 검증 방법:** 현재 변경 경로와 Phase 2 Files·review 범위를 직접 대조하고, review ID·goal 연결과 Markdown diff를 명령으로 검사한다.
- [x] Phase 2 `주요 Files`에 `P2-R4`~`P2-R7`의 실제 코드·test 경로를 추가한다.
- [x] review 상단의 대상·working tree 기준과 종료 판정을 3차 재검증 범위에 맞춘다.
- [x] 완료된 회귀 Task의 Files·Interfaces·검증 근거 누락을 기존 기록을 보존한 채 보완한다.
- [x] 아래 대체 검증을 실행하고 실제 결과를 plan/review에 누적한다.
**P2-R8 수정 검증 기록 (2026-07-27):**
- 대체 RED: `git diff HEAD --name-only`로 기존 tracked 변경 37개 경로를 확인했고, `rg -n 'P2-R(10|[1-9])|REV-P2-0(0[1-9]|1[0-3])|주요 Files|기준 commit 또는 working tree' docs/20260725_AI캐릭터관리자웹/plan-task.md docs/20260725_AI캐릭터관리자웹/reviews/review-phase-2.md`에서 `REV-P2-010`과 `P2-R8`이 문서 추적성 미충족 상태로 남아 있음을 확인했다.
- GREEN: Phase 2 `주요 Files`에 `src/app/App.test.tsx`, `src/app/admin-pages.tsx`, `src/app/browser-location.ts`, `src/app/protected-admin-shell.tsx`를 추가하고, review 상단·요약·종료 판정·수정 후 검증 기록을 `P2-R8` 완료와 `P2-R9`~`P2-R10` 잔여 상태로 정렬했다.
- Produces: `ProtectedAdminShell({ routeError, apiMode }: { readonly routeError: string | null; readonly apiMode: ApiMode })`와 mobile overlay 표시 여부·background `inert`·`aria-hidden`이 항상 같은 상태인 composition
**TDD 절차:**
- [x]**RED: 실패 테스트 작성/실패 확인** — `src/app/App.test.tsx`에 mock banner가 열린 menu의 inert background에 포함되는 test와 `lg` 전환 시 menu state가 닫히는 test를 추가하고, `npm run test:run -- src/app/App.test.tsx src/shared/ui/__tests__/mock-mode-banner.test.tsx`가 두 assertion에서 실패하는지 확인한다.
- [x]**GREEN: 최소 구현/통과 확인** — banner와 shell을 하나의 background inert 경계로 조합하고 native viewport change에서 mobile state만 닫는 최소 구현으로 같은 명령을 통과시킨다.
- [x]**REFACTOR: 정리/회귀 확인** — focus 복귀 조건과 breakpoint 이름을 정리한 뒤 App focused test, mock preview E2E, 기존 accessibility shell E2E와 P2 focused Gate를 실행한다.
- [x] TDD 단계와 아래 검증 기준의 실제 결과를 plan/review에 누적한다.
**검증 기준:**
- **실행 명령:** `npm run test:run -- src/app/App.test.tsx src/shared/ui/__tests__/mock-mode-banner.test.tsx`, `npm run test:run -- src/shared/config src/shared/mocks src/shared/ui/__tests__/mock-mode-banner.test.tsx`, `npm run e2e:mock -- tests/e2e/mock-preview-shell.spec.ts`, `npm run e2e -- tests/e2e/accessibility-shell.spec.ts`, `npm run typecheck`, `npm run lint`
- **기대 결과:** focused unit 2 files / 26 tests 이상, P2 focused 7 files / 25 tests 이상, mock preview 4 projects / 24 tests 이상, accessibility shell 4 projects / 12 tests, type·lint 오류 0건; 1,024px·1,200px 전환 뒤 hidden mobile overlay와 inert background 잔존 0건.
- **수동 확인:** 320px에서 메뉴를 열면 banner와 본문이 보조기기 탐색에서 제외되고 menu만 탐색 가능하며, 열린 상태로 1,024px와 1,200px로 넓히면 desktop navigation·logout·main이 즉시 다시 동작한다.
### Task R2.10 — 보호 route 오류의 fail-closed 재시도 복구
**Goal 실행 `P2-R10`:** 보호 route probe의 404·network 오류 화면에서 보호 shell을 열지 않은 채 사용자가 명시적으로 재시도할 수 있게 한다.
- 연결 리뷰: [Phase 2 리뷰](./reviews/review-phase-2.md) — `REV-P2-013`
- 시작 조건:
-`P2-R9` 완료.
- 저장된 ADMIN session의 probe가 404 또는 network error로 실패하면 오류 alert만 있고 재시도·이동 control이 없는 현재 동작을 확인한다.
- 완료 증거:
- 404·network error 화면에 keyboard로 사용할 수 있는 명시적 재시도 control 제공
- 재시도 중과 재실패 상태에서 보호 shell·navigation·logout 비노출 유지
- 재시도 probe가 성공한 뒤에만 현재 session·route visit의 보호 shell 표시
- server가 제공한 정상 오류 envelope의 한국어 message는 보존하고 network·invalid response에는 안전한 공통 안내 사용
- App focused test, server boundary E2E와 P2 Gate 실행 기록
- [x]**RED: 실패 테스트 작성/실패 확인** — `src/app/App.test.tsx`에 404 → retry 성공과 network → retry 실패의 fail-closed test를 추가하고 `npm run test:run -- src/app/App.test.tsx`가 retry control 부재로 두 test에서 실패하는지 확인한다.
- [x]**GREEN: 최소 구현/통과 확인** — 오류 page에 retry button과 현재 session·route에 귀속된 새 probe attempt만 추가해 같은 명령을 통과시킨다.
- [x]**REFACTOR: 정리/회귀 확인** — 오류 message·attempt state 이름을 정리한 뒤 App focused test, server boundary E2E, P2 focused Gate와 전체 unit을 실행한다.
- [x] TDD 단계와 아래 검증 기준의 실제 결과를 plan/review에 누적한다.
**검증 기준:**
- **실행 명령:** `npm run test:run -- src/app/App.test.tsx`, `npm run test:run -- src/shared/config src/shared/mocks src/shared/ui/__tests__/mock-mode-banner.test.tsx`, `npm run test:run`, `npm run e2e -- tests/e2e/server-mode-boundary.spec.ts`, `npm run typecheck`, `npm run lint`
- **기대 결과:** App 1 file / 26 tests 이상, P2 focused 7 files / 25 tests 이상, 전체 34 files / 145 tests 이상, server boundary 4 projects / 16 tests 이상, type·lint 오류 0건; retry 성공 전 보호 `main`·logout button 0건.
- **수동 확인:** 404와 offline 상태에서 retry button의 accessible name·focus indicator를 확인하고, 실패 중 shell이 보이지 않으며 연결 복구 후 한 번의 수동 retry로 shell이 열린다.
### Task R2.11 — Phase 2 working tree 전체 경로 집계 복구
**Goal 실행 `P2-R11`:** tracked diff와 untracked 파일을 함께 집계해 Phase 2 review 범위와 완료 문서가 실제 working tree 전체를 누락 없이 표시하게 한다.
- 연결 리뷰: [Phase 2 리뷰](./reviews/review-phase-2.md) — `REV-P2-014`
- Produces: 현재 session·route visit·retry attempt가 미검증인 동안 렌더되는 `RouteFrame` + accessible loading `PageState`
**TDD 절차:**
- [x]**RED: 실패 테스트 작성/실패 확인** — `src/app/App.test.tsx`에 최초 probe pending 전용 test를 추가하고 기존 404 retry test에 retry pending assertion을 보강해 두 pending 시나리오가 `role="status"`를 제공하면서 보호 shell을 숨기는지 확인한다. `npm run test:run -- src/app/App.test.tsx`가 status 부재로 실패하는지 확인한다.
- [x]**GREEN: 최소 구현/통과 확인** — 기존 `PageState` loading variant를 미검증 branch에 조합하는 최소 구현으로 같은 명령을 통과시킨다.
- [x]**REFACTOR: 정리/회귀 확인** — loading copy와 branch 이름을 정리하고 기존 404 retry E2E에 350ms pending status assertion을 추가한 뒤 focused·전체 회귀를 실행한다.
- [x] TDD 단계와 아래 검증 기준의 실제 결과를 plan/review에 누적한다.
**검증 기준:**
- **실행 명령:** `npm run test:run -- src/app/App.test.tsx`, `VITE_API_MODE=server npx playwright test tests/e2e/server-mode-boundary.spec.ts`, `npm run test:run -- src/shared/config src/shared/mocks src/shared/ui/__tests__/mock-mode-banner.test.tsx`, `npm run test:run`, `npm run typecheck`, `npm run lint`
- **기대 결과:** App 1 file / 27 tests, server boundary 4 projects / 12 tests 이상, P2 focused 7 files / 25 tests 이상, 전체 34 files / 147 tests 이상, type·lint 오류 0건; 최초 pending 전용 test 1건과 기존 retry test 보강으로 두 pending 시나리오에서 visible `role="status"` 1건과 보호 `main`·logout 0건.
- **수동 확인:** 375px server mode에서 최초 진입과 retry 응답을 각각 350ms 이상 지연해 한국어 loading 안내가 보이고 빈 root가 발생하지 않으며, 성공 뒤에만 shell이 열린다.
- Consumes: `VITE_API_MODE=server | mock`, Playwright `testMatch`, npm argument forwarding, 현재 server 4개·mock 2개 spec allowlist
- Produces: file 목록을 내장하지 않는 `e2e`·`e2e:mock` scripts와 server `testMatch=["**/server-mode-boundary.spec.ts", "**/smoke.spec.ts", "**/auth.spec.ts", "**/accessibility-shell.spec.ts"]`, mock `testMatch=["**/mock-preview-shell.spec.ts", "**/mock-mode-boundary.spec.ts"]`; CLI file filter와 mode allowlist의 교집합 실행 계약
**TDD 절차:**
- [x]**RED: 실패 테스트 작성/실패 확인** — mode boundary test가 npm scripts의 고정 spec 목록 제거와 config의 mode별 exact allowlist를 요구하게 하고 `npm run test:run -- src/shared/mocks/__tests__/mode-boundary.test.ts`가 현재 script/config로 실패하는지 확인한다.
- [x]**RED: surface 실패 확인** — network 재실패 retry E2E를 추가하고 현재 구현에서 동작을 확인하되, `npm run e2e -- --list tests/e2e/server-mode-boundary.spec.ts`가 불필요한 4 files를 수집해 focused list assertion을 실패시키는지 확인한다.
- [x]**GREEN: 최소 구현/통과 확인** — script는 각각 `VITE_API_MODE=server playwright test`, `VITE_API_MODE=mock playwright test`만 유지하고 config의 `apiMode`별 `testMatch`에 Interfaces의 exact glob allowlist를 옮겨 contract·focused list·network retry E2E를 통과시킨다.
- [x]**REFACTOR: 정리/회귀 확인** — mode allowlist 상수와 README/scripts 문구를 정리한 뒤 focused·bare E2E와 P2 Gate를 실행한다.
- [x] TDD 단계와 아래 검증 기준의 실제 결과를 plan/review에 누적한다.
**검증 기준:**
- **실행 명령:** `npm run test:run -- src/shared/mocks/__tests__/mode-boundary.test.ts src/shared/mocks/__tests__/mock-preview-docs.test.ts`, `npm run e2e -- --list tests/e2e/server-mode-boundary.spec.ts`, `npm run e2e:mock -- --list tests/e2e/mock-preview-shell.spec.ts`, `npm run e2e -- tests/e2e/server-mode-boundary.spec.ts`, `npm run e2e`, `npm run e2e:mock`, `npm run test:run -- src/shared/config src/shared/mocks src/shared/ui/__tests__/mock-mode-banner.test.tsx`, `npm run typecheck`, `npm run lint`
- **기대 결과:** focused server boundary 1 file / 16 tests 이상, focused mock preview 1 file / 24 tests, bare server 4 files / 36 tests 이상, bare mock 2 files / 28 tests, P2 focused 7 files / 25 tests 이상, type·lint 오류 0건; network retry 재실패 뒤 retry button 1건, 보호 `main`·logout·mock worker 0건.
- Test: 없음 — 구현·test 동작은 바꾸지 않고 완료 문서의 사실관계와 현재 상태만 정정한다.
**Interfaces:**
- Consumes: `REV-P2-017`, `src/app/App.test.tsx`의 27 test declarations, `P2-R12` 완료 기록
- Produces: actual test case와 검증 시나리오를 구분한 P2-R12 완료 증거와 정정 기록
**TDD 예외 사유:** 제품 코드와 test를 변경하지 않는 문서 정정이며, 새 test case를 추가하면 이미 존재하는 retry pending assertion을 중복하게 된다. 실제 test 선언·focused 결과와 문서 문자열 대조를 실패·성공 증거로 사용한다.
**대체 검증 방법:** App test 선언 수·두 pending 시나리오의 위치·focused 실행 수를 plan/review 문구와 대조하고, stale 표현 검색과 문서 diff 검사를 실행한다.
- [x]`rg -c '^test\(' src/app/App.test.tsx`와 두 pending test 위치를 수집해 27 tests 구조를 재확인한다.
- [x] P2-R12 체크·기대 결과·수정 검증 기록을 최초 전용 test 1건 + 기존 retry test 보강 + App 27 tests로 정정하고 이전 표현·정정 사유를 새 기록에 남긴다.
- [x] review 상단·발견 요약·종료 판정을 `REV-P2-017` 수정 완료와 `P2-R14` 완료 상태로 갱신한다.
- [x] 아래 대체 검증과 문서 diff 검사를 실행하고 실제 결과를 plan/review에 누적한다.
**P2-R14 수정 검증 기록 (2026-07-27):**
- 대체 RED: `rg -c '^test\(' src/app/App.test.tsx` — 27건. `rg -n 'initial protected route probe is pending|retries a protected route 404' src/app/App.test.tsx` — 최초 pending 전용 test 1건과 기존 404 retry test 1건을 확인했다. 기존 P2-R12 기록은 두 신규 test·App 28 tests 이상으로 표시돼 실제 구조와 불일치했다.
- GREEN: P2-R12 TDD 절차·기대 결과와 P2-R11~P2-R13 수정 검증 기록을 최초 pending 전용 test 1건 + 기존 retry test 보강 + App 27 tests로 정정했다. 이전 잘못된 표현과 정정 사유는 이 P2-R14 기록과 review `REV-P2-017`에 보존했다.
- Consumes: `REV-P2-010`~`REV-P2-016`, `P2-R8`~`P2-R13` 수정 검증 기록, review §5·§6·§8
- Produces: review §7과 요약·상세·종료 판정이 같은 현재 상태를 표시하는 Phase 2 인수인계 문서
**TDD 예외 사유:** 제품 동작이나 실행 가능한 계약을 바꾸지 않는 문서 상태 정정이므로 새 제품 test를 추가하지 않는다.
**대체 검증 방법:** review §5·§6·§7·§8의 상태를 직접 대조하고 stale 현재 상태 문자열 검색과 Markdown diff 검사를 실행한다.
- [x] review §7의 3차 회귀 Task 설명을 `P2-R8`~`P2-R10` 수정 완료 상태로 정정한다.
- [x] review §7의 4차 회귀 Task 설명을 `P2-R11`~`P2-R13` 수정 완료 상태로 정정한다.
- [x] 과거 시점의 수정 전 기록과 남은 항목이 보존됐는지 확인한다.
- [x] 아래 대체 검증을 실행하고 실제 결과를 plan/review에 누적한다.
**P2-R15 수정 검증 기록 (2026-07-27):**
- 대체 RED: `rg -n '3차 재검증의 새 확정 4건.*아직 수정하지 않았다|4차 재검증의 새 확정 3건.*아직 수정하지 않았다' docs/20260725_AI캐릭터관리자웹/reviews/review-phase-2.md` — 2건. review §7이 완료된 `P2-R8`~`P2-R13`을 여전히 미수정 현재 상태로 표시했다.
- GREEN: review §7의 3차·4차 회귀 Task 설명을 2026-07-27 수정·검증 완료 상태로 정정하고, review의 `REV-P2-018` 상태·발견 요약·종료 판정을 수정 완료로 맞췄다. §9의 당시 남은 항목과 과거 검증 기록은 보존했다.
- 검증: 같은 stale 현재 상태 검색 — no matches. `git diff --check -- docs/20260725_AI캐릭터관리자웹/plan-task.md docs/20260725_AI캐릭터관리자웹/reviews/review-phase-2.md` — exit 0.
- 애플리케이션 test/build는 구현 코드와 설정을 변경하지 않았고 신규 명령도 아직 계획 상태이므로 실행하지 않는다.
- 남은 항목: Phase 2 구현 시 실제 `dev:mock`·`e2e:mock` 명령과 환경 변수를 만든 후 README와 `docs/agent-guide/{environment,scripts}.md`를 실체에 맞게 갱신한다. 계약 미제공 도메인은 backend 계약 수신 전 fixture를 만들지 않는다.
### Phase 2 코드 리뷰·QA — 2026-07-27
- 무엇을: Phase 2 staged 구현 28개 경로를 PRD `MOCK-001~009`, API Contract §1·§3, `P2-T1~P2-GATE`와 대조하고 확정 문제 5건을 `P2-R1~P2-R3`으로 전환했다.
- 왜: 자동 검증 통과와 별개로 보호 route fail-closed, exact API origin, invalid·revoked JWT status, Phase 번호 표시와 완료 문서 추적성이 실제 계약과 일치하는지 독립적으로 판정하기 위해서다.
-`npm run e2e -- tests/e2e/server-mode-boundary.spec.ts` — 성공, 4 projects / 12 tests passed. 이 통과 과정에서 404·network error alert가 보호 shell 내부에서 렌더되는 회귀를 별도 확정했다.
- Vite SSR로 `createMockHandlers(createMockStore())`를 실행한 재현 — wrong-origin login 200, invalid JWT logout 200, 정상 logout 200, revoked JWT 재logout 200을 확인했다. Vite HMR WebSocket은 sandbox listen EPERM 경고가 있었으나 MSW request 재현 command는 exit 0으로 완료됐다.
- 남은 항목: `REV-P2-001~005`를 수정하는 `P2-R1~P2-R3`. 기존 Phase 2 완료 체크와 검증 기록은 되돌리지 않는다.
### Phase 2 구현·Gate 완료 기록 — 2026-07-27
- 무엇을: explicit `server | mock` mode, 개발 전용 browser MSW bootstrap, auth preview fixture, mock banner, no-auto-fallback E2E, production mock 차단과 실행 문서를 구현했다.
- 왜: backend endpoint 구현 전에도 제공 API Contract 범위의 최종 UI를 mock mode에서 확인하되, 기본 server mode와 production build가 mock으로 자동 대체되지 않게 하기 위해서다.
-`npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod` — 모두 exit 0.
-`VITE_API_MODE=mock npm run build:prod` — 기대대로 exit 1. production 산출물의 worker 파일·mock bootstrap 문자열은 0건.
-`npm run e2e` — 4 projects / 32 tests 통과. `npm run e2e:mock` — 4 projects / 24 tests 통과.
- Chromium one-off — login과 Character probe 응답이 모두 `fromServiceWorker=true`임을 확인했다. 320px menu open에서는 banner가 inert 경계 밖에 있었고, 1,200px 전환 뒤 overlay는 숨겨졌지만 main inert·`aria-hidden=true`가 남았다.
- 코드·test 대조 — 보호 route 오류 page의 interactive recovery control 0건과 App/server boundary retry test 0건을 확인했다.
- 문서 반영 검증 — `npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts`는 1 file / 3 tests 통과, review 상세 ID 13개·Phase 2 회귀 Task 10개를 확인했고 stale 3차 범위 문자열과 문서 whitespace 오류는 0건이었다.
- 변경 범위: [Phase 2 리뷰](./reviews/review-phase-2.md)에 3차 근거·발견·판정을 누적하고 이 문서에 `P2-R8`~`P2-R10`만 추가했다. 애플리케이션 코드·test·설정은 변경하지 않았다.
- 남은 항목: `P2-R8` 문서 추적성, `P2-R9` mobile menu 반응형·inert, `P2-R10` 보호 route 오류 retry 복구. 세 goal의 대체 검증 또는 RED/GREEN/REFACTOR, 관련 E2E와 P2 Gate가 끝나기 전에는 Phase 2 리뷰를 닫지 않는다.
### P2-R9 수정 검증 — 2026-07-27
- 무엇을: `REV-P2-011`, `REV-P2-012`를 `P2-R9` 범위에서 수정했다. Mock Preview 성공 shell의 banner를 `ProtectedAdminShell` background inert container 안으로 옮기고, native `matchMedia('(min-width: 1024px)')` change에서 mobile menu state와 inert·`aria-hidden`을 해제하되 숨겨진 mobile trigger로 focus를 복귀하지 않게 했다.
- 왜: mobile menu가 열린 상태에서 background 전체가 같은 접근성 차단 경계에 속해야 하며, `lg` 이상 viewport로 전환될 때 보이는 desktop navigation·logout·main이 즉시 다시 조작 가능해야 하기 때문이다.
- 어떻게:
- RED unit: `npm run test:run -- src/app/App.test.tsx src/shared/ui/__tests__/mock-mode-banner.test.tsx` — 2 files 중 `App.test.tsx` 2 tests가 기대대로 실패했다. 실패 핵심은 `mock banner inert background not found`와 `모바일 주 메뉴` 잔존이다.
- RED e2e: `npm run e2e:mock -- tests/e2e/mock-preview-shell.spec.ts` — 4 browser projects에서 신규 mock shell test가 모두 기대대로 실패했다. 실패 핵심은 320px open state의 `bannerInert=false`, `bannerHidden=false`, `mainInert=true` 불일치다.
- GREEN unit: 같은 focused unit command — 2 files / 26 tests 통과.
- GREEN e2e: 같은 mock e2e command — 28 tests 통과. 320px open state에서 banner·main이 같은 inert/`aria-hidden` 경계에 있고 1,024px·1,200px 전환 뒤 mobile menu가 제거되며 desktop navigation·logout이 보이는 것을 확인했다.
- Regression: `npm run e2e -- tests/e2e/accessibility-shell.spec.ts` — 32 tests 통과. `npm run typecheck`, `npm run lint` — 모두 exit 0.
- LSP diagnostics: `src/app/App.tsx`, `src/app/protected-admin-shell.tsx`, `src/app/App.test.tsx`, `tests/e2e/mock-preview-shell.spec.ts` 모두 0 diagnostics.
- P2 focused Gate: `npm run test:run -- src/shared/config src/shared/mocks src/shared/ui/__tests__/mock-mode-banner.test.tsx` — P2-R9 문서 기록 반영 전에는 docs contract 1 test가 실패했다. 기록 반영 후 재실행해 7 files / 25 tests 통과했다.
- 남은 항목: `P2-R10` 보호 route 오류 retry 복구. mock 통과는 후속 도메인 server integration 완료로 간주하지 않는다.
### P2-R10 수정 검증 — 2026-07-27
- 무엇을: `REV-P2-013`을 `P2-R10` 범위에서 수정했다. 보호 route 오류 page에 native retry button을 추가하고, 현재 session·route visit·retry attempt가 모두 일치할 때만 오류나 검증 성공을 사용하도록 했다. 정상 `ApiError`의 서버 message는 유지하고 network 오류에는 안전한 공통 안내를 표시한다.
- 왜: 404·network 오류 뒤에도 사용자가 browser refresh 없이 복구할 수 있어야 하며, 현재 수동 retry가 성공하기 전에는 보호 shell·navigation·logout을 계속 숨겨야 하기 때문이다.
- 어떻게:
- RED unit: `npm run test:run -- src/app/App.test.tsx` — 1 file / 26 tests 중 신규 2 tests가 `보호 route 다시 시도` button 부재로 기대대로 실패했고 24 tests는 통과했다.
- RED E2E: `npm run e2e -- tests/e2e/server-mode-boundary.spec.ts` — 32 tests 중 신규 retry 시나리오가 4 browser project에서 button 부재로 기대대로 실패했고 28 tests는 통과했다.
- GREEN unit: 같은 App command — 1 file / 26 tests 통과. 404 `없습니다.` 보존, network 재실패의 공통 안내·retry 유지, pending 중 shell·logout 비노출과 성공 뒤 shell 표시를 확인했다.
- GREEN E2E: 같은 server command — 4 projects / 32 tests 통과. 명시적 retry 전후 browser MSW worker 0건과 성공 전 shell·logout 0건을 확인했다.
- Static/build: `npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod` — 모두 exit 0. no-excuse 검사도 변경 TS/TSX 3 files / 위반 0건이었다.
- 수동·시각 확인: server mode 실제 브라우저 375px·768px·1,280px에서 button 높이 44px, `:focus-visible=true`, 한국어 clipping·비정상 줄바꿈 0건을 확인했다. retry 성공 뒤 shell·logout 표시와 mock worker 0건을 확인했고 기능 무결성·CJK 정밀 검토가 모두 PASS였다.
- 남은 항목: `P2-R10` 범위 없음. mock 통과는 후속 도메인 server integration 완료로 간주하지 않는다.
### Phase 2 4차 코드 리뷰·QA — 2026-07-27
- 무엇을: `P2-R8`~`P2-R10` 반영 뒤 working tree 전체 집계, 보호 route pending UI와 mode별 focused E2E 증거를 재검토해 `REV-P2-014` Low 1건과 `REV-P2-015~016` Medium 2건을 확정하고 `P2-R11`~`P2-R13`으로 전환했다.
- 왜: 완료 판정이 untracked 파일, 300ms 이상 retry 대기 상태와 Task가 지정한 단일 E2E spec의 실제 수집 범위를 빠뜨리지 않는지 확인하기 위해서다.
-`npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod` — 모두 exit 0, build는 각 160 modules 변환.
-`VITE_API_MODE=mock npm run build:prod` — 기대대로 exit 1. production worker 파일과 mock bootstrap 문자열은 0건.
-`npm run e2e` — 4 projects / 32 tests 통과. `npm run e2e:mock` — 4 projects / 28 tests 통과.
-`git diff HEAD --name-only | wc -l` — tracked 37개, `git status --porcelain=v1 | wc -l` — 전체 38개, `git ls-files --others --exclude-standard` — `src/app/protected-admin-shell.tsx` 1개.
-`npm run e2e -- --list tests/e2e/server-mode-boundary.spec.ts` — 4 files / 32 tests, 직접 `VITE_API_MODE=server npx playwright test tests/e2e/server-mode-boundary.spec.ts --list` — 1 file / 12 tests. 고정 script가 focused filter를 무효화하고 `P2-R10` 기대 16 tests 미달을 가리는 것을 확인했다.
- Chromium one-off — 404 retry 성공 응답을 350ms 지연했을 때 `#root` child·`main`·`status`·`alert` 0개, active element `BODY`; 응답 뒤 shell·logout 표시를 확인했다. 최초 sandbox local listen·browser launch 실패는 권한 허용 재실행으로 보완했다.
- 문서 반영 검증 — `npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts`는 1 file / 3 tests 통과. review 상세 ID 16개, Phase 2 회귀 Task 13개와 문서 whitespace 오류 0건을 확인했다.
- 변경 범위: [Phase 2 리뷰](./reviews/review-phase-2.md)에 4차 근거·발견·판정을 누적하고 이 문서에 `P2-R11`~`P2-R13`만 추가했다. 애플리케이션 코드·test·설정은 변경하지 않았다.
- 남은 항목: `P2-R11` working tree 추적성, `P2-R12` 보호 route pending 피드백, `P2-R13` focused E2E filter·network retry 증거. 세 goal의 대체 검증 또는 RED/GREEN/REFACTOR와 관련 Gate가 끝나기 전에는 Phase 2 리뷰를 닫지 않는다.
### P2-R11~P2-R13 수정 검증 — 2026-07-27
- 무엇을: `REV-P2-014~016`을 `P2-R11`~`P2-R13` 범위에서 수정했다. working tree 범위는 tracked 37개 + untracked `src/app/protected-admin-shell.tsx` 1개로 구분해 기록하고, 보호 route pending에는 기존 `PageState` loading status를 표시했다. E2E script의 spec allowlist는 `playwright.config.ts``testMatch`로 옮기고 network retry 재실패 E2E를 추가했다.
- 왜: 완료 증거가 untracked 파일, 접근 가능한 300ms 이상 pending feedback, focused E2E file filter와 실제 network retry 경계를 빠뜨리지 않게 하기 위해서다.
- 어떻게:
- P2-R11 대체 검증: `git diff HEAD --name-only | wc -l` — tracked 37개, `git status --short --untracked-files=all | wc -l` — 전체 38개, `git ls-files --others --exclude-standard` — `src/app/protected-admin-shell.tsx` 1개.
- P2-R12 RED: `npm run test:run -- src/app/App.test.tsx` — 최초 pending 전용 test 1건과 기존 404 retry test의 pending assertion이 `role="status"` 부재로 기대대로 실패했다.
- P2-R12 GREEN: 같은 command — 1 file / 27 tests 통과. 최초 probe와 retry pending 중 `role="status"`, 보호 `main`·logout 0건을 확인했다.
- P2-R13 RED: `npm run test:run -- src/shared/mocks/__tests__/mode-boundary.test.ts` — npm script와 Playwright config contract 2 tests가 기대대로 실패했다.
- Final Gate: `npm run test:run` — 34 files / 147 tests 통과. `npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod` — 모두 exit 0. `npm run e2e` — 36 tests 통과, `npm run e2e:mock` — 28 tests 통과.
-`npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod` — 모두 exit 0. `VITE_API_MODE=mock npm run build:prod` — 기대한 production guard로 exit 1.
- focused E2E list는 server 1 file / 16 tests, mock 1 file / 24 tests. 최초 sandbox listen `EPERM` 뒤 허용된 로컬 실행에서 server boundary 16, mock preview 24, bare server 36, bare mock 28 tests가 모두 통과했다.
- working tree는 tracked diff 37개 + untracked `src/app/protected-admin-shell.tsx` 1개 = 전체 38개 항목으로 유지됐다.
- 변경 범위: [Phase 2 리뷰](./reviews/review-phase-2.md)에 `REV-P2-017`과 5차 근거·판정을 누적하고 이 문서에 `P2-R14`만 추가했다. 애플리케이션 코드·test·설정은 변경하지 않았다.
- 남은 항목: `P2-R14` 범위 없음. mock 통과는 후속 도메인 server integration 완료로 간주하지 않는다.
### P2-R14 수정 검증 — 2026-07-27
- 무엇을: `REV-P2-017`을 `P2-R14` 범위에서 수정했다. P2-R12 완료 증거를 실제 App test 구조인 최초 pending 전용 test 1건 + 기존 404 retry test의 pending assertion 보강 + App 27 tests로 정정했다.
- 왜: 문서가 “두 신규 test·28 tests 이상”을 완료 조건처럼 표시하면 후속 reviewer가 실제 test case 수와 검증 시나리오 수를 혼동하기 때문이다.
- 어떻게:
- 대체 RED: `rg -c '^test\(' src/app/App.test.tsx` — 27건. `rg -n 'initial protected route probe is pending|retries a protected route 404' src/app/App.test.tsx` — 최초 pending 전용 test와 기존 404 retry test 위치를 확인했다.
- GREEN docs: P2-R12 TDD 절차·기대 결과, P2-R11~P2-R13 수정 검증 기록, review 요약·종료 판정을 실제 구조와 일치시켰다.
- 문서 검증: stale `신규 pending status tests 2건` 검색 결과 0건, `git diff --check -- docs/20260725_AI캐릭터관리자웹/plan-task.md docs/20260725_AI캐릭터관리자웹/reviews/review-phase-2.md` — exit 0.
- 남은 항목: Phase 2 review의 열린 확정 항목 없음. 애플리케이션 코드·test·설정은 변경하지 않았다.
### Phase 2 6차 코드 리뷰·QA — 2026-07-27
- 무엇을: `P2-R14` 반영 뒤 Phase 2 구현·test·production·mode별 E2E와 review 현재 상태를 다시 대조해 `REV-P2-018` Low 1건을 확정하고 `P2-R15`로 전환했다.
- 왜: review 요약·상세·종료 판정과 plan 전환 절이 완료된 회귀 Task의 현재 상태를 같은 의미로 표시하는지 확인하기 위해서다.
- 어떻게:
-`npm run test:run` — 34 files / 147 tests 통과.
-`npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod` — 모두 exit 0, build는 각각 160 modules 변환.
-`VITE_API_MODE=mock npm run build:prod` — 기대한 production guard로 exit 1.
-`npm run e2e` — 최초 sandbox listen `EPERM` 뒤 로컬 실행 권한으로 재실행해 4 projects / 36 tests 통과.
-`npm run e2e:mock` — 최초 sandbox listen `EPERM` 뒤 로컬 실행 권한으로 재실행해 4 projects / 28 tests 통과.
- Chromium one-off — login·보호 route 응답 `fromServiceWorker=true`, 320px menu·logout 높이 60px, mobile link 선택 뒤 menu·background inert 잔존 0건을 확인했다.
-`git diff --check HEAD` — review 문서 반영 전 exit 0. review §7의 `P2-R8`~`P2-R13` “아직 수정하지 않았다” 2건과 §5·§6·§8의 수정 완료 상태가 모순됨을 확인했다.
- 문서 반영 후 `npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts` — 1 file / 3 tests 통과, plan/review 대상 `git diff --check` — exit 0.
- 변경 범위: 이 review 문서와 `plan-task.md`에 `REV-P2-018`, `P2-R15` 판정·후속 계획만 추가했다. 애플리케이션 코드·test·설정은 변경하지 않았다.
- 남은 항목: `P2-R15`에서 review §7의 현재 상태 문구를 정정하고 문서 검색·diff 검증을 누적해야 한다.
### Phase 2 7차 코드 리뷰·QA — 2026-07-27
- 무엇을: `P2-R15` 반영 뒤 Phase 2 상단 현재 상태, Task 본문, review 종료 판정과 하단 최신 Progress를 대조해 `REV-P2-019` Low 1건을 확정하고 `P2-R16`으로 전환했다.
- 왜: 완료된 회귀 Task의 inline 기록뿐 아니라 Phase 현재 상태와 하단 누적 Progress도 Phase 3 실행자가 같은 완료 상태로 해석할 수 있어야 하기 때문이다.
- 어떻게:
- 대체 RED 완료 상태 검색 — Phase 2 상단의 `P2-R15`까지 완료·Phase 3 진행 가능 exact 상태가 없어 exit 1.
- 대체 RED 최신 Progress 검색 — 문서 끝이 6차 재검증의 `P2-R15` 수정 필요 상태로 끝나 현재 완료 기록이 없어 exit 1.
- 코드 회귀 기준은 6차 재검증 직후 독립 확인에서 unit 147 tests, server E2E 36 tests, mock E2E 28 tests, typecheck·lint·dev/prod build 통과와 production mock guard 거부를 확인했다.
- 변경 범위: 이 review 문서와 `plan-task.md`에 `REV-P2-019`, `P2-R16` 판정·후속 계획만 추가했다. 애플리케이션 코드·test·설정은 변경하지 않았다.
- 남은 항목: `P2-R16`에서 Phase 2 현재 상태와 최신 Progress를 정정하고 문서·Phase 2 Gate 검증을 누적해야 한다.
### P2-R16 수정 검증 — 2026-07-27
- 무엇을: `REV-P2-019`를 수정했다. Phase 2 상단 현재 상태를 `P2-R16`까지 완료 및 Phase 3 진행 가능으로 갱신하고, 6차 당시 남은 항목을 보존한 채 최신 수정 검증을 누적했다.
- 왜: Phase 3 실행자가 완료된 `P2-R15`를 열린 선행 작업으로 오해하지 않고 Phase 2의 실제 완료 상태를 단일하게 판정할 수 있어야 하기 때문이다.
- 어떻게:
- 대체 GREEN: Phase 2 완료 상태 exact 검색과 최신 Progress 검색이 각각 1건 이상 일치했다. 6차 당시 `P2-R15` 남은 항목도 이력으로 보존됐다.
- Full unit/static/build: `npm run test:run` — 34 files / 147 tests 통과. `npm run typecheck`, `npm run lint`, `npm run build:dev`, `npm run build:prod` — 모두 exit 0, build는 각각 160 modules 변환.
- Production boundary: `VITE_API_MODE=mock npm run build:prod` — 기대대로 exit 1. production worker 파일과 mock bootstrap 문자열은 0건.
- 모든 Task에는 고유 Goal ID, 한 문장 objective, 시작 조건, 완료 증거와 범위 밖을 둔다.
- Goal ID는 `P<Phase>-T<Task>`를 사용한다. Phase Gate는 `P<Phase>-GATE`, 완료 범위의 회귀 수정은 `P<Phase>-R<번호>`를 사용한다.
- Task는 독립 reviewer가 이웃 Task와 별도로 승인·거절할 수 있고, 자체 test cycle로 검증할 수 있는 최소 결과 단위로 나눈다.
- Task마다 생성·수정·test 파일의 정확한 경로를 기록한다. 선행 Task contract를 소비하거나 후속 Task에 제공하면 `Interfaces`에 정확한 type·function·component를 기록한다.
-구현 체크박스는 실패 test 작성 → 의도한 실패 확인 → 최소 구현 → focused test 성공 → 관련 품질 검증 → Progress 기록 순서를 포함한다.
- Task마다 생성·수정·test 파일의 정확한 경로를 기록한다. TDD 예외 Task에 test 파일이 없으면 `Test: 없음`과 사유를 적는다. 선행 Task contract를 소비하거나 후속 Task에 제공하면 `Interfaces`에 정확한 type·function·component를 기록한다.
-모든 구현 Task의 `TDD 절차`에는 다음 순서와 확인 내용을 명시한다.
-`RED: 실패 테스트 작성/실패 확인` — 검증할 동작과 실패 테스트 파일, 실행 명령, 의도한 실패 결과를 적는다.
-`GREEN: 최소 구현/통과 확인` — 최소 구현 범위와 동일한 테스트 명령의 통과 결과를 적는다.
-`REFACTOR: 정리/회귀 확인` — 동작을 바꾸지 않는 정리 범위와 focused·관련 회귀 테스트 결과를 적는다.
- 실패 테스트 작성이 현실적으로 불가능한 문서화, 조사, 외부 의존 작업 등은 같은 Task에 `TDD 예외 사유`와 `대체 검증 방법`을 명시한다. 단순히 `해당 없음`만 적거나 산출물과 무관한 테스트를 만드는 것으로 대체하지 않는다.
- 각 Task의 `검증 기준`에는 다음을 포함한다.
-`실행 명령`: focused test, 관련 회귀 test, typecheck·lint 또는 TDD 예외의 대체 검증 등 실제 실행할 명령
-`기대 결과`: 종료 코드, 통과할 test 수, 예상 출력 또는 상태 변화
-`수동 확인`: 사용자가 확인할 화면·동작·문서 항목. 불필요하면 `없음`과 사유를 기록한다.
- 구현 체크박스 마지막에는 검증 결과와 `Progress` 기록을 포함한다.
- “적절히 처리”, “나중에 구현”, “위와 동일”처럼 실행자가 다시 추측해야 하는 표현을 사용하지 않는다.
## 5. 완료와 차단 판정
@@ -52,6 +63,8 @@
- 동시에 하나의 미완료 goal만 운용한다. 활성 goal이 있으면 새 goal을 만들지 않고 같은 Task를 이어서 수행한다.
- 사용자가 명시적으로 요청하지 않으면 token budget을 설정하지 않는다.
- 코드 작성이나 일부 test만 끝난 상태는 완료가 아니다. 체크박스, 완료 증거, 실제 검증과 Progress 기록까지 충족한 뒤에만 goal을 `complete`로 갱신한다.
- 구현 Task는 RED/GREEN/REFACTOR 각 단계의 결과가 없으면 완료할 수 없다.
- TDD 예외 Task는 예외 사유와 대체 검증 결과가 없으면 완료할 수 없다.
- Phase의 모든 활성 Task goal을 완료한 뒤 Phase Gate를 별도 goal로 실행한다.
- 외부 계약이나 권한 같은 동일 차단 사유가 최초 시도와 자동 후속을 포함해 3회 연속 반복되고, 문서화·독립 작업 등 의미 있는 진전도 불가능할 때만 goal을 `blocked`로 갱신한다.
- 계약이 없어 안전하게 구현할 수 없으면 추정하지 않는다. 담당 주체·영향·재개 조건을 기록하고 PRD 결정 기록 → API Contract → `plan-task.md` 순서로 제외 또는 후속 결정을 반영한다.
@@ -62,6 +75,7 @@
- 범위나 구현 방식이 바뀌면 코드를 수정하기 전에 관련 체크박스, Files, Interfaces, 완료 증거와 Decision Log를 갱신한다.
- Progress와 Decision Log의 기존 기록은 삭제하거나 덮어쓰지 않는다. 정정은 날짜·사유와 함께 새 기록으로 추가한다.
- 실행한 명령만 기록하고 성공/실패, exit code, test 수 또는 불가 사유를 남긴다.
- 구현 Task의 Progress에는 RED의 의도한 실패, GREEN의 통과, REFACTOR의 회귀 확인 결과를 구분해 기록한다. TDD 예외 Task는 대체 검증의 실제 결과를 기록한다.
- 구현 중 발견한 범위 내 문제는 `발견된 문제`에 기록한다. 완료 범위의 상세 리뷰·QA는 [코드 리뷰 및 QA 기록 규칙](./review.md)에 따라 별도 review 문서로 관리한다.
- Phase 완료 후 현재 상태 표와 체크박스를 갱신하고 Phase Gate의 최신 증거를 Progress에 누적한다.
@@ -75,6 +89,7 @@ goal을 만들기 전에 다음을 확인한다.
- Files와 Interfaces의 이름이 앞뒤 Task에서 일치한다.
- 외부 의존과 안전한 기본값이 구분돼 있다.
- backend 구현 전 UI preview가 필요하면 제공 계약 기반 explicit mock mode와 실제 server integration을 별도 Task·Gate·Progress로 구분하고 404 자동 fallback을 금지한다.
-실제 검증 명령과 Expected가 구체적이다.
-각 구현 Task에 RED/GREEN/REFACTOR 절차가 있고, 예외 Task에는 예외 사유와 대체 검증 방법이 있다.
- 각 Task와 Phase Gate의 실행 명령, 기대 결과, 수동 확인 항목이 구체적이다.
> 이 문서는 goal 기능으로 구현 계획을 실행하기 위한 템플릿이다. 실제 `plan-task.md`를 만들 때 `<...>` placeholder를 모두 구체적인 값으로 교체한다. Phase는 결과와 의존성을 묶고, `create_goal`에는 Task 또는 Phase Gate 하나만 등록한다.
> 이 문서는 goal 기능으로 구현 계획을 실행하기 위한 템플릿이다. 실제 `plan-task.md`를 만들 때 `<...>` placeholder를 모두 구체적인 값으로 교체한다. Phase는 결과와 의존성을 묶고, `create_goal`에는 Task 또는 Phase Gate 하나만 등록한다. 각 구현 Task에는 RED/GREEN/REFACTOR 절차를, 테스트가 현실적으로 불가능한 Task에는 TDD 예외 사유와 대체 검증 방법을 적고, 모든 Task와 Phase Gate에 실행 명령·기대 결과·수동 확인을 둔다.
| 문서 항목 | 내용 |
|---|---|
@@ -49,7 +49,7 @@
- 의존성: 실제 소비 Task에서 필요한 최소 dependency만 추가한다.
- 계약: 제공되지 않은 endpoint, DTO, enum, 오류 status/key와 validation 상한을 추정하지 않는다.
- backend 구현 전 UI 확인이 필요하면 제공 계약 기반 explicit mock mode를 사용하고 실제 404 자동 fallback·production mock을 금지하며 mock/server 완료 증거를 분리한다.
- 구현: 모든 기능은 가장 작은 실패 test를 먼저 만들고 최소 구현으로 통과시킨다.
- 구현: 모든 기능은 `RED: 실패 테스트 작성/실패 확인` → `GREEN: 최소 구현/통과 확인` → `REFACTOR: 정리/회귀 확인` 순서로 진행한다. 실패 테스트가 현실적으로 불가능하면 Task에 TDD 예외 사유와 대체 검증 방법을 먼저 확정한다.
## Phase 1
@@ -80,11 +80,19 @@
- Consumes: `<선행 Task가 제공하는 type/function/component contract>`
- Produces: `<후속 Task가 사용할 정확한 type/function/component contract>`
- [ ] 가장 작은 실패 test를 작성한다.
- [ ]`<focused test 명령>`을 실행해 의도한 assertion 실패를 확인한다.
- [ ]test를 통과시키는 최소 구현을 작성한다.
- [ ]`<focused test 명령>`을 다시 실행해 성공을 확인한다.
- [ ]관련 typecheck·lint를 실행하고 실제 결과를 Progress에 기록한다.
**TDD 절차:**
- [ ]**RED: 실패 테스트 작성/실패 확인** — `<정확한 test 파일 경로>`에 `<검증할 동작>`의 가장 작은 실패 test를 작성하고 `<focused test 명령>` 실행 시 `<의도한 assertion 메시지>`로 실패하는지 확인한다.
- [ ]**GREEN: 최소 구현/통과 확인** — `<정확한 구현 파일 경로>`에 test를 통과시키는 최소 구현만 작성하고 같은 명령이 `exit 0`, `<N개 test 통과>`인지 확인한다.
- [ ]**REFACTOR: 정리/회귀 확인** — 중복·이름·구조만 정리한 뒤 `<focused test 명령>`과 `<관련 회귀 test 명령>`이 모두 `exit 0`인지 확인한다.
**검증 기준:**
- **실행 명령:** `<focused test 명령>`, `<관련 회귀 test 명령>`, `<typecheck 명령>`, `<lint 명령>`
- **기대 결과:** 모든 명령 `exit 0`, `<focused N개·회귀 N개 test>` 통과, type·lint 오류 0건.
- **수동 확인:** `<viewport>`에서 `<사용자 동작>` 시 `<관찰 가능한 상태 변화>`가 발생하고 금지 동작은 발생하지 않는다.
- [ ] TDD 단계와 검증 기준의 실제 결과를 Progress에 기록한다.
#### Task 1.2 `<두 번째 독립 결과>`
@@ -105,10 +113,19 @@
- Consumes: `<P1-T1이 제공한 정확한 contract>`
- Produces: `<Phase 2 또는 Gate가 사용할 정확한 contract>`
- [ ] 가장 작은 실패 test를 작성하고 의도한 실패를 확인한다.
- [ ] 최소 구현으로 focused test를 통과시킨다.
- [ ]오류·loading·empty·success와 접근성 상태를 검증한다.
- [ ]관련 test·typecheck·lint 결과를 Progress에 기록한다.
**TDD 절차:**
- [ ]**RED: 실패 테스트 작성/실패 확인** — `<정확한 test 파일 경로>`에 `<오류·loading·empty·success 중 이 Task가 소유한 상태>`와 `<사용자 action>`의 실패 test를 작성하고 `<focused test 명령>`이 의도한 이유로 실패하는지 확인한다.
- [ ]**GREEN: 최소 구현/통과 확인** — 필요한 상태와 action만 최소 구현하고 같은 명령이 `exit 0`, `<N개 test 통과>`인지 확인한다.
- [ ]**REFACTOR: 정리/회귀 확인** — 상태 분기와 접근성 이름을 정리한 뒤 `<focused test 명령>`과 `<P1-T1 관련 회귀 test 명령>`이 모두 통과하는지 확인한다.
**검증 기준:**
- **실행 명령:** `<focused UI test 명령>`, `<P1-T1 관련 회귀 test 명령>`, `<typecheck 명령>`, `<lint 명령>`
- **기대 결과:** 모든 명령 `exit 0`, `<상태·action별 N개 test>` 통과, type·lint 오류 0건.
> 이 문서는 완료된 Phase를 다시 검토할 때 사용하는 템플릿이다. 리뷰에서 발견한 후보를 먼저 검증하고, **확정**된 항목만 `plan-task.md`의 회귀 수정 Task와 goal로 전환한다. 기존 완료 체크박스와 검증 기록은 삭제하거나 되돌리지 않는다.
> 이 문서는 완료된 Phase를 다시 검토할 때 사용하는 템플릿이다. 실제 리뷰 문서는 대상 `prd.md`·`plan-task.md` 디렉터리 아래 `reviews/`에 둔다. 리뷰에서 발견한 후보를 먼저 검증하고, **확정**된 항목만 `plan-task.md`의 회귀 수정 Task와 goal로 전환한다. 기존 완료 체크박스와 검증 기록은 삭제하거나 되돌리지 않는다.
## 1. 리뷰 정보
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.