@walwal-harness/cli 2.0.1 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +296 -89
- package/assets/templates/config.json +41 -1
- package/bin/init.js +65 -3
- package/package.json +5 -2
- package/scripts/harness-next.sh +36 -1
- package/scripts/harness-user-prompt-submit.sh +106 -0
- package/scripts/lib/harness-render-progress.sh +15 -1
- package/scripts/scan-project.sh +24 -2
- package/skills/brainstorming/SKILL.md +200 -0
- package/skills/brainstorming/references/attribution.md +109 -0
- package/skills/brainstorming/references/spec-document-reviewer-prompt.md +49 -0
- package/skills/brainstorming/references/visual-companion.md +287 -0
- package/skills/brainstorming/scripts/frame-template.html +214 -0
- package/skills/brainstorming/scripts/helper.js +88 -0
- package/skills/brainstorming/scripts/server.cjs +354 -0
- package/skills/brainstorming/scripts/start-server.sh +148 -0
- package/skills/brainstorming/scripts/stop-server.sh +56 -0
- package/skills/dispatcher/SKILL.md +114 -2
- package/skills/dispatcher/references/pipeline-definitions.md +53 -5
- package/skills/evaluator-functional-flutter/SKILL.md +198 -0
- package/skills/evaluator-functional-flutter/references/ia-compliance.md +77 -0
- package/skills/evaluator-functional-flutter/references/scoring-rubric.md +132 -0
- package/skills/evaluator-functional-flutter/references/static-check-rules.md +99 -0
- package/skills/generator-frontend-flutter/SKILL.md +138 -0
- package/skills/generator-frontend-flutter/references/anti-patterns.md +288 -0
- package/skills/generator-frontend-flutter/references/api-layer-pattern.md +233 -0
- package/skills/generator-frontend-flutter/references/i18n-pattern.md +102 -0
- package/skills/generator-frontend-flutter/references/riverpod-pattern.md +199 -0
- package/skills/planner/SKILL.md +23 -1
- package/skills/planner/references/fe-stack-detection.md +131 -0
package/README.md
CHANGED
|
@@ -7,87 +7,217 @@
|
|
|
7
7
|
|
|
8
8
|
같은 AI 모델이라도 **하네스 설계에 따라 결과물 품질이 극적으로 달라집니다.** walwal-harness는 Anthropic이 제안한 하네스 엔지니어링 패턴을 설치 한 번으로 즉시 사용할 수 있게 패키징한 프레임워크입니다.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
---
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
## 설치
|
|
13
13
|
|
|
14
|
+
```bash
|
|
15
|
+
npm install @walwal-harness/cli
|
|
14
16
|
```
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
|
|
18
|
+
`postinstall`이 자동으로 프로젝트 루트에 설치합니다:
|
|
19
|
+
|
|
20
|
+
1. `.harness/` 디렉토리 스캐폴딩 (actions, archive, gotchas, config)
|
|
21
|
+
2. `.claude/skills/` 에 에이전트 스킬 설치 (9개)
|
|
22
|
+
3. `scripts/` 에 오케스트레이션 헬퍼 스크립트 설치
|
|
23
|
+
4. `SessionStart` 훅 등록 (세션 시작 시 진행 상태 표시)
|
|
24
|
+
5. `UserPromptSubmit` 훅 등록 (모든 프롬프트를 Dispatcher 경유 자동 라우팅)
|
|
25
|
+
6. `AGENTS.md` 생성 + `CLAUDE.md` 심볼릭 링크
|
|
26
|
+
7. 기존 프로젝트면 구조 스캔 → IA-MAP 자동 생성
|
|
27
|
+
|
|
28
|
+
> **중요:** 설치 후 Claude Code 세션을 **재시작**해야 skills가 인식됩니다.
|
|
29
|
+
> `/exit` → 디렉터리 재진입이 필요합니다.
|
|
30
|
+
|
|
31
|
+
### CLI 명령
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx walwal-harness # 초기화 (postinstall과 동일)
|
|
35
|
+
npx walwal-harness --force # 강제 재초기화 (기존 파일 덮어쓰기)
|
|
36
|
+
npx walwal-harness --help # 도움말
|
|
23
37
|
```
|
|
24
38
|
|
|
25
|
-
###
|
|
39
|
+
### 초기화에서 일어나는 일
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
your-project/
|
|
43
|
+
├── AGENTS.md # 에이전트 공통 컨텍스트 (Planner 관리)
|
|
44
|
+
├── CLAUDE.md → AGENTS.md # 심볼릭 링크
|
|
45
|
+
├── scripts/
|
|
46
|
+
│ ├── harness-next.sh # 세션 오케스트레이터
|
|
47
|
+
│ ├── harness-session-start.sh # SessionStart 훅
|
|
48
|
+
│ ├── harness-user-prompt-submit.sh # UserPromptSubmit 훅 (auto-routing)
|
|
49
|
+
│ ├── scan-project.sh # 프로젝트 구조 스캔
|
|
50
|
+
│ ├── init-agents-md.sh # AGENTS.md 생성/리빌드
|
|
51
|
+
│ └── lib/
|
|
52
|
+
│ └── harness-render-progress.sh # 프로그레스 바 렌더러
|
|
53
|
+
├── .harness/
|
|
54
|
+
│ ├── config.json # 하네스 설정
|
|
55
|
+
│ ├── HARNESS.md # 하네스 상세 가이드
|
|
56
|
+
│ ├── progress.json # 세션 간 상태 (기계 판독)
|
|
57
|
+
│ ├── gotchas/ # 에이전트별 실수 기록
|
|
58
|
+
│ ├── actions/ # 활성 스프린트 문서
|
|
59
|
+
│ └── archive/ # 완료 스프린트 보관 (불변)
|
|
60
|
+
└── .claude/
|
|
61
|
+
├── settings.json # 훅 등록 (SessionStart + UserPromptSubmit)
|
|
62
|
+
└── skills/ # Claude Code 스킬 (9개)
|
|
63
|
+
├── harness-dispatcher/
|
|
64
|
+
├── harness-brainstorming/
|
|
65
|
+
├── harness-planner/
|
|
66
|
+
├── harness-generator-backend/
|
|
67
|
+
├── harness-generator-frontend/
|
|
68
|
+
├── harness-generator-frontend-flutter/
|
|
69
|
+
├── harness-evaluator-functional/
|
|
70
|
+
├── harness-evaluator-functional-flutter/
|
|
71
|
+
└── harness-evaluator-visual/
|
|
26
72
|
```
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
### 1. 설치 + 재시작
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
cd your-project
|
|
82
|
+
npm install @walwal-harness/cli
|
|
83
|
+
# Claude Code 세션 재시작 (/exit → 재진입)
|
|
30
84
|
```
|
|
31
85
|
|
|
32
|
-
###
|
|
86
|
+
### 2. 하네스 시작
|
|
87
|
+
|
|
88
|
+
Claude Code에서 아무 요청이나 입력하면 **UserPromptSubmit 훅이 자동으로 Dispatcher를 호출**합니다. 또는 명시적으로:
|
|
89
|
+
|
|
33
90
|
```
|
|
34
|
-
|
|
35
|
-
└─ OpenAPI → api-contract.json 자동 변환
|
|
91
|
+
> 하네스 엔지니어링 시작
|
|
36
92
|
```
|
|
37
93
|
|
|
38
|
-
###
|
|
94
|
+
### 3. Dispatcher가 분류
|
|
95
|
+
|
|
39
96
|
```
|
|
40
|
-
|
|
97
|
+
사용자 입력
|
|
98
|
+
│
|
|
99
|
+
├─ 신규 기능/제품 요청 → 파이프라인 선택 (FULLSTACK / FE-ONLY / BE-ONLY)
|
|
100
|
+
│ └─ "브레인스토밍 필요합니까?" → Y: Brainstormer → Planner
|
|
101
|
+
│ → N: Planner 직행
|
|
102
|
+
├─ 실수 지적 → Gotcha 기록 → 해당 에이전트 재작업
|
|
103
|
+
├─ 특정 에이전트 명령 → 해당 에이전트 직접 라우팅
|
|
104
|
+
└─ 메타/인사 → 일반 응답
|
|
41
105
|
```
|
|
42
106
|
|
|
43
|
-
|
|
107
|
+
### 4. 에이전트 순차 실행
|
|
44
108
|
|
|
45
|
-
|
|
46
|
-
|
|
109
|
+
각 에이전트가 완료되면 다음 프롬프트를 제안합니다:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
✓ Dispatcher 완료. bash scripts/harness-next.sh 실행하여 다음 단계 확인.
|
|
47
113
|
```
|
|
48
114
|
|
|
49
|
-
`
|
|
50
|
-
- `.harness/` 디렉토리 스캐폴딩 (actions, archive, gotchas)
|
|
51
|
-
- `.claude/skills/` 에 6개 에이전트 스킬 설치
|
|
52
|
-
- `AGENTS.md` 생성 + `CLAUDE.md` 심볼릭 링크
|
|
53
|
-
- 기존 프로젝트면 구조 스캔 → IA-MAP 자동 생성
|
|
115
|
+
`bash scripts/harness-next.sh` 를 실행하면 프로그레스 바 + 다음 에이전트 안내:
|
|
54
116
|
|
|
55
|
-
|
|
56
|
-
|
|
117
|
+
```
|
|
118
|
+
═══ Sprint 1 / FULLSTACK ═══════════════════
|
|
57
119
|
|
|
58
|
-
|
|
120
|
+
Agents: planner✓ → generator-backend✓ → [generator-frontend] → evaluator-functional → evaluator-visual
|
|
59
121
|
|
|
60
|
-
|
|
61
|
-
npx walwal-harness # 초기화 (postinstall과 동일)
|
|
62
|
-
npx walwal-harness --force # 강제 재초기화 (기존 파일 덮어쓰기)
|
|
63
|
-
npx walwal-harness --help # 도움말
|
|
122
|
+
/harness-generator-frontend 를 실행하세요.
|
|
64
123
|
```
|
|
65
124
|
|
|
66
|
-
|
|
125
|
+
### 5. 반복
|
|
67
126
|
|
|
68
|
-
|
|
127
|
+
FAIL이 발생하면 Evaluator가 원인을 분석하고 해당 Generator로 자동 재작업 라우팅 (최대 10회). PASS하면 다음 Evaluator로 진행. 모든 Evaluator를 통과하면 스프린트 완료 → 아카이브.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 파이프라인
|
|
132
|
+
|
|
133
|
+
Dispatcher가 사용자 요청을 분석하여 3가지 파이프라인 중 하나를 자동 선택합니다:
|
|
134
|
+
|
|
135
|
+
### FULLSTACK (신규 프로젝트)
|
|
69
136
|
|
|
70
137
|
```
|
|
71
|
-
|
|
138
|
+
Brainstormer? → Planner → Generator-BE → Generator-FE → Evaluator-Func → Evaluator-Visual
|
|
139
|
+
│ FAIL
|
|
140
|
+
└──→ 재작업 (max 10회)
|
|
72
141
|
```
|
|
73
142
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
143
|
+
### FE-ONLY (기존 API에 프론트엔드 연동)
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
Brainstormer? → Planner(light) → Generator-FE → Evaluator-Func → Evaluator-Visual
|
|
147
|
+
└─ OpenAPI → api-contract.json 자동 변환
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### BE-ONLY (기존 서버에 백엔드 기능 추가)
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
Brainstormer? → Planner → Generator-BE → Evaluator-Func(API-only)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
> `Brainstormer?` = Dispatcher가 사용자에게 확인 후 조건부 실행. 명확한 PRD/OpenAPI가 있으면 생략 가능.
|
|
157
|
+
|
|
158
|
+
### Flutter 프로젝트 자동 감지
|
|
159
|
+
|
|
160
|
+
`pubspec.yaml` + `flutter:` 키가 감지되면 FE 에이전트가 **자동 치환**됩니다:
|
|
161
|
+
|
|
162
|
+
| React (기본) | Flutter |
|
|
163
|
+
|-------------|---------|
|
|
164
|
+
| `generator-frontend` | `generator-frontend-flutter` |
|
|
165
|
+
| `evaluator-functional` (Playwright) | `evaluator-functional-flutter` (flutter analyze/test) |
|
|
166
|
+
| `evaluator-visual` | **SKIP** (브라우저 없음) |
|
|
167
|
+
|
|
168
|
+
치환은 `pipeline.json.fe_stack` 값에 의해 `harness-next.sh`가 자동 처리합니다. Planner가 프로젝트 스캔 결과를 보고 `fe_stack`을 확정합니다.
|
|
169
|
+
|
|
170
|
+
---
|
|
78
171
|
|
|
79
|
-
##
|
|
172
|
+
## 에이전트
|
|
80
173
|
|
|
81
|
-
|
|
82
|
-
|----------|------|-------|
|
|
83
|
-
| **Dispatcher** | 파이프라인 선택 + Gotcha 관리 | `harness-dispatcher` |
|
|
84
|
-
| **Planner** | 제품 사양 + API 계약서 + IA-MAP 설계 | `harness-planner` |
|
|
85
|
-
| **Generator-Backend** | NestJS MSA 구현 (Gateway + Microservices) | `harness-generator-backend` |
|
|
86
|
-
| **Generator-Frontend** | React/Next.js UI + API 연동 | `harness-generator-frontend` |
|
|
87
|
-
| **Evaluator-Functional** | Playwright E2E 기능 검증 + IA 구조 검증 | `harness-evaluator-functional` |
|
|
88
|
-
| **Evaluator-Visual** | 디자인 일관성, 반응형, 접근성, AI슬롭 감지 | `harness-evaluator-visual` |
|
|
174
|
+
### 9개 에이전트 (조건부 포함)
|
|
89
175
|
|
|
90
|
-
|
|
176
|
+
| 에이전트 | 역할 | 호출 조건 |
|
|
177
|
+
|----------|------|----------|
|
|
178
|
+
| **Dispatcher** | 파이프라인 선택 + Gotcha 관리 + 라우팅 | 항상 (auto-routing 훅) |
|
|
179
|
+
| **Brainstormer** | 러프한 요구사항을 대화형으로 구체화 | Dispatcher가 사용자에게 확인 후 |
|
|
180
|
+
| **Planner** | 제품 사양 + API 계약서 + 서비스 분할 | 파이프라인 시작 시 |
|
|
181
|
+
| **Generator-Backend** | NestJS MSA 구현 (Gateway + Microservices) | FULLSTACK, BE-ONLY |
|
|
182
|
+
| **Generator-Frontend** | React/Next.js UI + API 연동 | FULLSTACK, FE-ONLY (React) |
|
|
183
|
+
| **Generator-Frontend-Flutter** | Flutter (Riverpod + Retrofit + ARB i18n) | FULLSTACK, FE-ONLY (Flutter) |
|
|
184
|
+
| **Evaluator-Functional** | Playwright E2E 기능 검증 | FULLSTACK, FE-ONLY (React) |
|
|
185
|
+
| **Evaluator-Functional-Flutter** | flutter analyze/test + 정적 anti-pattern 검증 | FULLSTACK, FE-ONLY (Flutter) |
|
|
186
|
+
| **Evaluator-Visual** | 디자인 일관성, 반응형, 접근성, AI슬롭 감지 | FULLSTACK, FE-ONLY (React만) |
|
|
187
|
+
|
|
188
|
+
### Brainstormer (조건부)
|
|
189
|
+
|
|
190
|
+
[obra/superpowers](https://github.com/obra/superpowers) (MIT License)의 brainstorming 방법론을 이식.
|
|
191
|
+
바이브코딩 수준의 러프한 요구사항을 **대화형 Q&A로 구체화**하여 Planner가 바로 소비할 수 있는 `brainstorm-spec.md`로 만듭니다.
|
|
192
|
+
|
|
193
|
+
**핵심 원칙:**
|
|
194
|
+
- HARD-GATE: 사용자 승인 없이 구현 단계로 넘어갈 수 없음
|
|
195
|
+
- 한 번에 한 질문, 객관식 우선
|
|
196
|
+
- 2-3개 접근법 제시 후 사용자가 선택
|
|
197
|
+
- Spec self-review + User Review Gate
|
|
198
|
+
|
|
199
|
+
**실행 조건:** Dispatcher가 "브레인스토밍 과정이 필요합니까? (Y/N)" 라고 묻고 사용자가 Y 응답한 경우에만. 피드백/이터레이션/직접 명령에서는 자동 스킵.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 핵심 메커니즘
|
|
204
|
+
|
|
205
|
+
### Auto-Routing (UserPromptSubmit Hook)
|
|
206
|
+
|
|
207
|
+
설치 시 `.claude/settings.json`에 `UserPromptSubmit` 훅이 자동 등록됩니다. 모든 사용자 프롬프트가 Dispatcher를 경유하도록 컨텍스트를 주입합니다.
|
|
208
|
+
|
|
209
|
+
**per-message opt-out:**
|
|
210
|
+
```
|
|
211
|
+
> harness skip 그냥 이것만 답해줘
|
|
212
|
+
> harness 없이 질문 하나만
|
|
213
|
+
> without harness ...
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**전역 비활성:**
|
|
217
|
+
```json
|
|
218
|
+
// .harness/config.json
|
|
219
|
+
{ "behavior": { "auto_route_dispatcher": false } }
|
|
220
|
+
```
|
|
91
221
|
|
|
92
222
|
### API Contract — 진실의 원천
|
|
93
223
|
|
|
@@ -124,52 +254,64 @@ Evaluator는 기능 테스트 전에 AGENTS.md의 IA-MAP과 실제 폴더 구조
|
|
|
124
254
|
- `scan-project.sh`가 Tech Stack, 폴더 구조, 기존 CLAUDE.md를 자동 스캔
|
|
125
255
|
- 기존 CLAUDE.md 규칙을 "Preserved Rules" 섹션으로 이관
|
|
126
256
|
- 원본은 `.harness/archive/pre-harness-backup/`에 백업
|
|
257
|
+
- Flutter 프로젝트 자동 감지 (`pubspec.yaml` + `flutter:`)
|
|
127
258
|
|
|
128
|
-
|
|
259
|
+
---
|
|
129
260
|
|
|
130
|
-
|
|
261
|
+
## FE 스택별 지원
|
|
131
262
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
263
|
+
### React / Next.js (기본)
|
|
264
|
+
|
|
265
|
+
| 항목 | 상세 |
|
|
266
|
+
|------|------|
|
|
267
|
+
| Generator | `harness-generator-frontend` — RSC, App Router, Tailwind CSS, Cache Components |
|
|
268
|
+
| Evaluator-Func | `harness-evaluator-functional` — Playwright MCP (`browser_*`) E2E 테스트 |
|
|
269
|
+
| Evaluator-Visual | `harness-evaluator-visual` — 스크린샷 기반 디자인/접근성/반응형 검증 |
|
|
270
|
+
| 레퍼런스 | Vercel Best Practices, Design System Rules, AI Forbidden Patterns, Component Patterns |
|
|
271
|
+
|
|
272
|
+
### Flutter (Dart)
|
|
273
|
+
|
|
274
|
+
| 항목 | 상세 |
|
|
275
|
+
|------|------|
|
|
276
|
+
| Generator | `harness-generator-frontend-flutter` — Riverpod + integrated_data_layer(Retrofit) + ARB i18n |
|
|
277
|
+
| Evaluator-Func | `harness-evaluator-functional-flutter` — `flutter analyze` + `flutter test` + build_runner drift + anti-pattern grep (FL-01~FL-08) |
|
|
278
|
+
| Evaluator-Visual | **SKIP** (Flutter 앱은 브라우저 기반 시각 검증 불가) |
|
|
279
|
+
| 레퍼런스 | API Layer Pattern, Riverpod Pattern, i18n Pattern, Anti-Patterns (9개 금지 패턴 + 셀프 체크 스크립트) |
|
|
280
|
+
|
|
281
|
+
### FE 스택 감지
|
|
282
|
+
|
|
283
|
+
1. `scan-project.sh`가 `pubspec.yaml` + `flutter:` 키를 탐지
|
|
284
|
+
2. Planner가 `pipeline.json.fe_stack = "flutter"` 확정
|
|
285
|
+
3. `harness-next.sh`가 FE 에이전트를 자동 치환 (Agent Bar에도 반영)
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 스크립트 레퍼런스
|
|
290
|
+
|
|
291
|
+
| 스크립트 | 설명 | 실행 방법 |
|
|
292
|
+
|----------|------|----------|
|
|
293
|
+
| `harness-next.sh` | 세션 오케스트레이터 — progress.json 읽고 다음 에이전트 결정, 프로그레스 바 출력 | `bash scripts/harness-next.sh` |
|
|
294
|
+
| `scan-project.sh` | 프로젝트 구조 스캔 → `.harness/actions/scan-result.json` 출력 | `bash scripts/scan-project.sh .` |
|
|
295
|
+
| `init-agents-md.sh` | scan-result.json 기반 AGENTS.md 생성/리빌드 | `bash scripts/init-agents-md.sh .` |
|
|
296
|
+
| `harness-session-start.sh` | SessionStart 훅 — 세션 시작 시 progress 요약 출력 | (자동 — .claude/settings.json 훅) |
|
|
297
|
+
| `harness-user-prompt-submit.sh` | UserPromptSubmit 훅 — 모든 프롬프트를 Dispatcher 경유 라우팅 | (자동 — .claude/settings.json 훅) |
|
|
298
|
+
|
|
299
|
+
---
|
|
161
300
|
|
|
162
301
|
## Tech Stack
|
|
163
302
|
|
|
164
303
|
| 영역 | 기술 |
|
|
165
304
|
|------|------|
|
|
166
305
|
| Backend | NestJS (TypeScript) + MSA |
|
|
167
|
-
| Frontend | React 또는 Next.js (TypeScript) |
|
|
168
|
-
|
|
|
169
|
-
| E2E Testing | Playwright MCP |
|
|
170
|
-
|
|
|
306
|
+
| Frontend (React) | React 또는 Next.js (TypeScript) + Tailwind CSS |
|
|
307
|
+
| Frontend (Flutter) | Flutter (Dart) + Riverpod + Retrofit + ARB i18n |
|
|
308
|
+
| E2E Testing (React) | Playwright MCP |
|
|
309
|
+
| E2E Testing (Flutter) | flutter analyze + flutter test + 정적 검증 |
|
|
310
|
+
| Unit Testing | Jest (BE) + Vitest (FE-React) + flutter test (FE-Flutter) |
|
|
171
311
|
| Database | PostgreSQL / SQLite |
|
|
172
312
|
|
|
313
|
+
---
|
|
314
|
+
|
|
173
315
|
## 권장 외부 스킬
|
|
174
316
|
|
|
175
317
|
하네스는 자체 reference 파일로 기본 가이드를 제공하지만, 아래 외부 스킬을 설치하면 품질이 향상됩니다. 초기화 시 자동으로 설치 여부를 체크하고 안내합니다.
|
|
@@ -181,9 +323,11 @@ your-project/
|
|
|
181
323
|
| **taste-skill** | AI 생성 UI 디자인 품질, AI슬롭 감지 | Evaluator-Visual, Generator-FE |
|
|
182
324
|
| **supanova-design-skill** | 디자인 시스템 규칙, 시각적 일관성 | Evaluator-Visual, Generator-FE |
|
|
183
325
|
|
|
184
|
-
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Playwright MCP 설정 (React 프로젝트)
|
|
185
329
|
|
|
186
|
-
Evaluator
|
|
330
|
+
Evaluator-Functional / Evaluator-Visual이 브라우저 테스트를 수행하려면 Playwright MCP가 필요합니다. `~/.mcp.json`에 추가:
|
|
187
331
|
|
|
188
332
|
```json
|
|
189
333
|
{
|
|
@@ -196,12 +340,75 @@ Evaluator가 브라우저 테스트를 수행하려면 Playwright MCP가 필요
|
|
|
196
340
|
}
|
|
197
341
|
```
|
|
198
342
|
|
|
343
|
+
> Flutter 프로젝트에서는 Playwright가 필요 없습니다 — `evaluator-functional-flutter`는 `flutter analyze` + `flutter test` 기반입니다.
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## 트러블슈팅
|
|
348
|
+
|
|
349
|
+
### Skills가 로드되지 않아요
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
# Claude Code 세션을 완전히 종료하고 다시 시작
|
|
353
|
+
/exit
|
|
354
|
+
# 프로젝트 디렉토리에서 재진입 후 확인
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Claude Code는 세션 시작 시 `.claude/skills/`를 스캔합니다. `npm install` 이후 반드시 세션 재시작이 필요합니다.
|
|
358
|
+
|
|
359
|
+
### Dispatcher가 자동 호출되지 않아요
|
|
360
|
+
|
|
361
|
+
`UserPromptSubmit` 훅이 정상적으로 등록되었는지 확인:
|
|
362
|
+
|
|
363
|
+
```bash
|
|
364
|
+
cat .claude/settings.json
|
|
365
|
+
# hooks.UserPromptSubmit 배열에 harness-user-prompt-submit.sh가 있어야 함
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
등록이 안 되었다면:
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
npx walwal-harness --force
|
|
372
|
+
# 재시작
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
### 브레인스토밍이 매번 실행돼서 피로해요
|
|
376
|
+
|
|
377
|
+
Brainstormer는 Dispatcher가 "브레인스토밍 필요합니까?" 물을 때만 실행됩니다. **N**으로 답하면 Planner로 직행합니다. 피드백/이터레이션/특정 에이전트 명령에서는 질문 자체가 나오지 않습니다.
|
|
378
|
+
|
|
379
|
+
### Flutter 프로젝트인데 React 에이전트가 실행돼요
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
# 프로젝트 루트에 pubspec.yaml이 있고 flutter: 키가 존재하는지 확인
|
|
383
|
+
grep "flutter:" pubspec.yaml
|
|
384
|
+
|
|
385
|
+
# 재스캔
|
|
386
|
+
bash scripts/scan-project.sh .
|
|
387
|
+
# pipeline.json의 fe_stack 값 확인
|
|
388
|
+
cat .harness/actions/pipeline.json | jq '.fe_stack'
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Auto-routing을 끄고 싶어요
|
|
392
|
+
|
|
393
|
+
```json
|
|
394
|
+
// .harness/config.json
|
|
395
|
+
{ "behavior": { "auto_route_dispatcher": false } }
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
또는 개별 메시지에서:
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
> harness skip 그냥 이것만 답해줘
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
---
|
|
405
|
+
|
|
199
406
|
## 참고
|
|
200
407
|
|
|
201
408
|
- [Anthropic: Effective Harnesses for Long-Running Agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents)
|
|
202
409
|
- [Anthropic: Harness Design for Long-Running Application Development](https://www.anthropic.com/engineering/harness-design-long-running-apps)
|
|
203
410
|
- [Claude Code Skills Documentation](https://code.claude.com/docs/en/skills)
|
|
204
|
-
- [
|
|
411
|
+
- [obra/superpowers](https://github.com/obra/superpowers) — Brainstorming skill 원본 (MIT License)
|
|
205
412
|
|
|
206
413
|
## License
|
|
207
414
|
|
|
@@ -12,9 +12,20 @@
|
|
|
12
12
|
"outputs": ["actions/pipeline.json"],
|
|
13
13
|
"always_first": true
|
|
14
14
|
},
|
|
15
|
+
"brainstorming": {
|
|
16
|
+
"role": "사용자의 러프한 요구사항을 대화형으로 구체화하여 Planner가 바로 쓸 수 있는 brainstorm-spec.md로 변환. Dispatcher가 사용자에게 '브레인스토밍 필요?' 확인 후에만 호출되는 조건부 에이전트.",
|
|
17
|
+
"skill": "harness-brainstorming",
|
|
18
|
+
"inputs": ["(user conversation)"],
|
|
19
|
+
"outputs": ["actions/brainstorm-spec.md"],
|
|
20
|
+
"conditional": true,
|
|
21
|
+
"invoked_by": "dispatcher (user opt-in)",
|
|
22
|
+
"next_on_complete": "planner",
|
|
23
|
+
"attribution": "Derived from obra/superpowers skills/brainstorming (MIT License)"
|
|
24
|
+
},
|
|
15
25
|
"planner": {
|
|
16
26
|
"role": "제품 사양 + API 계약서 + 서비스 분할 설계",
|
|
17
27
|
"skill": "harness-planner",
|
|
28
|
+
"inputs": ["actions/brainstorm-spec.md (optional)"],
|
|
18
29
|
"outputs": [
|
|
19
30
|
"actions/plan.md",
|
|
20
31
|
"actions/feature-list.json",
|
|
@@ -48,16 +59,40 @@
|
|
|
48
59
|
"tools": ["playwright:browser_take_screenshot", "playwright:browser_resize", "playwright:browser_snapshot"],
|
|
49
60
|
"inputs": ["actions/sprint-contract.md", "actions/evaluation-functional.md"],
|
|
50
61
|
"outputs": ["actions/evaluation-visual.md"]
|
|
62
|
+
},
|
|
63
|
+
"generator-frontend-flutter": {
|
|
64
|
+
"role": "Flutter 앱 개발 — Riverpod, integrated_data_layer(Retrofit), i18n(ARB), build_runner",
|
|
65
|
+
"skill": "harness-generator-frontend-flutter",
|
|
66
|
+
"inputs": ["actions/plan.md", "actions/feature-list.json", "actions/api-contract.json", "actions/sprint-contract.md"],
|
|
67
|
+
"outputs": ["code:flutter", "actions/sprint-contract.md"],
|
|
68
|
+
"order": 2,
|
|
69
|
+
"fe_stack": "flutter"
|
|
70
|
+
},
|
|
71
|
+
"evaluator-functional-flutter": {
|
|
72
|
+
"role": "Flutter 앱 검증 — flutter analyze, flutter test, build_runner 일관성, 안티패턴 정적 검증",
|
|
73
|
+
"skill": "harness-evaluator-functional-flutter",
|
|
74
|
+
"tools": ["bash:flutter", "bash:dart"],
|
|
75
|
+
"inputs": ["actions/sprint-contract.md"],
|
|
76
|
+
"outputs": ["actions/evaluation-functional.md"],
|
|
77
|
+
"fe_stack": "flutter"
|
|
51
78
|
}
|
|
52
79
|
},
|
|
53
80
|
"flow": {
|
|
54
81
|
"sequence": ["dispatcher", "planner", "generator-backend", "generator-frontend", "evaluator-functional", "evaluator-visual"],
|
|
55
82
|
"pipeline_selection": {
|
|
56
|
-
"comment": "Dispatcher가 pipeline.json으로 활성 에이전트를 결정.
|
|
83
|
+
"comment": "Dispatcher가 pipeline.json으로 활성 에이전트를 결정. fe_stack 필드로 React/Flutter를 구분. harness-next.sh가 pipeline.json.fe_stack 을 읽어 generator-frontend/evaluator-functional 을 Flutter 변형으로 치환한다.",
|
|
57
84
|
"pipelines": {
|
|
58
85
|
"FULLSTACK": ["planner", "generator-backend", "generator-frontend", "evaluator-functional", "evaluator-visual"],
|
|
59
86
|
"FE-ONLY": ["planner:light", "generator-frontend", "evaluator-functional", "evaluator-visual"],
|
|
60
87
|
"BE-ONLY": ["planner", "generator-backend", "evaluator-functional:api-only"]
|
|
88
|
+
},
|
|
89
|
+
"fe_stack_substitution": {
|
|
90
|
+
"comment": "pipeline.json.fe_stack=flutter 이면 아래 치환을 적용. evaluator-visual은 skip.",
|
|
91
|
+
"flutter": {
|
|
92
|
+
"generator-frontend": "generator-frontend-flutter",
|
|
93
|
+
"evaluator-functional": "evaluator-functional-flutter",
|
|
94
|
+
"evaluator-visual": "__skip__"
|
|
95
|
+
}
|
|
61
96
|
}
|
|
62
97
|
},
|
|
63
98
|
"sprint_execution": {
|
|
@@ -75,6 +110,11 @@
|
|
|
75
110
|
"state_log": ".harness/progress.log",
|
|
76
111
|
"next_prompt_file": ".harness/next-prompt.txt"
|
|
77
112
|
},
|
|
113
|
+
"behavior": {
|
|
114
|
+
"comment": "하네스 동작 플래그. UserPromptSubmit 훅이 이 값을 읽어 자동 라우팅을 결정한다.",
|
|
115
|
+
"auto_route_dispatcher": true,
|
|
116
|
+
"auto_route_dispatcher_description": "true 이면 사용자의 모든 프롬프트가 harness-dispatcher 경유로 분류/라우팅 된다. 사용자가 'harness skip' 등을 말하면 단일 메시지 한정으로 건너뛴다."
|
|
117
|
+
},
|
|
78
118
|
"paths": {
|
|
79
119
|
"actions": ".harness/actions",
|
|
80
120
|
"archive": ".harness/archive",
|
package/bin/init.js
CHANGED
|
@@ -295,6 +295,60 @@ function installSessionHook() {
|
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
+
// ─────────────────────────────────────────
|
|
299
|
+
// 3c. UserPromptSubmit hook (auto dispatcher routing)
|
|
300
|
+
// ─────────────────────────────────────────
|
|
301
|
+
function installUserPromptSubmitHook() {
|
|
302
|
+
log('Installing UserPromptSubmit hook (auto dispatcher routing)...');
|
|
303
|
+
|
|
304
|
+
const settingsDir = path.join(PROJECT_ROOT, '.claude');
|
|
305
|
+
const settingsFile = path.join(settingsDir, 'settings.json');
|
|
306
|
+
|
|
307
|
+
ensureDir(settingsDir);
|
|
308
|
+
|
|
309
|
+
let settings = {};
|
|
310
|
+
if (fileExists(settingsFile)) {
|
|
311
|
+
try {
|
|
312
|
+
settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
|
|
313
|
+
} catch (e) {
|
|
314
|
+
log('WARNING: Could not parse existing .claude/settings.json, creating new');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (!settings.hooks) settings.hooks = {};
|
|
319
|
+
if (!settings.hooks.UserPromptSubmit) settings.hooks.UserPromptSubmit = [];
|
|
320
|
+
|
|
321
|
+
const hookCmd = 'bash scripts/harness-user-prompt-submit.sh';
|
|
322
|
+
|
|
323
|
+
// Detect existing harness UserPromptSubmit hook (any shape)
|
|
324
|
+
const alreadyInstalled = settings.hooks.UserPromptSubmit.some((entry) => {
|
|
325
|
+
if (!entry || typeof entry !== 'object') return false;
|
|
326
|
+
if (Array.isArray(entry.hooks)) {
|
|
327
|
+
return entry.hooks.some(
|
|
328
|
+
(h) => h && h.command && h.command.includes('harness-user-prompt-submit')
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
if (entry.type === 'command' && entry.command) {
|
|
332
|
+
return entry.command.includes('harness-user-prompt-submit');
|
|
333
|
+
}
|
|
334
|
+
return false;
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
if (!alreadyInstalled) {
|
|
338
|
+
settings.hooks.UserPromptSubmit.push({
|
|
339
|
+
matcher: '',
|
|
340
|
+
hooks: [{ type: 'command', command: hookCmd }]
|
|
341
|
+
});
|
|
342
|
+
fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2) + '\n');
|
|
343
|
+
log('UserPromptSubmit hook installed in .claude/settings.json');
|
|
344
|
+
log(' → All prompts will be routed through harness-dispatcher');
|
|
345
|
+
log(' → Opt-out per message: say "harness skip" or "without harness"');
|
|
346
|
+
log(' → Disable globally: set .harness/config.json behavior.auto_route_dispatcher = false');
|
|
347
|
+
} else {
|
|
348
|
+
log('UserPromptSubmit hook already installed');
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
298
352
|
// ─────────────────────────────────────────
|
|
299
353
|
// 4. AGENTS.md + CLAUDE.md
|
|
300
354
|
// ─────────────────────────────────────────
|
|
@@ -453,9 +507,16 @@ What it does:
|
|
|
453
507
|
1. Scaffolds .harness/ directory (actions, archive, gotchas, config)
|
|
454
508
|
2. Installs skills to .claude/skills/ (dispatcher, planner, generators, evaluators)
|
|
455
509
|
3. Copies helper scripts to scripts/
|
|
456
|
-
4.
|
|
457
|
-
5.
|
|
458
|
-
6.
|
|
510
|
+
4. Registers SessionStart hook (boot-time progress render)
|
|
511
|
+
5. Registers UserPromptSubmit hook (auto-route every prompt through harness-dispatcher)
|
|
512
|
+
6. Creates AGENTS.md + CLAUDE.md symlink
|
|
513
|
+
7. Checks Playwright MCP configuration
|
|
514
|
+
8. Checks recommended external skills (Vercel, design skills)
|
|
515
|
+
|
|
516
|
+
Auto routing:
|
|
517
|
+
Every user prompt is routed through harness-dispatcher.
|
|
518
|
+
Per-message opt-out: say "harness skip" or "harness 없이".
|
|
519
|
+
Global disable: edit .harness/config.json → behavior.auto_route_dispatcher = false
|
|
459
520
|
|
|
460
521
|
After init:
|
|
461
522
|
1. Restart Claude Code session (exit and re-enter) for skills to load
|
|
@@ -487,6 +548,7 @@ function main() {
|
|
|
487
548
|
installSkills();
|
|
488
549
|
installScripts();
|
|
489
550
|
installSessionHook();
|
|
551
|
+
installUserPromptSubmitHook();
|
|
490
552
|
setupAgentsMd();
|
|
491
553
|
checkPlaywrightMcp();
|
|
492
554
|
checkRecommendedSkills();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walwal-harness/cli",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "Production harness for AI agent engineering — Planner, Generator(BE/FE), Evaluator(Func/Visual)
|
|
3
|
+
"version": "2.3.1",
|
|
4
|
+
"description": "Production harness for AI agent engineering — Planner, Generator(BE/FE), Evaluator(Func/Visual), optional Brainstormer (requirements refinement). Supports React and Flutter FE stacks.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"walwal-harness": "bin/init.js"
|
|
7
7
|
},
|
|
@@ -16,11 +16,14 @@
|
|
|
16
16
|
"ai-agent",
|
|
17
17
|
"claude-code",
|
|
18
18
|
"skill",
|
|
19
|
+
"brainstorming",
|
|
19
20
|
"planner",
|
|
20
21
|
"generator",
|
|
21
22
|
"evaluator",
|
|
22
23
|
"nestjs",
|
|
23
24
|
"react",
|
|
25
|
+
"flutter",
|
|
26
|
+
"riverpod",
|
|
24
27
|
"playwright"
|
|
25
28
|
],
|
|
26
29
|
"author": "",
|