@walwal-harness/cli 6.1.4 → 6.1.6

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 (58) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +43 -74
  3. package/assets/launchd/com.walwal.harness-wake.plist.template +32 -0
  4. package/assets/templates/CONVENTIONS.md +12 -0
  5. package/assets/templates/HARNESS.md +8 -8
  6. package/assets/templates/company-pipeline-manifest.json +71 -0
  7. package/assets/templates/config.json +29 -27
  8. package/assets/templates/memory.md +16 -2
  9. package/assets/templates/progress.json.template +6 -5
  10. package/bin/init.js +180 -90
  11. package/conventions/shared.md +34 -0
  12. package/gotchas/conductor.md +16 -0
  13. package/gotchas/dispatcher.md +16 -0
  14. package/gotchas/meeting-manager.md +8 -0
  15. package/gotchas/service-ops.md +8 -0
  16. package/package.json +4 -4
  17. package/scripts/conductor-tick.sh +157 -56
  18. package/scripts/harness-archive.sh +7 -5
  19. package/scripts/harness-dashboard-up.sh +11 -3
  20. package/scripts/harness-hourly-review.sh +582 -0
  21. package/scripts/harness-meeting-doc.sh +55 -16
  22. package/scripts/harness-next.sh +1 -1
  23. package/scripts/harness-parity-audit.sh +101 -0
  24. package/scripts/harness-queue-manager.sh +13 -6
  25. package/scripts/harness-service-ops-monitor.sh +273 -0
  26. package/scripts/harness-session-start.sh +60 -31
  27. package/scripts/harness-statusline.sh +8 -12
  28. package/scripts/harness-stop.sh +85 -0
  29. package/scripts/harness-user-prompt-submit.sh +11 -29
  30. package/scripts/harness-wake-install.sh +180 -0
  31. package/scripts/harness-wake.sh +350 -0
  32. package/scripts/harness-worker-dispatch.sh +188 -0
  33. package/scripts/lib/harness-agent-resolver.sh +127 -0
  34. package/scripts/lib/harness-progress-migrate.sh +6 -1
  35. package/scripts/lib/harness-render-progress.sh +3 -3
  36. package/skills/brainstorming/SKILL.md +2 -2
  37. package/skills/conductor/SKILL.md +67 -55
  38. package/skills/cqo/SKILL.md +1 -0
  39. package/skills/cto/SKILL.md +1 -0
  40. package/skills/dispatcher/SKILL.md +33 -14
  41. package/skills/evaluator-code-quality/SKILL.md +4 -4
  42. package/skills/evaluator-functional/SKILL.md +6 -6
  43. package/skills/evaluator-visual/SKILL.md +4 -4
  44. package/skills/generator-backend/SKILL.md +4 -4
  45. package/skills/generator-frontend/SKILL.md +5 -5
  46. package/skills/meeting-manager/SKILL.md +82 -12
  47. package/skills/planner/SKILL.md +3 -3
  48. package/skills/service-ops/SKILL.md +25 -0
  49. package/commands/harness-solo.md +0 -103
  50. package/commands/harness-stop.md +0 -53
  51. package/commands/harness-team.md +0 -530
  52. package/scripts/harness-dashboard.sh +0 -509
  53. package/scripts/harness-goal-init.sh +0 -72
  54. package/scripts/harness-goal-show.sh +0 -37
  55. package/scripts/harness-gotcha-memory.sh +0 -348
  56. package/scripts/harness-monitor.sh +0 -398
  57. package/scripts/harness-prompt-history.sh +0 -164
  58. package/scripts/harness-tmux.sh +0 -372
@@ -1,348 +0,0 @@
1
- #!/bin/bash
2
- # harness-gotcha-memory.sh — Gotcha · Memory · Conventions pane (index view)
3
- # 활성 에이전트의 gotcha를 최상단으로, 나머지는 요약(최근 3항목+총개수)으로 표시
4
- # + Shared Memory 요약 + Conventions 요약 (shared + 활성 에이전트별)
5
- #
6
- # Usage:
7
- # bash scripts/harness-gotcha-memory.sh [project-root] # 전체 (legacy)
8
- # bash scripts/harness-gotcha-memory.sh [project-root] --mode gotcha # gotcha 만
9
- # bash scripts/harness-gotcha-memory.sh [project-root] --mode conventions # conventions 만
10
- # bash scripts/harness-gotcha-memory.sh [project-root] --mode memory # memory 만
11
- #
12
- # tmux 분할 환경에서는 각 sub-pane 이 한 mode 만 렌더 → 좁은 창에서도 잘리지 않음.
13
- # tmux copy-mode (prefix + [) 로 각 pane 독립 스크롤.
14
-
15
- set -uo pipefail
16
-
17
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
18
- source "$SCRIPT_DIR/lib/harness-render-progress.sh"
19
- source "$SCRIPT_DIR/lib/harness-keywait.sh"
20
-
21
- # Args parsing — first non-flag = project root, --mode = view mode
22
- PROJECT_ROOT=""
23
- MODE="all"
24
- while [ $# -gt 0 ]; do
25
- case "$1" in
26
- --mode) MODE="$2"; shift 2 ;;
27
- --mode=*) MODE="${1#--mode=}"; shift ;;
28
- *) [ -z "$PROJECT_ROOT" ] && PROJECT_ROOT="$1"; shift ;;
29
- esac
30
- done
31
-
32
- if [ -z "$PROJECT_ROOT" ]; then
33
- PROJECT_ROOT="$(resolve_harness_root ".")" || { echo "[gotcha] .harness/ not found."; exit 1; }
34
- fi
35
-
36
- case "$MODE" in
37
- all|gotcha|conventions|memory) ;;
38
- *) echo "[gotcha] unknown mode: $MODE" >&2; exit 1 ;;
39
- esac
40
-
41
- MEMORY_FILE="$PROJECT_ROOT/.harness/memory.md"
42
- GOTCHAS_DIR="$PROJECT_ROOT/.harness/gotchas"
43
- CONVENTIONS_DIR="$PROJECT_ROOT/.harness/conventions"
44
- PROGRESS="$PROJECT_ROOT/.harness/progress.json"
45
-
46
- BOLD="\033[1m"
47
- DIM="\033[2m"
48
- GREEN="\033[32m"
49
- YELLOW="\033[33m"
50
- RED="\033[31m"
51
- CYAN="\033[36m"
52
- MAGENTA="\033[35m"
53
- RESET="\033[0m"
54
- BG_YELLOW="\033[43m"
55
-
56
- REFRESH_SEC="${HARNESS_REFRESH:-5}"
57
- # 단독 mode 패널은 전체 표시 (충분한 세로 공간), 통합 뷰만 최근 3 개로 압축.
58
- if [ "$MODE" = "all" ]; then
59
- RECENT_N="${HARNESS_GOTCHA_RECENT:-3}"
60
- else
61
- RECENT_N="${HARNESS_GOTCHA_RECENT:-9999}"
62
- fi
63
-
64
- # 렌더 캐시 — 내용이 바뀌지 않으면 redraw 스킵
65
- LAST_SIG=""
66
-
67
- # 입력 시그니처: gotchas + memory + 활성 에이전트의 mtime/size 해시
68
- compute_signature() {
69
- {
70
- [ -f "$PROGRESS" ] && stat -f '%m %z' "$PROGRESS" 2>/dev/null
71
- [ -f "$MEMORY_FILE" ] && stat -f '%m %z' "$MEMORY_FILE" 2>/dev/null
72
- if [ -d "$GOTCHAS_DIR" ]; then
73
- for f in "$GOTCHAS_DIR"/*.md; do
74
- [ -e "$f" ] || continue
75
- stat -f '%N %m %z' "$f" 2>/dev/null
76
- done
77
- fi
78
- if [ -d "$CONVENTIONS_DIR" ]; then
79
- for f in "$CONVENTIONS_DIR"/*.md; do
80
- [ -e "$f" ] || continue
81
- stat -f '%N %m %z' "$f" 2>/dev/null
82
- done
83
- fi
84
- } | md5 -q 2>/dev/null || echo "$RANDOM"
85
- }
86
-
87
- # 활성 에이전트 결정: current_agent > next_agent
88
- get_active_agent() {
89
- [ -f "$PROGRESS" ] || { echo ""; return; }
90
- command -v jq &>/dev/null || { echo ""; return; }
91
- local cur nxt
92
- cur=$(jq -r '.current_agent // ""' "$PROGRESS" 2>/dev/null)
93
- nxt=$(jq -r '.next_agent // ""' "$PROGRESS" 2>/dev/null)
94
- if [ -n "$cur" ] && [ "$cur" != "null" ] && [ "$cur" != "none" ]; then
95
- echo "$cur"
96
- elif [ -n "$nxt" ] && [ "$nxt" != "null" ] && [ "$nxt" != "none" ]; then
97
- echo "$nxt"
98
- else
99
- echo ""
100
- fi
101
- }
102
-
103
- # gotcha 파일에서 '### ' 헤딩 개수 = 항목 총수
104
- count_items() {
105
- local f="$1"
106
- local n
107
- n=$(grep -c '^### ' "$f" 2>/dev/null)
108
- echo "${n:-0}"
109
- }
110
-
111
- # 최근 N개 항목 제목 추출 (### 헤딩 — 파일 하단부가 최신이라 tail)
112
- # rule_id 마커 주석(<!-- rule_id: ... -->) 은 시각적 노이즈라 제거
113
- recent_titles() {
114
- local f="$1" n="$2"
115
- grep '^### ' "$f" 2>/dev/null \
116
- | tail -n "$n" \
117
- | sed -E 's/^### //; s/[[:space:]]*<!--[[:space:]]*rule_id:[[:space:]]*[^>]*-->[[:space:]]*$//'
118
- }
119
-
120
- # agent 이름 → 파일 basename 매핑 (정확/접두 일치)
121
- file_for_agent() {
122
- local agent="$1"
123
- local f="$GOTCHAS_DIR/${agent}.md"
124
- [ -f "$f" ] && { echo "$f"; return; }
125
- # 접두 일치 (예: current_agent=generator → generator-backend/frontend 중 하나)
126
- for cand in "$GOTCHAS_DIR"/*.md; do
127
- [ -e "$cand" ] || continue
128
- local base
129
- base=$(basename "$cand" .md)
130
- [ "$base" = "README" ] && continue
131
- case "$base" in
132
- "$agent"*|*"$agent"*) echo "$cand"; return ;;
133
- esac
134
- done
135
- echo ""
136
- }
137
-
138
- render_gotcha_entry() {
139
- local f="$1" active="$2"
140
- local name count
141
- name=$(basename "$f" .md)
142
- count=$(count_items "$f")
143
- if [ "$active" = "true" ]; then
144
- echo -e "${BOLD}${BG_YELLOW} ▸ ${name} ${RESET} ${DIM}(${count} items · ACTIVE)${RESET}"
145
- else
146
- echo -e "${BOLD}${GREEN}▸ ${name}${RESET} ${DIM}(${count} items)${RESET}"
147
- fi
148
- if [ "$count" -eq 0 ]; then
149
- echo -e " ${DIM}(항목 없음)${RESET}"
150
- else
151
- recent_titles "$f" "$RECENT_N" | while IFS= read -r t; do
152
- echo -e " ${DIM}·${RESET} $t"
153
- done
154
- fi
155
- }
156
-
157
- render_conventions_summary() {
158
- if [ ! -d "$CONVENTIONS_DIR" ]; then
159
- echo -e "${DIM}(conventions/ 없음)${RESET}"
160
- return
161
- fi
162
-
163
- local active="$1"
164
- local any=false
165
-
166
- # Shared 먼저, 그다음 활성 에이전트, 그다음 나머지
167
- local ordered_files=()
168
- [ -f "$CONVENTIONS_DIR/shared.md" ] && ordered_files+=("$CONVENTIONS_DIR/shared.md")
169
- if [ -n "$active" ] && [ -f "$CONVENTIONS_DIR/${active}.md" ]; then
170
- ordered_files+=("$CONVENTIONS_DIR/${active}.md")
171
- fi
172
- for cand in "$CONVENTIONS_DIR"/*.md; do
173
- [ -e "$cand" ] || continue
174
- local base; base=$(basename "$cand" .md)
175
- [ "$base" = "README" ] && continue
176
- [ "$cand" = "$CONVENTIONS_DIR/shared.md" ] && continue
177
- [ -n "$active" ] && [ "$cand" = "$CONVENTIONS_DIR/${active}.md" ] && continue
178
- ordered_files+=("$cand")
179
- done
180
-
181
- for f in "${ordered_files[@]}"; do
182
- [ -e "$f" ] || continue
183
- local name count
184
- name=$(basename "$f" .md)
185
- count=$(count_items "$f")
186
- if [ "$name" = "shared" ]; then
187
- echo -e "${BOLD}${CYAN}▸ ${name}${RESET} ${DIM}(${count} items · shared)${RESET}"
188
- elif [ -n "$active" ] && [ "$name" = "$active" ]; then
189
- echo -e "${BOLD}${BG_YELLOW} ▸ ${name} ${RESET} ${DIM}(${count} items · ACTIVE)${RESET}"
190
- else
191
- echo -e "${BOLD}${GREEN}▸ ${name}${RESET} ${DIM}(${count} items)${RESET}"
192
- fi
193
- if [ "$count" -eq 0 ]; then
194
- echo -e " ${DIM}(항목 없음)${RESET}"
195
- else
196
- recent_titles "$f" "$RECENT_N" | while IFS= read -r t; do
197
- echo -e " ${DIM}·${RESET} $t"
198
- done
199
- fi
200
- any=true
201
- done
202
-
203
- [ "$any" = "false" ] && echo -e "${DIM}(항목 없음)${RESET}"
204
- }
205
-
206
- render_memory_summary() {
207
- if [ ! -f "$MEMORY_FILE" ]; then
208
- echo -e "${DIM}(memory.md 없음)${RESET}"
209
- return
210
- fi
211
- local count
212
- count=$(grep -c '^### ' "$MEMORY_FILE" 2>/dev/null)
213
- count="${count:-0}"
214
- echo -e "${BOLD}${CYAN}▣ SHARED MEMORY${RESET} ${DIM}(${count} items · memory.md)${RESET}"
215
- if [ "$count" -eq 0 ]; then
216
- echo -e " ${DIM}(항목 없음)${RESET}"
217
- else
218
- grep '^### ' "$MEMORY_FILE" | tail -n "$RECENT_N" | sed 's/^### //' | while IFS= read -r t; do
219
- echo -e " ${DIM}·${RESET} $t"
220
- done
221
- fi
222
- }
223
-
224
- render_header() {
225
- local title="$1"
226
- local cols hr
227
- cols=$(tput cols 2>/dev/null || echo 80)
228
- hr=$(printf '─%.0s' $(seq 1 "$cols"))
229
- echo -e "${BOLD}${MAGENTA}${title}${RESET} ${DIM}$(date +%H:%M:%S) · recent=${RECENT_N} · refresh ${REFRESH_SEC}s${RESET}"
230
- local active="$1_active"
231
- [ -n "${2:-}" ] && echo -e "${DIM}active agent:${RESET} ${BOLD}${YELLOW}$2${RESET}"
232
- echo -e "${DIM}${hr}${RESET}"
233
- }
234
-
235
- render_gotcha_section() {
236
- local active="$1" active_file="$2"
237
- local cols hr
238
- cols=$(tput cols 2>/dev/null || echo 80)
239
- hr=$(printf '─%.0s' $(seq 1 "$cols"))
240
- echo -e "${BOLD}${MAGENTA}▣ GOTCHAS${RESET} ${DIM}(.harness/gotchas) · $(date +%H:%M:%S) · refresh ${REFRESH_SEC}s${RESET}"
241
- if [ -n "$active" ]; then
242
- echo -e "${DIM}active agent:${RESET} ${BOLD}${YELLOW}${active}${RESET}"
243
- fi
244
- echo -e "${DIM}${hr}${RESET}"
245
-
246
- if [ -n "$active_file" ]; then
247
- render_gotcha_entry "$active_file" "true"
248
- echo ""
249
- fi
250
- if [ -d "$GOTCHAS_DIR" ]; then
251
- for f in "$GOTCHAS_DIR"/*.md; do
252
- [ -e "$f" ] || continue
253
- [ "$f" = "$active_file" ] && continue
254
- local base; base=$(basename "$f" .md)
255
- [ "$base" = "README" ] && continue
256
- render_gotcha_entry "$f" "false"
257
- done
258
- fi
259
- }
260
-
261
- render_conventions_section() {
262
- local active="$1"
263
- local cols hr
264
- cols=$(tput cols 2>/dev/null || echo 80)
265
- hr=$(printf '─%.0s' $(seq 1 "$cols"))
266
- echo -e "${BOLD}${CYAN}▣ CONVENTIONS${RESET} ${DIM}(.harness/conventions) · $(date +%H:%M:%S) · refresh ${REFRESH_SEC}s${RESET}"
267
- echo -e "${DIM}${hr}${RESET}"
268
- render_conventions_summary "$active"
269
- }
270
-
271
- render_memory_section() {
272
- local cols hr
273
- cols=$(tput cols 2>/dev/null || echo 80)
274
- hr=$(printf '─%.0s' $(seq 1 "$cols"))
275
- echo -e "${BOLD}${CYAN}▣ SHARED MEMORY${RESET} ${DIM}(memory.md) · $(date +%H:%M:%S) · refresh ${REFRESH_SEC}s${RESET}"
276
- echo -e "${DIM}${hr}${RESET}"
277
- render_memory_summary
278
- }
279
-
280
- render() {
281
- # clear 대신 커서 홈 + 화면 끝까지 지우기 — 깜빡임 최소화
282
- printf '\033[H\033[2J\033[3J'
283
-
284
- local active active_file
285
- active=$(get_active_agent)
286
- active_file=""
287
- [ -n "$active" ] && active_file=$(file_for_agent "$active")
288
-
289
- case "$MODE" in
290
- gotcha)
291
- render_gotcha_section "$active" "$active_file"
292
- ;;
293
- conventions)
294
- render_conventions_section "$active"
295
- ;;
296
- memory)
297
- render_memory_section
298
- ;;
299
- all)
300
- local cols hr
301
- cols=$(tput cols 2>/dev/null || echo 80)
302
- hr=$(printf '─%.0s' $(seq 1 "$cols"))
303
- echo -e "${BOLD}${MAGENTA}RULES INDEX${RESET} ${DIM}Gotcha · Memory · Conventions · $(date +%H:%M:%S) · recent=${RECENT_N} · refresh ${REFRESH_SEC}s${RESET}"
304
- if [ -n "$active" ]; then
305
- echo -e "${DIM}active agent:${RESET} ${BOLD}${YELLOW}${active}${RESET}"
306
- else
307
- echo -e "${DIM}active agent: (none)${RESET}"
308
- fi
309
- echo -e "${DIM}${hr}${RESET}"
310
-
311
- if [ -n "$active_file" ]; then
312
- render_gotcha_entry "$active_file" "true"
313
- echo ""
314
- fi
315
- if [ -d "$GOTCHAS_DIR" ]; then
316
- for f in "$GOTCHAS_DIR"/*.md; do
317
- [ -e "$f" ] || continue
318
- [ "$f" = "$active_file" ] && continue
319
- local base; base=$(basename "$f" .md)
320
- [ "$base" = "README" ] && continue
321
- render_gotcha_entry "$f" "false"
322
- done
323
- fi
324
- echo ""
325
- echo -e "${DIM}${hr}${RESET}"
326
- echo -e "${BOLD}${CYAN}▣ CONVENTIONS${RESET} ${DIM}(.harness/conventions)${RESET}"
327
- render_conventions_summary "$active"
328
- echo ""
329
- echo -e "${DIM}${hr}${RESET}"
330
- render_memory_summary
331
- ;;
332
- esac
333
- }
334
-
335
- trap 'exit 0' INT TERM
336
-
337
- while true; do
338
- sig=$(compute_signature)
339
- if [ "$sig" != "$LAST_SIG" ]; then
340
- render
341
- printf "${DIM} [r] refresh [q] quit${RESET}\033[K\n"
342
- LAST_SIG="$sig"
343
- fi
344
- if ! wait_or_refresh "$REFRESH_SEC"; then
345
- # 'r' 키 → 캐시 무효화해서 다음 루프에서 강제 렌더
346
- LAST_SIG=""
347
- fi
348
- done