Files
voiceon-character-admin/docs/20260805_오디오콘텐츠댓글답글/plan-task.md

239 lines
13 KiB
Markdown

# 오디오 콘텐츠 댓글 답글 작성 진입 구현 계획
| 문서 항목 | 내용 |
|---|---|
| 상태 | 기능 구현·검증 및 `P1-R1` 문서 정합성 보완 완료 |
| 작성일 | 2026-08-05 |
| 요구사항 기준 | [prd.md](./prd.md) |
| API 기준 | [api-contract.md](./api-contract.md) |
| 현재 Phase | Phase 1 구현·검증 |
| 현재 활성 Goal | 없음 |
## 목표
활성 오디오 콘텐츠의 답글 0개 원댓글에서도 기존 답글 form을 열어 첫 답글을
작성할 수 있게 한다.
## 현재 상태
| Phase | 상태 | 완료 Task | 활성/다음 Goal | 남은 조건 |
|---:|---|---:|---|---|
| 1 | 완료 | `2/2` | 없음 | 없음 |
- 답글 API, form, 조회·작성·재조회 흐름은 이미 구현돼 있다.
- 활성 Audio의 `replyCount === 0` root에는 `답글 작성` 진입이 구현돼 있다.
- unit·mock E2E와 정적 검증이 완료됐고 애플리케이션 코드와 test가 현재 working tree에 반영돼 있다.
## 범위의 포함·제외
### 포함
- 활성 Audio root의 `replyCount === 0`일 때 `답글 작성` 버튼 표시
- 기존 답글 영역, form, GET·POST와 mutation 상태 재사용
- Audio 첫 답글과 Community·비활성·reply row 경계 회귀 test
- 기존 Comments Chromium mock E2E와 정적 검증
### 제외
- Community 댓글 답글 진입 조건 변경
- 새 endpoint, DTO, component, state library 또는 dependency
- form 상시 노출, reply-of-reply, payload 정책 변경
- 기존 답글 수정·삭제·pagination 리팩터링
## 기술적 제약
- React·TypeScript strict, Vitest·React Testing Library와 기존 Playwright 구성을 사용한다.
- [api-contract.md](./api-contract.md)의 기존 GET·POST만 사용한다.
- `CommentThread`, `CommentItem`, `CommentForm`의 현재 책임 경계를 유지한다.
- 새 추상화보다 기존 reply state와 `toggleReplies()`를 재사용한다.
- RED → GREEN → REFACTOR 순서와 최소 변경을 지킨다.
## Phase 1. 첫 답글 작성 진입 구현·검증
**Phase 결과:** 관리자가 활성 Audio의 답글 0개 원댓글에서 첫 답글을 작성하고
기존 Community·읽기 전용·2단계 경계가 유지된다.
**선행조건:** `ACR-001~005`와 기존 Audio 댓글 GET·POST 계약 확정.
**Phase 완료 조건:** `P1-T1`, `P1-GATE` 완료와 Progress 기록.
### Task 1.1 오디오 첫 답글 진입
**Goal 실행 `P1-T1`:** Audio의 답글 0개 원댓글에 기존 답글 영역을 여는
`답글 작성` action을 추가한다.
- **시작 조건:** [prd.md](./prd.md)의 `ACR-001~005`, [api-contract.md](./api-contract.md).
- **완료 증거:** TDD 체크박스, focused·회귀·E2E·정적 검증과 Progress 기록.
- **범위 밖:** Community 변경, API·mock·schema 변경, 관련 없는 Comments 리팩터링.
**Files:**
- Modify: `src/features/comments/components/CommentThread.tsx`
- Modify: `src/features/comments/components/CommentItem.tsx`
- Modify: `src/features/comments/tests/comment-thread.test.tsx`
- Modify: `tests/e2e/comments.spec.ts`
- Test: `src/features/comments/tests/comment-thread.test.tsx`, `tests/e2e/comments.spec.ts`
**Interfaces:**
- Consumes: `CommentRecord.replyCount`, `CommentTarget.kind`, `canMutate`, `toggleReplies()`, `CommentForm`, `createComment()`.
- Produces: `CommentItem`의 optional 답글 action label과 Audio 첫 답글 진입 조건.
**TDD 절차:**
- [x] **RED:** `comment-thread.test.tsx`에 Audio `replyCount=0` root의 `답글 작성` 노출, 클릭 후 form, `parentId` POST와 Community·비활성·reply row 신규 action 0건을 검증하는 실패 test를 작성하고 focused 명령의 의도한 실패를 확인한다.
- [x] **GREEN:** `CommentThread``CommentItem`에 action label·노출 조건만 추가해 기존 reply 조회·form·POST 흐름으로 test를 통과시킨다.
- [x] **REFACTOR:** 기존 `showRepliesButton` boolean을 optional action label로 단순화하고 새 helper·component·dependency 없이 focused·Comments 회귀를 확인한다.
- [x] 기존 Audio mock E2E에서 답글 0개 root의 첫 답글 작성 journey를 검증한다.
- [x] 검증 결과를 Progress에 기록한다.
**검증 기준:**
- **실행 명령:** `npm run test:run -- src/features/comments/tests/comment-thread.test.tsx`; `npm run test:run -- src/features/comments`; `npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium`; `npm run typecheck`; `npm run lint`.
- **기대 결과:** 모든 명령 exit 0, Audio 첫 답글 POST 1회, Community·비활성·reply row 신규 action 0건, 기존 Comments 회귀 실패 0건.
- **수동 확인:** 활성 Audio 상세에서 답글 0개 root의 `답글 작성` → form 노출 → 성공 후 목록 반영을 확인한다. Community와 비활성 Audio는 기존 동작을 유지한다.
### 완료 조건
- [x] `P1-T1`의 모든 TDD·검증 체크박스가 완료됐다.
- [x] `ACR-001~005`가 구현 또는 검증 증거에 연결됐다.
- [x] API·mock·schema와 범위 밖 파일 변경이 없다.
### 검증 방법
#### Phase 1 Gate
**Goal 실행 `P1-GATE`:** 첫 답글 journey와 Comments 경계를 최종 판정한다.
- **시작 조건:** `P1-T1` 완료.
- **완료 증거:** 아래 명령·수동 확인 통과와 Progress 기록.
- **범위 밖:** test 완화, timeout 상향과 관련 없는 수정.
**실행 명령:**
```bash
npm run test:run -- src/features/comments
npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium
npm run typecheck
npm run lint
git diff --check
```
**기대 결과:** 모든 명령 exit 0, `ACR-001~005` 위반 0건.
**수동 확인:** 활성 Audio, 비활성 Audio와 Community에서 action 노출 경계를
대조하고 keyboard-only로 첫 답글을 작성한다.
### Task R1.1 완료 문서 상태 정합성 복구
**Goal 실행 `P1-R1`:** `REV-P1-001`의 완료·미구현 상태 모순을 제거하고
실제 검증 증거와 PRD·plan을 일치시킨다.
- **연결 리뷰:** [Phase 1 구현 리뷰](./reviews/phase1-audio-comment-first-reply.md) — `REV-P1-001`
- **시작 조건:** `REV-P1-001` 확정, 완료된 `P1-T1`, `P1-GATE`.
- **완료 증거:** 현재 상태·발견된 문제·PRD §14 정정, 기존 Progress 보존, 리뷰 수정 후 검증 기록과 문서 검증 통과.
- **범위 밖:** 애플리케이션 코드·test·API Contract 변경, 기존 설계·구현 Progress 삭제.
**Files:**
- Modify: `docs/20260805_오디오콘텐츠댓글답글/prd.md`
- Modify: `docs/20260805_오디오콘텐츠댓글답글/plan-task.md`
- Modify: `docs/20260805_오디오콘텐츠댓글답글/reviews/phase1-audio-comment-first-reply.md`
- Test: 없음 — 구현 동작이 아닌 완료 문서 정합성 수정이다.
**Interfaces:**
- Consumes: `REV-P1-001`, `ACR-001~005`, `P1-T1`, `P1-GATE`와 2026-08-05 검증 증거.
- Produces: 실제 구현 상태와 일치하는 PRD 수용 기준, plan 현재 상태와 review 수정 완료 기록.
**TDD 예외 사유:** 애플리케이션 동작을 변경하지 않는 문서 정합성 Task이므로
실패 unit test를 추가하지 않는다.
**대체 검증 방법:** stale 미구현 marker와 PRD §14 미완료 checkbox가 제거됐는지
검사하고 review link와 Markdown diff를 확인한다.
- [x] 현재 상태의 미구현 문구를 실제 구현 완료 상태로 정정한다.
- [x] PRD §14 수용·추적 체크박스를 검증 증거에 맞게 완료 처리한다.
- [x] 발견된 문제를 `REV-P1-001` 문서 정합성 보완 상태로 정정한다.
- [x] 기존 Progress를 보존하고 `P1-R1`의 무엇을/왜/어떻게 검증 기록을 누적한다.
- [x] review 상태를 `수정 완료`로 갱신하고 수정 후 검증 기록을 누적한다.
**검증 기준:**
- **실행 명령:** `! rg -n '^- 현재 .*답글 진입 버튼이 없다|^- 애플리케이션 코드와 test는 아직 변경하지 않았다|^- 확정: .*첫 답글 작성 진입이 없다' docs/20260805_오디오콘텐츠댓글답글/plan-task.md`; `! sed -n '/## 14\./,/## 15\./p' docs/20260805_오디오콘텐츠댓글답글/prd.md | rg -n '^- \[ \]'`; `test -f docs/20260805_오디오콘텐츠댓글답글/reviews/phase1-audio-comment-first-reply.md`; `git diff --check`.
- **기대 결과:** 모든 명령 exit 0, stale 미구현 marker와 PRD §14 미완료 checkbox 0건, review link 존재, Markdown whitespace 오류 0건.
- **수동 확인:** 없음 — 문서 marker·checkbox·link를 명령으로 직접 판정한다.
## 실행 순서와 의존성
1. `P1-T1` RED
2. `P1-T1` GREEN
3. `P1-T1` REFACTOR·회귀
4. `P1-GATE`
5. 확정 review 후속 `P1-R1`
- 동시에 하나의 미완료 goal만 운용한다.
- 사용자가 goal 실행을 요청하기 전에는 goal을 생성하지 않는다.
## 변경 금지 항목
- Community 댓글 동작과 API Contract 변경
- 새 dependency, state library, component 또는 speculative abstraction
- 답글의 답글, optimistic update와 form 상시 노출
- 실패 test 삭제·skip, timeout 상향으로 Gate 통과
- 기존 Progress와 결정 기록 삭제·덮어쓰기
## 의사결정 및 중단 규칙
- `target.kind === "audio"`, `replyCount === 0`, `canMutate === true` 경계 밖으로 신규 작성 진입을 확대하지 않는다.
- API 응답이나 오류가 [api-contract.md](./api-contract.md)와 다르면 추정 수정하지 않고 외부 의존으로 기록한다.
- 범위가 바뀌면 코드보다 PRD Decision Log와 이 계획을 먼저 갱신한다.
## Progress
### 2026-08-05 설계
- **무엇을:** 답글 0개 Audio root의 첫 답글 작성 진입 요구사항, API 재사용 계약과 단일 구현 Task를 확정했다.
- **왜:** 기존 POST·form은 있지만 `replyCount === 0`일 때 진입 버튼이 없어 첫 답글을 작성할 수 없다.
- **어떻게:** 기존 코드·OpenAPI·unit·E2E를 대조하고 사용자에게 적용 target과 form 노출 방식을 한 번에 하나씩 확인했다. 애플리케이션 코드와 test는 변경하지 않았다.
### 2026-08-05 구현·검증
- **무엇을:** 활성 Audio의 `replyCount=0` 원댓글에 `답글 작성` action을 추가하고 기존 답글 영역·form·POST 흐름으로 첫 답글을 작성하게 했다.
- **왜:** 기존 `replyCount > 0` 조건만으로는 첫 답글 작성 진입이 없어 `ACR-001~005`를 충족할 수 없었다.
- **어떻게:** `CommentItem`의 답글 action을 optional label로 바꾸고, `CommentThread`에서 Audio·`canMutate`·빈 답글 root에만 `답글 작성` label을 전달했다. RED는 `npm run test:run -- src/features/comments/tests/comment-thread.test.tsx`에서 `AI 루트 댓글 답글 작성` 버튼 부재로 실패했다. GREEN·회귀는 focused 8/8, `npm run test:run -- src/features/comments` 15/15, `npm run e2e:mock -- tests/e2e/comments.spec.ts --project=chromium` 3/3, `npm run typecheck`, `npm run lint`, `git diff --check` 통과로 확인했다. Playwright mock 수동 QA에서 1280px·320px 첫 답글 작성과 320px 수평 overflow 없음도 확인했다.
### 2026-08-05 리뷰 후속 Task 전환 정정
- **무엇을:** 확정 finding `REV-P1-001`을 후속 회귀 수정 Task `P1-R1`로 계획에 추가했다.
- **왜:** 코드 수정과 달리 확정 finding의 계획 전환은 리뷰 범위에서도 필수인데 초안만 리뷰 문서에 남겨 가이드의 종료 조건을 충족하지 못했다.
- **어떻게:** [코드 리뷰 및 QA 기록 규칙](../agent-guide/review.md)의 확정 항목 전환 기준을 다시 대조하고 review ID, goal ID, 시작 조건, 완료 증거, 범위 밖, TDD 예외, 대체 검증과 검증 기록 항목을 `P1-R1`에 명시했다. 애플리케이션 코드·test·API Contract는 변경하지 않았다.
### 2026-08-05 P1-R1 문서 정합성 보완
- **무엇을:** `REV-P1-001`의 stale 현재 상태·발견된 문제를 구현 완료 상태로 정정하고 PRD §14 수용·추적 체크박스와 review 상태를 완료 처리했다.
- **왜:** 기능·test·검증은 완료됐지만 문서에 미구현·미완료 표기가 남아 다음 작업자와 자동 검증이 상반된 상태를 판정했다.
- **어떻게:** 수정 전 marker 검사에서 stale plan 문구 3곳과 PRD §14 미완료 체크박스 7개를 확인했다. 수정 후 stale marker 부재, PRD §14 미완료 체크박스 부재, review 파일 존재와 `git diff --check`를 각각 실행해 모두 exit 0을 확인했다. 추가 회귀 Gate는 Comments 15/15, Chromium mock E2E 3/3, typecheck·lint exit 0이었다. 애플리케이션 코드·test·API Contract는 변경하지 않았다.
## Decision Log
| 날짜 | 결정 | 근거 | 영향 |
|---|---|---|---|
| 2026-08-05 | 신규 진입은 Audio에만 적용한다. | 사용자 선택 B | `ACR-001`, `ACR-004`, `P1-T1` |
| 2026-08-05 | `답글 작성` 버튼으로 기존 답글 영역과 form을 연다. | 사용자 선택 A | `ACR-001~002`, `P1-T1` |
| 2026-08-05 | 새 API·컴포넌트 없이 기존 구현을 재사용한다. | OpenAPI와 코드 확인 | `ACR-003~005`, `P1-T1` |
| 2026-08-05 | 확정 review finding `REV-P1-001`을 문서 전용 후속 Task `P1-R1`로 전환한다. | review 가이드 §4·§5 | `P1-R1`, Phase 1 리뷰 |
## 발견된 문제
- 수정 완료: `REV-P1-001`의 완료 상태와 stale 현재 상태·PRD 수용 체크박스 간 모순을 `P1-R1`에서 정정했다.
- 외부 차단: 없음.
## 최종 보고 형식
- 완료 Goal ID
- 변경한 파일과 최소 구현 내용
- RED·GREEN·REFACTOR 및 Gate 명령과 실제 결과
- 실행하지 못한 수동·server 검증과 이유
- 남은 위험 또는 열린 질문