specweave 0.26.11 → 0.26.13
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/dist/plugins/specweave-github/lib/completion-calculator.d.ts +4 -1
- package/dist/plugins/specweave-github/lib/completion-calculator.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/completion-calculator.js +49 -29
- package/dist/plugins/specweave-github/lib/completion-calculator.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.d.ts +3 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +35 -4
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.d.ts +5 -0
- package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
- package/dist/src/core/living-docs/feature-archiver.js +66 -18
- package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/commands/specweave-archive.md +10 -1
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/hooks.json +10 -0
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/lib/update-active-increment.sh +96 -0
- package/plugins/specweave/hooks/lib/update-status-line.sh +153 -189
- package/plugins/specweave/hooks/post-edit-write-consolidated.sh +6 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-metadata-change.sh +9 -0
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-task-completion.sh +8 -0
- package/plugins/specweave/hooks/post-task-edit.sh +37 -0
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh +43 -53
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh +5 -0
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +143 -289
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-ado/lib/ado-multi-project-sync.js +1 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1098 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-github/lib/completion-calculator.js +34 -16
- package/plugins/specweave-github/lib/completion-calculator.ts +54 -32
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +3 -3
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1008 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
- package/src/templates/AGENTS.md.template +301 -2452
- package/src/templates/CLAUDE.md.template +99 -667
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Pre-Command Deduplication Hook
|
|
4
|
+
# Fires BEFORE any command executes (UserPromptSubmit hook)
|
|
5
|
+
# Purpose: Prevent duplicate command invocations within configurable time window
|
|
6
|
+
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
|
|
9
|
+
# ==============================================================================
|
|
10
|
+
# PROJECT ROOT DETECTION
|
|
11
|
+
# ==============================================================================
|
|
12
|
+
|
|
13
|
+
# Find project root by searching upward for .specweave/ directory
|
|
14
|
+
find_project_root() {
|
|
15
|
+
local dir="$1"
|
|
16
|
+
while [ "$dir" != "/" ]; do
|
|
17
|
+
if [ -d "$dir/.specweave" ]; then
|
|
18
|
+
echo "$dir"
|
|
19
|
+
return 0
|
|
20
|
+
fi
|
|
21
|
+
dir="$(dirname "$dir")"
|
|
22
|
+
done
|
|
23
|
+
# Fallback: try current directory
|
|
24
|
+
if [ -d "$(pwd)/.specweave" ]; then
|
|
25
|
+
pwd
|
|
26
|
+
else
|
|
27
|
+
echo "$(pwd)"
|
|
28
|
+
fi
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
32
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
33
|
+
|
|
34
|
+
# Read input JSON from stdin
|
|
35
|
+
INPUT=$(cat)
|
|
36
|
+
|
|
37
|
+
# ==============================================================================
|
|
38
|
+
# DEDUPLICATION CHECK: Block duplicate commands within 1 second
|
|
39
|
+
# ==============================================================================
|
|
40
|
+
|
|
41
|
+
# Check if deduplication module is available
|
|
42
|
+
if command -v node >/dev/null 2>&1 && [[ -f "dist/src/core/deduplication/command-deduplicator.js" ]]; then
|
|
43
|
+
# Use dedicated wrapper script for ES module compatibility
|
|
44
|
+
DEDUP_RESULT=$(echo "$INPUT" | node scripts/check-deduplication.js 2>/dev/null || echo "OK")
|
|
45
|
+
|
|
46
|
+
# Parse result
|
|
47
|
+
STATUS=$(echo "$DEDUP_RESULT" | head -1)
|
|
48
|
+
|
|
49
|
+
if [[ "$STATUS" == "DUPLICATE" ]]; then
|
|
50
|
+
# Get stats
|
|
51
|
+
STATS=$(echo "$DEDUP_RESULT" | tail -1)
|
|
52
|
+
|
|
53
|
+
# Extract command and stats for readable message
|
|
54
|
+
COMMAND=$(echo "$STATS" | grep -o '"lastCommand":"[^"]*"' | cut -d'"' -f4 || echo "unknown")
|
|
55
|
+
TOTAL_BLOCKED=$(echo "$STATS" | grep -o '"totalDuplicatesBlocked":[0-9]*' | cut -d':' -f2 || echo "1")
|
|
56
|
+
CACHE_SIZE=$(echo "$STATS" | grep -o '"currentCacheSize":[0-9]*' | cut -d':' -f2 || echo "1")
|
|
57
|
+
|
|
58
|
+
# Build error message WITHOUT embedding JSON (avoid escaping issues)
|
|
59
|
+
MESSAGE=$(cat <<'EOF'
|
|
60
|
+
{
|
|
61
|
+
"decision": "block",
|
|
62
|
+
"reason": "🚫 DUPLICATE COMMAND DETECTED\n\nCommand: `COMMAND_PLACEHOLDER`\nTime window: 1 second\n\nThis command was just executed! To prevent unintended duplicates, this invocation has been blocked.\n\n💡 If you meant to run this command again:\n 1. Wait 1 second\n 2. Run the command again\n\nDeduplication Stats:\n- Total duplicates blocked: BLOCKED_PLACEHOLDER\n- Commands in cache: CACHE_PLACEHOLDER"
|
|
63
|
+
}
|
|
64
|
+
EOF
|
|
65
|
+
)
|
|
66
|
+
# Replace placeholders (avoids JSON escaping issues)
|
|
67
|
+
# Use | as sed delimiter to avoid conflicts with / in command names
|
|
68
|
+
echo "$MESSAGE" | sed "s|COMMAND_PLACEHOLDER|$COMMAND|g" | sed "s|BLOCKED_PLACEHOLDER|$TOTAL_BLOCKED|g" | sed "s|CACHE_PLACEHOLDER|$CACHE_SIZE|g"
|
|
69
|
+
exit 0
|
|
70
|
+
fi
|
|
71
|
+
fi
|
|
72
|
+
|
|
73
|
+
# ==============================================================================
|
|
74
|
+
# PASS THROUGH: No duplicate detected, proceed with command
|
|
75
|
+
# ==============================================================================
|
|
76
|
+
|
|
77
|
+
cat <<EOF
|
|
78
|
+
{
|
|
79
|
+
"decision": "approve"
|
|
80
|
+
}
|
|
81
|
+
EOF
|
|
82
|
+
|
|
83
|
+
exit 0
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Pre-Implementation Hook
|
|
4
|
+
# Runs before starting implementation of a task
|
|
5
|
+
# Checks regression risk for brownfield projects
|
|
6
|
+
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
# Find project root by searching upward for .specweave/ directory
|
|
10
|
+
# Works regardless of where hook is installed (source or .claude/hooks/)
|
|
11
|
+
find_project_root() {
|
|
12
|
+
local dir="$1"
|
|
13
|
+
while [ "$dir" != "/" ]; do
|
|
14
|
+
if [ -d "$dir/.specweave" ]; then
|
|
15
|
+
echo "$dir"
|
|
16
|
+
return 0
|
|
17
|
+
fi
|
|
18
|
+
dir="$(dirname "$dir")"
|
|
19
|
+
done
|
|
20
|
+
# Fallback: try current directory
|
|
21
|
+
if [ -d "$(pwd)/.specweave" ]; then
|
|
22
|
+
pwd
|
|
23
|
+
else
|
|
24
|
+
echo "$(pwd)"
|
|
25
|
+
fi
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
29
|
+
cd "$PROJECT_ROOT"
|
|
30
|
+
|
|
31
|
+
# Colors
|
|
32
|
+
YELLOW='\033[1;33m'
|
|
33
|
+
BLUE='\033[0;34m'
|
|
34
|
+
GREEN='\033[0;32m'
|
|
35
|
+
NC='\033[0m'
|
|
36
|
+
|
|
37
|
+
echo -e "${BLUE}🔍 Pre-Implementation Check${NC}"
|
|
38
|
+
|
|
39
|
+
# Check if this is a brownfield project (has existing code)
|
|
40
|
+
if [ -d "src" ] || [ -d "app" ] || [ -d "lib" ]; then
|
|
41
|
+
echo -e "${YELLOW}⚠️ Brownfield project detected${NC}"
|
|
42
|
+
echo ""
|
|
43
|
+
echo "Recommendations:"
|
|
44
|
+
echo " 1. Create baseline tests before changes"
|
|
45
|
+
echo " 2. Check for existing tests that may break"
|
|
46
|
+
echo " 3. Review impact on existing features"
|
|
47
|
+
echo ""
|
|
48
|
+
|
|
49
|
+
# Check if baseline tests exist
|
|
50
|
+
if [ -d ".specweave/tests/baseline" ]; then
|
|
51
|
+
echo -e "${GREEN}✅ Baseline tests exist${NC}"
|
|
52
|
+
else
|
|
53
|
+
echo -e "${YELLOW}⚠️ No baseline tests found${NC}"
|
|
54
|
+
echo " Consider creating baseline tests first"
|
|
55
|
+
echo " This captures current state before changes"
|
|
56
|
+
fi
|
|
57
|
+
else
|
|
58
|
+
echo -e "${GREEN}✅ Greenfield project - no regression risk${NC}"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Log to hooks log
|
|
62
|
+
LOGS_DIR=".specweave/logs"
|
|
63
|
+
mkdir -p "$LOGS_DIR"
|
|
64
|
+
echo "[$(date)] Pre-implementation check complete" >> "$LOGS_DIR/hooks.log"
|
|
65
|
+
|
|
66
|
+
echo ""
|
|
67
|
+
echo -e "${GREEN}✅ Pre-implementation check complete${NC}"
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Pre-Task-Completion Hook
|
|
4
|
+
# CRITICAL QUALITY GATE: Validates AC tests before allowing task completion
|
|
5
|
+
#
|
|
6
|
+
# Runs automatically BEFORE any task is marked complete via TodoWrite
|
|
7
|
+
#
|
|
8
|
+
# WORKFLOW:
|
|
9
|
+
# =========
|
|
10
|
+
# 1. TodoWrite called with status="completed"
|
|
11
|
+
# 2. This hook fires (pre-completion validation)
|
|
12
|
+
# 3. Extract task ID from TodoWrite input
|
|
13
|
+
# 4. Find task in tasks.md
|
|
14
|
+
# 5. Run AC test validator
|
|
15
|
+
# 6. If tests PASS → Allow completion (continue: true)
|
|
16
|
+
# 7. If tests FAIL → Block completion (continue: false, show error)
|
|
17
|
+
#
|
|
18
|
+
# ENFORCEMENT:
|
|
19
|
+
# ============
|
|
20
|
+
# This is the ONLY way to mark tasks complete in SpecWeave.
|
|
21
|
+
# Manual edits to tasks.md are detected and flagged by pre-commit hooks.
|
|
22
|
+
|
|
23
|
+
set -e
|
|
24
|
+
|
|
25
|
+
# Find project root
|
|
26
|
+
find_project_root() {
|
|
27
|
+
local dir="$1"
|
|
28
|
+
while [ "$dir" != "/" ]; do
|
|
29
|
+
if [ -d "$dir/.specweave" ]; then
|
|
30
|
+
echo "$dir"
|
|
31
|
+
return 0
|
|
32
|
+
fi
|
|
33
|
+
dir="$(dirname "$dir")"
|
|
34
|
+
done
|
|
35
|
+
pwd
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
39
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
40
|
+
|
|
41
|
+
# ============================================================================
|
|
42
|
+
# CONFIGURATION
|
|
43
|
+
# ============================================================================
|
|
44
|
+
|
|
45
|
+
LOGS_DIR=".specweave/logs"
|
|
46
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
47
|
+
|
|
48
|
+
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
49
|
+
|
|
50
|
+
echo "[$(date)] 🔒 Pre-task-completion hook fired" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
51
|
+
|
|
52
|
+
# ============================================================================
|
|
53
|
+
# CAPTURE INPUT
|
|
54
|
+
# ============================================================================
|
|
55
|
+
|
|
56
|
+
STDIN_DATA=$(mktemp)
|
|
57
|
+
cat > "$STDIN_DATA"
|
|
58
|
+
|
|
59
|
+
echo "[$(date)] Input JSON:" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
60
|
+
cat "$STDIN_DATA" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
61
|
+
|
|
62
|
+
# ============================================================================
|
|
63
|
+
# CHECK FOR TASK COMPLETION
|
|
64
|
+
# ============================================================================
|
|
65
|
+
|
|
66
|
+
# Only validate if a task is being marked complete
|
|
67
|
+
COMPLETING_TASK=false
|
|
68
|
+
|
|
69
|
+
if command -v jq >/dev/null 2>&1; then
|
|
70
|
+
# Check if any task is transitioning to "completed" status
|
|
71
|
+
COMPLETED_COUNT=$(jq -r '.tool_input.todos // [] | map(select(.status == "completed")) | length' "$STDIN_DATA" 2>/dev/null || echo "0")
|
|
72
|
+
|
|
73
|
+
if [ "$COMPLETED_COUNT" != "0" ]; then
|
|
74
|
+
COMPLETING_TASK=true
|
|
75
|
+
echo "[$(date)] ✓ Detected task completion (${COMPLETED_COUNT} tasks)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
76
|
+
fi
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
# If no tasks being completed, allow without validation
|
|
80
|
+
if [ "$COMPLETING_TASK" = "false" ]; then
|
|
81
|
+
echo "[$(date)] ⏭️ No tasks being completed, skipping validation" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
82
|
+
rm -f "$STDIN_DATA"
|
|
83
|
+
cat <<EOF
|
|
84
|
+
{
|
|
85
|
+
"continue": true
|
|
86
|
+
}
|
|
87
|
+
EOF
|
|
88
|
+
exit 0
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
# ============================================================================
|
|
92
|
+
# DETECT CURRENT INCREMENT
|
|
93
|
+
# ============================================================================
|
|
94
|
+
|
|
95
|
+
CURRENT_INCREMENT=$(ls -td .specweave/increments/*/ 2>/dev/null | xargs -n1 basename | grep -v "_backlog" | grep -v "_archive" | grep -v "_working" | head -1)
|
|
96
|
+
|
|
97
|
+
if [ -z "$CURRENT_INCREMENT" ]; then
|
|
98
|
+
echo "[$(date)] ℹ️ No active increment found, skipping validation" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
99
|
+
rm -f "$STDIN_DATA"
|
|
100
|
+
cat <<EOF
|
|
101
|
+
{
|
|
102
|
+
"continue": true
|
|
103
|
+
}
|
|
104
|
+
EOF
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
TASKS_MD=".specweave/increments/$CURRENT_INCREMENT/tasks.md"
|
|
109
|
+
|
|
110
|
+
if [ ! -f "$TASKS_MD" ]; then
|
|
111
|
+
echo "[$(date)] ℹ️ tasks.md not found for $CURRENT_INCREMENT (increment may be in planning stage)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
112
|
+
rm -f "$STDIN_DATA"
|
|
113
|
+
cat <<EOF
|
|
114
|
+
{
|
|
115
|
+
"continue": true
|
|
116
|
+
}
|
|
117
|
+
EOF
|
|
118
|
+
exit 0
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
# ============================================================================
|
|
122
|
+
# RUN AC TEST VALIDATION
|
|
123
|
+
# ============================================================================
|
|
124
|
+
|
|
125
|
+
echo "[$(date)] 🧪 Running AC test validation for $CURRENT_INCREMENT" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
126
|
+
|
|
127
|
+
# Determine which validation script to use
|
|
128
|
+
VALIDATOR_SCRIPT=""
|
|
129
|
+
if [ -f "$PROJECT_ROOT/dist/src/core/ac-test-validator-cli.js" ]; then
|
|
130
|
+
VALIDATOR_SCRIPT="$PROJECT_ROOT/dist/src/core/ac-test-validator-cli.js"
|
|
131
|
+
elif [ -f "$PROJECT_ROOT/node_modules/specweave/dist/src/core/ac-test-validator-cli.js" ]; then
|
|
132
|
+
VALIDATOR_SCRIPT="$PROJECT_ROOT/node_modules/specweave/dist/src/core/ac-test-validator-cli.js"
|
|
133
|
+
elif [ -n "${CLAUDE_PLUGIN_ROOT}" ] && [ -f "${CLAUDE_PLUGIN_ROOT}/dist/src/core/ac-test-validator-cli.js" ]; then
|
|
134
|
+
VALIDATOR_SCRIPT="${CLAUDE_PLUGIN_ROOT}/dist/src/core/ac-test-validator-cli.js"
|
|
135
|
+
fi
|
|
136
|
+
|
|
137
|
+
if [ -z "$VALIDATOR_SCRIPT" ] || ! command -v node &> /dev/null; then
|
|
138
|
+
echo "[$(date)] ⚠️ AC test validator not found or Node.js missing" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
139
|
+
rm -f "$STDIN_DATA"
|
|
140
|
+
cat <<EOF
|
|
141
|
+
{
|
|
142
|
+
"continue": true,
|
|
143
|
+
"systemMessage": "⚠️ Warning: AC test validator not available. Task completion validation skipped. Install Node.js and rebuild SpecWeave to enable validation."
|
|
144
|
+
}
|
|
145
|
+
EOF
|
|
146
|
+
exit 0
|
|
147
|
+
fi
|
|
148
|
+
|
|
149
|
+
# Run validator (captures exit code)
|
|
150
|
+
VALIDATION_OUTPUT=$(mktemp)
|
|
151
|
+
VALIDATION_EXIT_CODE=0
|
|
152
|
+
|
|
153
|
+
(cd "$PROJECT_ROOT" && node "$VALIDATOR_SCRIPT" "$CURRENT_INCREMENT") > "$VALIDATION_OUTPUT" 2>&1 || VALIDATION_EXIT_CODE=$?
|
|
154
|
+
|
|
155
|
+
echo "[$(date)] Validator exit code: $VALIDATION_EXIT_CODE" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
156
|
+
cat "$VALIDATION_OUTPUT" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
157
|
+
|
|
158
|
+
rm -f "$STDIN_DATA"
|
|
159
|
+
|
|
160
|
+
# ============================================================================
|
|
161
|
+
# DECISION LOGIC
|
|
162
|
+
# ============================================================================
|
|
163
|
+
|
|
164
|
+
if [ "$VALIDATION_EXIT_CODE" = "0" ]; then
|
|
165
|
+
# Validation passed - allow completion
|
|
166
|
+
echo "[$(date)] ✅ AC test validation passed" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
167
|
+
|
|
168
|
+
VALIDATION_SUMMARY=$(cat "$VALIDATION_OUTPUT" | tail -5 | tr '\n' ' ')
|
|
169
|
+
|
|
170
|
+
rm -f "$VALIDATION_OUTPUT"
|
|
171
|
+
|
|
172
|
+
cat <<EOF
|
|
173
|
+
{
|
|
174
|
+
"continue": true,
|
|
175
|
+
"systemMessage": "✅ AC Test Validation Passed: All acceptance criteria have passing tests. Task completion allowed. ${VALIDATION_SUMMARY}"
|
|
176
|
+
}
|
|
177
|
+
EOF
|
|
178
|
+
else
|
|
179
|
+
# Validation failed - block completion
|
|
180
|
+
echo "[$(date)] ❌ AC test validation failed" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
181
|
+
|
|
182
|
+
VALIDATION_ERROR=$(cat "$VALIDATION_OUTPUT" | grep -A 10 "VALIDATION FAILED" | tr '\n' ' ' | cut -c 1-300)
|
|
183
|
+
|
|
184
|
+
rm -f "$VALIDATION_OUTPUT"
|
|
185
|
+
|
|
186
|
+
cat <<EOF
|
|
187
|
+
{
|
|
188
|
+
"continue": false,
|
|
189
|
+
"systemMessage": "❌ AC TEST VALIDATION FAILED: Cannot mark task as complete until all acceptance criteria have passing tests. ${VALIDATION_ERROR}
|
|
190
|
+
|
|
191
|
+
Fix the failing tests and try again. Run tests manually: npm test"
|
|
192
|
+
}
|
|
193
|
+
EOF
|
|
194
|
+
fi
|
|
@@ -45,6 +45,11 @@ find_project_root() {
|
|
|
45
45
|
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
46
46
|
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
47
47
|
|
|
48
|
+
# ULTRA-FAST EARLY EXIT FOR NON-SPECWEAVE PROJECTS (T-006 - v0.26.15)
|
|
49
|
+
if [[ ! -d "$PROJECT_ROOT/.specweave" ]]; then
|
|
50
|
+
exit 0
|
|
51
|
+
fi
|
|
52
|
+
|
|
48
53
|
LOGS_DIR=".specweave/logs"
|
|
49
54
|
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
50
55
|
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Pre-Tool-Use Hook
|
|
4
|
+
# Runs BEFORE Claude calls any tool (PreToolUse event)
|
|
5
|
+
#
|
|
6
|
+
# PURPOSE: Detect when Claude asks questions via AskUserQuestion
|
|
7
|
+
# - Plays sound IMMEDIATELY when question is about to be asked
|
|
8
|
+
# - Complements post-task-completion hook (which only fires after TodoWrite)
|
|
9
|
+
# - Ensures user is always notified when Claude needs input
|
|
10
|
+
#
|
|
11
|
+
# SCOPE:
|
|
12
|
+
# - This hook fires for ALL tool calls (Read, Edit, Write, AskUserQuestion, etc.)
|
|
13
|
+
# - We filter for AskUserQuestion specifically to play sound
|
|
14
|
+
# - Non-blocking and fast (<10ms overhead)
|
|
15
|
+
|
|
16
|
+
set -e
|
|
17
|
+
|
|
18
|
+
# ============================================================================
|
|
19
|
+
# CONFIGURATION
|
|
20
|
+
# ============================================================================
|
|
21
|
+
|
|
22
|
+
# Find project root
|
|
23
|
+
find_project_root() {
|
|
24
|
+
local dir="$1"
|
|
25
|
+
while [ "$dir" != "/" ]; do
|
|
26
|
+
if [ -d "$dir/.specweave" ]; then
|
|
27
|
+
echo "$dir"
|
|
28
|
+
return 0
|
|
29
|
+
fi
|
|
30
|
+
dir="$(dirname "$dir")"
|
|
31
|
+
done
|
|
32
|
+
# Fallback
|
|
33
|
+
if [ -d "$(pwd)/.specweave" ]; then
|
|
34
|
+
pwd
|
|
35
|
+
else
|
|
36
|
+
echo "$(pwd)"
|
|
37
|
+
fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
41
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
42
|
+
|
|
43
|
+
LOGS_DIR=".specweave/logs"
|
|
44
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
45
|
+
|
|
46
|
+
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
47
|
+
|
|
48
|
+
# ============================================================================
|
|
49
|
+
# CAPTURE INPUT (Tool Call Details)
|
|
50
|
+
# ============================================================================
|
|
51
|
+
|
|
52
|
+
STDIN_DATA=$(mktemp)
|
|
53
|
+
cat > "$STDIN_DATA"
|
|
54
|
+
|
|
55
|
+
# Log the tool call for debugging
|
|
56
|
+
echo "[$(date)] 🔧 PreToolUse hook fired" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
57
|
+
echo "[$(date)] Tool call JSON:" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
58
|
+
cat "$STDIN_DATA" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
59
|
+
echo "" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
60
|
+
|
|
61
|
+
# ============================================================================
|
|
62
|
+
# DETECT AskUserQuestion TOOL
|
|
63
|
+
# ============================================================================
|
|
64
|
+
|
|
65
|
+
TOOL_NAME=""
|
|
66
|
+
|
|
67
|
+
if command -v jq >/dev/null 2>&1; then
|
|
68
|
+
# Use jq if available (most reliable)
|
|
69
|
+
TOOL_NAME=$(jq -r '.tool_name // empty' "$STDIN_DATA" 2>/dev/null)
|
|
70
|
+
else
|
|
71
|
+
# Fallback: grep-based detection
|
|
72
|
+
if grep -q '"tool_name"' "$STDIN_DATA" 2>/dev/null; then
|
|
73
|
+
TOOL_NAME=$(grep -o '"tool_name":"[^"]*"' "$STDIN_DATA" | cut -d'"' -f4)
|
|
74
|
+
fi
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
echo "[$(date)] Tool name: $TOOL_NAME" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
78
|
+
|
|
79
|
+
# ============================================================================
|
|
80
|
+
# PLAY SOUND IF AskUserQuestion
|
|
81
|
+
# ============================================================================
|
|
82
|
+
|
|
83
|
+
play_sound() {
|
|
84
|
+
case "$(uname -s)" in
|
|
85
|
+
Darwin)
|
|
86
|
+
# macOS: Use afplay with a distinctive sound for questions
|
|
87
|
+
afplay /System/Library/Sounds/Tink.aiff 2>/dev/null || true
|
|
88
|
+
;;
|
|
89
|
+
Linux)
|
|
90
|
+
# Linux: Use paplay or aplay
|
|
91
|
+
paplay /usr/share/sounds/freedesktop/stereo/dialog-question.oga 2>/dev/null || \
|
|
92
|
+
paplay /usr/share/sounds/freedesktop/stereo/message-new-instant.oga 2>/dev/null || \
|
|
93
|
+
aplay /usr/share/sounds/alsa/Front_Center.wav 2>/dev/null || true
|
|
94
|
+
;;
|
|
95
|
+
MINGW*|MSYS*|CYGWIN*)
|
|
96
|
+
# Windows: Use PowerShell
|
|
97
|
+
powershell -c "(New-Object Media.SoundPlayer 'C:\Windows\Media\Windows Notify.wav').PlaySync();" 2>/dev/null || true
|
|
98
|
+
;;
|
|
99
|
+
esac
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if [ "$TOOL_NAME" = "AskUserQuestion" ]; then
|
|
103
|
+
echo "[$(date)] 🔔 QUESTION DETECTED! Playing notification sound" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
104
|
+
play_sound
|
|
105
|
+
|
|
106
|
+
# Log this event
|
|
107
|
+
echo "[$(date)] Claude is asking for user input via AskUserQuestion" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# ============================================================================
|
|
111
|
+
# CLEANUP
|
|
112
|
+
# ============================================================================
|
|
113
|
+
|
|
114
|
+
rm -f "$STDIN_DATA"
|
|
115
|
+
|
|
116
|
+
# ============================================================================
|
|
117
|
+
# OUTPUT TO CLAUDE (Always continue)
|
|
118
|
+
# ============================================================================
|
|
119
|
+
|
|
120
|
+
if [ "$TOOL_NAME" = "AskUserQuestion" ]; then
|
|
121
|
+
cat <<EOF
|
|
122
|
+
{
|
|
123
|
+
"continue": true,
|
|
124
|
+
"systemMessage": "🔔 Sound played - user notified of question request"
|
|
125
|
+
}
|
|
126
|
+
EOF
|
|
127
|
+
else
|
|
128
|
+
cat <<EOF
|
|
129
|
+
{
|
|
130
|
+
"continue": true
|
|
131
|
+
}
|
|
132
|
+
EOF
|
|
133
|
+
fi
|