@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/scripts/harness-next.sh
CHANGED
|
@@ -18,6 +18,7 @@ PROJECT_ROOT="$(resolve_harness_root "${1:-.}")" || {
|
|
|
18
18
|
|
|
19
19
|
PROGRESS="$PROJECT_ROOT/.harness/progress.json"
|
|
20
20
|
CONFIG="$PROJECT_ROOT/.harness/config.json"
|
|
21
|
+
PIPELINE_JSON="$PROJECT_ROOT/.harness/actions/pipeline.json"
|
|
21
22
|
NEXT_PROMPT="$PROJECT_ROOT/.harness/next-prompt.txt"
|
|
22
23
|
|
|
23
24
|
check_jq || exit 1
|
|
@@ -40,6 +41,29 @@ next_agent=$(jq -r '.next_agent // "null"' "$PROGRESS")
|
|
|
40
41
|
retry_count=$(jq -r '.sprint.retry_count // 0' "$PROGRESS")
|
|
41
42
|
max_retries=$(jq -r '.flow.max_retries_per_sprint // 10' "$CONFIG" 2>/dev/null || echo 10)
|
|
42
43
|
|
|
44
|
+
# fe_stack 치환 (Flutter 지원) — pipeline.json 에서 읽음
|
|
45
|
+
fe_stack="react"
|
|
46
|
+
if [ -f "$PIPELINE_JSON" ]; then
|
|
47
|
+
fe_stack=$(jq -r '.fe_stack // "react"' "$PIPELINE_JSON" 2>/dev/null || echo "react")
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# ─────────────────────────────────────────
|
|
51
|
+
# fe_stack 치환 헬퍼
|
|
52
|
+
# pipeline_selection.pipelines에서 읽은 에이전트명을 fe_stack에 따라 치환
|
|
53
|
+
# - react: 그대로
|
|
54
|
+
# - flutter: generator-frontend → generator-frontend-flutter 등, __skip__ 은 건너뜀
|
|
55
|
+
# ─────────────────────────────────────────
|
|
56
|
+
substitute_fe_stack() {
|
|
57
|
+
local agent="$1"
|
|
58
|
+
if [ "$fe_stack" != "flutter" ]; then
|
|
59
|
+
echo "$agent"
|
|
60
|
+
return
|
|
61
|
+
fi
|
|
62
|
+
local sub
|
|
63
|
+
sub=$(jq -r ".flow.pipeline_selection.fe_stack_substitution.flutter[\"${agent}\"] // \"${agent}\"" "$CONFIG" 2>/dev/null)
|
|
64
|
+
echo "$sub"
|
|
65
|
+
}
|
|
66
|
+
|
|
43
67
|
# ─────────────────────────────────────────
|
|
44
68
|
# Determine next agent
|
|
45
69
|
# ─────────────────────────────────────────
|
|
@@ -73,8 +97,18 @@ compute_next_agent() {
|
|
|
73
97
|
return
|
|
74
98
|
fi
|
|
75
99
|
|
|
100
|
+
local -a raw_agents
|
|
101
|
+
mapfile -t raw_agents < <(jq -r ".flow.pipeline_selection.pipelines[\"${pipeline}\"][]" "$CONFIG" 2>/dev/null | sed 's/:.*//')
|
|
102
|
+
|
|
103
|
+
# fe_stack 치환 + __skip__ 필터링
|
|
76
104
|
local -a agents
|
|
77
|
-
|
|
105
|
+
for a in "${raw_agents[@]}"; do
|
|
106
|
+
local sub
|
|
107
|
+
sub=$(substitute_fe_stack "$a")
|
|
108
|
+
if [ "$sub" != "__skip__" ]; then
|
|
109
|
+
agents+=("$sub")
|
|
110
|
+
fi
|
|
111
|
+
done
|
|
78
112
|
|
|
79
113
|
local found=false
|
|
80
114
|
for agent in "${agents[@]}"; do
|
|
@@ -82,6 +116,7 @@ compute_next_agent() {
|
|
|
82
116
|
echo "$agent"
|
|
83
117
|
return
|
|
84
118
|
fi
|
|
119
|
+
# current 비교 시에도 치환된 이름으로 (Flutter 변형 에이전트가 실행되는 경우)
|
|
85
120
|
if [ "$agent" = "$current" ]; then
|
|
86
121
|
found=true
|
|
87
122
|
fi
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# harness-user-prompt-submit.sh
|
|
3
|
+
# ─────────────────────────────────────────
|
|
4
|
+
# Claude Code UserPromptSubmit hook
|
|
5
|
+
# 모든 사용자 프롬프트를 harness-dispatcher 로 라우팅하도록 Claude 에게
|
|
6
|
+
# 지시하는 컨텍스트를 stdout 에 주입한다.
|
|
7
|
+
#
|
|
8
|
+
# 활성 조건:
|
|
9
|
+
# 1) 현재 cwd 에 .harness/config.json 존재
|
|
10
|
+
# 2) .harness/config.json 의 behavior.auto_route_dispatcher != false
|
|
11
|
+
#
|
|
12
|
+
# 비활성 상황에서는 아무것도 출력하지 않고 exit 0 (pass-through).
|
|
13
|
+
# ─────────────────────────────────────────
|
|
14
|
+
set -e
|
|
15
|
+
|
|
16
|
+
# stdin 의 JSON payload 읽기 (Claude Code 가 {prompt, cwd, session_id, ...} 전달)
|
|
17
|
+
INPUT=$(cat)
|
|
18
|
+
|
|
19
|
+
# cwd 추출 (payload 에 없으면 PWD fallback)
|
|
20
|
+
CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null || true)
|
|
21
|
+
if [ -z "$CWD" ]; then
|
|
22
|
+
CWD="$PWD"
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# 조건 1: 하네스 초기화 확인
|
|
26
|
+
if [ ! -f "$CWD/.harness/config.json" ]; then
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# 조건 2: opt-out 플래그 확인 (기본값 true)
|
|
31
|
+
AUTO_ROUTE="true"
|
|
32
|
+
if command -v jq >/dev/null 2>&1; then
|
|
33
|
+
AUTO_ROUTE=$(jq -r '.behavior.auto_route_dispatcher // true' "$CWD/.harness/config.json" 2>/dev/null || echo "true")
|
|
34
|
+
fi
|
|
35
|
+
if [ "$AUTO_ROUTE" != "true" ]; then
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# 프롬프트 내용 추출 (opt-out 문구 감지용)
|
|
40
|
+
PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null || true)
|
|
41
|
+
# 사용자가 명시적으로 건너뛰기 요청하면 pass-through
|
|
42
|
+
if echo "$PROMPT" | grep -qiE "harness\s*(skip|off|bypass|없이)|without\s*harness|just\s*(answer|chat|reply)"; then
|
|
43
|
+
exit 0
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# 현재 세션 상태 읽기
|
|
47
|
+
PIPELINE="none"
|
|
48
|
+
CURRENT_AGENT="none"
|
|
49
|
+
NEXT_AGENT="none"
|
|
50
|
+
SPRINT_NUM="0"
|
|
51
|
+
SPRINT_STATUS="init"
|
|
52
|
+
FE_STACK="react"
|
|
53
|
+
|
|
54
|
+
if [ -f "$CWD/.harness/progress.json" ] && command -v jq >/dev/null 2>&1; then
|
|
55
|
+
PIPELINE=$(jq -r '.pipeline // "none"' "$CWD/.harness/progress.json" 2>/dev/null || echo "none")
|
|
56
|
+
CURRENT_AGENT=$(jq -r '.current_agent // "none"' "$CWD/.harness/progress.json" 2>/dev/null || echo "none")
|
|
57
|
+
NEXT_AGENT=$(jq -r '.next_agent // "none"' "$CWD/.harness/progress.json" 2>/dev/null || echo "none")
|
|
58
|
+
SPRINT_NUM=$(jq -r '.sprint.number // 0' "$CWD/.harness/progress.json" 2>/dev/null || echo "0")
|
|
59
|
+
SPRINT_STATUS=$(jq -r '.sprint.status // "init"' "$CWD/.harness/progress.json" 2>/dev/null || echo "init")
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
if [ -f "$CWD/.harness/actions/pipeline.json" ] && command -v jq >/dev/null 2>&1; then
|
|
63
|
+
FE_STACK=$(jq -r '.fe_stack // "react"' "$CWD/.harness/actions/pipeline.json" 2>/dev/null || echo "react")
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# ─────────────────────────────────────────
|
|
67
|
+
# Context 주입 (stdout → Claude 컨텍스트)
|
|
68
|
+
# ─────────────────────────────────────────
|
|
69
|
+
cat <<EOF
|
|
70
|
+
[walwal-harness] Auto-routing is ACTIVE for this project.
|
|
71
|
+
|
|
72
|
+
이 프로젝트는 walwal-harness 가 초기화되어 있으며, auto_route_dispatcher 플래그가
|
|
73
|
+
켜져 있습니다. 사용자의 모든 프롬프트는 **harness-dispatcher** 스킬을 통해
|
|
74
|
+
분류/라우팅된 뒤 처리되어야 합니다.
|
|
75
|
+
|
|
76
|
+
## 분류 규칙 (Dispatcher Request Classification)
|
|
77
|
+
- **기능 요청** (만들어줘, 추가, 고쳐줘, PRD, OpenAPI) → Pipeline Flow
|
|
78
|
+
- **실수 지적** (아니, 잘못됐어, 그렇게 하면 안 돼, X로 해야지) → Gotcha Flow
|
|
79
|
+
- **혼합** → Gotcha 먼저 기록 → Pipeline 이어서
|
|
80
|
+
- **메타/인사/Claude 자체 질문** → 짧게 일반 응답 (dispatcher skip 허용)
|
|
81
|
+
|
|
82
|
+
## 현재 harness 세션 상태
|
|
83
|
+
- pipeline: $PIPELINE
|
|
84
|
+
- current_agent: $CURRENT_AGENT
|
|
85
|
+
- next_agent: $NEXT_AGENT
|
|
86
|
+
- sprint: $SPRINT_NUM ($SPRINT_STATUS)
|
|
87
|
+
- fe_stack: $FE_STACK
|
|
88
|
+
|
|
89
|
+
## 지시
|
|
90
|
+
1. 먼저 위 상태를 읽고, 사용자 메시지가 어떤 분류에 해당하는지 판단
|
|
91
|
+
2. **pipeline 이 'none' 또는 dispatcher 미실행 상태**면 harness-dispatcher 스킬 호출
|
|
92
|
+
3. **pipeline 이 이미 활성**이면:
|
|
93
|
+
- 실수 지적이면 → dispatcher 로 gotcha 기록
|
|
94
|
+
- 기능 연속 작업이면 → next_agent 또는 current_agent 의 컨텍스트로 계속
|
|
95
|
+
4. 응답 전 반드시 \`.harness/progress.json\` 을 읽고 세션 경계 프로토콜 준수
|
|
96
|
+
|
|
97
|
+
## 이 라우팅을 건너뛰려면
|
|
98
|
+
- **단일 메시지**: 사용자가 "harness skip", "without harness", "harness 없이", "just answer" 등을 명시
|
|
99
|
+
- **전역 비활성**: \`.harness/config.json\` 에서 \`behavior.auto_route_dispatcher = false\` 설정
|
|
100
|
+
|
|
101
|
+
## 참고
|
|
102
|
+
이 안내는 \`scripts/harness-user-prompt-submit.sh\` UserPromptSubmit 훅에 의해
|
|
103
|
+
매 프롬프트마다 자동 주입됩니다. 중복 안내처럼 보여도 무시하지 말고 위 규칙을 따르세요.
|
|
104
|
+
EOF
|
|
105
|
+
|
|
106
|
+
exit 0
|
|
@@ -282,12 +282,17 @@ render_progress() {
|
|
|
282
282
|
render_agent_bar() {
|
|
283
283
|
local PROGRESS="${1:-.}/.harness/progress.json"
|
|
284
284
|
local CONFIG="${1:-.}/.harness/config.json"
|
|
285
|
+
local PIPELINE_JSON="${1:-.}/.harness/actions/pipeline.json"
|
|
285
286
|
|
|
286
287
|
if [ ! -f "$PROGRESS" ] || [ ! -f "$CONFIG" ]; then return 1; fi
|
|
287
288
|
|
|
288
|
-
local pipeline current_agent
|
|
289
|
+
local pipeline current_agent fe_stack
|
|
289
290
|
pipeline=$(jq -r '.pipeline // "unknown"' "$PROGRESS")
|
|
290
291
|
current_agent=$(jq -r '.current_agent // "none"' "$PROGRESS")
|
|
292
|
+
fe_stack="react"
|
|
293
|
+
if [ -f "$PIPELINE_JSON" ]; then
|
|
294
|
+
fe_stack=$(jq -r '.fe_stack // "react"' "$PIPELINE_JSON" 2>/dev/null || echo "react")
|
|
295
|
+
fi
|
|
291
296
|
|
|
292
297
|
local completed_agents
|
|
293
298
|
completed_agents=$(jq -r '.completed_agents // [] | .[]' "$PROGRESS")
|
|
@@ -299,6 +304,15 @@ render_agent_bar() {
|
|
|
299
304
|
|
|
300
305
|
while IFS= read -r agent; do
|
|
301
306
|
agent=$(echo "$agent" | sed 's/:.*//') # strip mode suffix like :light, :api-only
|
|
307
|
+
|
|
308
|
+
# fe_stack 치환 적용
|
|
309
|
+
if [ "$fe_stack" = "flutter" ]; then
|
|
310
|
+
local sub
|
|
311
|
+
sub=$(jq -r ".flow.pipeline_selection.fe_stack_substitution.flutter[\"${agent}\"] // \"${agent}\"" "$CONFIG" 2>/dev/null)
|
|
312
|
+
if [ "$sub" = "__skip__" ]; then continue; fi
|
|
313
|
+
agent="$sub"
|
|
314
|
+
fi
|
|
315
|
+
|
|
302
316
|
if [ "$first" = true ]; then
|
|
303
317
|
first=false
|
|
304
318
|
else
|
package/scripts/scan-project.sh
CHANGED
|
@@ -61,7 +61,13 @@ elif [ -f "${PROJECT_ROOT}/pom.xml" ] || [ -f "${PROJECT_ROOT}/build.gradle" ];
|
|
|
61
61
|
fi
|
|
62
62
|
|
|
63
63
|
# Frontend
|
|
64
|
-
|
|
64
|
+
# Flutter 우선 감지 — pubspec.yaml 존재하면 Flutter 프로젝트로 판정 (TECH_LANG도 보정)
|
|
65
|
+
FE_STACK="react" # react | flutter (기본값은 react 계열)
|
|
66
|
+
if [ -f "${PROJECT_ROOT}/pubspec.yaml" ] && grep -q "flutter:" "${PROJECT_ROOT}/pubspec.yaml" 2>/dev/null; then
|
|
67
|
+
TECH_FRONTEND="flutter"
|
|
68
|
+
TECH_LANG="dart"
|
|
69
|
+
FE_STACK="flutter"
|
|
70
|
+
elif [ -f "${PROJECT_ROOT}/next.config.js" ] || [ -f "${PROJECT_ROOT}/next.config.ts" ] || [ -f "${PROJECT_ROOT}/next.config.mjs" ]; then
|
|
65
71
|
TECH_FRONTEND="nextjs"
|
|
66
72
|
elif [ -f "${PROJECT_ROOT}/vite.config.ts" ] || [ -f "${PROJECT_ROOT}/vite.config.js" ]; then
|
|
67
73
|
TECH_FRONTEND="vite-react"
|
|
@@ -75,11 +81,26 @@ fi
|
|
|
75
81
|
if [ -d "${PROJECT_ROOT}/apps/web" ]; then
|
|
76
82
|
if [ -f "${PROJECT_ROOT}/apps/web/next.config.js" ] || [ -f "${PROJECT_ROOT}/apps/web/next.config.ts" ]; then
|
|
77
83
|
TECH_FRONTEND="nextjs"
|
|
84
|
+
FE_STACK="react"
|
|
78
85
|
elif [ -f "${PROJECT_ROOT}/apps/web/vite.config.ts" ]; then
|
|
79
86
|
TECH_FRONTEND="vite-react"
|
|
87
|
+
FE_STACK="react"
|
|
80
88
|
fi
|
|
81
89
|
fi
|
|
82
90
|
|
|
91
|
+
# Flutter 서브디렉토리 감지 (monorepo 또는 서브 프로젝트 케이스)
|
|
92
|
+
if [ "$TECH_FRONTEND" = "unknown" ]; then
|
|
93
|
+
# 대표적인 Flutter 서브폴더 이름을 얕게 탐색
|
|
94
|
+
for d in apps/mobile mobile clue_mobile_app flutter_app; do
|
|
95
|
+
if [ -f "${PROJECT_ROOT}/${d}/pubspec.yaml" ] && grep -q "flutter:" "${PROJECT_ROOT}/${d}/pubspec.yaml" 2>/dev/null; then
|
|
96
|
+
TECH_FRONTEND="flutter"
|
|
97
|
+
TECH_LANG="dart"
|
|
98
|
+
FE_STACK="flutter"
|
|
99
|
+
break
|
|
100
|
+
fi
|
|
101
|
+
done
|
|
102
|
+
fi
|
|
103
|
+
|
|
83
104
|
# Database
|
|
84
105
|
if grep -rq "typeorm\|prisma\|sequelize\|knex" "${PROJECT_ROOT}/package.json" 2>/dev/null; then
|
|
85
106
|
if grep -q "pg\|postgres" "${PROJECT_ROOT}/package.json" 2>/dev/null; then
|
|
@@ -203,6 +224,7 @@ cat > "$OUTPUT" << JSONEOF
|
|
|
203
224
|
"tech_stack": {
|
|
204
225
|
"backend": "${TECH_BACKEND}",
|
|
205
226
|
"frontend": "${TECH_FRONTEND}",
|
|
227
|
+
"fe_stack": "${FE_STACK}",
|
|
206
228
|
"database": "${TECH_DB}",
|
|
207
229
|
"monorepo": "${TECH_MONOREPO}",
|
|
208
230
|
"language": "${TECH_LANG}"
|
|
@@ -260,7 +282,7 @@ echo "=== Scan Complete ==="
|
|
|
260
282
|
echo "Output: ${OUTPUT}"
|
|
261
283
|
echo ""
|
|
262
284
|
echo "--- Summary ---"
|
|
263
|
-
echo "Tech Stack: ${TECH_BACKEND} / ${TECH_FRONTEND} / ${TECH_DB}"
|
|
285
|
+
echo "Tech Stack: ${TECH_BACKEND} / ${TECH_FRONTEND} (fe_stack=${FE_STACK}) / ${TECH_DB}"
|
|
264
286
|
echo "Monorepo: ${TECH_MONOREPO}"
|
|
265
287
|
echo "OpenAPI: ${OPENAPI}"
|
|
266
288
|
echo "Git: ${GIT_INIT} (${GIT_COMMITS} commits, branch: ${GIT_BRANCH})"
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: harness-brainstorming
|
|
3
|
+
description: "사용자의 러프한(바이브코딩) 요구사항을 대화형으로 구체화하여 Planner가 바로 쓸 수 있는 디자인/스펙 문서(.harness/actions/brainstorm-spec.md)로 만든다. Dispatcher가 사용자에게 '브레인스토밍 필요?' 라고 확인한 뒤에만 호출된다. 원본: obra/superpowers MIT."
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Brainstormer — 요구사항 구체화 (obra/superpowers 파생)
|
|
8
|
+
|
|
9
|
+
> **Attribution**: 이 스킬의 방법론은 [obra/superpowers](https://github.com/obra/superpowers)
|
|
10
|
+
> (MIT License) 의 `skills/brainstorming` 을 walwal-harness 파이프라인에 맞게 이식한 것입니다.
|
|
11
|
+
> 원본 저자(J. Hubbard 등)에게 감사드립니다. 상세 원본 텍스트 + 라이센스는
|
|
12
|
+
> [references/attribution.md](references/attribution.md) 참조.
|
|
13
|
+
|
|
14
|
+
## 역할
|
|
15
|
+
|
|
16
|
+
walwal-harness 에서 Brainstormer 의 유일한 목적은 **러프한 바이브코딩 아이디어를
|
|
17
|
+
Planner 가 곧바로 plan.md / feature-list.json / api-contract.json 으로 변환할 수 있는
|
|
18
|
+
수준의 fit 한 요구사항 문서**로 구체화하는 것이다. 결과물은 단 하나:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
.harness/actions/brainstorm-spec.md
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
이 파일이 생성되면 Planner 는 이것을 PRD 대체 입력으로 읽는다.
|
|
25
|
+
|
|
26
|
+
## 언제 호출되는가
|
|
27
|
+
|
|
28
|
+
**Dispatcher 가 사용자에게 명시적으로 "브레인스토밍 과정이 필요합니까?" 라고 묻고
|
|
29
|
+
사용자가 승인한 경우에만 실행된다.** 이외의 모든 경로 (피드백, 이터레이션, 직접 에이전트
|
|
30
|
+
명령, Gotcha 교정, 스프린트 retry) 에서는 호출되지 않는다. 사용자가 명확한 PRD 를
|
|
31
|
+
제공하거나 브레인스토밍 불필요를 선언하면 Dispatcher 는 곧바로 `next_agent = planner`
|
|
32
|
+
로 라우팅한다.
|
|
33
|
+
|
|
34
|
+
## Session Boundary Protocol
|
|
35
|
+
|
|
36
|
+
### On Start
|
|
37
|
+
1. `.harness/progress.json` 읽기 — `next_agent == "brainstormer"` 인지 확인
|
|
38
|
+
- 아니면 즉시 STOP + "Dispatcher 를 먼저 실행하세요" 안내
|
|
39
|
+
2. progress.json 업데이트: `current_agent` → `"brainstormer"`, `agent_status` → `"running"`, `updated_at` 갱신
|
|
40
|
+
3. **Skip 조건 검사**: `.harness/actions/brainstorm-spec.md` 가 이미 존재하고
|
|
41
|
+
사용자가 "새로 브레인스토밍" 을 명시하지 않았다면:
|
|
42
|
+
- 사용자에게 "기존 brainstorm-spec.md 가 있습니다. 재사용(Y) / 새로 작성(N)?" 질문
|
|
43
|
+
- Y → 즉시 On Complete 로 이동 (interactive 단계 전부 스킵)
|
|
44
|
+
- N → 기존 파일을 `.harness/archive/brainstorm-spec-<timestamp>.md` 로 이동 후 interactive 시작
|
|
45
|
+
|
|
46
|
+
### On Complete
|
|
47
|
+
1. `.harness/actions/brainstorm-spec.md` 가 존재하고 "User Review Gate" 를 통과했는지 확인
|
|
48
|
+
2. progress.json 업데이트:
|
|
49
|
+
- `agent_status` → `"completed"`
|
|
50
|
+
- `completed_agents` 에 `"brainstormer"` 추가
|
|
51
|
+
- `next_agent` → `"planner"`
|
|
52
|
+
3. `.harness/progress.log` 에 요약 추가: `Brainstormer → Planner (spec: <경로>)`
|
|
53
|
+
4. **STOP. 다음 에이전트를 직접 호출하지 않는다.**
|
|
54
|
+
5. 출력: `"✓ Brainstormer 완료. bash scripts/harness-next.sh 실행하여 Planner 단계로 진행."`
|
|
55
|
+
|
|
56
|
+
### On Fail / Abort
|
|
57
|
+
사용자가 중간에 "중단" / "취소" / "abort" 를 요청하면:
|
|
58
|
+
1. progress.json 업데이트: `agent_status` → `"blocked"`, `failure.message` → `"user aborted brainstorming"`
|
|
59
|
+
2. 작성 중이던 `brainstorm-spec.md` 는 `.harness/archive/brainstorm-spec-draft-<timestamp>.md` 로 이동
|
|
60
|
+
3. **STOP**. 사용자에게 "재시작 원하면 'dispatcher 다시'" 안내
|
|
61
|
+
|
|
62
|
+
## HARD-GATE (원본에서 계승)
|
|
63
|
+
|
|
64
|
+
> **Planner / Generator / 어떤 구현 에이전트도 호출하지 말라. 사용자가 "이 디자인 승인한다" 고
|
|
65
|
+
> 명시적으로 말하기 전까지는 brainstorm-spec.md 를 저장하지도 않는다.**
|
|
66
|
+
|
|
67
|
+
아무리 간단해 보이는 프로젝트라도 이 게이트를 건너뛰지 않는다. "Simple" 한 프로젝트가
|
|
68
|
+
오히려 검증되지 않은 가정 때문에 가장 많은 시간을 낭비시킨다.
|
|
69
|
+
|
|
70
|
+
## 체크리스트 (Brainstormer 내부 워크플로우)
|
|
71
|
+
|
|
72
|
+
각 항목을 **순서대로** 수행하고 각 단계 끝에서 사용자 확인을 받는다:
|
|
73
|
+
|
|
74
|
+
1. **프로젝트 컨텍스트 탐색** — 기존 파일, docs, 최근 커밋, `AGENTS.md`, `.harness/actions/`
|
|
75
|
+
2. **Visual Companion 제안** (시각 요소가 많을 예정이라면, 단일 메시지로) — [visual-companion 가이드](references/visual-companion.md)
|
|
76
|
+
3. **명확화 질문** — 한 번에 **하나씩**, 목적/제약/성공 기준 파악 (가능하면 객관식)
|
|
77
|
+
4. **스코프 점검** — 여러 독립 서브시스템이 섞여 있으면 먼저 분할 제안 (예: "플랫폼 A + 채팅 + 결제" → 먼저 A 만)
|
|
78
|
+
5. **2~3 개 접근법 제시** — 각 접근의 장단점 + 추천안 + 추천 이유
|
|
79
|
+
6. **디자인 섹션별 제시** — 복잡도에 맞춰 섹션별 길이 조절, 각 섹션 끝에 사용자 확인
|
|
80
|
+
- 아키텍처, 컴포넌트, 데이터 흐름, 에러 처리, 테스트
|
|
81
|
+
7. **사용자 디자인 승인** 받기
|
|
82
|
+
8. **brainstorm-spec.md 저장** — `.harness/actions/brainstorm-spec.md` 에 커밋 (아래 스펙 포맷)
|
|
83
|
+
9. **Spec Self-Review** — 플레이스홀더, 모순, 애매성, 스코프, YAGNI 체크. 발견 시 inline 수정
|
|
84
|
+
상세 → [spec-document-reviewer-prompt.md](references/spec-document-reviewer-prompt.md)
|
|
85
|
+
10. **User Review Gate** — 사용자에게 작성된 파일을 리뷰 요청. 변경 요청 시 → 8번으로 복귀
|
|
86
|
+
11. **Planner 로 핸드오프** — Session Boundary Protocol On Complete 실행
|
|
87
|
+
|
|
88
|
+
## 핵심 원칙 (원본 계승)
|
|
89
|
+
|
|
90
|
+
- **한 번에 한 질문** — 질문 폭탄 금지
|
|
91
|
+
- **객관식 우선** — 가능하면 A/B/C/D 형태로
|
|
92
|
+
- **YAGNI** — 요청되지 않은 기능은 전부 제거
|
|
93
|
+
- **대안 탐색** — 결정하기 전에 항상 2-3 개 접근법 제시
|
|
94
|
+
- **점진적 검증** — 섹션별로 제시하고 승인 후 다음
|
|
95
|
+
- **유연성** — 중간에 "이건 안 맞는 것 같아" 가 나오면 언제든 이전 단계로 복귀
|
|
96
|
+
|
|
97
|
+
## 출력 포맷: `.harness/actions/brainstorm-spec.md`
|
|
98
|
+
|
|
99
|
+
```markdown
|
|
100
|
+
---
|
|
101
|
+
docmeta:
|
|
102
|
+
id: brainstorm-spec
|
|
103
|
+
title: Brainstorm Spec — <프로젝트/기능 이름>
|
|
104
|
+
type: output
|
|
105
|
+
createdAt: <ISO 8601>
|
|
106
|
+
updatedAt: <ISO 8601>
|
|
107
|
+
source:
|
|
108
|
+
producer: agent
|
|
109
|
+
skillId: harness-brainstorming
|
|
110
|
+
inputs:
|
|
111
|
+
- documentId: user-conversation
|
|
112
|
+
uri: (inline — 사용자와의 대화 전체)
|
|
113
|
+
relation: output-from
|
|
114
|
+
tags: [brainstorming, spec, planner-input]
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
# Brainstorm Spec — <프로젝트/기능 이름>
|
|
118
|
+
|
|
119
|
+
## 1. 목적 (Purpose)
|
|
120
|
+
<무엇을, 왜 만드는가 — 1-2 문단>
|
|
121
|
+
|
|
122
|
+
## 2. 성공 기준 (Success Criteria)
|
|
123
|
+
- [ ] ...
|
|
124
|
+
- [ ] ...
|
|
125
|
+
|
|
126
|
+
## 3. 스코프 (Scope)
|
|
127
|
+
### In
|
|
128
|
+
- ...
|
|
129
|
+
### Out (명시적 제외)
|
|
130
|
+
- ...
|
|
131
|
+
|
|
132
|
+
## 4. 제약 (Constraints)
|
|
133
|
+
- 기술 스택:
|
|
134
|
+
- 성능:
|
|
135
|
+
- 보안/컴플라이언스:
|
|
136
|
+
- 기타:
|
|
137
|
+
|
|
138
|
+
## 5. 선택된 접근법 (Chosen Approach)
|
|
139
|
+
<2-3 개 대안 중 사용자가 승인한 것 + 이유>
|
|
140
|
+
|
|
141
|
+
### 고려했던 대안
|
|
142
|
+
- **Alt A**: ... (장/단점)
|
|
143
|
+
- **Alt B**: ... (장/단점)
|
|
144
|
+
|
|
145
|
+
## 6. 아키텍처 스케치
|
|
146
|
+
<구성요소 + 상호작용 — ASCII 다이어그램 또는 간단한 설명>
|
|
147
|
+
|
|
148
|
+
## 7. 주요 컴포넌트 / 엔티티
|
|
149
|
+
- Component A — 책임:
|
|
150
|
+
- Entity X — 필드/관계:
|
|
151
|
+
|
|
152
|
+
## 8. 데이터 흐름 (Data Flow)
|
|
153
|
+
<입력 → 처리 → 출력 → 저장 경로>
|
|
154
|
+
|
|
155
|
+
## 9. 에러 처리 전략
|
|
156
|
+
- 경계 에러:
|
|
157
|
+
- 내부 에러:
|
|
158
|
+
- 사용자 노출 메시지:
|
|
159
|
+
|
|
160
|
+
## 10. 테스트 전략 (High-level)
|
|
161
|
+
- Unit:
|
|
162
|
+
- Integration:
|
|
163
|
+
- E2E:
|
|
164
|
+
|
|
165
|
+
## 11. Open Questions (Planner 가 확정할 것)
|
|
166
|
+
- Q1: ...
|
|
167
|
+
- Q2: ...
|
|
168
|
+
|
|
169
|
+
## 12. 사용자 승인 로그
|
|
170
|
+
- YYYY-MM-DD HH:MM — 섹션 <N> 승인 ("네, 좋아요")
|
|
171
|
+
- YYYY-MM-DD HH:MM — 디자인 전체 승인
|
|
172
|
+
- YYYY-MM-DD HH:MM — 작성 스펙 파일 리뷰 통과
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Planner 와의 인터페이스
|
|
176
|
+
|
|
177
|
+
Planner 는 On Start 에 이 파일을 읽고:
|
|
178
|
+
|
|
179
|
+
1. `1. 목적`, `2. 성공 기준`, `3. 스코프` → `plan.md` 의 사양서 도입부로 직접 반영
|
|
180
|
+
2. `5. 선택된 접근법`, `6. 아키텍처 스케치` → MSA 서비스 분할 (full 모드) 또는 컴포넌트 설계의 베이스
|
|
181
|
+
3. `7. 주요 컴포넌트 / 엔티티` → `feature-list.json` 초기 feature 목록 시드
|
|
182
|
+
4. `11. Open Questions` → Planner 가 해소 (API 계약으로 확정)
|
|
183
|
+
|
|
184
|
+
Planner 는 brainstorm-spec.md 에 있는 **승인된 결정** 을 뒤엎지 않는다. 필요한 경우
|
|
185
|
+
`## Change Request` 섹션을 추가해 Dispatcher 를 통한 재논의 요청.
|
|
186
|
+
|
|
187
|
+
## 금지 사항
|
|
188
|
+
|
|
189
|
+
- `brainstorm-spec.md` 승인 전에 `plan.md`, `feature-list.json`, `api-contract.json` 작성
|
|
190
|
+
- 코드 작성 / scaffolding / 파일 생성 (scripts/visual-companion 제외)
|
|
191
|
+
- 여러 질문을 한 메시지에 몰아 넣기
|
|
192
|
+
- 사용자 승인 없이 임의로 다음 섹션으로 진행
|
|
193
|
+
- `.harness/archive/` 쓰기 금지 원칙 위반 (skip/abort 시 draft 이동 외에는 금지)
|
|
194
|
+
|
|
195
|
+
## 참고
|
|
196
|
+
|
|
197
|
+
- 원본 방법론 + 라이센스 → [references/attribution.md](references/attribution.md)
|
|
198
|
+
- Visual Companion (브라우저 기반 목업/다이어그램 서버) → [references/visual-companion.md](references/visual-companion.md)
|
|
199
|
+
- Spec self-review 상세 → [references/spec-document-reviewer-prompt.md](references/spec-document-reviewer-prompt.md)
|
|
200
|
+
- Visual Companion 실행 스크립트 → `scripts/start-server.sh` (실행은 선택)
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
docmeta:
|
|
3
|
+
id: brainstorming-attribution
|
|
4
|
+
title: Brainstorming Skill — Attribution & Original Source
|
|
5
|
+
type: output
|
|
6
|
+
createdAt: 2026-04-09T00:00:00Z
|
|
7
|
+
updatedAt: 2026-04-09T00:00:00Z
|
|
8
|
+
source:
|
|
9
|
+
producer: agent
|
|
10
|
+
skillId: harness-brainstorming
|
|
11
|
+
inputs:
|
|
12
|
+
- documentId: obra-superpowers-brainstorming-skill
|
|
13
|
+
uri: https://github.com/obra/superpowers/blob/main/skills/brainstorming/SKILL.md
|
|
14
|
+
relation: output-from
|
|
15
|
+
sections:
|
|
16
|
+
- sourceRange:
|
|
17
|
+
startLine: 1
|
|
18
|
+
endLine: 165
|
|
19
|
+
targetRange:
|
|
20
|
+
startLine: 21
|
|
21
|
+
endLine: 32
|
|
22
|
+
- sourceRange:
|
|
23
|
+
startLine: 29
|
|
24
|
+
endLine: 33
|
|
25
|
+
targetRange:
|
|
26
|
+
startLine: 36
|
|
27
|
+
endLine: 42
|
|
28
|
+
- sourceRange:
|
|
29
|
+
startLine: 12
|
|
30
|
+
endLine: 18
|
|
31
|
+
targetRange:
|
|
32
|
+
startLine: 55
|
|
33
|
+
endLine: 62
|
|
34
|
+
- documentId: obra-superpowers-spec-reviewer
|
|
35
|
+
uri: https://github.com/obra/superpowers/blob/main/skills/brainstorming/spec-document-reviewer-prompt.md
|
|
36
|
+
relation: output-from
|
|
37
|
+
sections:
|
|
38
|
+
- sourceRange:
|
|
39
|
+
startLine: 1
|
|
40
|
+
endLine: 50
|
|
41
|
+
targetRange:
|
|
42
|
+
startLine: 23
|
|
43
|
+
endLine: 24
|
|
44
|
+
- documentId: obra-superpowers-visual-companion
|
|
45
|
+
uri: https://github.com/obra/superpowers/blob/main/skills/brainstorming/visual-companion.md
|
|
46
|
+
relation: output-from
|
|
47
|
+
sections:
|
|
48
|
+
- sourceRange:
|
|
49
|
+
startLine: 1
|
|
50
|
+
endLine: 287
|
|
51
|
+
targetRange:
|
|
52
|
+
startLine: 25
|
|
53
|
+
endLine: 27
|
|
54
|
+
tags: [attribution, license, mit, obra-superpowers]
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
# Attribution — obra/superpowers brainstorming skill
|
|
58
|
+
|
|
59
|
+
walwal-harness 의 `harness-brainstorming` 스킬은 아래 원본을 기반으로
|
|
60
|
+
파이프라인 통합(Session Boundary Protocol, Planner 인터페이스, 출력 경로 등)을
|
|
61
|
+
추가한 파생 저작물입니다.
|
|
62
|
+
|
|
63
|
+
## 원본
|
|
64
|
+
|
|
65
|
+
- **Repo**: [obra/superpowers](https://github.com/obra/superpowers)
|
|
66
|
+
- **Path**: `skills/brainstorming/`
|
|
67
|
+
- **Files reused**:
|
|
68
|
+
- `SKILL.md` — 방법론 (HARD-GATE, 한 번에 한 질문, 2-3 접근법, spec self-review)
|
|
69
|
+
- `spec-document-reviewer-prompt.md` — spec 리뷰 서브에이전트 프롬프트 템플릿
|
|
70
|
+
- `visual-companion.md` — 브라우저 기반 시각 도우미 가이드
|
|
71
|
+
- `scripts/frame-template.html`, `helper.js`, `server.cjs`, `start-server.sh`, `stop-server.sh` — visual companion 서버 구현
|
|
72
|
+
- **License**: MIT License
|
|
73
|
+
|
|
74
|
+
## 변경점 (walwal-harness 통합)
|
|
75
|
+
|
|
76
|
+
1. **Session Boundary Protocol 추가** — On Start / On Complete / On Fail 프로토콜로
|
|
77
|
+
harness 다중 에이전트 흐름에 맞춤
|
|
78
|
+
2. **Terminal state 변경** — 원본의 "invoke writing-plans skill" → "hand off to
|
|
79
|
+
harness-planner"
|
|
80
|
+
3. **출력 경로 변경** — 원본의 `docs/superpowers/specs/YYYY-MM-DD-<topic>-design.md`
|
|
81
|
+
→ `.harness/actions/brainstorm-spec.md` (Planner 의 입력 위치)
|
|
82
|
+
4. **출력 포맷 변경** — walwal-harness docmeta 프론트매터 + Planner 가 사용하는
|
|
83
|
+
12 개 섹션 (목적/성공기준/스코프/제약/접근법/아키텍처/컴포넌트/데이터흐름/
|
|
84
|
+
에러처리/테스트전략/Open Questions/승인로그) 로 구조화
|
|
85
|
+
5. **조건부 호출** — 원본은 "모든 창작 작업 전 필수" 였으나, harness 에서는 Dispatcher 가
|
|
86
|
+
사용자에게 "브레인스토밍 필요?" 확인 후에만 호출 (피드백/이터레이션 케이스에서
|
|
87
|
+
피로 최소화)
|
|
88
|
+
6. **Skip 로직** — 기존 brainstorm-spec.md 존재 시 재사용 여부 확인
|
|
89
|
+
|
|
90
|
+
## 보존된 핵심
|
|
91
|
+
|
|
92
|
+
- HARD-GATE (구현 전 디자인 필수)
|
|
93
|
+
- "Too simple to need a design" 안티패턴 경고
|
|
94
|
+
- 한 번에 한 질문 원칙
|
|
95
|
+
- 객관식 우선
|
|
96
|
+
- 2-3 개 접근법 탐색
|
|
97
|
+
- YAGNI
|
|
98
|
+
- Spec self-review loop
|
|
99
|
+
- User review gate
|
|
100
|
+
- Visual Companion 옵션
|
|
101
|
+
|
|
102
|
+
## MIT License
|
|
103
|
+
|
|
104
|
+
원본 저장소 [obra/superpowers](https://github.com/obra/superpowers) 의 MIT License
|
|
105
|
+
전문은 아래 링크에서 확인할 수 있습니다:
|
|
106
|
+
https://github.com/obra/superpowers/blob/main/LICENSE
|
|
107
|
+
|
|
108
|
+
MIT License 하에 원본 저작권 표시 및 라이센스 고지 의무를 이 파일로 대체합니다.
|
|
109
|
+
파생물 배포 시에도 이 attribution 파일을 유지해야 합니다.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Spec Document Reviewer Prompt Template
|
|
2
|
+
|
|
3
|
+
Use this template when dispatching a spec document reviewer subagent.
|
|
4
|
+
|
|
5
|
+
**Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
|
|
6
|
+
|
|
7
|
+
**Dispatch after:** Spec document is written to docs/superpowers/specs/
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Task tool (general-purpose):
|
|
11
|
+
description: "Review spec document"
|
|
12
|
+
prompt: |
|
|
13
|
+
You are a spec document reviewer. Verify this spec is complete and ready for planning.
|
|
14
|
+
|
|
15
|
+
**Spec to review:** [SPEC_FILE_PATH]
|
|
16
|
+
|
|
17
|
+
## What to Check
|
|
18
|
+
|
|
19
|
+
| Category | What to Look For |
|
|
20
|
+
|----------|------------------|
|
|
21
|
+
| Completeness | TODOs, placeholders, "TBD", incomplete sections |
|
|
22
|
+
| Consistency | Internal contradictions, conflicting requirements |
|
|
23
|
+
| Clarity | Requirements ambiguous enough to cause someone to build the wrong thing |
|
|
24
|
+
| Scope | Focused enough for a single plan — not covering multiple independent subsystems |
|
|
25
|
+
| YAGNI | Unrequested features, over-engineering |
|
|
26
|
+
|
|
27
|
+
## Calibration
|
|
28
|
+
|
|
29
|
+
**Only flag issues that would cause real problems during implementation planning.**
|
|
30
|
+
A missing section, a contradiction, or a requirement so ambiguous it could be
|
|
31
|
+
interpreted two different ways — those are issues. Minor wording improvements,
|
|
32
|
+
stylistic preferences, and "sections less detailed than others" are not.
|
|
33
|
+
|
|
34
|
+
Approve unless there are serious gaps that would lead to a flawed plan.
|
|
35
|
+
|
|
36
|
+
## Output Format
|
|
37
|
+
|
|
38
|
+
## Spec Review
|
|
39
|
+
|
|
40
|
+
**Status:** Approved | Issues Found
|
|
41
|
+
|
|
42
|
+
**Issues (if any):**
|
|
43
|
+
- [Section X]: [specific issue] - [why it matters for planning]
|
|
44
|
+
|
|
45
|
+
**Recommendations (advisory, do not block approval):**
|
|
46
|
+
- [suggestions for improvement]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Reviewer returns:** Status, Issues (if any), Recommendations
|