@walwal-harness/cli 5.9.0 → 5.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@walwal-harness/cli",
3
- "version": "5.9.0",
3
+ "version": "5.9.1",
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,7 +112,7 @@ 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
115
+ -- Split right → Gotcha & Memory (combined view; tmux 경로는 3분할 사용)
116
116
  set dashPane to (split vertically with default profile)
117
117
  tell dashPane
118
118
  write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}'"
@@ -163,7 +163,7 @@ launch_iterm2_solo() {
163
163
  write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-prompt-history.sh' '${PROJECT_ROOT}'"
164
164
  end tell
165
165
 
166
- -- Split right → Gotcha · Memory · Conventions
166
+ -- Split right → Gotcha · Memory · Conventions (combined view; tmux 경로는 3분할)
167
167
  set dashPane to (split vertically with default profile)
168
168
  tell dashPane
169
169
  write text "cd '${PROJECT_ROOT}' && bash '${SCRIPT_DIR}/harness-gotcha-memory.sh' '${PROJECT_ROOT}'"
@@ -198,12 +198,21 @@ launch_tmux_team() {
198
198
  PANE_ARCHIVE=$(tmux split-window -v -p 35 -t "$PANE_DASH" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
199
199
  "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-prompt-history.sh\" \"${PROJECT_ROOT}\"'")
200
200
 
201
+ # Gotcha 패널을 3 개 sub-pane 으로 수직 분할: Gotchas / Conventions / Memory
202
+ # 각 pane 은 tmux copy-mode (prefix + [) 로 독립 스크롤 가능
203
+ PANE_CONV=$(tmux split-window -v -p 60 -t "$PANE_GOTCHA" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
204
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode conventions'")
205
+ PANE_MEM=$(tmux split-window -v -p 50 -t "$PANE_CONV" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
206
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode memory'")
207
+
201
208
  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
209
+ tmux send-keys -t "$PANE_GOTCHA" "bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode gotcha" Enter
203
210
 
204
211
  tmux select-pane -t "$PANE_DASH" -T "Dashboard"
205
212
  tmux select-pane -t "$PANE_ARCHIVE" -T "Archive Prompt"
206
- tmux select-pane -t "$PANE_GOTCHA" -T "Gotcha · Memory · Conventions"
213
+ tmux select-pane -t "$PANE_GOTCHA" -T "Gotchas (scrollable: prefix + [ )"
214
+ tmux select-pane -t "$PANE_CONV" -T "Conventions (scrollable: prefix + [ )"
215
+ tmux select-pane -t "$PANE_MEM" -T "Shared Memory (scrollable: prefix + [ )"
207
216
  tmux select-pane -t "$PANE_T1" -T "TEAM 1"
208
217
  tmux select-pane -t "$PANE_T2" -T "TEAM 2"
209
218
  tmux select-pane -t "$PANE_T3" -T "TEAM 3"
@@ -224,12 +233,20 @@ launch_tmux_solo() {
224
233
  PANE_HISTORY=$(tmux split-window -v -p 35 -t "$PANE_DASH" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
225
234
  "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-prompt-history.sh\" \"${PROJECT_ROOT}\"'")
226
235
 
236
+ # Gotcha 패널을 3 개 sub-pane 으로 수직 분할: Gotchas / Conventions / Memory
237
+ PANE_CONV=$(tmux split-window -v -p 60 -t "$PANE_GOTCHA" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
238
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode conventions'")
239
+ PANE_MEM=$(tmux split-window -v -p 50 -t "$PANE_CONV" -c "$PROJECT_ROOT" -P -F '#{pane_id}' \
240
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode memory'")
241
+
227
242
  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
243
+ tmux send-keys -t "$PANE_GOTCHA" "bash \"${SCRIPT_DIR}/harness-gotcha-memory.sh\" \"${PROJECT_ROOT}\" --mode gotcha" Enter
229
244
 
230
245
  tmux select-pane -t "$PANE_DASH" -T "Dashboard"
231
246
  tmux select-pane -t "$PANE_HISTORY" -T "Prompt History"
232
- tmux select-pane -t "$PANE_GOTCHA" -T "Gotcha · Memory · Conventions"
247
+ tmux select-pane -t "$PANE_GOTCHA" -T "Gotchas (scrollable: prefix + [ )"
248
+ tmux select-pane -t "$PANE_CONV" -T "Conventions (scrollable: prefix + [ )"
249
+ tmux select-pane -t "$PANE_MEM" -T "Shared Memory (scrollable: prefix + [ )"
233
250
  tmux select-pane -t "$PANE_MONITOR" -T "Monitor"
234
251
  tmux select-pane -t "$PANE_DASH"
235
252