@angar2/taskery 0.2.1 → 0.3.1

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.
package/README.md CHANGED
@@ -118,20 +118,23 @@ my-app/
118
118
  ├─ LINKED-REPOS.md # 관계 리포지토리 정보
119
119
  ├─ GLOSSARY.md # 도메인 용어집 (영문/한글 표기 일관성)
120
120
  ├─ .env # 사용자 설정 환경변수 (관계 리포지토리 환경변수 등)
121
+ ├─ SERVICE-POLICY.md / TECH-STACK.md / ARCHITECTURE.md # 제품 관통 문서 — 정적 (project-init 작성)
122
+ ├─ DATA-MODEL.md / API-SPEC.md / FEATURES.md / UX-UI.md # 제품 관통 문서 — 성장 (골격 → plan·task가 채움)
121
123
  ├─ rules/
122
124
  │ ├─ TASK_DOC_RULE.md # task 문서 작성 규칙
123
125
  │ ├─ GIT_RULE.md # 로컬 깃 운영 규칙
124
126
  │ ├─ CHANGELOG_RULE.md # CHANGELOG 작성 규칙
125
127
  │ ├─ MOCKUP_RULE.md # UX/UI HTML 목업 규칙
126
128
  │ └─ *.local.md # 사용자 오버라이드 규칙 (패키지 업데이트 대상 제외)
127
- ├─ plans/ # plan 문서
128
- ├─ tasks/ # task 문서 (vX.X/BACKLOG.md / spec-diffs / screenshots / mockup 포함)
129
+ ├─ plans/ # plan(기능 그룹)별 PLAN.md / ROADMAP.md (<NNN_slug>/)
130
+ ├─ tasks/ # task 문서 (<NNN_slug>/BACKLOG.md / spec-diffs / screenshots / mockup 포함)
129
131
  ├─ flows/ # 서비스 로직 플로우 정보
130
132
  ├─ changelog/ # 수정사항 정보
131
133
  ├─ shared/ # 관계 리포지토리 소통 메세지함
132
134
  │ ├─ sent/completed/
133
135
  │ └─ received/completed/
134
- └─ FRICTION_LOG.md # taskery 불편사항 누적 로그
136
+ ├─ FRICTION_LOG.md # taskery 불편사항 누적 로그
137
+ └─ TEST-GUIDE.md # 검증 방법 (방식별 이 프로젝트 실행 경로 — /task-plan이 채움)
135
138
  ```
136
139
 
137
140
  `.project/`는 플랫폼 무관 공통 자산이다. 진입 문서와 에이전트 자산 위치는 선택한 플랫폼에 따라 갈린다.
@@ -160,12 +163,12 @@ my-app/
160
163
 
161
164
  ## 백로그 메모
162
165
 
163
- 작업 흐름 중 발견되는 추가 기능과 버그를 *그 자리에서 짧게 적어 둔다*. 메인 세션이 사용자 발화를 받아 `/add-backlog`로 1건씩 활성 plan 버전의 `tasks/<vX.X>/BACKLOG.md`에 누적한다.
166
+ 작업 흐름 중 발견되는 추가 기능과 버그를 *그 자리에서 짧게 적어 둔다*. 메인 세션이 사용자 발화를 받아 `/add-backlog`로 1건씩 활성 plan(기능 그룹)의 `tasks/<NNN_slug>/BACKLOG.md`에 누적한다.
164
167
 
165
168
  - 항목 형식: 체크박스 + 식별자(BL-NNN) + 유형 + 제목 + 슬러그. 그 아래 *개요*(추정 원인 / 구상)와 *대상 영역*(관여할 파일·모듈) 2줄.
166
169
  - 시작 시점: 사용자가 *"BL-NNN 진행"*이라고 말하면 `/task-init`이 그 항목 메타로 task를 분기하고 BACKLOG.md 항목을 *확인* 마킹(`[x]`)하며 `- TASK: TASK-NNN`을 함께 남긴다. *완료*가 아니라 *task로 옮겼다*는 의미만 담는다.
167
170
  - 완료 추적: git 머지 히스토리와 `taskery status`. BACKLOG.md는 메모지 역할만 한다.
168
- - plan 후보 카탈로그(글로벌 `.project/BACKLOG.md`)는 다음 plan 버전 기획용으로 분리 관리한다.
171
+ - 다음 기능 그룹 후보 카탈로그(글로벌 `.project/BACKLOG.md`)는 다음 plan 기획용으로 분리 관리한다.
169
172
 
170
173
  ---
171
174
 
@@ -174,20 +177,20 @@ my-app/
174
177
  스킬은 호출 시점에 따라 4 카테고리(`project` / `plan` / `task` / `meta`)로 분류된다.
175
178
 
176
179
  - `project` — 프로젝트 첫 도입 시 1회만 호출
177
- - `plan` — 새 기획 버전 시작 시 호출
180
+ - `plan` — 새 기능 그룹(작업 묶음) 시작 시 호출
178
181
  - `task` — 새 task 작업 진행 단계에서 호출
179
182
  - `meta` — 그 외 taskery 관리
180
183
 
181
184
  | 스킬 | 레벨 | 역할 |
182
185
  |------|------|------|
183
- | `/project-init` | project | 프로젝트 첫 도입 시 메타 문서와 디렉토리 골격 생성 (1회성) |
184
- | `/plan-init` | plan | 새 기획 버전의 기획 문서 작성 |
186
+ | `/project-init` | project | 프로젝트 첫 도입 시 메타 문서 + 제품 관통 기획 문서(정책/스택/구조 작성, 데이터/API/기능/UI 골격) 생성 (1회성) |
187
+ | `/plan-init` | plan | 새 기능 그룹의 PLAN.md / ROADMAP.md + 제품 관통 문서(FEATURES/UX-UI)에 기능 의도 추가 |
185
188
  | `/task-init` | task | 새 task의 빈 문서 생성 |
186
189
  | `/task-plan` | task | task의 요구사항·범위·개발 계획·테스트 계획 작성 |
187
190
  | `/task-dev` | task | 계획에 따른 단계별 구현 + 자가 검증 |
188
191
  | `/task-test` | task | 별도 격리 세션에서 독립 검증 (메인 가정 차단) |
189
192
  | `/task-close` | task | 최종 검증 후 git 커밋 + dev 브랜치 `--no-ff` 병합 |
190
- | `/add-backlog` | meta | 사용자 발화로 버전별 `tasks/<vX.X>/BACKLOG.md`에 task 후보 1건씩 추가 (0.1.2+) |
193
+ | `/add-backlog` | meta | 사용자 발화로 plan(기능 그룹)별 `tasks/<NNN_slug>/BACKLOG.md`에 task 후보 1건씩 추가 (0.1.2+) |
191
194
  | `/log-friction` | meta | 사용자 불편을 `.project/FRICTION_LOG.md`에 한 행 기록 |
192
195
 
193
196
  각 스킬은 슬래시로 직접 호출하거나, 사용자 발화의 의미가 스킬의 frontmatter description과 매칭되면 메인 세션이 자동으로 발동시킨다.
@@ -196,9 +199,9 @@ my-app/
196
199
 
197
200
  | 스킬 | 생성 위치 | 생성 문서 |
198
201
  |------|---------|---------|
199
- | `/project-init` | `.project/` | PROJECT.md / AGENT-GUIDE.md / LINKED-REPOS.md / .env |
200
- | `/plan-init` | `.project/plans/<plan-name>/` | 9 기획 문서 — PLAN.md / SERVICE-POLICY.md / FEATURES.md / UX-UI.md / TECH-STACK.md / ARCHITECTURE.md / DATA-MODEL.md / API-SPEC.md / ROADMAP.md (프로젝트 타입에 따라 일부 제외) |
201
- | `/task-init` | `.project/tasks/<plan-name>/` | `<NNN>_<slug>.md` (단일 파일) 또는 `TASK-<NNN>_<slug>/task.md` (규모 `large` 시 폴더 승격) |
202
+ | `/project-init` | `.project/` | PROJECT.md / AGENT-GUIDE.md / LINKED-REPOS.md / GLOSSARY.md / .env + 제품 관통 문서(SERVICE-POLICY / TECH-STACK / ARCHITECTURE 작성, DATA-MODEL / API-SPEC / FEATURES / UX-UI 골격 — 타입 해당분) |
203
+ | `/plan-init` | `.project/plans/<NNN_slug>/` | PLAN.md / ROADMAP.md + 제품 관통 문서 FEATURES/UX-UI에 기능 그룹 의도 추가 (제품 관통 문서 전체를 한꺼번에 만들지는 않음) |
204
+ | `/task-init` | `.project/tasks/<NNN_slug>/` | `<NNN>_<slug>.md` (단일 파일) 또는 `TASK-<NNN>_<slug>/task.md` (사용자 명시 시 폴더 승격) |
202
205
 
203
206
  > 각 스킬의 호출 시점, 입력 처리 방식, 단계별 절차, 주의사항은 [SKILLS.md](https://github.com/angar2/taskery/blob/main/plan/SKILLS.md)에서 확인 가능
204
207
 
@@ -229,7 +232,7 @@ npx @angar2/taskery init
229
232
 
230
233
  ```
231
234
  /project-init # 진입 메타 문서와 디렉토리 골격 생성
232
- /plan-init v1.0 # v1.0 기획 문서 작성
235
+ /plan-init mvp # 첫 plan(기능 그룹) — PLAN/ROADMAP + 제품 문서에 기능 의도 추가
233
236
  /task-init # draft : 첫 task의 빈 문서 생성
234
237
  /task-plan TASK-001 # draft → planned : 요구사항·범위·개발 계획·테스트 계획 작성
235
238
  /task-dev TASK-001 # planned → developed : 단계별 구현과 자체 검증
package/bin/init.js CHANGED
@@ -172,7 +172,7 @@ async function main() {
172
172
  if (platforms.includes('codex')) {
173
173
  console.log(` 2. Codex 최초 1회 '/hooks'로 hook trust 승인 (.codex/config.toml — git-guard / closed-immutable)`);
174
174
  }
175
- console.log(` 3. 에이전트 진입 → '/project-init' → '/plan-init <vX.X>' → '/task-init'\n`);
175
+ console.log(` 3. 에이전트 진입 → '/project-init' → '/plan-init <기능그룹>' → '/task-init'\n`);
176
176
  }
177
177
 
178
178
  main().catch((e) => {
package/bin/lib.js CHANGED
@@ -27,8 +27,8 @@
27
27
  * - assertDevExists(mainWtPath): dev 브랜치 존재 검증
28
28
  *
29
29
  * 백로그 (0.1.2+):
30
- * - getActiveVersion(mainWtPath): .project/AGENT-GUIDE.md에서 활성 plan 버전(vX.X) 추출
31
- * - getBacklogPath(mainWtPath, activeVersion?): .project/tasks/<vX.X>/BACKLOG.md 절대 경로
30
+ * - getActiveVersion(mainWtPath): .project/AGENT-GUIDE.md에서 활성 plan 식별자(버전 또는 기능 그룹명) 추출
31
+ * - getBacklogPath(mainWtPath, activeVersion?): .project/tasks/<활성 plan>/BACKLOG.md 절대 경로
32
32
  * - parseBacklogItem(mainWtPath, blId): BL-NNN 항목 메타 파싱 ({ status, type, title, slug, summary, target, taskNums })
33
33
  * - appendBacklogItem(mainWtPath, meta): withMetaLock + BL-NNN 채번 + 항목 append (placeholder 치환 우선)
34
34
  * - markBacklogChecked(mainWtPath, blId, taskNum): withMetaLock + [ ] → [x] + TASK 마크 (다회 진행 시 콤마 추가)
@@ -369,13 +369,35 @@ function getNextTaskNumber(mainWtPath) {
369
369
  return Math.max(...all) + 1;
370
370
  }
371
371
 
372
+ function computeNextPlanNumber(mainWtPath) {
373
+ // .project/plans/ 하위 'NNN_<slug>' 디렉토리 스캔 → NNN max+1, 3자리 zero-pad 문자열 반환.
374
+ // plan = 기능 그룹 단위, 폴더명 앞 3자리 채번(TASK-NNN과 결 맞춤). slug은 호출측(plan-init)이 결합.
375
+ // legacy 가드: 'NNN_' 패턴이 아닌 폴더(구버전 vX.X 등)는 legacyDirs로 수집 → plan-init이
376
+ // 새 plan 생성 전 경고·수동 이전 안내에 사용(채번 공존 시 활성 plan 갈림 = 원 문제 재발 차단).
377
+ const plansDir = path.join(mainWtPath, '.project', 'plans');
378
+ if (!fs.existsSync(plansDir)) {
379
+ return { next: '001', legacyDirs: [] };
380
+ }
381
+ const nums = [];
382
+ const legacyDirs = [];
383
+ for (const ent of fs.readdirSync(plansDir, { withFileTypes: true })) {
384
+ if (!ent.isDirectory()) continue;
385
+ const m = ent.name.match(/^(\d{3})_/);
386
+ if (m) nums.push(parseInt(m[1], 10));
387
+ else legacyDirs.push(ent.name);
388
+ }
389
+ const next = nums.length === 0 ? 1 : Math.max(...nums) + 1;
390
+ return { next: String(next).padStart(3, '0'), legacyDirs };
391
+ }
392
+
372
393
  // ─── 백로그 (0.1.2+) ────────────────────────────────────────────────
373
394
 
374
395
  const BACKLOG_PLACEHOLDER =
375
396
  '(사용자 발화 또는 task-close 직후 메인 감지로 한 행씩 추가. 빈 상태 default.)';
376
397
 
377
398
  function getActiveVersion(mainWtPath) {
378
- // .project/AGENT-GUIDE.md '## 활성 plan 버전' 섹션 다음 비어 있지 않은 첫 줄에서 vX.X 추출
399
+ // .project/AGENT-GUIDE.md '## 활성 plan 버전' 섹션 다음 비어 있지 않은 첫 줄에서 활성 plan 식별자 추출.
400
+ // plan = 기능 그룹 단위 → 식별자는 vX.X 버전명 또는 기능 그룹 slug(compare-products 등) 모두 가능.
379
401
  const guidePath = path.join(mainWtPath, '.project', 'AGENT-GUIDE.md');
380
402
  if (!fs.existsSync(guidePath)) {
381
403
  throw new Error(`.project/AGENT-GUIDE.md 부재. /project-init 먼저 호출.`);
@@ -385,13 +407,14 @@ function getActiveVersion(mainWtPath) {
385
407
  if (!sec) {
386
408
  throw new Error(`.project/AGENT-GUIDE.md '## 활성 plan 버전' 섹션 부재.`);
387
409
  }
388
- const m = sec[1].match(/\bv[\d.]+(?:[-\w]*)?/);
389
- if (!m) {
410
+ // 첫 토큰 = plan 폴더 이름(' — 설명' 앞부분). '<예: ...>' 자리표시자는 미설정으로 간주.
411
+ const firstLine = sec[1].trim();
412
+ if (!firstLine || firstLine.startsWith('<')) {
390
413
  throw new Error(
391
- `'## 활성 plan 버전' 값에서 vX.X 패턴 추출 실패: ${sec[1].trim()} — /plan-init으로 활성 버전 갱신 필요.`,
414
+ `'## 활성 plan 버전' 값 미설정(${firstLine || '빈 줄'}) — /plan-init으로 활성 plan 갱신 필요.`,
392
415
  );
393
416
  }
394
- return m[0];
417
+ return firstLine.split(/\s+/)[0];
395
418
  }
396
419
 
397
420
  function getBacklogPath(mainWtPath, activeVersion) {
@@ -573,6 +596,7 @@ module.exports = {
573
596
  parseBranchName,
574
597
  getActiveTasks,
575
598
  getNextTaskNumber,
599
+ computeNextPlanNumber,
576
600
  // 백로그 (0.1.2+)
577
601
  BACKLOG_PLACEHOLDER,
578
602
  getActiveVersion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@angar2/taskery",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Lightweight task system for Claude Code & Codex — 1 메인 세션(또는 멀티세션) + 스킬 9종 + catastrophic hook 안전망 2종",
5
5
  "bin": {
6
6
  "taskery": "bin/taskery.js",
@@ -3,14 +3,14 @@
3
3
  # PreToolUse(Write|Edit) 훅 — closed 상태 task.md 재수정 차단
4
4
  #
5
5
  # 잡는 것 (단순화 — task.md 본 파일만 보호):
6
- # 1. .project/tasks/<vX.X>/<NNN>_<slug>.md (단일 파일)
7
- # 2. .project/tasks/<vX.X>/TASK-<NNN>_<slug>/task.md (폴더 승격)
6
+ # 1. .project/tasks/<NNN_slug>/<NNN>_<slug>.md (단일 파일)
7
+ # 2. .project/tasks/<NNN_slug>/TASK-<NNN>_<slug>/task.md (폴더 승격)
8
8
  # → 헤더 status가 'closed'면 차단
9
9
  #
10
10
  # 차단 안 함 (의도적):
11
- # - .project/tasks/<vX.X>/spec-diffs/*.md — 역사적 자료, 자유 수정
12
- # - .project/tasks/<vX.X>/screenshots/* — 자유
13
- # - .project/tasks/<vX.X>/mockup/*.html — UX/UI 목업, 자유 수정 (vX.X 공통)
11
+ # - .project/tasks/<NNN_slug>/spec-diffs/*.md — 역사적 자료, 자유 수정
12
+ # - .project/tasks/<NNN_slug>/screenshots/* — 자유
13
+ # - .project/tasks/<NNN_slug>/mockup/*.html — UX/UI 목업, 자유 수정 (<NNN_slug> 공통)
14
14
  # - 폴더 승격 task 폴더 안 추가 자료 (서브 문서 등) — 자유
15
15
  # - 코드 영역 — closed task 코드 재수정은 *새 task로 처리*가 정상 흐름
16
16
  #
@@ -33,10 +33,10 @@ except Exception:
33
33
  " 2>/dev/null)
34
34
 
35
35
  # task.md 본 파일 매칭 (단일 + 폴더 승격)
36
- # - 단일: .project/tasks/v*/<NNN>_<slug>.md (NNN_<slug> 패턴 — vX.X 직속, spec-diffs/screenshots/mockup 하위 X)
37
- # - 폴더: .project/tasks/v*/TASK-<NNN>_<slug>/task.md
38
- # spec-diffs/ + screenshots/ + mockup/ 직속 파일은 매칭 안 됨 (보호 대상 X)
39
- if ! echo "$FILE_PATH" | grep -qE '\.project/tasks/v[^/]+/([0-9]+_[^/]+\.md|TASK-[^/]+/task\.md)$'; then
36
+ # - 단일: .project/tasks/<NNN_slug>/<NNN>_<slug>.md (NNN_<slug> 패턴 — plan 폴더 직속, spec-diffs/screenshots/mockup 하위 X)
37
+ # - 폴더: .project/tasks/<NNN_slug>/TASK-<NNN>_<slug>/task.md
38
+ # plan 폴더명은 한 세그먼트([^/]+)면 무엇이든 매칭 (NNN_slug 신규 / 구버전 vX.X 모두). spec-diffs/screenshots/mockup 직속 파일은 추가 세그먼트라 매칭 안 됨 (보호 대상 X)
39
+ if ! echo "$FILE_PATH" | grep -qE '\.project/tasks/[^/]+/([0-9]+_[^/]+\.md|TASK-[^/]+/task\.md)$'; then
40
40
  exit 0
41
41
  fi
42
42
 
@@ -1,20 +1,32 @@
1
1
  # taskery 격리 검증 서브에이전트 — /task-test가 spawn하는 독립 tester
2
2
  #
3
3
  # 클로드의 "Task tool 격리 세션"에 대응하는 코덱스 서브에이전트 정의.
4
- # 메인 세션의 plan/dev 컨텍스트(확증편향) 없이 task.md만 보고 독립 검증한다.
4
+ # 메인 세션의 plan/dev 컨텍스트(확증편향) 없이 task.md + TEST-GUIDE.md를 보고 독립 검증한다.
5
+ #
6
+ # ⚠ 미러 — 아래 developer_instructions는 `.agents/skills/task-test/SKILL.md`의 격리 펜스(수행 룰)와
7
+ # *같은 효과*를 내야 한다. /task-test는 그 펜스 전체를 spawn prompt(task)로 전달하므로 펜스가 단일 룰
8
+ # 소스이며, 이 지침은 코덱스에서 동일 효과를 보장하는 기준선이다. 펜스의 룰이 바뀌면 이 지침도 함께 갱신한다.
9
+ # (클로드 = general-purpose 서브에이전트 + 펜스 / 코덱스 = 본 에이전트 + 펜스 — 양쪽 동일 효과)
5
10
  #
6
11
  # ⚠ model 명시 필수 — 생략하면 자식 모델 resolve가 service tier validation에서 실패한다.
7
12
  # 환경의 사용 가능 모델에 맞게 조정한다(기본 gpt-5.5).
8
13
 
9
14
  name = "task-tester"
10
- description = "격리 검증 에이전트. 메인의 확증편향 없이 task.md만 보고 Test Plan을 독립 수행한다. /task-test가 spawn한다."
15
+ description = "격리 검증 에이전트. 메인의 확증편향 없이 task.md + TEST-GUIDE를 보고 Test Plan을 증거 기반으로 독립 수행한다. /task-test가 spawn한다."
11
16
  model = "gpt-5.5"
12
17
  sandbox_mode = "read-only"
13
18
  developer_instructions = """
14
- 너는 격리된 tester다. 메인 세션의 가정을 일체 신뢰하지 말고, 넘겨받은 task.md 하나만 보고 자기완결적으로 검증하라.
19
+ 너는 격리된 tester다. 메인 세션의 가정(plan/dev 컨텍스트, "잘 될 거야")을 일체 신뢰하지 말고, 넘겨받은 검사 지시(spawn prompt)와 문서만 보고 자기완결적으로 검증하라.
20
+
21
+ 검사 룰의 단일 소스 = spawn 시 넘겨받은 검사 지시(prompt)다. 그것을 그대로 따르며, 아래는 그 핵심을 코덱스에서 동일하게 보장하는 기준선이다(넘겨받은 지시와 충돌 시 넘겨받은 지시 우선):
22
+
23
+ - 넘겨받은 task.md와 TEST-GUIDE.md를 직접 읽는다(task.md가 목업을 참조하면 목업도). "task.md 하나만"이 아니다 — TEST-GUIDE는 각 검증 방식을 *이 프로젝트에서 실제로 어떻게 실행하나*(DB 조회 경로 / API 호출법 / E2E 셋업 / 시각 실행)의 단일 소스다.
15
24
  - task.md의 ## Test Plan 시나리오를 순서대로 그대로 수행한다(임의 추가/스킵/변형 금지).
16
- - [AUTO] 시나리오는 실제 명령을 실행하고 로그를 확보한다. 실행 없이 pass 처리 금지.
17
- - [USER] 시나리오는 UNCERTAIN으로 분류하고 사용자 직접 검수 항목으로 리턴한다.
18
- - 코드와 동작만 신뢰한다. "잘 될 것"이라는 가정 금지. 코드 파일 수정 금지.
19
- - 검증을 마치면 task-test SKILL.md의 결과 형식(종합 판정 / 시나리오별 결과 / 검증·테스트 명령 결과)을 그대로 리턴한다.
25
+ - 문 앞 검사(먼저) — 각 [AUTO] 시나리오가 [실행 명령/입력 + 구체적·관측 가능한 기대값(출력값/상태코드/어서션/조회 결과/화면 상태)] 한 쌍을 갖췄는지 확인한다. "정상 동작/잘 됨/확인한다" 같은 소원은 기대값이 아니다. 미달인 [AUTO]는 검사하지 말고 "시험문제 결함(검증 불가)"으로 분류 + 무엇이 빠졌는지 지목한다(PASS 반올림 금지).
26
+ - 증거 일치 시만 PASS — 자격 갖춘 [AUTO]는 실제로 실행해 *관측 결과가 기대값과 일치할 때만* PASS. 코드 정독 "그럴듯함"·추정으로 PASS 금지. 증거(명령 출력/응답 로그/캡처/조회 결과)를 첨부한다.
27
+ - [AUTO]/[USER] 분류 — [USER]는 정답지가 *주관*인 것만(시각 미세 취향 / 색조·2px / UX 느낌) → UNCERTAIN(사람 검수) + 증거 캡처로 리턴. 시각 *객관* 깨짐(요소 빠짐/빈 화면/배치 딴판/색 완전히 틀림)은 [USER]가 아니라 [AUTO] — 실제 화면 캡처 → 승인 목업과 대조해 네가 직접 판정한다(어긋나면 *구체적 어긋남 목록* + FAIL). 시각이라고 무조건 사람에게 넘기지 마라.
28
+ - UNCERTAIN 두 종류 — (사람 검수)=정답지가 주관인 영역 / (검증 불가)=[AUTO]인데 대조할 기대값을 구성 못 함=시험문제 결함. 검증 불가는 PASS로 반올림하거나 사람 검수로 떠넘기지 말고, *무엇을 시도했고 왜 기대값을 구성할 수 없는지* 근거를 반드시 기록한다(task-plan으로 Test Plan을 보수해야 하는 신호).
29
+ - 신규 테스트 추가 시 카운트 +N / 모든 PASS만으로 단정 X — 신규 *테스트 식별자*(suite/class/function 등)가 runner 로그에 실제 등장했는지 grep으로 확인한다(1 hit 이상, 없으면 Suite 미실행 → FAIL). grep/Read 존재 확인은 보조용 — 실동작 PASS를 대체할 수 없다.
30
+ - 코드와 동작만 신뢰한다. 코드 파일 수정 금지. 임시 파일(테스트 스크립트 등)은 종료 후 삭제한다.
31
+ - 검증을 마치면 넘겨받은 검사 지시의 결과 형식(종합 판정 PASS/FAIL/UNCERTAIN / 시나리오별 결과 / 검증·테스트 명령 결과 / UNCERTAIN 2종 / 시험문제 결함)을 그대로 리턴한다.
20
32
  """
@@ -10,8 +10,8 @@
10
10
  # 경로를 정규식 추출해 각각 검사한다. matcher = "apply_patch".
11
11
  #
12
12
  # 잡는 것:
13
- # 1. .project/tasks/<vX.X>/<NNN>_<slug>.md (단일 파일)
14
- # 2. .project/tasks/<vX.X>/TASK-<NNN>_<slug>/task.md (폴더 승격)
13
+ # 1. .project/tasks/<NNN_slug>/<NNN>_<slug>.md (단일 파일)
14
+ # 2. .project/tasks/<NNN_slug>/TASK-<NNN>_<slug>/task.md (폴더 승격)
15
15
  # → 헤더 status가 'closed'면 차단 (exit 2)
16
16
  #
17
17
  # 차단 안 함 (의도적): spec-diffs / screenshots / mockup — 역사적 자료 자유 수정.
@@ -38,7 +38,7 @@ PATHS=$(echo "$CMD" | grep -oE '^\*\*\* (Update|Add) File: .+$' | sed -E 's/^\*\
38
38
 
39
39
  while IFS= read -r FILE_PATH; do
40
40
  # task.md 본 파일 패턴만 검사 (spec-diffs/screenshots/mockup 직속은 보호 대상 X)
41
- echo "$FILE_PATH" | grep -qE '\.project/tasks/v[^/]+/([0-9]+_[^/]+\.md|TASK-[^/]+/task\.md)$' || continue
41
+ echo "$FILE_PATH" | grep -qE '\.project/tasks/[^/]+/([0-9]+_[^/]+\.md|TASK-[^/]+/task\.md)$' || continue
42
42
  # 존재하는 파일만 (Add File 신규 생성은 통과)
43
43
  [ -f "$FILE_PATH" ] || continue
44
44
 
@@ -0,0 +1,51 @@
1
+ # TEST-GUIDE
2
+
3
+ > 이 프로젝트에서 각 테스트 방식을 *실제로 어떻게 실행하나*의 단일 소스.
4
+ > **제품 관통 문서 아님 — 검증 방법 문서.** (제품 스펙은 `.project/` 루트 그룹 A/B 문서 참조.)
5
+ > `/task-test` 격리 세션이 task.md와 함께 이 파일을 읽어, 명세된 방식을 *이 프로젝트의 실제 경로*로 실행한다.
6
+
7
+ **사용 규칙**:
8
+ - 처음엔 빈 골격 — 검증 방법을 아직 모름. `/task-plan`이 방식별 실행 경로를 *사용자에게 확인받은 즉시* 채운다.
9
+ - 각 항목 = "이 프로젝트에서의 실제 실행 방법" (명령 · 경로 · 연결). 추상 설명 아니라 *그대로 돌릴 수 있는* 형태.
10
+ - 모르면 비워 두지 말고 `/task-plan`이 사용자에게 물어 채운다 (모르면 묻고, 알면 재사용).
11
+ - 부정확이 드러나면 정정. 손수 편집보다 task 진행 중 갱신 권장.
12
+
13
+ ---
14
+
15
+ ## 데이터 검증 (DB / 파일 / 상태 조회)
16
+
17
+ > 시나리오 실행 후 데이터 상태를 *직접 조회*하는 실제 경로. (예: ORM repository / DB 클라이언트 / 쿼리 명령 / 파일 확인 명령.)
18
+
19
+ <아직 미정 — 데이터 쓰기·변경·삭제 검증이 필요한 task에서 `/task-plan`이 사용자에게 확인 후 기록>
20
+
21
+ ---
22
+
23
+ ## API 호출 (엔드포인트 / 외부 인터페이스)
24
+
25
+ > 엔드포인트를 실제로 호출하고 상태코드·응답 필드를 확인하는 경로. (예: curl / httpie / 테스트 클라이언트 + 베이스 URL · 인증 방법.)
26
+
27
+ <아직 미정>
28
+
29
+ ---
30
+
31
+ ## UI 동작 · E2E (클릭 / 입력 / 흐름 자동화)
32
+
33
+ > UI 동작·흐름을 자동화하는 도구와 셋업. (예: Playwright / Cypress 설치 여부 · 실행 명령 · 셋업 단계.) 도구가 없으면 "없음 — 사람 검수"로 명시.
34
+
35
+ <아직 미정>
36
+
37
+ ---
38
+
39
+ ## 시각 실행 (앱 기동 + 화면 캡처)
40
+
41
+ > 앱을 띄워 실제 화면을 캡처해 승인 목업과 대조하는 경로. (예: 개발 서버 실행 명령 · 포트 · 캡처 방법.) 검수 서버는 `CLAUDE.md`(코덱스 `AGENTS.md`)의 `## 검수 실행 명령` 참조.
42
+
43
+ <아직 미정>
44
+
45
+ ---
46
+
47
+ ## 기타
48
+
49
+ > 위 분류에 안 맞는 프로젝트 고유 검증 방법.
50
+
51
+ <아직 미정>
@@ -50,7 +50,7 @@
50
50
 
51
51
  | 출처 | 의미 | 채번 주체 |
52
52
  |------|------|---------|
53
- | `BL-NNN` | 백로그 항목 | `/add-backlog` 스킬 (0.1.2). 버전별 `.project/tasks/<vX.X>/BACKLOG.md`에 누적 |
53
+ | `BL-NNN` | 백로그 항목 | `/add-backlog` 스킬 (0.1.2). plan(기능 그룹)별 `.project/tasks/<NNN_slug>/BACKLOG.md`에 누적 |
54
54
  | `RM-NNN` | 로드맵 항목 | `/plan-init` (RM-NNN 채번 자동화는 후속 — 1차는 사용자 수동 명시) |
55
55
  | `DR` | 직접 요구사항 (별도 ID 없음) | 사용자 발화 → `/task-init` |
56
56
 
@@ -134,7 +134,7 @@ docs: [TASK-{NNN}] CHANGELOG 업데이트
134
134
  - `-m` 옵션으로 커밋 메시지 지정 금지
135
135
  - **`--no-ff` 강제 (일반 타입)**: feature/bug/improvement/refactor 등 일반 작업 브랜치 → dev 병합 시 `git merge --no-ff {브랜치명}` 사용. fast-forward 병합 절대 금지. 머지 커밋이 없으면 작업 브랜치 삭제 후 분기 정보 영구 손실(90일 reflog GC 후 추적 불가).
136
136
  - **추적 변경 0 → 마커 빈커밋 (`--allow-empty` 금지의 유일 예외)**: 코드 변경 0 + `.project` gitignore로 작업 브랜치가 dev보다 앞선 커밋이 0개이면 `--no-ff`도 *Already up to date*가 되어 머지 커밋이 생성되지 않는다. 이 경우 `/task-close`가 추적 마커 빈커밋 1개(`--allow-empty`)를 생성해 분기·채번 정보를 보존한다 (상세: task-close Step 6-8). 그 외 빈커밋은 금지.
137
- - **plan/roadmap 임시 docs 브랜치 예외**: plan-init 단계의 단일 커밋(plan 신규/카피)에 한정 `--ff-only` 가능.
137
+ - **plan/roadmap 임시 docs 브랜치 예외**: plan-init 단계의 단일 커밋(plan 신규 생성 — PLAN/ROADMAP + 제품 관통 문서 delta)에 한정 `--ff-only` 가능.
138
138
  - **task 진행 중 ROADMAP/플랜 문서 갱신은 별도 `docs/*` 브랜치 분리 절대 금지**: 해당 task의 작업 브랜치 (`feature/*` / `improve/*` 등) 안에서 수정 + 다른 구현 커밋과 함께 `--no-ff` 머지로 dev 병합 (분기 정보 손실 방지).
139
139
 
140
140
  ---
@@ -31,7 +31,7 @@ UX/UI 구현 task의 *시각 영역 사전 정합* + *task-test 시 USER 검수
31
31
 
32
32
  ## 3. 파일 위치 / 네이밍
33
33
 
34
- - **경로**: `.project/tasks/<vX.X>/mockup/<task-doc-name>-mockup.html`
34
+ - **경로**: `.project/tasks/<NNN_slug>/mockup/<task-doc-name>-mockup.html`
35
35
  - **네이밍**: task 문서 파일명 + `-mockup.html`
36
36
  - 예 1: `001_login-form.md` → `001_login-form-mockup.html`
37
37
  - 예 2: 폴더 승격 `TASK-007_payment-flow/task.md` → `TASK-007_payment-flow-mockup.html`
@@ -11,10 +11,10 @@
11
11
 
12
12
  | 생성일 | 플랜 | 유형 | 규모 | 상태 |
13
13
  |--------|------|------|------|------|
14
- | 2026-05-08 | v1.0 | feature | medium | developing |
14
+ | 2026-05-08 | 001_mvp | feature | medium | developing |
15
15
 
16
16
  - **생성일**: ISO 형식 (YYYY-MM-DD)
17
- - **플랜**: 어느 plan 버전 하위인지 (예: v1.0, v2.0, alpha) — `tasks/<vX.X>/` 디렉토리 명과 일치
17
+ - **플랜**: 어느 plan(기능 그룹) 하위인지 (예: 001_mvp, 002_compare-products) — `tasks/<NNN_slug>/` 디렉토리 명과 일치
18
18
  - **유형**: `feature` / `bug` / `improvement` / `refactor` / `docs` / `chore` (git 브랜치 타입과 직결)
19
19
  - **규모**:
20
20
  - `micro` — 구현 파트 1개 (단일 함수/설정 수정)
@@ -39,12 +39,15 @@ draft → planned → developing → developed → testing → tested → closed
39
39
  | `tested` | 격리 세션 PASS 결과 받은 후 | `/task-test` 끝에 메인 |
40
40
  | `closed` | git 마무리 완료 | `/task-close` 끝에 메인 |
41
41
 
42
- **FAIL/UNCERTAIN 분기**:
42
+ **FAIL/UNCERTAIN 분기** (세 갈래 — 코드 결함 / 시험문제 결함 / 주관 검수):
43
43
  - `/task-test` PASS → `tested` 갱신 → `/task-close` 진행
44
- - `/task-test` FAIL → 메인이 격리 결과(로그/근거) 보고 → 사용자에게 *"고쳐? OK 마무리?"* 묻기 → "고쳐" 시 `developing`으로 되돌림 → `/task-dev` 재진입
45
- - `/task-test` UNCERTAIN → 메인이 결과 보고 → 사용자 판단
44
+ - `/task-test` FAIL (**코드 결함**) → 메인이 격리 결과(로그/근거) 보고 → 사용자에게 *"고쳐? OK 마무리?"* 묻기 → "고쳐" 시 `developing`으로 되돌림 → `/task-dev` 재진입
45
+ - `/task-test` UNCERTAIN(**검증 불가 = 시험문제 결함**) → `[AUTO]`인데 대조할 기대값을 구성 못 한 경우. 코드는 멀쩡 → `developing` 아님. **status=`testing` 유지** + `/task-plan`을 *Test Plan 보수 모드*로 재호출(Test Plan 섹션만 보수, Requirements/Scope/Dev Plan/코드 보존) → 보수 후 `/task-test` 재실행. (되돌림용 별도 status 신설 X — 7상태 유지.)
46
+ - `/task-test` UNCERTAIN(**사람 검수**) → 정답지가 주관인 `[USER]` 항목(시각 미세 취향 / UX 느낌). `testing` 유지 + 사용자 직접 검수 → 모두 ✓면 `tested`, ✗면 `developing`(고쳐).
46
47
  - `/task-dev` 중 self-check FAIL → `developing` 그대로, 메인 자체 수정 → PASS 시 `developed` 갱신
47
48
 
49
+ > **시험문제 결함 되돌림이 새 status를 안 만드는 이유**: 새 상태(예: `replanning`)는 -ing/-ed 페어 원칙(본 §1.2)·7상태 고정과 충돌하고 `closed-immutable.sh` 화이트리스트와도 어긋난다. 코드 미변경이라 `developing`을 거칠 이유도 없으므로 `testing`을 유지한 채 Test Plan만 보수한다.
50
+
48
51
  ### 1.3 섹션 구성 — 6 섹션
49
52
 
50
53
  ```markdown
@@ -93,16 +96,17 @@ draft → planned → developing → developed → testing → tested → closed
93
96
 
94
97
  | 항목 | 위치 | 작성 주체 |
95
98
  |------|------|---------|
96
- | 단일 파일 task | `.project/tasks/<vX.X>/<NNN>_<slug>.md` (예: `001_login-feature.md`) | `/task-init` |
97
- | 폴더 승격 task | `.project/tasks/<vX.X>/TASK-<NNN>_<slug>/task.md` | `/task-init` (규모 large 또는 사용자 명시 또는 추가 자료 다수) |
98
- | spec-diffs (변경된 plan 문서 추적) | `.project/tasks/<vX.X>/spec-diffs/<NNN>_<slug>_spec-diff.md` (**vX.X 공통** — 단일/폴더 모두) | `/task-plan` Step 6 (Phase 0 변경 시) |
99
- | screenshots (UI 작업 자료) | `.project/tasks/<vX.X>/screenshots/<NNN>_*.png` (**vX.X 공통**) | `/task-test` 격리 세션 또는 메인 |
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` |
99
+ | 단일 파일 task | `.project/tasks/<NNN_slug>/<NNN>_<slug>.md` (예: `001_login-feature.md`) | `/task-init` |
100
+ | 폴더 승격 task | `.project/tasks/<NNN_slug>/TASK-<NNN>_<slug>/task.md` | `/task-init` (*사용자 명시 시에만* — 규모 large여도 자동 승격 X) |
101
+ | spec-diffs (변경된 제품 문서(루트) 추적) | `.project/tasks/<NNN_slug>/spec-diffs/<NNN>_<slug>_spec-diff.md` (**`<NNN_slug>` 공통** — 단일/폴더 모두) | `/task-plan` Step 6 (Phase 0 변경 시) |
102
+ | screenshots (UI 작업 자료) | `.project/tasks/<NNN_slug>/screenshots/<NNN>_*.png` (**`<NNN_slug>` 공통**) | `/task-test` 격리 세션 또는 메인 |
103
+ | mockup (UX/UI HTML 목업) | `.project/tasks/<NNN_slug>/mockup/<task-doc-name>-mockup.html` (**`<NNN_slug>` 공통** — 단일/폴더 모두) | `/task-plan` Step 4.5 (UX/UI task 한정) — 단일 진실 소스 `MOCKUP_RULE.md` |
101
104
  | 폴더 승격 task의 추가 자료 (서브 문서 등) | `TASK-<NNN>_<slug>/` 안 자유 | 메인 / `/task-dev` |
102
105
 
103
106
  **원칙**:
104
- - spec-diffs / screenshots / mockup은 *vX.X 공통* — 파일명 NNN prefix 또는 task 문서 파일명으로 task 식별. 폴더 승격 task도 동일 (별도 spec-diffs/screenshots/mockup 만들지 X).
105
- - vX.X 공통 디렉토리는 `/plan-init` Step 5가 mkdir.
107
+ - spec-diffs / screenshots / mockup은 *`<NNN_slug>` 공통* — 파일명 NNN prefix 또는 task 문서 파일명으로 task 식별. 폴더 승격 task도 동일 (별도 spec-diffs/screenshots/mockup 만들지 X).
108
+ - `<NNN_slug>` 공통 디렉토리는 `/plan-init`이 mkdir.
109
+ - **spec-diff = per-task 기록** — 그 task가 어느 *제품 문서(`.project/` 루트)*를 NEW/MOD/DEL 했는지의 task 산출물. 제품 문서의 *정식 변경 이력은 git*이 단일 진실이며, 별도 전역 변경 인덱스는 두지 않는다.
106
110
  - 폴더 승격은 *task의 추가 자료*용 (서브 문서 / 디자인 자료 등) — *spec-diffs / screenshots / mockup 위치 X*.
107
111
 
108
112
  **closed-immutable hook 보호 범위** — task.md 본 파일만 (단일 파일 또는 폴더 승격 task.md). spec-diffs / screenshots / mockup / 폴더 승격 추가 자료는 *역사적 자료*로 자유 수정.
@@ -113,13 +117,13 @@ draft → planned → developing → developed → testing → tested → closed
113
117
 
114
118
  ### 2.1 헤더 작성 (`/task-init`)
115
119
 
116
- 1. `tasks/<vX.X>/` 디렉토리 안 가장 큰 NNN+1로 task 번호 결정 (예: 기존 002까지 있으면 003)
120
+ 1. `tasks/<NNN_slug>/` 디렉토리 안 가장 큰 NNN+1로 task 번호 결정 (예: 기존 002까지 있으면 003)
117
121
  2. kebab-slug = 태스크 이름 한국어 → 영어 kebab-case (예: "로그인 기능 추가" → `login-feature`)
118
- 3. 파일명 = `NNN_kebab-slug.md` (예: `003_login-feature.md`). 큰 작업이면 폴더 승격 (`TASK-003_login-feature/task.md`).
122
+ 3. 파일명 = `NNN_kebab-slug.md` (예: `003_login-feature.md`). *사용자 명시 시* 폴더 승격 (`TASK-003_login-feature/task.md`) — 규모 large여도 자동 승격 X.
119
123
  4. 파일 제목 작성: `# TASK-003 — 로그인 기능 추가`
120
124
  5. 헤더 표 작성 (5컬럼 모두 채움):
121
125
  - 생성일: 오늘 (YYYY-MM-DD)
122
- - 플랜: 현재 active plan 버전 (예: v1.0)
126
+ - 플랜: 현재 active plan (예: 001_mvp — `NNN_slug` 폴더명)
123
127
  - 유형: 사용자/메인 합의 (feature/bug/...)
124
128
  - 규모: 사용자/메인 합의 (micro/small/medium/large)
125
129
  - 상태: `draft` (고정)
@@ -166,39 +170,49 @@ draft → planned → developing → developed → testing → tested → closed
166
170
  - UX/UI 시각: 레이아웃 / 색상 / 간격 / 호버 효과 (목업 기준)
167
171
  - 백엔드 동작: 시스템 호출 → 외부 응답 / 사이드 이펙트 / 에러 처리
168
172
 
169
- **시나리오 형식**:
173
+ **시나리오 형식** — 모든 `[AUTO]` = [실행 명령/입력] + [구체적·관측 가능한 기대값] 한 쌍:
170
174
 
171
175
  ```markdown
172
176
  ## Test Plan
173
177
 
174
- | # | 시나리오 | 분류 | 방식 | PASS 기준 |
178
+ | # | 시나리오 | 분류 | 방식 | PASS 기준 (구체적 기대값) |
175
179
  |---|---------|------|------|----------|
176
- | 1 | <한 줄 설명> | [AUTO] / [USER] | <카탈로그 방식> | <명확한 기대값> |
180
+ | 1 | <쪼갠 장면 한 줄: 무엇을 실행> | [AUTO] / [USER] | <카탈로그 방식> | <관측 가능한 구체값 — 출력/상태코드/조회결과/화면상태> |
177
181
  | 2 | ... | ... | ... | ... |
178
182
  ```
179
183
 
184
+ - **소원 금지** — "정상 동작 / 잘 됨 / 확인한다"는 PASS 기준이 아님. 눈에 보이는 결과여야 함.
185
+ - **장면 쪼개기** — 한 덩어리 금지, 진짜 떨어질 장면 여러 개로.
186
+ - **잣대** — "고장나면 어떻게 걸리나"를 못 적는 장면 = 버린다. (이게 task-test "문 앞 검사" 자격 — 미달 시 *시험문제 결함*으로 반려됨.)
187
+
180
188
  **분류 강제**:
181
- - `[AUTO]` — 자동화 가능. 격리 세션이 *실제 명령 실행 + 결과 로그* 확보.
182
- - `[USER]` — 자동화 불가 (UI 인터랙션 / 시각 디자인 / 사용자 입력). 격리 세션은 UNCERTAIN 분류 + *사용자 직접 검수 항목*으로 리턴.
189
+ - `[AUTO]` — 정답지(구체적 기대값)를 구성할 수 있는 영역. 격리 세션이 *실제 명령 실행 + 결과 로그* 확보 → 기대값과 일치 시만 PASS. **시각 *객관* 깨짐(레이아웃/요소 유무/색/배치)도 `[AUTO]`** (캡처-목업 대조, 목업이 정답지).
190
+ - `[USER]` — *정답지가 주관*인 영역만 (시각 미세 취향 / 색조·2px / UX 느낌). 격리 세션은 UNCERTAIN(사람 검수) 분류 + *사용자 직접 검수 항목*으로 리턴(증거 캡처 첨부). UI 인터랙션은 E2E 도구 있으면 `[AUTO]`, 없으면 `[USER]`.
183
191
 
184
- **방식 카탈로그** (시나리오마다 1개 이상):
192
+ **방식 선택 규칙** (요구사항 성격 → 필수 방식, 재량 0): 화면 변경→시각 / 상호작용→UI 동작 / 엔드포인트→API / 데이터 쓰기→상태 조회 / 순수 계산→입출력 / 기존 영역 건드림→회귀. 여러 개 걸리면 다 붙인다.
185
193
 
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 등) |
194
+ **방식 카탈로그** (시나리오마다 1개 이상 — 각 방식은 *비교할 정답지*가 다름):
195
+
196
+ | 방식 | 적용 영역 | 정답지 | 누가 검사 |
197
+ |------|----------|------|------|
198
+ | 수동 검수 | UI 미세 / UX 느낌 | 주관(목업·사용감) | 사람 (증거 첨부) |
199
+ | 시나리오 스크립트 실행 | 백엔드 / 통합 흐름 (end-to-end script) | 구체적 출력·종료코드 | test 자동 |
200
+ | API/엔드포인트 호출 | 백엔드 / 외부 인터페이스 | 상태코드 + 응답 필드값 | test 자동 |
201
+ | 입출력 비교 | 함수 / 변환 / 처리 | 구체적 기대 출력 (snapshot / golden) | test 자동 |
202
+ | 사이드 이펙트 확인 | DB / 파일 / 로그 | 조회 결과(행/파일/카운트) | test 자동 |
203
+ | 시각 (캡처-목업 대조) | UI 레이아웃/색/배치 | 승인된 목업 | test 자동 (+ 미세는 사람) |
204
+ | 회귀 시나리오 | 기존 기능 영향 | 이전과 동일 결과 | test 자동 |
205
+ | E2E 자동화 도구 | UI 동작 자동화 | 액션 후 관측 변화 | 도구면 test, 아니면 사람 |
206
+
207
+ **관통 규칙**: 어느 방식이든 *실제 관측 결과* == *구체적 정답지*여야 PASS. 정답지가 주관이면 사람한테(단 증거 깔고). 어느 방식도 코드 정독·grep으로 PASS 대체 금지.
195
208
 
196
209
  **UX/UI 영역 분리** (UX/UI 구현 task 한정):
197
210
 
198
- | 영역 | 자동화 가능 | 자동화 불가 |
199
- |------|------------|------------|
200
- | 동작 (클릭 / 호버 / 드래그 / 입력 → 결과) | `[AUTO]` E2E 자동화 스크립트 | `[USER]` 체크리스트 |
201
- | 시각 (레이아웃 / 색상 / 간격 / 호버 효과) | (자동 비교 의미 X — 픽셀 단위 + 주관 판단 영역) | `[USER]` 체크리스트 + 목업 기준 (`mockup/<task-doc-name>-mockup.html`) |
211
+ | 영역 | 분류 | 기준 |
212
+ |------|------|------|
213
+ | 동작 (클릭 / 호버 / 드래그 / 입력 → 결과) | 도구 있으면 `[AUTO]` E2E, 없으면 `[USER]` | 액션 후 관측 변화 |
214
+ | 시각 *객관* (레이아웃 / 요소 유무 / 색 / 배치 깨짐) | `[AUTO]` 캡처-목업 대조 | 승인 목업 (`mockup/<task-doc-name>-mockup.html`) — 화면 캡처 → 대조 → 어긋남 목록 |
215
+ | 시각 *미세 취향* (2px / 색조 / 호버 강도 / 느낌) | `[USER]` 체크리스트 + 목업 참조 | 사용자 최종 사인 (증거 캡처) |
202
216
 
203
217
  **시각 영역 fix 사이클 사전 예고** — 시각 시나리오 있으면 Test Plan 끝에 *"시각 영역 항목 N개 — fix 사이클 1~2회 예상"* 명시 (사용자 기대치 사전 정렬).
204
218
 
@@ -208,7 +222,7 @@ draft → planned → developing → developed → testing → tested → closed
208
222
  - **자기완결적**: `/task-test` 격리 세션이 *task.md만 보고도* 수행 가능. 메인의 plan/dev 컨텍스트 없이.
209
223
  - **명령 / 기대값 포함**: 무엇을 실행하고 무엇이 기대되는지 명확.
210
224
  - **메인 가정 X**: 격리 세션이 *코드와 동작만 신뢰*. *"잘 될 거야"* 같은 가정 금지.
211
- - **grep/Read-only 존재 확인 시나리오 = 보조용** (stash FRICTION_LOG 2026-06-01 반영) — 구현 코드의 존재 여부를 grep/Read로 재확인하는 시나리오는 *동어반복*. PASS 카운트에서 제외하거나 실동작 시나리오의 *보조*로만 사용. 단독 검증 가치 X.
225
+ - **grep/Read-only 존재 확인 시나리오 = 보조용, PASS 대체 영구 금지** (stash FRICTION_LOG 2026-06-01 반영) — 구현 코드의 존재 여부를 grep/Read로 재확인하는 시나리오는 *동어반복*. PASS 카운트에서 제외, 실동작 시나리오의 *보조*로만. grep으로 실동작 검증 *대체 불가* (task-test 룰 10과 동일 강도).
212
226
  - **요구사항당 end-to-end 1개 이상 강제** — Requirements 각 항목이 *사용자 관점에서 실제 작동하는지* 검증하는 end-to-end 실동작 시나리오 최소 1개 보장. 산출물 실행 → 결과 확인 형태.
213
227
  - **무거운 검증 회피 영구 금지** — 부담(빌드 수 분+ / 외부 의존 / 환경 설정) 이유로 실동작 시나리오를 grep 동어반복으로 대체 X. 최소 1회는 실제 산출물로 확인. 부담은 *fix 사이클 1~2회 예상* 같은 사전 예고로 처리 (생략 사유 X).
214
228
 
@@ -285,7 +299,7 @@ Test Plan 작성 완료 후 *반드시* 점검. *"누적/리셋 안 함"* 같은
285
299
 
286
300
  | 생성일 | 플랜 | 유형 | 규모 | 상태 |
287
301
  |--------|------|------|------|------|
288
- | 2026-05-08 | v1.0 | feature | small | planned |
302
+ | 2026-05-08 | 001_mvp | feature | small | planned |
289
303
  ```
290
304
 
291
305
  ### 4.2 Requirements
@@ -403,7 +417,7 @@ Test Plan 작성 완료 후 *반드시* 점검. *"누적/리셋 안 함"* 같은
403
417
 
404
418
  | 생성일 | 플랜 | 유형 | 규모 | 상태 |
405
419
  |--------|------|------|------|------|
406
- | 2026-05-08 | v1.0 | chore | micro | closed |
420
+ | 2026-05-08 | 001_mvp | chore | micro | closed |
407
421
 
408
422
  ## Requirements
409
423
  사용자 요구:
@@ -449,7 +463,7 @@ Test Plan 작성 완료 후 *반드시* 점검. *"누적/리셋 안 함"* 같은
449
463
 
450
464
  | 생성일 | 플랜 | 유형 | 규모 | 상태 |
451
465
  |--------|------|------|------|------|
452
- | 2026-05-08 | v1.0 | feature | medium | tested |
466
+ | 2026-05-08 | 001_mvp | feature | medium | tested |
453
467
 
454
468
  ## Requirements
455
469
  사용자 요구:
@@ -566,7 +580,7 @@ Test Plan 작성 완료 후 *반드시* 점검. *"누적/리셋 안 함"* 같은
566
580
 
567
581
  | 생성일 | 플랜 | 유형 | 규모 | 상태 |
568
582
  |--------|------|------|------|------|
569
- | 2026-05-08 | v1.0 | bug | small | tested |
583
+ | 2026-05-08 | 001_mvp | bug | small | tested |
570
584
 
571
585
  ## Requirements
572
586
  사용자 보고:
@@ -638,3 +652,4 @@ Test Plan 작성 완료 후 *반드시* 점검. *"누적/리셋 안 함"* 같은
638
652
  | 2026-05-09 | 표현 정제 — 인명 / 경박 표현 / 스킬 용어 / 이전 버전 비교 단락 정리 |
639
653
  | 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 정합) |
640
654
  | 2026-06-02 | 0.1.3 F5 정합 — §2.5 가이드라인 안티패턴 3종 추가 (grep/Read-only 보조용 / 요구사항당 end-to-end 1개 이상 / 무거운 검증 회피 금지) + 요구사항 ↔ 시나리오 커버리지 점검 단계 신설 (stash FRICTION_LOG 2026-06-01 Test Plan 동어반복 + 누락 마찰 반영) |
655
+ | 2026-06-27 | PLAYBOOK §13 정합 — plan = 기능 그룹. 헤더 *플랜* 컬럼 = `NNN_slug` 폴더명(예: 001_mvp). §1.5 경로 `tasks/<NNN_slug>/`, *`<NNN_slug>` 공통*으로 통일. spec-diff 정의 = *변경된 제품 문서(루트) 추적*(per-task 기록, 정식 변경 이력은 git 단일 진실) |