@walwal-harness/cli 5.5.1 → 5.5.3

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 (3) hide show
  1. package/README.md +208 -63
  2. package/bin/init.js +24 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -9,6 +9,141 @@
9
9
 
10
10
  ---
11
11
 
12
+ ## Run Book — 0 → 첫 스프린트 완주
13
+
14
+ > 프로젝트 루트에서 `npm i @walwal-harness/cli` 를 마치고 Claude Code 를 재시작한 뒤 아래 순서 그대로 진행합니다.
15
+
16
+ ### Step 1. Dispatcher — 들어오자마자
17
+
18
+ Claude Code 세션을 연 뒤 첫 메시지로:
19
+
20
+ ```
21
+ 하네스 엔지니어링 시작
22
+ ```
23
+
24
+ Dispatcher 가:
25
+ - 요청을 분류 (기능 요청 / 실수 지적 / 메타 질문)
26
+ - `FULLSTACK` / `FE-ONLY` / `BE-ONLY` 파이프라인 결정 → `actions/pipeline.json`
27
+ - 신규/재플래닝이면 "Brainstormer 를 거칠지" 한 번 묻고 `next_agent` 설정 후 STOP
28
+
29
+ 완료되면 **새 세션을 열기만 하면** SessionStart 훅이 다음 에이전트(`planner` 또는 `brainstorming`)를 안내합니다.
30
+
31
+ ### Step 2. Planner
32
+
33
+ 새 세션에서:
34
+
35
+ ```
36
+ /harness-planner
37
+ ```
38
+
39
+ Planner 가 `plan.md` + `feature-list.json` + `api-contract.json` 을 생성합니다. AC(Acceptance Criteria)는 반드시 **Executable** 포맷으로 기술됩니다.
40
+
41
+ ### Step 3. Solo / Team 모드 선택
42
+
43
+ Planner 완료 후 두 갈래 중 하나.
44
+
45
+ | 선택 | 명령 | 언제 |
46
+ |------|------|------|
47
+ | **Solo** | 프롬프트로 `/harness-generator-backend` → `/harness-generator-frontend` → `/harness-evaluator-*` 순차 호출 | 학습 목적 · feature 3개 이하 · 레이아웃이 좁음 |
48
+ | **Team** | `/harness-team` | feature 4개 이상 · 병렬로 확 밀고 싶을 때 |
49
+
50
+ ### Step 4. Team 모드 — Dashboard 띄우기
51
+
52
+ Team 모드는 tmux 통합 Studio 레이아웃을 제공합니다:
53
+
54
+ ```bash
55
+ # Claude Code 내에서
56
+ > /harness-team
57
+
58
+ # 또는 외부 터미널에서
59
+ npx walwal-harness team
60
+ ```
61
+
62
+ 첫 실행 시 자동으로:
63
+ 1. `feature-queue.json` 초기화 (의존성 topological sort)
64
+ 2. tmux (또는 iTerm2 native split) 레이아웃 구축
65
+ 3. 3개 팀 worker 가 Gen → Eval 루프를 병렬 실행
66
+ 4. 팀이 feature 완료 시 자동 dequeue
67
+ 5. 5회 초과 실패하면 사용자 개입 요청
68
+
69
+ #### 대시보드 구성
70
+
71
+ ```
72
+ ┌────────────────────┬──────────────────────────┬───────────┐
73
+ │ Dashboard │ Gotcha & Memory │ TEAM 1 │
74
+ │ - pipeline/sprint │ - 활성 에이전트 gotcha │ Gen|Eval │
75
+ │ - feature 진행도 │ - 나머지 에이전트 요약 ├───────────┤
76
+ │ - queue 상태 │ - SHARED MEMORY │ TEAM 2 │
77
+ │ │ (memory.md 최근 N) │ Gen|Eval │
78
+ ├────────────────────┤ ├───────────┤
79
+ │ Archive Prompt │ │ TEAM 3 │
80
+ │ (완료 feature 요약)│ │ Gen|Eval │
81
+ └────────────────────┴──────────────────────────┴───────────┘
82
+ ```
83
+
84
+ | 패널 | 내용 | 소스 |
85
+ |------|------|------|
86
+ | **Dashboard** | Pipeline · Sprint · Feature passes (●/◐/○/◌/✗) · Queue R:B:P · Retry | `harness-dashboard.sh` |
87
+ | **Gotcha & Memory** | 활성 에이전트의 누적 실수 + 나머지 요약 + 공유 메모리 | `harness-gotcha-memory.sh` |
88
+ | **TEAM 1–3** | 각 워커의 현재 feature · phase(Gen/Eval) · 실시간 stdout | `harness-queue-manager.sh` worker loop |
89
+ | **Archive Prompt** | 직전 완료 feature 요약 (다음 팀 컨텍스트 주입용) | archive 디렉토리 |
90
+
91
+ - 새로고침 주기: `HARNESS_REFRESH=5` (초). 환경변수로 조정.
92
+ - 단축키: `tmux prefix + 방향키` 로 패널 이동, `prefix + z` 로 확대/축소.
93
+ - 종료: `npx walwal-harness team --kill`.
94
+
95
+ ### Step 5. Gotcha 등록 — 같은 실수 반복 막기
96
+
97
+ 사용자가 에이전트의 실수를 지적하면 Dispatcher 가 해당 에이전트의 `.harness/gotchas/<agent>.md` 에 자동 append. 다음 세션부터 그 에이전트는 세션 시작 시 자기 gotcha 파일을 읽고 같은 실수를 피합니다.
98
+
99
+ #### 예제 — 실수 지적
100
+
101
+ ```
102
+ 아니 그렇게 하면 안 되지. Generator-Backend 가 MockServer 를 무시하고
103
+ 실제 DB 에 붙으려고 하는데, npm run dev 에서 MockServer 가 concurrent 로
104
+ 기동되어 있으니 그걸 먼저 확인하고 써.
105
+ ```
106
+
107
+ Dispatcher 는 자동으로 분류:
108
+ - **대상 에이전트**: `generator-backend`
109
+ - **저장 위치**: `.harness/gotchas/generator-backend.md`
110
+ - **ID 할당**: `[G-002]` (기존 항목 다음 번호)
111
+
112
+ #### 기록 포맷 (Dispatcher 가 자동 작성)
113
+
114
+ ```markdown
115
+ ### [G-002] MockServer + npm run dev 자동 기동 + OpenAPI 동기화
116
+ - **Date**: 2026-04-22
117
+ - **Severity**: HIGH
118
+ - **Occurrences**: 1
119
+ - **Symptom**: 실제 DB 연결 시도 → 연결 실패로 스프린트 중단
120
+ - **Rule**: `npm run dev` 는 MockServer 를 concurrent 로 기동한다.
121
+ API 호출 전 `http://localhost:3001/health` 를 확인할 것.
122
+ - **Applies to**: generator-backend
123
+ ```
124
+
125
+ #### 공유 메모리 (프로젝트 전체 규칙)
126
+
127
+ 한 에이전트 실수가 아니라 **모든 에이전트에 적용할 구조적 교훈** 이면 `.harness/memory.md` 로 승격:
128
+
129
+ ```
130
+ 이건 특정 Generator 실수가 아니라 이 프로젝트 공통 규칙이야 —
131
+ 모든 테스트는 MockServer seed data 기반이어야 한다는 걸
132
+ 메모리에 올려줘.
133
+ ```
134
+
135
+ → Dispatcher 가 `memory.md` 에 `### [M-NNN] ...` 로 기록. Planner 리뷰 후 `unverified → verified` 로 승격.
136
+
137
+ #### 주의 — 데이터 보존
138
+
139
+ v5.5.2 부터 `npm install` postinstall 이 `### [G-NNN]` 엔트리가 있는 gotcha 파일을 **절대 덮어쓰지 않습니다**. 그 이전 버전에서는 업데이트 시 누적 기록이 템플릿으로 초기화되는 버그가 있었습니다 — 반드시 `5.5.2+` 를 사용하세요.
140
+
141
+ ---
142
+
143
+ ## Detail Architecture
144
+
145
+ 여기부터는 어떻게 구성되어 있는지, 왜 그렇게 설계했는지에 대한 상세 문서입니다.
146
+
12
147
  ## 두 가지 모드
13
148
 
14
149
  | 모드 | 설명 | 실행 방법 |
@@ -31,7 +166,7 @@ npm install @walwal-harness/cli
31
166
 
32
167
  `postinstall`이 자동으로:
33
168
  1. `.harness/` 디렉토리 스캐폴딩
34
- 2. `.claude/skills/` 에 에이전트 스킬 설치 (7개)
169
+ 2. `.claude/skills/` 에 에이전트 스킬 설치 (8개)
35
170
  3. `.claude/commands/` 에 모드 제어 커맨드 설치 (3개)
36
171
  4. `scripts/` 에 오케스트레이션 스크립트 설치
37
172
  5. SessionStart / UserPromptSubmit 훅 등록
@@ -45,8 +180,7 @@ npm install @walwal-harness/cli
45
180
  npm update @walwal-harness/cli
46
181
  ```
47
182
 
48
- npm update 시 모든 시스템 파일(scripts, skills, commands)이 **자동으로 교체**됩니다.
49
- 사용자 데이터(progress.json, progress.log, gotchas 커스텀 항목, archive)는 보존됩니다.
183
+ npm update 시 모든 시스템 파일(scripts, skills, commands, config 템플릿)이 **자동으로 교체**됩니다. 사용자 데이터(progress.json, progress.log, **gotchas 누적 엔트리**, memory.md, archive)는 보존됩니다.
50
184
 
51
185
  ### CLI 명령어
52
186
 
@@ -60,40 +194,67 @@ npx walwal-harness --help # 도움말
60
194
 
61
195
  ---
62
196
 
63
- ## Quick Start — Solo Mode
197
+ ## 에이전트 구성
64
198
 
65
- ```bash
66
- # 1. 설치
67
- npm install @walwal-harness/cli
199
+ | 에이전트 | 역할 | 모델 |
200
+ |----------|------|------|
201
+ | **Dispatcher** | 요청 분석 → 파이프라인 결정 · gotcha 관리 | opus |
202
+ | **Brainstormer** | 러프한 요구사항 → 구조화된 spec | opus |
203
+ | **Planner** | 제품 사양 + API 계약서 + 서비스 분할 | opus |
204
+ | **Generator-Backend** | NestJS MSA 서비스 구현 | sonnet |
205
+ | **Generator-Frontend** | React/Next.js UI 구현 | sonnet |
206
+ | **Evaluator-Code-Quality** | 코드 유지보수성/아키텍처/Best Practice (BE/FE/libs 공통, 브라우저 없음) | opus |
207
+ | **Evaluator-Functional** | Playwright E2E 기능 검증 · API 계약 준수 | opus |
208
+ | **Evaluator-Visual** | 레이아웃/접근성/AI슬롭 검증 | opus |
68
209
 
69
- # 2. Claude Code 재시작
70
- claude # (또는 codex)
210
+ ### Evaluator Chain (v5.5+)
71
211
 
72
- # 3. 하네스 시작
73
- > 하네스 엔지니어링 시작
212
+ Generator 이후는 **3-Evaluator 직렬 체인 + 조기 종료** 로 동작:
74
213
 
75
- # 4. Dispatcher → Planner 순서로 자동 진행
76
- # 5. Generator, Evaluator를 프롬프트로 순차 호출
77
214
  ```
215
+ Generator
216
+ → Evaluator-Code-Quality (정적 · 저비용 · 브라우저 없음)
217
+ → Evaluator-Functional (동작 · 중비용 · Playwright/curl)
218
+ → Evaluator-Visual (렌더 · 고비용 · 스크린샷)
219
+ → Archive
220
+ ```
221
+
222
+ 앞단 FAIL 시 뒤 평가자는 실행하지 않고 바로 Generator 재작업으로 리라우팅. BE-ONLY 파이프라인에서는 Visual 이 체인에서 제외됩니다.
223
+
224
+ | 단계 | 채점 축 | Weight | 도구 |
225
+ |------|---------|--------|------|
226
+ | Code-Quality | C1 Layer · C2 Readability · C3 DRY · C4 Type/Error · C5 Test | 25/15/20/25/15 | Read/Grep + tsc/eslint |
227
+ | Functional | R1 Contract · R2 AC · R3 Negative · R4 E2E · R5 Error | 25/25/20/15/15 | Playwright 또는 curl |
228
+ | Visual | V1 Layout · V2 Responsive · V3 A11y · V4 Consistency · V5 Interaction | 20×5 | Playwright 스크린샷 |
229
+
230
+ ### Evaluation 기준
231
+ - PASS: Weighted Score ≥ 2.80 / 3.00
232
+ - AC 100% 충족 필수 (부분 통과 = FAIL)
233
+ - Regression 실패 1건+ = FAIL (이전 Sprint PASS 기능 재검증)
234
+ - Evidence 없는 Score = 0점 강제 재계산
235
+ - Cross-Validation 불일치 1건+ = CONDITIONAL FAIL
236
+ - Team Mode: 최대 5회 재시도 후 사용자 개입 요청
78
237
 
79
- ### Solo 파이프라인
238
+ ---
239
+
240
+ ## 솔로 파이프라인 상세
80
241
 
81
242
  ```
82
243
  사용자 요청 → Dispatcher → (Brainstormer) → Planner
83
244
  → Generator-Backend → Generator-Frontend
84
- → Evaluator-Functional → Evaluator-Visual
245
+ → Evaluator-Code-Quality → Evaluator-Functional → Evaluator-Visual
85
246
  → PASS: 다음 Sprint | FAIL: Generator로 재시도 (최대 5회)
86
247
  ```
87
248
 
88
- ---
249
+ 각 에이전트는 **독립 Claude Code 세션** 에서 실행됩니다. Session Boundary Protocol 이 On Start / On Complete / On Fail 훅으로 progress.json 을 갱신하고 STOP. 다음 세션을 열면 SessionStart 훅이 자동으로 다음 에이전트를 안내합니다.
89
250
 
90
- ## Quick Start — Team Mode
251
+ ## 팀 파이프라인 상세
91
252
 
92
253
  ```bash
93
- # Planner 완료 후:
254
+ # Planner 완료 후
94
255
  > /harness-team
95
256
 
96
- # 자동으로:
257
+ # 자동 실행 흐름:
97
258
  # 1. feature-queue.json 초기화 (의존성 topological sort)
98
259
  # 2. tmux Studio 레이아웃 구축
99
260
  # 3. 3개 팀이 병렬로 Gen→Eval 루프 자동 실행
@@ -101,23 +262,7 @@ claude # (또는 codex)
101
262
  # 5. 5회 초과 실패 시 사용자 개입 요청
102
263
  ```
103
264
 
104
- ### Team 모드 레이아웃
105
-
106
- ```
107
- ┌──────────────┬──────────────┬──────────────┐
108
- │ Prompt │ Dashboard │ TEAM 1 │
109
- │ History │ (queue + │ Gen | Eval │
110
- │ │ status) ├──────────────┤
111
- ├──────────────┤ │ TEAM 2 │
112
- │ Controller │ │ Gen | Eval │
113
- │ (Claude / │ ├──────────────┤
114
- │ Codex) │ │ TEAM 3 │
115
- └──────────────┴──────────────┴──────────────┘
116
- ```
117
-
118
- ---
119
-
120
- ## 모드 전환
265
+ ### 모드 전환
121
266
 
122
267
  | 명령 | 설명 |
123
268
  |------|------|
@@ -133,27 +278,6 @@ Team 실행 중 → /harness-stop → /harness-solo → 프롬프트로 계속
133
278
 
134
279
  ---
135
280
 
136
- ## 에이전트 구성
137
-
138
- | 에이전트 | 역할 | 모델 |
139
- |----------|------|------|
140
- | **Dispatcher** | 요청 분석 → 파이프라인 결정 | opus |
141
- | **Brainstormer** | 러프한 요구사항 → 구조화된 spec | opus |
142
- | **Planner** | 제품 사양 + API 계약서 + 서비스 분할 | opus |
143
- | **Generator-Backend** | NestJS MSA 서비스 구현 | sonnet |
144
- | **Generator-Frontend** | React/Next.js UI 구현 | sonnet |
145
- | **Evaluator-Functional** | Playwright E2E 기능 검증 | opus |
146
- | **Evaluator-Visual** | 디자인/접근성/AI슬롭 검증 | opus |
147
-
148
- ### Evaluation 기준
149
- - PASS: Weighted Score ≥ 2.80/3.00
150
- - AC 100% 충족 필수 (부분 통과 = FAIL)
151
- - Regression 실패 1건+ = FAIL
152
- - Evidence 없는 Score = 0점
153
- - Team Mode: 최대 5회 재시도 후 사용자 개입 요청
154
-
155
- ---
156
-
157
281
  ## 디렉토리 구조
158
282
 
159
283
  ```
@@ -162,21 +286,34 @@ your-project/
162
286
  │ ├── config.json # 하네스 설정
163
287
  │ ├── progress.json # 런타임 상태 (mode, sprint, agent)
164
288
  │ ├── progress.log # 실시간 이벤트 로그
289
+ │ ├── memory.md # 공유 학습 기록 (모든 에이전트 공통)
165
290
  │ ├── HARNESS.md # 하네스 상세 가이드
166
291
  │ ├── actions/ # 활성 스프린트 문서
167
- │ │ ├── feature-list.json # Feature 목록 + AC
168
- │ │ ├── api-contract.json # API 계약서
292
+ │ │ ├── pipeline.json # Dispatcher 결정 (evaluator_chain 포함)
293
+ │ │ ├── plan.md
294
+ │ │ ├── feature-list.json # Feature 목록 + Executable AC
295
+ │ │ ├── api-contract.json
169
296
  │ │ ├── feature-queue.json # Feature Queue 상태 (Team Mode)
170
- │ │ └── ...
297
+ │ │ ├── sprint-contract.md
298
+ │ │ ├── evaluation-code-quality.md
299
+ │ │ ├── evaluation-functional.md
300
+ │ │ └── evaluation-visual.md
171
301
  │ ├── archive/ # 완료 스프린트 보관 (불변)
172
- │ └── gotchas/ # 에이전트 실수 기록
302
+ │ └── gotchas/ # 에이전트 실수 기록 (누적 보존)
303
+ │ ├── planner.md
304
+ │ ├── generator-backend.md
305
+ │ ├── generator-frontend.md
306
+ │ ├── evaluator-code-quality.md
307
+ │ ├── evaluator-functional.md
308
+ │ └── evaluator-visual.md
173
309
  ├── .claude/
174
- │ ├── skills/harness-*/ # 에이전트 스킬 (7개)
310
+ │ ├── skills/harness-*/ # 에이전트 스킬 (8개)
175
311
  │ ├── commands/harness-*.md # 모드 제어 커맨드 (3개)
176
312
  │ └── settings.json # 훅, statusline
177
313
  ├── scripts/
178
314
  │ ├── harness-tmux.sh # 통합 tmux 레이아웃 (Solo/Team)
179
315
  │ ├── harness-dashboard.sh # 통합 대시보드
316
+ │ ├── harness-gotcha-memory.sh # Gotcha & Memory 패널
180
317
  │ ├── harness-monitor.sh # 에이전트 모니터
181
318
  │ ├── harness-queue-manager.sh # Feature Queue 관리
182
319
  │ ├── harness-next.sh # 에이전트 전환 라우터
@@ -186,7 +323,7 @@ your-project/
186
323
  │ ├── harness-prompt-history.sh # 프롬프트 히스토리
187
324
  │ └── lib/ # 공유 라이브러리
188
325
  ├── AGENTS.md # 프로젝트 컨텍스트 (IA-MAP)
189
- └── CLAUDE.md → AGENTS.md # 심볼릭 링크
326
+ └── CLAUDE.md → AGENTS.md # 심볼릭 링크
190
327
  ```
191
328
 
192
329
  ---
@@ -218,6 +355,14 @@ cat .harness/progress.json | jq '{mode, sprint, current_agent, next_agent}'
218
355
  jq '.mode = "solo"' .harness/progress.json > /tmp/p.json && mv /tmp/p.json .harness/progress.json
219
356
  ```
220
357
 
358
+ ### 대시보드에 feature title 이 "?" 로 표시
359
+ - v5.5.1 에서 해결 (feature 의 `name`/`title`/`description` 순으로 fallback).
360
+ - 그 이전 버전이면 `npm i @walwal-harness/cli@latest` 로 업데이트.
361
+
362
+ ### Gotcha 가 누적되지 않고 사라짐
363
+ - v5.5.2 에서 해결 (postinstall 이 누적 엔트리를 절대 덮어쓰지 않도록 수정).
364
+ - 반드시 `5.5.2+` 사용.
365
+
221
366
  ---
222
367
 
223
368
  ## License
package/bin/init.js CHANGED
@@ -101,27 +101,38 @@ function scaffoldHarness() {
101
101
  ensureDir(path.join(HARNESS_DIR, 'archive'));
102
102
  ensureDir(path.join(HARNESS_DIR, 'gotchas'));
103
103
 
104
- // Copy gotchas — ALWAYS overwrite system templates, preserve user custom entries
104
+ // Copy gotchas — preserve any existing file that has accumulated entries.
105
+ // Dispatcher appends `### [G-NNN] ...` entries directly; we must NEVER overwrite
106
+ // a file that has such entries, or user learning history is lost.
105
107
  const gotchasSrc = path.join(PKG_ROOT, 'gotchas');
106
108
  if (fs.existsSync(gotchasSrc)) {
107
- const CUSTOM_MARKER = '## Custom Gotchas';
109
+ const ENTRY_PATTERN = /^### \[G-\d+\]/m; // Gotcha entry heading
110
+ const CUSTOM_MARKER = '## Custom Gotchas'; // Legacy marker still supported
108
111
  const files = fs.readdirSync(gotchasSrc);
109
112
  for (const file of files) {
110
113
  const destPath = path.join(HARNESS_DIR, 'gotchas', file);
111
114
  const srcPath = path.join(gotchasSrc, file);
112
- if (fileExists(destPath) && file.endsWith('.md')) {
113
- // Preserve user-added custom section
114
- const existing = fs.readFileSync(destPath, 'utf8');
115
- const customIdx = existing.indexOf(CUSTOM_MARKER);
116
- const userCustom = customIdx !== -1 ? existing.substring(customIdx) : '';
117
- let newContent = fs.readFileSync(srcPath, 'utf8');
118
- if (userCustom) {
119
- newContent = newContent.trimEnd() + '\n\n' + userCustom;
120
- }
121
- fs.writeFileSync(destPath, newContent);
122
- } else {
115
+ if (!fileExists(destPath)) {
123
116
  copyFile(srcPath, destPath);
117
+ continue;
124
118
  }
119
+ if (!file.endsWith('.md')) continue;
120
+
121
+ const existing = fs.readFileSync(destPath, 'utf8');
122
+ const hasEntries = ENTRY_PATTERN.test(existing);
123
+ const hasCustomSection = existing.indexOf(CUSTOM_MARKER) !== -1;
124
+
125
+ if (hasEntries || hasCustomSection) {
126
+ // User has accumulated data — DO NOT overwrite. Skip silently.
127
+ // README.md is the only exception (system doc, regenerated below).
128
+ if (file === 'README.md') {
129
+ copyFile(srcPath, destPath);
130
+ }
131
+ continue;
132
+ }
133
+
134
+ // File exists but is just the scaffold template — safe to refresh
135
+ copyFile(srcPath, destPath);
125
136
  }
126
137
  }
127
138
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walwal-harness/cli",
3
- "version": "5.5.1",
3
+ "version": "5.5.3",
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"