@walwal-harness/cli 7.1.34 → 7.1.37
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 +19 -0
- package/HR-Resource/ceo/SKILL.md +15 -4
- package/HR-Resource/ops/SKILL.md +3 -3
- package/README.md +7 -2
- package/apps/harness-dashboard/components/Scene.tsx +48 -17
- package/apps/harness-dashboard/lib/__tests__/harness-state.test.ts +36 -3
- package/apps/harness-dashboard/lib/harness-state.ts +44 -20
- package/apps/harness-dashboard/package-lock.json +42 -43
- package/assets/templates/AGENTS-ko.md.template +4 -0
- package/assets/templates/AGENTS.md.template +7 -3
- package/assets/templates/config.json +1 -1
- package/assets/templates/gitignore-append.txt +6 -1
- package/assets/templates/memory.md +1 -1
- package/bin/init.js +49 -4
- package/commands/goal.md +2 -1
- package/commands/hot-fix.md +2 -1
- package/commands/submission.md +3 -2
- package/conventions/ceo.md +2 -0
- package/gotchas/ceo.md +4 -0
- package/package.json +1 -1
- package/scripts/harness-activity-record.js +6 -1
- package/scripts/harness-dashboard-up.sh +36 -8
- package/scripts/harness-hourly-review.sh +1 -1
- package/scripts/harness-service-ops-monitor.sh +2 -2
- package/scripts/harness-stop.sh +18 -17
- package/scripts/harness-user-prompt-submit.sh +2 -0
- package/scripts/harness-wake-install.sh +68 -15
- package/scripts/harness-worker-evidence-validate.sh +35 -0
|
@@ -26,6 +26,28 @@ LAUNCH_AGENTS_DIR="$HOME/Library/LaunchAgents"
|
|
|
26
26
|
PLIST_NAME="com.walwal.harness-wake"
|
|
27
27
|
PLIST_PATH="$LAUNCH_AGENTS_DIR/$PLIST_NAME.plist"
|
|
28
28
|
|
|
29
|
+
launch_domain() {
|
|
30
|
+
echo "gui/$(id -u)"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
launch_is_loaded() {
|
|
34
|
+
local domain
|
|
35
|
+
domain="$(launch_domain)"
|
|
36
|
+
launchctl print "$domain/$PLIST_NAME" >/dev/null 2>&1
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
launch_unload() {
|
|
40
|
+
local domain
|
|
41
|
+
domain="$(launch_domain)"
|
|
42
|
+
launchctl bootout "$domain" "$PLIST_PATH" >/dev/null 2>&1 || launchctl unload "$PLIST_PATH" 2>/dev/null || true
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
launch_load() {
|
|
46
|
+
local domain
|
|
47
|
+
domain="$(launch_domain)"
|
|
48
|
+
launchctl bootstrap "$domain" "$PLIST_PATH" >/dev/null 2>&1 || launchctl load "$PLIST_PATH" 2>/dev/null
|
|
49
|
+
}
|
|
50
|
+
|
|
29
51
|
# 템플릿 위치 후보 — walwal-harness 패키지 안일 수도, 프로젝트 안일 수도.
|
|
30
52
|
detect_template() {
|
|
31
53
|
local candidates=(
|
|
@@ -39,8 +61,8 @@ detect_template() {
|
|
|
39
61
|
}
|
|
40
62
|
|
|
41
63
|
ensure_dirs() {
|
|
42
|
-
mkdir -p "$HARNESS_DIR" "$LOG_DIR" "$LAUNCH_AGENTS_DIR"
|
|
43
|
-
touch "$PROJECTS_LIST"
|
|
64
|
+
mkdir -p "$HARNESS_DIR" "$LOG_DIR" "$LAUNCH_AGENTS_DIR" || return 1
|
|
65
|
+
touch "$PROJECTS_LIST" || return 1
|
|
44
66
|
}
|
|
45
67
|
|
|
46
68
|
abs_path() {
|
|
@@ -53,19 +75,32 @@ abs_path() {
|
|
|
53
75
|
}
|
|
54
76
|
|
|
55
77
|
cmd_add() {
|
|
56
|
-
ensure_dirs
|
|
78
|
+
ensure_dirs || {
|
|
79
|
+
echo "[wake] ERROR: cannot prepare $HARNESS_DIR" >&2
|
|
80
|
+
return 1
|
|
81
|
+
}
|
|
57
82
|
local project
|
|
58
83
|
project=$(abs_path "$1")
|
|
59
84
|
if grep -Fxq "$project" "$PROJECTS_LIST" 2>/dev/null; then
|
|
60
85
|
echo "[wake] already registered: $project"
|
|
61
86
|
return 0
|
|
62
87
|
fi
|
|
63
|
-
echo "$project" >> "$PROJECTS_LIST"
|
|
88
|
+
echo "$project" >> "$PROJECTS_LIST" || {
|
|
89
|
+
echo "[wake] ERROR: cannot write $PROJECTS_LIST" >&2
|
|
90
|
+
return 1
|
|
91
|
+
}
|
|
92
|
+
if ! grep -Fxq "$project" "$PROJECTS_LIST" 2>/dev/null; then
|
|
93
|
+
echo "[wake] ERROR: registration did not persist: $project" >&2
|
|
94
|
+
return 1
|
|
95
|
+
fi
|
|
64
96
|
echo "[wake] added: $project"
|
|
65
97
|
}
|
|
66
98
|
|
|
67
99
|
cmd_remove() {
|
|
68
|
-
ensure_dirs
|
|
100
|
+
ensure_dirs || {
|
|
101
|
+
echo "[wake] ERROR: cannot prepare $HARNESS_DIR" >&2
|
|
102
|
+
return 1
|
|
103
|
+
}
|
|
69
104
|
local project
|
|
70
105
|
project=$(abs_path "$1")
|
|
71
106
|
if ! grep -Fxq "$project" "$PROJECTS_LIST" 2>/dev/null; then
|
|
@@ -80,7 +115,10 @@ cmd_remove() {
|
|
|
80
115
|
}
|
|
81
116
|
|
|
82
117
|
cmd_list() {
|
|
83
|
-
ensure_dirs
|
|
118
|
+
ensure_dirs || {
|
|
119
|
+
echo "[wake] ERROR: cannot prepare $HARNESS_DIR" >&2
|
|
120
|
+
return 1
|
|
121
|
+
}
|
|
84
122
|
if [ ! -s "$PROJECTS_LIST" ]; then
|
|
85
123
|
echo "(empty)"
|
|
86
124
|
return 0
|
|
@@ -89,28 +127,41 @@ cmd_list() {
|
|
|
89
127
|
}
|
|
90
128
|
|
|
91
129
|
cmd_status() {
|
|
130
|
+
ensure_dirs || {
|
|
131
|
+
echo "[wake] ERROR: cannot prepare $HARNESS_DIR" >&2
|
|
132
|
+
return 1
|
|
133
|
+
}
|
|
134
|
+
local loaded=1
|
|
92
135
|
if [ -f "$PLIST_PATH" ]; then
|
|
93
136
|
echo "[wake] plist: $PLIST_PATH (exists)"
|
|
94
137
|
else
|
|
95
138
|
echo "[wake] plist: $PLIST_PATH (NOT installed)"
|
|
96
139
|
fi
|
|
97
|
-
if
|
|
140
|
+
if launch_is_loaded; then
|
|
141
|
+
loaded=0
|
|
98
142
|
echo "[wake] launchd: loaded"
|
|
99
|
-
launchctl
|
|
143
|
+
launchctl print "$(launch_domain)/$PLIST_NAME" 2>/dev/null | awk '
|
|
144
|
+
/state =/ {print " " $0}
|
|
145
|
+
/run interval =/ {print " " $0}
|
|
146
|
+
/runs =/ {print " " $0}
|
|
147
|
+
'
|
|
100
148
|
else
|
|
101
149
|
echo "[wake] launchd: NOT loaded"
|
|
102
150
|
fi
|
|
103
151
|
echo "[wake] projects:"
|
|
104
152
|
cmd_list | sed 's/^/ /'
|
|
153
|
+
return "$loaded"
|
|
105
154
|
}
|
|
106
155
|
|
|
107
156
|
cmd_install() {
|
|
108
|
-
ensure_dirs
|
|
157
|
+
ensure_dirs || {
|
|
158
|
+
echo "[wake] ERROR: cannot prepare $HARNESS_DIR" >&2
|
|
159
|
+
return 1
|
|
160
|
+
}
|
|
109
161
|
|
|
110
162
|
# 추가 인자가 있으면 add
|
|
111
|
-
shift_count=0
|
|
112
163
|
for p in "$@"; do
|
|
113
|
-
cmd_add "$p"
|
|
164
|
+
cmd_add "$p" || return 1
|
|
114
165
|
done
|
|
115
166
|
|
|
116
167
|
local template
|
|
@@ -127,22 +178,24 @@ cmd_install() {
|
|
|
127
178
|
"$template" > "$PLIST_PATH"
|
|
128
179
|
|
|
129
180
|
# 기존 jobs 언로드 (idempotent)
|
|
130
|
-
|
|
181
|
+
launch_unload
|
|
131
182
|
|
|
132
183
|
# 로드
|
|
133
|
-
|
|
184
|
+
local loaded=1
|
|
185
|
+
if launch_load; then
|
|
186
|
+
loaded=0
|
|
134
187
|
echo "[wake] launchd loaded: $PLIST_PATH"
|
|
135
188
|
else
|
|
136
189
|
echo "[wake] WARN: launchctl load 실패. 다음 명령으로 직접 시도해 보세요:" >&2
|
|
137
190
|
echo " launchctl load $PLIST_PATH" >&2
|
|
138
191
|
fi
|
|
139
192
|
|
|
140
|
-
cmd_status
|
|
193
|
+
cmd_status || return "$loaded"
|
|
141
194
|
}
|
|
142
195
|
|
|
143
196
|
cmd_uninstall() {
|
|
144
197
|
if [ -f "$PLIST_PATH" ]; then
|
|
145
|
-
|
|
198
|
+
launch_unload
|
|
146
199
|
rm -f "$PLIST_PATH"
|
|
147
200
|
echo "[wake] uninstalled: $PLIST_PATH"
|
|
148
201
|
else
|
|
@@ -8,6 +8,7 @@ DOC_ROOT="$PROJECT_ROOT/.harness/documents"
|
|
|
8
8
|
[ -d "$DOC_ROOT" ] || exit 0
|
|
9
9
|
|
|
10
10
|
mode="${2:-text}"
|
|
11
|
+
scope="${3:-all}"
|
|
11
12
|
violations=()
|
|
12
13
|
|
|
13
14
|
has_implementation_notes() {
|
|
@@ -37,6 +38,40 @@ has_legacy_flat_worker_report() {
|
|
|
37
38
|
|
|
38
39
|
mission_dirs=$(find "$DOC_ROOT" -type f \( -name 'ceo.md' -o -name 'coo.md' -o -name 'cdo.md' -o -name 'cto.md' -o -name 'cqo.md' -o -name 'ops.md' \) -exec dirname {} \; 2>/dev/null | sort -u)
|
|
39
40
|
|
|
41
|
+
mission_mtime() {
|
|
42
|
+
stat -f '%m' "$1" 2>/dev/null || stat -c '%Y' "$1" 2>/dev/null || echo 0
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
is_terminal_lifecycle() {
|
|
46
|
+
case "$1" in
|
|
47
|
+
closed|cancelled|superseded|complete|completed|blocked) return 0 ;;
|
|
48
|
+
*) return 1 ;;
|
|
49
|
+
esac
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
latest_active_mission=""
|
|
53
|
+
if [ "$scope" = "latest-active" ]; then
|
|
54
|
+
latest_active_mtime=0
|
|
55
|
+
while IFS= read -r mission_dir; do
|
|
56
|
+
[ -n "$mission_dir" ] || continue
|
|
57
|
+
state_path="$mission_dir/mission-state.json"
|
|
58
|
+
[ -f "$state_path" ] || continue
|
|
59
|
+
active=$(jq -r '.active // false' "$state_path" 2>/dev/null || echo false)
|
|
60
|
+
lifecycle=$(jq -r '.lifecycle // .status // "unknown"' "$state_path" 2>/dev/null || echo unknown)
|
|
61
|
+
if [ "$active" != "true" ] || is_terminal_lifecycle "$lifecycle"; then
|
|
62
|
+
continue
|
|
63
|
+
fi
|
|
64
|
+
mtime=$(mission_mtime "$mission_dir")
|
|
65
|
+
if [ "${mtime:-0}" -ge "${latest_active_mtime:-0}" ]; then
|
|
66
|
+
latest_active_mtime="$mtime"
|
|
67
|
+
latest_active_mission="$mission_dir"
|
|
68
|
+
fi
|
|
69
|
+
done <<EOF
|
|
70
|
+
$mission_dirs
|
|
71
|
+
EOF
|
|
72
|
+
mission_dirs="$latest_active_mission"
|
|
73
|
+
fi
|
|
74
|
+
|
|
40
75
|
while IFS= read -r mission_dir; do
|
|
41
76
|
[ -n "$mission_dir" ] || continue
|
|
42
77
|
[ -d "$mission_dir" ] || continue
|