specweave 1.0.551 → 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.
Files changed (132) hide show
  1. package/bin/specweave.js +23 -1
  2. package/dist/src/cli/commands/hook.d.ts +15 -0
  3. package/dist/src/cli/commands/hook.d.ts.map +1 -0
  4. package/dist/src/cli/commands/hook.js +61 -0
  5. package/dist/src/cli/commands/hook.js.map +1 -0
  6. package/dist/src/config/types.d.ts +2 -2
  7. package/dist/src/core/hooks/handlers/hook-router.d.ts +19 -0
  8. package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -0
  9. package/dist/src/core/hooks/handlers/hook-router.js +75 -0
  10. package/dist/src/core/hooks/handlers/hook-router.js.map +1 -0
  11. package/dist/src/core/hooks/handlers/index.d.ts +10 -0
  12. package/dist/src/core/hooks/handlers/index.d.ts.map +1 -0
  13. package/dist/src/core/hooks/handlers/index.js +9 -0
  14. package/dist/src/core/hooks/handlers/index.js.map +1 -0
  15. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +11 -0
  16. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +1 -0
  17. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +73 -0
  18. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +1 -0
  19. package/dist/src/core/hooks/handlers/post-tool-use.d.ts +11 -0
  20. package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +1 -0
  21. package/dist/src/core/hooks/handlers/post-tool-use.js +76 -0
  22. package/dist/src/core/hooks/handlers/post-tool-use.js.map +1 -0
  23. package/dist/src/core/hooks/handlers/pre-compact.d.ts +11 -0
  24. package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
  25. package/dist/src/core/hooks/handlers/pre-compact.js +77 -0
  26. package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
  27. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts +11 -0
  28. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -0
  29. package/dist/src/core/hooks/handlers/pre-tool-use.js +318 -0
  30. package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -0
  31. package/dist/src/core/hooks/handlers/session-start.d.ts +9 -0
  32. package/dist/src/core/hooks/handlers/session-start.d.ts.map +1 -0
  33. package/dist/src/core/hooks/handlers/session-start.js +111 -0
  34. package/dist/src/core/hooks/handlers/session-start.js.map +1 -0
  35. package/dist/src/core/hooks/handlers/stop-auto.d.ts +16 -0
  36. package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +1 -0
  37. package/dist/src/core/hooks/handlers/stop-auto.js +122 -0
  38. package/dist/src/core/hooks/handlers/stop-auto.js.map +1 -0
  39. package/dist/src/core/hooks/handlers/stop-reflect.d.ts +14 -0
  40. package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +1 -0
  41. package/dist/src/core/hooks/handlers/stop-reflect.js +43 -0
  42. package/dist/src/core/hooks/handlers/stop-reflect.js.map +1 -0
  43. package/dist/src/core/hooks/handlers/stop-sync.d.ts +15 -0
  44. package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +1 -0
  45. package/dist/src/core/hooks/handlers/stop-sync.js +68 -0
  46. package/dist/src/core/hooks/handlers/stop-sync.js.map +1 -0
  47. package/dist/src/core/hooks/handlers/types.d.ts +63 -0
  48. package/dist/src/core/hooks/handlers/types.d.ts.map +1 -0
  49. package/dist/src/core/hooks/handlers/types.js +27 -0
  50. package/dist/src/core/hooks/handlers/types.js.map +1 -0
  51. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts +14 -0
  52. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -0
  53. package/dist/src/core/hooks/handlers/user-prompt-submit.js +173 -0
  54. package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -0
  55. package/dist/src/core/hooks/handlers/utils.d.ts +25 -0
  56. package/dist/src/core/hooks/handlers/utils.d.ts.map +1 -0
  57. package/dist/src/core/hooks/handlers/utils.js +64 -0
  58. package/dist/src/core/hooks/handlers/utils.js.map +1 -0
  59. package/dist/src/init/research/types.d.ts +1 -1
  60. package/dist/src/sync/sync-target-resolver.js.map +1 -1
  61. package/dist/src/utils/lock-manager.d.ts.map +1 -1
  62. package/dist/src/utils/lock-manager.js +5 -0
  63. package/dist/src/utils/lock-manager.js.map +1 -1
  64. package/dist/src/utils/plugin-copier.d.ts.map +1 -1
  65. package/dist/src/utils/plugin-copier.js +3 -30
  66. package/dist/src/utils/plugin-copier.js.map +1 -1
  67. package/package.json +1 -1
  68. package/plugins/specweave/hooks/hooks.json +10 -10
  69. package/plugins/specweave/hooks/README.md +0 -493
  70. package/plugins/specweave/hooks/_archive/stop-auto-v4-legacy.sh +0 -1319
  71. package/plugins/specweave/hooks/lib/common-setup.sh +0 -144
  72. package/plugins/specweave/hooks/lib/hook-errors.sh +0 -414
  73. package/plugins/specweave/hooks/lib/migrate-increment-work.sh +0 -245
  74. package/plugins/specweave/hooks/lib/resolve-package.sh +0 -146
  75. package/plugins/specweave/hooks/lib/scheduler-startup.sh +0 -135
  76. package/plugins/specweave/hooks/lib/score-increment.sh +0 -87
  77. package/plugins/specweave/hooks/lib/sync-spec-content.sh +0 -193
  78. package/plugins/specweave/hooks/lib/update-active-increment.sh +0 -95
  79. package/plugins/specweave/hooks/lib/update-status-line.sh +0 -233
  80. package/plugins/specweave/hooks/lib/validate-spec-status.sh +0 -171
  81. package/plugins/specweave/hooks/llm-judge-validator.sh +0 -219
  82. package/plugins/specweave/hooks/log-decision.sh +0 -168
  83. package/plugins/specweave/hooks/pre-compact.sh +0 -64
  84. package/plugins/specweave/hooks/startup-health-check.sh +0 -64
  85. package/plugins/specweave/hooks/stop-auto-v5.sh +0 -276
  86. package/plugins/specweave/hooks/stop-reflect.sh +0 -336
  87. package/plugins/specweave/hooks/stop-sync.sh +0 -283
  88. package/plugins/specweave/hooks/tests/test-auto-context-integration.sh +0 -126
  89. package/plugins/specweave/hooks/tests/test-stop-auto-enriched.sh +0 -128
  90. package/plugins/specweave/hooks/universal/dispatcher.mjs +0 -336
  91. package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +0 -325
  92. package/plugins/specweave/hooks/universal/hook-wrapper.cmd +0 -26
  93. package/plugins/specweave/hooks/universal/hook-wrapper.sh +0 -69
  94. package/plugins/specweave/hooks/universal/run-hook.sh +0 -20
  95. package/plugins/specweave/hooks/universal/session-start.cmd +0 -16
  96. package/plugins/specweave/hooks/universal/session-start.ps1 +0 -16
  97. package/plugins/specweave/hooks/user-prompt-submit.sh +0 -2550
  98. package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +0 -87
  99. package/plugins/specweave/hooks/v2/detectors/us-completion-detector.sh +0 -186
  100. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +0 -83
  101. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +0 -447
  102. package/plugins/specweave/hooks/v2/dispatchers/pre-tool-use.sh +0 -104
  103. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +0 -270
  104. package/plugins/specweave/hooks/v2/guards/completion-guard.sh +0 -14
  105. package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +0 -14
  106. package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +0 -240
  107. package/plugins/specweave/hooks/v2/guards/interview-enforcement-guard.sh +0 -171
  108. package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +0 -14
  109. package/plugins/specweave/hooks/v2/guards/skill-chain-enforcement-guard.sh +0 -222
  110. package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +0 -21
  111. package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +0 -14
  112. package/plugins/specweave/hooks/v2/guards/status-completion-guard.sh +0 -84
  113. package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +0 -475
  114. package/plugins/specweave/hooks/v2/guards/tdd-enforcement-guard.sh +0 -268
  115. package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +0 -332
  116. package/plugins/specweave/hooks/v2/handlers/ac-validation-handler.sh +0 -50
  117. package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +0 -347
  118. package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +0 -83
  119. package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +0 -268
  120. package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +0 -104
  121. package/plugins/specweave/hooks/v2/handlers/status-line-handler.sh +0 -165
  122. package/plugins/specweave/hooks/v2/handlers/status-update.sh +0 -61
  123. package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +0 -270
  124. package/plugins/specweave/hooks/v2/integrations/ado-post-living-docs-update.sh +0 -367
  125. package/plugins/specweave/hooks/v2/integrations/ado-post-task.sh +0 -179
  126. package/plugins/specweave/hooks/v2/integrations/github-auto-create-handler.sh +0 -553
  127. package/plugins/specweave/hooks/v2/integrations/github-post-task.sh +0 -345
  128. package/plugins/specweave/hooks/v2/integrations/jira-post-task.sh +0 -180
  129. package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +0 -52
  130. package/plugins/specweave/hooks/v2/queue/enqueue.sh +0 -81
  131. package/plugins/specweave/hooks/v2/session-end.sh +0 -139
  132. 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