autoworkflow 3.9.1 → 3.11.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-bash-router.sh +9 -2
- package/.claude/hooks/post-edit.sh +12 -0
- package/.claude/hooks/pre-commit-check.sh +10 -0
- package/.claude/hooks/pre-tool-router.sh +10 -1
- package/.claude/hooks/session-check.sh +13 -1
- package/.claude/settings.json +10 -15
- package/.claude/settings.local.json +7 -1
- package/.claude/skills/nextjs.md +2730 -0
- 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}"
|
|
@@ -9,8 +9,15 @@
|
|
|
9
9
|
# Project directory (use env var if set, otherwise current directory)
|
|
10
10
|
PROJECT_DIR="${CLAUDE_PROJECT_DIR:-.}"
|
|
11
11
|
|
|
12
|
-
#
|
|
13
|
-
|
|
12
|
+
# Read JSON input from stdin (Claude Code hooks pass data via stdin)
|
|
13
|
+
INPUT_JSON=$(cat)
|
|
14
|
+
|
|
15
|
+
# Extract command from JSON
|
|
16
|
+
if echo "$INPUT_JSON" | grep -q '"command"'; then
|
|
17
|
+
TOOL_INPUT=$(echo "$INPUT_JSON" | grep -o '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"command"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
|
|
18
|
+
else
|
|
19
|
+
TOOL_INPUT="$INPUT_JSON"
|
|
20
|
+
fi
|
|
14
21
|
|
|
15
22
|
# Check if this was a git commit command
|
|
16
23
|
if echo "$TOOL_INPUT" | grep -qE "git\s+commit"; then
|
|
@@ -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
|
}
|
|
@@ -6,7 +6,16 @@
|
|
|
6
6
|
# This router determines what checks to run based on the command being executed
|
|
7
7
|
# It also enforces task-type-aware restrictions (similar to Serena's mode switching)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
# Read JSON input from stdin (Claude Code hooks pass data via stdin)
|
|
10
|
+
INPUT_JSON=$(cat)
|
|
11
|
+
|
|
12
|
+
# Extract command from JSON - handle both formats:
|
|
13
|
+
# {"tool_input":{"command":"..."}} or just the command string
|
|
14
|
+
if echo "$INPUT_JSON" | grep -q '"command"'; then
|
|
15
|
+
TOOL_INPUT=$(echo "$INPUT_JSON" | grep -o '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"command"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//')
|
|
16
|
+
else
|
|
17
|
+
TOOL_INPUT="$INPUT_JSON"
|
|
18
|
+
fi
|
|
10
19
|
|
|
11
20
|
# Colors
|
|
12
21
|
RED='\033[0;31m'
|
|
@@ -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/settings.json
CHANGED
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
"hooks": [
|
|
12
12
|
{
|
|
13
13
|
"type": "command",
|
|
14
|
-
"command": "
|
|
15
|
-
"timeout": 10
|
|
16
|
-
"statusMessage": "Checking project state..."
|
|
14
|
+
"command": ".claude/hooks/session-check.sh",
|
|
15
|
+
"timeout": 10
|
|
17
16
|
}
|
|
18
17
|
]
|
|
19
18
|
}
|
|
@@ -24,9 +23,8 @@
|
|
|
24
23
|
"hooks": [
|
|
25
24
|
{
|
|
26
25
|
"type": "command",
|
|
27
|
-
"command": "
|
|
28
|
-
"timeout": 5
|
|
29
|
-
"statusMessage": "Checking plan approval..."
|
|
26
|
+
"command": ".claude/hooks/pre-edit.sh",
|
|
27
|
+
"timeout": 5
|
|
30
28
|
}
|
|
31
29
|
]
|
|
32
30
|
},
|
|
@@ -35,9 +33,8 @@
|
|
|
35
33
|
"hooks": [
|
|
36
34
|
{
|
|
37
35
|
"type": "command",
|
|
38
|
-
"command": "
|
|
39
|
-
"timeout": 300
|
|
40
|
-
"statusMessage": "Checking workflow gates..."
|
|
36
|
+
"command": ".claude/hooks/pre-tool-router.sh",
|
|
37
|
+
"timeout": 300
|
|
41
38
|
}
|
|
42
39
|
]
|
|
43
40
|
}
|
|
@@ -48,9 +45,8 @@
|
|
|
48
45
|
"hooks": [
|
|
49
46
|
{
|
|
50
47
|
"type": "command",
|
|
51
|
-
"command": "
|
|
52
|
-
"timeout": 120
|
|
53
|
-
"statusMessage": "Running verification..."
|
|
48
|
+
"command": ".claude/hooks/post-edit.sh",
|
|
49
|
+
"timeout": 120
|
|
54
50
|
}
|
|
55
51
|
]
|
|
56
52
|
},
|
|
@@ -59,9 +55,8 @@
|
|
|
59
55
|
"hooks": [
|
|
60
56
|
{
|
|
61
57
|
"type": "command",
|
|
62
|
-
"command": "
|
|
63
|
-
"timeout": 30
|
|
64
|
-
"statusMessage": "Checking post-command actions..."
|
|
58
|
+
"command": ".claude/hooks/post-bash-router.sh",
|
|
59
|
+
"timeout": 30
|
|
65
60
|
}
|
|
66
61
|
]
|
|
67
62
|
}
|
|
@@ -25,7 +25,13 @@
|
|
|
25
25
|
"WebFetch(domain:apidog.com)",
|
|
26
26
|
"WebFetch(domain:mcpservers.org)",
|
|
27
27
|
"WebFetch(domain:oraios.github.io)",
|
|
28
|
-
"Bash(bash:*)"
|
|
28
|
+
"Bash(bash:*)",
|
|
29
|
+
"Bash(CLAUDE_PROJECT_DIR=\".\" ./.claude/hooks/session-check.sh:*)",
|
|
30
|
+
"Bash(claude:*)",
|
|
31
|
+
"WebFetch(domain:raw.githubusercontent.com)",
|
|
32
|
+
"Bash(./.claude/hooks/pre-tool-router.sh:*)",
|
|
33
|
+
"Bash(./.claude/hooks/session-check.sh:*)",
|
|
34
|
+
"Bash(CLAUDE_PROJECT_DIR=\".\" bash:*)"
|
|
29
35
|
]
|
|
30
36
|
}
|
|
31
37
|
}
|