@walwal-harness/cli 6.0.4 → 6.0.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.
- package/CHANGELOG.md +21 -0
- package/bin/init.js +121 -4
- package/package.json +1 -1
- package/scripts/harness-archive.sh +0 -109
- package/scripts/harness-dashboard-up.sh +0 -72
- package/scripts/harness-dashboard.sh +0 -509
- package/scripts/harness-goal-init.sh +0 -72
- package/scripts/harness-goal-show.sh +0 -37
- package/scripts/harness-gotcha-memory.sh +0 -348
- package/scripts/harness-gotcha-register.sh +0 -393
- package/scripts/harness-monitor.sh +0 -398
- package/scripts/harness-next.sh +0 -546
- package/scripts/harness-progress-set.sh +0 -41
- package/scripts/harness-prompt-history.sh +0 -164
- package/scripts/harness-queue-manager.sh +0 -694
- package/scripts/harness-session-start.sh +0 -129
- package/scripts/harness-statusline.sh +0 -139
- package/scripts/harness-tmux.sh +0 -372
- package/scripts/harness-user-prompt-submit.sh +0 -105
- package/scripts/init-agents-md.sh +0 -337
- package/scripts/init-ref-docs.sh +0 -262
- package/scripts/lib/harness-audit.sh +0 -113
- package/scripts/lib/harness-guardrail.sh +0 -148
- package/scripts/lib/harness-keywait.sh +0 -57
- package/scripts/lib/harness-render-progress.sh +0 -346
- package/scripts/scan-project.sh +0 -367
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# harness-user-prompt-submit.sh — UserPromptSubmit hook (v5 unified)
|
|
3
|
-
# 핵심 상태 + 라우팅 지시만 주입. Solo/Team 통합.
|
|
4
|
-
set -e
|
|
5
|
-
|
|
6
|
-
INPUT=$(cat)
|
|
7
|
-
CWD=$(echo "$INPUT" | jq -r '.cwd // empty' 2>/dev/null || true)
|
|
8
|
-
if [ -z "$CWD" ]; then CWD="$PWD"; fi
|
|
9
|
-
|
|
10
|
-
# 조건 1: 하네스 초기화 확인
|
|
11
|
-
if [ ! -f "$CWD/.harness/config.json" ]; then exit 0; fi
|
|
12
|
-
|
|
13
|
-
# 조건 2: opt-out 플래그 확인
|
|
14
|
-
AUTO_ROUTE="true"
|
|
15
|
-
if command -v jq >/dev/null 2>&1; then
|
|
16
|
-
AUTO_ROUTE=$(jq -r '.behavior.auto_route_dispatcher // true' "$CWD/.harness/config.json" 2>/dev/null || echo "true")
|
|
17
|
-
fi
|
|
18
|
-
if [ "$AUTO_ROUTE" != "true" ]; then exit 0; fi
|
|
19
|
-
|
|
20
|
-
# 사용자 skip 감지
|
|
21
|
-
PROMPT=$(echo "$INPUT" | jq -r '.prompt // empty' 2>/dev/null || true)
|
|
22
|
-
if echo "$PROMPT" | grep -qiE "harness\s*(skip|off|bypass|없이)|without\s*harness|just\s*(answer|chat|reply)"; then
|
|
23
|
-
exit 0
|
|
24
|
-
fi
|
|
25
|
-
|
|
26
|
-
# 현재 세션 상태 읽기
|
|
27
|
-
PIPELINE="none"; CURRENT_AGENT="none"; NEXT_AGENT="none"
|
|
28
|
-
SPRINT_NUM="0"; SPRINT_STATUS="init"; AGENT_STATUS="pending"
|
|
29
|
-
|
|
30
|
-
if [ -f "$CWD/.harness/progress.json" ] && command -v jq >/dev/null 2>&1; then
|
|
31
|
-
PIPELINE=$(jq -r '.pipeline // "none"' "$CWD/.harness/progress.json" 2>/dev/null || echo "none")
|
|
32
|
-
CURRENT_AGENT=$(jq -r '.current_agent // "none"' "$CWD/.harness/progress.json" 2>/dev/null || echo "none")
|
|
33
|
-
NEXT_AGENT=$(jq -r '.next_agent // "none"' "$CWD/.harness/progress.json" 2>/dev/null || echo "none")
|
|
34
|
-
SPRINT_NUM=$(jq -r '.sprint.number // 0' "$CWD/.harness/progress.json" 2>/dev/null || echo "0")
|
|
35
|
-
SPRINT_STATUS=$(jq -r '.sprint.status // "init"' "$CWD/.harness/progress.json" 2>/dev/null || echo "init")
|
|
36
|
-
AGENT_STATUS=$(jq -r '.agent_status // "pending"' "$CWD/.harness/progress.json" 2>/dev/null || echo "pending")
|
|
37
|
-
fi
|
|
38
|
-
|
|
39
|
-
# ── 명령 히스토리 기록 (모든 모드 공통) ──
|
|
40
|
-
PROGRESS_LOG="$CWD/.harness/progress.log"
|
|
41
|
-
if [ -n "$PROMPT" ] && [ -d "$CWD/.harness" ]; then
|
|
42
|
-
# progress.log가 없으면 생성
|
|
43
|
-
if [ ! -f "$PROGRESS_LOG" ]; then
|
|
44
|
-
echo "# Harness Command History — $(date +%Y-%m-%d)" > "$PROGRESS_LOG"
|
|
45
|
-
fi
|
|
46
|
-
PROMPT_SHORT=$(echo "$PROMPT" | tr '\n' ' ' | sed 's/ */ /g' | cut -c1-80)
|
|
47
|
-
if [ ${#PROMPT_SHORT} -gt 2 ]; then
|
|
48
|
-
echo "$(date +"%Y-%m-%d %H:%M") | user-prompt | input | ${PROMPT_SHORT}" >> "$PROGRESS_LOG"
|
|
49
|
-
fi
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
# ── 컨텍스트 분리 가드레일 ──
|
|
53
|
-
# 현재 에이전트가 활성인데 다른 에이전트 스킬을 호출하려는 경우 경고
|
|
54
|
-
CONTEXT_WARNING=""
|
|
55
|
-
if [ "$CURRENT_AGENT" != "none" ] && [ "$CURRENT_AGENT" != "null" ] && [ "$AGENT_STATUS" = "running" ]; then
|
|
56
|
-
# 프롬프트에서 /harness-* 패턴 추출
|
|
57
|
-
REQUESTED_SKILL=$(echo "$PROMPT" | grep -oE '/harness-[a-z-]+' | head -1 | sed 's|/harness-||')
|
|
58
|
-
if [ -n "$REQUESTED_SKILL" ] && [ "$REQUESTED_SKILL" != "$CURRENT_AGENT" ]; then
|
|
59
|
-
CONTEXT_WARNING="
|
|
60
|
-
## !! Context Isolation Warning !!
|
|
61
|
-
current_agent=${CURRENT_AGENT} (running) 인데 /harness-${REQUESTED_SKILL} 호출 감지.
|
|
62
|
-
한 세션에서 다른 에이전트를 실행하면 컨텍스트가 오염됩니다.
|
|
63
|
-
현재 에이전트를 먼저 완료(completed)하거나, 새 세션을 시작하세요."
|
|
64
|
-
fi
|
|
65
|
-
fi
|
|
66
|
-
|
|
67
|
-
# ── Mode 기반 분기 ──
|
|
68
|
-
MODE="solo"
|
|
69
|
-
if [ -f "$CWD/.harness/progress.json" ] && command -v jq >/dev/null 2>&1; then
|
|
70
|
-
MODE=$(jq -r '.mode // "solo"' "$CWD/.harness/progress.json" 2>/dev/null || echo "solo")
|
|
71
|
-
fi
|
|
72
|
-
|
|
73
|
-
if [ "$MODE" = "team" ]; then
|
|
74
|
-
FEATURE_QUEUE="$CWD/.harness/actions/feature-queue.json"
|
|
75
|
-
T_PASSED=0; T_TOTAL=0; T_FAILED=0
|
|
76
|
-
if [ -f "$FEATURE_QUEUE" ]; then
|
|
77
|
-
T_PASSED=$(jq '.queue.passed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
78
|
-
T_TOTAL=$(jq '[.queue.ready, (.queue.blocked | keys), (.queue.in_progress | keys), .queue.passed, .queue.failed] | flatten | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
79
|
-
T_FAILED=$(jq '.queue.failed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
80
|
-
fi
|
|
81
|
-
|
|
82
|
-
cat <<EOF
|
|
83
|
-
[harness] team | ${T_PASSED}/${T_TOTAL} passed | ${T_FAILED} failed
|
|
84
|
-
|
|
85
|
-
## Team Mode Active
|
|
86
|
-
- 3 Agent Teams이 자율적으로 Gen→Eval 루프 실행 중 (max 5 retries)
|
|
87
|
-
- 역할: 모니터링, 실패 대응, 수동 개입
|
|
88
|
-
- /harness-stop → 중단 | /harness-solo → Solo 전환
|
|
89
|
-
- skip: "harness skip" 시 일반 대화
|
|
90
|
-
EOF
|
|
91
|
-
exit 0
|
|
92
|
-
fi
|
|
93
|
-
|
|
94
|
-
# ── Compact context 주입 (solo/paused mode) ──
|
|
95
|
-
cat <<EOF
|
|
96
|
-
[harness] S${SPRINT_NUM} | ${PIPELINE} | agent=${CURRENT_AGENT} (${AGENT_STATUS}) | next=${NEXT_AGENT}
|
|
97
|
-
${CONTEXT_WARNING}
|
|
98
|
-
## Route
|
|
99
|
-
- pipeline=none/dispatcher 미실행 → harness-dispatcher 스킬 호출
|
|
100
|
-
- 기능 요청 → pipeline flow | 실수 지적 → gotcha flow | 메타 질문 → 짧게 응답 (skip)
|
|
101
|
-
- 활성 pipeline → next_agent/current_agent 컨텍스트로 계속
|
|
102
|
-
- skip: "harness skip", "just answer" 등 명시 시 단일 메시지 건너뜀
|
|
103
|
-
EOF
|
|
104
|
-
|
|
105
|
-
exit 0
|
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# init-agents-md.sh — scan-result.json을 기반으로 AGENTS.md를 생성/리빌드
|
|
3
|
-
# 기존 CLAUDE.md의 사용자 규칙을 보존하면서 하네스 포맷으로 변환
|
|
4
|
-
set -e
|
|
5
|
-
|
|
6
|
-
PROJECT_ROOT="${1:-.}"
|
|
7
|
-
SCAN_RESULT="${PROJECT_ROOT}/.harness/actions/scan-result.json"
|
|
8
|
-
export SCAN_RESULT PROJECT_ROOT
|
|
9
|
-
AGENTS_FILE="${PROJECT_ROOT}/AGENTS.md"
|
|
10
|
-
CLAUDE_FILE="${PROJECT_ROOT}/CLAUDE.md"
|
|
11
|
-
BACKUP_DIR="${PROJECT_ROOT}/.harness/archive/pre-harness-backup"
|
|
12
|
-
|
|
13
|
-
if [ ! -f "$SCAN_RESULT" ]; then
|
|
14
|
-
echo "ERROR: scan-result.json not found. Run scan-project.sh first."
|
|
15
|
-
exit 1
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
# ─────────────────────────────────────────
|
|
19
|
-
# 1. Python으로 scan-result.json 파싱
|
|
20
|
-
# ─────────────────────────────────────────
|
|
21
|
-
eval "$(python3 << 'PYEOF'
|
|
22
|
-
import json, sys, os
|
|
23
|
-
|
|
24
|
-
with open(os.environ.get("SCAN_RESULT", ".harness/actions/scan-result.json")) as f:
|
|
25
|
-
scan = json.load(f)
|
|
26
|
-
|
|
27
|
-
docs = scan["existing_docs"]
|
|
28
|
-
tech = scan["tech_stack"]
|
|
29
|
-
rec = scan["recommendation"]
|
|
30
|
-
dirs = scan["structure"]["directories"]
|
|
31
|
-
configs = scan["structure"]["config_files"]
|
|
32
|
-
|
|
33
|
-
print(f'ACTION="{rec["agents_md_action"]}"')
|
|
34
|
-
print(f'PROJECT_TYPE="{rec["project_type"]}"')
|
|
35
|
-
print(f'TECH_BE="{tech["backend"]}"')
|
|
36
|
-
print(f'TECH_FE="{tech["frontend"]}"')
|
|
37
|
-
print(f'TECH_DB="{tech["database"]}"')
|
|
38
|
-
print(f'TECH_MONO="{tech["monorepo"]}"')
|
|
39
|
-
print(f'OPENAPI="{scan["api"]["openapi_spec"]}"')
|
|
40
|
-
print(f'HAS_EXISTING_CLAUDE="{docs["claude_md"]}"')
|
|
41
|
-
print(f'EXISTING_CONTENT={json.dumps(docs["existing_claude_md_content"])}')
|
|
42
|
-
PYEOF
|
|
43
|
-
)"
|
|
44
|
-
|
|
45
|
-
echo "=== AGENTS.md Initialization ==="
|
|
46
|
-
echo "Action: ${ACTION}"
|
|
47
|
-
echo "Project Type: ${PROJECT_TYPE}"
|
|
48
|
-
echo ""
|
|
49
|
-
|
|
50
|
-
# ─────────────────────────────────────────
|
|
51
|
-
# 2. 기존 문서 백업
|
|
52
|
-
# ─────────────────────────────────────────
|
|
53
|
-
if [ "$ACTION" = "migrate-claude-to-agents" ] || [ "$ACTION" = "rebuild-with-harness" ]; then
|
|
54
|
-
mkdir -p "$BACKUP_DIR"
|
|
55
|
-
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
56
|
-
|
|
57
|
-
if [ -f "$AGENTS_FILE" ] && [ ! -L "$AGENTS_FILE" ]; then
|
|
58
|
-
cp "$AGENTS_FILE" "${BACKUP_DIR}/AGENTS.md.${TIMESTAMP}.bak"
|
|
59
|
-
echo "Backed up: AGENTS.md → ${BACKUP_DIR}/AGENTS.md.${TIMESTAMP}.bak"
|
|
60
|
-
fi
|
|
61
|
-
|
|
62
|
-
if [ -f "$CLAUDE_FILE" ] && [ ! -L "$CLAUDE_FILE" ]; then
|
|
63
|
-
cp "$CLAUDE_FILE" "${BACKUP_DIR}/CLAUDE.md.${TIMESTAMP}.bak"
|
|
64
|
-
echo "Backed up: CLAUDE.md → ${BACKUP_DIR}/CLAUDE.md.${TIMESTAMP}.bak"
|
|
65
|
-
fi
|
|
66
|
-
fi
|
|
67
|
-
|
|
68
|
-
# ─────────────────────────────────────────
|
|
69
|
-
# 3. IA-MAP 자동 생성
|
|
70
|
-
# ─────────────────────────────────────────
|
|
71
|
-
generate_ia_map() {
|
|
72
|
-
python3 << 'PYEOF'
|
|
73
|
-
import json, os
|
|
74
|
-
|
|
75
|
-
with open(os.environ.get("SCAN_RESULT", ".harness/actions/scan-result.json")) as f:
|
|
76
|
-
scan = json.load(f)
|
|
77
|
-
|
|
78
|
-
dirs = scan["structure"]["directories"]
|
|
79
|
-
tech = scan["tech_stack"]
|
|
80
|
-
|
|
81
|
-
# 경로별 태그/설명 추론 규칙
|
|
82
|
-
tag_rules = {
|
|
83
|
-
# Backend patterns
|
|
84
|
-
"apps/gateway": ("[BE]", "API Gateway", "Generator-Backend"),
|
|
85
|
-
"apps/service": ("[BE]", "Microservice", "Generator-Backend"),
|
|
86
|
-
"src/controllers": ("[BE]", "API Controllers", "Generator-Backend"),
|
|
87
|
-
"src/services": ("[BE]", "Business Logic", "Generator-Backend"),
|
|
88
|
-
"src/models": ("[BE]", "Data Models", "Generator-Backend"),
|
|
89
|
-
"src/entities": ("[BE]", "DB Entities", "Generator-Backend"),
|
|
90
|
-
"src/modules": ("[BE]", "NestJS Modules", "Generator-Backend"),
|
|
91
|
-
"src/guards": ("[BE]", "Auth Guards", "Generator-Backend"),
|
|
92
|
-
"src/pipes": ("[BE]", "Validation Pipes", "Generator-Backend"),
|
|
93
|
-
"src/interceptors": ("[BE]", "Interceptors", "Generator-Backend"),
|
|
94
|
-
"src/filters": ("[BE]", "Exception Filters", "Generator-Backend"),
|
|
95
|
-
"routers": ("[BE]", "API Routers", "Generator-Backend"),
|
|
96
|
-
"routes": ("[BE]", "API Routes", "Generator-Backend"),
|
|
97
|
-
"middleware": ("[BE]", "Middleware", "Generator-Backend"),
|
|
98
|
-
"migrations": ("[BE]", "DB Migrations", "Generator-Backend"),
|
|
99
|
-
|
|
100
|
-
# Frontend patterns
|
|
101
|
-
"apps/web": ("[FE]", "Frontend App", "Generator-Frontend"),
|
|
102
|
-
"src/components": ("[FE]", "UI Components", "Generator-Frontend"),
|
|
103
|
-
"src/pages": ("[FE]", "Page Routes", "Generator-Frontend"),
|
|
104
|
-
"src/app": ("[FE]", "App Router", "Generator-Frontend"),
|
|
105
|
-
"src/hooks": ("[FE]", "Custom Hooks", "Generator-Frontend"),
|
|
106
|
-
"src/stores": ("[FE]", "State Management", "Generator-Frontend"),
|
|
107
|
-
"src/styles": ("[FE]", "Stylesheets", "Generator-Frontend"),
|
|
108
|
-
"src/api": ("[FE]", "API Client Layer", "Generator-Frontend"),
|
|
109
|
-
"src/lib": ("[FE]", "Utility Library", "Generator-Frontend"),
|
|
110
|
-
"public": ("[FE]", "Static Assets", "Generator-Frontend"),
|
|
111
|
-
|
|
112
|
-
# Shared / Libs
|
|
113
|
-
"libs/shared": ("[BE]", "Shared Libraries", "Generator-Backend"),
|
|
114
|
-
"libs/database": ("[BE]", "Database Module", "Generator-Backend"),
|
|
115
|
-
"libs/common": ("[BE]", "Common Utilities", "Generator-Backend"),
|
|
116
|
-
|
|
117
|
-
# Infra
|
|
118
|
-
"docker": ("[INFRA]", "Docker Configuration", "Planner"),
|
|
119
|
-
".github": ("[INFRA]", "CI/CD Workflows", "Planner"),
|
|
120
|
-
"deploy": ("[INFRA]", "Deployment Scripts", "Planner"),
|
|
121
|
-
"terraform": ("[INFRA]", "Infrastructure as Code", "Planner"),
|
|
122
|
-
"k8s": ("[INFRA]", "Kubernetes Manifests", "Planner"),
|
|
123
|
-
|
|
124
|
-
# Harness
|
|
125
|
-
".harness": ("[HARNESS]", "Harness System", "Planner"),
|
|
126
|
-
|
|
127
|
-
# Tests
|
|
128
|
-
"test": ("[TEST]", "Test Suite", "Evaluator"),
|
|
129
|
-
"tests": ("[TEST]", "Test Suite", "Evaluator"),
|
|
130
|
-
"e2e": ("[TEST]", "E2E Tests", "Evaluator"),
|
|
131
|
-
"__tests__": ("[TEST]", "Unit Tests", "Evaluator"),
|
|
132
|
-
|
|
133
|
-
# Native app patterns (Swift / Kotlin / Rust 등)
|
|
134
|
-
"Sources": ("[FE]", "Native Source Root", "Generator-Frontend"),
|
|
135
|
-
"Tests": ("[TEST]", "Native Test Suite", "Evaluator"),
|
|
136
|
-
"Resources": ("[FE]", "Native Resources", "Generator-Frontend"),
|
|
137
|
-
"android": ("[FE]", "Android Host", "Generator-Frontend"),
|
|
138
|
-
"ios": ("[FE]", "iOS Host", "Generator-Frontend"),
|
|
139
|
-
"macos": ("[FE]", "macOS Host", "Generator-Frontend"),
|
|
140
|
-
"Shared": ("[FE]", "Cross-platform Shared", "Generator-Frontend"),
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
# 디렉토리를 분석
|
|
144
|
-
ia_lines = []
|
|
145
|
-
for d in sorted(dirs):
|
|
146
|
-
if d == "." or not d:
|
|
147
|
-
continue
|
|
148
|
-
|
|
149
|
-
matched = False
|
|
150
|
-
for pattern, (tag, desc, owner) in tag_rules.items():
|
|
151
|
-
if pattern in d:
|
|
152
|
-
depth = d.count("/")
|
|
153
|
-
indent = "│ " * depth
|
|
154
|
-
name = d.split("/")[-1] + "/"
|
|
155
|
-
ia_lines.append(f"{indent}├── {name:<25} # {tag} {desc:<30} → {owner}")
|
|
156
|
-
matched = True
|
|
157
|
-
break
|
|
158
|
-
|
|
159
|
-
if not matched:
|
|
160
|
-
depth = d.count("/")
|
|
161
|
-
if depth <= 1: # 1depth만 미분류 표시
|
|
162
|
-
indent = "│ " * depth
|
|
163
|
-
name = d.split("/")[-1] + "/"
|
|
164
|
-
ia_lines.append(f"{indent}├── {name:<25} # [?] (Planner가 분류 필요) → TBD")
|
|
165
|
-
|
|
166
|
-
for line in ia_lines:
|
|
167
|
-
print(line)
|
|
168
|
-
PYEOF
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
IA_MAP=$(generate_ia_map)
|
|
172
|
-
|
|
173
|
-
# ─────────────────────────────────────────
|
|
174
|
-
# 4. 기존 사용자 규칙 추출 (CLAUDE.md에서)
|
|
175
|
-
# ─────────────────────────────────────────
|
|
176
|
-
extract_user_rules() {
|
|
177
|
-
if [ "$HAS_EXISTING_CLAUDE" = "exists" ]; then
|
|
178
|
-
python3 << 'PYEOF'
|
|
179
|
-
import json, os
|
|
180
|
-
|
|
181
|
-
with open(os.environ.get("SCAN_RESULT", ".harness/actions/scan-result.json")) as f:
|
|
182
|
-
scan = json.load(f)
|
|
183
|
-
|
|
184
|
-
content = scan["existing_docs"]["existing_claude_md_content"]
|
|
185
|
-
|
|
186
|
-
if not content or content.strip() == "":
|
|
187
|
-
print("(기존 규칙 없음)")
|
|
188
|
-
else:
|
|
189
|
-
# 사용자 정의 규칙 영역만 추출 (harness 관련 제외)
|
|
190
|
-
lines = content.split("\n")
|
|
191
|
-
user_section = []
|
|
192
|
-
skip = False
|
|
193
|
-
for line in lines:
|
|
194
|
-
# harness가 생성한 섹션은 제외
|
|
195
|
-
if any(kw in line.lower() for kw in ["ia-map", "ia map", "harness", "## tech stack"]):
|
|
196
|
-
skip = True
|
|
197
|
-
elif line.startswith("## ") and skip:
|
|
198
|
-
skip = False
|
|
199
|
-
|
|
200
|
-
if not skip:
|
|
201
|
-
user_section.append(line)
|
|
202
|
-
|
|
203
|
-
result = "\n".join(user_section).strip()
|
|
204
|
-
if result:
|
|
205
|
-
print(result)
|
|
206
|
-
else:
|
|
207
|
-
print("(기존 규칙 없음)")
|
|
208
|
-
PYEOF
|
|
209
|
-
else
|
|
210
|
-
echo "(기존 규칙 없음)"
|
|
211
|
-
fi
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
USER_RULES=$(extract_user_rules)
|
|
215
|
-
|
|
216
|
-
# ─────────────────────────────────────────
|
|
217
|
-
# 5. AGENTS.md 생성
|
|
218
|
-
# ─────────────────────────────────────────
|
|
219
|
-
cat > "$AGENTS_FILE" << AGENTSEOF
|
|
220
|
-
# AGENTS.md — Project Context for AI Agents
|
|
221
|
-
|
|
222
|
-
> 이 파일은 모든 AI 에이전트(Claude, Cursor, Copilot, Windsurf 등)의 공통 진입점입니다.
|
|
223
|
-
> CLAUDE.md는 이 파일의 심볼릭 링크입니다.
|
|
224
|
-
> Generated by walwal-harness ($(date +%Y-%m-%d))
|
|
225
|
-
|
|
226
|
-
## Project
|
|
227
|
-
|
|
228
|
-
- **Name**: (Planner가 설정)
|
|
229
|
-
- **Description**: (Planner가 설정)
|
|
230
|
-
- **Phase**: INIT
|
|
231
|
-
- **Type**: ${PROJECT_TYPE}
|
|
232
|
-
- **Harness**: \`.harness/HARNESS.md\` 참조
|
|
233
|
-
|
|
234
|
-
## Tech Stack (Auto-detected)
|
|
235
|
-
|
|
236
|
-
- Backend: ${TECH_BE}
|
|
237
|
-
- Frontend: ${TECH_FE}
|
|
238
|
-
- Database: ${TECH_DB}
|
|
239
|
-
- Monorepo: ${TECH_MONO}
|
|
240
|
-
- OpenAPI: ${OPENAPI}
|
|
241
|
-
|
|
242
|
-
## IA-MAP (Information Architecture)
|
|
243
|
-
|
|
244
|
-
> 자동 스캔으로 생성됨. Planner가 검토 후 확정해야 합니다.
|
|
245
|
-
> \`[?]\` 태그는 Planner가 분류해야 하는 미확인 경로입니다.
|
|
246
|
-
|
|
247
|
-
\`\`\`
|
|
248
|
-
/
|
|
249
|
-
${IA_MAP}
|
|
250
|
-
├── AGENTS.md # [META] 프로젝트 컨텍스트 → Planner
|
|
251
|
-
├── CLAUDE.md # [META] → AGENTS.md 심볼릭 링크
|
|
252
|
-
└── .harness/ # [HARNESS] 하네스 시스템 → Planner
|
|
253
|
-
\`\`\`
|
|
254
|
-
|
|
255
|
-
### IA-MAP 범례
|
|
256
|
-
|
|
257
|
-
| 태그 | 의미 | 소유 에이전트 |
|
|
258
|
-
|------|------|--------------|
|
|
259
|
-
| \`[BE]\` | Backend 영역 | Generator-Backend |
|
|
260
|
-
| \`[FE]\` | Frontend 영역 | Generator-Frontend |
|
|
261
|
-
| \`[HARNESS]\` | 하네스 시스템 | Planner / Evaluator |
|
|
262
|
-
| \`[META]\` | 프로젝트 메타 문서 | Planner |
|
|
263
|
-
| \`[INFRA]\` | 인프라/배포 설정 | Planner |
|
|
264
|
-
| \`[TEST]\` | 테스트 코드 | Evaluator / Generator |
|
|
265
|
-
| \`[?]\` | 미분류 (Planner 확인 필요) | TBD |
|
|
266
|
-
|
|
267
|
-
## Preserved Rules (기존 프로젝트에서 이관)
|
|
268
|
-
|
|
269
|
-
${USER_RULES}
|
|
270
|
-
|
|
271
|
-
## Rules (모든 에이전트 공통)
|
|
272
|
-
|
|
273
|
-
### 읽기/쓰기 권한
|
|
274
|
-
|
|
275
|
-
| 파일 | 읽기 | 쓰기 |
|
|
276
|
-
|------|------|------|
|
|
277
|
-
| AGENTS.md | 전체 | Planner만 |
|
|
278
|
-
| .harness/actions/api-contract.json | 전체 | Planner만 |
|
|
279
|
-
| .harness/actions/feature-list.json | 전체 | passes: Generator, 나머지: Planner |
|
|
280
|
-
| .harness/progress.json | 전체 | 전체 (Session Boundary Protocol에 따라 업데이트) |
|
|
281
|
-
| \`[BE]\` 소유 경로 | 전체 | Generator-Backend만 |
|
|
282
|
-
| \`[FE]\` 소유 경로 | 전체 | Generator-Frontend만 |
|
|
283
|
-
| .harness/archive/ | 전체 | 쓰기 금지 (불변) |
|
|
284
|
-
|
|
285
|
-
### 변경 요청 프로토콜
|
|
286
|
-
|
|
287
|
-
AGENTS.md 또는 api-contract.json 변경이 필요할 때:
|
|
288
|
-
1. sprint-contract.md에 \`## Change Request\` 섹션 추가
|
|
289
|
-
2. Planner가 다음 스프린트 전환 시 반영 여부 결정
|
|
290
|
-
|
|
291
|
-
### 금지 사항
|
|
292
|
-
|
|
293
|
-
- AGENTS.md를 Planner 외 에이전트가 수정
|
|
294
|
-
- 서비스 간 직접 DB 접근
|
|
295
|
-
- 테스트 삭제/약화
|
|
296
|
-
- archive/ 내 파일 수정
|
|
297
|
-
- 프로젝트를 조기 "완료" 선언
|
|
298
|
-
|
|
299
|
-
## Harness Quick Reference
|
|
300
|
-
|
|
301
|
-
| 명령 | 설명 |
|
|
302
|
-
|------|------|
|
|
303
|
-
| \`bash scripts/scan-project.sh\` | 프로젝트 구조 재스캔 |
|
|
304
|
-
| \`.harness/progress.json\` | 현재 진행 상태 (기계 판독) |
|
|
305
|
-
| \`.harness/actions/\` | 활성 스프린트 문서 |
|
|
306
|
-
| \`.harness/HARNESS.md\` | 하네스 상세 가이드 |
|
|
307
|
-
AGENTSEOF
|
|
308
|
-
|
|
309
|
-
echo ""
|
|
310
|
-
echo "=== AGENTS.md Generated ==="
|
|
311
|
-
echo "Path: ${AGENTS_FILE}"
|
|
312
|
-
|
|
313
|
-
# ─────────────────────────────────────────
|
|
314
|
-
# 6. CLAUDE.md 심볼릭 링크
|
|
315
|
-
# ─────────────────────────────────────────
|
|
316
|
-
if [ -f "$CLAUDE_FILE" ] && [ ! -L "$CLAUDE_FILE" ]; then
|
|
317
|
-
echo ""
|
|
318
|
-
echo "WARNING: CLAUDE.md가 일반 파일로 존재합니다."
|
|
319
|
-
echo "기존 내용은 AGENTS.md의 'Preserved Rules' 섹션에 이관되었습니다."
|
|
320
|
-
echo "백업: ${BACKUP_DIR}/"
|
|
321
|
-
rm "$CLAUDE_FILE"
|
|
322
|
-
fi
|
|
323
|
-
|
|
324
|
-
if [ ! -L "$CLAUDE_FILE" ]; then
|
|
325
|
-
ln -sf AGENTS.md "$CLAUDE_FILE"
|
|
326
|
-
echo "Created symlink: CLAUDE.md → AGENTS.md"
|
|
327
|
-
else
|
|
328
|
-
echo "Symlink already exists: CLAUDE.md → AGENTS.md"
|
|
329
|
-
fi
|
|
330
|
-
|
|
331
|
-
echo ""
|
|
332
|
-
echo "=== Initialization Complete ==="
|
|
333
|
-
echo ""
|
|
334
|
-
echo "Next steps:"
|
|
335
|
-
echo " 1. AGENTS.md의 [?] 태그를 확인하고 Planner에게 분류를 요청하세요"
|
|
336
|
-
echo " 2. 'Preserved Rules' 섹션에서 불필요한 규칙을 정리하세요"
|
|
337
|
-
echo " 3. '하네스 엔지니어링 시작'으로 Dispatcher를 실행하세요"
|