@angar2/taskery 0.5.0 → 0.6.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 +11 -5
- package/bin/close.js +2 -2
- package/bin/fork.js +5 -2
- package/bin/lib.js +128 -57
- package/bin/mcp.js +4 -3
- package/bin/status.js +6 -3
- package/package.json +1 -1
- package/template/.claude/hooks/closed-immutable.sh +5 -3
- package/template/.codex/agents/task-tester.toml +6 -3
- package/template/.codex/hooks/closed-immutable.sh +2 -2
- package/template/.project/TEST-GUIDE.md +11 -0
- package/template/.project/rules/GIT_RULE.md +32 -19
- package/template/.project/rules/TASK_DOC_RULE.md +12 -10
- package/template/AGENTS.md +16 -14
- package/template/CLAUDE.md +16 -14
- package/template/shared/skills/add-backlog/SKILL.md +1 -1
- package/template/shared/skills/plan-init/SKILL.md +2 -2
- package/template/shared/skills/project-init/SKILL.md +2 -2
- package/template/shared/skills/task-close/SKILL.md +53 -24
- package/template/shared/skills/task-dev/SKILL.md +33 -2
- package/template/shared/skills/task-init/SKILL.md +16 -16
- package/template/shared/skills/task-plan/SKILL.md +17 -10
- package/template/shared/skills/task-test/SKILL.md +64 -11
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-close
|
|
3
|
-
description: task git 마무리 — 검증 게이트 + 커밋 순서 + 머지 락 직렬화 +
|
|
3
|
+
description: task git 마무리 — 검증 게이트 + 커밋 순서 + 머지 락 직렬화 + 부모 브랜치 --no-ff 병합 + 워크트리/브랜치 자동 정리, tested → closed (멀티세션 0.1.2+)
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /task-close
|
|
7
7
|
|
|
8
8
|
## 개요
|
|
9
9
|
|
|
10
|
-
`tested` 상태 task의 git 마무리. **호출 위치 자유** — 워크트리 cwd / 메인 워크트리 cwd / 다른 세션이 호출한 서브 세션 모두 동작 동일 (모든 git 명령이 `git -C <경로>` 형태라 cwd 무관). `close` CLI 결정적 준비(Phase 커밋·status=closed·문서 커밋·추적 마커) → 사전 rebase → 충돌 해결 (3단계 에스컬레이션) → 머지 락 → 락 안 재 rebase →
|
|
10
|
+
`tested` 상태 task의 git 마무리. **호출 위치 자유** — 워크트리 cwd / 메인 워크트리 cwd / 다른 세션이 호출한 서브 세션 모두 동작 동일 (모든 git 명령이 `git -C <경로>` 형태라 cwd 무관). `close` CLI 결정적 준비(Phase 커밋·status=closed·문서 커밋·추적 마커) → 사전 rebase → 충돌 해결 (3단계 에스컬레이션) → 머지 락 → 락 안 재 rebase → 부모 브랜치 `--no-ff` 머지 → 워크트리 제거 + 작업 브랜치 자동 삭제.
|
|
11
11
|
|
|
12
12
|
**최종 게이트**: 모든 검증 명령 재실행 — 린트/타입체크/빌드 PASS여야 진행.
|
|
13
13
|
|
|
@@ -56,17 +56,17 @@ LOCK_FILE="$HOME/.taskery/${PROJECT_ID}.merge.lock"
|
|
|
56
56
|
### Step 1 — 사전 검증
|
|
57
57
|
|
|
58
58
|
1. **메인 워크트리 검출** (위 핵심 변수).
|
|
59
|
-
2. **메인 워크트리 =
|
|
59
|
+
2. **메인 워크트리 = 부모 브랜치 확인**: 메인 워크트리는 이 task의 *부모 브랜치*(task-init 시점 현재 브랜치, 헤더 기록)에 서 있어야 close가 그 부모로 되병합한다. 정확한 부모 일치는 Step 3 `close`가 검증(불일치 시 명확한 에러로 중단)하므로, 여기서는 detached HEAD만 조기 차단한다.
|
|
60
60
|
```sh
|
|
61
61
|
CURRENT=$(git -C "$MAIN_WT" rev-parse --abbrev-ref HEAD)
|
|
62
|
-
[ "$CURRENT"
|
|
62
|
+
[ "$CURRENT" != "HEAD" ] || abort "메인 워크트리가 detached HEAD — 부모 브랜치로 체크아웃 필요"
|
|
63
63
|
```
|
|
64
64
|
3. **워크트리 미커밋 변경 확인**:
|
|
65
65
|
```sh
|
|
66
66
|
git -C "$WT_PATH" status --porcelain
|
|
67
67
|
```
|
|
68
68
|
- 결과 *있음* = 정상 흐름 (taskery 정책: `/task-dev` = *git 작업 X*). 본 변경분은 Step 3 `close`가 *Dev Plan Phase 매핑 → Phase별 자동 커밋*으로 처리.
|
|
69
|
-
- 결과 *없음* = 변경분 0건 → Step 2 검증만 수행. **워크트리 브랜치가
|
|
69
|
+
- 결과 *없음* = 변경분 0건 → Step 2 검증만 수행. **워크트리 브랜치가 부모보다 앞선 커밋이 0개면 Step 3 `close`가 추적 마커 빈커밋 1개 생성** (`.project` gitignore + docs/분석 전용 task → 채번 보존).
|
|
70
70
|
- **차단 X** — 본 단계는 *상태 인지*용. close 중단 사유 X.
|
|
71
71
|
4. **task 파일 + GIT_RULE 확인**:
|
|
72
72
|
- task 문서 위치 분기 (`.gitignore` 케이스):
|
|
@@ -80,6 +80,7 @@ LOCK_FILE="$HOME/.taskery/${PROJECT_ID}.merge.lock"
|
|
|
80
80
|
- `$MAIN_WT/.project/rules/GIT_RULE.md` (프로젝트별 — 우선)
|
|
81
81
|
- `~/.claude/rules/GIT_RULE.md` (글로벌)
|
|
82
82
|
둘 다 없으면 종료 + *"GIT_RULE 누락"* 보고.
|
|
83
|
+
- **로컬 오버라이드** — `$MAIN_WT/.project/rules/GIT_RULE.local.md`가 있으면 함께 Read하고, 겹치는 항목은 **로컬 우선** 적용한다 (`npx update` 미터치 영역). 단 로컬 룰이 뒤집을 수 없는 것: 부모 브랜치 직접 커밋 금지 · `--no-ff` 강제 · 머지 락 직렬화 · destructive 명령 사용자 승인.
|
|
83
84
|
|
|
84
85
|
### Step 2 — 최종 검증 명령 재실행 (게이트)
|
|
85
86
|
|
|
@@ -101,28 +102,52 @@ FAIL 시:
|
|
|
101
102
|
- *"고쳐"* → status `developing`으로 되돌림 + `/task-dev` 안내 + close 중단.
|
|
102
103
|
- *"OK 마무리"* → 결함 명시한 채 진행 (Result 섹션에 *"검증 명령 X FAIL 알려진 결함 — 사유: ..."* 추가).
|
|
103
104
|
|
|
105
|
+
### Step 2.5 — 문서 갱신 훑기 (게이트 통과 후 · `close` 호출 전)
|
|
106
|
+
|
|
107
|
+
본 task로 갱신돼야 할 문서를 *목록으로* 훑는다. 이 단계가 없어 PLAN.md 체크리스트·수정이력·CHANGELOG가 연속으로 누락된 사례가 있다 (recordion FRICTION 2026-08-05, 5태스크 연속·26문서 무이력·6태스크 무CHANGELOG). 개별 항목이 아니라 *목록 훑기*가 본 단계의 요지다 — 하나씩 규칙을 더하는 방식으로는 습관 밖의 문서가 계속 빠진다.
|
|
108
|
+
|
|
109
|
+
**편집 위치** (`.gitignore` 케이스 — Step 1에서 판정한 값 사용):
|
|
110
|
+
- 등록 케이스 → `$MAIN_WT/.project/...` (gitignore라 git 추적 무관, 즉시 반영)
|
|
111
|
+
- 미등록 케이스 → `$WT_PATH/.project/...` (Step 3 `close`의 문서 커밋이 자동 수거 → 부모 머지로 반영)
|
|
112
|
+
|
|
113
|
+
**점검 목록** (해당 없으면 "해당 없음"으로 명시하고 넘어간다 — 침묵 통과 금지):
|
|
114
|
+
|
|
115
|
+
| # | 대상 | 갱신 내용 |
|
|
116
|
+
|---|------|----------|
|
|
117
|
+
| 1 | `.project/plans/<활성 plan>/PLAN.md` | 본 task에 해당하는 체크리스트 항목 `[x]` + TASK 번호 표기 |
|
|
118
|
+
| 2 | `.project/plans/<활성 plan>/ROADMAP.md` | Stage 상태·완료 노트 (출처가 `ST-N`이거나 Stage 진척이 생긴 경우) |
|
|
119
|
+
| 3 | `.project/changelog/<YYYY-MM>.md` | 본 task 항목 추가. **파일이 없으면 생성한다** (형식은 `.project/rules/CHANGELOG_RULE.md` — `.local.md` 있으면 그쪽 우선) |
|
|
120
|
+
| 4 | 본 task가 수정한 **제품 관통 문서·plan 문서**의 `## 수정 이력` | 해당 문서마다 행 추가, 표가 없으면 신설. 대상 목록의 출처 = `spec-diffs/` + Dev Plan Phase 0 기록 (등록 케이스는 `.project/`가 git 밖이라 `git diff`로 찾을 수 없다). **task 문서는 제외** — close가 잠그는 별개 계열이다 |
|
|
121
|
+
| 5 | 후속 task 후보 (있을 때만) | **손편집 금지** — `backlog_add` 도구(또는 `npx @angar2/taskery backlog-add ...`)로 등재한다. BL 채번·서식·`withMetaLock` 직렬화를 코드가 보장하며, 파일 위치는 등록/미등록과 무관하게 **항상 메인 워크트리**(`.project/tasks/<활성 plan>/BACKLOG.md`)다 — 위 "편집 위치" 분기가 적용되지 않는 유일한 항목 |
|
|
122
|
+
| 6 | `spec-diffs/` ↔ 실제 문서 변경 | 기재한 diff가 실제 반영됐는지 대조 |
|
|
123
|
+
|
|
124
|
+
- 갱신 결과는 Step 8 보고의 `- 문서 갱신:` 줄에 적는다.
|
|
125
|
+
- 본 단계에서 git 명령을 실행하지 않는다 (커밋은 Step 3 `close`와 Step 5 머지가 담당).
|
|
126
|
+
|
|
104
127
|
### Step 3 — 결정적 준비 (`task_close` 도구)
|
|
105
128
|
|
|
106
129
|
`task_close` 도구 (또는 `npx @angar2/taskery close TASK-NNN`) 한 번으로 다음을 코드가 수행:
|
|
107
|
-
- **Phase 기능 커밋** — uncommitted 코드 변경분(`.project/` 외)을 task.md `### Phase N`의 `- 파일:` 필드에 매핑해 Phase 순서대로 자동 커밋 (GIT_RULE 메시지 형식, 태그 자동: feature→`feat:` / bug→`fix:` / improve→`improve:` / refactor→`refactor:` / docs·chore→`docs:`).
|
|
130
|
+
- **Phase 기능 커밋** — uncommitted 코드 변경분(`.project/` 외)을 task.md `### Phase N`의 `- 파일:` 필드에 매핑해 Phase 순서대로 자동 커밋 (GIT_RULE 메시지 형식, 태그 자동: feature→`feat:` / bug→`fix:` / improve→`improve:` / refactor→`refactor:` / docs·chore→`docs:`). 매핑 폴백은 GIT_RULE §"Phase↔파일 매핑 규칙" — 한 파일이 여러 Phase에 걸치면 *가장 이른 Phase*, Dev Plan에 없는 *빌드 산출물*(`*.pbxproj`·잠금파일)은 *마지막 Phase*에 자동 편입(커밋 메시지에 사유 표기).
|
|
108
131
|
- **status → `closed`** — task 문서 헤더 (`.gitignore` 케이스 자동 판정 — 등록=메인WT / 미등록=워크트리).
|
|
109
132
|
- **flows/문서 커밋** (미등록 케이스) — 워크트리 안 `.project/flows/` + task 문서.
|
|
110
|
-
- **추적 마커 빈커밋** —
|
|
133
|
+
- **추적 마커 빈커밋** — 부모 브랜치보다 앞선 커밋이 0개(코드 0·`.project` gitignore인 docs/분석 task)면 채번 보존용 1개.
|
|
111
134
|
|
|
112
|
-
반환 JSON `{ prepped, branch, wtPath, registered, commits,
|
|
135
|
+
반환 JSON `{ prepped, branch, parent, wtPath, registered, commits, aheadOfParent, multiPhase?, autoAssigned? }`. **`parent`(= task 헤더에 기록된 부모 브랜치, 예 `dev` / `dev_feat_x`)가 이후 Step 4·5의 rebase·머지 대상이다** — 아래 명령의 `$PARENT`로 사용. (task-init이 fork 시점 현재 브랜치를 헤더에 기록해뒀다.)
|
|
136
|
+
|
|
137
|
+
- **`multiPhase` / `autoAssigned`가 있으면 Step 8 보고에 그대로 옮긴다** — 코드가 자동 편입한 파일과 그 근거(어느 Phase로 갔는지)를 사용자가 볼 수 있어야 한다. 재배치 목적의 수동 커밋 재작업은 하지 않는다(GIT_RULE: 중간 커밋 독립 빌드 비보장).
|
|
113
138
|
|
|
114
139
|
**콜백 (반환 `blocked` 필드 / npx는 특수 exit — 메인이 LLM 판단 후 처리):**
|
|
115
|
-
- **`blocked:'mapping'`** (npx exit 2 — `{files, phases, reason}`): Dev Plan `- 파일:` 필드가 변경 파일을 못 덮음(
|
|
140
|
+
- **`blocked:'mapping'`** (npx exit 2 — `{files, phases, reason}`): Dev Plan `- 파일:` 필드가 변경 파일을 못 덮음(**미매핑 — 빌드 산출물이 아닌 일반 파일 한정**. 다중 Phase 파일·산출물은 위 폴백으로 자동 처리돼 여기 오지 않는다). → 메인이 Dev Plan + `git -C "$WT_PATH" diff --name-only` 정독 후 **코드 변경분을 Phase별로 수동 커밋**(GIT_RULE 형식, 위 태그) → `task_close` 도구(또는 `npx ... close`) **재호출**. 코드가 이미 커밋돼 있으므로 close가 status=closed + 문서 커밋 + 마커를 자동 완료한다.
|
|
116
141
|
- **`blocked:'status'`** (npx exit 3 — `{current}`): status가 `tested`가 아님. Step 1~2 통과했다면 발생 X. 발생 시 사용자 보고 + 중단.
|
|
117
142
|
|
|
118
143
|
> **close 후 task 문서 수정 금지** — close가 status=`closed`로 잠갔다(`closed-immutable.sh` hook 차단). 이후 Step 4 충돌 해결 내역은 *task 문서가 아니라 rebase/머지 커밋 메시지*에 기록한다.
|
|
119
144
|
|
|
120
145
|
### Step 4 — 사전 rebase + 충돌 자체 해결 (락 외, UX용 조기 감지)
|
|
121
146
|
|
|
122
|
-
`close`가 모든 변경을 커밋했으므로 rebase가 깨끗하게 replay된다.
|
|
147
|
+
`close`가 모든 변경을 커밋했으므로 rebase가 깨끗하게 replay된다. `$PARENT` = Step 3 `close` 반환의 `parent`(머지 대상 부모 브랜치).
|
|
123
148
|
|
|
124
149
|
```sh
|
|
125
|
-
git -C "$WT_PATH" rebase
|
|
150
|
+
git -C "$WT_PATH" rebase "$PARENT"
|
|
126
151
|
```
|
|
127
152
|
|
|
128
153
|
- 충돌 없음 → Step 5 (머지).
|
|
@@ -140,7 +165,7 @@ git -C "$WT_PATH" rebase dev
|
|
|
140
165
|
| 순위 | 자료 | 위치 |
|
|
141
166
|
|------|------|------|
|
|
142
167
|
| 1 | 태스크 문서 + 제품/plan 문서 (양쪽 정독 후 의도 종합) | 태스크: `$MAIN_WT/.project/tasks/<NNN_slug>/...` (등록 케이스) / `~/.taskery/worktrees/<projectId>/TASK-...` 다른 워크트리 (미등록 케이스, SSoT 조회로 경로 산출). 제품 관통 문서(FEATURES / ARCHITECTURE / TECH-STACK / DATA-MODEL / API-SPEC 등) = `$MAIN_WT/.project/<doc>.md` (루트 평평). plan 로컬(ROADMAP / PLAN) = `$MAIN_WT/.project/plans/<NNN_slug>/` |
|
|
143
|
-
| 2 | 커밋 메시지 | `git log
|
|
168
|
+
| 2 | 커밋 메시지 | `git log --all --grep` (GIT_RULE 풍부 메시지) |
|
|
144
169
|
| 3 | diff | 변경 코드 자체 |
|
|
145
170
|
|
|
146
171
|
- 1순위 부재 시 2/3순위 자동 fallback + 사용자에게 *자료 한계* 보고
|
|
@@ -152,9 +177,9 @@ git -C "$WT_PATH" rebase dev
|
|
|
152
177
|
- 해결 방향 후보 제시 + 사용자 결정 후 재개.
|
|
153
178
|
- 사용자가 중단 결정 시: `git -C "$WT_PATH" rebase --abort` 자동 + close 중단.
|
|
154
179
|
|
|
155
|
-
### Step 5 — 머지 락 + 락 안 재 rebase +
|
|
180
|
+
### Step 5 — 머지 락 + 락 안 재 rebase + 부모 브랜치 머지
|
|
156
181
|
|
|
157
|
-
머지 락 안에서 [락 안 rebase → 메인WT 검증 →
|
|
182
|
+
머지 락 안에서 [락 안 rebase → 메인WT 검증 → 부모 브랜치 `--no-ff` 머지]를 직렬 수행한다 (`bin/lib.js` `withMergeLock(projectId, fn)` — 다른 세션 머지와 직렬화). Phase 커밋·status=closed·문서 커밋·추적마커는 Step 3 `close`가 이미 끝냈으므로 본 단계는 *락 + rebase + 머지*만 담당. 메인 워크트리는 부모 브랜치(`$PARENT`)에 서 있어야 하며(close가 이미 검증), 머지는 그 부모 위로 이뤄진다.
|
|
158
183
|
|
|
159
184
|
#### 5-1. 머지 락 획득
|
|
160
185
|
|
|
@@ -163,13 +188,13 @@ git -C "$WT_PATH" rebase dev
|
|
|
163
188
|
#### 5-2. 락 안에서 rebase 재실행
|
|
164
189
|
|
|
165
190
|
```sh
|
|
166
|
-
git -C "$WT_PATH" rebase
|
|
191
|
+
git -C "$WT_PATH" rebase "$PARENT"
|
|
167
192
|
```
|
|
168
193
|
|
|
169
|
-
락 외(Step 4) rebase 이후 *다른 세션이
|
|
194
|
+
락 외(Step 4) rebase 이후 *다른 세션이 부모 브랜치에 머지했을 수 있음* — 락 안 rebase로 흡수.
|
|
170
195
|
- 재충돌 발견 시 Step 4 에스컬레이션 재실행 (해결 내역은 커밋 메시지 — 문서 closed).
|
|
171
196
|
|
|
172
|
-
> Phase 커밋 · flows/문서 커밋 · status=closed · 추적 마커는 **Step 3 `close`가 이미 완료**했다. 본 단계는 머지 락 안에서 *재 rebase + 메인WT 검증 +
|
|
197
|
+
> Phase 커밋 · flows/문서 커밋 · status=closed · 추적 마커는 **Step 3 `close`가 이미 완료**했다. 본 단계는 머지 락 안에서 *재 rebase + 메인WT 검증 + 부모 머지*만 수행한다.
|
|
173
198
|
|
|
174
199
|
#### 5-3. 메인 워크트리 uncommitted 검증 (머지 직전)
|
|
175
200
|
|
|
@@ -180,7 +205,9 @@ git -C "$MAIN_WT" status --porcelain
|
|
|
180
205
|
- 변경 있으면 → 사용자 호출 + 결정 (stash / 중단).
|
|
181
206
|
- 등록 케이스에서 task 문서 직접 수정이 *.gitignore 차단으로 status에 안 잡힘* — 정상.
|
|
182
207
|
|
|
183
|
-
#### 5-4.
|
|
208
|
+
#### 5-4. 부모 브랜치 `--no-ff` 머지
|
|
209
|
+
|
|
210
|
+
메인 워크트리는 부모 브랜치(`$PARENT`)에 체크아웃돼 있다(close 검증). 그 위로 작업 브랜치를 머지한다.
|
|
184
211
|
|
|
185
212
|
```sh
|
|
186
213
|
git -C "$MAIN_WT" merge --no-ff "$BRANCH"
|
|
@@ -188,7 +215,7 @@ git -C "$MAIN_WT" merge --no-ff "$BRANCH"
|
|
|
188
215
|
|
|
189
216
|
- `-m` 옵션 금지 (git 기본 메시지).
|
|
190
217
|
- 머지 커밋 해시 캡처: `MERGE_COMMIT=$(git -C "$MAIN_WT" rev-parse HEAD)`
|
|
191
|
-
- 브랜치가
|
|
218
|
+
- 브랜치가 부모보다 1커밋 이상 앞서야 머지 커밋이 생성된다 — Step 3 `close`의 추적 마커가 docs/분석 task의 0-커밋 케이스를 이미 보장(채번 보존).
|
|
192
219
|
|
|
193
220
|
#### 5-5. 머지 락 해제
|
|
194
221
|
|
|
@@ -220,7 +247,7 @@ git -C "$WT_PATH" ls-files --others --exclude-standard # 추적 X 파일
|
|
|
220
247
|
- 발견 시 사용자 호출 + 결정:
|
|
221
248
|
- 보존 → 7-2, 7-3 모두 건너뜀 (브랜치도 보존 — 정합)
|
|
222
249
|
- 삭제 → 7-2 진행
|
|
223
|
-
- 취소 → close 중단 (
|
|
250
|
+
- 취소 → close 중단 (부모 브랜치 머지는 이미 완료)
|
|
224
251
|
|
|
225
252
|
#### 7-2. 워크트리 제거
|
|
226
253
|
|
|
@@ -245,7 +272,9 @@ git -C "$MAIN_WT" worktree remove "$WT_PATH"
|
|
|
245
272
|
- 작업 브랜치: <BRANCH> (삭제 / 보존)
|
|
246
273
|
- 워크트리: <WT_PATH> (제거 / 보존)
|
|
247
274
|
- 커밋: Phase <N>개 + 태스크 문서 + (CHANGELOG)
|
|
248
|
-
-
|
|
275
|
+
- 문서 갱신: <Step 2.5 점검 6항 중 실제 갱신한 것 — 예: PLAN.md 체크리스트 [x] / changelog 2026-08 신규 / ARCHITECTURE 수정이력 1행. 없으면 "해당 없음">
|
|
276
|
+
- 자동 편입: <multiPhase / autoAssigned 있을 때만 — 예: `src/ipc.ts` Phase 2·5 → Phase 2 / `project.pbxproj` → Phase 3(빌드 산출물)>
|
|
277
|
+
- 부모 브랜치 병합: <PARENT> ← --no-ff 완료 ($MERGE_COMMIT)
|
|
249
278
|
- 충돌 해결: <건수, 자료 한계 보고 있으면 포함>
|
|
250
279
|
- 상태: tested → closed
|
|
251
280
|
- 다음: 새 task 시작은 /task-init. 마찰 신호 감지된 경우 /log-friction 등록 제안
|
|
@@ -262,14 +291,14 @@ git -C "$MAIN_WT" worktree remove "$WT_PATH"
|
|
|
262
291
|
|
|
263
292
|
- **사용자 명시 호출 외 자체 진입 영구 금지** (stash FRICTION_LOG #6+10/#20) — task-close는 git 영역. 사용자가 *"X부터 Y까지"* 범위 명시했는데 Y가 close 이전 단계면 close 자체 진입 영구 X.
|
|
264
293
|
- **검증 명령 재실행 게이트** — `/task-dev` self-check와 *별개*. 환경 변화 / 부분 작업 잡는 안전망.
|
|
265
|
-
-
|
|
294
|
+
- **부모 브랜치 직접 커밋 절대 X** — 작업 브랜치에서만. 부모가 dev/main이면 그 브랜치에서 `git commit` 시도 시 git-guard.sh가 차단(git-guard는 main/dev 보호). 모든 git 명령은 cwd 무관 `git -C "$WT_PATH" ...` / `git -C "$MAIN_WT" ...` 형태 강제. 셸 prefix(`cd && git`) / `--git-dir=` / `--work-tree=` 변형 영구 금지 (§호출 위치 정책).
|
|
266
295
|
- **`--no-ff` 강제** — 머지 커밋 없으면 분기 정보 영구 손실.
|
|
267
296
|
- **머지 락 직렬화** — 두 세션이 동시 머지 시도해도 한쪽씩 순차 진행. 락 외 rebase로 race 흡수 + 락 안 재 rebase로 다른 세션 머지 흡수.
|
|
268
297
|
- **충돌 자체 해결 3단계** — 단순 자동 / 의미적 자료 / 판단 불가 사용자. 자료 한계 발견 시 *반드시 사용자에게 보고* (1순위 자료 부재 등).
|
|
269
298
|
- **자료 한계 보고** — 충돌 분석 시 *2/3순위 fallback 사용했음*을 사용자에게 명시. 묵묵히 진행 X.
|
|
270
299
|
- **destructive 명령 사용자 승인 필수** — `git reset --hard` / `git push --force` / `git branch -D` / `git clean -fd` 사용자 명시 승인 없이 절대 실행 X. (단 `/task-close` 자동 흐름 `git branch -d` + `worktree remove`는 §"작업 브랜치 삭제 정책 — 자동 삭제 면제 조항" 면제)
|
|
271
300
|
- **민감 정보 staging X** — `.env` / `credentials.json` / API key 등 staging 절대 X.
|
|
272
|
-
- **빈 commit 금지 (예외 1건)** — `close`가 변경 없는 영역은 빈 commit을 만들지 않는다. **단 Step 3 `close`의 추적 마커 빈커밋만 예외** — 워크트리 브랜치가
|
|
301
|
+
- **빈 commit 금지 (예외 1건)** — `close`가 변경 없는 영역은 빈 commit을 만들지 않는다. **단 Step 3 `close`의 추적 마커 빈커밋만 예외** — 워크트리 브랜치가 부모보다 앞선 커밋이 0개일 때 채번 보존용으로 1개 허용.
|
|
273
302
|
- **`-m` 옵션 머지 커밋에 사용 금지** — git 기본 메시지 사용.
|
|
274
303
|
- **검수 서버/터널 정리는 자기 것만** — 본 task가 검수용으로 띄운 서버·터널(자기 포트 것)만 종료. `pkill -f` 류 광역 종료 금지 (다른 세션 프로세스까지 죽임). 상세: GIT_RULE "멀티세션 검수 환경".
|
|
275
304
|
|
|
@@ -287,4 +316,4 @@ git -C "$MAIN_WT" worktree remove "$WT_PATH"
|
|
|
287
316
|
- **task 문서 단일 진실 소스** — `.gitignore` 케이스에 따라 메인 워크트리 또는 워크트리. 다른 세션의 충돌 해결 자료 정독 시 *SSoT 조회 → 워크트리 경로 산출* (미등록 케이스) 또는 *메인 워크트리 절대 경로* (등록 케이스).
|
|
288
317
|
- **워크트리 + 브랜치 자동 제거** — GIT_RULE.md "작업 브랜치 삭제 정책" 면제 조항 (taskery 한정). 보존 키워드 시 양쪽 보존.
|
|
289
318
|
- **safety net** — Step 8 복구 명령 출력. 사용자가 잘못 삭제 인지 시 즉시 복구 가능.
|
|
290
|
-
- **BACKLOG.md 무관** — `.project/tasks/<NNN_slug>/BACKLOG.md` 체크 마킹은 `/task-init` Step 7.5가 처리(`[ ]` → `[x]` + `- TASK: TASK-NNN`). `[x]` = *task로 옮김* 의미라 close 시점에 추가 마킹 X. 완료 추적은 `npx @angar2/taskery status`(진행 중이면
|
|
319
|
+
- **BACKLOG.md 무관** — `.project/tasks/<NNN_slug>/BACKLOG.md` 체크 마킹은 `/task-init` Step 7.5가 처리(`[ ]` → `[x]` + `- TASK: TASK-NNN`). `[x]` = *task로 옮김* 의미라 close 시점에 추가 마킹 X. 완료 추적은 `npx @angar2/taskery status`(진행 중이면 부모 미머지가 정상) → 목록에 없을 때만 `git log --all --grep 'BL-NNN'` 순.
|
|
@@ -59,6 +59,8 @@ self-check 명령은 워크트리(`$WT_PATH`)에서 실행 — 코드 변경이
|
|
|
59
59
|
- **`## 검증 명령`** (코드 상태 — 빌드/린트/타입체크): self-check 게이트의 단일 진실 소스 (Step 6).
|
|
60
60
|
- **`## 테스트 명령`** (테스트 실행 — 단위/통합/E2E): 구현 후 테스트 실행의 단일 진실 소스 (Step 6.5).
|
|
61
61
|
- stash FRICTION_LOG #25 반영 — 두 섹션 분리. self-check 게이트는 *코드 상태*만, 테스트는 *별도 단계*.
|
|
62
|
+
5. **프로젝트 로컬 룰 확인** — `$MAIN_WT/.project/rules/DEV_RULE.local.md`(구현 정책)와 `$MAIN_WT/.project/rules/TEST_RULE.local.md`(테스트 범위·방식 정책)를 각각 있으면 Read한다 (없으면 넘어간다. `npx update` 미터치 영역이라 프로젝트가 자유롭게 소유한다). 본 스킬 조항과 겹치는 항목은 **로컬 룰을 우선 적용**한다 — 프로젝트마다 구현·테스트 실행 방식이 다르므로 본 스킬 조항은 *안전한 기본값*이다. **Step 6.5의 테스트 실행 범위·신설 상한은 `TEST_RULE.local.md`가 있으면 그 규정을 따른다** (본 스킬이 테스트를 실제로 실행하는 주체이므로, 그 파일을 읽지 않으면 프로젝트 고유 규칙이 무력해진다).
|
|
63
|
+
- **로컬 룰이 뒤집을 수 없는 것** (충돌 시 코어 우선): 멀티세션 불변식(머지 락 · 메인 워크트리 테스트 금지 · git 명령은 `/task-close`만) · destructive 명령 사용자 승인 · 상태 전이 유효성.
|
|
62
64
|
|
|
63
65
|
### Step 2 — status 전환 (planned → developing)
|
|
64
66
|
|
|
@@ -118,7 +120,7 @@ Dev Plan에 Phase 0(제품 관통 문서 변경)이 있으면:
|
|
|
118
120
|
|
|
119
121
|
stash FRICTION_LOG #14+19 / #25 반영 — 유닛 테스트는 본 단계에서 단일 시점 실행 (task-close / hook 영역 중복 제거).
|
|
120
122
|
|
|
121
|
-
`CLAUDE.md` `## 테스트 명령` 섹션의 명령을 *전부* 실행. 모두 PASS여야 `developed`로 전이 가능.
|
|
123
|
+
`CLAUDE.md` `## 테스트 명령` 섹션의 명령을 *전부* 실행. 모두 PASS여야 `developed`로 전이 가능. **본 게이트는 *구현 완료 시점 1회*다** — 아래 "수정 루프 국면"에 해당하는 동안에는 매 사이클 전부 실행하지 않는다. 또한 수정 루프 국면을 거친 뒤 곧바로 `/task-test`로 이어가는 경우에는 국면 ⑥에 따라 본 게이트의 전체 실행을 생략하고 *격리 세션의 실행*으로 갈음한다 (그때의 `developed` 전이 근거 = 린트·타입체크 PASS + 변경이 닿는 테스트 PASS이며, 전체 스위트는 격리 세션이 책임진다).
|
|
122
124
|
|
|
123
125
|
| 명령 | PASS 기준 |
|
|
124
126
|
|------|---------|
|
|
@@ -132,6 +134,34 @@ stash FRICTION_LOG #14+19 / #25 반영 — 유닛 테스트는 본 단계에서
|
|
|
132
134
|
- 신규 *테스트 식별자* (suite / class / function / describe 등) 가 테스트 runner 결과 로그에 *실제 등장*했는지 grep 직접 확인 (1 hit 이상).
|
|
133
135
|
- 예: `grep -E "Suite \"<NewSuite>\"" test-output.log` → hit 1 이상.
|
|
134
136
|
- 등장 안 하면 *Suite 미실행* (빌드 시스템 등록 누락 등) → FAIL 처리.
|
|
137
|
+
- **신규 테스트 실효성 확인 (음성대조)** — 본 task에서 테스트를 신설했으면, 가능한 범위에서 *구현을 일시적으로 되돌린 상태에서 그 테스트가 실제로 FAIL하는지* 확인한 뒤 통과를 근거로 삼는다 (Edit로 되돌렸다가 확인 후 즉시 원복 — git 명령 사용 금지). 통과만 보면 테스트가 무력해도 알 수 없다 (stash FRICTION 2026-07-28 — 흐름 테스트 2건이 이 확인으로 실효성을 입증했다). 되돌리기가 위험하거나 부작용이 큰 영역이면 생략하고 그 사유를 Result에 적는다.
|
|
138
|
+
|
|
139
|
+
**화면·입력 점유 스위트 자동 실행 금지 (stash FRICTION 2026-07-25 / recordion FRICTION 2026-08-05 반영)**:
|
|
140
|
+
|
|
141
|
+
실제 앱을 띄워 UI를 자동 조작하는 스위트(XCUITest·headed 브라우저 E2E 등)는 사용자의 화면·마우스·키보드를 점유해 **작업을 중단시킨다.** `## 테스트 명령`이 단일 진실 소스라는 원칙은 유지하되, 실행 방식은 아래를 따른다.
|
|
142
|
+
|
|
143
|
+
| 상황 | 실행 방식 |
|
|
144
|
+
|------|----------|
|
|
145
|
+
| `TEST-GUIDE.md` *테스트 실행 환경* 절에 **격리 실행 경로**(창 숨김·헤드리스 플래그 / 컨테이너·가상 디스플레이 / VM / CI 러너) 선언됨 | 그 경로로 **자동 실행 OK** |
|
|
146
|
+
| 격리 경로 없음 + 비점유 부분만 한정 실행 가능 (번들·프로젝트·태그 지정 등) | **비점유 부분만 자동 실행**, 점유 스위트는 제외 |
|
|
147
|
+
| 격리 경로 없음 + 한정 수단도 없음 | **자동 실행 금지** — 사용자에게 *무엇을 왜 돌려야 하고 얼마나 걸리며 그동안 화면·입력을 못 쓴다*를 예고하고 승인을 받은 뒤에만 실행 |
|
|
148
|
+
|
|
149
|
+
- 헤드리스 모드가 존재하면 항상 그쪽을 쓴다.
|
|
150
|
+
- 본 task가 UI를 건드리지 않는데(순수 로직·CLI 등) 테스트 명령이 UI 스위트를 포함하면, 그 스위트는 실행 대상이 아니다.
|
|
151
|
+
- 격리 실행 경로를 새로 확인했으면 `TEST-GUIDE.md` *테스트 실행 환경* 절에 기록해 다음 task가 재사용하게 한다.
|
|
152
|
+
|
|
153
|
+
**수정 루프 국면 — 재실행 범위 비례 (recordion FRICTION 2026-08-08 반영)**:
|
|
154
|
+
|
|
155
|
+
적용 범위 = ① `developed` 이후 사용자 검수 피드백으로 고치는 동안, ② `/task-test` FAIL 후 사용자 *"고쳐"*로 재진입해 고치는 동안. 이 두 국면은 *구현 완료 게이트*와 별개이며, 매 사이클 전체를 돌리지 않는다 (한 태스크에서 전체 E2E를 6회 이상 재실행해 사용자 시간을 수십 분 태운 사례가 있다).
|
|
156
|
+
|
|
157
|
+
1. **매 사이클 실행** — 린트·타입체크(수 초) + *변경한 파일이 닿는 테스트* + 그 테스트가 쓰는 공유 헬퍼를 함께 쓰는 테스트. 대개 1~2개·수십 초다.
|
|
158
|
+
2. **전체 게이트(Step 6 + Step 6.5)는 국면이 끝날 때 1회** — 국면 도중에는 돌리지 않는다. 풀빌드를 포함한 Step 6도 매 사이클 대상이 아니다. (국면이 끝나는 시점에 *실제로 돌릴지*는 아래 ⑥이 정한다 — 바로 `/task-test`로 이어가면 격리 세션의 실행으로 갈음한다.)
|
|
159
|
+
3. **테스트 러너가 빌드를 포함하지 않으면 빌드를 선행**한다 — 옛 산출물로 돌면 이미 고친 결함이 남아 있는 것처럼 보여 없는 버그를 쫓게 된다 (recordion에서 이 때문에 30분을 소모했다). 어느 명령이 빌드를 포함하는지는 `TEST-GUIDE.md`에 기록해 재사용한다.
|
|
160
|
+
4. **무관한 테스트가 깨질 때만 범위를 넓힌다** — 예상 밖 실패가 나오면 그때 상위 범위로 확대한다.
|
|
161
|
+
5. **회귀 누락 위험은 2 + `/task-test` 격리 세션의 이중 게이트가 막는다.** 좁힌 범위 때문에 회귀를 놓친다는 우려로 매 사이클 전체를 도는 것은 비용 대비 효과가 없다.
|
|
162
|
+
6. **`/task-test`로 바로 이어갈 때는 2의 전체 1회를 생략한다** — 격리 세션이 `## 검증 명령`·`## 테스트 명령`을 다시 전부 실행하므로 같은 스위트를 연달아 두 번 돌리는 셈이 된다. 세션이 `developed`에서 멈추고 사용자에게 제어를 넘길 때만 메인이 전체를 1회 실행한다. (결과: 전체 스위트는 태스크당 원칙 1회.)
|
|
163
|
+
|
|
164
|
+
**테스트 신설은 요구 범위에 비례** — 신설하는 테스트는 *본 task 요구사항을 덮는 데 필요한 최소*로 둔다. 기존 스펙이 이미 덮는 영역을 중복 검증하는 테스트를 새로 만들지 않는다. 스위트가 커질수록 이후 모든 task의 재실행 비용이 늘어난다. 프로젝트별 상한(예: *"E2E는 핵심 흐름만"*)은 `.project/rules/TEST_RULE.local.md`가 있으면 그쪽을 우선한다.
|
|
135
165
|
|
|
136
166
|
**FAIL 시**: Step 6의 FAIL 룰 동일 적용 (추측 fix 반복 방지 / 진단 로그 / 동일 신고 재발 시 root cause).
|
|
137
167
|
|
|
@@ -156,7 +186,7 @@ stash FRICTION_LOG #14+19 / #25 반영 — 유닛 테스트는 본 단계에서
|
|
|
156
186
|
|
|
157
187
|
### Step 8 — status 전환 + 결과 보고
|
|
158
188
|
|
|
159
|
-
1. `set_status` 도구로 `developed` 전이 (또는 `npx @angar2/taskery set-status TASK-<NNN> developed`) — self-check + 테스트 PASS 후. (유효전이 코드 검증.)
|
|
189
|
+
1. `set_status` 도구로 `developed` 전이 (또는 `npx @angar2/taskery set-status TASK-<NNN> developed`) — self-check + 테스트 PASS 후. (유효전이 코드 검증.) 수정 루프 국면을 거쳐 곧바로 `/task-test`로 이어가는 경우에는 Step 6.5 ⑥에 따라 *린트·타입체크 + 변경이 닿는 테스트 PASS*가 전이 근거이며, 전체 스위트는 격리 세션이 실행한다.
|
|
160
190
|
2. 결과 보고:
|
|
161
191
|
|
|
162
192
|
```
|
|
@@ -175,6 +205,7 @@ stash FRICTION_LOG #14+19 / #25 반영 — 유닛 테스트는 본 단계에서
|
|
|
175
205
|
- 두 조건 충족 시 — 그 명령으로 서버를 *백그라운드* 기동(포트 = 기준 포트 + TASK번호) + 접속 URL 보고. 모바일 검수가 필요하다고 판단되면 터널도 기동.
|
|
176
206
|
- `/task-test`로 계속 진행하면 본 단계 생략 (마지막 단계에서만 기동 — 상세: GIT_RULE "멀티세션 검수 환경").
|
|
177
207
|
- `## 검수 실행 명령` 미선언(CLI/라이브러리 등) 또는 사용자 *"안 띄워도 돼"* 발화 시 생략.
|
|
208
|
+
- **기동 전 확인 필수** — 새로 띄우기 전에 해당 포트·프로세스가 이미 살아 있는지 확인한다. `Port … is in use` 류 경고는 *이미 떠 있다*는 뜻이므로 무시하고 재기동하지 않는다. 종료할 때는 부모 프로세스만이 아니라 **자식 프로세스(브라우저·렌더러 창 등)까지** 확인해 정리한다 (recordion FRICTION 2026-08-05 — 중복 기동 + 창 잔존으로 두 번 지적, TASK-005 재발).
|
|
178
209
|
|
|
179
210
|
## 도구 가이드
|
|
180
211
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-init
|
|
3
|
-
description: task 시작 — 워크트리 분기 + 6 섹션 빈 골격 + 헤더
|
|
3
|
+
description: task 시작 — 워크트리 분기 + 6 섹션 빈 골격 + 헤더 6컬럼 (부모 브랜치 자동 기록 · status=draft) task.md 생성 (멀티세션 0.1.2+)
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# /task-init
|
|
@@ -9,26 +9,26 @@ description: task 시작 — 워크트리 분기 + 6 섹션 빈 골격 + 헤더
|
|
|
9
9
|
|
|
10
10
|
새 task 시작 시 호출. **워크트리 분기 + task.md 빈 골격 작성**. Requirements / Scope / Dev Plan / Test Plan 본문은 다음 단계 `/task-plan`에서 채운다.
|
|
11
11
|
|
|
12
|
-
> 메인 워크트리(
|
|
12
|
+
> 메인 워크트리(부모 브랜치 체크아웃 — 기본 dev)에서 호출. 서 있는 브랜치가 곧 부모가 된다. 채번·워크트리·브랜치 생성·골격 작성은 `task_init` 도구(fork)가 init 락 안에서 원자 수행한다.
|
|
13
13
|
|
|
14
14
|
## 호출 시점 + 입력
|
|
15
15
|
|
|
16
|
-
- 새 task 시작 (*"~~ 추가해줘"* / *"~~ 버그 고쳐"* / *"~~ 리팩터링"*), 백로그 진행(*"BL-003 진행하자"*), 로드맵 진행(*"
|
|
17
|
-
- 인자 = (선택) 주제 / 유형 / 출처(BL-NNN,
|
|
16
|
+
- 새 task 시작 (*"~~ 추가해줘"* / *"~~ 버그 고쳐"* / *"~~ 리팩터링"*), 백로그 진행(*"BL-003 진행하자"*), 로드맵 진행(*"Stage 2 진행하자"* / *"로드맵 다음 거 시작"*).
|
|
17
|
+
- 인자 = (선택) 주제 / 유형 / 출처(BL-NNN, ST-N, DR) / 규모.
|
|
18
18
|
- **두 분기**: ① **제안** — 직전 맥락 명확 → *"이렇게 task 만들까요?"* + confirm. ② **인터뷰** — 맥락 부족 → 한 번에 한 질문씩.
|
|
19
19
|
- **자동 추정 진행 X** — confirm 또는 답 받기 전 워크트리/파일 생성 금지.
|
|
20
20
|
|
|
21
21
|
## Step 1 — 메타 수집
|
|
22
22
|
|
|
23
23
|
직전 대화 정독 → 추정 가능하면 분기 1(제안), 불가하면 분기 2(인터뷰):
|
|
24
|
-
- Q1 *"무슨 작업? (한 줄로)"* / Q2 *"유형? (feature / bug / improvement / refactor / docs / chore)"* / Q3 *"출처? (백로그 BL-NNN / 로드맵
|
|
24
|
+
- Q1 *"무슨 작업? (한 줄로)"* / Q2 *"유형? (feature / bug / improvement / refactor / docs / chore)"* / Q3 *"출처? (백로그 BL-NNN / 로드맵 Stage ST-N / 직접 요구사항 DR)"* / Q4 *"규모? (micro / small / medium / large)"* / (필요 시) Q5 *"plan `<NNN_slug>` 맞나요?"*
|
|
25
25
|
|
|
26
26
|
수집 항목(모두 확정 후 진행): 주제(한국어) · 유형 · 출처 · 규모 · plan(활성 plan — `status` 도구나 AGENT-GUIDE에서). 활성 plan 부재 시 *"`/plan-init` 먼저 실행할까요?"* 안내 + 중단.
|
|
27
27
|
|
|
28
28
|
## Step 2 — 출처별 메타 + 슬러그
|
|
29
29
|
|
|
30
30
|
- **BL**: `backlog_get` 도구(또는 `npx @angar2/taskery backlog-get BL-NNN`) → `{ blId, status, type, title, slug, summary, target, taskNums }`. 항목 없으면 에러 → 보고 + 중단. **개요/대상 영역은 task.md §1 Requirements 초안 시작점**으로 기억(본문은 task-plan에서). 슬러그 = 반환 `slug` 그대로(재현성 — 별도 변환 X).
|
|
31
|
-
- **
|
|
31
|
+
- **ST**: `$MAIN_WT/.project/plans/<활성 plan>/ROADMAP.md`에서 해당 Stage N의 작업 단위 확인 → 이번 task가 맡을 작업 단위를 사용자와 confirm. 슬러그 = 그 작업 단위 제목 → 영어 kebab-case(3 단어 이내) → confirm. (ROADMAP은 Stage 단위·별도 항목 채번 없음 — `ST-N` = Stage 번호 그대로.)
|
|
32
32
|
- **DR**: 사용자 발화에서 주제 그대로. 슬러그 = 한국어 제목 → 영어 kebab-case(3 단어 이내) → confirm.
|
|
33
33
|
|
|
34
34
|
**이미 `[x]` BL 재진행 케이스** — `backlog_get` 결과 `status==='checked'` & `taskNums` 비어있지 않으면: 사용자 호출 *"BL-NNN은 ${taskNums}로 이미 처리된 적 있어. 새 task로 다시 진행할까?"* → OK면 새 TASK 진행(§4 마킹은 콤마 누적) / X면 중단.
|
|
@@ -41,33 +41,33 @@ description: task 시작 — 워크트리 분기 + 6 섹션 빈 골격 + 헤더
|
|
|
41
41
|
|
|
42
42
|
## Step 4 — 분기 + 골격 생성 (`task_init`) + BL 마킹
|
|
43
43
|
|
|
44
|
-
`task_init` 도구(또는 `npx @angar2/taskery fork <타입> <개발자> <출처> <슬러그> --size <규모> --title "<한국어 제목>" [--promote]`) 한 번으로 **채번 → 워크트리·브랜치 생성**(init 락 원자 — 병렬 task-init 번호 충돌·동일 출처
|
|
44
|
+
`task_init` 도구(또는 `npx @angar2/taskery fork <타입> <개발자> <출처> <슬러그> --size <규모> --title "<한국어 제목>" [--promote]`) 한 번으로 **채번 → 워크트리·브랜치 생성**(init 락 원자 — 병렬 task-init 번호 충돌·동일 출처 중복(**BL·구형 RM 한정** — `ST-N`은 Stage 하나에서 복수 task가 정상, `DR`은 ID 없음이라 둘 다 중복 검사 제외)·동일 브랜치명을 코드가 차단)에 더해 **빈 골격 task.md 자동 생성**(생성일=오늘 · plan=활성 plan · 유형 자동매핑 `improve`→`improvement` · **부모 브랜치=fork 시점 현재 브랜치 자동 기록**(dev 고정 아님) · status=draft · `.gitignore` 케이스로 위치 자동 판정)까지 수행한다.
|
|
45
45
|
|
|
46
|
-
- 반환 `{ taskNum, nnn, branch, wtPath, projectId, docPath, registered, promoted }
|
|
47
|
-
- 에러 시(*"… 이미 진행중"* / *"…
|
|
48
|
-
- **BL 출처면** 직후 `backlog_mark` 도구(또는 `npx @angar2/taskery backlog-mark BL-NNN TASK-NNN`)로 `[ ]→[x]` + `- TASK:` 마크(콤마 누적, withMetaLock).
|
|
46
|
+
- 반환 `{ taskNum, nnn, branch, wtPath, projectId, parent, docPath, registered, promoted }` (`parent` = fork 시점 현재 브랜치 = 이 task의 부모 브랜치. `/task-close`가 이 브랜치로 되병합한다). 폴더 승격은 `--promote`/`promote:true`.
|
|
47
|
+
- 에러 시(*"… 이미 진행중"* / *"… detached HEAD"* — 부모 브랜치(현재 브랜치) 확인·SSoT를 fork가 강제) stderr 메시지 그대로 보고 + 중단.
|
|
48
|
+
- **BL 출처면** 직후 `backlog_mark` 도구(또는 `npx @angar2/taskery backlog-mark BL-NNN TASK-NNN`)로 `[ ]→[x]` + `- TASK:` 마크(콤마 누적, withMetaLock). ST/DR은 skip.
|
|
49
49
|
|
|
50
50
|
## Step 5 — 골격 확인 + 보고
|
|
51
51
|
|
|
52
|
-
반환 `docPath`(절대 경로)를 Read해 헤더
|
|
52
|
+
반환 `docPath`(절대 경로)를 Read해 헤더 6컬럼 + 6 섹션 placeholder + status=draft 확인만 한다. **본문 작성 금지** — Requirements / Scope / Dev Plan / Test Plan은 *반드시* `/task-plan`에서.
|
|
53
53
|
|
|
54
54
|
> **폴백** (반환에 `docPath` 없이 `scaffoldError`만 있을 때만): TASK_DOC_RULE §1.3 형식으로 해당 위치에 직접 작성(생성일=오늘, status=draft, 단일=`<NNN>_<slug>.md` / 폴더=`TASK-<NNN>_<slug>/task.md`).
|
|
55
55
|
|
|
56
56
|
```
|
|
57
57
|
✅ TASK-<NNN> 생성 완료
|
|
58
58
|
- 워크트리: <wtPath> / 브랜치: <branch> / task 문서: <docPath>
|
|
59
|
-
- 헤더: <생성일> / <plan> / <유형> / <규모> / draft
|
|
60
|
-
- BL 마킹: BL-<NNN> [x] (BL 출처 시.
|
|
59
|
+
- 헤더: <생성일> / <plan> / <유형> / <규모> / <부모 브랜치> / draft
|
|
60
|
+
- BL 마킹: BL-<NNN> [x] (BL 출처 시. ST/DR 생략)
|
|
61
61
|
- 다음: /task-plan TASK-<NNN> 으로 기획 채우기
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
## 주의사항
|
|
65
65
|
|
|
66
66
|
- **워크트리 생성 + 골격 작성만** — 본문 채우기 금지. Requirements / Scope / Dev Plan / Test Plan은 *반드시* `/task-plan`.
|
|
67
|
-
- **단계 경계** — 허용: ROADMAP
|
|
67
|
+
- **단계 경계** — 허용: ROADMAP의 해당 Stage 확인(출처가 `ST-N`일 때) / SSoT 조회 / `task_init` 호출 / 빈 골격 확인. 금지: ARCHITECTURE/API-SPEC/FEATURES 등 루트 제품 관통 문서 본문 Read · 도메인 코드 Read·Grep · 기존 task 본문 Read (그건 `/task-plan` 영역).
|
|
68
68
|
- **자동 추정 진행 X** — 맥락 명확해도 *제안 + OK* 후 생성.
|
|
69
|
-
- **상태는 `draft` 고정** · **slug 영어 kebab-case** · **헤더
|
|
70
|
-
- **fork 실패(같은 브랜치명 / 같은 출처 진행중) → 사용자 호출** + 중단(*"다른 세션이 같은 항목 진행 중"*).
|
|
69
|
+
- **상태는 `draft` 고정** · **slug 영어 kebab-case** · **헤더 6컬럼 모두 채움**(*"미정"* placeholder X — 코드가 채움. 부모 브랜치도 코드 자동 기록).
|
|
70
|
+
- **fork 실패(같은 브랜치명 / 같은 출처 진행중 — BL·구형 RM 한정) → 사용자 호출** + 중단(*"다른 세션이 같은 항목 진행 중"*). `ST-N`·`DR`은 중복 게이트가 없으므로 같은 Stage로 두 번째 task를 만들 때 코드가 막아주지 않는다 — 중복 진행 여부는 메인이 `status`로 확인한다.
|
|
71
71
|
|
|
72
72
|
## 상태 전이
|
|
73
73
|
|
|
@@ -24,7 +24,7 @@ MAIN_WT=$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")
|
|
|
24
24
|
| 케이스 | task 문서 위치 | 제품 관통 문서 위치 | 동시 쓰기 |
|
|
25
25
|
|--------|--------------|----------------|----------|
|
|
26
26
|
| 등록 (퍼블릭 리포 default) | `$MAIN_WT/.project/tasks/<NNN_slug>/...` | `$MAIN_WT/.project/<doc>.md` (루트 평평) | `withMetaLock` (`bin/lib.js`) |
|
|
27
|
-
| 미등록 | `$WT_PATH/.project/tasks/<NNN_slug>/...` (워크트리 안, 머지 시
|
|
27
|
+
| 미등록 | `$WT_PATH/.project/tasks/<NNN_slug>/...` (워크트리 안, 머지 시 부모 브랜치 반영) | `$MAIN_WT/.project/<doc>.md` (제품 문서는 여전히 단일 소스) | 단일 세션 가정 (워크트리 내부) |
|
|
28
28
|
|
|
29
29
|
본문 모든 `.project/...` 경로는 *위 분기에 따라* 적용. spec-diff / mockup / screenshots는 task 문서와 같은 위치.
|
|
30
30
|
|
|
@@ -54,6 +54,7 @@ MAIN_WT=$(dirname "$(git rev-parse --path-format=absolute --git-common-dir)")
|
|
|
54
54
|
- **`draft`** → 일반 기획 (Step 2~ 전체 진행).
|
|
55
55
|
- **`testing` + Test Plan 보수 모드** → `/task-test`가 *시험문제 결함*으로 반려해 되돌아온 경우에 한해 허용. 이때는 **Test Plan 섹션만 보수**(Requirements / Scope / Dev Plan 보존), Step 2~4는 건너뛰고 Step 5(Test Plan)만 수행, status는 `testing` 그대로 둔다(전이 X — 보수 후 `/task-test` 재실행).
|
|
56
56
|
- **그 외(`planned` / `developing` / `developed` / `tested` / `closed`)** → 종료 + 안내. (특히 `tested` / `closed`는 보수 모드로도 진입 거부 — 우회 방지.)
|
|
57
|
+
4. **프로젝트 로컬 룰 확인** — `$MAIN_WT/.project/rules/TEST_RULE.local.md`가 있으면 Read한다 (없으면 넘어간다). Test Plan의 검증 범위·방식 선택에서 본 스킬 조항과 겹치면 **로컬 룰 우선** (멀티세션 불변식·안전 조항 제외).
|
|
57
58
|
|
|
58
59
|
### Step 2 — Requirements 인터뷰 + 증폭
|
|
59
60
|
|
|
@@ -169,11 +170,12 @@ Step 2 Requirements 인터뷰 결과로 본 task가 *UX/UI 구현 (페이지/컴
|
|
|
169
170
|
|
|
170
171
|
#### 3. 목업 생성 + 사용자 승인
|
|
171
172
|
|
|
172
|
-
1.
|
|
173
|
+
1. 목업 형식·위치·네이밍은 `$MAIN_WT/.project/rules/MOCKUP_RULE.md`를 따른다 (`MOCKUP_RULE.local.md`가 있으면 그쪽 우선).
|
|
174
|
+
2. 메인이 HTML 목업 생성 — 정적 HTML/CSS (외부 라이브러리 X, 단일 파일 안 inline style + 필요 시 vanilla JS):
|
|
173
175
|
- 시각 영역 (레이아웃 / 색상 / 간격 / 타이포 / 호버 효과)
|
|
174
176
|
- 인터랙션 (가능한 범위 — 클릭 / 호버 시뮬)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
3. 사용자에게 *"브라우저로 `.project/tasks/<NNN_slug>/mockup/<task-doc-name>-mockup.html` 열어 확인 후 ✓/✗ 응답"*.
|
|
178
|
+
4. 사용자 ✓ → 승인 완료, 다음 절(4. 파일 위치 / 네이밍) 진행. ✗ → 메인이 수정 후 재승인 요청.
|
|
177
179
|
|
|
178
180
|
#### 4. 파일 위치 / 네이밍
|
|
179
181
|
|
|
@@ -186,6 +188,7 @@ Step 2 Requirements 인터뷰 결과로 본 task가 *UX/UI 구현 (페이지/컴
|
|
|
186
188
|
승인된 목업 = task-test의 **시각 *자동 대조* 정답지** (+ 미세 취향은 사용자 최종 사인). 사용자가 맘에 들 때까지 승인 안 하므로 목업 = 이미 사용자가 검증한 정답지 — task-test 격리 세션이 *실제 화면 캡처 → 이 목업과 자동 대조*해 객관적 깨짐을 잡는다. Step 5 Test Plan 작성 시:
|
|
187
189
|
- **시각 *객관* 영역(레이아웃/요소 유무/색/배치) → `[AUTO]`** (캡처-목업 대조) + 목업 경로 참조 명시.
|
|
188
190
|
- **시각 *미세 취향*(2px·색조·느낌) → `[USER]`** (사용자 최종 사인, 증거 캡처).
|
|
191
|
+
- **`[AUTO]` 승격 조건 — 실행 경로 확인 필수**: 시각 객관 영역의 `[AUTO]` 분류는 `$MAIN_WT/.project/TEST-GUIDE.md` *시각 실행* 절에 **이 프로젝트의 캡처 실행 경로가 적혀 있을 때만** 성립한다. 목업 존재는 *정답지 확보*일 뿐 *실행 경로 확보*가 아니다. 경로가 없거나, 앱 기동이 사용자 실데이터·전역 단축키·화면 입력을 건드리는 구조면 `[USER]` 폴백으로 둔다 (stash FRICTION 2026-07-27 — 경로 없는 `[AUTO]` 분류로 `/task-test` 2회 왕복). **다른 방식과 달리 시각은 경로가 없다고 사용자에게 도구 도입을 요구하며 멈추지 않는다** — 조용히 `[USER]`로 두고 진행한다. 자동화 도입 여부는 사용자가 원할 때 별도로 정한다.
|
|
189
192
|
(이전의 "승인 목업 = USER 검수 기준 / 시각=전부 [USER]"는 폐기 — 사용자에게 흠 사냥을 떠넘기던 원인.)
|
|
190
193
|
|
|
191
194
|
---
|
|
@@ -230,14 +233,16 @@ Test Plan = *본 task에서 구현한 요구사항이 정상 동작하는지*
|
|
|
230
233
|
| 사이드 이펙트 확인 | DB / 파일 / 로그 | 조회 결과(행/파일/카운트) | test 자동 | 시나리오 실행 후 상태 직접 조회 |
|
|
231
234
|
| 시각 (캡처-목업 대조) | UI 레이아웃/색/배치 | 승인된 목업 | test 자동 (+ 미세는 사람) | 실제 화면 캡처 → 목업과 대조, 어긋남 목록 |
|
|
232
235
|
| 회귀 시나리오 | 기존 기능 영향 | 이전과 동일 결과 | test 자동 | 직전 동작하던 시나리오 재실행 |
|
|
233
|
-
| E2E 자동화 도구 | UI 동작 자동화 (도구 있을 시) | 액션 후 관측 변화 | 도구면 test, 아니면 사람 | Playwright / Cypress / XCTest UI Test 등 — 가능하면 자동화, 안 되면 수동
|
|
236
|
+
| E2E 자동화 도구 | UI 동작 자동화 (도구 있을 시) | 액션 후 관측 변화 | 도구면 test, 아니면 사람 | Playwright / Cypress / XCTest UI Test 등 — 가능하면 자동화, 안 되면 수동 검수. **화면·입력 점유 여부를 먼저 확인** (아래) |
|
|
237
|
+
|
|
238
|
+
> **점유 스위트의 `[AUTO]` 조건** — UI를 실제 조작하는 자동화(XCUITest·headed 브라우저 E2E 등)는 실행 중 사용자의 화면·마우스·키보드를 점유한다. 이런 방식을 `[AUTO]`로 두려면 `TEST-GUIDE.md` *테스트 실행 환경* 절에 **격리 실행 경로**(창 숨김·헤드리스 플래그 / 컨테이너·가상 디스플레이 / VM / CI 러너)가 있어야 한다. 없으면 `[USER]`로 두거나 *사용자 승인 후 실행*을 시나리오에 명시한다 — 그냥 `[AUTO]`로 두면 격리 세션이 실행하지 못하고 *실행 보류*로 돌려보내 왕복이 생긴다 (stash FRICTION 2026-07-25 · recordion FRICTION 2026-08-05 — 자동 게이트가 사용자 작업을 중단시킨 마찰).
|
|
234
239
|
|
|
235
240
|
#### UX/UI 영역 분리 + 검증 방식 매트릭스 (UX/UI 구현 task 한정)
|
|
236
241
|
|
|
237
242
|
| 영역 | 분류 | 기준 |
|
|
238
243
|
|------|------|------|
|
|
239
|
-
| 동작 (클릭/호버/드래그/입력 → 결과) | 도구 있으면 `[AUTO]` E2E, 없으면 `[USER]` 체크리스트 | 액션 후 관측되는 변화 |
|
|
240
|
-
| 시각 *객관* (레이아웃/요소 유무/색/배치 깨짐) | `[AUTO]` 캡처-목업 대조 | 승인된 목업 (격리 세션이 화면 캡처 → 대조 → 어긋남 목록) |
|
|
244
|
+
| 동작 (클릭/호버/드래그/입력 → 결과) | 도구 있고 *점유하지 않게 돌릴 경로*가 있으면 `[AUTO]` E2E, 없으면 `[USER]` 체크리스트 | 액션 후 관측되는 변화 |
|
|
245
|
+
| 시각 *객관* (레이아웃/요소 유무/색/배치 깨짐) | TEST-GUIDE에 캡처 실행 경로 **있으면** `[AUTO]` 캡처-목업 대조 (원칙), **없으면** `[USER]` 폴백 | 승인된 목업 (격리 세션이 화면 캡처 → 대조 → 어긋남 목록) |
|
|
241
246
|
| 시각 *미세 취향* (2px·색조·호버 강도·느낌) | `[USER]` 체크리스트 + 목업 참조 | 사용자 최종 사인 (증거 캡처 첨부) |
|
|
242
247
|
|
|
243
248
|
#### 시나리오 형식 — [명령/입력] + [구체적 기대값] 한 쌍 강제
|
|
@@ -277,6 +282,8 @@ Test Plan = *본 task에서 구현한 요구사항이 정상 동작하는지*
|
|
|
277
282
|
- **grep/Read-only 존재 확인 시나리오 = 보조용, PASS 대체 영구 금지** (stash FRICTION_LOG 2026-06-01 반영) — 구현 코드의 존재 여부를 grep/Read로 재확인하는 시나리오는 *동어반복*. PASS 카운트에서 제외, 실동작 시나리오의 *보조*로만 사용. 단독 검증 가치 X — grep으로 실동작 검증을 *대체*할 수 없다(task-test 룰 10과 동일 강도).
|
|
278
283
|
- **요구사항당 end-to-end 1개 이상 강제** — Requirements 각 항목이 *사용자 관점에서 실제 작동하는지* 검증하는 end-to-end 실동작 시나리오 최소 1개 보장. 산출물 실행 → 결과 확인 형태.
|
|
279
284
|
- **무거운 검증 회피 영구 금지** — 부담(빌드 수 분+ / 외부 의존 / 환경 설정) 이유로 실동작 시나리오를 grep 동어반복으로 대체 X. 최소 1회는 실제 산출물로 확인. 부담은 *fix 사이클 1~2회 예상* 같은 사전 예고로 처리 (생략 사유 X).
|
|
285
|
+
- **어서션 정면성** — 각 시나리오의 PASS 기준이 *요구사항 자체를 관측*하는지 확인한다. "벗어날 수 없다"는 요구사항이면 실제로 벗어나 보는 것이 정면이고, 버튼 `disabled` 확인 같은 *우회 지표*는 통로가 열려 있어도 통과하므로 PASS 기준이 될 수 없다 (recordion FRICTION 2026-08-05 — 우회 지표로 스펙 113개가 전부 통과한 채 결함이 남았다).
|
|
286
|
+
- **흐름 계층도 시나리오 대상** — 상태 함수와 *그 함수들을 순서대로 엮는 흐름*(dispatch / 흐름 함수)이 함께 생기는 task는, 함수 단위 검증만이 아니라 **흐름을 타는 시나리오를 최소 1개** 둔다. 화면·이벤트에 묶여 있다는 이유로 흐름 계층을 빼면 *함수 사이 순서*에서 나는 결함이 검증에서 통째로 빠진다 (stash FRICTION 2026-07-28 — 검수 반려 4회 누적). 이벤트 객체가 필요한 자리는 판정을 호출 가능한 메서드로 분리해 시나리오가 닿게 한다.
|
|
280
287
|
|
|
281
288
|
#### 요구사항 ↔ 시나리오 커버리지 점검 (필수 — stash FRICTION_LOG 2026-06-01 반영)
|
|
282
289
|
|
|
@@ -302,9 +309,9 @@ Test Plan 작성 완료 후 *반드시* 점검 단계 수행. *"누적/리셋
|
|
|
302
309
|
|
|
303
310
|
방식을 골랐어도, **격리 세션이 *이 프로젝트의* DB/API/E2E에 실제로 어떻게 접근하는지 모르면 그 시나리오는 실행 불가능한 허울뿐인 명세다.** 스택마다 다르다(NestJS+TypeORM이면 그 DataSource/repository, 다른 프로젝트는 또 다름). 그래서 *모르면 묻고, 알면 재사용*:
|
|
304
311
|
|
|
305
|
-
1. 필요 방식마다 `$MAIN_WT/.project/TEST-GUIDE.md`를 Read → **이 프로젝트에 실행 경로가 적혀 있나** 확인.
|
|
312
|
+
1. 필요 방식마다 `$MAIN_WT/.project/TEST-GUIDE.md`를 Read → **이 프로젝트에 실행 경로가 적혀 있나** 확인. **데이터·API·E2E뿐 아니라 *시각(앱 기동 + 화면 캡처)* 방식도 동일하게 확인 대상이다** — 목업이 있다는 사실은 실행 경로 확보가 아니다.
|
|
306
313
|
2. **있으면** → 그 경로를 시나리오의 *방식* 칸에 반영(재사용). 앱은 기존 실행 명령으로 띄움.
|
|
307
|
-
3. **없으면** → *멈추고 사용자에게 요구*: 예) *"이 요구사항은 DB 검증이 필요한데 이 프로젝트에 실행 경로가 없다. 어떻게 검증할지 알려주거나 도구를 깔아줘."* → 사용자가 경로를 주거나 결정.
|
|
314
|
+
3. **없으면** → *멈추고 사용자에게 요구*: 예) *"이 요구사항은 DB 검증이 필요한데 이 프로젝트에 실행 경로가 없다. 어떻게 검증할지 알려주거나 도구를 깔아줘."* → 사용자가 경로를 주거나 결정. **단 시각 방식은 예외** — 멈추지 않고 `[USER]` 폴백으로 두고 진행한다 (Step 4.5 §5 참조).
|
|
308
315
|
4. **확인받은 즉시 `TEST-GUIDE.md`에 기록** → 다음 task/세션부터 안 묻고 재사용. (재사용 = 기억이 아니라 *파일* — 세션/컴팩트로 사라지지 않게.)
|
|
309
316
|
|
|
310
317
|
> TEST-GUIDE는 init이 빈 골격으로 깔아둔다(`.project/TEST-GUIDE.md`). 방식별 섹션(데이터 검증 / API 호출 / UI·E2E / 시각 실행 / 기타)에 *이 프로젝트의 실제 실행 방법*을 채운다.
|
|
@@ -364,7 +371,7 @@ Test Plan 작성 완료 후 *반드시* 점검 단계 수행. *"누적/리셋
|
|
|
364
371
|
|
|
365
372
|
## 주의사항
|
|
366
373
|
|
|
367
|
-
- **본문 영역만 작성** — 헤더
|
|
374
|
+
- **본문 영역만 작성** — 헤더 6컬럼 중 *상태*만 갱신(`draft` → `planned`). 생성일/플랜/유형/규모/부모 브랜치는 `/task-init`에서 작성된 값 유지. 단 Step 4에서 *규모가 명백히 잘못 추정*된 게 드러나면 사용자 confirm 후 갱신 OK (예: medium 추정했는데 Phase 8개 나옴 → large 갱신 + 분리 검토).
|
|
368
375
|
- **Phase 선제적 일괄 작성 금지** — small task에 medium 분량 Phase 작성하는 함정 회피. 명확한 것만 작성하고 진행 중 추가.
|
|
369
376
|
- **Test Plan = 실질 동작 시나리오 (유닛 테스트 X)** — Test Plan은 *요구사항이 정상 동작하는지* 검증. 유닛 테스트는 task-dev Step 6.5에서 단일 시점 실행 (코드 정상성 영역, Test Plan과 직교).
|
|
370
377
|
- **Test Plan 자기완결적** — 격리 세션이 *task.md만 보고* 수행 가능해야. 메인의 plan/dev 컨텍스트 *"위 Phase에서 만든 X"* 같은 표현 금지. 코드/동작/명령만 명시.
|