@walwal-harness/cli 6.0.5 → 6.1.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/CHANGELOG.md +42 -0
- package/commands/harness-solo.md +20 -20
- package/commands/harness-team.md +1 -1
- package/package.json +1 -1
- package/scripts/conductor-tick.sh +382 -0
- package/scripts/harness-archive.sh +123 -0
- package/scripts/harness-dashboard-up.sh +72 -0
- package/scripts/harness-dashboard.sh +509 -0
- package/scripts/harness-goal-init.sh +72 -0
- package/scripts/harness-goal-show.sh +37 -0
- package/scripts/harness-gotcha-memory.sh +348 -0
- package/scripts/harness-gotcha-register.sh +393 -0
- package/scripts/harness-meeting-doc.sh +153 -0
- package/scripts/harness-monitor.sh +398 -0
- package/scripts/harness-next.sh +577 -0
- package/scripts/harness-progress-set.sh +41 -0
- package/scripts/harness-prompt-history.sh +164 -0
- package/scripts/harness-queue-manager.sh +694 -0
- package/scripts/harness-session-start.sh +140 -0
- package/scripts/harness-statusline.sh +139 -0
- package/scripts/harness-task-session.sh +48 -0
- package/scripts/harness-tmux.sh +372 -0
- package/scripts/harness-user-prompt-submit.sh +123 -0
- package/scripts/init-agents-md.sh +337 -0
- package/scripts/init-ref-docs.sh +262 -0
- package/scripts/lib/harness-audit.sh +113 -0
- package/scripts/lib/harness-guardrail.sh +148 -0
- package/scripts/lib/harness-keywait.sh +57 -0
- package/scripts/lib/harness-render-progress.sh +346 -0
- package/scripts/scan-project.sh +367 -0
- package/skills/brainstorming/SKILL.md +4 -4
- package/skills/conductor/SKILL.md +12 -16
- package/skills/cqo/SKILL.md +7 -0
- package/skills/cto/SKILL.md +7 -0
- package/skills/dispatcher/SKILL.md +17 -28
- package/skills/evaluator-code-quality/SKILL.md +1 -1
- package/skills/evaluator-functional/SKILL.md +1 -1
- package/skills/evaluator-visual/SKILL.md +1 -1
- package/skills/generator-backend/SKILL.md +1 -1
- package/skills/generator-frontend/SKILL.md +1 -1
- package/skills/meeting-manager/SKILL.md +33 -1
- package/skills/planner/SKILL.md +23 -9
- package/skills/service-ops/SKILL.md +19 -4
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# harness-session-start.sh — SessionStart 훅
|
|
3
|
+
# 새 세션 시작 시 자동으로:
|
|
4
|
+
# 1) 이전 에이전트가 completed이면 harness-next.sh 실행 (게이트 + handoff)
|
|
5
|
+
# 2) Planner/Dispatcher 사이클이면 audit 리셋
|
|
6
|
+
# 3) 모드별 안내 출력
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
9
|
+
LIB="$SCRIPT_DIR/lib/harness-render-progress.sh"
|
|
10
|
+
AUDIT_LIB="$SCRIPT_DIR/lib/harness-audit.sh"
|
|
11
|
+
|
|
12
|
+
if [ ! -f "$LIB" ]; then exit 0; fi
|
|
13
|
+
source "$LIB"
|
|
14
|
+
[ -f "$AUDIT_LIB" ] && source "$AUDIT_LIB"
|
|
15
|
+
command -v jq &>/dev/null || exit 0
|
|
16
|
+
|
|
17
|
+
PROJECT_ROOT="$(resolve_harness_root "." 2>/dev/null)" || exit 0
|
|
18
|
+
PROGRESS="$PROJECT_ROOT/.harness/progress.json"
|
|
19
|
+
CONFIG="$PROJECT_ROOT/.harness/config.json"
|
|
20
|
+
HANDOFF="$PROJECT_ROOT/.harness/handoff.json"
|
|
21
|
+
[ -f "$PROGRESS" ] || exit 0
|
|
22
|
+
|
|
23
|
+
sprint_status=$(jq -r '.sprint.status // "init"' "$PROGRESS" 2>/dev/null)
|
|
24
|
+
sprint_num=$(jq -r '.sprint.number // 0' "$PROGRESS" 2>/dev/null)
|
|
25
|
+
current_agent=$(jq -r '.current_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
26
|
+
next_agent=$(jq -r '.next_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
27
|
+
agent_status=$(jq -r '.agent_status // "pending"' "$PROGRESS" 2>/dev/null)
|
|
28
|
+
mode=$(jq -r '.mode // "team"' "$PROGRESS" 2>/dev/null)
|
|
29
|
+
conductor_state=$(jq -r '.conductor.state // "idle"' "$PROGRESS" 2>/dev/null)
|
|
30
|
+
|
|
31
|
+
# ─────────────────────────────────────────
|
|
32
|
+
# Auto-heal mode drift — Team 상태 유실 복구
|
|
33
|
+
# feature-queue.json 에 활성 작업(in_progress)이 있는데 mode 가 solo/paused 면
|
|
34
|
+
# 누군가 progress.json 을 통째로 덮어써서 team_state 를 날린 것. mode=team 으로
|
|
35
|
+
# 자동 복원하고 경고 로그 남김.
|
|
36
|
+
# ─────────────────────────────────────────
|
|
37
|
+
FEATURE_QUEUE_HEAL="$PROJECT_ROOT/.harness/actions/feature-queue.json"
|
|
38
|
+
if [ -f "$FEATURE_QUEUE_HEAL" ] && [ "$mode" != "team" ]; then
|
|
39
|
+
active_count=$(jq -r '(.queue.in_progress | length) // 0' "$FEATURE_QUEUE_HEAL" 2>/dev/null || echo 0)
|
|
40
|
+
if [ "${active_count:-0}" -gt 0 ]; then
|
|
41
|
+
heal_teams=$active_count
|
|
42
|
+
[ "$heal_teams" -gt 3 ] && heal_teams=3
|
|
43
|
+
bash "$SCRIPT_DIR/harness-progress-set.sh" "$PROJECT_ROOT" \
|
|
44
|
+
".mode = \"team\" | .team_state.active_teams = ${heal_teams} | .team_state.paused_at = null" \
|
|
45
|
+
2>/dev/null
|
|
46
|
+
mode="team"
|
|
47
|
+
echo "# Harness: mode auto-healed to 'team' (feature-queue has ${active_count} active, but mode was drifted)" >&2
|
|
48
|
+
if [ -f "$PROJECT_ROOT/.harness/progress.log" ]; then
|
|
49
|
+
echo "$(date +'%Y-%m-%d %H:%M') | system | heal | mode | reset solo→team (queue had ${active_count} in_progress)" >> "$PROJECT_ROOT/.harness/progress.log"
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# ─────────────────────────────────────────
|
|
55
|
+
# Team Mode — 팀이 자율 실행 중이면 오케스트레이터 안내
|
|
56
|
+
# ─────────────────────────────────────────
|
|
57
|
+
if [ "$mode" = "team" ]; then
|
|
58
|
+
FEATURE_QUEUE="$PROJECT_ROOT/.harness/actions/feature-queue.json"
|
|
59
|
+
passed=0; total=0; in_prog=0; failed=0
|
|
60
|
+
if [ -f "$FEATURE_QUEUE" ]; then
|
|
61
|
+
passed=$(jq '.queue.passed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
62
|
+
total=$(jq '[.queue.ready, (.queue.blocked | keys), (.queue.in_progress | keys), .queue.passed, .queue.failed] | flatten | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
63
|
+
in_prog=$(jq '.queue.in_progress | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
64
|
+
failed=$(jq '.queue.failed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
echo "# Harness Team Mode active"
|
|
68
|
+
echo "# Queue: ${passed}/${total} passed, ${in_prog} in progress, ${failed} failed"
|
|
69
|
+
echo "# Worker pool runs autonomously (Gen-Eval loop, max 5 retries). Control-plane Cxx agents are outside this limit."
|
|
70
|
+
echo "# Stop: /harness-stop | Emergency fallback: /harness-solo"
|
|
71
|
+
exit 0
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# ─────────────────────────────────────────
|
|
75
|
+
# Paused Mode — 중단 상태 안내
|
|
76
|
+
# ─────────────────────────────────────────
|
|
77
|
+
if [ "$mode" = "paused" ]; then
|
|
78
|
+
echo "# Harness paused — resume with /harness-team"
|
|
79
|
+
exit 0
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
# ─────────────────────────────────────────
|
|
83
|
+
# init 상태: 첫 안내
|
|
84
|
+
# ─────────────────────────────────────────
|
|
85
|
+
if [ "$sprint_status" = "init" ]; then
|
|
86
|
+
echo "# Harness ready — say \"하네스 엔지니어링 시작\" or /harness-dispatcher"
|
|
87
|
+
echo "# 기본 경로는 회사 루프입니다: dispatch -> CEO meeting -> COO/CTO 분배 -> gen/eval -> CQO -> service-ops -> batch meeting."
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# ─────────────────────────────────────────
|
|
92
|
+
# Audit lifecycle: Planner/Dispatcher 시작 시 리셋
|
|
93
|
+
# ─────────────────────────────────────────
|
|
94
|
+
init_audit "$PROJECT_ROOT"
|
|
95
|
+
if [ "$next_agent" = "planner" ] || [ "$next_agent" = "dispatcher" ]; then
|
|
96
|
+
# 새 사이클 — 이전 audit을 archive로 이동하고 새로 시작
|
|
97
|
+
reset_audit "$PROJECT_ROOT" "$sprint_num"
|
|
98
|
+
audit_log "system" "cycle" "start" "sprint-${sprint_num}" "new plan/dispatch cycle"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# ─────────────────────────────────────────
|
|
102
|
+
# 이전 에이전트가 completed/failed → 자동 전환
|
|
103
|
+
# ─────────────────────────────────────────
|
|
104
|
+
if [ "$agent_status" = "completed" ] || [ "$agent_status" = "failed" ]; then
|
|
105
|
+
bash "$SCRIPT_DIR/harness-next.sh" "$PROJECT_ROOT" 2>/dev/null
|
|
106
|
+
|
|
107
|
+
next_agent=$(jq -r '.next_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
108
|
+
agent_status=$(jq -r '.agent_status // "pending"' "$PROGRESS" 2>/dev/null)
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# ─────────────────────────────────────────
|
|
112
|
+
# Conductor running/queued → refresh routing once on session start
|
|
113
|
+
# ─────────────────────────────────────────
|
|
114
|
+
if [ "$conductor_state" = "running" ] || [ "$next_agent" = "conductor" ]; then
|
|
115
|
+
if [ -x "$SCRIPT_DIR/conductor-tick.sh" ]; then
|
|
116
|
+
bash "$SCRIPT_DIR/conductor-tick.sh" "$PROJECT_ROOT" >/dev/null 2>&1 || true
|
|
117
|
+
next_agent=$(jq -r '.next_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# ─────────────────────────────────────────
|
|
122
|
+
# 상태별 안내 출력
|
|
123
|
+
# ─────────────────────────────────────────
|
|
124
|
+
if [ "$agent_status" = "blocked" ]; then
|
|
125
|
+
echo "# Harness BLOCKED — retry limit reached, user intervention required"
|
|
126
|
+
|
|
127
|
+
elif [ -f "$HANDOFF" ] && [ "$next_agent" != "none" ] && [ "$next_agent" != "null" ]; then
|
|
128
|
+
handoff_model=$(jq -r '.model // "opus"' "$HANDOFF" 2>/dev/null)
|
|
129
|
+
handoff_thinking=$(jq -r '.thinking_mode // empty' "$HANDOFF" 2>/dev/null)
|
|
130
|
+
|
|
131
|
+
mode_str=""
|
|
132
|
+
if [ -n "$handoff_thinking" ] && [ "$handoff_thinking" != "null" ]; then
|
|
133
|
+
mode_str=" /${handoff_thinking}"
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
echo "# Harness: next → /harness-${next_agent} (${handoff_model}${mode_str})"
|
|
137
|
+
|
|
138
|
+
elif [ "$current_agent" != "none" ] && [ "$current_agent" != "null" ]; then
|
|
139
|
+
echo "# Harness: ${current_agent} [${agent_status}]"
|
|
140
|
+
fi
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# harness-statusline.sh — Claude Code statusline hook (v5 unified)
|
|
3
|
+
# 터미널 하단에 항상 고정되는 1줄 compact 상태 표시.
|
|
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
|
+
|
|
7
|
+
# Read Claude Code session data from stdin
|
|
8
|
+
input=$(cat)
|
|
9
|
+
|
|
10
|
+
# Extract Claude Code built-in data
|
|
11
|
+
context_pct=$(echo "$input" | jq -r '.context_window.used_percentage // 0' 2>/dev/null | cut -d. -f1)
|
|
12
|
+
cost=$(echo "$input" | jq -r '.cost.total_cost_usd // 0' 2>/dev/null)
|
|
13
|
+
|
|
14
|
+
# Resolve project root (walk up from cwd)
|
|
15
|
+
CWD=$(echo "$input" | jq -r '.workspace.current_dir // empty' 2>/dev/null)
|
|
16
|
+
if [ -z "$CWD" ]; then CWD="$PWD"; fi
|
|
17
|
+
|
|
18
|
+
PROJECT_ROOT="$CWD"
|
|
19
|
+
while [ "$PROJECT_ROOT" != "/" ]; do
|
|
20
|
+
if [ -d "$PROJECT_ROOT/.harness" ]; then break; fi
|
|
21
|
+
PROJECT_ROOT="$(dirname "$PROJECT_ROOT")"
|
|
22
|
+
done
|
|
23
|
+
|
|
24
|
+
PROGRESS="$PROJECT_ROOT/.harness/progress.json"
|
|
25
|
+
FEATURE_LIST="$PROJECT_ROOT/.harness/actions/feature-list.json"
|
|
26
|
+
PIPELINE_JSON="$PROJECT_ROOT/.harness/actions/pipeline.json"
|
|
27
|
+
|
|
28
|
+
# No harness → minimal status
|
|
29
|
+
if [ ! -f "$PROGRESS" ]; then
|
|
30
|
+
echo "harness: not initialized | ctx ${context_pct}%"
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
# Read harness state
|
|
35
|
+
sprint_num=$(jq -r '.sprint.number // 0' "$PROGRESS" 2>/dev/null)
|
|
36
|
+
sprint_status=$(jq -r '.sprint.status // "init"' "$PROGRESS" 2>/dev/null)
|
|
37
|
+
pipeline=$(jq -r '.pipeline // "?"' "$PROGRESS" 2>/dev/null)
|
|
38
|
+
current_agent=$(jq -r '.current_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
39
|
+
agent_status=$(jq -r '.agent_status // "pending"' "$PROGRESS" 2>/dev/null)
|
|
40
|
+
next_agent=$(jq -r '.next_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
41
|
+
retry_count=$(jq -r '.sprint.retry_count // 0' "$PROGRESS" 2>/dev/null)
|
|
42
|
+
harness_mode=$(jq -r '.mode // "solo"' "$PROGRESS" 2>/dev/null)
|
|
43
|
+
|
|
44
|
+
# Pipeline short name
|
|
45
|
+
case "$pipeline" in
|
|
46
|
+
FULLSTACK) pl="FULL" ;;
|
|
47
|
+
FE-ONLY) pl="FE" ;;
|
|
48
|
+
BE-ONLY) pl="BE" ;;
|
|
49
|
+
null|"?") pl="?" ;;
|
|
50
|
+
*) pl="$pipeline" ;;
|
|
51
|
+
esac
|
|
52
|
+
|
|
53
|
+
# Agent short name (strip harness prefix)
|
|
54
|
+
agent_short="${current_agent#generator-}"
|
|
55
|
+
agent_short="${agent_short#evaluator-}"
|
|
56
|
+
if [ "$current_agent" = "none" ] || [ "$current_agent" = "null" ]; then
|
|
57
|
+
agent_short="$next_agent"
|
|
58
|
+
if [ "$agent_short" = "none" ] || [ "$agent_short" = "null" ]; then
|
|
59
|
+
agent_short="idle"
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Feature progress
|
|
64
|
+
total_features=0
|
|
65
|
+
completed_features=0
|
|
66
|
+
if [ -f "$FEATURE_LIST" ]; then
|
|
67
|
+
total_features=$(jq '.features | length' "$FEATURE_LIST" 2>/dev/null || echo 0)
|
|
68
|
+
completed_features=$(jq '[.features[]? | select(
|
|
69
|
+
(.passes // []) | (
|
|
70
|
+
(map(select(. == "evaluator-code-quality")) | length > 0) and
|
|
71
|
+
(map(select(. == "evaluator-functional")) | length > 0) and
|
|
72
|
+
(map(select(. == "evaluator-visual")) | length > 0)
|
|
73
|
+
)
|
|
74
|
+
)] | length' "$FEATURE_LIST" 2>/dev/null || echo 0)
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Status indicator
|
|
78
|
+
status_icon=""
|
|
79
|
+
case "$agent_status" in
|
|
80
|
+
running) status_icon=">" ;;
|
|
81
|
+
completed) status_icon="v" ;;
|
|
82
|
+
failed) status_icon="x" ;;
|
|
83
|
+
blocked) status_icon="!" ;;
|
|
84
|
+
*) status_icon="-" ;;
|
|
85
|
+
esac
|
|
86
|
+
|
|
87
|
+
# Retry indicator
|
|
88
|
+
retry_str=""
|
|
89
|
+
if [ "$retry_count" -gt 0 ]; then
|
|
90
|
+
retry_str=" R${retry_count}"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Model/mode for current or next agent
|
|
94
|
+
CONFIG="$PROJECT_ROOT/.harness/config.json"
|
|
95
|
+
active_agent="$current_agent"
|
|
96
|
+
if [ "$active_agent" = "none" ] || [ "$active_agent" = "null" ]; then
|
|
97
|
+
active_agent=$(jq -r '.next_agent // "none"' "$PROGRESS" 2>/dev/null)
|
|
98
|
+
fi
|
|
99
|
+
model_short=""
|
|
100
|
+
if [ -f "$CONFIG" ] && [ "$active_agent" != "none" ] && [ "$active_agent" != "null" ]; then
|
|
101
|
+
am=$(jq -r ".agents[\"${active_agent}\"].model // empty" "$CONFIG" 2>/dev/null)
|
|
102
|
+
at=$(jq -r ".agents[\"${active_agent}\"].thinking_mode // empty" "$CONFIG" 2>/dev/null)
|
|
103
|
+
if [ -n "$am" ]; then
|
|
104
|
+
model_short="${am}"
|
|
105
|
+
if [ -n "$at" ] && [ "$at" != "null" ]; then
|
|
106
|
+
model_short+="/${at}"
|
|
107
|
+
fi
|
|
108
|
+
fi
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# Build compact status line based on mode
|
|
112
|
+
FEATURE_QUEUE="$PROJECT_ROOT/.harness/actions/feature-queue.json"
|
|
113
|
+
|
|
114
|
+
if [ "$harness_mode" = "team" ] && [ -f "$FEATURE_QUEUE" ]; then
|
|
115
|
+
# Team mode: show team status instead of single agent
|
|
116
|
+
team_info=""
|
|
117
|
+
for i in 1 2 3; do
|
|
118
|
+
t_status=$(jq -r ".teams[\"$i\"].status // \"idle\"" "$FEATURE_QUEUE" 2>/dev/null)
|
|
119
|
+
t_feature=$(jq -r ".teams[\"$i\"].feature // \"\"" "$FEATURE_QUEUE" 2>/dev/null)
|
|
120
|
+
if [ "$t_status" = "busy" ] && [ -n "$t_feature" ] && [ "$t_feature" != "null" ]; then
|
|
121
|
+
t_phase=$(jq -r --arg f "$t_feature" '.queue.in_progress[$f].phase // "?"' "$FEATURE_QUEUE" 2>/dev/null)
|
|
122
|
+
team_info+="T${i}:${t_phase} "
|
|
123
|
+
else
|
|
124
|
+
team_info+="T${i}:- "
|
|
125
|
+
fi
|
|
126
|
+
done
|
|
127
|
+
t_passed=$(jq '.queue.passed | length' "$FEATURE_QUEUE" 2>/dev/null || echo 0)
|
|
128
|
+
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)
|
|
129
|
+
|
|
130
|
+
echo "[S${sprint_num}] ${pl} | team | ${team_info}| ${t_passed}/${t_total} feat | ctx ${context_pct}% | \$${cost}"
|
|
131
|
+
else
|
|
132
|
+
# Solo/paused mode: show single agent status
|
|
133
|
+
mode_tag="${harness_mode}"
|
|
134
|
+
if [ -n "$model_short" ]; then
|
|
135
|
+
echo "[S${sprint_num}] ${pl} | ${mode_tag} | ${status_icon}${agent_short}${retry_str} | ${model_short} | ${completed_features}/${total_features} feat | ctx ${context_pct}% | \$${cost}"
|
|
136
|
+
else
|
|
137
|
+
echo "[S${sprint_num}] ${pl} | ${mode_tag} | ${status_icon}${agent_short}${retry_str} | ${completed_features}/${total_features} feat | ctx ${context_pct}% | \$${cost}"
|
|
138
|
+
fi
|
|
139
|
+
fi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# harness-task-session.sh — create per-agent task session document
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
source "$SCRIPT_DIR/lib/harness-render-progress.sh"
|
|
7
|
+
|
|
8
|
+
PROJECT_ROOT="$(resolve_harness_root "${1:-.}")" || exit 1
|
|
9
|
+
AGENT="${2:-}"
|
|
10
|
+
SOURCE="${3:-}"
|
|
11
|
+
|
|
12
|
+
[ -n "$AGENT" ] || exit 2
|
|
13
|
+
command -v jq >/dev/null 2>&1 || exit 1
|
|
14
|
+
|
|
15
|
+
PROGRESS="$PROJECT_ROOT/.harness/progress.json"
|
|
16
|
+
TASK_ROOT="$PROJECT_ROOT/.harness/actions/task-sessions/$AGENT"
|
|
17
|
+
mkdir -p "$TASK_ROOT"
|
|
18
|
+
|
|
19
|
+
dispatch_id=$(jq -r '.dispatch.id // "D-000"' "$PROGRESS")
|
|
20
|
+
sprint_num=$(jq -r '.sprint.number // 0' "$PROGRESS")
|
|
21
|
+
ts=$(date -u +%Y%m%dT%H%M%SZ)
|
|
22
|
+
session_id="${AGENT}-S$(printf '%03d' "$sprint_num")-${ts}"
|
|
23
|
+
session_path="$TASK_ROOT/${session_id}.md"
|
|
24
|
+
|
|
25
|
+
cat > "$session_path" <<EOF
|
|
26
|
+
# Task Session — $session_id
|
|
27
|
+
|
|
28
|
+
- agent: $AGENT
|
|
29
|
+
- dispatch: $dispatch_id
|
|
30
|
+
- sprint: $sprint_num
|
|
31
|
+
- source: ${SOURCE:-none}
|
|
32
|
+
- created_at: $(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
33
|
+
|
|
34
|
+
## Allowed Inputs
|
|
35
|
+
- .harness/handoff.json
|
|
36
|
+
- .harness/progress.json
|
|
37
|
+
- assigned evidence documents only
|
|
38
|
+
|
|
39
|
+
## Rule
|
|
40
|
+
- 이전 대화 기억이 아니라 문서와 evidence만 근거로 판단할 것
|
|
41
|
+
- 사실과 추론을 분리해서 기록할 것
|
|
42
|
+
EOF
|
|
43
|
+
|
|
44
|
+
bash "$SCRIPT_DIR/harness-progress-set.sh" "$PROJECT_ROOT" \
|
|
45
|
+
".task_sessions.current = {\"agent\":\"$AGENT\",\"id\":\"$session_id\",\"path\":\"${session_path#$PROJECT_ROOT/}\",\"source\":$(jq -Rn --arg v "${SOURCE:-}" '$v')} |
|
|
46
|
+
.task_sessions.history = ((.task_sessions.history // []) + [{\"agent\":\"$AGENT\",\"id\":\"$session_id\",\"path\":\"${session_path#$PROJECT_ROOT/}\",\"source\":$(jq -Rn --arg v "${SOURCE:-}" '$v')}])" >/dev/null
|
|
47
|
+
|
|
48
|
+
echo "${session_path#$PROJECT_ROOT/}"
|