@walwal-harness/cli 3.7.2 → 3.7.4

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": "3.7.2",
3
+ "version": "3.7.4",
4
4
  "description": "Production harness for AI agent engineering — Planner, Generator(BE/FE), Evaluator(Func/Visual), optional Brainstormer (requirements refinement). Supports React and Flutter FE stacks.",
5
5
  "bin": {
6
6
  "walwal-harness": "bin/init.js"
@@ -38,8 +38,23 @@ RED="\033[31m"
38
38
  CYAN="\033[36m"
39
39
  RESET="\033[0m"
40
40
 
41
- # ── Agent Session pane target ──
42
- AGENT_PANE="harness-studio.2"
41
+ # ── Agent Session pane target (find by title) ──
42
+ find_agent_pane() {
43
+ tmux list-panes -t harness-studio -F '#{pane_id} #{pane_title}' 2>/dev/null \
44
+ | grep "Agent Session" | awk '{print $1}' | head -1
45
+ }
46
+
47
+ CONFIG="$PROJECT_ROOT/.harness/config.json"
48
+
49
+ # Build claude command from config
50
+ build_claude_cmd() {
51
+ local agent="$1"
52
+ local model="opus"
53
+ if [ -f "$CONFIG" ]; then
54
+ model=$(jq -r ".agents[\"${agent}\"].model // \"opus\"" "$CONFIG" 2>/dev/null)
55
+ fi
56
+ echo "claude --dangerously-skip-permissions --model ${model}"
57
+ }
43
58
 
44
59
  cmd_log() {
45
60
  local msg="$1"
@@ -63,8 +78,10 @@ cmd_clear_fail() {
63
78
  }
64
79
 
65
80
  cmd_next() {
66
- if ! tmux list-panes -t harness-studio 2>/dev/null | grep -q .; then
67
- echo -e " ${RED}tmux session not found.${RESET}"
81
+ local pane
82
+ pane=$(find_agent_pane)
83
+ if [ -z "$pane" ]; then
84
+ echo -e " ${RED}Agent Session pane not found.${RESET}"
68
85
  return
69
86
  fi
70
87
 
@@ -75,16 +92,25 @@ cmd_next() {
75
92
  return
76
93
  fi
77
94
 
78
- echo -e " ${CYAN}Starting ${next_agent} in Agent Session...${RESET}"
95
+ local claude_cmd
96
+ claude_cmd=$(build_claude_cmd "$next_agent")
97
+
98
+ echo -e " ${CYAN}Starting ${next_agent}...${RESET}"
99
+ echo -e " ${DIM}${claude_cmd}${RESET}"
100
+
79
101
  local ts
80
102
  ts=$(date +"%Y-%m-%d")
81
103
  echo "${ts} | manual | start-agent | ${next_agent}" >> "$PROGRESS_LOG"
82
- tmux send-keys -t "$AGENT_PANE" "/harness-${next_agent}" Enter
104
+
105
+ # Launch claude in Agent Session pane with the agent's prompt
106
+ tmux send-keys -t "$pane" "${claude_cmd} -p '하네스 엔지니어링 시작'" Enter
83
107
  }
84
108
 
85
109
  cmd_retry() {
86
- if ! tmux list-panes -t harness-studio 2>/dev/null | grep -q .; then
87
- echo -e " ${RED}tmux session not found.${RESET}"
110
+ local pane
111
+ pane=$(find_agent_pane)
112
+ if [ -z "$pane" ]; then
113
+ echo -e " ${RED}Agent Session pane not found.${RESET}"
88
114
  return
89
115
  fi
90
116
 
@@ -95,21 +121,26 @@ cmd_retry() {
95
121
  return
96
122
  fi
97
123
 
124
+ local claude_cmd
125
+ claude_cmd=$(build_claude_cmd "$current_agent")
126
+
98
127
  echo -e " ${CYAN}Retrying ${current_agent}...${RESET}"
99
128
  local ts
100
129
  ts=$(date +"%Y-%m-%d")
101
130
  echo "${ts} | manual | retry | ${current_agent}" >> "$PROGRESS_LOG"
102
- tmux send-keys -t "$AGENT_PANE" "/harness-${current_agent}" Enter
131
+ tmux send-keys -t "$pane" "${claude_cmd} -p '하네스 엔지니어링 시작'" Enter
103
132
  }
104
133
 
105
134
  cmd_stop() {
106
- if ! tmux list-panes -t harness-studio 2>/dev/null | grep -q .; then
107
- echo -e " ${RED}tmux session not found.${RESET}"
135
+ local pane
136
+ pane=$(find_agent_pane)
137
+ if [ -z "$pane" ]; then
138
+ echo -e " ${RED}Agent Session pane not found.${RESET}"
108
139
  return
109
140
  fi
110
141
 
111
142
  echo -e " ${YELLOW}Sending Ctrl+C to Agent Session...${RESET}"
112
- tmux send-keys -t "$AGENT_PANE" C-c
143
+ tmux send-keys -t "$pane" C-c
113
144
  local ts
114
145
  ts=$(date +"%Y-%m-%d")
115
146
  echo "${ts} | manual | stop | user-initiated" >> "$PROGRESS_LOG"
@@ -1,22 +1,21 @@
1
1
  #!/bin/bash
2
- # harness-tmux.sh — Harness Studio tmux 4-pane 레이아웃
2
+ # harness-tmux.sh — Harness Studio tmux 5-pane 레이아웃
3
3
  #
4
- # ┌───────────────────────────┬─────────────────────────┐
5
- # │ │ Monitor (compact) │
6
- # │ Main: Control Center ├─────────────────────────┤
7
- # │ (Dashboard + Manual │ Agent Session │
8
- # │ Prompt + Orchestration) │ (claude --skip-perms) │
9
- # │ ├─────────────────────────┤
10
- # │ │ Eval Review │
11
- # │ │ (eval 결과 요약) │
12
- # └───────────────────────────┴─────────────────────────┘
4
+ # ┌─────────────────────────┬────────────────────────┐
5
+ # │ Dashboard (auto-refresh)│ Monitor (compact) │
6
+ # │ ├────────────────────────┤
7
+ # │ │ Agent Session (claude) │
8
+ # ├─────────────────────────┤ │
9
+ # │ Control (harness> _) ├────────────────────────┤
10
+ # │ │ Eval Review │
11
+ # └─────────────────────────┴────────────────────────┘
13
12
  #
14
13
  # Usage:
15
14
  # bash scripts/harness-tmux.sh [project-root]
16
15
  # bash scripts/harness-tmux.sh /path/to/project --ai
17
16
  #
18
17
  # Options:
19
- # --ai Eval Review에서 claude -p 로 AI 요약 생성
18
+ # --ai Eval Review에서 claude -p AI 요약
20
19
  # --detach 세션 생성 후 attach 하지 않음
21
20
  # --kill 기존 harness-studio 세션 종료
22
21
 
@@ -34,7 +33,7 @@ for arg in "$@"; do
34
33
  --ai) USE_AI="--ai" ;;
35
34
  --detach) DETACH=true ;;
36
35
  --kill)
37
- tmux kill-session -t "$SESSION_NAME" 2>/dev/null && echo "Session '$SESSION_NAME' killed." || echo "No session to kill."
36
+ tmux kill-session -t "$SESSION_NAME" 2>/dev/null && echo "Killed." || echo "No session."
38
37
  exit 0
39
38
  ;;
40
39
  *)
@@ -43,7 +42,6 @@ for arg in "$@"; do
43
42
  esac
44
43
  done
45
44
 
46
- # Auto-detect project root
47
45
  if [ -z "$PROJECT_ROOT" ]; then
48
46
  dir="$(pwd)"
49
47
  while [ "$dir" != "/" ]; do
@@ -53,18 +51,16 @@ if [ -z "$PROJECT_ROOT" ]; then
53
51
  fi
54
52
 
55
53
  if [ -z "$PROJECT_ROOT" ] || [ ! -d "$PROJECT_ROOT/.harness" ]; then
56
- echo "Error: .harness/ directory not found."
57
- echo "Usage: bash scripts/harness-tmux.sh [project-root]"
54
+ echo "Error: .harness/ not found."
58
55
  exit 1
59
56
  fi
60
57
 
61
58
  echo "Project: $PROJECT_ROOT"
62
59
  echo "Session: $SESSION_NAME"
63
60
 
64
- # Kill existing session if any
65
61
  tmux kill-session -t "$SESSION_NAME" 2>/dev/null || true
66
62
 
67
- # ── Resolve Claude command for Agent Session ──
63
+ # ── Resolve Claude command ──
68
64
  HANDOFF="$PROJECT_ROOT/.harness/handoff.json"
69
65
  CLAUDE_CMD="claude --dangerously-skip-permissions"
70
66
  if [ -f "$HANDOFF" ]; then
@@ -75,66 +71,66 @@ if [ -f "$HANDOFF" ]; then
75
71
  fi
76
72
 
77
73
  # ══════════════════════════════════════════
78
- # Layout Construction
79
- # ══════════════════════════════════════════
80
- # ══════════════════════════════════════════
81
- # Pane layout:
82
- # 0 = Dashboard (top-left, auto-refresh)
83
- # 1 = Monitor (top-right, compact)
84
- # 2 = Agent Session (mid-right, claude)
85
- # 3 = Eval Review (bottom-right)
86
- # 4 = Control Prompt (bottom-left, interactive)
74
+ # Build layout using explicit pane IDs
87
75
  # ══════════════════════════════════════════
88
76
 
89
- # Step 1: Create session → Pane 0 = Dashboard (top-left)
90
- tmux new-session -d -s "$SESSION_NAME" -c "$PROJECT_ROOT" -x 200 -y 50 \
91
- "exec bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-dashboard.sh\" \"${PROJECT_ROOT}\"'"
77
+ # 1. Create session → capture Dashboard pane ID
78
+ PANE_DASHBOARD=$(tmux new-session -d -s "$SESSION_NAME" -c "$PROJECT_ROOT" -x 200 -y 50 \
79
+ -P -F '#{pane_id}' \
80
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-dashboard.sh\" \"${PROJECT_ROOT}\"'")
92
81
 
93
- # Step 2: Split right column (45%) → Pane 1 = Monitor (top-right, compact)
94
- tmux split-window -h -p 45 -t "$SESSION_NAME" -c "$PROJECT_ROOT" \
95
- "exec bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-monitor.sh\" \"${PROJECT_ROOT}\"'"
82
+ # 2. Split Dashboard horizontally (55% left / 45% right) → Monitor pane
83
+ PANE_MONITOR=$(tmux split-window -h -p 45 -t "$PANE_DASHBOARD" -c "$PROJECT_ROOT" \
84
+ -P -F '#{pane_id}' \
85
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-monitor.sh\" \"${PROJECT_ROOT}\"'")
96
86
 
97
- # Step 3: Split Pane 1 vertically (80% below) → Pane 2 = Agent Session
98
- tmux split-window -v -p 80 -t "${SESSION_NAME}.1" -c "$PROJECT_ROOT"
99
- tmux send-keys -t "${SESSION_NAME}.2" "$CLAUDE_CMD" Enter
87
+ # 3. Split Dashboard vertically (75% top / 25% bottom) → Control pane
88
+ PANE_CONTROL=$(tmux split-window -v -p 25 -t "$PANE_DASHBOARD" -c "$PROJECT_ROOT" \
89
+ -P -F '#{pane_id}' \
90
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-control.sh\" \"${PROJECT_ROOT}\"'")
100
91
 
101
- # Step 4: Split Pane 2 vertically (50%) → Pane 3 = Eval Review
102
- tmux split-window -v -p 50 -t "${SESSION_NAME}.2" -c "$PROJECT_ROOT" \
103
- "exec bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-eval-watcher.sh\" \"${PROJECT_ROOT}\" ${USE_AI}'"
92
+ # 4. Split Monitor vertically (15% top / 85% bottom) → Agent Session pane
93
+ PANE_AGENT=$(tmux split-window -v -p 85 -t "$PANE_MONITOR" -c "$PROJECT_ROOT" \
94
+ -P -F '#{pane_id}')
104
95
 
105
- # Step 5: Split Dashboard (Pane 0) vertically → Pane 4 = Control Prompt (bottom-left)
106
- # Dashboard gets ~75% height, Control Prompt gets ~25%
107
- tmux split-window -v -p 25 -t "${SESSION_NAME}.0" -c "$PROJECT_ROOT"
108
- tmux send-keys -t "${SESSION_NAME}.4" "bash ${SCRIPT_DIR}/harness-control.sh '${PROJECT_ROOT}'" Enter
96
+ # 5. Split Agent Session vertically (55% top / 45% bottom) → Eval Review pane
97
+ PANE_EVAL=$(tmux split-window -v -p 45 -t "$PANE_AGENT" -c "$PROJECT_ROOT" \
98
+ -P -F '#{pane_id}' \
99
+ "bash --norc --noprofile -c 'exec bash \"${SCRIPT_DIR}/harness-eval-watcher.sh\" \"${PROJECT_ROOT}\" ${USE_AI}'")
109
100
 
110
- # ── Select Control Prompt as active (where user types) ──
111
- tmux select-pane -t "${SESSION_NAME}.4"
101
+ # 6. Agent Session — leave as empty shell, ready for Control to launch claude
102
+ # Pre-unset nvm conflict variable
103
+ tmux send-keys -t "$PANE_AGENT" "unset npm_config_prefix 2>/dev/null" Enter
104
+ tmux send-keys -t "$PANE_AGENT" "clear" Enter
112
105
 
113
106
  # ── Pane titles ──
114
- tmux select-pane -t "${SESSION_NAME}.0" -T "Dashboard"
115
- tmux select-pane -t "${SESSION_NAME}.1" -T "Monitor"
116
- tmux select-pane -t "${SESSION_NAME}.2" -T "Agent Session"
117
- tmux select-pane -t "${SESSION_NAME}.3" -T "Eval Review"
118
- tmux select-pane -t "${SESSION_NAME}.4" -T "Control"
107
+ tmux select-pane -t "$PANE_DASHBOARD" -T "Dashboard"
108
+ tmux select-pane -t "$PANE_MONITOR" -T "Monitor"
109
+ tmux select-pane -t "$PANE_CONTROL" -T "Control"
110
+ tmux select-pane -t "$PANE_AGENT" -T "Agent Session"
111
+ tmux select-pane -t "$PANE_EVAL" -T "Eval Review"
119
112
 
120
113
  tmux set-option -t "$SESSION_NAME" pane-border-status top 2>/dev/null || true
121
114
  tmux set-option -t "$SESSION_NAME" pane-border-format " #{pane_title} " 2>/dev/null || true
122
115
 
116
+ # ── Focus on Control pane (where user types) ──
117
+ tmux select-pane -t "$PANE_CONTROL"
118
+
123
119
  # ── Attach ──
124
120
  if [ "$DETACH" = true ]; then
125
121
  echo ""
126
- echo "Session created. Attach with:"
127
- echo " tmux attach -t $SESSION_NAME"
122
+ echo "Session created. Attach: tmux attach -t $SESSION_NAME"
128
123
  else
129
124
  if [ -n "${TMUX:-}" ]; then
130
125
  tmux switch-client -t "$SESSION_NAME"
131
126
  else
132
127
  echo ""
133
128
  echo "Launching harness-studio..."
134
- echo " Control Center (left) : Dashboard + manual prompting"
135
- echo " Monitor (right↑) : Agent lifecycle (compact)"
136
- echo " Agent Session (right↔) : claude --dangerously-skip-permissions"
137
- echo " Eval Review (right↓) : Evaluation summaries"
129
+ echo " Dashboard (left↑) : Auto-refresh progress"
130
+ echo " Control (left↓) : Manual commands (next/retry/stop/log)"
131
+ echo " Monitor (right↑) : Agent lifecycle (compact)"
132
+ echo " Agent Session (right↔): claude --dangerously-skip-permissions"
133
+ echo " Eval Review (right↓): Evaluation summaries"
138
134
  echo ""
139
135
  tmux attach -t "$SESSION_NAME"
140
136
  fi