@walwal-harness/cli 4.0.0-beta.9 → 5.0.0
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/README.md +118 -294
- package/assets/templates/config.json +8 -7
- package/assets/templates/progress.json.template +7 -1
- package/bin/init.js +115 -84
- package/commands/harness-solo.md +68 -0
- package/commands/harness-stop.md +53 -0
- package/{skills/team-action/SKILL.md → commands/harness-team.md} +100 -43
- package/package.json +9 -10
- package/scripts/harness-dashboard.sh +219 -154
- package/scripts/harness-monitor.sh +126 -73
- package/scripts/harness-prompt-history.sh +1 -1
- package/scripts/harness-queue-manager.sh +1 -1
- package/scripts/harness-session-start.sh +24 -13
- package/scripts/harness-statusline.sh +31 -8
- package/scripts/harness-tmux.sh +125 -72
- package/scripts/harness-user-prompt-submit.sh +22 -15
- package/skills/dispatcher/SKILL.md +6 -6
- package/skills/evaluator-functional/SKILL.md +2 -2
- package/skills/generator-frontend/SKILL.md +2 -2
- package/scripts/harness-control.sh +0 -183
- package/scripts/harness-dashboard-v4.sh +0 -155
- package/scripts/harness-eval-watcher.sh +0 -228
- package/scripts/harness-studio-setup.sh +0 -143
- package/scripts/harness-studio.sh +0 -66
- package/scripts/harness-tmux-v4.sh +0 -136
- package/skills/team-stop/SKILL.md +0 -19
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# harness-monitor.sh — Agent Lifecycle Monitor
|
|
2
|
+
# harness-monitor.sh — Agent Lifecycle Monitor (v5 unified)
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
4
|
+
# Solo 모드: 단일 이벤트 스트림 (progress.json 변경 감지 + audit.log)
|
|
5
|
+
# Team 모드: 팀별 섹션 분리 (feature-queue.json + progress.log 기반)
|
|
6
6
|
#
|
|
7
7
|
# Usage: bash scripts/harness-monitor.sh [project-root]
|
|
8
8
|
|
|
@@ -10,7 +10,19 @@ set -uo pipefail
|
|
|
10
10
|
|
|
11
11
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
# ── Args ──
|
|
14
|
+
# Usage: harness-monitor.sh [project-root] [--team N]
|
|
15
|
+
# --team N → 단일 팀만 렌더 (tmux per-team pane 용도)
|
|
16
|
+
PROJECT_ROOT=""
|
|
17
|
+
TEAM_FILTER=""
|
|
18
|
+
while [ $# -gt 0 ]; do
|
|
19
|
+
case "$1" in
|
|
20
|
+
--team) TEAM_FILTER="$2"; shift 2 ;;
|
|
21
|
+
--team=*) TEAM_FILTER="${1#--team=}"; shift ;;
|
|
22
|
+
*) [ -z "$PROJECT_ROOT" ] && PROJECT_ROOT="$1"; shift ;;
|
|
23
|
+
esac
|
|
24
|
+
done
|
|
25
|
+
|
|
14
26
|
if [ -z "$PROJECT_ROOT" ]; then
|
|
15
27
|
source "$SCRIPT_DIR/lib/harness-render-progress.sh"
|
|
16
28
|
PROJECT_ROOT="$(resolve_harness_root ".")" || {
|
|
@@ -50,7 +62,7 @@ team_color() {
|
|
|
50
62
|
}
|
|
51
63
|
|
|
52
64
|
# ══════════════════════════════════════════
|
|
53
|
-
#
|
|
65
|
+
# Team 모드: 팀별 섹션 렌더링
|
|
54
66
|
# ══════════════════════════════════════════
|
|
55
67
|
|
|
56
68
|
render_v4_header() {
|
|
@@ -58,8 +70,18 @@ render_v4_header() {
|
|
|
58
70
|
echo ""
|
|
59
71
|
}
|
|
60
72
|
|
|
73
|
+
# 고정폭 배너 구분선 (터미널 너비에 맞춰 채움)
|
|
74
|
+
banner_line() {
|
|
75
|
+
local cols
|
|
76
|
+
cols=$(tput cols 2>/dev/null || echo 78)
|
|
77
|
+
local line=""
|
|
78
|
+
for ((i=0; i<cols; i++)); do line+="━"; done
|
|
79
|
+
echo "$line"
|
|
80
|
+
}
|
|
81
|
+
|
|
61
82
|
render_team_section() {
|
|
62
83
|
local team_num="$1"
|
|
84
|
+
local log_lines="${2:-10}"
|
|
63
85
|
local color
|
|
64
86
|
color=$(team_color "$team_num")
|
|
65
87
|
|
|
@@ -90,93 +112,119 @@ render_team_section() {
|
|
|
90
112
|
*) phase_str="" ;;
|
|
91
113
|
esac
|
|
92
114
|
|
|
93
|
-
#
|
|
94
|
-
|
|
115
|
+
# ── 큰 배너 ──
|
|
116
|
+
local bar
|
|
117
|
+
bar=$(banner_line)
|
|
118
|
+
printf "%b%s%b\n" "$color" "$bar" "$RESET"
|
|
119
|
+
|
|
120
|
+
printf "%b%b TEAM %s%b" "$color$BOLD" "$icon" "$team_num" "$RESET"
|
|
95
121
|
if [ "$t_feature" != "—" ] && [ "$t_feature" != "null" ]; then
|
|
96
|
-
printf "%s " "$t_feature"
|
|
122
|
+
printf " %b%s%b" "$BOLD" "$t_feature" "$RESET"
|
|
97
123
|
if [ -n "$phase_str" ]; then
|
|
98
|
-
printf "%b%s%b" "$color" "$phase_str" "$RESET"
|
|
124
|
+
printf " %b[%s]%b" "$color" "$phase_str" "$RESET"
|
|
99
125
|
fi
|
|
100
126
|
if [ -n "$t_attempt" ] && [ "$t_attempt" != "—" ] && [ "$t_attempt" != "1" ]; then
|
|
101
|
-
printf " %
|
|
127
|
+
printf " %battempt #%s%b" "$YELLOW" "$t_attempt" "$RESET"
|
|
102
128
|
fi
|
|
103
129
|
else
|
|
104
|
-
printf "%bidle%b" "$DIM" "$RESET"
|
|
130
|
+
printf " %bidle%b" "$DIM" "$RESET"
|
|
105
131
|
fi
|
|
106
132
|
echo ""
|
|
133
|
+
printf "%b%s%b\n" "$color" "$bar" "$RESET"
|
|
107
134
|
|
|
108
|
-
# 팀 로그
|
|
135
|
+
# ── 팀 로그 ──
|
|
136
|
+
local have_logs=0
|
|
109
137
|
if [ -f "$PROGRESS_LOG" ]; then
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
local matched
|
|
139
|
+
matched=$(grep -E "team-${team_num}\b|team_${team_num}\b" "$PROGRESS_LOG" 2>/dev/null | tail -"$log_lines")
|
|
140
|
+
if [ -n "$matched" ]; then
|
|
141
|
+
have_logs=1
|
|
142
|
+
local cols
|
|
143
|
+
cols=$(tput cols 2>/dev/null || echo 78)
|
|
144
|
+
# 포맷: [ts] [icon agent] detail (너무 길면 터미널 너비에서 줄바꿈)
|
|
145
|
+
local prefix_w=18 # " HH:MM ✦ eval "
|
|
146
|
+
local detail_w=$(( cols - prefix_w ))
|
|
147
|
+
[ "$detail_w" -lt 20 ] && detail_w=20
|
|
148
|
+
|
|
149
|
+
echo "$matched" | while IFS= read -r line; do
|
|
150
|
+
local ts action detail
|
|
151
|
+
ts=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$1); print $1}')
|
|
152
|
+
action=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$3); print $3}')
|
|
153
|
+
detail=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$4); print $4}')
|
|
154
|
+
|
|
155
|
+
local short_ts
|
|
156
|
+
short_ts=$(echo "$ts" | grep -oE '[0-9]{2}:[0-9]{2}' | tail -1 || echo "$ts")
|
|
157
|
+
|
|
158
|
+
local a_icon="·" a_color="$DIM" a_label="$action"
|
|
159
|
+
case "$action" in
|
|
160
|
+
gen|gen-start|gen-read|gen-write|gen-test|gen-done)
|
|
161
|
+
a_icon="▶"; a_color="$GREEN"; a_label="Gen" ;;
|
|
162
|
+
eval|eval-start|eval-check|eval-done)
|
|
163
|
+
a_icon="✦"; a_color="$BLUE"; a_label="Eval" ;;
|
|
164
|
+
result|pass)
|
|
165
|
+
a_icon="✓"; a_color="$GREEN"; a_label="Result" ;;
|
|
166
|
+
fail)
|
|
167
|
+
a_icon="✗"; a_color="$RED"; a_label="Result" ;;
|
|
168
|
+
dequeue) a_icon="→"; a_color="$CYAN"; a_label="Queue" ;;
|
|
169
|
+
gate) a_icon="◆"; a_color="$YELLOW"; a_label="Gate" ;;
|
|
170
|
+
*) a_icon="·"; a_color="$DIM"; a_label="$action" ;;
|
|
171
|
+
esac
|
|
172
|
+
|
|
173
|
+
# 첫 줄
|
|
174
|
+
local first="${detail:0:$detail_w}"
|
|
175
|
+
printf " %b%s%b %b%s%b %-6s %s\n" \
|
|
176
|
+
"$DIM" "$short_ts" "$RESET" \
|
|
177
|
+
"$a_color" "$a_icon" "$RESET" \
|
|
178
|
+
"$a_label" "$first"
|
|
179
|
+
# 이어질 줄 (긴 detail 은 접지 않고 들여쓰기로 이어서 출력)
|
|
180
|
+
local rest="${detail:$detail_w}"
|
|
181
|
+
while [ -n "$rest" ]; do
|
|
182
|
+
local chunk="${rest:0:$detail_w}"
|
|
183
|
+
rest="${rest:$detail_w}"
|
|
184
|
+
printf " %*s%s\n" "$prefix_w" "" "$chunk"
|
|
185
|
+
done
|
|
186
|
+
done
|
|
187
|
+
fi
|
|
188
|
+
fi
|
|
189
|
+
if [ "$have_logs" -eq 0 ]; then
|
|
190
|
+
printf " %b(no activity)%b\n" "$DIM" "$RESET"
|
|
138
191
|
fi
|
|
139
192
|
}
|
|
140
193
|
|
|
141
194
|
render_v4() {
|
|
195
|
+
# 단일 팀 모드 (tmux per-team pane)
|
|
196
|
+
if [ -n "$TEAM_FILTER" ]; then
|
|
197
|
+
local rows log_lines
|
|
198
|
+
rows=$(tput lines 2>/dev/null || echo 20)
|
|
199
|
+
log_lines=$(( rows - 5 ))
|
|
200
|
+
[ "$log_lines" -lt 3 ] && log_lines=3
|
|
201
|
+
render_team_section "$TEAM_FILTER" "$log_lines"
|
|
202
|
+
return
|
|
203
|
+
fi
|
|
204
|
+
|
|
142
205
|
render_v4_header
|
|
143
206
|
|
|
144
|
-
# 팀 수 확인
|
|
145
207
|
local team_count=3
|
|
146
208
|
if [ -f "$QUEUE" ]; then
|
|
147
209
|
team_count=$(jq '.teams | length' "$QUEUE" 2>/dev/null || echo 3)
|
|
148
210
|
fi
|
|
211
|
+
[ "$team_count" -lt 1 ] && team_count=3
|
|
212
|
+
|
|
213
|
+
local rows per_team log_lines
|
|
214
|
+
rows=$(tput lines 2>/dev/null || echo 40)
|
|
215
|
+
per_team=$(( (rows - 2) / team_count ))
|
|
216
|
+
log_lines=$(( per_team - 5 ))
|
|
217
|
+
if [ "$log_lines" -lt 3 ]; then log_lines=3; fi
|
|
218
|
+
if [ "$log_lines" -gt 15 ]; then log_lines=15; fi
|
|
149
219
|
|
|
150
220
|
for i in $(seq 1 "$team_count"); do
|
|
151
|
-
render_team_section "$i"
|
|
221
|
+
render_team_section "$i" "$log_lines"
|
|
152
222
|
echo ""
|
|
153
223
|
done
|
|
154
|
-
|
|
155
|
-
# Lead/시스템 이벤트 (team이 아닌 엔트리)
|
|
156
|
-
echo -e "${BOLD}SYSTEM${RESET}"
|
|
157
|
-
if [ -f "$PROGRESS_LOG" ]; then
|
|
158
|
-
grep -v 'team-[0-9]' "$PROGRESS_LOG" 2>/dev/null | grep -v '^#' | grep -v '^$' | tail -5 | while IFS= read -r line; do
|
|
159
|
-
local ts agent action detail
|
|
160
|
-
ts=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$1); print $1}')
|
|
161
|
-
agent=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$2); print $2}')
|
|
162
|
-
action=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$3); print $3}')
|
|
163
|
-
detail=$(echo "$line" | awk -F'|' '{gsub(/^ +| +$/,"",$4); print $4}')
|
|
164
|
-
|
|
165
|
-
local short_ts
|
|
166
|
-
short_ts=$(echo "$ts" | grep -oE '[0-9]{2}:[0-9]{2}' | tail -1 || echo "$ts")
|
|
167
|
-
|
|
168
|
-
if [ ${#detail} -gt 35 ]; then detail="${detail:0:33}.."; fi
|
|
169
|
-
|
|
170
|
-
printf " %b%s%b %s %b%s%b\n" \
|
|
171
|
-
"$DIM" "$short_ts" "$RESET" \
|
|
172
|
-
"$agent" \
|
|
173
|
-
"$DIM" "$detail" "$RESET"
|
|
174
|
-
done
|
|
175
|
-
fi
|
|
176
224
|
}
|
|
177
225
|
|
|
178
226
|
# ══════════════════════════════════════════
|
|
179
|
-
#
|
|
227
|
+
# Solo 모드: 단일 스트림 (기존 동작)
|
|
180
228
|
# ══════════════════════════════════════════
|
|
181
229
|
|
|
182
230
|
LAST_AGENT=""
|
|
@@ -285,26 +333,31 @@ cleanup() {
|
|
|
285
333
|
}
|
|
286
334
|
trap cleanup EXIT INT TERM
|
|
287
335
|
|
|
288
|
-
# 매 루프마다
|
|
336
|
+
# 매 루프마다 mode 동적 감지 — 시작 후에도 모드 전환 가능
|
|
289
337
|
tput civis 2>/dev/null
|
|
290
338
|
clear
|
|
291
339
|
|
|
292
340
|
CURRENT_MODE=""
|
|
293
341
|
|
|
294
342
|
while true; do
|
|
295
|
-
# 동적 모드 감지
|
|
296
|
-
if [ -f "$QUEUE" ]; then
|
|
297
|
-
NEW_MODE="
|
|
343
|
+
# 동적 모드 감지 (--team 지정 시 항상 team, 그 외 progress.json.mode 참조)
|
|
344
|
+
if [ -n "$TEAM_FILTER" ] || [ -f "$QUEUE" ]; then
|
|
345
|
+
NEW_MODE="team"
|
|
298
346
|
else
|
|
299
|
-
|
|
347
|
+
if [ -f "$PROGRESS" ] && command -v jq &>/dev/null; then
|
|
348
|
+
NEW_MODE=$(jq -r '.mode // "solo"' "$PROGRESS" 2>/dev/null)
|
|
349
|
+
[ "$NEW_MODE" = "team" ] || NEW_MODE="solo"
|
|
350
|
+
else
|
|
351
|
+
NEW_MODE="solo"
|
|
352
|
+
fi
|
|
300
353
|
fi
|
|
301
354
|
|
|
302
355
|
# 모드 전환 시 화면 초기화
|
|
303
356
|
if [ "$NEW_MODE" != "$CURRENT_MODE" ]; then
|
|
304
357
|
clear
|
|
305
358
|
CURRENT_MODE="$NEW_MODE"
|
|
306
|
-
if [ "$CURRENT_MODE" = "
|
|
307
|
-
#
|
|
359
|
+
if [ "$CURRENT_MODE" = "solo" ]; then
|
|
360
|
+
# solo 초기화
|
|
308
361
|
if [ -f "$PROGRESS" ]; then
|
|
309
362
|
LAST_AGENT=$(jq -r '.current_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
310
363
|
LAST_STATUS=$(jq -r '.agent_status // "pending"' "$PROGRESS" 2>/dev/null)
|
|
@@ -314,7 +367,7 @@ while true; do
|
|
|
314
367
|
fi
|
|
315
368
|
fi
|
|
316
369
|
|
|
317
|
-
if [ "$CURRENT_MODE" = "
|
|
370
|
+
if [ "$CURRENT_MODE" = "team" ]; then
|
|
318
371
|
buf=$(render_v4 2>&1)
|
|
319
372
|
tput cup 0 0 2>/dev/null
|
|
320
373
|
echo "$buf"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# harness-prompt-history.sh — Prompt History pane for
|
|
2
|
+
# harness-prompt-history.sh — Prompt History pane for tmux layout
|
|
3
3
|
# progress.log + audit.log에서 유저 프롬프트/에이전트 활동 히스토리를 표시
|
|
4
4
|
# Usage: bash scripts/harness-prompt-history.sh [project-root]
|
|
5
5
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# 새 세션 시작 시 자동으로:
|
|
4
4
|
# 1) 이전 에이전트가 completed이면 harness-next.sh 실행 (게이트 + handoff)
|
|
5
5
|
# 2) Planner/Dispatcher 사이클이면 audit 리셋
|
|
6
|
-
# 3)
|
|
6
|
+
# 3) 모드별 안내 출력
|
|
7
7
|
|
|
8
8
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
9
|
LIB="$SCRIPT_DIR/lib/harness-render-progress.sh"
|
|
@@ -25,22 +25,33 @@ sprint_num=$(jq -r '.sprint.number // 0' "$PROGRESS" 2>/dev/null)
|
|
|
25
25
|
current_agent=$(jq -r '.current_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
26
26
|
next_agent=$(jq -r '.next_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
27
27
|
agent_status=$(jq -r '.agent_status // "pending"' "$PROGRESS" 2>/dev/null)
|
|
28
|
+
mode=$(jq -r '.mode // "solo"' "$PROGRESS" 2>/dev/null)
|
|
28
29
|
|
|
29
30
|
# ─────────────────────────────────────────
|
|
30
|
-
#
|
|
31
|
+
# Team Mode — 팀이 자율 실행 중이면 오케스트레이터 안내
|
|
31
32
|
# ─────────────────────────────────────────
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
passed
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
if [ "$mode" = "team" ]; then
|
|
34
|
+
FEATURE_QUEUE="$PROJECT_ROOT/.harness/actions/feature-queue.json"
|
|
35
|
+
passed=0; total=0; in_prog=0; failed=0
|
|
36
|
+
if [ -f "$FEATURE_QUEUE" ]; then
|
|
37
|
+
passed=$(jq '.queue.passed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
38
|
+
total=$(jq '[.queue.ready, (.queue.blocked | keys), (.queue.in_progress | keys), .queue.passed, .queue.failed] | flatten | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
39
|
+
in_prog=$(jq '.queue.in_progress | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
40
|
+
failed=$(jq '.queue.failed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
echo "# Harness Team Mode active"
|
|
40
44
|
echo "# Queue: ${passed}/${total} passed, ${in_prog} in progress, ${failed} failed"
|
|
41
|
-
echo "# Teams
|
|
42
|
-
echo "#
|
|
43
|
-
|
|
45
|
+
echo "# Teams run autonomously (Gen-Eval loop, max 5 retries)."
|
|
46
|
+
echo "# Stop: /harness-stop | Switch to solo: /harness-solo"
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# ─────────────────────────────────────────
|
|
51
|
+
# Paused Mode — 중단 상태 안내
|
|
52
|
+
# ─────────────────────────────────────────
|
|
53
|
+
if [ "$mode" = "paused" ]; then
|
|
54
|
+
echo "# Harness paused — resume with /harness-team or /harness-solo"
|
|
44
55
|
exit 0
|
|
45
56
|
fi
|
|
46
57
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# harness-statusline.sh — Claude Code statusline hook
|
|
2
|
+
# harness-statusline.sh — Claude Code statusline hook (v5 unified)
|
|
3
3
|
# 터미널 하단에 항상 고정되는 1줄 compact 상태 표시.
|
|
4
|
-
#
|
|
5
|
-
#
|
|
4
|
+
# Solo: [S1] FULL | solo | >backend | sonnet | 2/5 feat | ctx 45% | $1.23
|
|
5
|
+
# Team: [S1] FULL | team | T1:gen T2:eval T3:idle | 2/5 feat | ctx 45% | $1.23
|
|
6
6
|
|
|
7
7
|
# Read Claude Code session data from stdin
|
|
8
8
|
input=$(cat)
|
|
@@ -39,6 +39,7 @@ current_agent=$(jq -r '.current_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
|
39
39
|
agent_status=$(jq -r '.agent_status // "pending"' "$PROGRESS" 2>/dev/null)
|
|
40
40
|
next_agent=$(jq -r '.next_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
41
41
|
retry_count=$(jq -r '.sprint.retry_count // 0' "$PROGRESS" 2>/dev/null)
|
|
42
|
+
harness_mode=$(jq -r '.mode // "solo"' "$PROGRESS" 2>/dev/null)
|
|
42
43
|
|
|
43
44
|
# Pipeline short name
|
|
44
45
|
case "$pipeline" in
|
|
@@ -106,10 +107,32 @@ if [ -f "$CONFIG" ] && [ "$active_agent" != "none" ] && [ "$active_agent" != "nu
|
|
|
106
107
|
fi
|
|
107
108
|
fi
|
|
108
109
|
|
|
109
|
-
# Build compact status line
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
# Build compact status line based on mode
|
|
111
|
+
FEATURE_QUEUE="$PROJECT_ROOT/.harness/actions/feature-queue.json"
|
|
112
|
+
|
|
113
|
+
if [ "$harness_mode" = "team" ] && [ -f "$FEATURE_QUEUE" ]; then
|
|
114
|
+
# Team mode: show team status instead of single agent
|
|
115
|
+
team_info=""
|
|
116
|
+
for i in 1 2 3; do
|
|
117
|
+
t_status=$(jq -r ".teams[\"$i\"].status // \"idle\"" "$FEATURE_QUEUE" 2>/dev/null)
|
|
118
|
+
t_feature=$(jq -r ".teams[\"$i\"].feature // \"\"" "$FEATURE_QUEUE" 2>/dev/null)
|
|
119
|
+
if [ "$t_status" = "busy" ] && [ -n "$t_feature" ] && [ "$t_feature" != "null" ]; then
|
|
120
|
+
t_phase=$(jq -r --arg f "$t_feature" '.queue.in_progress[$f].phase // "?"' "$FEATURE_QUEUE" 2>/dev/null)
|
|
121
|
+
team_info+="T${i}:${t_phase} "
|
|
122
|
+
else
|
|
123
|
+
team_info+="T${i}:- "
|
|
124
|
+
fi
|
|
125
|
+
done
|
|
126
|
+
t_passed=$(jq '.queue.passed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
127
|
+
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)
|
|
128
|
+
|
|
129
|
+
echo "[S${sprint_num}] ${pl} | team | ${team_info}| ${t_passed}/${t_total} feat | ctx ${context_pct}% | \$${cost}"
|
|
113
130
|
else
|
|
114
|
-
|
|
131
|
+
# Solo/paused mode: show single agent status
|
|
132
|
+
mode_tag="${harness_mode}"
|
|
133
|
+
if [ -n "$model_short" ]; then
|
|
134
|
+
echo "[S${sprint_num}] ${pl} | ${mode_tag} | ${status_icon}${agent_short}${retry_str} | ${model_short} | ${completed_features}/${total_features} feat | ctx ${context_pct}% | \$${cost}"
|
|
135
|
+
else
|
|
136
|
+
echo "[S${sprint_num}] ${pl} | ${mode_tag} | ${status_icon}${agent_short}${retry_str} | ${completed_features}/${total_features} feat | ctx ${context_pct}% | \$${cost}"
|
|
137
|
+
fi
|
|
115
138
|
fi
|