Files
voiceon-character-admin/docs/20260725_AI캐릭터관리자웹/reviews/phase9-cross-cutting-quality.md

61 KiB

Phase 9 Cross-cutting Quality 코드 리뷰·QA

1. 리뷰 정보

항목 내용
리뷰 대상 Phase 9 / responsive, accessibility, error recovery, cross-domain quality Gate
기준 commit 또는 working tree dd30e36323543e8f60e9983326503653e8001f12, 2026-07-31 종합 재점검 당시 사용자 변경을 포함한 current working tree
리뷰 일자 2026-08-01
리뷰어 Codex
기준 문서 prd.md, api-contract.openapi.json 2.3.0, plan-task.md, 이전 Phase 9 리뷰
리뷰 상태 REV-P9-018REV-P9-019/P9-R18P9-R19 수정 완료, 수동 QA 대기

2. 리뷰 목적과 범위

목적

  • 비활성 Character mutation 차단, field 오류 연결, responsive·keyboard·axe 품질과 Gate 기록을 재검증한다.
  • 이전 Phase 9 리뷰의 발견 상태와 완료된 회귀 Task 기록이 일치하는지 확인한다.

포함 범위

  • 코드: 전 도메인의 capability, form error, responsive/accessibility 공통 구현
  • 테스트: 전체 unit, typecheck, lint, build, mock/server E2E
  • 문서: PRD §10·§13·§14, P9-*, review-phase-9-20260729.md
  • 수동 검증: 이전 발견 ID와 P9-R1·P9-R2 완료 증거의 문서 대조

제외 범위

  • 외부 server credential·fixture 기반 수동 QA
  • 각 도메인에서 별도 소유한 신규 발견의 중복 등록

3. 판정 기준

심각도는 Blocker, High, Medium, Low, 상태는 후보, 확정, 오탐, 보류, 수정 완료를 사용한다. 접근성·반응형 기능 문제와 검증 이력의 추적 가능성을 모두 확인한다.

4. 검토한 근거

문서와 코드

  • 요구사항: PRD §10.2~§10.4, §13, §14.2
  • 계획: P9-T1~P9-GATE, P9-R1, P9-R2
  • 이전 리뷰: reviews/review-phase-9-20260729.md:70-147
  • 현재 구현: inactive mutation capability와 form error/focus 회귀 test

실행 환경

macOS 26.0 (Build 25A354)
Node v24.12.0 / npm 11.7.0
Playwright Chromium, Mobile Chrome

실행한 검증

명령 또는 수동 검증 결과 핵심 증거
npm run typecheck / npm run lint 성공 모두 exit 0
npm run test:run 성공 72 files, 354 tests passed
npm run build 성공 exit 0, 253 modules transformed
npm run e2e:mock 실패 201 passed, 22 skipped, 5 failed; 4건은 REV-P0-004, 1건 timeout은 focused 재실행 통과
npm run e2e 실패 12 passed, 24 failed; REV-P0-004의 동일 origin 원인
이전 Phase 9 리뷰와 plan 완료 기록 대조 성공 REV-P9-001~002 수정 완료와 P9-R1~R2, Gate 완료 기록 일치

5. 발견 사항 요약

ID 심각도 상태 제목 소유 Task 후속 goal
REV-P9-003 Low 수정 완료 이전 Phase 9 리뷰가 완료된 P9-R1·P9-R2를 미해결로 표시한다 P9-R3 P9-R3
REV-P9-004 Medium 수정 완료 일반 mutation 일부가 pending 중 중복 요청을 허용하고 비활성화 실패를 화면에 표시하지 않는다 P9-R4 P9-R4

6. 발견 사항 상세

REV-P9-003 — 이전 Phase 9 리뷰가 완료된 P9-R1·P9-R2를 미해결로 표시한다

  • 심각도: Low
  • 상태: 수정 완료
  • 관련 요구사항: 리뷰 가이드 §4 수정 후 상태·검증 누적 규칙
  • 관련 계약: 없음
  • 소유 Task: 신규 P9-R3

관찰 내용

2026-07-29 Phase 9 리뷰는 REV-P9-001, REV-P9-002확정으로 유지하고 최종 남은 항목을 P9-R1, P9-R2라고 기록한다. 이후 plan 하단에는 두 회귀 Task와 자동 Gate 완료 기록이 있으나 원 리뷰의 상태를 수정 완료로 갱신하고 수정 후 검증을 누적하지 않았다.

근거

  • 리뷰: reviews/review-phase-9-20260729.md:70-71,78,109,147
  • 계획: plan-task.mdP9-R1, P9-R2 완료 체크와 후속 검증 기록
  • 가이드: docs/agent-guide/review.md §4는 수정 후 상태 변경과 실제 검증 결과 누적을 요구

재현 또는 검증 절차

  1. 이전 Phase 9 리뷰의 발견 요약과 최종 남은 항목을 읽는다.
  2. plan-task.md 하단의 P9-R1, P9-R2 완료 기록과 관련 test 결과를 확인한다.
  3. 같은 항목이 한 문서에서는 미해결, 다른 문서에서는 완료로 표시되는 것을 확인한다.

영향

다음 reviewer와 구현자가 이미 완료된 회귀 Task를 다시 수행하거나 현재 남은 작업을 잘못 판단할 수 있다. 코드 기능보다 이력 추적의 정합성 문제다.

권장 조치

기존 내용을 삭제하지 않고 이전 리뷰의 상태를 수정 완료로 변경하고 날짜별 수정 후 검증 기록을 추가한다. 신규 2026-07-30 발견과는 구분한다.

판정 기록

  • 2026-07-30 — 이전 리뷰의 상태·최종 결론과 plan의 완료·Gate 기록을 대조해 확정.
  • 2026-07-30 — 과거 Phase 9 리뷰에 REV-P9-001~002 수정 완료 상태와 P9-R1~R2, P9-GATE 검증 기록을 누적해 완료.

REV-P9-004 — 일반 mutation 일부가 pending 중 중복 요청을 허용하고 비활성화 실패를 화면에 표시하지 않는다

  • 심각도: Medium
  • 상태: 수정 완료
  • 관련 요구사항: PRD §13 일반 mutation 중복 제출 차단·오류 복구
  • 관련 계약: Character/Audio/Series soft delete, Series link/unlink/order operation
  • 소유 Task: 신규 P9-R4

관찰 내용

공통 ConfirmDeactivateDialog에는 pending/disabled/error interface가 없고 Character·Audio·Series의 confirm handler도 guard와 catch가 없다. 요청이 끝나기 전에 확인을 다시 누르면 같은 soft-delete를 반복 호출할 수 있고 실패하면 visible 오류 없이 rejected Promise가 남는다. Series 연결·해제·순서 저장도 pending guard/state가 없어 버튼이 요청 중 계속 활성화된다.

근거

  • 공통 UI: src/shared/ui/confirm-deactivate-dialog.tsx:3-34
  • Character: src/features/characters/pages/CharacterDetailPage.tsx:53-76
  • Audio: src/features/audio-contents/components/AudioContentForm.tsx:172-178,228
  • Series: src/features/series/components/SeriesForm.tsx:152-157,191
  • Series link/order: src/features/series/components/SeriesContents.tsx:72-98,138-139, src/features/series/pages/SeriesOrderPage.tsx:79-92,118
  • 테스트 검색: 대상 흐름의 pending Promise 이중 입력·deactivate reject visible alert test 0건

재현 또는 검증 절차

  1. deactivate API Promise를 pending 상태로 유지하고 confirm 버튼을 빠르게 두 번 누르면 request가 두 번 호출된다.
  2. Promise를 reject하면 dialog/page에 오류 alert가 없고 호출부가 오류를 처리하지 않는다.
  3. 같은 방식으로 Series 연결·해제·순서 저장 버튼을 반복하면 pending 중 추가 request가 가능하다.

영향

느린 네트워크나 반복 입력에서 같은 mutation이 중복 전송되고 실패 원인과 재시도 방법을 운영자가 확인할 수 없다. soft-delete가 idempotent하더라도 요청 폭증과 잘못된 성공/오류 피드백이 발생할 수 있다.

권장 조치

각 mutation 경계에 synchronous guard와 pending state를 두고 controls를 비활성화한다. 공통 deactivate dialog에는 pending·오류 표시를 추가하되 서로 다른 도메인 mutation을 새 범용 hook으로 합치지 않는다.

판정 기록

  • 2026-07-30 — 관련 handler·dialog·test를 정적 대조해 pending guard와 오류 처리 부재를 확정.
  • 2026-07-30 — P9-R4에서 공통 deactivate dialog pending/error UI와 Character/Audio/Series deactivate, Series link/unlink/order pending guard를 추가하고 focused unit 검증으로 완료.

7. 확정 항목의 plan·goal 전환

  • REV-P9-003plan-task.md 신규 P9-R3
  • goal objective: [P9-R3] 이전 Phase 9 리뷰에 완료된 회귀 Task의 상태와 검증 이력을 누적해 문서 정합성을 복구한다.
  • REV-P9-004plan-task.md 신규 P9-R4
  • goal objective: [P9-R4] 일반 mutation의 pending 중복 차단과 비활성화 오류 복구를 보강한다.

8. 리뷰 종료 판정

판정 항목 결과 근거
리뷰 범위 전체 확인 충족 cross-cutting 코드·Gate·리뷰 이력 대조
후보 항목 판정 완료 충족 기존 1건 수정 완료, 신규 1건 확정
확정 항목 plan 반영 충족 P9-R3, P9-R4 완료
보류 항목의 담당·재개 조건 기록 해당 없음 보류 없음
검증 명령과 결과 기록 충족 §4

최종 결론: REV-P9-003, REV-P9-004 수정 완료

남은 항목: 실제 개발 API fixture가 필요한 integration은 P10-GATE 수동 QA로 분리한다.

9. 수정 후 검증 기록

P9-R3 수정 후 검증 — 2026-07-30

  • 무엇을: review-phase-9-20260729.mdREV-P9-001~002 상태, 판정 기록, 최종 결론, 남은 항목, 수정 후 검증 기록을 P9-R1~R2P9-GATE 완료 증거에 맞춰 누적했다.
  • 왜: 현재 리뷰의 REV-P9-003이 지적한 과거 리뷰와 최신 plan/Gate 상태의 불일치를 닫기 위해서다.
  • 검증: stale 현재 상태 검색과 git diff --check -- docs/20260725_AI캐릭터관리자웹를 통과했다.
  • 2026-07-30 — 2차 정적 점검에서 공통 deactivate 3개 흐름과 Series link/unlink/order의 pending guard, deactivate failure UI 부재를 확인했다. 애플리케이션 코드는 수정하지 않고 P9-R4로 전환했다.

P9-R4 수정 후 검증 — 2026-07-30

  • 무엇을: ConfirmDeactivateDialog에 pending/error UI를 추가하고, Character/Audio/Series 비활성화와 Series 연결·해제·순서 저장에 synchronous guard와 pending state를 추가했다.
  • 왜: 일반 mutation이 pending 중 중복 request를 보내지 않고 실패 후 운영자가 같은 화면에서 재시도할 수 있게 하기 위해서다.
  • 검증: npm run test:run -- src/features/characters/tests/CharacterDetailPage.test.tsx src/features/audio-contents/tests/audio-form-update.test.tsx src/features/series/tests/series-form.test.tsx src/shared/ui/__tests__/confirm-deactivate-dialog.test.tsx src/features/series/tests/series-order.test.tsx src/features/series/tests/series-contents.test.tsx 결과 6 files / 28 tests passed. 변경 test 파일 LSP diagnostics는 모두 clean이었다. E2E는 P10-R5까지 구현 후 최종 실행한다.

10. 2026-07-31 재점검

실행 결과

명령 결과 판정
npm run test:run 72 files / 360 tests passed 성공
npm run typecheck exit 0 성공
npm run lint exit 0 성공
npm run build exit 0, 255 modules transformed 성공
npm run e2e 36 passed 성공. sandbox의 listen EPERM 뒤 승인된 로컬 server 실행으로 재검증
npm run e2e:mock 205 passed / 22 skipped / 1 failed 당시 Mobile Safari Character dirty-leave dialog 미출현. 이후 지원 project 축소로 현재 Gate 대상 아님

신규 발견 요약

ID 심각도 상태 제목 소유 Task 후속 goal
REV-P9-005 Medium 수정 완료 Series mutation은 중복 guard만 있고 visible pending 상태가 없다 P9-R5 P9-R5

REV-P9-005 — Series mutation은 중복 guard만 있고 visible pending 상태가 없다

  • 심각도: Medium
  • 상태: 수정 완료
  • 관련 요구사항: PRD §10.5 저장 중 상태·300ms feedback, §13 일반 mutation 중복 제출 차단
  • 소유 Task: 신규 P9-R5

관찰 내용

Series 연결·해제·순서 저장은 useRef 동기 guard로 반복 request만 막는다. React pending state가 없어 link button, unlink dialog의 취소/확인, order 이동/저장 control은 request 중에도 활성 상태이며 aria-busy나 진행 문구가 없다. 이는 P9-R4의 완료 기록이 선언한 “pending state·disabled controls·aria-busy”와 현재 코드가 일치하지 않는 회귀다.

근거

  • 코드: src/features/series/components/SeriesContents.tsx:20-31,74-109,149-150,169-188
  • 코드: src/features/series/pages/SeriesOrderPage.tsx:48-55,80-99,118-126
  • 코드: src/features/series/components/SeriesOrderList.tsx:3-12
  • 계획 이력: plan-task.md 기존 P9-R4 Interfaces와 2026-07-30 GREEN 기록

재현 또는 검증 절차

  1. link/unlink/order API Promise를 pending으로 유지한다.
  2. mutation control을 누른 뒤 관련 button이 계속 enabled이고 진행 상태가 없는지 확인한다.
  3. 연타 request는 ref guard 때문에 1건이지만 운영자가 pending 여부를 알 수 없고 순서 이동 같은 다른 관련 control을 계속 조작할 수 있다.

영향 및 권장 수정 방향

느린 네트워크에서 저장 여부가 보이지 않고 request payload와 화면 순서를 다르게 바꿀 수 있다. 기존 ref guard는 보존하고 reactive pending state로 관련 control을 비활성화하며 accessible progress를 표시한 뒤 reject 시 재시도를 허용한다.

판정 기록:

  • 2026-07-31 — 현재 코드와 P9-R4 완료 인터페이스 및 PRD를 대조해 확정.
  • 2026-07-31 — P9-R5에서 Series link/unlink/order에 reactive pending state와 disabled/status UI를 추가하고 focused·Series unit·정적 Gate로 수정 완료.

plan·goal 전환 및 종료 판정

  • REV-P9-005P9-R5
  • 최종 결론: 신규 Medium 1건 수정 완료. Mobile Safari/WebKit 기반 후보는 현재 Playwright 지원 project에서 제외되어 Task로 전환하지 않는다.
  • 주의: 과거 Mobile Safari 실패 기록은 이력으로만 남기고 현재 자동 Gate 대상에는 포함하지 않는다.

11. 최종 Phase별 점검 — 2026-07-31

실행 결과

명령 또는 검증 결과 판정
Phase별 focused unit P0·1 64, shared 117, P3 43, P4 53, P5 37, P6 42, P7 13, P8 11 tests passed 성공
npm run typecheck / npm run lint / npm run build 모두 exit 0, build 255 modules 성공
npm run e2e 18/18 passed 성공. 현재 Chromium·Mobile Chrome 구성
npm run e2e:mock -- --project=chromium 57/57 passed 성공
일반 mutation handler·pending UI 정적 대조 일부 handler에 동기 guard·진행/실패 표시 없음 실패, 신규 finding 확정

신규 발견 요약

ID 심각도 상태 제목 소유 Task 후속 goal
REV-P9-006 Medium 수정 완료 일부 일반 mutation이 동기 재진입 차단과 접근 가능한 진행·실패 피드백을 보장하지 않는다 P9-R6 P9-R6

REV-P9-006 — 일부 일반 mutation이 동기 재진입 차단과 접근 가능한 진행·실패 피드백을 보장하지 않는다

  • 심각도: Medium
  • 상태: 수정 완료
  • 관련 요구사항: PRD §10.5 저장 중 상태·300ms 피드백, §13 일반 mutation 중복 제출 차단
  • 관련 계약: Series create/update, Community create/update/fixed, FanTalk reply/delete, Comments create/update/delete
  • 소유 Task: 신규 P9-R6

관찰 내용

Series form, Community create·Sheet save/fixed, Comments runMutation은 React isSaving만 설정하고 handler 진입 시 동기 guard를 확인하지 않는다. state가 반영되기 전 같은 submit/click이 재진입하면 동일 mutation을 다시 시작할 수 있다. 관련 submit button은 pending 뒤 disabled되지만 label·role=status·aria-busy가 없어 저장 진행을 전달하지 않는다.

FanTalk reply/delete는 isSavingRef로 중복 요청은 막지만 진행 표시가 없고, DELETE confirm dialog에 isPending·errorMessage를 전달하지 않는다. 특히 답변이 없는 원글에서 DELETE가 실패하면 visibleReply === null 조건 때문에 sheet 오류 alert도 렌더링되지 않는다.

근거

  • Series: src/features/series/components/SeriesForm.tsx:152-175,226
  • Community: src/features/community-posts/components/CommunityPostForm.tsx:117-139,159, CommunityPostSheet.tsx:37-51,100-111,179-185
  • FanTalk: src/features/fan-talks/components/FanTalkReplyForm.tsx:42-44, FanTalkReplySheet.tsx:40-88,115-120
  • Comments: src/features/comments/components/CommentThread.tsx:82-96,136-168, CommentForm.tsx:11-24,40-42, CommentItem.tsx:28-41
  • 테스트 공백: FanTalk reply 이중 submit과 일부 deactivate만 고정되어 있고 위 대상의 pending Promise 재진입·visible progress·미답변 DELETE reject 회귀는 없다.

재현 또는 검증 절차

  1. Series create 또는 Community create API를 pending Promise로 둔다.
  2. 같은 form에 submit event를 state rerender 전 연속 두 번 전달한다.
  3. 현재 handler에 동기 early return이 없어 request가 두 번 시작되는지 확인한다.
  4. FanTalk 미답변 item의 DELETE를 reject하고 dialog가 닫힌 뒤 오류 alert가 없는지 확인한다.
  5. 각 pending 상태에서 접근 가능한 progress text/aria-busy가 없는지 확인한다.

영향과 권장 조치

느린 네트워크·키보드 submit·자동화 입력에서 생성/수정 요청이 중복될 수 있고, 운영자는 저장 진행 또는 FanTalk 삭제 실패를 인지하지 못한다. backend idempotency나 새 상태 library를 추가하지 않고 각 mutation 경계에 ref 기반 최소 guard, 기존 isSaving 기반 disabled·status, 기존 confirm dialog pending/error prop을 연결한다.

판정 기록

  • 2026-07-31 — PRD 공통 상태·중복 제출 계약과 handler·UI·test를 도메인별로 대조해 확정.
  • 2026-07-31 — 중복 Phase Task를 만들지 않고 plan-task.md의 미완료 신규 Task P9-R6로 전환. 애플리케이션 코드는 이번 리뷰 범위에서 수정하지 않았다.
  • 2026-07-31 — P9-R6에서 Series form, Community create/Sheet save/fixed, Comments mutation, FanTalk DELETE에 동기 guard와 accessible pending/error feedback을 추가하고 focused/domain 검증으로 수정 완료.

plan·goal 전환 및 종료 판정

  • REV-P9-006plan-task.md 신규 P9-R6
  • 최종 결론: 신규 Medium 1건 수정 완료. Blocker/High 없음.
  • 남은 항목: 기존 실제 개발 API 수동 QA.

12. P9-R6 수정 후 검증 — 2026-07-31

  • 무엇을: Series form, Community create/Sheet save/fixed, Comments mutation, FanTalk 미답변 원글 DELETE의 pending 중 재진입 차단과 접근 가능한 진행·실패 피드백을 검증했다.
  • 왜: REV-P9-006의 일반 mutation 재진입·피드백 누락을 닫고, 기존 P9-R4·P9-R5 완료 범위와 중복되지 않는 도메인 경계만 보강했는지 확인하기 위해서다.
  • 검증: npm run test:run -- src/features/series/tests/series-form-pending.test.tsx src/features/community-posts/tests/community-mutation-pending.test.tsx src/features/comments/tests/comment-thread-pending.test.tsx src/features/fan-talks/tests/fan-talk-delete-pending.test.tsx는 4 files / 5 tests passed. npm run test:run -- src/features/community-posts/tests/community-sheet.test.tsx src/features/community-posts/tests/community-mutation-pending.test.tsx는 2 files / 9 tests passed. npm run test:run -- src/features/series src/features/comments는 12 files / 50 tests passed. npm run test:run -- src/features/fan-talks는 4 files / 14 tests passed.
  • 분리 기록: npm run test:run -- src/features/series src/features/community-posts src/features/comments src/features/fan-talks는 120초 timeout 중 community-sheet.test.tsx 목록 로딩 실패를 1건 표시했으나, 해당 spec 단독과 인접 pending spec 실행이 모두 통과해 P9-R6 코드 변경 실패가 아니라 넓은 병렬 suite의 비결정 로딩 실패로 분리한다.
  • E2E 검증: npm run e2e:mock -- tests/e2e/series.spec.ts tests/e2e/community.spec.ts tests/e2e/fan-talk.spec.ts tests/e2e/comments.spec.ts --project=chromium은 24 tests passed.
  • 정적 검증: 변경 TS/TSX 일부 LSP diagnostics는 3초 제한으로 timeout됐고, CommentThread.tsx, comment-thread-pending.test.tsx, FanTalkReplySheet.tsx, fan-talk-delete-pending.test.tsx는 diagnostics 0건이었다. 보완 검증으로 npm run typecheck, npm run lint, npm run build, 관련 파일 git diff --check를 실행했고 모두 exit 0이었다. build는 기존 500kB chunk warning만 표시했다.

13. 종합 재점검 — 2026-07-31

REV-P9-007 — Safari/WebKit 지원 project 제거로 완료 Gate가 축소됨

항목 내용
심각도 High
상태 수정 완료
관련 요구사항·계약 PRD §13 browser support, P9-T2 browser 자동 Gate, Phase 9 수용 기준
소유 Task P9-R7
설정·문서 근거 playwright.config.ts:34~37chromium, mobile-chrome만 정의하고 README Browser Support도 Safari를 제외한다. PRD prd.md:807과 완료된 P9-T2 checklist는 Safari desktop/mobile을 유지한다.
실행 근거 npx playwright test --list --project=webkit — exit 1, Project(s) "webkit" not found. Available projects: "chromium", "mobile-chrome".

재현 또는 검증 절차

  1. playwright.config.ts의 project 목록과 PRD §13, P9-T2 완료 checklist를 대조한다.
  2. npx playwright test --list --project=webkit--project=mobile-safari를 실행한다.
  3. 현재 두 project가 수집되지 않아 과거 4-project Gate와 같은 범위를 재실행할 수 없는지 확인한다.
  4. 현재 exact npm run e2e:mock 109 passed / 5 skipped와 npm run e2e 18/18이 Chromium·Mobile Chrome에만 해당함을 확인한다.

영향과 권장 조치

명시적으로 지원하는 browser 계열 절반이 자동 acceptance에서 빠졌고, 과거 Mobile Safari dirty-leave 실패를 project 제거로 종결한 기록은 PRD 변경 결정 없이 Gate를 약화한다. 기존 webkit·mobile-safari project를 복원하고, 재현되는 실패는 제품 코드/테스트/환경 원인을 분리해 수정한 뒤 exact full matrix를 다시 실행한다. Safari 지원 축소가 제품 결정이라면 코드부터 줄이지 말고 별도 결정으로 PRD를 먼저 변경해야 한다.

판정 기록

  • 2026-07-31 — 요구사항, 과거 Gate 완료 기록, 현재 config/README와 실제 project 수집 실패를 대조해 확정.
  • 2026-07-31 — 기존 완료 checklist를 되돌리지 않고 신규 P9-R7로 전환.
  • 2026-07-31 — P9-R7에서 webkit·mobile-safari project를 복원하고 full mock/server/static Gate를 재실행해 수정 완료로 전환.
  • 2026-07-31 — 후속 제품 결정으로 현재 지원·자동 검증 범위를 Chromium/mobile Chrome으로 축소했다. 이 finding은 과거 이력으로 보존한다.

수정 후 검증 기록

  • RED: npx playwright test --list --project=webkitnpx playwright test --list --project=mobile-safari는 project-not-found로 실패해 자동 Gate 축소를 재현했다.
  • Unit/static: npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts는 1 file / 4 tests passed. npm run typecheck, npm run lint, npm run build는 모두 exit 0이었다.
  • E2E: 최종 npm run e2e:mock은 Chromium 52 passed, WebKit 34+10 passed / 8 skipped, Mobile Chrome 47 passed / 5 skipped, Mobile Safari 34+9 passed / 9 skipped로 0 failure였다. npm run e2e는 server allowlist 36 passed였다.
  • 범위 분리: skipped 항목은 기존 keyboard-only/WebKit tab focus 또는 Chromium 전용 audio metadata case로 제한했고, 실제 Edge·Safari 기기 최신 2개 major 확인은 릴리스 QA 범위로 유지한다.

Phase 9 결론

  • 자동 검증: unit은 두 묶음 합계 77 files / 387 tests passed였고, P9-R7 focused docs test는 1 file / 4 tests passed였다. typecheck·lint·build exit 0, 당시 exact mock E2E와 server E2E는 통과했다. 현재 지원 Gate는 Chromium/mobile Chrome만 대상으로 한다.
  • 판정: REV-P9-007은 과거 P9-R7에서 수정 완료됐고, 후속 제품 결정으로 Safari/WebKit은 지원 범위에서 제외됐다.
  • 남은 위험: 기존 실제 개발 API QA만 별도다.

14. 요청 기준 재리뷰 — 2026-07-31

실행 결과

명령 또는 검증 결과 판정
npm run test:run 실패 78 files 중 2 failed / 76 passed, 394 tests 중 2 failed / 392 passed
focused mock 문서·mode test 실패 2 files, 2 failed / 5 passed로 동일 원인 재현
npm run typecheck, npm run lint 성공 모두 exit 0
npm run build:dev, npm run build:prod 성공 각 256 modules, 기존 502.94kB chunk warning만 존재
npm run e2e 성공 4 projects / 36 passed
npm run e2e:mock 성공 4 projects / 186 passed / 22 skipped / 0 failed
OpenAPI·금지 패턴·diff 정적 검사 성공 2.3.0, 25 paths / 37 implemented operations, 누락 schema ref·production 금지 패턴·diff 오류 0건

REV-P9-008 — 분할 mock E2E script가 문서·mode contract와 불일치해 전체 unit Gate가 실패함

  • 심각도: Low
  • 상태: 수정 완료
  • 관련 요구사항: MOCK-001~004, PRD §13 browser Gate, P9-GATE 전체 자동 검증 0 failure
  • 관련 계약: API payload 영향 없음. npm script의 bare/full·filtered/focused 실행 계약
  • 소유 Task: 신규 P9-R8

관찰 내용

P9-R7은 bare npm run e2e:mock을 네 browser project의 분할 script로 실행하고 인자가 있으면 Playwright에 전달하는 wrapper로 변경했다. README는 여전히 direct VITE_API_MODE=mock playwright test라고 설명하고, mode-boundary.test.ts도 같은 direct 문자열만 허용한다. mock-preview-docs.test.ts는 변경된 실제 script 전체가 README에 있어야 한다고 요구하므로 두 test가 동시에 실패한다.

근거

  • 코드: package.json:17~24
  • 문서: README.md:40~41, docs/agent-guide/scripts.md:12~13
  • 테스트: src/shared/mocks/__tests__/mode-boundary.test.ts:20~34, src/shared/mocks/__tests__/mock-preview-docs.test.ts:23~36
  • 실행: 전체 unit 2 failed / 392 passed, focused 실행 2 failed / 5 passed
  • 반대 근거: npm run e2e:mock -- --list --project=chromium 52 tests 정상 수집, exact mock matrix 186 passed / 22 skipped / 0 failed

재현 또는 검증 절차

  1. npm run test:run -- src/shared/mocks/__tests__/mode-boundary.test.ts src/shared/mocks/__tests__/mock-preview-docs.test.ts를 실행한다.
  2. mode test가 direct script 기대와 wrapper 차이로 실패하는지 확인한다.
  3. docs test가 README에 wrapper 전체 문자열이 없어서 실패하는지 확인한다.
  4. npm run e2e:mock -- --list --project=chromium으로 filtered 인자 전달 자체는 성공하는지 구분한다.

영향

제품 runtime과 브라우저 journey는 통과하지만 P9-GATE의 전체 unit 0 failure 조건이 깨지고, README 사용자는 bare 명령이 분할 full matrix를 실행한다는 사실을 알 수 없다.

권장 조치

bare/full과 filtered/focused의 공개 동작을 README·agent guide 한 기준으로 문서화하고, contract test는 긴 내부 shell 문자열 복제 대신 해당 public semantics와 VITE_API_MODE=mock 경계를 검증한다. Safari project나 E2E spec을 줄이지 않는다.

판정 기록

  • 2026-07-31 — 전체·focused unit에서 동일 2건을 재현하고 package/README/test 변경 이력을 역추적해 확정.
  • 2026-07-31 — runtime 인자 전달과 exact 4-project matrix는 통과해 기능 결함이 아닌 Low 문서·Gate 회귀로 판정.
  • 2026-07-31 — plan-task.md 신규 P9-R8로 전환. 애플리케이션 코드는 수정하지 않음.
  • 2026-07-31 — P9-R8에서 script/document contract test와 README·agent guide를 public 실행 의미 기준으로 정렬하고 full unit Gate를 복구해 수정 완료.

종료 판정

  • 최종 결론: REV-P9-008 수정 완료. Phase 9 unit Gate는 복구됐고 mock/server E2E pass 기록은 유지된다.
  • 남은 항목: 실제 개발 API 수동 QA.

15. P9-R8 수정 후 검증 — 2026-07-31

  • 무엇을: e2e:mock wrapper를 direct script 문자열로 고정하던 test와 README/agent guide 설명을 public 실행 의미 기준으로 정렬했다.
  • 왜: P9-R7에서 복원한 4-project mock matrix wrapper가 실제로는 통과하지만, unit contract와 README가 서로 다른 문자열을 기대해 전체 unit Gate가 실패했기 때문이다.
  • RED: npm run test:run -- src/shared/mocks/__tests__/mode-boundary.test.ts src/shared/mocks/__tests__/mock-preview-docs.test.ts — 2 failed / 5 passed.
  • GREEN/REFACTOR: focused script/docs contract는 2 files / 7 tests passed. npm run e2e:mock -- --list --project=chromium은 filtered 인자 전달로 52 tests를 수집했다. 내부 wrapper 전체 문자열을 README에 복제하지 않고, raw direct script와 분할 wrapper 책임을 test에서 분리했다.
  • Unit Gate: production-graph.test.tsaudio-list.test.tsx, community-sheet.test.tsx의 부하성 timeout을 단독 재현으로 분리하고 integration test timeout만 명시했다. 최종 npm run test:run은 78 files / 394 tests passed였다.
  • 정적 검증: npm run typecheck, npm run lint, 관련 git diff --check는 모두 exit 0이었다. E2E full matrix는 이번 요청 기준 재리뷰 직전 npm run e2e:mock 186 passed / 22 skipped / 0 failed와 npm run e2e 36 passed 기록을 보존하고, 개발 중 반복 E2E를 줄이라는 지시에 따라 재실행하지 않았다.

16. 최종 재검증 — 2026-07-31

  • 검토 범위: responsive/accessibility, error recovery, mock/server boundary, browser matrix와 전체 자동 Gate.
  • 실행 증거: test:run 78 files / 394 tests, e2e 36 tests, e2e:mock 186 passed / 22 skipped, typecheck·lint·개발/운영 build가 통과했다. UI/UX 기준 검색 결과 중 PRD와 충돌하는 dark/OLED 제안은 적용하지 않고 밝은 token, focus, keyboard, live error, 320px/200% zoom 기준만 대조했다.
  • 판정: Phase 9 소유의 별도 확정 신규 발견 사항 없음. 인증·upload lifecycle 두 건은 root-cause 파일 소유 Phase의 REV-P1-018/P1-R12, REV-P4-011/P4-R8로만 전환한다.
  • 남은 위험: 실제 개발 API와 위 두 신규 회귀 Task. Edge/Safari는 현재 지원 범위에서 제외한다.
  • 신규 Phase 9 Task: 없음.

17. 2026-07-31 문서 기준 재리뷰

검토 범위와 제외

  • 검토: Phase 0~10 공통 unit·type·lint·build·server/mock E2E Gate, responsive/accessibility test 구성, Vitest 격리·cleanup과 실패 후보 spec을 current working tree에서 재실행·대조했다.
  • 제외: 실제 Edge·Safari 기기 매트릭스와 개발 API credential이 필요한 수동 QA는 기존 대기 범위로 유지했다.

REV-P9-009 전체 unit Gate의 비결정적 loading·timeout 실패

항목 내용
심각도 Medium
상태 수정 완료
관련 요구사항 Phase 9 Gate 0 failure, 리뷰 가이드 §3·5 실제 검증 증거
소유 Task P9-R9

근거·재현

  • fresh npm run test:run -- --reporter=verbose는 exit 1, 79 files 중 5 failed / 74 passed, 397 tests 중 5 failed / 392 passed, 717.76초였다.
  • 실패는 CharacterWorkspaceLayout.test.tsx의 detail loading 잔류, community-sheet.test.tsxfan-talk-reply.test.tsx의 list loading 잔류, series-routes.test.tsx의 5초 timeout 등으로 나타났다. 이전 fresh full 실행에서는 Character mutation 등 실패 집합이 달라져 단일 기능 assertion의 재현성은 없었다.
  • 실패 후보 5개를 같이 실행한 npm run test:run -- src/features/community-posts/tests/community-sheet.test.tsx src/features/series/tests/series-routes.test.tsx src/layouts/CharacterWorkspaceLayout.test.tsx src/features/characters/tests/character-mutation-reload.test.tsx src/features/fan-talks/tests/fan-talk-reply.test.tsx는 exit 0, 5 files / 25 tests passed였다.
  • full output에는 touched integration spec의 React act(...) 미적용 warning과 loading 완료 전 assertion이 함께 관찰됐다. 단독 통과이므로 이를 제품 기능 실패로 판정하지는 않았다.

영향

  • Phase 9 Gate의 “전체 unit 0 failure” 조건이 현재 재현 가능하게 충족되지 않아 신규 수정의 안전한 release 회귀 기준으로 사용할 수 없다. 제품 data 손실·인증 우회는 이 항목에서 확인되지 않았다.

권장 조치·판정 기록

  • 전역 timeout 상향·skip·커버리지 축소로 가리지 말고, request·timer·history listener·React update의 완료·cleanup 경계를 축소 재현한 뒤 최소 수정한다.
  • 2026-07-31 — 두 차례 full 실행과 5-spec focused 실행을 대조해 Medium Gate 회귀로 확정. 완료된 P9-R8을 열지 않고 신규 P9-R9로 전환했다. 제품·test 코드는 수정하지 않았다.
  • 2026-07-31 — P9-R9에서 Character create mutation reload test가 보호 route probe 완료 전 form field를 조회하던 비동기 대기를 findByLabelText로 맞췄다. focused 1 file / 3 tests passed, 전체 unit은 2회 연속 81 files / 409 tests passed로 수정 완료했다.

REV-P9-010 bare mock WebKit Gate의 navigation·mutation 대기 비결정성

항목 내용
심각도 Medium
상태 수정 완료
관련 요구사항 PRD §14.2 4-browser matrix, P9-T2, P9-GATE
소유 Task P9-R10

근거·재현

  • fresh bare npm run e2e:mock은 Chromium 52 passed 후 WebKit main에서 2 failed / 32 passed / 7 skipped로 exit 1이었고, 후속 WebKit tail·Mobile Chrome·Mobile Safari segment를 실행하지 못했다.
  • Character 실패는 page.goto('/ai-characters/new')가 이전 login의 /ai-characters navigation에 의해 interruption된 경합이었다. FanTalk 실패는 기존 reply PUT 후 답변이 수정되었습니다. success status를 5초 안에 찾지 못했으며 동시에 목록 URL navigation 완료를 대기하고 있었다.
  • 동일 WebKit 두 test만 실행한 npm run e2e:mock -- tests/e2e/character-workspace.spec.ts tests/e2e/fan-talk.spec.ts --project=webkit --workers=1 --grep "direct create and edit routes|FanTalk mock journey"는 exit 0, 2 passed / 28.2초였다.

영향·권장 조치·판정 기록

  • 제품 기능 실패는 focused에서 재현되지 않았지만 bare release Gate가 중간에 중단되어 4-browser 증거를 새로 생성할 수 없으므로 Medium으로 판정했다.
  • login URL만이 아니라 보호 route ready까지 대기하고, FanTalk request→success→refetch/navigation의 시각 상태를 명시적으로 순서화한 뒤 WebKit 반복·bare full matrix를 재검증한다.
  • 2026-07-31 — bare 실패와 동일 focused 통과를 대조해 Gate 비결정성으로 확정. 신규 P9-R10으로 전환했고 제품·E2E 코드는 수정하지 않았다.
  • 2026-07-31 — 사용자 지시에 따라 추가 E2E는 Chromium·Mobile Chrome만 실행했다. P9-R10에서 login helper가 보호 route heading까지 기다리게 하고 FanTalk 수정 뒤 list-backed 버튼 상태를 기다리게 해 focused Chromium 2 passed, Mobile Chrome 2 passed로 수정 완료했다.

재리뷰 검증·종료 판정

  • 통과: npm run typecheck, npm run lint, npm run build:dev, npm run build:prod exit 0. server E2E는 Chromium·WebKit·Mobile Chrome·Mobile Safari 36 passed였다. build는 503.04kB chunk warning만 표시했다.
  • 실패: 전체 unit 5 failed / 392 passed, bare mock E2E는 Chromium 52 passed 후 WebKit main 2 failed / 32 passed / 7 skipped로 중단. unit 실패 후보 5-spec focused 25 passed, WebKit 실패 2-test focused 2 passed였다.
  • 판정: Medium 2건을 확정해 P9-R9~R10으로 전환했고, 둘 다 수정 완료했다. 오탐·보류로 남은 후보는 없다.
  • 남은 위험: WebKit·Mobile Safari 자동 E2E는 2026-07-31 사용자 지시에 따라 실행하지 않았다. 실제 browser 기기·개발 API 수동 QA는 계속 대기 상태다.

18. 수정 결과 재리뷰 — 2026-07-31

검토 범위와 실행 증거

  • P9-R9~R10, PRD §13, Playwright project, npm wrapper, README·agent guide와 contract test를 current staged working tree에서 대조했다.
  • 전체 npm run test:run — 두 차례 연속 각각 81 files / 409 tests passed. docs contract는 2 files / 7 tests passed했고 typecheck·lint·개발/운영 build·staged diff check도 통과했다.
  • npm run e2e:mock -- --list — Chromium/mobile Chrome만 12 files / 104 tests 수집. npm run e2e -- --list — 같은 두 project만 4 files / 18 tests 수집.
  • 수정된 Character/FanTalk focused mock E2E는 Chromium·mobile Chrome 합계 4/4 passed였다. WebKit·Mobile Safari는 지원 범위에서 제외해 실행하지 않았다.

REV-P9-011 — Chromium-only 결정과 현재 문서·smoke 경로가 불일치함

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 PRD §13·Decision Log, Chromium/mobile Chrome 지원 결정, P9-T2, 현재 P9-GATE
소유 Task 신규 P9-R11

근거·재현

  • executable 설정은 playwright.config.ts:34~37의 두 project, package.json:17~20의 두 분할 script로 정정됐고 contract test도 WebKit/mobile Safari 부재를 검증한다.
  • 반면 plan-task.mdP9-R8 기대 결과는 여전히 “mock matrix 4 projects”, 완료 기록은 “4-project 분할 script”를 현재 의미처럼 사용한다.
  • P9-R10 제목·Goal·실행 명령·기대 결과는 WebKit 반복과 bare 4-project matrix를 요구하면서 같은 Task의 완료 기록은 Chromium/mobile Chrome만 실행했다고 적는다.
  • 이 리뷰의 직전 최신 결론도 관련 요구사항을 “4-browser matrix”로 두고 WebKit/Mobile Safari 미실행을 남은 위험으로 표시한다.
  • PRD §13은 지원 범위를 Chrome/mobile Chrome으로 바꿨지만 Decision Log는 2026-07-29에서 끝나 변경 날짜·사유·Playwright/QA 영향 범위를 기록하지 않았다.
  • P9-R9 server smoke 명령은 존재하지 않는 tests/e2e/server-boundary.spec.ts를 사용한다. 실제 spec은 tests/e2e/server-mode-boundary.spec.ts다.

영향·권장 조치

현재 실행 코드는 두 project로 일치하지만 다음 에이전트가 완료 Task의 실행 계약을 기준으로 WebKit/mobile Safari를 복원하거나 존재하지 않는 smoke spec을 실행할 수 있다. PRD Decision Log에 Chrome-only 결정의 사유·영향을 추가하고, 과거 pass/failure 수치는 삭제하지 않은 채 당시 이력으로 표시하며 현재 실행 명령·기대 결과·최신 결론·smoke 경로와 docs contract를 정정한다.

판정 기록

  • 2026-07-31 — 현재 config/script/test의 104·18 test 수집, PRD Decision Log, P9-R8~R10·최신 리뷰 문구와 실제 spec 경로를 대조해 Low 확정.
  • 2026-07-31 — 완료된 P9-R8/R10을 다시 열지 않고 신규 P9-R11로 전환. 코드·test·설정은 수정하지 않았다.
  • 2026-07-31 — P9-R11에서 PRD Decision Log, 현재 Task 정의, docs contract와 최신 결론을 Chromium/mobile Chrome 기준으로 정렬해 수정 완료.

종료 판정

  • P9-R9은 전체 unit 두 차례 연속 409/409로, P9-R10의 현재 지원 project 흐름은 focused E2E 4/4로 유지됐다.
  • 최종 결론: REV-P9-011/P9-R11 문서 계약 수정 완료. 현재 자동 Gate 기준은 Chromium/mobile Chrome이며 실제 개발 API 수동 QA는 별도다.

19. P9-R11 수정 후 검증 기록 — 2026-07-31

  • RED: npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts — 1 failed / 4 passed. 신규 docs contract가 현재 P9-R8~R11 Task 정의의 mock matrix 4 projects, --project=webkit, 잘못된 server-boundary.spec.ts 경로를 검출했다.
  • GREEN/REFACTOR: PRD Decision Log에 Chrome-only 자동 Gate 결정을 추가하고, plan의 현재 Task 정의와 Phase 9 최신 결론을 Chromium/mobile Chrome·server-mode-boundary.spec.ts 기준으로 정정했다. 과거 네 browser project pass/failure 기록은 검증 이력으로 보존했다.
  • 검증: docs contract 2 files / 8 tests passed, mock list 104 tests와 server list 18 tests는 Chromium/mobile Chrome에서만 수집됐다. 실제 E2E 실행은 사용자 지시에 따라 생략했다.

20. P9-R11 수정 결과 재점검 — 2026-07-31

REV-P9-012 — Chromium-only 현재 문서 계약의 종료 증거가 불완전함

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 PRD Decision Log, P9-R11 완료 증거, docs contract 재현성
소유 Task 신규 P9-R12

근거·영향

  • PRD의 2026-07-31 결정 행은 날짜와 Playwright·QA 영향 범위는 기록하지만 Chrome-only로 축소한 사용자 결정 사유를 명시하지 않는다.
  • P9-R10의 현재 수동 확인은 여전히 “자동 WebKit harness 결정성 Task”라고 쓰고, 본 리뷰 상단 metadata도 P9-R11 수정 필요로 남았다. P9-R11 기대 결과는 2 files / 7 tests지만 실제 결과는 8 tests다.
  • docs contract는 올바른 server spec 경로를 P9-R9 block이 아니라 plan 전체에서 찾고 최신 결론부터 EOF까지 검사해 과거/후속 이력의 우연한 match로 통과할 수 있으며 P9-R11 종료 상태를 직접 고정하지 않는다.

권장 조치·판정 기록

  • Decision Log 사유, 현재 Task·리뷰 metadata·기대 test 수를 정정하고 contract가 P9-R9/최신 결론의 정확한 section만 검사하게 한다.
  • 2026-07-31 — executable config와 104·18 list는 정상임을 분리하고 Low 문서/test 계약으로 확정. 완료된 P9-R11을 다시 열지 않고 신규 P9-R12로 전환했다.

종료 판정

  • Playwright는 Chromium/mobile Chrome만 수집하고 잘못된 server-boundary.spec.ts 실행 경로는 현재 Task에서 제거됐다.
  • 검증: npm run test:run -- src/shared/mocks/__tests__/mode-boundary.test.ts src/shared/mocks/__tests__/mock-preview-docs.test.ts — 2 files / 8 tests passed. npm run e2e:mock -- --list는 Chromium/mobile Chrome 104 tests, npm run e2e -- --list는 Chromium/mobile Chrome 18 tests만 수집했다.
  • 최종 결론: REV-P9-012/P9-R12 수정 완료. WebKit·Mobile Safari는 현재 지원 범위가 아니다.

21. P9-R12 수정 결과 재점검 — 2026-07-31

검토 범위와 실행 증거

  • PRD §13·§16, P9-R9~R12, Phase 9 최신 review section, mock-preview-docs.test.ts와 실제 Playwright project를 대조했다.
  • docs contract 2 files / 8 tests가 통과했고 npm run e2e:mock -- --list는 104 tests, npm run e2e -- --list는 18 tests를 Chromium/mobile Chrome에서만 수집했다. Safari 계열 project는 실행하지 않았다.

REV-P9-013 — Decision Log 사유와 docs contract section 경계가 불완전함

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 PRD §13·§16, P9-R12 완료 증거, docs contract 재현성
소유 Task 신규 P9-R13

근거·영향

  • PRD Decision Log는 축소가 사용자 직접 지시라는 사실만 적고, 실제 지원 대상이 Chrome 2종뿐이며 불필요한 Safari 계열 실행이 테스트 시간을 크게 늘린다는 결정 근거를 남기지 않았다.
  • mock-preview-docs.test.ts는 위 사유를 PRD 전체 문자열로 검사하고 Phase 9 review를 특정 heading부터 EOF까지 잘라 검사한다. 후속 review에 같은 문자열이 추가되면 현재 Decision Log나 종료 판정이 stale해도 우연히 통과할 수 있다.
  • 현재 Playwright project와 수집 결과는 정상이며 제품·E2E 설정 결함은 아니다. 문제 범위는 결정 추적성과 회귀 test의 section 경계다.

권장 조치·판정 기록

  • PRD Decision Log에 지원 범위와 테스트 시간 근거를 명시하고, heading level 또는 명시적 종료 heading으로 PRD Decision Log와 최신 Phase 9 review/종료 판정만 추출해 검사한다.
  • 2026-07-31 — source scope와 사용자 결정 근거를 원문 대조해 Low로 확정. 완료된 P9-R12를 다시 열지 않고 신규 P9-R13으로 전환했다.

종료 판정

  • Chromium/mobile Chrome 2-project 실행 계약과 P9-R12의 현재 기능 결과는 유지된다.
  • 최종 결론: REV-P9-013 후속 goal 필요. P9-R13을 plan에 추가했다.

22. P9-R13 수정 결과 검증 — 2026-07-31

검토 범위와 실행 증거

  • PRD §16 Decision Log의 Chrome-only 결정 행, P9-R13 plan block, Phase 9 최신 review section, mock-preview-docs.test.ts를 대조했다.
  • RED: npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts — 1 file / 2 failed / 3 passed. PRD 결정 행의 Chrome 2종·테스트 시간 근거 누락과 ## 22. P9-R13 수정 결과 검증 section 부재를 검출했다.
  • GREEN: PRD Decision Log에 Chrome 2종 지원 범위와 Safari 계열 실행의 테스트 시간 영향을 명시하고, docs contract가 PRD Decision Log와 Phase 9 최신 section만 검사하도록 닫았다.

종료 판정

  • 최종 결론: REV-P9-013/P9-R13 수정 완료. Chrome 2종과 테스트 시간 근거가 PRD Decision Log에 남았고, 최신 Phase 9 종료 판정은 후속 review section의 우연한 문자열에 의존하지 않는다.
  • 남은 항목: P10-R12, 실제 crop pixel·stale ADMIN server QA, 실제 개발 API Series/FanTalk/Comments/file policy 수동 QA.

23. P9-R13·P10-R12 수정 결과 재리뷰 — 2026-07-31

검토 범위와 실행 증거

  • PRD Decision Log, mock-preview-docs.test.ts, Community Sheet focus test와 full unit Gate를 current working tree에서 대조했다.
  • docs contract 2 files / 8 tests, typecheck, lint, 개발/운영 build와 diff 검사는 통과했다. Playwright 목록은 Chromium/mobile Chrome에서만 mock 104 tests와 server 18 tests를 수집했다.
  • 첫 fresh full unit은 Community Sheet focus assertion 1 failed / 416 passed, 두 번째 fresh full은 81 files / 417 tests passed였다. 동일 focus test 단독 5회는 모두 통과했다.

REV-P9-014 — Community Sheet focus 반환 test가 full load에서 경합함

항목 내용
심각도 Medium
상태 수정 완료
관련 요구사항 Phase 9 전체 unit Gate, keyboard·focus 회귀, P9-R9 결정성 완료 증거
소유 Task 신규 P9-R14

근거·영향

  • community-sheet.test.tsx:82는 비활성화 dialog 취소 직후 trigger focus를 동기 assertion한다. 공통 ConfirmDeactivateDialog test는 같은 effect cleanup focus 반환을 waitFor로 관찰한다.
  • full load에서는 부모 Community Sheet의 refetch/remount focus effect와 중첩 dialog cleanup이 경합해 닫기 button이 focus를 받았고, 단독 5회와 다음 full에서는 통과했다.
  • 제품 focus 구현 변경의 증거는 없지만 동일 working tree의 full Gate가 통과와 실패를 오가므로 완료 증거를 신뢰할 수 없다.

권장 조치·판정 기록

  • 공통 dialog test와 동일하게 effect 완료를 기다리는 최소 waitFor로 assertion을 맞추고 임의 timeout·retry 없이 focused 반복 5회와 full unit 2회로 검증한다.
  • 2026-07-31 — fresh full 실패, focused 5회 통과, 다음 fresh full 통과를 대조해 Medium 비결정성으로 확정. 완료된 P9-R9을 다시 열지 않고 신규 P9-R14로 전환했다.
  • 2026-07-31 — P9-R14에서 제품 focus 구현은 변경하지 않고 Community Sheet test의 취소 후 trigger focus assertion만 waitFor로 맞췄다. focused 반복 5회는 모두 1 passed / 6 skipped, full unit 2회는 모두 81 files / 417 tests passed였다. typecheck, lint, build:dev, build:prod, targeted git diff --check도 통과했다.

REV-P9-015 — PRD Decision Log·최신 종료 판정이 정확한 heading에서 닫히지 않음

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 P9-R13 완료 증거, docs contract section 재현성
소유 Task 신규 P9-R15

근거·영향

  • mock-preview-docs.test.ts:91은 PRD Decision Log를 sectionFrom()으로 EOF까지 읽고, 115행의 최신 종료 판정도 이미 H2까지만 닫힌 block 안에서 다음 H3를 구분하지 않고 끝까지 읽는다.
  • 메모리 negative-control에서 Chrome-only 결정 행을 후속 H2로 옮기거나 완료 문구를 후속 H3로 옮겨도 현재 assertion이 통과했다.
  • 실제 PRD 결정 내용과 현재 P9-R13 결론은 올바르지만, 후속 section이 추가되면 stale 현재 section이 우연히 통과할 수 있다.

권장 조치·판정 기록

  • heading 행을 anchor하고 동일·상위 level의 다음 heading에서 닫는 helper 하나로 PRD H2, 최신 Phase 9 H2와 종료 판정 H3를 각각 추출한다. synthetic 후속 H2/H3 negative test를 남긴다.
  • 2026-07-31 — 결정 행·완료 문구 이동 negative-control이 모두 통과함을 재현해 Low로 확정. 완료된 P9-R13을 다시 열지 않고 신규 P9-R15로 전환했다.
  • 2026-07-31 — P9-R15에서 heading level 기반 helper로 PRD Decision Log와 Phase 9 종료 판정 section을 닫고 synthetic 후속 H2/H3 negative assertion을 남겼다. docs contract 2 files / 8 tests, mock/server Playwright list, Markdown link 검사와 targeted diff check가 통과했다.

종료 판정

  • Chrome 2종 지원 결정과 Playwright 2-project 설정 자체는 유지된다.
  • 최종 결론: REV-P9-014~015/P9-R14~R15 수정 완료. 다음 순서는 Phase 10 P10-R13이다.

24. P9-R14~R15 수정 결과 재점검 — 2026-07-31

검토 범위와 실행 증거

  • Community Sheet focus assertion, Markdown section helper, Phase 9 최신 H2와 P9-R14~R15 완료 기록을 current working tree에서 대조했다.
  • focused Community Sheet test는 5회 모두 1 passed / 6 skipped였고 fresh full unit은 81 files / 418 tests passed였다. finding 기록 전 docs contract는 2 files / 9 tests, typecheck, lint, 개발/운영 build도 통과했다. finding과 신규 Task를 current-state에 반영한 뒤 docs contract는 기존 자동 보완 완료 기대를 실패시켜 1 failed / 8 passed RED가 됐다.
  • Playwright --list는 mock 104 tests와 server 18 tests를 Chromium/mobile Chrome에서만 수집했다. WebKit·Mobile Safari는 실행하지 않았다.
  • negative control에서 목표 heading 뒤 임의 suffix를 붙인 H2가 exact target으로 선택됐고, 실제 contract가 최신 Phase 9 H2가 아니라 과거 ## 22. P9-R13 수정 결과 검증을 계속 검사함을 확인했다.

REV-P9-016 — exact heading contract가 임의 suffix와 과거 Phase 9 H2를 허용함

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 P9-R15 exact heading anchor·최신 종료 판정 완료 증거
소유 Task 신규 P9-R16

근거·영향

  • sectionAtHeading()line === heading 외에 line.startsWith(`${heading} `)도 허용한다. 날짜 suffix만을 위한 조건이 아니라 임의 suffix를 모두 받으므로 다른 H2를 목표 heading으로 오인할 수 있다.
  • Phase 9 contract는 현재 최신 H2가 아닌 과거 ## 22. P9-R13 수정 결과 검증과 그 종료 판정을 추출한다. 이후 P9-R14~R15 완료 또는 신규 finding이 stale해도 현재 계약은 이를 읽지 않는다.
  • 제품 focus 동작, Chrome 2종 지원 결정과 Playwright 설정에는 신규 결함이 없지만 문서 완료 증거는 후속 section에서 false positive가 가능하다.

권장 조치·판정 기록

  • helper를 전체 heading 행 exact match로 축소하고 호출부가 날짜를 포함한 실제 최신 H2를 명시하게 한다. 최신 H2 내부 종료 판정도 별도로 닫고 임의 suffix·과거 H2 negative assertion을 남긴다.
  • 2026-07-31 — synthetic heading collision과 실제 H2 대상 불일치를 재현해 Low로 확정. 완료된 P9-R15를 다시 열지 않고 신규 P9-R16으로 전환했다.
  • 2026-07-31 — P9-R16에서 sectionAtHeading()을 전체 heading 행 exact match로 축소하고 Phase 9 contract 대상을 최신 ## 24. P9-R14~R15 수정 결과 재점검 — 2026-07-31와 내부 ### 종료 판정으로 옮겼다. 임의 suffix·후속 H2/H3 false positive assertion을 남겨 수정 완료로 판정했다.
  • 수정 후 검증: docs contract 2 files / 9 tests passed, typecheck, lint, 필수 12 section 검사, Markdown link 검사, git diff --check 모두 exit 0. Playwright --list는 mock 104 tests와 server 18 tests를 Chromium/mobile Chrome에서만 수집했다.

종료 판정

  • REV-P9-014의 focus test 수정은 focused 5회와 fresh full unit에서 재현됐고 신규 제품 문제는 확인되지 않았다.
  • 최종 결론: REV-P9-016/P9-R16 수정 완료. P10-R14 후속 goal 필요. Chromium/mobile Chrome 2-project 지원 범위는 유지한다.

25. P9-R16·P10-R14 수정 결과 재점검 — 2026-08-01

검토 범위와 실행 증거

  • P9-R16 exact heading helper와 Phase 9 H2/H3 negative-control, P10-R14 완료 뒤 Phase 9 metadata·최신 결론을 current working tree에서 대조했다.
  • finding 기록 전 docs contract 2 files / 9 tests, fresh full unit 81 files / 418 tests, typecheck, lint가 통과했다. Playwright --list는 Chromium/mobile Chrome에서만 mock 104 tests와 server 18 tests를 수집했다. 신규 finding과 Task를 current-state에 반영한 뒤 docs contract는 기존 자동 보완 완료 기대를 실패시켜 1 failed / 8 passed RED가 됐다.
  • Phase 9 review 상단과 마지막 H2 결론은 완료된 P10-R14를 계속 후속 필요로 표시하지만 current test는 metadata를 읽지 않고 ## 24를 고정 대상으로 사용해 통과했다.

REV-P9-017 — Phase 9 current metadata가 완료된 P10-R14를 후속으로 유지함

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 review current metadata·최신 판정, P9-R16 최신 H2 contract
소유 Task 신규 P9-R17

근거·영향

  • Phase 9 상단 리뷰 상태## 24 종료 판정은 P10-R14 후속 필요를 유지하지만 plan top과 Phase 10 review는 P10-R14 완료를 선언한다.
  • docs contract는 Phase 9 metadata를 추출하지 않고 ## 24를 최신 H2로 고정하며 해당 H2가 문서의 마지막 H2인지도 확인하지 않아 이후 append-only section을 현재 판정으로 사용하지 않는다.
  • 제품·Chrome 2종 설정에는 영향이 없지만 다음 실행자가 완료된 P10-R14를 다시 열 수 있다.

권장 조치·판정 기록

  • 과거 ## 24 결론은 보존하고 현재 상태를 기록하는 새 H2를 append한다. Phase 9 metadata·실제 마지막 H2·내부 종료 판정을 독립 추출해 P10-R14 완료와 남은 수동 QA를 검사하고 trailing H2 negative-control을 남긴다.
  • 2026-08-01 — plan/Phase 10 완료 상태와 Phase 9 metadata·고정 H2를 대조해 Low로 확정. 완료된 P9-R16을 다시 열지 않고 신규 P9-R17로 전환했다.
  • 2026-08-01 — P9-R17에서 metadata·실제 마지막 H2·종료 판정을 동기화하고 docs contract 2 files / 9 tests를 통과해 수정 완료로 판정했다.

종료 판정

  • REV-P9-016 exact heading 수정과 negative-control은 fresh docs contract에서 재현됐다.
  • 최종 결론: REV-P9-017 후속 goal 필요. P9-R17을 plan에 추가했으며 Chromium/mobile Chrome 지원 범위는 유지한다.

26. P9-R17 수정 후 검증 — 2026-08-01

검토 범위와 실행 증거

  • Phase 9 metadata, 실제 마지막 H2와 내부 종료 판정을 독립 scope로 대조하게 했다.
  • RED: npm run test:run -- src/shared/mocks/__tests__/mock-preview-docs.test.ts -t "keeps current Phase 9" — 1 file / 1 failed / 5 skipped. Phase 9 metadata가 P9-R17 완료를 담지 않아 실패했다.
  • GREEN: REV-P9-017/P9-R17 current-state를 append-only 최신 H2로 기록하고, 과거 ## 24·## 25 판정은 보존했다. focused GREEN은 1 file / 1 passed / 5 skipped, docs contract는 2 files / 9 tests passed였다. Chromium/mobile Chrome 2-project 지원 범위와 실제 crop pixel·stale ADMIN·Series/FanTalk/Comments/file policy 수동 QA 대기는 유지한다.

종료 판정

  • 최종 결론: REV-P9-017/P9-R17 수정 완료. P10-R15 완료 후 자동 보완 Task는 완료됐고 Chromium/mobile Chrome 2-project 지원 범위는 유지한다. 실제 crop pixel·stale ADMIN server 확인과 실제 개발 API Series/FanTalk/Comments/file policy 수동 QA가 남았다.

27. P9-R17 수정 결과 재점검 — 2026-08-01

검토 범위와 실행 증거

  • P9-R17의 metadata·실제 마지막 H2·종료 판정 동기화와 docs contract helper를 current working tree에서 재검토했다.
  • finding 기록 전 docs contract는 2 files / 9 tests, 전체 unit은 81 files / 418 tests가 통과했고 typecheck, lint도 exit 0이었다. Playwright --list는 Chromium/mobile Chrome에서만 mock 104 tests와 server 18 tests를 수집했다.
  • 신규 finding·Task를 current-state에 반영한 뒤 docs contract는 2 files 중 1 failed / 1 passed, 9 tests 중 2 failed / 7 passed의 RED가 됐다. Phase 9 실패는 P9-R17 범위가 후속 미완료 Task를 포함한 경계에서 발생했다. 필수 section 12/12, Markdown link broken 0, git diff --check는 통과했다.
  • P9-R17 수정 자체는 재현됐지만 소유 finding 상태와 append-only Task 경계, 최신 H2 helper의 Markdown fence·동일 제목 경계를 contract가 보장하지 않는다.

REV-P9-018 — 완료 결론과 소유 finding·Task checklist 범위가 불일치함

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 review finding lifecycle, 완료 Task checklist의 독립 범위
소유 Task 신규 P9-R18

근거·영향

  • metadata와 ## 26REV-P9-017/P9-R17 수정 완료를 선언하지만 REV-P9-017 표의 상태는 확정으로 남아 있다. 완료 날짜별 근거도 해당 finding의 판정 기록에 없다.
  • docs contract는 REV-P9-017 표를 검사하지 않으며 P9-R17 Task를 다음 Phase의 ### Task R10.1까지 추출한다. 따라서 정상적인 후속 Phase 9 Task append가 완료된 P9-R17 checklist 실패로 섞인다.
  • 제품 동작에는 영향이 없지만 현재 finding 상태와 완료 증거를 자동으로 신뢰할 수 없다.

권장 조치·판정 기록

  • REV-P9-017 상태를 수정 완료로 종결하고 2026-08-01 검증 근거를 append한다. P9-R17 Task는 바로 다음 Task에서 닫아 소유 finding·checklist·metadata·최신 결론을 함께 검사한다.
  • 2026-08-01 — 실제 표와 section 범위를 대조해 Low로 확정. 완료된 P9-R17을 다시 열지 않고 신규 P9-R18로 전환했다.
  • 2026-08-01 — P9-R17 범위를 다음 H3에서 닫고 REV-P9-017·REV-P9-018 상태와 날짜별 근거를 직접 검사하게 해 수정 완료로 판정했다.

REV-P9-019 — 최신 H2 helper가 fenced heading과 동일 제목을 오인함

항목 내용
심각도 Low
상태 수정 완료
관련 요구사항 Phase 9 실제 마지막 H2·종료 판정 current-state contract
소유 Task 신규 P9-R19

근거·영향

  • latestSectionAtLevel()은 fence 상태 없이 문서 뒤에서 ## 행을 찾으므로 fenced code 안의 heading 예시를 실제 마지막 H2로 선택한다.
  • 찾은 heading 문자열을 sectionAtHeading()에 다시 넘기며 첫 exact occurrence를 사용하므로 같은 제목이 반복되면 실제 마지막 section이 아니라 앞선 section을 반환한다.
  • 문서가 코드 예시나 정정용 동일 제목을 append하면 current-state assertion이 잘못된 section을 검사하거나 원인과 무관하게 실패한다.

권장 조치·판정 기록

  • 새 parser dependency 없이 기존 helper가 backtick·tilde fence를 제외하고 찾은 마지막 H2 index에서 section을 직접 추출하게 한다. 두 synthetic negative-control을 남긴다.
  • 2026-08-01 — fence와 동일 제목 synthetic 문서로 잘못된 section 선택을 재현해 Low로 확정. P9-R18 뒤 신규 P9-R19로 전환했다.
  • 2026-08-01 — fence 밖 heading index를 한 번 수집해 마지막 실제 H2를 직접 추출하고 backtick·tilde fence와 동일 제목 회귀 2건을 통과해 수정 완료로 판정했다.

종료 판정

  • P9-R17의 metadata·최신 결론 수정과 Chromium/mobile Chrome 2-project 범위는 확인됐다.
  • 최종 결론: REV-P9-018~REV-P9-019 후속 goal 필요. P9-R18P9-R19를 plan에 추가했으며 실제 crop pixel·stale ADMIN server 및 개발 API 수동 QA는 별도 대기다.

28. P9-R18~R19 수정 후 검증 — 2026-08-01

검토 범위와 실행 증거

  • P9-R18P9-R17 Task를 다음 H3에서 닫고 REV-P9-017·REV-P9-018의 상태·날짜별 근거를 current contract에 포함했다. Phase 9 metadata는 Phase 10 current Task를 중복 소유하지 않는다.
  • RED: keeps current Phase 9 focused test가 REV-P9-017확정 상태로 1 failed / 5 skipped였고, checklist assertion 추가 뒤에는 P9-R18~P9-R19 미완료 상태로 1 failed / 7 skipped였다.
  • P9-R19 RED는 fenced heading과 동일 제목 synthetic 2건이 모두 실패했다. 실제 마지막 H2 index를 직접 사용하도록 최소 수정한 GREEN은 2 passed / 6 skipped였다.
  • GREEN/회귀: Phase 9 current-state와 두 synthetic focused는 3 passed / 5 skipped, docs contract는 2 files / 12 tests passed였다.
  • 전체 검증: 81 files / 421 tests, typecheck, lint, 필수 section·Markdown link·diff 검사가 통과했다. Playwright 목록은 Chromium/mobile Chrome만 mock 104 tests와 server 18 tests를 수집했다.

종료 판정

  • 최종 결론: REV-P9-018REV-P9-019/P9-R18P9-R19 수정 완료. Chromium/mobile Chrome 2-project 지원 범위는 유지하며 자동 보완 Task는 완료됐다. 실제 crop pixel·stale ADMIN server 확인과 실제 개발 API Series/FanTalk/Comments/file policy 수동 QA가 남았다.