@walwal-harness/cli 5.9.0 → 5.9.2
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/package.json +1 -1
- package/scripts/harness-gotcha-memory.sh +107 -21
- package/scripts/harness-tmux.sh +53 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walwal-harness/cli",
|
|
3
|
-
"version": "5.9.
|
|
3
|
+
"version": "5.9.2",
|
|
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"
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
# harness-gotcha-memory.sh — Gotcha · Memory · Conventions pane (index view)
|
|
3
3
|
# 활성 에이전트의 gotcha를 최상단으로, 나머지는 요약(최근 3항목+총개수)으로 표시
|
|
4
4
|
# + Shared Memory 요약 + Conventions 요약 (shared + 활성 에이전트별)
|
|
5
|
-
#
|
|
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 독립 스크롤.
|
|
6
14
|
|
|
7
15
|
set -uo pipefail
|
|
8
16
|
|
|
@@ -10,11 +18,26 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
|
10
18
|
source "$SCRIPT_DIR/lib/harness-render-progress.sh"
|
|
11
19
|
source "$SCRIPT_DIR/lib/harness-keywait.sh"
|
|
12
20
|
|
|
13
|
-
|
|
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
|
+
|
|
14
32
|
if [ -z "$PROJECT_ROOT" ]; then
|
|
15
33
|
PROJECT_ROOT="$(resolve_harness_root ".")" || { echo "[gotcha] .harness/ not found."; exit 1; }
|
|
16
34
|
fi
|
|
17
35
|
|
|
36
|
+
case "$MODE" in
|
|
37
|
+
all|gotcha|conventions|memory) ;;
|
|
38
|
+
*) echo "[gotcha] unknown mode: $MODE" >&2; exit 1 ;;
|
|
39
|
+
esac
|
|
40
|
+
|
|
18
41
|
MEMORY_FILE="$PROJECT_ROOT/.harness/memory.md"
|
|
19
42
|
GOTCHAS_DIR="$PROJECT_ROOT/.harness/gotchas"
|
|
20
43
|
CONVENTIONS_DIR="$PROJECT_ROOT/.harness/conventions"
|
|
@@ -190,54 +213,117 @@ render_memory_summary() {
|
|
|
190
213
|
fi
|
|
191
214
|
}
|
|
192
215
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
printf '\033[H\033[2J\033[3J'
|
|
216
|
+
render_header() {
|
|
217
|
+
local title="$1"
|
|
196
218
|
local cols hr
|
|
197
219
|
cols=$(tput cols 2>/dev/null || echo 80)
|
|
198
220
|
hr=$(printf '─%.0s' $(seq 1 "$cols"))
|
|
221
|
+
echo -e "${BOLD}${MAGENTA}${title}${RESET} ${DIM}$(date +%H:%M:%S) · recent=${RECENT_N} · refresh ${REFRESH_SEC}s${RESET}"
|
|
222
|
+
local active="$1_active"
|
|
223
|
+
[ -n "${2:-}" ] && echo -e "${DIM}active agent:${RESET} ${BOLD}${YELLOW}$2${RESET}"
|
|
224
|
+
echo -e "${DIM}${hr}${RESET}"
|
|
225
|
+
}
|
|
199
226
|
|
|
200
|
-
|
|
201
|
-
active
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
echo -e "${BOLD}${MAGENTA}
|
|
227
|
+
render_gotcha_section() {
|
|
228
|
+
local active="$1" active_file="$2"
|
|
229
|
+
local cols hr
|
|
230
|
+
cols=$(tput cols 2>/dev/null || echo 80)
|
|
231
|
+
hr=$(printf '─%.0s' $(seq 1 "$cols"))
|
|
232
|
+
echo -e "${BOLD}${MAGENTA}▣ GOTCHAS${RESET} ${DIM}(.harness/gotchas) · $(date +%H:%M:%S) · refresh ${REFRESH_SEC}s${RESET}"
|
|
206
233
|
if [ -n "$active" ]; then
|
|
207
234
|
echo -e "${DIM}active agent:${RESET} ${BOLD}${YELLOW}${active}${RESET}"
|
|
208
|
-
else
|
|
209
|
-
echo -e "${DIM}active agent: (none)${RESET}"
|
|
210
235
|
fi
|
|
211
236
|
echo -e "${DIM}${hr}${RESET}"
|
|
212
237
|
|
|
213
|
-
# 활성 에이전트 gotcha 최상단
|
|
214
238
|
if [ -n "$active_file" ]; then
|
|
215
239
|
render_gotcha_entry "$active_file" "true"
|
|
216
240
|
echo ""
|
|
217
241
|
fi
|
|
218
|
-
|
|
219
|
-
# 나머지 gotcha
|
|
220
242
|
if [ -d "$GOTCHAS_DIR" ]; then
|
|
221
243
|
for f in "$GOTCHAS_DIR"/*.md; do
|
|
222
244
|
[ -e "$f" ] || continue
|
|
223
245
|
[ "$f" = "$active_file" ] && continue
|
|
224
|
-
local base
|
|
225
|
-
base=$(basename "$f" .md)
|
|
246
|
+
local base; base=$(basename "$f" .md)
|
|
226
247
|
[ "$base" = "README" ] && continue
|
|
227
248
|
render_gotcha_entry "$f" "false"
|
|
228
249
|
done
|
|
229
250
|
fi
|
|
251
|
+
}
|
|
230
252
|
|
|
231
|
-
|
|
253
|
+
render_conventions_section() {
|
|
254
|
+
local active="$1"
|
|
255
|
+
local cols hr
|
|
256
|
+
cols=$(tput cols 2>/dev/null || echo 80)
|
|
257
|
+
hr=$(printf '─%.0s' $(seq 1 "$cols"))
|
|
258
|
+
echo -e "${BOLD}${CYAN}▣ CONVENTIONS${RESET} ${DIM}(.harness/conventions) · $(date +%H:%M:%S) · refresh ${REFRESH_SEC}s${RESET}"
|
|
232
259
|
echo -e "${DIM}${hr}${RESET}"
|
|
233
|
-
echo -e "${BOLD}${CYAN}▣ CONVENTIONS${RESET} ${DIM}(.harness/conventions)${RESET}"
|
|
234
260
|
render_conventions_summary "$active"
|
|
261
|
+
}
|
|
235
262
|
|
|
236
|
-
|
|
263
|
+
render_memory_section() {
|
|
264
|
+
local cols hr
|
|
265
|
+
cols=$(tput cols 2>/dev/null || echo 80)
|
|
266
|
+
hr=$(printf '─%.0s' $(seq 1 "$cols"))
|
|
267
|
+
echo -e "${BOLD}${CYAN}▣ SHARED MEMORY${RESET} ${DIM}(memory.md) · $(date +%H:%M:%S) · refresh ${REFRESH_SEC}s${RESET}"
|
|
237
268
|
echo -e "${DIM}${hr}${RESET}"
|
|
238
269
|
render_memory_summary
|
|
239
270
|
}
|
|
240
271
|
|
|
272
|
+
render() {
|
|
273
|
+
# clear 대신 커서 홈 + 화면 끝까지 지우기 — 깜빡임 최소화
|
|
274
|
+
printf '\033[H\033[2J\033[3J'
|
|
275
|
+
|
|
276
|
+
local active active_file
|
|
277
|
+
active=$(get_active_agent)
|
|
278
|
+
active_file=""
|
|
279
|
+
[ -n "$active" ] && active_file=$(file_for_agent "$active")
|
|
280
|
+
|
|
281
|
+
case "$MODE" in
|
|
282
|
+
gotcha)
|
|
283
|
+
render_gotcha_section "$active" "$active_file"
|
|
284
|
+
;;
|
|
285
|
+
conventions)
|
|
286
|
+
render_conventions_section "$active"
|
|
287
|
+
;;
|
|
288
|
+
memory)
|
|
289
|
+
render_memory_section
|
|
290
|
+
;;
|
|
291
|
+
all)
|
|
292
|
+
local cols hr
|
|
293
|
+
cols=$(tput cols 2>/dev/null || echo 80)
|
|
294
|
+
hr=$(printf '─%.0s' $(seq 1 "$cols"))
|
|
295
|
+
echo -e "${BOLD}${MAGENTA}RULES INDEX${RESET} ${DIM}Gotcha · Memory · Conventions · $(date +%H:%M:%S) · recent=${RECENT_N} · refresh ${REFRESH_SEC}s${RESET}"
|
|
296
|
+
if [ -n "$active" ]; then
|
|
297
|
+
echo -e "${DIM}active agent:${RESET} ${BOLD}${YELLOW}${active}${RESET}"
|
|
298
|
+
else
|
|
299
|
+
echo -e "${DIM}active agent: (none)${RESET}"
|
|
300
|
+
fi
|
|
301
|
+
echo -e "${DIM}${hr}${RESET}"
|
|
302
|
+
|
|
303
|
+
if [ -n "$active_file" ]; then
|
|
304
|
+
render_gotcha_entry "$active_file" "true"
|
|
305
|
+
echo ""
|
|
306
|
+
fi
|
|
307
|
+
if [ -d "$GOTCHAS_DIR" ]; then
|
|
308
|
+
for f in "$GOTCHAS_DIR"/*.md; do
|
|
309
|
+
[ -e "$f" ] || continue
|
|
310
|
+
[ "$f" = "$active_file" ] && continue
|
|
311
|
+
local base; base=$(basename "$f" .md)
|
|
312
|
+
[ "$base" = "README" ] && continue
|
|
313
|
+
render_gotcha_entry "$f" "false"
|
|
314
|
+
done
|
|
315
|
+
fi
|
|
316
|
+
echo ""
|
|
317
|
+
echo -e "${DIM}${hr}${RESET}"
|
|
318
|
+
echo -e "${BOLD}${CYAN}▣ CONVENTIONS${RESET} ${DIM}(.harness/conventions)${RESET}"
|
|
319
|
+
render_conventions_summary "$active"
|
|
320
|
+
echo ""
|
|
321
|
+
echo -e "${DIM}${hr}${RESET}"
|
|
322
|
+
render_memory_summary
|
|
323
|
+
;;
|
|
324
|
+
esac
|
|
325
|
+
}
|
|
326
|
+
|
|
241
327
|
trap 'exit 0' INT TERM
|
|
242
328
|
|
|
243
329
|
while true; do
|
package/scripts/harness-tmux.sh
CHANGED
|
@@ -112,28 +112,37 @@ launch_iterm2_team() {
|
|
|
112
112
|
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-prompt-history.sh' '${PROJECT_ROOT}'"
|
|
113
113
|
end tell
|
|
114
114
|
|
|
115
|
-
-- Split right →
|
|
116
|
-
set
|
|
117
|
-
tell
|
|
118
|
-
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}'"
|
|
115
|
+
-- Split right → Gotchas (top of Rules column, full-height initially)
|
|
116
|
+
set gotchaPane to (split vertically with default profile)
|
|
117
|
+
tell gotchaPane
|
|
118
|
+
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}' --mode gotcha"
|
|
119
119
|
|
|
120
|
-
--
|
|
120
|
+
-- IMPORTANT: Team 컬럼을 먼저 분리 (전체 높이 유지). 그 후에 gotchaPane 을 horizontal 분할.
|
|
121
121
|
set t1Pane to (split vertically with default profile)
|
|
122
122
|
tell t1Pane
|
|
123
123
|
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-monitor.sh' '${PROJECT_ROOT}' --team 1"
|
|
124
124
|
|
|
125
|
-
-- Split down → Team 2
|
|
126
125
|
set t2Pane to (split horizontally with default profile)
|
|
127
126
|
tell t2Pane
|
|
128
127
|
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-monitor.sh' '${PROJECT_ROOT}' --team 2"
|
|
129
128
|
|
|
130
|
-
-- Split down → Team 3
|
|
131
129
|
set t3Pane to (split horizontally with default profile)
|
|
132
130
|
tell t3Pane
|
|
133
131
|
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-monitor.sh' '${PROJECT_ROOT}' --team 3"
|
|
134
132
|
end tell
|
|
135
133
|
end tell
|
|
136
134
|
end tell
|
|
135
|
+
|
|
136
|
+
-- Team 컬럼 분리 후, gotchaPane (Rules 컬럼) 을 horizontal 두 번 split → Conventions / Memory
|
|
137
|
+
set convPane to (split horizontally with default profile)
|
|
138
|
+
tell convPane
|
|
139
|
+
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}' --mode conventions"
|
|
140
|
+
|
|
141
|
+
set memPane to (split horizontally with default profile)
|
|
142
|
+
tell memPane
|
|
143
|
+
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}' --mode memory"
|
|
144
|
+
end tell
|
|
145
|
+
end tell
|
|
137
146
|
end tell
|
|
138
147
|
end tell
|
|
139
148
|
end tell
|
|
@@ -163,16 +172,27 @@ launch_iterm2_solo() {
|
|
|
163
172
|
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-prompt-history.sh' '${PROJECT_ROOT}'"
|
|
164
173
|
end tell
|
|
165
174
|
|
|
166
|
-
-- Split right →
|
|
167
|
-
set
|
|
168
|
-
tell
|
|
169
|
-
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}'"
|
|
175
|
+
-- Split right → Gotchas (top of Rules column, full-height initially)
|
|
176
|
+
set gotchaPane to (split vertically with default profile)
|
|
177
|
+
tell gotchaPane
|
|
178
|
+
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}' --mode gotcha"
|
|
170
179
|
|
|
171
|
-
--
|
|
180
|
+
-- Monitor 컬럼을 먼저 분리 (전체 높이 유지)
|
|
172
181
|
set monPane to (split vertically with default profile)
|
|
173
182
|
tell monPane
|
|
174
183
|
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-monitor.sh' '${PROJECT_ROOT}'"
|
|
175
184
|
end tell
|
|
185
|
+
|
|
186
|
+
-- Monitor 분리 후, gotchaPane (Rules 컬럼) 을 horizontal 두 번 split → Conventions / Memory
|
|
187
|
+
set convPane to (split horizontally with default profile)
|
|
188
|
+
tell convPane
|
|
189
|
+
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}' --mode conventions"
|
|
190
|
+
|
|
191
|
+
set memPane to (split horizontally with default profile)
|
|
192
|
+
tell memPane
|
|
193
|
+
write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}' --mode memory"
|
|
194
|
+
end tell
|
|
195
|
+
end tell
|
|
176
196
|
end tell
|
|
177
197
|
end tell
|
|
178
198
|
end tell
|
|
@@ -198,12 +218,21 @@ launch_tmux_team() {
|
|
|
198
218
|
PANE_ARCHIVE=$(tmux split-window -v -p 35 -t "$PANE_DASH" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
|
|
199
219
|
"bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-prompt-history.sh\" \"${PROJECT_ROOT}\"'")
|
|
200
220
|
|
|
221
|
+
# Gotcha 패널을 3 개 sub-pane 으로 수직 분할: Gotchas / Conventions / Memory
|
|
222
|
+
# 각 pane 은 tmux copy-mode (prefix + [) 로 독립 스크롤 가능
|
|
223
|
+
PANE_CONV=$(tmux split-window -v -p 60 -t "$PANE_GOTCHA" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
|
|
224
|
+
"bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode conventions'")
|
|
225
|
+
PANE_MEM=$(tmux split-window -v -p 50 -t "$PANE_CONV" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
|
|
226
|
+
"bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode memory'")
|
|
227
|
+
|
|
201
228
|
tmux send-keys -t "$PANE_DASH" "bash \"${SCRIPT_DIR}/harness-dashboard.sh\" \"${PROJECT_ROOT}\"" Enter
|
|
202
|
-
tmux send-keys -t "$PANE_GOTCHA" "bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\"" Enter
|
|
229
|
+
tmux send-keys -t "$PANE_GOTCHA" "bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode gotcha" Enter
|
|
203
230
|
|
|
204
231
|
tmux select-pane -t "$PANE_DASH" -T "Dashboard"
|
|
205
232
|
tmux select-pane -t "$PANE_ARCHIVE" -T "Archive Prompt"
|
|
206
|
-
tmux select-pane -t "$PANE_GOTCHA" -T "
|
|
233
|
+
tmux select-pane -t "$PANE_GOTCHA" -T "Gotchas (scrollable: prefix + [ )"
|
|
234
|
+
tmux select-pane -t "$PANE_CONV" -T "Conventions (scrollable: prefix + [ )"
|
|
235
|
+
tmux select-pane -t "$PANE_MEM" -T "Shared Memory (scrollable: prefix + [ )"
|
|
207
236
|
tmux select-pane -t "$PANE_T1" -T "TEAM 1"
|
|
208
237
|
tmux select-pane -t "$PANE_T2" -T "TEAM 2"
|
|
209
238
|
tmux select-pane -t "$PANE_T3" -T "TEAM 3"
|
|
@@ -224,12 +253,20 @@ launch_tmux_solo() {
|
|
|
224
253
|
PANE_HISTORY=$(tmux split-window -v -p 35 -t "$PANE_DASH" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
|
|
225
254
|
"bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-prompt-history.sh\" \"${PROJECT_ROOT}\"'")
|
|
226
255
|
|
|
256
|
+
# Gotcha 패널을 3 개 sub-pane 으로 수직 분할: Gotchas / Conventions / Memory
|
|
257
|
+
PANE_CONV=$(tmux split-window -v -p 60 -t "$PANE_GOTCHA" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
|
|
258
|
+
"bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode conventions'")
|
|
259
|
+
PANE_MEM=$(tmux split-window -v -p 50 -t "$PANE_CONV" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
|
|
260
|
+
"bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode memory'")
|
|
261
|
+
|
|
227
262
|
tmux send-keys -t "$PANE_DASH" "bash \"${SCRIPT_DIR}/harness-dashboard.sh\" \"${PROJECT_ROOT}\"" Enter
|
|
228
|
-
tmux send-keys -t "$PANE_GOTCHA" "bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\"" Enter
|
|
263
|
+
tmux send-keys -t "$PANE_GOTCHA" "bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode gotcha" Enter
|
|
229
264
|
|
|
230
265
|
tmux select-pane -t "$PANE_DASH" -T "Dashboard"
|
|
231
266
|
tmux select-pane -t "$PANE_HISTORY" -T "Prompt History"
|
|
232
|
-
tmux select-pane -t "$PANE_GOTCHA" -T "
|
|
267
|
+
tmux select-pane -t "$PANE_GOTCHA" -T "Gotchas (scrollable: prefix + [ )"
|
|
268
|
+
tmux select-pane -t "$PANE_CONV" -T "Conventions (scrollable: prefix + [ )"
|
|
269
|
+
tmux select-pane -t "$PANE_MEM" -T "Shared Memory (scrollable: prefix + [ )"
|
|
233
270
|
tmux select-pane -t "$PANE_MONITOR" -T "Monitor"
|
|
234
271
|
tmux select-pane -t "$PANE_DASH"
|
|
235
272
|
|