specweave 1.0.550 → 1.0.552
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.md +1 -1
- package/bin/specweave.js +23 -1
- package/dist/src/cli/commands/hook.d.ts +15 -0
- package/dist/src/cli/commands/hook.d.ts.map +1 -0
- package/dist/src/cli/commands/hook.js +61 -0
- package/dist/src/cli/commands/hook.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +5 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.js +11 -1
- package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
- package/dist/src/cli/commands/sync-setup.d.ts.map +1 -1
- package/dist/src/cli/commands/sync-setup.js +7 -3
- package/dist/src/cli/commands/sync-setup.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts +9 -0
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js +9 -3
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js.map +1 -1
- package/dist/src/config/types.d.ts +2 -2
- package/dist/src/core/config/types.d.ts +18 -2
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/hooks/handlers/hook-router.d.ts +19 -0
- package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/hook-router.js +75 -0
- package/dist/src/core/hooks/handlers/hook-router.js.map +1 -0
- package/dist/src/core/hooks/handlers/index.d.ts +10 -0
- package/dist/src/core/hooks/handlers/index.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/index.js +9 -0
- package/dist/src/core/hooks/handlers/index.js.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +11 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +73 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts +11 -0
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use.js +76 -0
- package/dist/src/core/hooks/handlers/post-tool-use.js.map +1 -0
- package/dist/src/core/hooks/handlers/pre-compact.d.ts +11 -0
- package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/pre-compact.js +77 -0
- package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.d.ts +11 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.js +318 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -0
- package/dist/src/core/hooks/handlers/session-start.d.ts +9 -0
- package/dist/src/core/hooks/handlers/session-start.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/session-start.js +111 -0
- package/dist/src/core/hooks/handlers/session-start.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-auto.d.ts +16 -0
- package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-auto.js +122 -0
- package/dist/src/core/hooks/handlers/stop-auto.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts +14 -0
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-reflect.js +43 -0
- package/dist/src/core/hooks/handlers/stop-reflect.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-sync.d.ts +15 -0
- package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-sync.js +68 -0
- package/dist/src/core/hooks/handlers/stop-sync.js.map +1 -0
- package/dist/src/core/hooks/handlers/types.d.ts +63 -0
- package/dist/src/core/hooks/handlers/types.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/types.js +27 -0
- package/dist/src/core/hooks/handlers/types.js.map +1 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts +14 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.js +173 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -0
- package/dist/src/core/hooks/handlers/utils.d.ts +25 -0
- package/dist/src/core/hooks/handlers/utils.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/utils.js +64 -0
- package/dist/src/core/hooks/handlers/utils.js.map +1 -0
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
- package/dist/src/core/increment/completion-validator.js +32 -0
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/init/research/types.d.ts +1 -1
- package/dist/src/sync/sync-target-resolver.js.map +1 -1
- package/dist/src/utils/lock-manager.d.ts.map +1 -1
- package/dist/src/utils/lock-manager.js +5 -0
- package/dist/src/utils/lock-manager.js.map +1 -1
- package/dist/src/utils/plugin-copier.d.ts +10 -0
- package/dist/src/utils/plugin-copier.d.ts.map +1 -1
- package/dist/src/utils/plugin-copier.js +63 -35
- package/dist/src/utils/plugin-copier.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/agents/sw-closer.md +3 -2
- package/plugins/specweave/hooks/hooks.json +10 -10
- package/plugins/specweave/skills/code-reviewer/SKILL.md +180 -16
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-comments.md +83 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-silent-failures.md +19 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-spec-compliance.md +19 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-tests.md +101 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-types.md +20 -0
- package/plugins/specweave/skills/done/SKILL.md +56 -21
- package/plugins/specweave/skills/grill/SKILL.md +1 -1
- package/plugins/specweave/skills/team-lead/agents/reviewer-logic.md +19 -0
- package/plugins/specweave/skills/team-lead/agents/reviewer-performance.md +20 -0
- package/plugins/specweave/skills/team-lead/agents/reviewer-security.md +20 -0
- package/src/templates/CLAUDE.md.template +7 -4
- package/plugins/specweave/hooks/README.md +0 -493
- package/plugins/specweave/hooks/_archive/stop-auto-v4-legacy.sh +0 -1319
- package/plugins/specweave/hooks/lib/common-setup.sh +0 -144
- package/plugins/specweave/hooks/lib/hook-errors.sh +0 -414
- package/plugins/specweave/hooks/lib/migrate-increment-work.sh +0 -245
- package/plugins/specweave/hooks/lib/resolve-package.sh +0 -146
- package/plugins/specweave/hooks/lib/scheduler-startup.sh +0 -135
- package/plugins/specweave/hooks/lib/score-increment.sh +0 -87
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +0 -193
- package/plugins/specweave/hooks/lib/update-active-increment.sh +0 -95
- package/plugins/specweave/hooks/lib/update-status-line.sh +0 -233
- package/plugins/specweave/hooks/lib/validate-spec-status.sh +0 -171
- package/plugins/specweave/hooks/llm-judge-validator.sh +0 -219
- package/plugins/specweave/hooks/log-decision.sh +0 -168
- package/plugins/specweave/hooks/pre-compact.sh +0 -64
- package/plugins/specweave/hooks/startup-health-check.sh +0 -64
- package/plugins/specweave/hooks/stop-auto-v5.sh +0 -276
- package/plugins/specweave/hooks/stop-reflect.sh +0 -336
- package/plugins/specweave/hooks/stop-sync.sh +0 -283
- package/plugins/specweave/hooks/tests/test-auto-context-integration.sh +0 -126
- package/plugins/specweave/hooks/tests/test-stop-auto-enriched.sh +0 -128
- package/plugins/specweave/hooks/universal/dispatcher.mjs +0 -336
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +0 -325
- package/plugins/specweave/hooks/universal/hook-wrapper.cmd +0 -26
- package/plugins/specweave/hooks/universal/hook-wrapper.sh +0 -69
- package/plugins/specweave/hooks/universal/run-hook.sh +0 -20
- package/plugins/specweave/hooks/universal/session-start.cmd +0 -16
- package/plugins/specweave/hooks/universal/session-start.ps1 +0 -16
- package/plugins/specweave/hooks/user-prompt-submit.sh +0 -2550
- package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +0 -87
- package/plugins/specweave/hooks/v2/detectors/us-completion-detector.sh +0 -186
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +0 -83
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +0 -447
- package/plugins/specweave/hooks/v2/dispatchers/pre-tool-use.sh +0 -104
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +0 -270
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +0 -240
- package/plugins/specweave/hooks/v2/guards/interview-enforcement-guard.sh +0 -171
- package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/skill-chain-enforcement-guard.sh +0 -222
- package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +0 -21
- package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/status-completion-guard.sh +0 -84
- package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +0 -475
- package/plugins/specweave/hooks/v2/guards/tdd-enforcement-guard.sh +0 -268
- package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +0 -332
- package/plugins/specweave/hooks/v2/handlers/ac-validation-handler.sh +0 -50
- package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +0 -347
- package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +0 -83
- package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +0 -268
- package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +0 -104
- package/plugins/specweave/hooks/v2/handlers/status-line-handler.sh +0 -165
- package/plugins/specweave/hooks/v2/handlers/status-update.sh +0 -61
- package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +0 -270
- package/plugins/specweave/hooks/v2/integrations/ado-post-living-docs-update.sh +0 -367
- package/plugins/specweave/hooks/v2/integrations/ado-post-task.sh +0 -179
- package/plugins/specweave/hooks/v2/integrations/github-auto-create-handler.sh +0 -553
- package/plugins/specweave/hooks/v2/integrations/github-post-task.sh +0 -345
- package/plugins/specweave/hooks/v2/integrations/jira-post-task.sh +0 -180
- package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +0 -52
- package/plugins/specweave/hooks/v2/queue/enqueue.sh +0 -81
- package/plugins/specweave/hooks/v2/session-end.sh +0 -139
- package/plugins/specweave/hooks/validate-skill-activations.sh +0 -227
|
@@ -1,475 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# task-ac-sync-guard.sh - Non-blocking Task-AC synchronization
|
|
3
|
-
#
|
|
4
|
-
# v1.0.43+: FULLY NON-BLOCKING - operations ALWAYS succeed, errors become warnings
|
|
5
|
-
#
|
|
6
|
-
# CRITICAL DESIGN PRINCIPLE:
|
|
7
|
-
# - This hook MUST NEVER cause an Edit to fail
|
|
8
|
-
# - All errors are logged as warnings
|
|
9
|
-
# - Original operation ALWAYS succeeds
|
|
10
|
-
# - If sync fails, user gets warning message (not error)
|
|
11
|
-
#
|
|
12
|
-
# When a task is marked complete in tasks.md, this hook:
|
|
13
|
-
# 1. Marks all **Acceptance** checkboxes in the completed task as [x]
|
|
14
|
-
# 2. Extracts the AC tags from the completed task (e.g., AC-US1-01, AC-US1-02)
|
|
15
|
-
# 3. Automatically marks those ACs as complete in spec.md
|
|
16
|
-
# 4. When ALL tasks are complete -> auto-transitions status to ready_for_review
|
|
17
|
-
#
|
|
18
|
-
# PostToolUse hook - runs AFTER Edit/Write tool completes on tasks.md
|
|
19
|
-
#
|
|
20
|
-
# CROSS-PLATFORM: Works on macOS, Linux, and Windows (Git Bash/WSL)
|
|
21
|
-
|
|
22
|
-
set +e # CRITICAL: Never exit on error
|
|
23
|
-
|
|
24
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
25
|
-
|
|
26
|
-
# ============================================================================
|
|
27
|
-
# CONSTANTS
|
|
28
|
-
# ============================================================================
|
|
29
|
-
|
|
30
|
-
HOOK_NAME="task-ac-sync"
|
|
31
|
-
HOOK_VERSION="1.0.43"
|
|
32
|
-
|
|
33
|
-
# ============================================================================
|
|
34
|
-
# PROJECT ROOT DETECTION (CRITICAL: must NOT fallback to pwd!)
|
|
35
|
-
# ============================================================================
|
|
36
|
-
|
|
37
|
-
find_project_root() {
|
|
38
|
-
local dir="$PWD"
|
|
39
|
-
while [[ "$dir" != "/" ]]; do
|
|
40
|
-
if [[ -f "$dir/.specweave/config.json" ]]; then
|
|
41
|
-
echo "$dir"
|
|
42
|
-
return 0
|
|
43
|
-
fi
|
|
44
|
-
dir=$(dirname "$dir")
|
|
45
|
-
done
|
|
46
|
-
# Return empty - NOT pwd (prevents .specweave pollution)
|
|
47
|
-
return 1
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
PROJECT_ROOT=$(find_project_root)
|
|
51
|
-
[[ -z "$PROJECT_ROOT" ]] && exit 0
|
|
52
|
-
[[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
|
|
53
|
-
|
|
54
|
-
# ============================================================================
|
|
55
|
-
# LOGGING INFRASTRUCTURE
|
|
56
|
-
# ============================================================================
|
|
57
|
-
|
|
58
|
-
LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
|
|
59
|
-
DEBUG_LOG="$LOGS_DIR/task-ac-sync.log"
|
|
60
|
-
WARNING_LOG="$LOGS_DIR/hook-warnings.log"
|
|
61
|
-
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
62
|
-
|
|
63
|
-
log_debug() {
|
|
64
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
log_warning() {
|
|
68
|
-
local message="$1"
|
|
69
|
-
local details="${2:-}"
|
|
70
|
-
|
|
71
|
-
# Always log to file
|
|
72
|
-
{
|
|
73
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] WARNING [$HOOK_NAME]: $message"
|
|
74
|
-
[[ -n "$details" ]] && echo " Details: $details"
|
|
75
|
-
} >> "$WARNING_LOG" 2>/dev/null || true
|
|
76
|
-
|
|
77
|
-
# Show to user - they should know the sync didn't work
|
|
78
|
-
echo ""
|
|
79
|
-
echo " [Hook Warning] $HOOK_NAME: $message"
|
|
80
|
-
[[ -n "$details" ]] && echo " $details"
|
|
81
|
-
echo " (File operation succeeded - sync issue only)"
|
|
82
|
-
echo ""
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
log_success() {
|
|
86
|
-
local message="$1"
|
|
87
|
-
log_debug "SUCCESS: $message"
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
# ============================================================================
|
|
91
|
-
# INPUT PARSING (with safe fallbacks)
|
|
92
|
-
# ============================================================================
|
|
93
|
-
|
|
94
|
-
# Accept file path as $1 argument (background mode) or fall back to stdin (sync mode)
|
|
95
|
-
if [[ -n "${1:-}" ]] && [[ "$1" == *tasks.md ]]; then
|
|
96
|
-
FILE_PATH="$1"
|
|
97
|
-
else
|
|
98
|
-
# Legacy: read from stdin (when called via safe_run_sync)
|
|
99
|
-
INPUT=$(timeout 1 cat 2>/dev/null || cat 2>/dev/null || echo '{}')
|
|
100
|
-
FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"\([^"]*\)"/\1/')
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
# Only care about tasks.md files in increments folder
|
|
104
|
-
if [[ "$FILE_PATH" != */.specweave/increments/*/tasks.md ]]; then
|
|
105
|
-
exit 0
|
|
106
|
-
fi
|
|
107
|
-
|
|
108
|
-
log_debug "Task edit detected: $FILE_PATH"
|
|
109
|
-
|
|
110
|
-
# Extract paths
|
|
111
|
-
INCREMENT_DIR=$(dirname "$FILE_PATH")
|
|
112
|
-
SPEC_FILE="$INCREMENT_DIR/spec.md"
|
|
113
|
-
METADATA_FILE="$INCREMENT_DIR/metadata.json"
|
|
114
|
-
|
|
115
|
-
# Verify files exist
|
|
116
|
-
if [[ ! -f "$FILE_PATH" ]]; then
|
|
117
|
-
log_warning "tasks.md not found (may have been moved)" "$FILE_PATH"
|
|
118
|
-
exit 0
|
|
119
|
-
fi
|
|
120
|
-
|
|
121
|
-
# ============================================================================
|
|
122
|
-
# STEP 0: Check if any task is marked complete
|
|
123
|
-
# ============================================================================
|
|
124
|
-
|
|
125
|
-
# Check if tasks.md has any completed tasks (check actual file, not edit input)
|
|
126
|
-
if ! grep -qE '^\*\*Status\*\*:[[:space:]]*\[x\]' "$FILE_PATH" 2>/dev/null; then
|
|
127
|
-
log_debug "No completed tasks found, skipping"
|
|
128
|
-
exit 0
|
|
129
|
-
fi
|
|
130
|
-
|
|
131
|
-
log_debug "Completed tasks detected - syncing ACs..."
|
|
132
|
-
|
|
133
|
-
# ============================================================================
|
|
134
|
-
# STEP 1: Mark task's **Acceptance** checkboxes as complete (NON-BLOCKING)
|
|
135
|
-
# ============================================================================
|
|
136
|
-
|
|
137
|
-
sync_acceptance_checkboxes() {
|
|
138
|
-
log_debug "Syncing acceptance checkboxes..."
|
|
139
|
-
|
|
140
|
-
# Create temp file for safe editing
|
|
141
|
-
local temp_file
|
|
142
|
-
temp_file=$(mktemp 2>/dev/null) || {
|
|
143
|
-
log_warning "Failed to create temp file for acceptance sync"
|
|
144
|
-
return 0
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
# Process with awk (buffered approach - never modifies during read)
|
|
148
|
-
if ! awk '
|
|
149
|
-
BEGIN {
|
|
150
|
-
task_start = 0
|
|
151
|
-
task_lines = ""
|
|
152
|
-
task_completed = 0
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/^### T-[0-9]+:/ {
|
|
156
|
-
if (task_start > 0) {
|
|
157
|
-
n = split(task_lines, lines, "\n")
|
|
158
|
-
in_acceptance = 0
|
|
159
|
-
for (i = 1; i <= n; i++) {
|
|
160
|
-
line = lines[i]
|
|
161
|
-
if (line ~ /^\*\*Acceptance\*\*:/) in_acceptance = 1
|
|
162
|
-
if (line ~ /^\*\*[A-Z]/ && line !~ /^\*\*Acceptance/) in_acceptance = 0
|
|
163
|
-
if (in_acceptance && task_completed && line ~ /^[-*] \[ \]/) {
|
|
164
|
-
sub(/\[ \]/, "[x]", line)
|
|
165
|
-
}
|
|
166
|
-
print line
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
task_start = NR
|
|
170
|
-
task_lines = $0
|
|
171
|
-
task_completed = 0
|
|
172
|
-
next
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
{
|
|
176
|
-
if (task_start > 0) {
|
|
177
|
-
task_lines = task_lines "\n" $0
|
|
178
|
-
if ($0 ~ /^\*\*Status\*\*:[[:space:]]*\[x\]/) {
|
|
179
|
-
task_completed = 1
|
|
180
|
-
}
|
|
181
|
-
} else {
|
|
182
|
-
print
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
END {
|
|
187
|
-
if (task_start > 0) {
|
|
188
|
-
n = split(task_lines, lines, "\n")
|
|
189
|
-
in_acceptance = 0
|
|
190
|
-
for (i = 1; i <= n; i++) {
|
|
191
|
-
line = lines[i]
|
|
192
|
-
if (line ~ /^\*\*Acceptance\*\*:/) in_acceptance = 1
|
|
193
|
-
if (line ~ /^\*\*[A-Z]/ && line !~ /^\*\*Acceptance/) in_acceptance = 0
|
|
194
|
-
if (in_acceptance && task_completed && line ~ /^[-*] \[ \]/) {
|
|
195
|
-
sub(/\[ \]/, "[x]", line)
|
|
196
|
-
}
|
|
197
|
-
print line
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
' "$FILE_PATH" > "$temp_file" 2>/dev/null; then
|
|
202
|
-
log_warning "awk processing failed for acceptance checkboxes"
|
|
203
|
-
rm -f "$temp_file" 2>/dev/null
|
|
204
|
-
return 0
|
|
205
|
-
fi
|
|
206
|
-
|
|
207
|
-
# Verify output is valid (not empty, not truncated)
|
|
208
|
-
if [[ ! -s "$temp_file" ]]; then
|
|
209
|
-
log_warning "awk produced empty output, skipping acceptance sync"
|
|
210
|
-
rm -f "$temp_file" 2>/dev/null
|
|
211
|
-
return 0
|
|
212
|
-
fi
|
|
213
|
-
|
|
214
|
-
# Check if changes were made
|
|
215
|
-
if diff -q "$FILE_PATH" "$temp_file" >/dev/null 2>&1; then
|
|
216
|
-
log_debug "No acceptance checkboxes to update"
|
|
217
|
-
rm -f "$temp_file" 2>/dev/null
|
|
218
|
-
return 0
|
|
219
|
-
fi
|
|
220
|
-
|
|
221
|
-
# Apply changes
|
|
222
|
-
if mv "$temp_file" "$FILE_PATH" 2>/dev/null; then
|
|
223
|
-
log_success "Updated acceptance checkboxes for completed tasks"
|
|
224
|
-
else
|
|
225
|
-
log_warning "Failed to update acceptance checkboxes" "mv failed"
|
|
226
|
-
rm -f "$temp_file" 2>/dev/null
|
|
227
|
-
fi
|
|
228
|
-
|
|
229
|
-
return 0
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
# Run acceptance sync (never fails)
|
|
233
|
-
sync_acceptance_checkboxes
|
|
234
|
-
|
|
235
|
-
# ============================================================================
|
|
236
|
-
# STEP 2: Extract AC tags from completed tasks
|
|
237
|
-
# ============================================================================
|
|
238
|
-
|
|
239
|
-
extract_completed_acs() {
|
|
240
|
-
local tasks_file="$1"
|
|
241
|
-
local -a completed_acs=()
|
|
242
|
-
|
|
243
|
-
# Normalize line endings for cross-platform compatibility
|
|
244
|
-
local temp_normalized
|
|
245
|
-
temp_normalized=$(mktemp 2>/dev/null) || {
|
|
246
|
-
log_warning "Failed to create temp file for AC extraction"
|
|
247
|
-
return 0
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
tr -d '\r' < "$tasks_file" > "$temp_normalized" 2>/dev/null || cat "$tasks_file" > "$temp_normalized"
|
|
251
|
-
|
|
252
|
-
local current_task=""
|
|
253
|
-
local current_acs=""
|
|
254
|
-
|
|
255
|
-
while IFS= read -r line; do
|
|
256
|
-
# Detect task header
|
|
257
|
-
if [[ "$line" =~ ^###[[:space:]]+(T-[0-9]+): ]]; then
|
|
258
|
-
current_task="${BASH_REMATCH[1]}"
|
|
259
|
-
current_acs=""
|
|
260
|
-
fi
|
|
261
|
-
|
|
262
|
-
# Detect AC tags (handle whitespace variations)
|
|
263
|
-
if [[ "$line" =~ ^\*\*Satisfies[[:space:]]*ACs?\*\*:[[:space:]]*(.*) ]]; then
|
|
264
|
-
current_acs="${BASH_REMATCH[1]}"
|
|
265
|
-
fi
|
|
266
|
-
|
|
267
|
-
# Detect completion status
|
|
268
|
-
if [[ "$line" =~ ^\*\*Status\*\*:[[:space:]]*\[x\] ]]; then
|
|
269
|
-
if [[ -n "$current_acs" ]]; then
|
|
270
|
-
# Split ACs by comma
|
|
271
|
-
IFS=',' read -ra AC_ARRAY <<< "$current_acs"
|
|
272
|
-
for ac in "${AC_ARRAY[@]}"; do
|
|
273
|
-
# Trim whitespace and carriage returns
|
|
274
|
-
ac=$(echo "$ac" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
|
|
275
|
-
ac="${ac%$'\r'}"
|
|
276
|
-
[[ -n "$ac" ]] && completed_acs+=("$ac")
|
|
277
|
-
done
|
|
278
|
-
fi
|
|
279
|
-
fi
|
|
280
|
-
done < "$temp_normalized"
|
|
281
|
-
|
|
282
|
-
rm -f "$temp_normalized" 2>/dev/null
|
|
283
|
-
|
|
284
|
-
# Output space-separated list
|
|
285
|
-
echo "${completed_acs[*]}"
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
COMPLETED_ACS_STRING=$(extract_completed_acs "$FILE_PATH")
|
|
289
|
-
read -ra COMPLETED_ACS <<< "$COMPLETED_ACS_STRING"
|
|
290
|
-
|
|
291
|
-
log_debug "Completed ACs: ${COMPLETED_ACS[*]}"
|
|
292
|
-
|
|
293
|
-
# ============================================================================
|
|
294
|
-
# STEP 3: Mark ACs as complete in spec.md (NON-BLOCKING)
|
|
295
|
-
# ============================================================================
|
|
296
|
-
|
|
297
|
-
sync_spec_acs() {
|
|
298
|
-
if [[ ! -f "$SPEC_FILE" ]]; then
|
|
299
|
-
log_debug "spec.md not found, skipping AC sync"
|
|
300
|
-
return 0
|
|
301
|
-
fi
|
|
302
|
-
|
|
303
|
-
if [[ ${#COMPLETED_ACS[@]} -eq 0 ]]; then
|
|
304
|
-
log_debug "No ACs to sync"
|
|
305
|
-
return 0
|
|
306
|
-
fi
|
|
307
|
-
|
|
308
|
-
local updated_count=0
|
|
309
|
-
local not_found_count=0
|
|
310
|
-
local not_found_acs=()
|
|
311
|
-
|
|
312
|
-
for ac in "${COMPLETED_ACS[@]}"; do
|
|
313
|
-
[[ -z "$ac" ]] && continue
|
|
314
|
-
|
|
315
|
-
# Escape special characters for grep/sed
|
|
316
|
-
local ac_escaped
|
|
317
|
-
ac_escaped=$(printf '%s' "$ac" | sed 's/[.[\*^$()+?{|\\]/\\&/g')
|
|
318
|
-
|
|
319
|
-
# Check if AC exists and is unchecked
|
|
320
|
-
# Support multiple formats:
|
|
321
|
-
# - [ ] **AC-US1-01**: Description
|
|
322
|
-
# - [ ] **AC-US1-01** Description
|
|
323
|
-
# - [ ] AC-US1-01: Description
|
|
324
|
-
if grep -qE "^[-*][[:space:]]+\[ \][[:space:]]+(\*\*)?${ac_escaped}(\*\*)?" "$SPEC_FILE" 2>/dev/null; then
|
|
325
|
-
# Try macOS sed first, then Linux
|
|
326
|
-
if sed -i '' "s|^\([-*][[:space:]]\+\)\[ \]\([[:space:]]\+\)\(\*\*\)\?${ac_escaped}\(\*\*\)\?|\1[x]\2\3${ac}\4|" "$SPEC_FILE" 2>/dev/null || \
|
|
327
|
-
sed -i "s|^\([-*][[:space:]]\+\)\[ \]\([[:space:]]\+\)\(\*\*\)\?${ac_escaped}\(\*\*\)\?|\1[x]\2\3${ac}\4|" "$SPEC_FILE" 2>/dev/null; then
|
|
328
|
-
log_debug "Marked AC complete: $ac"
|
|
329
|
-
((updated_count++))
|
|
330
|
-
else
|
|
331
|
-
log_debug "sed failed for AC: $ac"
|
|
332
|
-
not_found_acs+=("$ac")
|
|
333
|
-
((not_found_count++))
|
|
334
|
-
fi
|
|
335
|
-
else
|
|
336
|
-
log_debug "AC not found or already complete: $ac"
|
|
337
|
-
# Check if it's already complete
|
|
338
|
-
if grep -qE "^[-*][[:space:]]+\[x\][[:space:]]+(\*\*)?${ac_escaped}(\*\*)?" "$SPEC_FILE" 2>/dev/null; then
|
|
339
|
-
log_debug "AC already marked complete: $ac"
|
|
340
|
-
else
|
|
341
|
-
not_found_acs+=("$ac")
|
|
342
|
-
((not_found_count++))
|
|
343
|
-
fi
|
|
344
|
-
fi
|
|
345
|
-
done
|
|
346
|
-
|
|
347
|
-
if [[ $updated_count -gt 0 ]]; then
|
|
348
|
-
log_success "Updated $updated_count ACs in spec.md"
|
|
349
|
-
fi
|
|
350
|
-
|
|
351
|
-
if [[ $not_found_count -gt 0 ]]; then
|
|
352
|
-
log_warning "Some ACs could not be synced to spec.md" "Not found: ${not_found_acs[*]}"
|
|
353
|
-
fi
|
|
354
|
-
|
|
355
|
-
return 0
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
# Run spec AC sync (never fails)
|
|
359
|
-
sync_spec_acs
|
|
360
|
-
|
|
361
|
-
# ============================================================================
|
|
362
|
-
# STEP 4: Check if ALL tasks complete -> auto-transition to ready_for_review
|
|
363
|
-
# ============================================================================
|
|
364
|
-
|
|
365
|
-
check_auto_transition() {
|
|
366
|
-
local total_tasks
|
|
367
|
-
local completed_tasks
|
|
368
|
-
|
|
369
|
-
total_tasks=$(grep -c '^\*\*Status\*\*:' "$FILE_PATH" 2>/dev/null || echo 0)
|
|
370
|
-
completed_tasks=$(grep -c '^\*\*Status\*\*:[[:space:]]*\[x\]' "$FILE_PATH" 2>/dev/null || echo 0)
|
|
371
|
-
|
|
372
|
-
log_debug "Task progress: $completed_tasks / $total_tasks"
|
|
373
|
-
|
|
374
|
-
# Not all complete? Exit early
|
|
375
|
-
if [[ "$total_tasks" -eq 0 ]] || [[ "$completed_tasks" -ne "$total_tasks" ]]; then
|
|
376
|
-
return 0
|
|
377
|
-
fi
|
|
378
|
-
|
|
379
|
-
log_debug "ALL TASKS COMPLETE! Checking for auto-transition..."
|
|
380
|
-
|
|
381
|
-
# Need jq for JSON manipulation
|
|
382
|
-
if ! command -v jq >/dev/null 2>&1; then
|
|
383
|
-
log_warning "jq not installed - status auto-transition skipped" \
|
|
384
|
-
"Install: brew install jq (macOS) | apt install jq (Linux)"
|
|
385
|
-
return 0
|
|
386
|
-
fi
|
|
387
|
-
|
|
388
|
-
if [[ ! -f "$METADATA_FILE" ]]; then
|
|
389
|
-
log_debug "metadata.json not found, skipping auto-transition"
|
|
390
|
-
return 0
|
|
391
|
-
fi
|
|
392
|
-
|
|
393
|
-
local current_status
|
|
394
|
-
current_status=$(jq -r '.status // "active"' "$METADATA_FILE" 2>/dev/null)
|
|
395
|
-
|
|
396
|
-
if [[ "$current_status" != "active" ]] && [[ "$current_status" != "in-progress" ]]; then
|
|
397
|
-
log_debug "Status is '$current_status', not auto-transitioning"
|
|
398
|
-
return 0
|
|
399
|
-
fi
|
|
400
|
-
|
|
401
|
-
# Auto-transition to ready_for_review
|
|
402
|
-
log_debug "Auto-transitioning: $current_status -> ready_for_review"
|
|
403
|
-
|
|
404
|
-
local tmp_file
|
|
405
|
-
tmp_file=$(mktemp 2>/dev/null) || {
|
|
406
|
-
log_warning "Failed to create temp file for status update"
|
|
407
|
-
return 0
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
if jq '.status = "ready_for_review" | .updated = (now | strftime("%Y-%m-%dT%H:%M:%S.000Z"))' \
|
|
411
|
-
"$METADATA_FILE" > "$tmp_file" 2>/dev/null && [[ -s "$tmp_file" ]]; then
|
|
412
|
-
if mv "$tmp_file" "$METADATA_FILE" 2>/dev/null; then
|
|
413
|
-
log_success "Status updated to ready_for_review"
|
|
414
|
-
|
|
415
|
-
# Show success banner to user
|
|
416
|
-
echo ""
|
|
417
|
-
echo " ALL TASKS COMPLETED! Status -> ready_for_review"
|
|
418
|
-
echo " ------------------------------------------------"
|
|
419
|
-
echo " Tasks: $completed_tasks/$total_tasks (100%)"
|
|
420
|
-
echo ""
|
|
421
|
-
echo " Next step: Run /sw:done to close the increment"
|
|
422
|
-
echo " ------------------------------------------------"
|
|
423
|
-
echo ""
|
|
424
|
-
else
|
|
425
|
-
log_warning "Failed to update metadata.json"
|
|
426
|
-
rm -f "$tmp_file" 2>/dev/null
|
|
427
|
-
fi
|
|
428
|
-
else
|
|
429
|
-
log_warning "jq failed to update metadata.json"
|
|
430
|
-
rm -f "$tmp_file" 2>/dev/null
|
|
431
|
-
fi
|
|
432
|
-
|
|
433
|
-
return 0
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
# Run auto-transition check (never fails)
|
|
437
|
-
check_auto_transition
|
|
438
|
-
|
|
439
|
-
# ============================================================================
|
|
440
|
-
# STEP 5: Trigger LifecycleHookDispatcher.onTaskCompleted (NON-BLOCKING)
|
|
441
|
-
# ============================================================================
|
|
442
|
-
|
|
443
|
-
trigger_sync_task() {
|
|
444
|
-
# Extract increment folder name (e.g. "0400-sync-pipeline-reliability")
|
|
445
|
-
local increment_id
|
|
446
|
-
increment_id=$(basename "$INCREMENT_DIR")
|
|
447
|
-
|
|
448
|
-
[[ -z "$increment_id" ]] && return 0
|
|
449
|
-
|
|
450
|
-
# Find specweave CLI (npx fallback)
|
|
451
|
-
local sw_bin=""
|
|
452
|
-
if command -v specweave >/dev/null 2>&1; then
|
|
453
|
-
sw_bin="specweave"
|
|
454
|
-
elif command -v npx >/dev/null 2>&1; then
|
|
455
|
-
sw_bin="npx specweave"
|
|
456
|
-
else
|
|
457
|
-
log_debug "specweave CLI not found, skipping sync-task"
|
|
458
|
-
return 0
|
|
459
|
-
fi
|
|
460
|
-
|
|
461
|
-
# Run in background — must not block the Edit operation
|
|
462
|
-
(cd "$PROJECT_ROOT" && $sw_bin sync-task "$increment_id" >>"$DEBUG_LOG" 2>&1) &
|
|
463
|
-
log_debug "Spawned sync-task for $increment_id (pid $!)"
|
|
464
|
-
return 0
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
# Run sync-task trigger (never fails, never blocks)
|
|
468
|
-
trigger_sync_task
|
|
469
|
-
|
|
470
|
-
# ============================================================================
|
|
471
|
-
# ALWAYS EXIT SUCCESS
|
|
472
|
-
# ============================================================================
|
|
473
|
-
|
|
474
|
-
log_debug "Hook completed successfully"
|
|
475
|
-
exit 0
|