@walwal-harness/cli 5.7.3 → 5.8.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.
@@ -0,0 +1,80 @@
1
+ ---
2
+ docmeta:
3
+ id: harness-next
4
+ title: /harness-next — 다음 에이전트로 자동 진행
5
+ type: input
6
+ createdAt: 2026-04-27T00:00:00Z
7
+ updatedAt: 2026-04-27T00:00:00Z
8
+ source:
9
+ producer: user
10
+ skillId: harness
11
+ inputs: []
12
+ tags: [harness, solo-mode, orchestration, command]
13
+ ---
14
+
15
+ # /harness-next — 다음 에이전트로 자동 진행
16
+
17
+ 현재 에이전트의 완료 상태(`progress.json`)를 읽고 파이프라인 시퀀스에 따라 **다음 에이전트로 자동 진행**합니다. Solo 모드에서 매 단계마다 사용자가 직접 bash 명령을 칠 필요 없이 자동 핸드오프합니다.
18
+
19
+ ## 실행 절차
20
+
21
+ ### Step 1: harness-next.sh 실행
22
+
23
+ ```bash
24
+ bash scripts/harness-next.sh .
25
+ ```
26
+
27
+ 스크립트가 수행하는 작업:
28
+ - `progress.json` 읽기 → `current_agent`, `agent_status`, `next_agent` 확인
29
+ - Pre-Eval Gate (lint/type/test) 실행 — Generator → Evaluator 전환 시
30
+ - Artifact prerequisite 검증
31
+ - `.harness/handoff.json` 생성 (다음 에이전트 컨텍스트)
32
+ - 에스컬레이션 체크 (3회 실패 시 → Planner)
33
+ - 마지막 에이전트면 자동 archive 실행
34
+
35
+ ### Step 2: handoff.json 읽고 다음 에이전트 호출
36
+
37
+ ```bash
38
+ cat .harness/handoff.json | jq '{from, to, sprint, prompt, model, thinking_mode, failure_context}'
39
+ ```
40
+
41
+ `to` 필드 값에 따라 자동으로 해당 스킬을 호출합니다:
42
+
43
+ | `to` 값 | 호출할 스킬 |
44
+ |---------|------------|
45
+ | `dispatcher` | `harness-dispatcher` |
46
+ | `brainstorming` | `harness-brainstorming` |
47
+ | `planner` | `harness-planner` |
48
+ | `generator-backend` | `harness-generator-backend` |
49
+ | `generator-frontend` | `harness-generator-frontend` |
50
+ | `generator-frontend-flutter` | `harness-generator-frontend-flutter` |
51
+ | `evaluator-code-quality` | `harness-evaluator-code-quality` |
52
+ | `evaluator-functional` | `harness-evaluator-functional` |
53
+ | `evaluator-functional-flutter` | `harness-evaluator-functional-flutter` |
54
+ | `evaluator-visual` | `harness-evaluator-visual` |
55
+ | `archive` | (자동 처리됨, 새 dispatch 대기) |
56
+ | `null` (blocked) | 멈춤. 사용자에게 차단 사유 안내 |
57
+
58
+ ### Step 3: 호출된 스킬이 handoff.json을 컨텍스트로 사용
59
+
60
+ `handoff.json.prompt` 에 thinking mode, sprint, 실패 컨텍스트가 포함되어 있으므로 그대로 사용합니다.
61
+
62
+ ## 사용 시점
63
+
64
+ - **자동 호출** (스킬이 알아서):
65
+ - Dispatcher, Generator-*, Evaluator-* 완료 직후 (사용자 검토 게이트 없음)
66
+ - Planner / Brainstorming은 **사용자 승인 후** 스킬이 호출
67
+ - **수동 호출** (사용자가 직접 입력):
68
+ - 흐름이 멈춰서 다시 진행시키고 싶을 때
69
+ - Eval FAIL 후 재시도를 시작할 때
70
+ - `/harness-stop` 이후 재개
71
+
72
+ ## Team 모드와의 관계
73
+
74
+ Team 모드는 Lead worker가 자체 오케스트레이션 루프를 돌리므로 `/harness-next`가 필요 없습니다. 이 명령은 **Solo 모드 전용**입니다.
75
+
76
+ ## 관련 명령
77
+
78
+ - `/harness-solo` — Solo 모드 진입/전환
79
+ - `/harness-team` — Team 모드 진입
80
+ - `/harness-stop` — 진행 중단
@@ -1,3 +1,17 @@
1
+ ---
2
+ docmeta:
3
+ id: harness-solo
4
+ title: /harness-solo — Solo Mode 시작/전환
5
+ type: input
6
+ createdAt: 2026-04-20T00:00:00Z
7
+ updatedAt: 2026-04-27T00:00:00Z
8
+ source:
9
+ producer: user
10
+ skillId: harness
11
+ inputs: []
12
+ tags: [harness, solo-mode, command]
13
+ ---
14
+
1
15
  # /harness-solo — Solo Mode 시작/전환
2
16
 
3
17
  프롬프트 기반으로 하네스 파이프라인을 순차 진행합니다.
@@ -53,8 +67,13 @@ progress.json의 `next_agent` 필드를 확인하여 다음 단계를 안내합
53
67
 
54
68
  ### Step 4: Solo 모드 진행
55
69
 
56
- 사용자가 프롬프트로 각 에이전트 스킬을 호출하여 순차 진행합니다.
57
- 각 에이전트 완료 시 harness-next.sh가 자동으로 다음 에이전트를 결정합니다.
70
+ 각 에이전트는 완료 즉시 **`/harness-next` 슬래시 명령을 자동 호출** 하여 다음 에이전트로 핸드오프합니다 (사용자가 매번 bash 명령을 칠 필요 없음).
71
+
72
+ **예외 — 사용자 승인 게이트가 있는 단계:**
73
+ - **Brainstorming**: brainstorm-spec.md 완성 후 사용자 승인 대기 → 승인 시 자동 `/harness-next`
74
+ - **Planner**: plan.md / api-contract.json 완성 후 사용자 승인 대기 → 승인 시 자동 `/harness-next`
75
+
76
+ 흐름이 멈췄거나 수동으로 다음 단계를 트리거하고 싶으면 사용자가 직접 `/harness-next` 입력 가능.
58
77
 
59
78
  feature-queue.json이 존재하는 경우:
60
79
  - 피처 완료(evaluator PASS) 시 `bash scripts/harness-queue-manager.sh pass {FEATURE_ID} .`를 호출하여 공유 상태 업데이트
@@ -269,6 +269,13 @@ LOG="$HARNESS_ROOT/.harness/progress.log"
269
269
  logev() { echo "$(date +'%Y-%m-%d %H:%M') | team-{N} | $1 | $2" >> "$LOG"; }
270
270
  ```
271
271
 
272
+ **⚠ Prefix 규칙 (필수, 위반 금지)**
273
+
274
+ - 두 번째 필드($2)는 **반드시 `team-{N}`** 으로 통일한다 (`{N}` 자리에 팀 번호).
275
+ - Worker 가 "evaluator 분간이 더 깔끔해 보인다" 는 이유로 `eval-{N}`, `gen-fe-{N}`, `worker-{N}` 등으로 임의 변경하지 말 것. Dashboard/monitor 의 team panel 필터가 prefix 단위로 매칭하며, 과거 실제로 `eval-{N}` 변형 때문에 7개 워커의 evaluator 라인이 패널에서 모두 누락된 사고가 있었다.
276
+ - Generator 와 Evaluator 의 구분은 prefix 가 아니라 **action 필드($3)** 에서 한다: `gen-*` vs `eval-*` action 으로 충분히 색상/아이콘 분리됨.
277
+ - monitor 필터는 `team-{N}` 외 변형도 매칭하도록 robust 하게 보강되었지만, 그래도 위 규칙은 단일 진실의 원천으로 유지한다.
278
+
272
279
  | ACTION | 사용 시점 | DETAIL 예시 (필수 포함 정보) |
273
280
  |--------|-----------|------------------------------|
274
281
  | `gen-start` | Gen Phase 시작 (1회) | `F-001 "사용자 회원가입 API" start — goal=POST /users, 6 AC` — **Feature 제목+목표** 포함 필수 |
@@ -337,6 +344,8 @@ LOG=\"$HARNESS_ROOT/.harness/progress.log\"
337
344
  logev() { echo \"$(date +'%Y-%m-%d %H:%M') | team-{N} | $1 | $2\" >> \"$LOG\"; }
338
345
  ```
339
346
 
347
+ **⚠ 두 번째 필드($2)는 반드시 `team-{N}` 그대로 사용.** Evaluator 라고 `eval-{N}` 으로 바꾸지 말 것 — dashboard/monitor 가 prefix 로 팀을 묶어 렌더링하므로 변형 시 패널에서 라인이 누락된다. Generator/Evaluator 구분은 action 필드($3 = `gen-*` / `eval-*`)에서 자동으로 된다.
348
+
340
349
  **로깅 시점:**
341
350
  1. 평가 시작 즉시: `logev eval-start \"{FEATURE_ID} evaluating — {AC수} ACs\"`
342
351
  2. 각 AC 검증 후: `logev eval-check \"{FEATURE_ID} AC-{N}: [PASS/FAIL] {근거 요약}\"`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walwal-harness/cli",
3
- "version": "5.7.3",
3
+ "version": "5.8.1",
4
4
  "description": "Production harness for AI agent engineering — Solo/Team mode, Planner, Generator(BE/FE), Evaluator chain (Code-Quality → Functional → Visual), optional Brainstormer. Supports React, Next.js, and Flutter FE stacks.",
5
5
  "bin": {
6
6
  "walwal-harness": "bin/init.js"
@@ -197,10 +197,22 @@ render_team_queue_summary() {
197
197
  ready=$(jq '.queue.ready | length' "$QUEUE" 2>/dev/null || echo 0)
198
198
  blocked=$(jq '.queue.blocked | length' "$QUEUE" 2>/dev/null || echo 0)
199
199
  in_prog=$(jq '.queue.in_progress | length' "$QUEUE" 2>/dev/null || echo 0)
200
- passed=$(jq '.queue.passed | length' "$QUEUE" 2>/dev/null || echo 0)
201
200
  failed=$(jq '.queue.failed | length' "$QUEUE" 2>/dev/null || echo 0)
202
- ready=${ready:-0}; blocked=${blocked:-0}; in_prog=${in_prog:-0}; passed=${passed:-0}; failed=${failed:-0}
203
- total=$((ready + blocked + in_prog + passed + failed))
201
+
202
+ # passed 는 queue.passed ∪ feature-list.json 의 self-passed 를 dedup 합집합으로 계산
203
+ # (과거 sprint 에서 PASS 되어 queue 에서 빠진 feature 도 카운트)
204
+ if [ -f "$FEATURES" ]; then
205
+ passed=$(jq -r --slurpfile q "$QUEUE" '
206
+ ($q[0].queue.passed // []) as $qp |
207
+ ([.features[] | select((.passes // []) | any(. == "evaluator-functional" or . == "evaluator-visual" or . == "evaluator-code-quality")) | .id]) as $sp |
208
+ ($qp + $sp | unique | length)
209
+ ' "$FEATURES" 2>/dev/null || echo 0)
210
+ total=$(jq '.features | length' "$FEATURES" 2>/dev/null || echo 0)
211
+ else
212
+ passed=$(jq '.queue.passed | length' "$QUEUE" 2>/dev/null || echo 0)
213
+ total=$((ready + blocked + in_prog + passed + failed))
214
+ fi
215
+ ready=${ready:-0}; blocked=${blocked:-0}; in_prog=${in_prog:-0}; passed=${passed:-0}; failed=${failed:-0}; total=${total:-0}
204
216
 
205
217
  local pct=0
206
218
  if [ "$total" -gt 0 ]; then pct=$(( passed * 100 / total )); fi
@@ -274,7 +286,11 @@ render_team_features() {
274
286
  .features[] |
275
287
  .id as $fid |
276
288
  (.name // .title // .description // "?" | if length > 18 then .[0:16] + ".." else . end) as $fname |
277
- (if ($fid | IN($passed[])) then "P"
289
+ # passed 판정: queue.passed 또는 feature.passes 에 evaluator-functional/visual/code-quality 가 있으면 PASS.
290
+ # 과거 sprint 에서 PASS 된 feature 가 새 sprint queue 재생성 시 queue.passed 에서 누락되어도
291
+ # feature-list.json 의 passes 배열은 이력으로 남아있으므로, 거기서도 검사한다.
292
+ ((.passes // []) | any(. == "evaluator-functional" or . == "evaluator-visual" or . == "evaluator-code-quality")) as $self_passed |
293
+ (if ($fid | IN($passed[])) or $self_passed then "P"
278
294
  elif $prog[$fid] then "I|\($prog[$fid].team)|\($prog[$fid].phase)"
279
295
  elif ($fid | IN($failed[])) then "F"
280
296
  elif ($fid | IN($ready[])) then "R"
@@ -137,7 +137,16 @@ render_team_section() {
137
137
  local have_logs=0
138
138
  if [ -f "$PROGRESS_LOG" ]; then
139
139
  local matched
140
- matched=$(grep -E "team-${team_num}\b|team_${team_num}\b" "$PROGRESS_LOG" 2>/dev/null | tail -"$log_lines")
140
+ # Team panel 필터: agent 필드($2)가 해당 team 번호를 포함하는 모든 prefix 매칭.
141
+ # 허용: team-N, team_N, eval-N, eval_N, gen-N, gen-fe-N, worker-N, lead-N 등
142
+ # (워커가 evaluator 분리를 위해 eval-N 으로 로깅해도 누락되지 않게 한다)
143
+ matched=$(awk -F'|' -v n="${team_num}" '
144
+ {
145
+ # $2 = agent (앞뒤 공백 trim)
146
+ a=$2; gsub(/^ +| +$/,"",a)
147
+ # agent 토큰이 [-_]N\b 로 끝나거나 -N- / _N_ 처럼 N이 토큰 경계에 포함되면 매치
148
+ if (match(a, "(^|[-_])" n "([-_]|$)")) print
149
+ }' "$PROGRESS_LOG" 2>/dev/null | tail -"$log_lines")
141
150
  if [ -n "$matched" ]; then
142
151
  have_logs=1
143
152
  local cols
@@ -69,8 +69,9 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
69
69
  - `completed_agents` 에 `"brainstormer"` 추가
70
70
  - `next_agent` → `"planner"`
71
71
  3. `.harness/progress.log` 에 요약 추가: `Brainstormer → Planner (spec: <경로>)`
72
- 4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
73
- 5. 출력: `"✓ Brainstormer 완료. bash scripts/harness-next.sh 실행하여 Planner 단계로 진행."`
72
+ 4. 출력: `"✓ Brainstormer 완료. brainstorm-spec.md 검토 후 승인 신호를 주세요. 승인 시 /harness-next 자동 진행 (Planner)."`
73
+ 5. **사용자 승인 게이트**: 사용자의 명시적 승인 ("이 디자인 승인한다", "ok", "다음", "Planner 가자" 등) 을 기다린 후, **`/harness-next` 슬래시 명령을 호출하여 Planner 로 자동 핸드오프**.
74
+ 6. 사용자가 피드백/수정 요청을 하면 brainstorm-spec.md 를 갱신하고 다시 승인 요청. 승인 없이는 `/harness-next` 호출 금지 (HARD-GATE 준수).
74
75
 
75
76
  ### On Fail / Abort
76
77
  사용자가 중간에 "중단" / "취소" / "abort" 를 요청하면:
@@ -55,8 +55,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
55
55
  ```
56
56
  아카이빙 후 `dispatch.id` 는 `null` 로 리셋되므로, 다음 dispatcher 실행 시 새 D-NNN 이 할당된다.
57
57
  2. `.harness/progress.log`에 요약 한 줄 추가
58
- 3. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
59
- 4. 출력: `"✓ Dispatcher 완료. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
58
+ 3. 출력: `"✓ Dispatcher 완료. /harness-next 자동 진행."`
59
+ 4. **즉시 `/harness-next` 슬래시 명령을 호출하여 다음 에이전트로 자동 핸드오프** (Solo 모드. Team 모드는 Lead가 별도 오케스트레이션). Brainstorming/Planner 단계가 아니면 사용자 승인 게이트 없음.
60
60
 
61
61
  ## Auto-Routing (UserPromptSubmit Hook)
62
62
 
@@ -41,8 +41,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
41
41
  - `failure` 필드 초기화
42
42
  2. `feature-list.json`의 통과 feature `passes`에 `"evaluator-code-quality"` 추가
43
43
  3. `.harness/progress.log`에 PASS 요약 추가
44
- 4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
45
- 5. 출력: `"✓ Evaluator-Code-Quality PASS. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
44
+ 4. 출력: `"✓ Evaluator-Code-Quality PASS. /harness-next 자동 진행."`
45
+ 5. **즉시 `/harness-next` 슬래시 명령을 호출하여 다음 에이전트로 자동 핸드오프** (Solo 모드. Team 모드는 Lead가 별도 오케스트레이션).
46
46
 
47
47
  ### On Fail
48
48
  1. progress.json 업데이트:
@@ -55,8 +55,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
55
55
  - `sprint.retry_count` 증가
56
56
  2. `sprint.retry_count >= 10`이면 `agent_status` → `"blocked"`, 사용자 개입 요청
57
57
  3. `.harness/progress.log`에 FAIL 요약 추가
58
- 4. **STOP.**
59
- 5. 출력: `"✖ Evaluator-Code-Quality FAIL. bash scripts/harness-next.sh 실행하여 재작업 대상 확인."`
58
+ 4. 출력: `"✖ Evaluator-Code-Quality FAIL. /harness-next 자동 진행 (재작업 대상으로 라우팅)."`
59
+ 5. **즉시 `/harness-next` 슬래시 명령을 호출하여 `failure.retry_target` 으로 자동 핸드오프** (Solo 모드).
60
60
 
61
61
  ## Critical Mindset
62
62
 
@@ -43,8 +43,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
43
43
  - `failure` 필드 초기화
44
44
  3. `feature-list.json`의 통과 feature `passes`에 `"evaluator-functional"` 추가
45
45
  4. `.harness/progress.log`에 PASS 요약 추가
46
- 5. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
47
- 6. 출력: `"✓ Evaluator-Functional PASS. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
46
+ 5. 출력: `"✓ Evaluator-Functional PASS. /harness-next 자동 진행."`
47
+ 6. **즉시 `/harness-next` 슬래시 명령을 호출하여 다음 에이전트로 자동 핸드오프** (Solo 모드. Team 모드는 Lead가 별도 오케스트레이션).
48
48
 
49
49
  ### On Fail
50
50
  1. **Screenshot Cleanup** — PASS 와 동일하게 스크린샷 파일 삭제 (FAIL 시에도 정리 필수).
@@ -58,8 +58,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
58
58
  - `sprint.retry_count` 증가
59
59
  3. `sprint.retry_count >= 10`이면 `agent_status` → `"blocked"`, 사용자 개입 요청
60
60
  4. `.harness/progress.log`에 FAIL 요약 추가
61
- 5. **STOP.**
62
- 6. 출력: `"✖ Evaluator-Functional FAIL. bash scripts/harness-next.sh 실행하여 재작업 대상 확인."`
61
+ 5. 출력: `"✖ Evaluator-Functional FAIL. /harness-next 자동 진행 (재작업 대상으로 라우팅)."`
62
+ 6. **즉시 `/harness-next` 슬래시 명령을 호출하여 `failure.retry_target` 으로 자동 핸드오프** (Solo 모드).
63
63
 
64
64
  ## Critical Mindset
65
65
 
@@ -43,8 +43,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
43
43
  - `failure` 필드 초기화
44
44
  3. `feature-list.json`의 통과 feature `passes`에 `"evaluator-visual"` 추가
45
45
  4. `.harness/progress.log`에 PASS 요약 추가
46
- 5. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
47
- 6. 출력: `"✓ Evaluator-Visual PASS. bash scripts/harness-next.sh 실행하여 아카이브 진행."`
46
+ 5. 출력: `"✓ Evaluator-Visual PASS. /harness-next 자동 진행 (아카이브)."`
47
+ 6. **즉시 `/harness-next` 슬래시 명령을 호출하여 아카이브 단계로 자동 핸드오프** (Solo 모드. Team 모드는 Lead가 별도 오케스트레이션).
48
48
 
49
49
  ### On Fail
50
50
  1. **Screenshot Cleanup** — PASS 와 동일하게 스크린샷 파일 삭제 (FAIL 시에도 정리 필수).
@@ -58,8 +58,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
58
58
  - `sprint.retry_count` 증가
59
59
  3. `sprint.retry_count >= 10`이면 `agent_status` → `"blocked"`, 사용자 개입 요청
60
60
  4. `.harness/progress.log`에 FAIL 요약 추가
61
- 5. **STOP.**
62
- 6. 출력: `"✖ Evaluator-Visual FAIL. bash scripts/harness-next.sh 실행하여 재작업 대상 확인."`
61
+ 5. 출력: `"✖ Evaluator-Visual FAIL. /harness-next 자동 진행 (재작업 대상으로 라우팅)."`
62
+ 6. **즉시 `/harness-next` 슬래시 명령을 호출하여 `failure.retry_target` 으로 자동 핸드오프** (Solo 모드).
63
63
 
64
64
  ## FE Playwright Mandatory Rule (v5.4)
65
65
 
@@ -39,8 +39,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
39
39
  - `failure` 필드 초기화 (retry 성공 시)
40
40
  2. `feature-list.json` 의 해당 feature `passes` 에 `"generator-backend"` 추가
41
41
  3. `.harness/progress.log` 에 요약 추가
42
- 4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
43
- 5. 출력: `"✓ Generator-Backend 완료. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
42
+ 4. 출력: `"✓ Generator-Backend 완료. /harness-next 자동 진행."`
43
+ 5. **즉시 `/harness-next` 슬래시 명령을 호출하여 다음 에이전트로 자동 핸드오프** (Solo 모드. Team 모드는 Lead가 별도 오케스트레이션).
44
44
 
45
45
  ## Startup (Adaptive Loading)
46
46
 
@@ -39,8 +39,8 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
39
39
  - `failure` 필드 초기화 (retry 성공 시)
40
40
  2. `feature-list.json` 의 해당 feature `passes` 에 `"generator-frontend"` 추가
41
41
  3. `.harness/progress.log` 에 요약 추가
42
- 4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
43
- 5. 출력: `"✓ Generator-Frontend 완료. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
42
+ 4. 출력: `"✓ Generator-Frontend 완료. /harness-next 자동 진행."`
43
+ 5. **즉시 `/harness-next` 슬래시 명령을 호출하여 다음 에이전트로 자동 핸드오프** (Solo 모드. Team 모드는 Lead가 별도 오케스트레이션).
44
44
 
45
45
  ## Startup (Adaptive Loading)
46
46
 
@@ -36,8 +36,9 @@ jq '.agent_status = "completed" | .completed_agents += ["planner"]' .harness/p
36
36
  - `completed_agents`에 `"planner"` 추가
37
37
  - `next_agent` → 파이프라인에 따라 결정 (FULLSTACK/BE-ONLY: `"generator-backend"`, FE-ONLY: `"generator-frontend"`)
38
38
  2. `.harness/progress.log`에 요약 추가
39
- 3. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
40
- 4. 출력: `"✓ Planner 완료. bash scripts/harness-next.sh 실행하여 다음 단계 확인."`
39
+ 3. 출력: `"✓ Planner 완료. plan.md / api-contract.json 검토 후 승인 신호를 주세요. 승인 시 /harness-next 자동 진행."`
40
+ 4. **사용자 승인 게이트**: 사용자의 명시적 승인 ("승인", "ok", "다음", "진행", "go" 등) 을 기다린 후, **`/harness-next` 슬래시 명령을 호출하여 다음 에이전트로 자동 핸드오프**.
41
+ 5. 사용자가 피드백/수정 요청을 하면 plan.md / feature-list.json / api-contract.json 을 갱신하고 다시 승인 요청. 승인 없이는 `/harness-next` 호출 금지.
41
42
 
42
43
  ## Startup
43
44