@angar2/taskery 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97,14 +97,15 @@ draft → planned → developing → developed → testing → tested → closed
97
97
  | 폴더 승격 task | `.project/tasks/<vX.X>/TASK-<NNN>_<slug>/task.md` | `/task-init` (규모 large 또는 사용자 명시 또는 추가 자료 다수) |
98
98
  | spec-diffs (변경된 plan 문서 추적) | `.project/tasks/<vX.X>/spec-diffs/<NNN>_<slug>_spec-diff.md` (**vX.X 공통** — 단일/폴더 모두) | `/task-plan` Step 6 (Phase 0 변경 시) |
99
99
  | screenshots (UI 작업 자료) | `.project/tasks/<vX.X>/screenshots/<NNN>_*.png` (**vX.X 공통**) | `/task-test` 격리 세션 또는 메인 |
100
- | 폴더 승격 task의 추가 자료 (서브 문서, mockup 등) | `TASK-<NNN>_<slug>/` 안 자유 | 메인 / `/task-dev` |
100
+ | mockup (UX/UI HTML 목업) | `.project/tasks/<vX.X>/mockup/<task-doc-name>-mockup.html` (**vX.X 공통** — 단일/폴더 모두) | `/task-plan` Step 4.5 (UX/UI task 한정) — 단일 진실 소스 `MOCKUP_RULE.md` |
101
+ | 폴더 승격 task의 추가 자료 (서브 문서 등) | `TASK-<NNN>_<slug>/` 안 자유 | 메인 / `/task-dev` |
101
102
 
102
103
  **원칙**:
103
- - spec-diffs / screenshots는 *vX.X 공통* — 파일명 NNN prefix로 task 식별. 폴더 승격 task도 동일 (별도 spec-diffs/screenshots 만들지 X).
104
+ - spec-diffs / screenshots / mockup은 *vX.X 공통* — 파일명 NNN prefix 또는 task 문서 파일명으로 task 식별. 폴더 승격 task도 동일 (별도 spec-diffs/screenshots/mockup 만들지 X).
104
105
  - vX.X 공통 디렉토리는 `/plan-init` Step 5가 mkdir.
105
- - 폴더 승격은 *task의 추가 자료*용 (서브 문서, mockup, 디자인 자료 등) — *spec-diffs/screenshots 위치 X*.
106
+ - 폴더 승격은 *task의 추가 자료*용 (서브 문서 / 디자인 자료 등) — *spec-diffs / screenshots / mockup 위치 X*.
106
107
 
107
- **closed-immutable hook 보호 범위** — task.md 본 파일만 (단일 파일 또는 폴더 승격 task.md). spec-diffs / screenshots / 폴더 승격 추가 자료는 *역사적 자료*로 자유 수정.
108
+ **closed-immutable hook 보호 범위** — task.md 본 파일만 (단일 파일 또는 폴더 승격 task.md). spec-diffs / screenshots / mockup / 폴더 승격 추가 자료는 *역사적 자료*로 자유 수정.
108
109
 
109
110
  ---
110
111
 
@@ -157,29 +158,57 @@ draft → planned → developing → developed → testing → tested → closed
157
158
 
158
159
  ### 2.5 Test Plan 작성 (`/task-plan` 4단계)
159
160
 
160
- 양식 강제 X — *작업에 맞게 자유롭게* 채움. 다만 가이드라인 따름:
161
+ **본질** — Test Plan = *본 task에서 구현한 요구사항이 정상 동작하는지* 검증 시나리오. **유닛 테스트 X** (유닛 테스트는 `/task-dev` Step 6.5에서 단일 시점 실행 — 코드 정상성 영역, Test Plan과 직교).
161
162
 
162
- - **자기완결적**: `/task-test` 격리 세션이 *task.md만 보고도* 수행 가능. 메인의 plan/dev 컨텍스트 없이.
163
- - **명령/기대값 포함**: 무엇을 실행하고 무엇이 기대되는지 명확.
164
- - **메인 가정 X**: 격리 세션이 *코드와 동작만 신뢰*. *"잘 될 거야"* 같은 가정 금지.
163
+ **검증 대상**:
164
+ - 기능 동작: 사용자 입력 → 기대 결과 / API 호출 → 응답 / 데이터 처리 → 상태 변화
165
+ - UX/UI 동작: 클릭 → 결과 / 호버 → 상태 / 드래그 → 위치 변경
166
+ - UX/UI 시각: 레이아웃 / 색상 / 간격 / 호버 효과 (목업 기준)
167
+ - 백엔드 동작: 시스템 호출 → 외부 응답 / 사이드 이펙트 / 에러 처리
165
168
 
166
- 자유 형식 (체크리스트 / 시나리오 / 명령 나열 등):
169
+ **시나리오 형식**:
167
170
 
168
171
  ```markdown
169
172
  ## Test Plan
170
173
 
171
- 1. `npm run dev` 실행 → 로그인 페이지(/login) 접속.
172
- 2. 빈 값 제출 → 에러 메시지 *"이메일 입력 필요"* 표시 확인.
173
- 3. 잘못된 이메일 형식 → *"올바른 이메일 형식이 아닙니다"* 확인.
174
- 4. DB에 미등록 계정 → 401 + *"계정 없음"* 확인.
175
- 5. 정상 로그인 → 홈(/)으로 리다이렉트 + 세션 쿠키 확인.
176
-
177
- 검증 명령:
178
- - `npm run lint` PASS
179
- - `npm run typecheck` PASS
180
- - `npm run build` PASS
174
+ | # | 시나리오 | 분류 | 방식 | PASS 기준 |
175
+ |---|---------|------|------|----------|
176
+ | 1 | <한 줄 설명> | [AUTO] / [USER] | <카탈로그 방식> | <명확한 기대값> |
177
+ | 2 | ... | ... | ... | ... |
181
178
  ```
182
179
 
180
+ **분류 강제**:
181
+ - `[AUTO]` — 자동화 가능. 격리 세션이 *실제 명령 실행 + 결과 로그* 확보.
182
+ - `[USER]` — 자동화 불가 (UI 인터랙션 / 시각 디자인 / 사용자 입력). 격리 세션은 UNCERTAIN 분류 + *사용자 직접 검수 항목*으로 리턴.
183
+
184
+ **방식 카탈로그** (시나리오마다 1개 이상):
185
+
186
+ | 방식 | 적용 영역 |
187
+ |------|----------|
188
+ | 수동 검수 | UI / UX / 인터랙션 |
189
+ | 시나리오 스크립트 실행 | 백엔드 / 통합 흐름 (end-to-end script — bash / node 등) |
190
+ | API/엔드포인트 호출 | 백엔드 / 외부 인터페이스 (실제 호출 + 응답·상태 코드 확인) |
191
+ | 입출력 비교 | 함수 / 변환 / 처리 (snapshot / golden file) |
192
+ | 사이드 이펙트 확인 | DB / 파일 / 로그 |
193
+ | 회귀 시나리오 | 기존 기능 영향 (직전 동작하던 시나리오 재실행) |
194
+ | E2E 자동화 도구 | UI 자동화 (Playwright / Cypress / XCTest UI Test 등) |
195
+
196
+ **UX/UI 영역 분리** (UX/UI 구현 task 한정):
197
+
198
+ | 영역 | 자동화 가능 | 자동화 불가 |
199
+ |------|------------|------------|
200
+ | 동작 (클릭 / 호버 / 드래그 / 입력 → 결과) | `[AUTO]` E2E 자동화 스크립트 | `[USER]` 체크리스트 |
201
+ | 시각 (레이아웃 / 색상 / 간격 / 호버 효과) | (자동 비교 의미 X — 픽셀 단위 + 주관 판단 영역) | `[USER]` 체크리스트 + 목업 기준 (`mockup/<task-doc-name>-mockup.html`) |
202
+
203
+ **시각 영역 fix 사이클 사전 예고** — 시각 시나리오 있으면 Test Plan 끝에 *"시각 영역 항목 N개 — fix 사이클 1~2회 예상"* 명시 (사용자 기대치 사전 정렬).
204
+
205
+ **검증 / 테스트 명령 참조** — `CLAUDE.md`의 `## 검증 명령` (코드 상태: 빌드 / 린트 / 타입체크) + `## 테스트 명령` (테스트 실행: 단위 / 통합 / E2E) 두 섹션을 격리 세션이 자동 참조. Test Plan 본문에 재인용 불필요.
206
+
207
+ **가이드라인**:
208
+ - **자기완결적**: `/task-test` 격리 세션이 *task.md만 보고도* 수행 가능. 메인의 plan/dev 컨텍스트 없이.
209
+ - **명령 / 기대값 포함**: 무엇을 실행하고 무엇이 기대되는지 명확.
210
+ - **메인 가정 X**: 격리 세션이 *코드와 동작만 신뢰*. *"잘 될 거야"* 같은 가정 금지.
211
+
183
212
  ### 2.6 Result 기록 (`/task-dev`, `/task-test` 끝)
184
213
 
185
214
  1. `/task-dev` 끝에 phase별 진행 결과 기록:
@@ -310,25 +339,17 @@ draft → planned → developing → developed → testing → tested → closed
310
339
  ```markdown
311
340
  ## Test Plan
312
341
 
313
- 1. `npm run dev` 실행 → http://localhost:3000/login 접속.
314
- 2. 빈 이메일 + 비밀번호 제출:
315
- - 기대: *"이메일 입력 필요"* + *"비밀번호 입력 필요"* 표시. API 호출 X.
316
- 3. 잘못된 이메일 형식 (예: "abc"):
317
- - 기대: *"올바른 이메일 형식 아님"* 표시. API 호출 X.
318
- 4. 짧은 비밀번호 (예: "123"):
319
- - 기대: *"비밀번호 8자 이상 필요"* 표시. API 호출 X.
320
- 5. 정상값 제출:
321
- - 기대: API 호출 → 정상 응답 시 / 리다이렉트.
322
- 6. 한국어 ↔ 영어 전환:
323
- - 기대: 메시지 언어 따라 변경.
324
-
325
- 검증 명령:
326
- - `npm run lint` PASS
327
- - `npm run typecheck` PASS
328
- - `npm run build` PASS
329
- - `npm test src/utils/validation.test.ts` PASS
342
+ | # | 시나리오 | 분류 | 방식 | PASS 기준 |
343
+ |---|---------|------|------|----------|
344
+ | 1 | 빈 이메일 + 비밀번호 제출 | [USER] | 수동 검수 | "이메일 입력 필요" + "비밀번호 입력 필요" 표시, API 호출 X |
345
+ | 2 | 잘못된 이메일 형식 ("abc") | [USER] | 수동 검수 | "올바른 이메일 형식 아님" 표시, API 호출 X |
346
+ | 3 | 짧은 비밀번호 ("123") | [USER] | 수동 검수 | "비밀번호 8자 이상 필요" 표시, API 호출 X |
347
+ | 4 | 정상값 제출 | [USER] | 수동 검수 | API 호출 → 정상 응답 시 / 리다이렉트 |
348
+ | 5 | 한국어 ↔ 영어 전환 | [USER] | 수동 검수 | 메시지 언어 따라 변경 |
330
349
  ```
331
350
 
351
+ > 검증 명령 / 테스트 명령은 `CLAUDE.md` 두 섹션을 격리 세션이 자동 참조 — Test Plan 본문 재인용 X.
352
+
332
353
  ### 4.6 Result
333
354
 
334
355
  **역할**: 진행 + 테스트 결과 통합. *"실제로 어떻게 됐는가"*.
@@ -379,8 +400,11 @@ draft → planned → developing → developed → testing → tested → closed
379
400
  - 진행: [x]
380
401
 
381
402
  ## Test Plan
382
- - `grep -n "Instalation" README.md` → 결과 0행.
383
- - `grep -n "Installation" README.md` → 1행 이상.
403
+
404
+ | # | 시나리오 | 분류 | 방식 | PASS 기준 |
405
+ |---|---------|------|------|----------|
406
+ | 1 | README.md 안 오타 검색 | [AUTO] | 시나리오 스크립트 실행 | `grep -n "Instalation" README.md` 결과 0건 |
407
+ | 2 | README.md 안 정정 표기 검색 | [AUTO] | 시나리오 스크립트 실행 | `grep -n "Installation" README.md` 결과 1건 이상 |
384
408
 
385
409
  ## Result
386
410
 
@@ -479,32 +503,16 @@ draft → planned → developing → developed → testing → tested → closed
479
503
 
480
504
  ## Test Plan
481
505
 
482
- 1. `npm run dev` 실행 → API 서버 :3000.
483
- 2. 정상 로그인:
484
- - POST /api/auth/login { email: "test@x.com", password: "Password123!" }
485
- - 기대: 200, body { token: "eyJ..." }, Set-Cookie: refreshToken=...
486
- 3. 잘못된 비밀번호:
487
- - POST /api/auth/login { email: "test@x.com", password: "wrong" }
488
- - 기대: 401, body { error: "이메일 또는 비밀번호가 올바르지 않습니다" }
489
- 4. 미등록 이메일:
490
- - 기대: 401, **동일 메시지** (enumeration 방어)
491
- 5. 빈 입력 / 형식 오류:
492
- - 기대: 400, validation 에러
493
- 6. JWT 검증:
494
- - GET /api/protected with Authorization: Bearer <token>
495
- - 기대: 200 (유효 토큰) / 401 (만료, 무효)
496
- 7. Rate limit:
497
- - 11회 연속 요청
498
- - 기대: 11번째 요청 429
499
- 8. Refresh token:
500
- - GET /api/auth/refresh with cookie
501
- - 기대: 200, 새 token 발급
502
-
503
- 검증 명령:
504
- - `npm run lint` PASS
505
- - `npm run typecheck` PASS
506
- - `npm run build` PASS
507
- - `npm test src/api/auth.test.ts` PASS
506
+ | # | 시나리오 | 분류 | 방식 | PASS 기준 |
507
+ |---|---------|------|------|----------|
508
+ | 1 | 정상 로그인 | [AUTO] | API/엔드포인트 호출 | POST /api/auth/login {email, password} → 200, body {token}, Set-Cookie: refreshToken |
509
+ | 2 | 잘못된 비밀번호 | [AUTO] | API/엔드포인트 호출 | 401, body {error: "이메일 또는 비밀번호가 올바르지 않습니다"} |
510
+ | 3 | 미등록 이메일 (enumeration 방어) | [AUTO] | API/엔드포인트 호출 | 401, body 메시지 #2와 동일 |
511
+ | 4 | 빈 입력 / 형식 오류 | [AUTO] | API/엔드포인트 호출 | 400, validation 에러 |
512
+ | 5 | JWT 검증 — 유효 토큰 | [AUTO] | API/엔드포인트 호출 | GET /api/protected with Authorization → 200 |
513
+ | 6 | JWT 검증 — 만료 / 무효 | [AUTO] | API/엔드포인트 호출 | 401 |
514
+ | 7 | Rate limit (11회 연속) | [AUTO] | 시나리오 스크립트 실행 | 11번째 요청 429, 헤더 X-RateLimit-Remaining: 0 |
515
+ | 8 | Refresh token | [AUTO] | API/엔드포인트 호출 | GET /api/auth/refresh with cookie → 200, 새 token 발급 |
508
516
 
509
517
  ## Result
510
518
 
@@ -573,18 +581,11 @@ draft → planned → developing → developed → testing → tested → closed
573
581
 
574
582
  ## Test Plan
575
583
 
576
- 1. `npm run dev` 실행 → iOS Safari로 http://localhost:3000/search 접속.
577
- 2. 검색어 입력 후 검색 버튼 클릭:
578
- - 기대: 페이지 URL의 search query만 갱신, 새로고침 X (네트워크 탭에서 document 요청 X 확인).
579
- 3. 데스크톱 Chrome 동일 동작:
580
- - 기대: 회귀 X (기존 정상 동작 유지).
581
- 4. 단위 테스트:
582
- - `npm test src/components/SearchForm.test.tsx` PASS.
583
-
584
- 검증 명령:
585
- - `npm run lint` PASS
586
- - `npm run typecheck` PASS
587
- - `npm run build` PASS
584
+ | # | 시나리오 | 분류 | 방식 | PASS 기준 |
585
+ |---|---------|------|------|----------|
586
+ | 1 | iOS Safari 검색어 입력 후 검색 버튼 클릭 | [USER] | 수동 검수 | 페이지 URL의 search query만 갱신, 새로고침 X (네트워크 탭 document 요청 X) |
587
+ | 2 | 데스크톱 Chrome 동일 동작 (회귀) | [USER] | 수동 검수 | 회귀 X (기존 정상 동작 유지) |
588
+ | 3 | onSubmit handler preventDefault 회귀 테스트 | [AUTO] | 입출력 비교 | fireEvent.submit + expect(preventDefault) 호출 확인 |
588
589
 
589
590
  ## Result
590
591
 
@@ -612,3 +613,4 @@ draft → planned → developing → developed → testing → tested → closed
612
613
  | 2026-05-08 | 초안 — 5컬럼 헤더 / 7상태 / 6섹션 / 4단 layer 가이드 / 완성 예시 3개 |
613
614
  | 2026-05-08 | §1.5 추가 — task 파일/폴더/부속 자료 위치 단일 진실 소스. spec-diffs/screenshots는 vX.X 공통 통일. closed-immutable hook 보호 범위는 task.md 본 파일만 (스킬 본문 간 위치 모순 통일) |
614
615
  | 2026-05-09 | 표현 정제 — 인명 / 경박 표현 / 스킬 용어 / 이전 버전 비교 단락 정리 |
616
+ | 2026-05-30 | stash FRICTION_LOG 기반 정합 — §1.5 mockup 행 추가 (vX.X 공통, 단일 진실 소스 MOCKUP_RULE) + §2.5 Test Plan 본질 재정의 (실질 동작 시나리오 + `[AUTO]` / `[USER]` 분류 강제 + 카탈로그 7방식 + UX/UI 영역 분리 매트릭스 + 시각 fix 사이클 사전 예고 + 검증 / 테스트 명령 두 섹션 참조) + §4.5 / §5 완성 예시 3개 Test Plan 형식 갱신 (분류 표 + PASS 기준 명시. 기존 번호 매김 시나리오 + 검증 명령 나열은 옛 형식). (stash FRICTION_LOG #14+19 / #25 정합) |
@@ -1,7 +1,7 @@
1
1
  # CLAUDE.md
2
2
 
3
3
  > 이 파일은 메인 세션이 *매 세션 시작 시 자동 로드*하는 단일 진입점이다.
4
- > 프로젝트 메타 + 검증 명령 + 룰 참조 + 스킬 8종 + 동기화 룰만 포함한다.
4
+ > 프로젝트 메타 + 검증 명령 + 룰 참조 + 스킬 9종 + 동기화 룰만 포함한다.
5
5
  > 사람용 도메인 설명은 `.project/PROJECT.md`, 진입 가이드는 `.project/AGENT-GUIDE.md` 참조.
6
6
 
7
7
  ---
@@ -17,17 +17,78 @@
17
17
 
18
18
  ---
19
19
 
20
+ ## 메인 세션 최상위 룰
21
+
22
+ > 본 룰은 *모든 스킬 호출 / 사용자 발화 처리 / 작업 진행*에 적용. 위반 시 사용자 마찰 직결.
23
+
24
+ 1. **범위 준수** — 사용자가 명시한 범위/행동만 수행. 명시 외 자체 진입 영구 금지. 예: 사용자가 *"X부터 Y까지"* 지시 → Y 끝에서 정지 + 상태 보고 + 다음 단계 명시 호출 대기.
25
+ 2. **Skill 정식 발동** — task 단계는 반드시 Skill 도구로 정식 호출. 가이드 본문을 머릿속 절차로 대체 금지 (컴팩트 세션 / 시스템 리마인더 인지 상태에서도 동일).
26
+ 3. **워크트리 자가 진단** — 세션 시작 시 현재 cwd가 *메인 워크트리*인지 *태스크 워크트리*인지 자가 판단 (`git rev-parse --show-toplevel` + `~/.taskery/worktrees/` 경로 비교). 태스크 워크트리면 *해당 진행중 태스크 컨텍스트*로 진입, 메인 워크트리면 *새 태스크 / 진행중 목록 인터뷰* 흐름.
27
+
28
+ ---
29
+
30
+ ## 멀티세션 워크트리 (0.1.2+)
31
+
32
+ > 멀티세션 = 같은 프로젝트에서 *여러 메인 세션이 독립 태스크를 병렬*로 진행. git worktree로 작업 폴더 격리, dev 머지 시 직렬화.
33
+
34
+ - **메인 워크트리 = dev 전용**: 메인 워크트리는 항상 `dev` 체크아웃 상태. 모든 태스크 작업은 별도 워크트리에서 수행.
35
+ - **워크트리 위치**: `~/.taskery/worktrees/<projectId>/TASK-NNN_<출처>_<슬러그>/`
36
+ - `<projectId>`: `.taskery-manifest.json` `projectId` (8자 hex)
37
+ - `<출처>`: `BL-NNN` / `RM-NNN` / `DR`
38
+ - **`/task-init`이 워크트리 생성** + **`/task-close`가 dev 머지 + 워크트리 자동 제거** (자동 흐름. 보존 키워드 `keep` / `브랜치 남겨` 등 발화 시 둘 다 보존).
39
+ - **메인 메타 접근**: 워크트리에서 `.project/`, `CLAUDE.md` 등 접근 시 *메인 워크트리 절대 경로* 사용:
40
+ ```sh
41
+ MAIN_WT=$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")
42
+ ```
43
+ - **수동 git 작업 시 정합성 보장 X** — taskery 명령(스킬 / `npx @angar2/taskery <서브>`)으로만 운영.
44
+ - **CLI 보조 명령**:
45
+ - `npx @angar2/taskery status` — 진행중 태스크 + 워크트리 + dev 머지 상태 요약
46
+ - `npx @angar2/taskery prune` — stale 워크트리 대화형 정리
47
+
48
+ 상세: `.project/rules/GIT_RULE.md` "멀티세션 워크트리 정책" 섹션.
49
+
50
+ 요건: git ≥ 2.31 (`--path-format=absolute` 옵션 필요).
51
+
52
+ ---
53
+
54
+ ## 백로그 (0.1.2+)
55
+
56
+ > `.project/tasks/<vX.X>/BACKLOG.md` = *버전별 task 후보 누적*. 사용자 발화로 1건씩 얕은 분석(개요 / 대상 영역) 곁들여 추가.
57
+
58
+ - **`/add-backlog`**: 사용자 *"~ 백로그에 추가"* 발화 → 얕은 분석(코드 탐색 X, 추정 수준) → BL-NNN 채번 → BACKLOG.md append (`[ ]` 대기).
59
+ - **`/task-init` 연동**: 사용자 *"백로그의 BL-NNN 진행"* 발화 → 해당 항목 *확인 마킹*. `[ ]` → `[x]` + `- TASK: TASK-NNN` 추가 (다회 진행 시 콤마).
60
+ - **체크박스 의미**: `[ ]` = 미확인 (task로 옮기지 않은 메모) / `[x]` = 확인 완료 (task로 옮김). **dev 머지 완료 의미 X** — 완료 여부는 `git log dev --grep 'BL-NNN'` + 브랜치명 추적 + `taskery status`.
61
+ - **글로벌 `.project/BACKLOG.md`** (plan 기획 후보 카탈로그) 는 본 흐름 무관 — `/plan-init` 영역.
62
+
63
+ 상세: `.claude/skills/add-backlog/SKILL.md`.
64
+
65
+ ---
66
+
20
67
  ## 검증 명령
21
68
 
22
- > `/task-dev` self-check / `/task-test` 격리 게이트 / `/task-close` 최종 게이트 / `pre-commit-verify.sh` hook이 *모두 이 섹션을 단일 진실 소스로 참조*.
69
+ > *코드 상태 검증* (빌드 / 린트 / 타입체크). 테스트 실행은 본 섹션 X — `## 테스트 명령` 참조.
70
+ > `/task-dev` self-check / `/task-close` 최종 게이트가 *이 섹션을 단일 진실 소스로 참조*.
23
71
  > 백틱(`...`) 안 명령 그대로 실행됨. 언어/프레임워크 따라 변경.
24
72
 
25
73
  - 린트: `<예: npm run lint>`
26
74
  - 타입체크: `<예: npm run typecheck>` (TypeScript / Flow / mypy 등 — 해당 시)
27
75
  - 빌드: `<예: npm run build>`
76
+
77
+ > 위 항목 중 *프로젝트에 해당 없는 것*은 행 자체 삭제. 빈 백틱(\`\`)은 사용 금지.
78
+
79
+ ---
80
+
81
+ ## 테스트 명령
82
+
83
+ > *테스트 실행* (단위 / 통합 / E2E 등). 코드 상태 검증은 `## 검증 명령` 참조.
84
+ > `/task-dev` 구현 후 테스트 + `/task-test` 격리 세션이 *이 섹션을 단일 진실 소스로 참조*.
85
+ > 백틱(`...`) 안 명령 그대로 실행됨. 언어/프레임워크 따라 변경.
86
+
28
87
  - 단위 테스트: `<예: npm test>`
88
+ - 통합 테스트: `<예: npm run test:integration>` (있을 시)
89
+ - E2E 테스트: `<예: npx playwright test>` (있을 시)
29
90
 
30
- > 위 4 항목 중 *프로젝트에 해당 없는 것*은 행 자체 삭제. 빈 백틱(\`\`)은 사용 금지.
91
+ > 위 항목 중 *프로젝트에 해당 없는 것*은 행 자체 삭제. 빈 백틱(\`\`)은 사용 금지.
31
92
 
32
93
  ---
33
94
 
@@ -37,11 +98,13 @@
37
98
  |----|------|------|
38
99
  | TASK_DOC_RULE | `.project/rules/TASK_DOC_RULE.md` | task 문서 양식 (헤더 5컬럼 / 6 섹션 / 7 상태) |
39
100
  | GIT_RULE | `.project/rules/GIT_RULE.md` (있으면) → 글로벌 `~/.claude/rules/GIT_RULE.md` (fallback) | git 정책 (브랜치 / 커밋 / 머지) |
101
+ | CHANGELOG_RULE | `.project/rules/CHANGELOG_RULE.md` | CHANGELOG 작성 정책 (위치 / 형식 / 필수 필드) |
102
+ | MOCKUP_RULE | `.project/rules/MOCKUP_RULE.md` | UX/UI task의 HTML 목업 위치 / 형식 / 네이밍 |
40
103
  | `*.local.md` | `.project/rules/` | (옵션) 사용자 오버라이드 — `*.local.md` suffix는 npx 미터치 |
41
104
 
42
105
  ---
43
106
 
44
- ## 스킬 8종 — project > plan > task 위계 + 회고
107
+ ## 스킬 9종 — project > plan > task 위계 + 회고
45
108
 
46
109
  | 스킬 | 레벨 | 역할 |
47
110
  |------|------|------|
@@ -52,22 +115,24 @@
52
115
  | `/task-dev` | task | Phase 순서 구현 + self-check (planned → developed) |
53
116
  | `/task-test` | task | Task tool 격리 검증 (developed → tested) |
54
117
  | `/task-close` | task | 검증 명령 게이트 + 커밋 + dev 병합 (tested → closed) |
118
+ | `/add-backlog` | meta | 사용자 발화로 버전별 BACKLOG.md에 항목 1건 추가 (얕은 분석 + BL-NNN 채번 — 0.1.2+) |
55
119
  | `/log-friction` | meta | FRICTION_LOG.md에 사용자 불편 한 행 기록 |
56
120
 
57
121
  본문은 `.claude/skills/<스킬>/SKILL.md` 참조.
58
122
 
59
123
  ---
60
124
 
61
- ## Hook 안전망 — Catastrophic 3종
125
+ ## Hook 안전망 — Catastrophic 2종
62
126
 
63
127
  | Hook | 영역 | 잡는 것 |
64
128
  |------|------|--------|
65
129
  | `git-guard.sh` | PreToolUse(Bash) | main/dev 직접 커밋 / `--force` / `--no-verify` / `branch -D` / `reset --hard` / `clean -fd` |
66
- | `pre-commit-verify.sh` | PreToolUse(Bash) | `git commit` 시 위 *검증 명령* 모두 PASS 게이트. 하나라도 fail → 차단 |
67
- | `closed-immutable.sh` | PreToolUse(Write\|Edit) | `closed` 상태 task.md 본 파일 재수정 차단 (정상 흐름은 새 task로). spec-diffs/screenshots는 자유 수정 (역사적 자료) |
130
+ | `closed-immutable.sh` | PreToolUse(Write\|Edit) | `closed` 상태 task.md 본 파일 재수정 차단 (정상 흐름은 새 task로). spec-diffs / screenshots / mockup은 자유 수정 (역사적 자료) |
68
131
 
69
132
  **잘 지키면 hook 작동 0회 (무해). catastrophic만 차단.**
70
133
 
134
+ > 이전 `pre-commit-verify.sh` hook은 폐기 — task-close Step 2 게이트 + git-guard 안전망으로 충분 (redundant 검증 사이클 제거). 폐기 사유는 [plan/HOOKS.md](../plan/HOOKS.md) §5 참조.
135
+
71
136
  ---
72
137
 
73
138
  ## 불편 데이터
@@ -1,97 +0,0 @@
1
- #!/bin/bash
2
- # .claude/hooks/pre-commit-verify.sh
3
- # PreToolUse(Bash) 훅 — git commit 시점에 검증 명령 모두 PASS 게이트
4
- #
5
- # 잡는 것:
6
- # git commit 명령 감지 → 프로젝트 루트 CLAUDE.md '## 검증 명령' 섹션의 명령 모두 실행
7
- # 하나라도 fail (exit code != 0) → exit 2 (commit 차단)
8
- #
9
- # Process catastrophic — 결정적 영역(린트/타입/빌드/테스트). 합리적 변형 없음.
10
- # 잘 지키면 작동 0회 (무해 — /task-dev self-check + /task-close 게이트로 이미 PASS 상태에서 commit).
11
- # 부분 작업 / 환경 변화 / 가정 누설 시 catastrophic 차단 안전망.
12
- #
13
- # Single source of truth: 프로젝트 루트 CLAUDE.md '## 검증 명령' 섹션
14
- # 형식 예:
15
- # ## 검증 명령
16
- # - 린트: `npm run lint`
17
- # - 타입체크: `npm run typecheck`
18
- # - 빌드: `npm run build`
19
- # - 단위테스트: `npm test`
20
-
21
- INPUT=$(cat)
22
-
23
- # tool_input.command 추출
24
- CMD=$(echo "$INPUT" | python3 -c "
25
- import sys, json
26
- try:
27
- d = json.load(sys.stdin)
28
- print(d.get('tool_input', {}).get('command', ''))
29
- except Exception:
30
- print('')
31
- " 2>/dev/null)
32
-
33
- # git commit 명령 아니면 통과
34
- if ! echo "$CMD" | grep -qE '(^|;|&&|\|\|)\s*git\s+commit\b'; then
35
- exit 0
36
- fi
37
-
38
- # CLAUDE.md 정독 — 프로젝트 루트
39
- if [ ! -f "./CLAUDE.md" ]; then
40
- echo "pre-commit-verify: 프로젝트 루트 CLAUDE.md 없음. 검증 명령 단일 진실 소스 누락 — commit 차단." >&2
41
- echo " '/project-init' 또는 'npx @angar2/taskery init' 호출해 CLAUDE.md 생성." >&2
42
- exit 2
43
- fi
44
-
45
- # '## 검증 명령' 섹션 추출 + 백틱(`...`) 안 명령 추출
46
- COMMANDS=$(python3 <<'PYEOF'
47
- import re
48
-
49
- try:
50
- with open('./CLAUDE.md') as f:
51
- content = f.read()
52
- except Exception:
53
- raise SystemExit('claude_md_read_failed')
54
-
55
- # '## 검증 명령' 섹션 (다음 ## 헤딩 또는 EOF까지)
56
- m = re.search(r'^##\s*검증\s*명령\s*$([\s\S]*?)(?=^##\s|\Z)', content, re.MULTILINE)
57
- if not m:
58
- raise SystemExit('section_missing')
59
-
60
- section = m.group(1)
61
- # 백틱 안 명령 추출 — list item(`-`로 시작) 줄에서만
62
- # (blockquote `>` 메타 텍스트 등 비-list 백틱 오인식 방지)
63
- cmds = []
64
- for line in section.split('\n'):
65
- stripped = line.strip()
66
- if stripped.startswith('-'):
67
- cmds.extend(re.findall(r'`([^`]+)`', stripped))
68
- for c in cmds:
69
- print(c)
70
- PYEOF
71
- )
72
-
73
- # 섹션 누락 / 추출 실패 케이스
74
- if [ -z "$COMMANDS" ]; then
75
- echo "pre-commit-verify: CLAUDE.md '## 검증 명령' 섹션 없거나 명령 없음. commit 차단." >&2
76
- echo " CLAUDE.md에 '## 검증 명령' 섹션 추가 + 백틱 안에 명령 작성 (예: \`npm run lint\`)." >&2
77
- exit 2
78
- fi
79
-
80
- # 각 명령 실행 — 하나라도 fail → 차단
81
- FAILED=""
82
- while IFS= read -r cmd; do
83
- [ -z "$cmd" ] && continue
84
- echo "pre-commit-verify: 실행 — $cmd" >&2
85
- if ! eval "$cmd" >/dev/null 2>&1; then
86
- FAILED="$FAILED\n - FAIL: $cmd"
87
- fi
88
- done <<< "$COMMANDS"
89
-
90
- if [ -n "$FAILED" ]; then
91
- echo "pre-commit-verify: 검증 명령 실패 — commit 차단." >&2
92
- printf "%b\n" "$FAILED" >&2
93
- echo " /task-dev self-check 또는 /task-close 게이트 통과 후 다시 시도." >&2
94
- exit 2
95
- fi
96
-
97
- exit 0