autoworkflow 3.9.1 → 3.10.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/.claude/hooks/logger.sh +318 -0
- package/.claude/hooks/phase-transition.sh +12 -0
- package/.claude/hooks/post-edit.sh +12 -0
- package/.claude/hooks/pre-commit-check.sh +10 -0
- package/.claude/hooks/session-check.sh +13 -1
- package/CLAUDE.md +36 -0
- package/bin/cli.js +67 -1
- package/package.json +1 -1
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# AutoWorkflow Logger
|
|
3
|
+
# Centralized logging for all hooks, gates, and workflow events
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# source logger.sh
|
|
7
|
+
# aw_log "HOOK" "session-check.sh" "START"
|
|
8
|
+
# aw_log "GATE" "plan_approval" "PASSED"
|
|
9
|
+
# aw_log "PHASE" "PLAN" "IMPLEMENT"
|
|
10
|
+
# aw_log "VERIFY" "1/10" "checking..."
|
|
11
|
+
# aw_log "ERROR" "pre-commit" "TypeScript errors found"
|
|
12
|
+
|
|
13
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
14
|
+
# CONFIGURATION
|
|
15
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
16
|
+
|
|
17
|
+
# Project directory
|
|
18
|
+
LOGGER_PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
19
|
+
|
|
20
|
+
# Log directory and file
|
|
21
|
+
LOG_DIR="$LOGGER_PROJECT_DIR/.claude/.autoworkflow/logs"
|
|
22
|
+
LOG_FILE="$LOG_DIR/aw.log"
|
|
23
|
+
MAX_LOG_SIZE=1048576 # 1MB
|
|
24
|
+
MAX_LOG_FILES=5
|
|
25
|
+
|
|
26
|
+
# Debug mode (set AUTOWORKFLOW_DEBUG=1 to enable verbose output)
|
|
27
|
+
DEBUG_MODE="${AUTOWORKFLOW_DEBUG:-0}"
|
|
28
|
+
|
|
29
|
+
# Colors for terminal output (when viewing with tail -f)
|
|
30
|
+
LOG_RED='\033[0;31m'
|
|
31
|
+
LOG_GREEN='\033[0;32m'
|
|
32
|
+
LOG_YELLOW='\033[1;33m'
|
|
33
|
+
LOG_CYAN='\033[0;36m'
|
|
34
|
+
LOG_BLUE='\033[0;34m'
|
|
35
|
+
LOG_MAGENTA='\033[0;35m'
|
|
36
|
+
LOG_BOLD='\033[1m'
|
|
37
|
+
LOG_DIM='\033[2m'
|
|
38
|
+
LOG_NC='\033[0m'
|
|
39
|
+
|
|
40
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
41
|
+
# INITIALIZATION
|
|
42
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
43
|
+
|
|
44
|
+
# Ensure log directory exists
|
|
45
|
+
mkdir -p "$LOG_DIR"
|
|
46
|
+
|
|
47
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
48
|
+
# LOG ROTATION
|
|
49
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
50
|
+
|
|
51
|
+
rotate_logs() {
|
|
52
|
+
if [ -f "$LOG_FILE" ]; then
|
|
53
|
+
local size=$(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null || echo "0")
|
|
54
|
+
|
|
55
|
+
if [ "$size" -gt "$MAX_LOG_SIZE" ]; then
|
|
56
|
+
# Rotate existing logs
|
|
57
|
+
for i in $(seq $((MAX_LOG_FILES - 1)) -1 1); do
|
|
58
|
+
if [ -f "$LOG_FILE.$i" ]; then
|
|
59
|
+
mv "$LOG_FILE.$i" "$LOG_FILE.$((i + 1))"
|
|
60
|
+
fi
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
# Move current log to .1
|
|
64
|
+
mv "$LOG_FILE" "$LOG_FILE.1"
|
|
65
|
+
|
|
66
|
+
# Create new log file with header
|
|
67
|
+
echo "# AutoWorkflow Log - Rotated $(date '+%Y-%m-%d %H:%M:%S')" > "$LOG_FILE"
|
|
68
|
+
echo "# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" >> "$LOG_FILE"
|
|
69
|
+
echo "" >> "$LOG_FILE"
|
|
70
|
+
|
|
71
|
+
# Remove oldest if exceeds max
|
|
72
|
+
if [ -f "$LOG_FILE.$MAX_LOG_FILES" ]; then
|
|
73
|
+
rm -f "$LOG_FILE.$MAX_LOG_FILES"
|
|
74
|
+
fi
|
|
75
|
+
fi
|
|
76
|
+
fi
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
80
|
+
# LOGGING FUNCTIONS
|
|
81
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
82
|
+
|
|
83
|
+
# Get color for category
|
|
84
|
+
get_category_color() {
|
|
85
|
+
local category="$1"
|
|
86
|
+
case "$category" in
|
|
87
|
+
HOOK) echo "$LOG_CYAN" ;;
|
|
88
|
+
PHASE) echo "$LOG_BLUE" ;;
|
|
89
|
+
GATE) echo "$LOG_MAGENTA" ;;
|
|
90
|
+
VERIFY) echo "$LOG_GREEN" ;;
|
|
91
|
+
MEMORY) echo "$LOG_CYAN" ;;
|
|
92
|
+
COMMIT) echo "$LOG_GREEN" ;;
|
|
93
|
+
ERROR) echo "$LOG_RED" ;;
|
|
94
|
+
WARN) echo "$LOG_YELLOW" ;;
|
|
95
|
+
DEBUG) echo "$LOG_DIM" ;;
|
|
96
|
+
*) echo "$LOG_NC" ;;
|
|
97
|
+
esac
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
# Get symbol for status
|
|
101
|
+
get_status_symbol() {
|
|
102
|
+
local status="$1"
|
|
103
|
+
case "$status" in
|
|
104
|
+
START|STARTED) echo "▶" ;;
|
|
105
|
+
COMPLETE|DONE) echo "✓" ;;
|
|
106
|
+
PASSED|SUCCESS) echo "✓" ;;
|
|
107
|
+
FAILED|ERROR) echo "✗" ;;
|
|
108
|
+
BLOCKED|DENIED) echo "⛔" ;;
|
|
109
|
+
WAITING|PENDING) echo "◉" ;;
|
|
110
|
+
SKIPPED) echo "○" ;;
|
|
111
|
+
*) echo "●" ;;
|
|
112
|
+
esac
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
# Main logging function
|
|
116
|
+
# Usage: aw_log <CATEGORY> <SOURCE> <MESSAGE> [DETAILS]
|
|
117
|
+
aw_log() {
|
|
118
|
+
local category="${1:-INFO}"
|
|
119
|
+
local source="${2:-unknown}"
|
|
120
|
+
local message="${3:-}"
|
|
121
|
+
local details="${4:-}"
|
|
122
|
+
|
|
123
|
+
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
124
|
+
local time_only=$(date '+%H:%M:%S')
|
|
125
|
+
|
|
126
|
+
# Check for log rotation
|
|
127
|
+
rotate_logs
|
|
128
|
+
|
|
129
|
+
# Get color and symbol
|
|
130
|
+
local color=$(get_category_color "$category")
|
|
131
|
+
local symbol=$(get_status_symbol "$message")
|
|
132
|
+
|
|
133
|
+
# Format the log entry
|
|
134
|
+
local log_entry="[$time_only] [$category] $source $symbol $message"
|
|
135
|
+
[ -n "$details" ] && log_entry="$log_entry - $details"
|
|
136
|
+
|
|
137
|
+
# Write to log file (plain text, no colors)
|
|
138
|
+
echo "[$timestamp] [$category] $source $symbol $message${details:+ - $details}" >> "$LOG_FILE"
|
|
139
|
+
|
|
140
|
+
# If debug mode, also output to stderr (visible in terminal)
|
|
141
|
+
if [ "$DEBUG_MODE" = "1" ]; then
|
|
142
|
+
echo -e "${color}${log_entry}${LOG_NC}" >&2
|
|
143
|
+
fi
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# Convenience functions for common log types
|
|
147
|
+
aw_log_hook() {
|
|
148
|
+
local hook_name="$1"
|
|
149
|
+
local status="$2"
|
|
150
|
+
local details="${3:-}"
|
|
151
|
+
aw_log "HOOK" "$hook_name" "$status" "$details"
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
aw_log_phase() {
|
|
155
|
+
local from="$1"
|
|
156
|
+
local to="$2"
|
|
157
|
+
aw_log "PHASE" "$from → $to" "TRANSITION"
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
aw_log_gate() {
|
|
161
|
+
local gate_name="$1"
|
|
162
|
+
local status="$2"
|
|
163
|
+
local details="${3:-}"
|
|
164
|
+
aw_log "GATE" "$gate_name" "$status" "$details"
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
aw_log_verify() {
|
|
168
|
+
local iteration="$1"
|
|
169
|
+
local status="$2"
|
|
170
|
+
local details="${3:-}"
|
|
171
|
+
aw_log "VERIFY" "iteration $iteration" "$status" "$details"
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
aw_log_memory() {
|
|
175
|
+
local action="$1"
|
|
176
|
+
local file="$2"
|
|
177
|
+
aw_log "MEMORY" "$action" "$file"
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
aw_log_commit() {
|
|
181
|
+
local status="$1"
|
|
182
|
+
local message="${2:-}"
|
|
183
|
+
aw_log "COMMIT" "$status" "$message"
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
aw_log_error() {
|
|
187
|
+
local source="$1"
|
|
188
|
+
local message="$2"
|
|
189
|
+
aw_log "ERROR" "$source" "FAILED" "$message"
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
aw_log_warn() {
|
|
193
|
+
local source="$1"
|
|
194
|
+
local message="$2"
|
|
195
|
+
aw_log "WARN" "$source" "WARNING" "$message"
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
aw_log_debug() {
|
|
199
|
+
if [ "$DEBUG_MODE" = "1" ]; then
|
|
200
|
+
local source="$1"
|
|
201
|
+
local message="$2"
|
|
202
|
+
aw_log "DEBUG" "$source" "DEBUG" "$message"
|
|
203
|
+
fi
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
207
|
+
# LOG VIEWING FUNCTIONS
|
|
208
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
209
|
+
|
|
210
|
+
# View logs in real-time (for CLI command)
|
|
211
|
+
view_logs_live() {
|
|
212
|
+
if [ -f "$LOG_FILE" ]; then
|
|
213
|
+
echo -e "${LOG_CYAN}━━━ AutoWorkflow Logs (live) ━━━${LOG_NC}"
|
|
214
|
+
echo -e "${LOG_DIM}Press Ctrl+C to stop${LOG_NC}"
|
|
215
|
+
echo ""
|
|
216
|
+
tail -f "$LOG_FILE"
|
|
217
|
+
else
|
|
218
|
+
echo "No log file found. Logs will appear after first hook execution."
|
|
219
|
+
fi
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
# View recent logs
|
|
223
|
+
view_logs_recent() {
|
|
224
|
+
local lines="${1:-50}"
|
|
225
|
+
if [ -f "$LOG_FILE" ]; then
|
|
226
|
+
echo -e "${LOG_CYAN}━━━ AutoWorkflow Logs (last $lines) ━━━${LOG_NC}"
|
|
227
|
+
echo ""
|
|
228
|
+
tail -n "$lines" "$LOG_FILE"
|
|
229
|
+
else
|
|
230
|
+
echo "No log file found."
|
|
231
|
+
fi
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
# View all logs
|
|
235
|
+
view_logs_all() {
|
|
236
|
+
if [ -f "$LOG_FILE" ]; then
|
|
237
|
+
echo -e "${LOG_CYAN}━━━ AutoWorkflow Logs (all) ━━━${LOG_NC}"
|
|
238
|
+
echo ""
|
|
239
|
+
cat "$LOG_FILE"
|
|
240
|
+
else
|
|
241
|
+
echo "No log file found."
|
|
242
|
+
fi
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
# Clear logs
|
|
246
|
+
clear_logs() {
|
|
247
|
+
rm -f "$LOG_FILE" "$LOG_FILE".*
|
|
248
|
+
echo -e "${LOG_GREEN}✓${LOG_NC} Logs cleared"
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
# Show log stats
|
|
252
|
+
show_log_stats() {
|
|
253
|
+
echo -e "${LOG_CYAN}━━━ Log Statistics ━━━${LOG_NC}"
|
|
254
|
+
echo ""
|
|
255
|
+
|
|
256
|
+
if [ -f "$LOG_FILE" ]; then
|
|
257
|
+
local size=$(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null || echo "0")
|
|
258
|
+
local lines=$(wc -l < "$LOG_FILE" | tr -d ' ')
|
|
259
|
+
local hooks=$(grep -c "\[HOOK\]" "$LOG_FILE" 2>/dev/null || echo "0")
|
|
260
|
+
local phases=$(grep -c "\[PHASE\]" "$LOG_FILE" 2>/dev/null || echo "0")
|
|
261
|
+
local gates=$(grep -c "\[GATE\]" "$LOG_FILE" 2>/dev/null || echo "0")
|
|
262
|
+
local errors=$(grep -c "\[ERROR\]" "$LOG_FILE" 2>/dev/null || echo "0")
|
|
263
|
+
|
|
264
|
+
echo " Log file: $LOG_FILE"
|
|
265
|
+
echo " Size: $((size / 1024)) KB"
|
|
266
|
+
echo " Lines: $lines"
|
|
267
|
+
echo ""
|
|
268
|
+
echo " Events:"
|
|
269
|
+
echo " Hooks: $hooks"
|
|
270
|
+
echo " Phases: $phases"
|
|
271
|
+
echo " Gates: $gates"
|
|
272
|
+
echo " Errors: $errors"
|
|
273
|
+
else
|
|
274
|
+
echo " No log file found."
|
|
275
|
+
fi
|
|
276
|
+
echo ""
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
280
|
+
# CLI INTERFACE (when run directly)
|
|
281
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
282
|
+
|
|
283
|
+
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
|
284
|
+
case "${1:-}" in
|
|
285
|
+
live|watch|tail|-f)
|
|
286
|
+
view_logs_live
|
|
287
|
+
;;
|
|
288
|
+
recent)
|
|
289
|
+
view_logs_recent "${2:-50}"
|
|
290
|
+
;;
|
|
291
|
+
all|--all|-a)
|
|
292
|
+
view_logs_all
|
|
293
|
+
;;
|
|
294
|
+
clear|--clear|-c)
|
|
295
|
+
clear_logs
|
|
296
|
+
;;
|
|
297
|
+
stats|--stats|-s)
|
|
298
|
+
show_log_stats
|
|
299
|
+
;;
|
|
300
|
+
*)
|
|
301
|
+
echo "AutoWorkflow Logger"
|
|
302
|
+
echo ""
|
|
303
|
+
echo "Usage: logger.sh <command>"
|
|
304
|
+
echo ""
|
|
305
|
+
echo "Commands:"
|
|
306
|
+
echo " live, watch, tail, -f View logs in real-time"
|
|
307
|
+
echo " recent [n] Show last n log entries (default: 50)"
|
|
308
|
+
echo " all, --all, -a Show all logs"
|
|
309
|
+
echo " clear, --clear, -c Clear all logs"
|
|
310
|
+
echo " stats, --stats, -s Show log statistics"
|
|
311
|
+
echo ""
|
|
312
|
+
echo "Environment:"
|
|
313
|
+
echo " AUTOWORKFLOW_DEBUG=1 Enable debug output to terminal"
|
|
314
|
+
echo ""
|
|
315
|
+
echo "Log file: $LOG_FILE"
|
|
316
|
+
;;
|
|
317
|
+
esac
|
|
318
|
+
fi
|
|
@@ -17,6 +17,10 @@ NC='\033[0m'
|
|
|
17
17
|
# Project directory (use env var if set, otherwise current directory)
|
|
18
18
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
19
19
|
|
|
20
|
+
# Source the logger
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
22
|
+
source "$SCRIPT_DIR/logger.sh" 2>/dev/null || true
|
|
23
|
+
|
|
20
24
|
# State directory
|
|
21
25
|
STATE_DIR="$PROJECT_DIR/.claude/.autoworkflow"
|
|
22
26
|
mkdir -p "$STATE_DIR"
|
|
@@ -112,11 +116,13 @@ check_analyze_gate() {
|
|
|
112
116
|
check_plan_approval_gate() {
|
|
113
117
|
echo ""
|
|
114
118
|
echo "Checking plan_approval_gate..."
|
|
119
|
+
aw_log_gate "plan_approval" "CHECKING"
|
|
115
120
|
|
|
116
121
|
if [ -f "$APPROVAL_FILE" ]; then
|
|
117
122
|
local approval=$(cat "$APPROVAL_FILE")
|
|
118
123
|
if [ "$approval" = "approved" ]; then
|
|
119
124
|
echo -e " ${GREEN}✅${NC} Plan has been approved"
|
|
125
|
+
aw_log_gate "plan_approval" "PASSED"
|
|
120
126
|
return 0
|
|
121
127
|
fi
|
|
122
128
|
fi
|
|
@@ -127,6 +133,7 @@ check_plan_approval_gate() {
|
|
|
127
133
|
echo ""
|
|
128
134
|
echo "Wait for user to say 'yes', 'proceed', 'approved', etc."
|
|
129
135
|
echo ""
|
|
136
|
+
aw_log_gate "plan_approval" "BLOCKED" "awaiting user approval"
|
|
130
137
|
return 1
|
|
131
138
|
}
|
|
132
139
|
|
|
@@ -134,11 +141,13 @@ check_plan_approval_gate() {
|
|
|
134
141
|
check_verify_gate() {
|
|
135
142
|
echo ""
|
|
136
143
|
echo "Checking verify_gate..."
|
|
144
|
+
aw_log_gate "verify" "CHECKING"
|
|
137
145
|
|
|
138
146
|
if [ -f "$STATE_DIR/verify-status" ]; then
|
|
139
147
|
local status=$(cat "$STATE_DIR/verify-status")
|
|
140
148
|
if [ "$status" = "PASSED" ]; then
|
|
141
149
|
echo -e " ${GREEN}✅${NC} Verification passed"
|
|
150
|
+
aw_log_gate "verify" "PASSED"
|
|
142
151
|
return 0
|
|
143
152
|
fi
|
|
144
153
|
fi
|
|
@@ -147,6 +156,7 @@ check_verify_gate() {
|
|
|
147
156
|
echo ""
|
|
148
157
|
echo -e "${YELLOW}BLOCKED:${NC} Run npm run verify and fix all errors first."
|
|
149
158
|
echo ""
|
|
159
|
+
aw_log_gate "verify" "BLOCKED" "verification not passed"
|
|
150
160
|
return 1
|
|
151
161
|
}
|
|
152
162
|
|
|
@@ -190,6 +200,8 @@ transition() {
|
|
|
190
200
|
local from="$1"
|
|
191
201
|
local to="$2"
|
|
192
202
|
|
|
203
|
+
aw_log_phase "$from" "$to"
|
|
204
|
+
|
|
193
205
|
echo ""
|
|
194
206
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
195
207
|
echo -e "${BOLD}AUTOWORKFLOW: PHASE TRANSITION${NC}"
|
|
@@ -20,6 +20,10 @@ NC='\033[0m'
|
|
|
20
20
|
# Project directory (use env var if set, otherwise current directory)
|
|
21
21
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
22
22
|
|
|
23
|
+
# Source the logger
|
|
24
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
25
|
+
source "$SCRIPT_DIR/logger.sh" 2>/dev/null || true
|
|
26
|
+
|
|
23
27
|
# State directory
|
|
24
28
|
STATE_DIR="$PROJECT_DIR/.claude/.autoworkflow"
|
|
25
29
|
mkdir -p "$STATE_DIR"
|
|
@@ -311,6 +315,8 @@ run_verify() {
|
|
|
311
315
|
|
|
312
316
|
# Main execution
|
|
313
317
|
main() {
|
|
318
|
+
aw_log_hook "post-edit.sh" "START"
|
|
319
|
+
|
|
314
320
|
local current_phase=$(get_phase)
|
|
315
321
|
|
|
316
322
|
# Track that we're in VERIFY phase
|
|
@@ -318,6 +324,7 @@ main() {
|
|
|
318
324
|
|
|
319
325
|
# Get current iteration and increment
|
|
320
326
|
local iteration=$(increment_iteration)
|
|
327
|
+
aw_log_verify "$iteration/$MAX_ITERATIONS" "STARTED"
|
|
321
328
|
|
|
322
329
|
# Check if we've exceeded max iterations
|
|
323
330
|
if [ "$iteration" -gt "$MAX_ITERATIONS" ]; then
|
|
@@ -334,6 +341,7 @@ main() {
|
|
|
334
341
|
echo " 2. Reset counter: rm $VERIFY_ITERATION_FILE"
|
|
335
342
|
echo ""
|
|
336
343
|
echo "BLOCKED" > "$VERIFY_STATUS_FILE"
|
|
344
|
+
aw_log_verify "$iteration/$MAX_ITERATIONS" "BLOCKED" "max iterations reached"
|
|
337
345
|
# Don't exit with error - let Claude continue but report the issue
|
|
338
346
|
exit 0
|
|
339
347
|
fi
|
|
@@ -356,6 +364,7 @@ main() {
|
|
|
356
364
|
|
|
357
365
|
# Update status
|
|
358
366
|
echo "PASSED" > "$VERIFY_STATUS_FILE"
|
|
367
|
+
aw_log_verify "$iteration/$MAX_ITERATIONS" "PASSED" "0 errors"
|
|
359
368
|
|
|
360
369
|
# Check if this was a feature/refactor that needs audit
|
|
361
370
|
local task_type=""
|
|
@@ -386,6 +395,7 @@ main() {
|
|
|
386
395
|
# Update status
|
|
387
396
|
echo "FAILED" > "$VERIFY_STATUS_FILE"
|
|
388
397
|
echo "$iteration" > "$VERIFY_ITERATION_FILE"
|
|
398
|
+
aw_log_verify "$iteration/$MAX_ITERATIONS" "FAILED" "errors found"
|
|
389
399
|
|
|
390
400
|
echo "Fix the errors above and save the file."
|
|
391
401
|
echo "Verification will re-run automatically."
|
|
@@ -396,6 +406,8 @@ main() {
|
|
|
396
406
|
# Enter FIX phase
|
|
397
407
|
set_phase "FIX"
|
|
398
408
|
fi
|
|
409
|
+
|
|
410
|
+
aw_log_hook "post-edit.sh" "COMPLETE"
|
|
399
411
|
}
|
|
400
412
|
|
|
401
413
|
main
|
|
@@ -19,6 +19,10 @@ NC='\033[0m'
|
|
|
19
19
|
# Project directory (use env var if set, otherwise current directory)
|
|
20
20
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
21
21
|
|
|
22
|
+
# Source the logger
|
|
23
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
24
|
+
source "$SCRIPT_DIR/logger.sh" 2>/dev/null || true
|
|
25
|
+
|
|
22
26
|
# State directory
|
|
23
27
|
STATE_DIR="$PROJECT_DIR/.claude/.autoworkflow"
|
|
24
28
|
mkdir -p "$STATE_DIR"
|
|
@@ -191,6 +195,8 @@ check_commit_message() {
|
|
|
191
195
|
|
|
192
196
|
# Main execution
|
|
193
197
|
main() {
|
|
198
|
+
aw_log_gate "pre_commit" "CHECKING" "7 checks"
|
|
199
|
+
|
|
194
200
|
print_header
|
|
195
201
|
|
|
196
202
|
echo "Checking requirements..."
|
|
@@ -219,6 +225,8 @@ main() {
|
|
|
219
225
|
echo "BLOCKED" > "$STATE_DIR/gate-status"
|
|
220
226
|
echo "$ERRORS" > "$STATE_DIR/gate-errors"
|
|
221
227
|
|
|
228
|
+
aw_log_gate "pre_commit" "BLOCKED" "$ERRORS errors"
|
|
229
|
+
|
|
222
230
|
# EXIT WITH ERROR TO BLOCK THE COMMIT
|
|
223
231
|
exit 1
|
|
224
232
|
else
|
|
@@ -231,6 +239,8 @@ main() {
|
|
|
231
239
|
echo "PASSED" > "$STATE_DIR/gate-status"
|
|
232
240
|
echo "0" > "$STATE_DIR/gate-errors"
|
|
233
241
|
|
|
242
|
+
aw_log_gate "pre_commit" "PASSED" "7/7 checks"
|
|
243
|
+
|
|
234
244
|
exit 0
|
|
235
245
|
fi
|
|
236
246
|
}
|
|
@@ -21,6 +21,10 @@ NC='\033[0m'
|
|
|
21
21
|
# Project directory (use env var if set, otherwise current directory)
|
|
22
22
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
23
23
|
|
|
24
|
+
# Source the logger
|
|
25
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
source "$SCRIPT_DIR/logger.sh" 2>/dev/null || true
|
|
27
|
+
|
|
24
28
|
# State directory
|
|
25
29
|
STATE_DIR="$PROJECT_DIR/.claude/.autoworkflow"
|
|
26
30
|
mkdir -p "$STATE_DIR"
|
|
@@ -505,11 +509,14 @@ show_memories_summary() {
|
|
|
505
509
|
|
|
506
510
|
# Main execution
|
|
507
511
|
main() {
|
|
512
|
+
aw_log_hook "session-check.sh" "START"
|
|
513
|
+
|
|
508
514
|
local is_new_session=false
|
|
509
515
|
|
|
510
516
|
# Initialize session
|
|
511
517
|
if init_session; then
|
|
512
518
|
is_new_session=true
|
|
519
|
+
aw_log "HOOK" "session-check.sh" "NEW_SESSION"
|
|
513
520
|
fi
|
|
514
521
|
|
|
515
522
|
# Reset turn state on each user message
|
|
@@ -517,6 +524,7 @@ main() {
|
|
|
517
524
|
|
|
518
525
|
# Check if init is needed (package installed but not set up)
|
|
519
526
|
if check_init_needed; then
|
|
527
|
+
aw_log "HOOK" "session-check.sh" "INIT_NEEDED"
|
|
520
528
|
exit 0
|
|
521
529
|
fi
|
|
522
530
|
|
|
@@ -526,13 +534,17 @@ main() {
|
|
|
526
534
|
fi
|
|
527
535
|
|
|
528
536
|
# Check for missing blueprint (prompts user for documentation)
|
|
529
|
-
check_blueprint
|
|
537
|
+
if ! check_blueprint; then
|
|
538
|
+
aw_log "HOOK" "session-check.sh" "DOCS_REQUIRED"
|
|
539
|
+
fi
|
|
530
540
|
|
|
531
541
|
# Show memories summary (if any exist)
|
|
532
542
|
show_memories_summary
|
|
533
543
|
|
|
534
544
|
# Show current state if not idle
|
|
535
545
|
show_state
|
|
546
|
+
|
|
547
|
+
aw_log_hook "session-check.sh" "COMPLETE"
|
|
536
548
|
}
|
|
537
549
|
|
|
538
550
|
main
|
package/CLAUDE.md
CHANGED
|
@@ -124,6 +124,41 @@ All state stored in `.claude/.autoworkflow/`:
|
|
|
124
124
|
|
|
125
125
|
---
|
|
126
126
|
|
|
127
|
+
## Logging System
|
|
128
|
+
|
|
129
|
+
Real-time visibility into hook execution, gates, and workflow events.
|
|
130
|
+
|
|
131
|
+
**Log Location:** `.claude/.autoworkflow/logs/aw.log`
|
|
132
|
+
|
|
133
|
+
**CLI Commands:**
|
|
134
|
+
```bash
|
|
135
|
+
npx autoworkflow logs # Watch logs in real-time
|
|
136
|
+
npx autoworkflow logs --recent # Show last 50 entries
|
|
137
|
+
npx autoworkflow logs --all # Show all logs
|
|
138
|
+
npx autoworkflow logs --clear # Clear logs
|
|
139
|
+
npx autoworkflow logs --stats # Show statistics
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Or use tail directly:**
|
|
143
|
+
```bash
|
|
144
|
+
tail -f .claude/.autoworkflow/logs/aw.log
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Log Categories:**
|
|
148
|
+
| Category | Events |
|
|
149
|
+
|----------|--------|
|
|
150
|
+
| HOOK | Hook start/complete |
|
|
151
|
+
| PHASE | Phase transitions |
|
|
152
|
+
| GATE | Gate checks (pass/block) |
|
|
153
|
+
| VERIFY | Verification iterations |
|
|
154
|
+
| MEMORY | Memory update prompts |
|
|
155
|
+
| COMMIT | Commit events |
|
|
156
|
+
| ERROR | Errors and failures |
|
|
157
|
+
|
|
158
|
+
**Debug Mode:** Set `AUTOWORKFLOW_DEBUG=1` to see logs in terminal.
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
127
162
|
## Memory System (Serena-inspired)
|
|
128
163
|
|
|
129
164
|
Persistent context that survives across sessions. **Claude edits files directly** + hooks prompt at key moments.
|
|
@@ -246,6 +281,7 @@ npm run format # Prettier
|
|
|
246
281
|
| `phase-transition.sh` | Manual call | State management |
|
|
247
282
|
| `audit-runner.sh` | Manual call | Run UI + cycle audits |
|
|
248
283
|
| `blueprint-generator.sh` | Manual call | Enhanced project discovery (8 scans) |
|
|
284
|
+
| `logger.sh` | Sourced by hooks | Centralized logging system |
|
|
249
285
|
|
|
250
286
|
---
|
|
251
287
|
|
package/bin/cli.js
CHANGED
|
@@ -72,6 +72,12 @@ Commands:
|
|
|
72
72
|
${colors.cyan('update')} Smart update - core files only, preserve user files
|
|
73
73
|
${colors.cyan('status')} Show installed version and what would change
|
|
74
74
|
|
|
75
|
+
${colors.cyan('logs')} View AutoWorkflow logs (real-time)
|
|
76
|
+
${colors.cyan('logs --recent')} Show last 50 log entries
|
|
77
|
+
${colors.cyan('logs --all')} Show all logs
|
|
78
|
+
${colors.cyan('logs --clear')} Clear all logs
|
|
79
|
+
${colors.cyan('logs --stats')} Show log statistics
|
|
80
|
+
|
|
75
81
|
${colors.cyan('help')} Show this help message
|
|
76
82
|
|
|
77
83
|
Options:
|
|
@@ -82,7 +88,7 @@ Examples:
|
|
|
82
88
|
npx autoworkflow init # Fresh install
|
|
83
89
|
npx autoworkflow update # Update core files only
|
|
84
90
|
npx autoworkflow status # Check what would change
|
|
85
|
-
npx autoworkflow
|
|
91
|
+
npx autoworkflow logs # Watch logs in real-time
|
|
86
92
|
`);
|
|
87
93
|
}
|
|
88
94
|
|
|
@@ -453,6 +459,62 @@ function init(options = {}) {
|
|
|
453
459
|
console.log(`${colors.dim('Optional: Edit instructions/AI_RULES.md to customize coding standards')}\n`);
|
|
454
460
|
}
|
|
455
461
|
|
|
462
|
+
// Logs command
|
|
463
|
+
import { spawn } from 'child_process';
|
|
464
|
+
|
|
465
|
+
function logs() {
|
|
466
|
+
const cwd = process.cwd();
|
|
467
|
+
const loggerScript = join(cwd, '.claude', 'hooks', 'logger.sh');
|
|
468
|
+
|
|
469
|
+
// Check if logger exists
|
|
470
|
+
if (!existsSync(loggerScript)) {
|
|
471
|
+
console.log(`${colors.yellow('⚠')} AutoWorkflow not initialized in this directory.`);
|
|
472
|
+
console.log(` Run: npx autoworkflow init`);
|
|
473
|
+
process.exit(1);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// Determine subcommand
|
|
477
|
+
const subCommand = args[1] || 'live';
|
|
478
|
+
|
|
479
|
+
let loggerArg;
|
|
480
|
+
switch (subCommand) {
|
|
481
|
+
case '--recent':
|
|
482
|
+
case '-r':
|
|
483
|
+
loggerArg = 'recent';
|
|
484
|
+
break;
|
|
485
|
+
case '--all':
|
|
486
|
+
case '-a':
|
|
487
|
+
loggerArg = 'all';
|
|
488
|
+
break;
|
|
489
|
+
case '--clear':
|
|
490
|
+
case '-c':
|
|
491
|
+
loggerArg = 'clear';
|
|
492
|
+
break;
|
|
493
|
+
case '--stats':
|
|
494
|
+
case '-s':
|
|
495
|
+
loggerArg = 'stats';
|
|
496
|
+
break;
|
|
497
|
+
default:
|
|
498
|
+
loggerArg = 'live';
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Run the logger script
|
|
502
|
+
const child = spawn('bash', [loggerScript, loggerArg], {
|
|
503
|
+
cwd: cwd,
|
|
504
|
+
stdio: 'inherit',
|
|
505
|
+
env: { ...process.env, CLAUDE_PROJECT_DIR: cwd }
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
child.on('error', (err) => {
|
|
509
|
+
console.error(`${colors.red('Error:')} ${err.message}`);
|
|
510
|
+
process.exit(1);
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
child.on('exit', (code) => {
|
|
514
|
+
process.exit(code || 0);
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
|
|
456
518
|
// Main
|
|
457
519
|
switch (command) {
|
|
458
520
|
case 'init':
|
|
@@ -464,6 +526,10 @@ switch (command) {
|
|
|
464
526
|
case 'status':
|
|
465
527
|
status();
|
|
466
528
|
break;
|
|
529
|
+
case 'logs':
|
|
530
|
+
case 'log':
|
|
531
|
+
logs();
|
|
532
|
+
break;
|
|
467
533
|
case 'help':
|
|
468
534
|
case '--help':
|
|
469
535
|
case '-h':
|