@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walwal-harness/cli",
3
- "version": "5.9.0",
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
- # Usage: bash scripts/harness-gotcha-memory.sh [project-root]
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
- PROJECT_ROOT="${1:-}"
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
- render() {
194
- # clear 대신 커서 홈 + 화면 끝까지 지우기 — 깜빡임 최소화
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
- local active active_file
201
- active=$(get_active_agent)
202
- active_file=""
203
- [ -n "$active" ] && active_file=$(file_for_agent "$active")
204
-
205
- echo -e "${BOLD}${MAGENTA}RULES INDEX${RESET} ${DIM}Gotcha · Memory · Conventions · $(date +%H:%M:%S) · recent=${RECENT_N} · refresh ${REFRESH_SEC}s${RESET}"
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
- echo ""
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
- echo ""
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
@@ -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 → Gotcha & Memory
116
- set dashPane to (split vertically with default profile)
117
- tell dashPane
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
- -- Split right → Team 1
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 → Gotcha · Memory · Conventions
167
- set dashPane to (split vertically with default profile)
168
- tell dashPane
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
- -- Split right → Monitor (solo 단일 에이전트 라이프사이클)
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 "Gotcha · Memory · Conventions"
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 "Gotcha · Memory · Conventions"
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