@walwal-harness/cli 6.1.3 → 6.1.5

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +43 -74
  3. package/assets/launchd/com.walwal.harness-wake.plist.template +32 -0
  4. package/assets/templates/CONVENTIONS.md +12 -0
  5. package/assets/templates/HARNESS.md +216 -403
  6. package/assets/templates/config.json +27 -29
  7. package/assets/templates/memory.md +16 -2
  8. package/assets/templates/progress.json.template +6 -5
  9. package/bin/init.js +179 -90
  10. package/conventions/README.md +92 -0
  11. package/conventions/conductor.md +24 -0
  12. package/conventions/coo-developer.md +24 -0
  13. package/conventions/cqo.md +24 -0
  14. package/conventions/cto.md +24 -0
  15. package/conventions/dispatcher.md +24 -0
  16. package/conventions/documentationer.md +24 -0
  17. package/conventions/evaluator-architecture.md +24 -0
  18. package/conventions/evaluator-code-quality.md +24 -0
  19. package/conventions/evaluator-functional.md +24 -0
  20. package/conventions/evaluator-security.md +24 -0
  21. package/conventions/evaluator-visual.md +24 -0
  22. package/conventions/generator-backend.md +24 -0
  23. package/conventions/generator-designer.md +24 -0
  24. package/conventions/generator-devops.md +24 -0
  25. package/conventions/generator-frontend.md +24 -0
  26. package/conventions/meeting-manager.md +24 -0
  27. package/conventions/planner.md +24 -0
  28. package/conventions/service-ops.md +24 -0
  29. package/conventions/shared.md +40 -0
  30. package/gotchas/conductor.md +16 -0
  31. package/gotchas/dispatcher.md +16 -0
  32. package/gotchas/meeting-manager.md +8 -0
  33. package/gotchas/service-ops.md +8 -0
  34. package/package.json +5 -4
  35. package/scripts/conductor-tick.sh +61 -53
  36. package/scripts/harness-archive.sh +7 -5
  37. package/scripts/harness-dashboard-up.sh +11 -3
  38. package/scripts/harness-hourly-review.sh +303 -0
  39. package/scripts/harness-meeting-doc.sh +55 -16
  40. package/scripts/harness-next.sh +1 -1
  41. package/scripts/harness-queue-manager.sh +12 -5
  42. package/scripts/harness-service-ops-monitor.sh +228 -0
  43. package/scripts/harness-session-start.sh +60 -31
  44. package/scripts/harness-statusline.sh +8 -12
  45. package/scripts/harness-stop.sh +85 -0
  46. package/scripts/harness-user-prompt-submit.sh +11 -29
  47. package/scripts/harness-wake-install.sh +179 -0
  48. package/scripts/harness-wake.sh +258 -0
  49. package/scripts/harness-worker-dispatch.sh +157 -0
  50. package/scripts/lib/harness-progress-migrate.sh +6 -1
  51. package/scripts/lib/harness-render-progress.sh +3 -3
  52. package/skills/brainstorming/SKILL.md +2 -2
  53. package/skills/conductor/SKILL.md +67 -55
  54. package/skills/cqo/SKILL.md +1 -0
  55. package/skills/cto/SKILL.md +1 -0
  56. package/skills/dispatcher/SKILL.md +33 -14
  57. package/skills/evaluator-code-quality/SKILL.md +4 -4
  58. package/skills/evaluator-functional/SKILL.md +6 -6
  59. package/skills/evaluator-visual/SKILL.md +4 -4
  60. package/skills/generator-backend/SKILL.md +4 -4
  61. package/skills/generator-frontend/SKILL.md +5 -5
  62. package/skills/meeting-manager/SKILL.md +82 -12
  63. package/skills/planner/SKILL.md +3 -3
  64. package/skills/service-ops/SKILL.md +25 -0
  65. package/commands/harness-solo.md +0 -103
  66. package/commands/harness-stop.md +0 -53
  67. package/commands/harness-team.md +0 -530
  68. package/scripts/harness-dashboard.sh +0 -509
  69. package/scripts/harness-goal-init.sh +0 -72
  70. package/scripts/harness-goal-show.sh +0 -37
  71. package/scripts/harness-gotcha-memory.sh +0 -348
  72. package/scripts/harness-monitor.sh +0 -398
  73. package/scripts/harness-prompt-history.sh +0 -164
  74. package/scripts/harness-tmux.sh +0 -372
@@ -1,530 +0,0 @@
1
- ---
2
- docmeta:
3
- id: harness-team
4
- title: /harness-team — Team Mode 사용자 Override (v6.0+)
5
- type: input
6
- createdAt: 2026-04-20T00:00:00Z
7
- updatedAt: 2026-05-07T00:00:00Z
8
- source:
9
- producer: user
10
- skillId: harness
11
- inputs:
12
- - documentId: skill-conductor
13
- uri: ../skills/conductor/SKILL.md
14
- relation: output-from
15
- sections:
16
- - sourceRange: { startLine: 115, endLine: 145 } # §7.5 모드 결정 + user_override
17
- targetRange: { startLine: 17, endLine: 22 }
18
- - documentId: config-template
19
- uri: ../assets/templates/config.json
20
- relation: output-from
21
- sections:
22
- - sourceRange: { startLine: 345, endLine: 372 } # mode_selection.rules.force_team_when
23
- targetRange: { startLine: 17, endLine: 22 }
24
- tags: [harness, team-mode, tmux, command, override, v6]
25
- ---
26
-
27
- # /harness-team — Team Mode 사용자 Override (v6.0+)
28
-
29
- > v6.0 부터 모드 결정은 **Conductor 가 자동**으로 합니다 (config.json `mode_selection.rules.force_team_when`: ready≥3 + features≥6 + critical_path_depth≤2). 본 명령은 Conductor 의 자동 결정을 사용자가 강제로 덮어쓰는 **override** 입니다.
30
- >
31
- > **효과**: `progress.json.mode = "team"` 강제 + `mode_decision.user_override = "team"` 기록 + tmux 세션 부팅. 현재 sprint 끝까지 유지. 다음 sprint 진입 시 Conductor 가 재자동결정. **Auto 복귀**: 사용자 발화 "auto 로 돌려" 또는 "Conductor 결정으로".
32
-
33
- Planner가 완료한 feature-list.json의 피처들을 최대 3개 팀이 병렬로 Gen→Eval 사이클을 수행합니다.
34
-
35
- ## 프로세스 설계 원칙
36
-
37
- 1. **Worker = 1 Feature Only**: 각 Worker는 단일 피처만 처리하고 반환. 자동 다음 피처 획득하지 않음.
38
- 2. **Lead = Orchestration Loop**: Lead가 Worker 완료 알림을 받고, merge → unblock 확인 → 새 Worker 생성을 반복.
39
- 3. **Background Agent**: Worker를 `run_in_background: true`로 생성하여 Lead가 개별 완료에 즉시 반응.
40
- 4. **Merge 후 재투입**: Worker PASS → Lead가 worktree merge → queue pass (unblock) → 새 Worker 생성.
41
-
42
- ## 실행 절차
43
-
44
- ### Step 0: 선행 조건 확인
45
-
46
- ```bash
47
- [ -f .harness/actions/feature-list.json ] && [ -f .harness/actions/api-contract.json ] && echo "READY" || echo "NOT_READY"
48
- ```
49
-
50
- - **NOT_READY** → "Planner가 먼저 완료되어야 합니다." 안내 후 중단.
51
- - **READY** → Step 1로 진행.
52
-
53
- ### Step 1: 모드 전환 + Queue 초기화
54
-
55
- ```bash
56
- # progress.json에 mode=team 설정
57
- jq '.mode = "team" | .mode_decision.user_override = "team" | .team_state.active_teams = 3 | .team_state.paused_at = null' .harness/progress.json > /tmp/progress_tmp.json && mv /tmp/progress_tmp.json .harness/progress.json
58
-
59
- # Queue 초기화 또는 복구
60
- if [ ! -f .harness/actions/feature-queue.json ]; then
61
- bash scripts/harness-queue-manager.sh init .
62
- else
63
- bash scripts/harness-queue-manager.sh recover .
64
- fi
65
-
66
- # Queue 상태 확인
67
- bash scripts/harness-queue-manager.sh status .
68
- ```
69
-
70
- ### Step 2: tmux Studio 레이아웃 구축
71
-
72
- ```bash
73
- bash scripts/harness-tmux.sh --team --force-tmux
74
- ```
75
-
76
- **`--force-tmux` 필수**: iTerm2 감지 경로는 백그라운드에 iTerm2가 떠 있기만 해도 활성화되어 AppleScript 실패 시 팀 레이아웃이 조용히 사라짐. Team Mode는 항상 tmux로 강제하여 재현 가능한 레이아웃을 보장.
77
-
78
- ### Step 2.5: Worker Pre-flight Bundle 빌드 (v5.6.6+)
79
-
80
- Worker 는 plain Agent 로 실행되어 SKILL.md Startup 체크리스트를 자동 주입받지 못한다. Lead 가 Worker spawn 직전에 **역할별 바인딩 문서를 프롬프트에 직접 주입**한다. 이렇게 하면 "Worker 가 읽어야 함" → "이미 읽은 상태로 시작" 으로 전환되어 스킵이 구조적으로 불가능해진다.
81
-
82
- ```bash
83
- # Generator-{be|fe} / Evaluator-{functional|visual|code-quality} 별 번들 빌드
84
- build_preflight_bundle() {
85
- local role="$1" # generator-frontend | generator-backend | evaluator-functional | ...
86
- local hroot="$2" # HARNESS_ROOT (worktree 가 아닌 원본 루트)
87
- {
88
- echo "===== ROOT CONVENTIONS.md ====="
89
- [ -f "$hroot/CONVENTIONS.md" ] && cat "$hroot/CONVENTIONS.md" || echo "(none)"
90
- echo
91
- echo "===== AGENTS.md ====="
92
- [ -f "$hroot/AGENTS.md" ] && cat "$hroot/AGENTS.md" || echo "(none)"
93
- echo
94
- echo "===== .harness/conventions/shared.md ====="
95
- [ -f "$hroot/.harness/conventions/shared.md" ] && cat "$hroot/.harness/conventions/shared.md" || echo "(empty)"
96
- echo
97
- echo "===== .harness/conventions/$role.md ====="
98
- [ -f "$hroot/.harness/conventions/$role.md" ] && cat "$hroot/.harness/conventions/$role.md" || echo "(empty)"
99
- echo
100
- echo "===== .harness/gotchas/$role.md ====="
101
- [ -f "$hroot/.harness/gotchas/$role.md" ] && cat "$hroot/.harness/gotchas/$role.md" || echo "(empty)"
102
- echo
103
- echo "===== .harness/memory.md ====="
104
- [ -f "$hroot/.harness/memory.md" ] && cat "$hroot/.harness/memory.md" || echo "(empty)"
105
- }
106
- }
107
- ```
108
-
109
- Worker/내부 Evaluator Agent 프롬프트 상단에 이 번들 출력을 `## Binding Rules (pre-loaded)` 섹션으로 삽입한다. Worker 는 이를 **추가 조회 없이 이미 적용되는 규범**으로 취급한다.
110
-
111
- ### Step 3: 초기 Worker 생성 (Auto-Dispatch)
112
-
113
- **v5.6.4+**: 개별 dequeue 대신 **`auto-dispatch`** 한 번으로 모든 idle team 에 ready feature 를 원자적으로 배정합니다. 의존성 없는 작업은 병렬로 즉시 시작됩니다.
114
-
115
- ```bash
116
- # 모든 idle team ↔ ready feature 쌍을 한 번에 배정
117
- bash scripts/harness-queue-manager.sh auto-dispatch .
118
- # → [{"team":1,"feature":"F-001"},{"team":2,"feature":"F-002"},{"team":3,"feature":"F-003"}]
119
- ```
120
-
121
- 출력(JSON 배열)을 파싱해 각 `{team, feature}` 쌍마다 **background Agent** 를 생성합니다.
122
-
123
- > **Fallback**: 단일 팀만 배정하려면 `dequeue <team_id>` 도 계속 사용 가능.
124
-
125
- dequeue 성공한 피처마다 **background Agent**를 생성합니다:
126
-
127
- ```
128
- Agent({
129
- description: "Team-{N}: {FEATURE_ID}",
130
- isolation: "worktree",
131
- run_in_background: true,
132
- prompt: "<아래 Team Worker 프롬프트>"
133
- })
134
- ```
135
-
136
- **중요: `run_in_background: true`로 생성**하면 Lead가 블록되지 않고, 각 Worker 완료 시 알림을 받습니다.
137
-
138
- 초기 생성 후 **Step 4 (Orchestration Loop)**로 진입합니다.
139
-
140
- ### Step 4: Orchestration Loop (Lead 핵심 루프)
141
-
142
- **이 루프가 Team Mode의 핵심입니다. 모든 Sprint가 완료될 때까지 반복합니다.**
143
-
144
- ```
145
- ORCHESTRATION LOOP:
146
-
147
- Background Agent 완료 알림을 받으면:
148
-
149
- 1. Worker 결과 분석 (반환 메시지 첫 줄 태그로 분기):
150
- - `PASS` → Step 4a (Merge + Unblock)
151
- - `FAIL` (재시도 가능) → Step 4b (Retry)
152
- - `RATE_LIMIT` → Step 4c (Rate-Limit Hold, 10m probe)
153
- - `ESCALATED` → 사용자에게 알림, 해당 팀 유휴
154
-
155
- 2. **Auto-Dispatch (필수)** — worker 완료 직후 idle 이 된 팀뿐 아니라
156
- 모든 idle team 에 ready feature 를 즉시 재배정:
157
-
158
- bash scripts/harness-queue-manager.sh auto-dispatch .
159
-
160
- 반환된 모든 (team, feature) 쌍에 대해 즉시 background Agent 생성.
161
- 한 작업의 merge 지연이 다른 idle team 을 놀게 두지 않는다.
162
-
163
- 3. Queue 상태 확인 (로그용):
164
- bash scripts/harness-queue-manager.sh idle-slots .
165
- bash scripts/harness-queue-manager.sh status .
166
-
167
- 4. auto-dispatch 가 pairs=[] (= ready 도 0, idle 도 0 혹은 idle 만 있고 ready 가 0) 이면:
168
- → ready=0 AND in_progress>0 → 다른 worker 완료 대기. LOOP 계속
169
- → ready=0 AND in_progress=0 → Sprint 전환 시도:
170
- bash scripts/harness-queue-manager.sh next-sprint .
171
- - "Advancing" → auto-dispatch 다시 실행 (Step 2로 복귀)
172
- - "ALL SPRINTS COMPLETE" → 최종 보고. LOOP 종료.
173
- - "Cannot advance" → 실패 피처 사용자 개입 요청. LOOP 종료.
174
- ```
175
-
176
- **핵심 원칙**: worker 완료 알림 → **즉시 auto-dispatch** → 반환된 모든 쌍에 대해 병렬 spawn. 팀 간 의존성이 없으면 idle 시간은 "Agent 생성에 걸리는 수초" 로 수렴한다.
177
-
178
- #### Step 4a: Merge + Unblock (PASS 처리)
179
-
180
- **⚠ HARD GATE — Runtime Bug 검출 시 PASS 처리 금지**
181
-
182
- Worker 가 PASS 로 반환했더라도, 보고서에 다음 신호가 하나라도 포함되어 있으면 **PASS 처리하지 말고 즉시 FAIL 로 전환**한다. carry-over / 다음 sprint 미루기 절대 금지 — 견고한 기반 위에서만 다음 sprint 로 진행한다.
183
-
184
- 검출 시그널 (worker 반환 텍스트 검색):
185
- - "runtime bug", "런타임 버그", "런타임 에러", "runtime error"
186
- - "RSC", "Client Component" 경계 위반 (use client 누락 등)
187
- - "not-found", "error.tsx", "loading.tsx" 누락/오류
188
- - "typed-routes", "TypeScript route" 미스매치
189
- - "console error", "uncaught", "Hydration error", "hydration mismatch"
190
- - 그 외 worker 가 자신의 결과를 "carry-over", "다음 sprint 에서 처리", "추후 수정", "follow-up" 으로 표현하는 모든 케이스
191
-
192
- 위 신호 검출 시 처리:
193
- ```bash
194
- # 1) PASS 가 아니라 FAIL 로 큐 업데이트
195
- bash scripts/harness-queue-manager.sh fail {FEATURE_ID} .
196
-
197
- # 2) 즉시 같은 feature 를 재투입 (worktree 재사용 또는 새 worker)
198
- # Agent 프롬프트에 worker 가 보고한 버그 목록을 명시하고
199
- # "이 sprint 안에서 fix 완료될 때까지 done 처리 금지" 강제
200
- ```
201
-
202
- 3) Sprint 전환 게이트: `next-sprint` 호출 전에 carry-over / known-bug 가 0 인지 반드시 확인. 1 건이라도 남아있으면 sprint advance 금지 — 같은 sprint 안에서 fix sprint 를 한 사이클 더 돈다.
203
-
204
- 이 룰을 위반한 사례: F-209 평가에서 "monitoring page RSC/CC, not-found.tsx, sidebar-nav typed-routes" 3 개 런타임 버그를 인지한 채 PASS 처리하고 Sprint 4 carry-over 로 미룬 적이 있다. 사용자 명시: "오류가 있는 것을 인지한 채로 스프린트를 넘어가는 행위는 절대 용납할 수 없다."
205
-
206
- ---
207
-
208
- 위 hard gate 를 통과한(=깨끗한 PASS) 경우에만:
209
-
210
- 1. **Worktree branch 확인**: Agent 반환 결과에서 worktree path와 branch 확인
211
- 2. **Main에 merge**:
212
- ```bash
213
- git merge {BRANCH_NAME} --no-edit
214
- ```
215
- - 충돌 시: 자동 해결 시도 → 실패 시 사용자 개입 요청
216
- 3. **동적 Gotcha/Convention 등록** (merge 직후 필수):
217
- ```bash
218
- # worker 가 작성한 evaluation-*.md / gen-report-*.md 의
219
- # gotcha_candidates / convention_candidates 블록을 모두 dedup append
220
- bash scripts/harness-gotcha-register.sh . --scan-all
221
- ```
222
- 다음 worker spawn 전에 갱신된 gotchas/conventions 가 file system 에 반영되어야 함.
223
- 실수가 sprint 중에 등록되지 않으면 다음 worker 가 같은 실수 반복.
224
-
225
- 4. **Queue 업데이트** (unblock 포함):
226
- ```bash
227
- bash scripts/harness-queue-manager.sh pass {FEATURE_ID} .
228
- ```
229
- → 의존 피처가 자동으로 blocked → ready로 전이
230
- 4. **진행 로그**:
231
- ```bash
232
- echo "$(date +'%Y-%m-%d %H:%M') | lead | pass | {FEATURE_ID} merged + unblocked deps" >> .harness/progress.log
233
- ```
234
-
235
- #### Step 4c: Rate-Limit Hold (토큰 한도 대응 · v5.6.7+)
236
-
237
- Worker 반환 첫 줄이 `RATE_LIMIT` 으로 시작하면 Lead 는 **에러 아닌 hold 모드**로 전환한다. 나머지 Worker 들은 자연 완료까지 계속 실행되고, 그 결과도 RATE_LIMIT 이면 합쳐서 hold 상태에 누적된다.
238
-
239
- ```bash
240
- # 1) Checkpoint 기록 (current in_progress + ready 스냅샷 저장)
241
- bash "$HARNESS_ROOT/scripts/harness-queue-manager.sh" hold rate_limit 600 .
242
-
243
- # 2) 로그 + tmux pane 타이틀 변경
244
- echo "$(date +'%Y-%m-%d %H:%M') | lead | hold | rate-limit detected, pausing 10m" >> .harness/progress.log
245
- tmux rename-window "⏸ HOLD (resume ~$(date -v+10M +%H:%M 2>/dev/null || date -d '+10 min' +%H:%M))" 2>/dev/null || true
246
-
247
- # 3) 실패한 feature 는 requeue (WIP worktree 는 유지 — merge 없이 재사용)
248
- bash "$HARNESS_ROOT/scripts/harness-queue-manager.sh" requeue {FEATURE_ID} .
249
- ```
250
-
251
- 4) **ScheduleWakeup 으로 10분 뒤 재진입 스케줄**:
252
- ```
253
- ScheduleWakeup({
254
- delaySeconds: 600,
255
- prompt: "/harness-team resume",
256
- reason: "rate-limit hold — 10m probe"
257
- })
258
- ```
259
-
260
- 5) Lead LOOP return (중단 아님 — wake-up 이 재진입 트리거).
261
-
262
- **Wake-up 재진입 시 Lead 동작** (`/harness-team resume` 처리):
263
-
264
- ```bash
265
- # Probe: claude CLI 가 실제로 응답하는지 최소 호출로 확인
266
- bash "$HARNESS_ROOT/scripts/harness-queue-manager.sh" resume-probe .
267
- # 종료 코드: 0=clear, 1=still held, 2=escalated(>12h)
268
- ```
269
-
270
- - **0 (clear)** → 체크포인트 삭제됨. 즉시 `auto-dispatch` 실행 → Step 4 LOOP 복귀.
271
- - **1 (still held)** → 다시 `ScheduleWakeup(600, "/harness-team resume", "rate-limit still held — cycle N")` 스케줄. hold_count 증가.
272
- - **2 (escalated)** → 72 사이클(12시간) 초과. 사용자 개입 알림 후 LOOP 종료. 체크포인트 파일 (`.harness/actions/team-checkpoint.json`) 에 전체 상태가 남아있으므로 사용자가 수동 복구 가능.
273
-
274
- **핵심 원칙**: 토큰 리밋은 "실패"가 아닌 "일시 정지". 진행 중이던 worktree/queue 상태는 그대로 보존되고, 10분 간격 probe 로 해제 즉시 이어서 진행한다. Session 을 닫아도 이어지길 원한다면 `ScheduleWakeup` 대신 `schedule` 스킬(CronCreate) 로 cron-backed 재시도 설정 가능.
275
-
276
- #### Step 4b: Retry (FAIL 처리)
277
-
278
- Worker가 FAIL (재시도 가능)로 반환되면:
279
-
280
- 1. 시도 횟수 확인 (최대 5회)
281
- 2. 5회 미만:
282
- ```bash
283
- bash scripts/harness-queue-manager.sh requeue {FEATURE_ID} .
284
- bash scripts/harness-queue-manager.sh dequeue {TEAM_NUMBER} .
285
- ```
286
- → 새 background Agent Worker 생성 (이전 Eval feedback 포함)
287
- 3. 5회 도달:
288
- ```bash
289
- bash scripts/harness-queue-manager.sh fail {FEATURE_ID} .
290
- echo "$(date +'%Y-%m-%d %H:%M') | lead | escalate | {FEATURE_ID} ESCALATED after 5 attempts" >> .harness/progress.log
291
- ```
292
- → 사용자 개입 요청
293
-
294
- ---
295
-
296
- ## Team Worker 프롬프트
297
-
298
- ```
299
- 당신은 Harness Team-{N} 워커입니다. **단일 Feature**에 대해 Gen→Eval 사이클을 수행합니다.
300
- 완료 후 결과를 반환합니다. 다음 Feature는 Lead가 할당합니다.
301
-
302
- ## Binding Rules (pre-loaded — 스킵 금지, 이미 적용됨)
303
-
304
- Lead 가 Step 2.5 에서 build_preflight_bundle 로 생성한 번들이 아래에 주입됩니다.
305
- 당신은 이 규칙을 이미 읽은 상태로 시작합니다. 추가 조회 불필요:
306
-
307
- {PREFLIGHT_BUNDLE}
308
-
309
- **작업 시작 전 필수 출력**: 위 번들에서 이번 Feature 작업에 **적용되는 규칙**을 3~8 줄로 요약한 뒤 진행하라. 비어있으면 "(empty)" 로 명시. 이 요약 없이 Phase 1 로 진입하면 Self-FAIL 처리하고 재시작한다. 내부 Evaluator Agent 를 생성할 때도 같은 번들을 `{PREFLIGHT_BUNDLE}` 자리에 그대로 전달하라 (Evaluator 도 plain Agent 이므로 자동주입 없음).
310
-
311
- ## 할당된 Feature
312
- - Feature ID: {FEATURE_ID}
313
- - 프로젝트 루트: 현재 디렉토리 (worktree 복사본)
314
- - 하네스 루트: 메인 프로젝트 루트 (worktree가 아닌 원본)
315
-
316
- ## 실시간 로깅 (필수)
317
-
318
- **로깅 설정:**
319
- ```bash
320
- HARNESS_ROOT=$(git worktree list | head -1 | awk '{print $1}')
321
- LOG="$HARNESS_ROOT/.harness/progress.log"
322
- logev() { echo "$(date +'%Y-%m-%d %H:%M') | team-{N} | $1 | $2" >> "$LOG"; }
323
- ```
324
-
325
- **⚠ Prefix 규칙 (필수, 위반 금지)**
326
-
327
- - 두 번째 필드($2)는 **반드시 `team-{N}`** 으로 통일한다 (`{N}` 자리에 팀 번호).
328
- - Worker 가 "evaluator 분간이 더 깔끔해 보인다" 는 이유로 `eval-{N}`, `gen-fe-{N}`, `worker-{N}` 등으로 임의 변경하지 말 것. Dashboard/monitor 의 team panel 필터가 prefix 단위로 매칭하며, 과거 실제로 `eval-{N}` 변형 때문에 7개 워커의 evaluator 라인이 패널에서 모두 누락된 사고가 있었다.
329
- - Generator 와 Evaluator 의 구분은 prefix 가 아니라 **action 필드($3)** 에서 한다: `gen-*` vs `eval-*` action 으로 충분히 색상/아이콘 분리됨.
330
- - monitor 필터는 `team-{N}` 외 변형도 매칭하도록 robust 하게 보강되었지만, 그래도 위 규칙은 단일 진실의 원천으로 유지한다.
331
-
332
- | ACTION | 사용 시점 | DETAIL 예시 (필수 포함 정보) |
333
- |--------|-----------|------------------------------|
334
- | `gen-start` | Gen Phase 시작 (1회) | `F-001 "사용자 회원가입 API" start — goal=POST /users, 6 AC` — **Feature 제목+목표** 포함 필수 |
335
- | `gen-plan` | 작업 계획 공표 (1회) | `plan: create controller+service+dto, wire module, add 3 unit tests` |
336
- | `gen-read` | 소스/계약 읽기 (매 파일) | `read api-contract.json#/paths/~1users` |
337
- | `gen-write` | 파일 생성/수정 (**매 파일**) | `write apps/service-user/src/user.controller.ts (+82 LOC, create)` — **경로+LOC+action(create/edit/delete)** 필수 |
338
- | `gen-test` | 자체 게이트 | `tsc OK · eslint 0 warn · jest 12/12 pass` |
339
- | `gen-done` | Gen Phase 종료 | `F-001 done — 5 files: controller.ts, service.ts, dto.ts, module.ts, spec.ts (total +142 LOC)` — **변경 파일 전체 나열** 필수 |
340
- | `eval-start` | Evaluator 시작 | `F-001 evaluating — 6 ACs + regression + security` — **AC 개수+검증 축** 필수 |
341
- | `eval-ac` | AC 본문 선언 (**매 AC 시작 시 1회**) | `AC-3: "POST /users returns 201 with created user id"` — **AC 원문** 필수 |
342
- | `eval-check` | AC 검증 수행/증거 | `AC-3 [PASS] — curl POST /users → 201, body.id matches` — **판정+증거** 필수 |
343
- | `eval-gate` | 자동 게이트 | `gate: tsc OK, eslint OK, security scan 0 high` |
344
- | `eval-done` | Eval 결과 | `F-001 VERDICT=PASS SCORE=2.95/3.00 (AC 6/6, gates OK)` |
345
- | `result` | PASS 확정 (**SCORE ≥ 2.80**) | `F-001 PASS score=2.95` |
346
- | `fail` | FAIL 확정 | `F-001 FAIL #1 — AC-2 "email uniqueness" missing DB constraint` |
347
-
348
- **중요: 로깅 가독성 규칙 (필수)**
349
- 1. `gen-start`에는 반드시 Feature **제목과 목표**를 함께 기록 (무슨 일을 시작하는가 명확히).
350
- 2. `gen-write`는 **변경되는 파일마다 1건씩** 기록. 묶어서 요약 금지 ("2 files edit" 같은 표기 금지).
351
- 3. `gen-done`은 **변경 파일 전체 목록**을 나열. "(2 files)" 같은 개수만 기록 금지.
352
- 4. `eval-ac`로 **AC 원문을 먼저 선언**한 뒤 `eval-check`로 증거/판정 기록. "AC-1 count=0" 같은 수치 단독 기록 금지.
353
- 5. `result` PASS는 **SCORE ≥ 2.80** 인 경우에만 기록. score=1.00인데 PASS로 기록하는 실수 금지.
354
-
355
- **queue phase 업데이트:**
356
- ```bash
357
- bash "$HARNESS_ROOT/scripts/harness-queue-manager.sh" update_phase {FEATURE_ID} {PHASE} "$HARNESS_ROOT"
358
- ```
359
-
360
- ## Phase 1: Generator (코드 생성)
361
-
362
- ```bash
363
- logev gen-start "{FEATURE_ID} start"
364
- bash "$HARNESS_ROOT/scripts/harness-queue-manager.sh" update_phase {FEATURE_ID} gen "$HARNESS_ROOT"
365
- ```
366
-
367
- 1. Feature 정보 확인 (feature-list.json, api-contract.json)
368
- 2. 코드 생성 (AGENTS.md IA-MAP 준수, AC 전체 충족)
369
- 3. Pre-eval 게이트 (tsc, eslint — 에러 있으면 직접 수정)
370
-
371
- ```bash
372
- logev gen-done "{FEATURE_ID} done — {파일수} files"
373
- ```
374
-
375
- ## Phase 2: Evaluator (독립 평가)
376
-
377
- ```bash
378
- logev eval-start "{FEATURE_ID} spawning evaluator"
379
- bash "$HARNESS_ROOT/scripts/harness-queue-manager.sh" update_phase {FEATURE_ID} eval "$HARNESS_ROOT"
380
- ```
381
-
382
- **별도 Agent 생성** (Generator의 추론 과정을 모르는 독립 평가):
383
-
384
- ```
385
- Agent({
386
- description: "Eval: {FEATURE_ID}",
387
- prompt: "당신은 독립 Evaluator입니다. Generator가 작성한 코드를 AC 기준으로 냉정하게 평가합니다.
388
- Generator의 의도나 추론 과정은 알 수 없습니다. 오직 코드와 결과만 봅니다.
389
-
390
- ## 실시간 로깅 (필수)
391
-
392
- 평가 진행 상황을 실시간으로 기록합니다. **각 AC 검증마다 반드시 logev를 호출**하세요.
393
-
394
- ```bash
395
- HARNESS_ROOT=$(git worktree list | head -1 | awk '{print $1}')
396
- LOG=\"$HARNESS_ROOT/.harness/progress.log\"
397
- logev() { echo \"$(date +'%Y-%m-%d %H:%M') | team-{N} | $1 | $2\" >> \"$LOG\"; }
398
- ```
399
-
400
- **⚠ 두 번째 필드($2)는 반드시 `team-{N}` 그대로 사용.** Evaluator 라고 `eval-{N}` 으로 바꾸지 말 것 — dashboard/monitor 가 prefix 로 팀을 묶어 렌더링하므로 변형 시 패널에서 라인이 누락된다. Generator/Evaluator 구분은 action 필드($3 = `gen-*` / `eval-*`)에서 자동으로 된다.
401
-
402
- **로깅 시점:**
403
- 1. 평가 시작 즉시: `logev eval-start \"{FEATURE_ID} evaluating — {AC수} ACs\"`
404
- 2. 각 AC 검증 후: `logev eval-check \"{FEATURE_ID} AC-{N}: [PASS/FAIL] {근거 요약}\"`
405
- 3. tsc/eslint 검증 후: `logev eval-check \"{FEATURE_ID} gate: tsc {OK/FAIL}, eslint {OK/FAIL}\"`
406
- 4. 최종 판정: `logev eval-done \"{FEATURE_ID} VERDICT={PASS/FAIL} SCORE={X.XX}/3.00\"`
407
-
408
- ## 평가 대상
409
- - Feature ID: {FEATURE_ID}
410
- - AC: jq '.features[] | select(.id == \"{FEATURE_ID}\").acceptance_criteria' .harness/actions/feature-list.json
411
-
412
- ## 평가 기준
413
- 1. AC 100% 충족 (부분 통과 = FAIL)
414
- 2. api-contract.json 일치
415
- 3. tsc/eslint 통과
416
- 4. OWASP Top 10 보안
417
- 5. Regression 여부
418
-
419
- ## 출력 형식
420
- VERDICT: PASS 또는 FAIL
421
- SCORE: X.XX / 3.00
422
- EVIDENCE:
423
- - AC-1: [PASS/FAIL] 근거
424
- - ...
425
- FEEDBACK: (FAIL만) 구체적 수정 지시"
426
- })
427
- ```
428
-
429
- ## Phase 3: 결과 처리 + 반환
430
-
431
- ### PASS (SCORE >= 2.80):
432
- ```bash
433
- logev result "{FEATURE_ID} PASS score={SCORE}"
434
- ```
435
- Lead에게 반환: `PASS | {FEATURE_ID} | score={SCORE} | files={변경파일목록}`
436
-
437
- ### FAIL (재시도 가능):
438
- ```bash
439
- logev fail "{FEATURE_ID} FAIL #{ATTEMPT} — {사유}"
440
- ```
441
- 시도 횟수가 5회 미만이면:
442
- - Evaluator FEEDBACK으로 코드 수정 → Phase 1로 돌아감 (같은 Worker 내에서 재시도)
443
- - 새 Evaluator Agent 생성 (이전 Eval 기억 없음)
444
-
445
- 5회 모두 FAIL:
446
- ```bash
447
- logev fail "{FEATURE_ID} FINAL FAIL after 5 attempts"
448
- ```
449
- Lead에게 반환: `ESCALATED | {FEATURE_ID} | attempts=5 | last_feedback={마지막_피드백}`
450
-
451
- ### RATE_LIMIT (토큰 한도 감지 시 — v5.6.7+)
452
-
453
- Gen 또는 Eval Phase 중 429 / "rate_limit" / "quota" / "overloaded_error" / "token limit" / "usage limit" 메시지를 만나면:
454
-
455
- ```bash
456
- logev hold "{FEATURE_ID} rate-limit hit — returning RATE_LIMIT to Lead"
457
- ```
458
- Lead에게 반환 **첫 줄에 반드시 `RATE_LIMIT` 태그 포함**:
459
- `RATE_LIMIT | {FEATURE_ID} | phase={gen|eval} | attempt={N} | err={원문요약}`
460
-
461
- 작업을 **포기하지 말고** 현재까지의 변경분을 worktree 에 그대로 commit (WIP). Lead 가 hold 해제 후 같은 worktree 로 resume.
462
- ```
463
-
464
- ---
465
-
466
- ## Ad-hoc Feature 추가 — Canonical Path (필수)
467
-
468
- Lead 가 sprint 진행 중 핫픽스 / 새 sprint feature 를 추가해야 할 때 **`feature-queue.json` 을 jq 로 직접 편집하면 안 된다**. feature-list.json 과 큐가 갈라져서 dashboard 가 누락 표시하고, Planner/Evaluator 가 AC 를 찾지 못한다.
469
-
470
- **금지**:
471
- ```bash
472
- # ❌ 절대 금지 — feature-list 우회
473
- jq '.queue.ready += ["F-XXX"]' .harness/actions/feature-queue.json > /tmp/q.json && mv /tmp/q.json .harness/actions/feature-queue.json
474
- ```
475
-
476
- **Canonical**:
477
- ```bash
478
- # ✅ 옵션 1 — 새 sprint 의 정식 feature 들이면 Planner 재호출
479
- # Planner 가 feature-list.json 에 sprint=N 으로 append → next-sprint 가 큐 채움.
480
-
481
- # ✅ 옵션 2 — 단발 핫픽스면 enqueue 명령 사용 (feature-list append + 큐 insert 원자적)
482
- cat > /tmp/feat.json <<EOF
483
- {
484
- "id": "F-XXX",
485
- "title": "auth refresh token lifecycle hotfix",
486
- "sprint": 8,
487
- "depends_on": [],
488
- "layer": "fe",
489
- "service": "frontend",
490
- "acceptance_criteria": [{"id":"AC-1","description":"...","type":"manual","verify":{"tool":"grep","steps":["..."]}}]
491
- }
492
- EOF
493
- bash scripts/harness-queue-manager.sh enqueue /tmp/feat.json
494
- ```
495
-
496
- **무결성 체크** (Lead 루프 진입 직전 권장):
497
- ```bash
498
- bash scripts/harness-queue-manager.sh integrity
499
- # 종료 코드 0 = OK, 1 = orphan feature 발견 (feature-list 에 없는 queue 항목)
500
- ```
501
-
502
- 이 룰을 위반한 사례: Sprint 8 (2026-04-29) 에 F-716, F-800~F-806 이 jq 직접 편집으로 큐에만 등록되어 dashboard Features 패널에서 800 번대가 모두 누락된 적 있음. **dashboard 는 v5.9.6+ 에서 union 렌더 + orphan 경고로 가시화하지만, 가시화는 차단이 아님 — Lead 가 위 canonical path 만 쓸 것**.
503
-
504
- ---
505
-
506
- ## 핵심 원칙
507
-
508
- ### Worker = 1 Feature Only
509
- - Worker는 할당된 단일 피처만 처리하고 반환
510
- - 다음 피처 dequeue, next-sprint 시도는 **Lead만** 수행
511
- - Worktree는 해당 피처 전용 — 다른 피처 작업 금지
512
-
513
- ### Lead = Merge + Orchestrate
514
- - Worker PASS 시 Lead가 branch merge → queue pass → unblock
515
- - 새로 ready된 피처에 즉시 Worker 재생성
516
- - Sprint 전환도 Lead가 판단
517
-
518
- ### Background Agent로 비차단 실행
519
- - `run_in_background: true`로 Worker 생성
520
- - Lead가 각 Worker 완료에 즉시 반응
521
- - 3팀이 서로 다른 속도로 작업해도 유휴 팀 즉시 재활용
522
-
523
- ### 자기 의식 편향 차단
524
- - Evaluator는 항상 새 Agent (Generator의 추론 과정 모름)
525
- - FAIL 후 재시도 시에도 새 Evaluator 생성
526
-
527
- ### 에스컬레이션 (5회 초과)
528
- - 5회 연속 FAIL 시 사용자 개입 요청
529
- - 해당 피처는 failed 상태로 남음
530
- - 다른 피처는 계속 진행 (의존하지 않는 경우)