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.
Files changed (166) hide show
  1. package/CLAUDE.md +1 -1
  2. package/bin/specweave.js +23 -1
  3. package/dist/src/cli/commands/hook.d.ts +15 -0
  4. package/dist/src/cli/commands/hook.d.ts.map +1 -0
  5. package/dist/src/cli/commands/hook.js +61 -0
  6. package/dist/src/cli/commands/hook.js.map +1 -0
  7. package/dist/src/cli/commands/init.d.ts.map +1 -1
  8. package/dist/src/cli/commands/init.js +5 -0
  9. package/dist/src/cli/commands/init.js.map +1 -1
  10. package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
  11. package/dist/src/cli/commands/refresh-plugins.js +11 -1
  12. package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
  13. package/dist/src/cli/commands/sync-setup.d.ts.map +1 -1
  14. package/dist/src/cli/commands/sync-setup.js +7 -3
  15. package/dist/src/cli/commands/sync-setup.js.map +1 -1
  16. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts +9 -0
  17. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts.map +1 -1
  18. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js +9 -3
  19. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js.map +1 -1
  20. package/dist/src/config/types.d.ts +2 -2
  21. package/dist/src/core/config/types.d.ts +18 -2
  22. package/dist/src/core/config/types.d.ts.map +1 -1
  23. package/dist/src/core/config/types.js.map +1 -1
  24. package/dist/src/core/hooks/handlers/hook-router.d.ts +19 -0
  25. package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -0
  26. package/dist/src/core/hooks/handlers/hook-router.js +75 -0
  27. package/dist/src/core/hooks/handlers/hook-router.js.map +1 -0
  28. package/dist/src/core/hooks/handlers/index.d.ts +10 -0
  29. package/dist/src/core/hooks/handlers/index.d.ts.map +1 -0
  30. package/dist/src/core/hooks/handlers/index.js +9 -0
  31. package/dist/src/core/hooks/handlers/index.js.map +1 -0
  32. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +11 -0
  33. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +1 -0
  34. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +73 -0
  35. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +1 -0
  36. package/dist/src/core/hooks/handlers/post-tool-use.d.ts +11 -0
  37. package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +1 -0
  38. package/dist/src/core/hooks/handlers/post-tool-use.js +76 -0
  39. package/dist/src/core/hooks/handlers/post-tool-use.js.map +1 -0
  40. package/dist/src/core/hooks/handlers/pre-compact.d.ts +11 -0
  41. package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
  42. package/dist/src/core/hooks/handlers/pre-compact.js +77 -0
  43. package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
  44. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts +11 -0
  45. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -0
  46. package/dist/src/core/hooks/handlers/pre-tool-use.js +318 -0
  47. package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -0
  48. package/dist/src/core/hooks/handlers/session-start.d.ts +9 -0
  49. package/dist/src/core/hooks/handlers/session-start.d.ts.map +1 -0
  50. package/dist/src/core/hooks/handlers/session-start.js +111 -0
  51. package/dist/src/core/hooks/handlers/session-start.js.map +1 -0
  52. package/dist/src/core/hooks/handlers/stop-auto.d.ts +16 -0
  53. package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +1 -0
  54. package/dist/src/core/hooks/handlers/stop-auto.js +122 -0
  55. package/dist/src/core/hooks/handlers/stop-auto.js.map +1 -0
  56. package/dist/src/core/hooks/handlers/stop-reflect.d.ts +14 -0
  57. package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +1 -0
  58. package/dist/src/core/hooks/handlers/stop-reflect.js +43 -0
  59. package/dist/src/core/hooks/handlers/stop-reflect.js.map +1 -0
  60. package/dist/src/core/hooks/handlers/stop-sync.d.ts +15 -0
  61. package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +1 -0
  62. package/dist/src/core/hooks/handlers/stop-sync.js +68 -0
  63. package/dist/src/core/hooks/handlers/stop-sync.js.map +1 -0
  64. package/dist/src/core/hooks/handlers/types.d.ts +63 -0
  65. package/dist/src/core/hooks/handlers/types.d.ts.map +1 -0
  66. package/dist/src/core/hooks/handlers/types.js +27 -0
  67. package/dist/src/core/hooks/handlers/types.js.map +1 -0
  68. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts +14 -0
  69. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -0
  70. package/dist/src/core/hooks/handlers/user-prompt-submit.js +173 -0
  71. package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -0
  72. package/dist/src/core/hooks/handlers/utils.d.ts +25 -0
  73. package/dist/src/core/hooks/handlers/utils.d.ts.map +1 -0
  74. package/dist/src/core/hooks/handlers/utils.js +64 -0
  75. package/dist/src/core/hooks/handlers/utils.js.map +1 -0
  76. package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
  77. package/dist/src/core/increment/completion-validator.js +32 -0
  78. package/dist/src/core/increment/completion-validator.js.map +1 -1
  79. package/dist/src/init/research/types.d.ts +1 -1
  80. package/dist/src/sync/sync-target-resolver.js.map +1 -1
  81. package/dist/src/utils/lock-manager.d.ts.map +1 -1
  82. package/dist/src/utils/lock-manager.js +5 -0
  83. package/dist/src/utils/lock-manager.js.map +1 -1
  84. package/dist/src/utils/plugin-copier.d.ts +10 -0
  85. package/dist/src/utils/plugin-copier.d.ts.map +1 -1
  86. package/dist/src/utils/plugin-copier.js +63 -35
  87. package/dist/src/utils/plugin-copier.js.map +1 -1
  88. package/package.json +1 -1
  89. package/plugins/specweave/agents/sw-closer.md +3 -2
  90. package/plugins/specweave/hooks/hooks.json +10 -10
  91. package/plugins/specweave/skills/code-reviewer/SKILL.md +180 -16
  92. package/plugins/specweave/skills/code-reviewer/agents/reviewer-comments.md +83 -0
  93. package/plugins/specweave/skills/code-reviewer/agents/reviewer-silent-failures.md +19 -0
  94. package/plugins/specweave/skills/code-reviewer/agents/reviewer-spec-compliance.md +19 -0
  95. package/plugins/specweave/skills/code-reviewer/agents/reviewer-tests.md +101 -0
  96. package/plugins/specweave/skills/code-reviewer/agents/reviewer-types.md +20 -0
  97. package/plugins/specweave/skills/done/SKILL.md +56 -21
  98. package/plugins/specweave/skills/grill/SKILL.md +1 -1
  99. package/plugins/specweave/skills/team-lead/agents/reviewer-logic.md +19 -0
  100. package/plugins/specweave/skills/team-lead/agents/reviewer-performance.md +20 -0
  101. package/plugins/specweave/skills/team-lead/agents/reviewer-security.md +20 -0
  102. package/src/templates/CLAUDE.md.template +7 -4
  103. package/plugins/specweave/hooks/README.md +0 -493
  104. package/plugins/specweave/hooks/_archive/stop-auto-v4-legacy.sh +0 -1319
  105. package/plugins/specweave/hooks/lib/common-setup.sh +0 -144
  106. package/plugins/specweave/hooks/lib/hook-errors.sh +0 -414
  107. package/plugins/specweave/hooks/lib/migrate-increment-work.sh +0 -245
  108. package/plugins/specweave/hooks/lib/resolve-package.sh +0 -146
  109. package/plugins/specweave/hooks/lib/scheduler-startup.sh +0 -135
  110. package/plugins/specweave/hooks/lib/score-increment.sh +0 -87
  111. package/plugins/specweave/hooks/lib/sync-spec-content.sh +0 -193
  112. package/plugins/specweave/hooks/lib/update-active-increment.sh +0 -95
  113. package/plugins/specweave/hooks/lib/update-status-line.sh +0 -233
  114. package/plugins/specweave/hooks/lib/validate-spec-status.sh +0 -171
  115. package/plugins/specweave/hooks/llm-judge-validator.sh +0 -219
  116. package/plugins/specweave/hooks/log-decision.sh +0 -168
  117. package/plugins/specweave/hooks/pre-compact.sh +0 -64
  118. package/plugins/specweave/hooks/startup-health-check.sh +0 -64
  119. package/plugins/specweave/hooks/stop-auto-v5.sh +0 -276
  120. package/plugins/specweave/hooks/stop-reflect.sh +0 -336
  121. package/plugins/specweave/hooks/stop-sync.sh +0 -283
  122. package/plugins/specweave/hooks/tests/test-auto-context-integration.sh +0 -126
  123. package/plugins/specweave/hooks/tests/test-stop-auto-enriched.sh +0 -128
  124. package/plugins/specweave/hooks/universal/dispatcher.mjs +0 -336
  125. package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +0 -325
  126. package/plugins/specweave/hooks/universal/hook-wrapper.cmd +0 -26
  127. package/plugins/specweave/hooks/universal/hook-wrapper.sh +0 -69
  128. package/plugins/specweave/hooks/universal/run-hook.sh +0 -20
  129. package/plugins/specweave/hooks/universal/session-start.cmd +0 -16
  130. package/plugins/specweave/hooks/universal/session-start.ps1 +0 -16
  131. package/plugins/specweave/hooks/user-prompt-submit.sh +0 -2550
  132. package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +0 -87
  133. package/plugins/specweave/hooks/v2/detectors/us-completion-detector.sh +0 -186
  134. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +0 -83
  135. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +0 -447
  136. package/plugins/specweave/hooks/v2/dispatchers/pre-tool-use.sh +0 -104
  137. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +0 -270
  138. package/plugins/specweave/hooks/v2/guards/completion-guard.sh +0 -14
  139. package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +0 -14
  140. package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +0 -240
  141. package/plugins/specweave/hooks/v2/guards/interview-enforcement-guard.sh +0 -171
  142. package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +0 -14
  143. package/plugins/specweave/hooks/v2/guards/skill-chain-enforcement-guard.sh +0 -222
  144. package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +0 -21
  145. package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +0 -14
  146. package/plugins/specweave/hooks/v2/guards/status-completion-guard.sh +0 -84
  147. package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +0 -475
  148. package/plugins/specweave/hooks/v2/guards/tdd-enforcement-guard.sh +0 -268
  149. package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +0 -332
  150. package/plugins/specweave/hooks/v2/handlers/ac-validation-handler.sh +0 -50
  151. package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +0 -347
  152. package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +0 -83
  153. package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +0 -268
  154. package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +0 -104
  155. package/plugins/specweave/hooks/v2/handlers/status-line-handler.sh +0 -165
  156. package/plugins/specweave/hooks/v2/handlers/status-update.sh +0 -61
  157. package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +0 -270
  158. package/plugins/specweave/hooks/v2/integrations/ado-post-living-docs-update.sh +0 -367
  159. package/plugins/specweave/hooks/v2/integrations/ado-post-task.sh +0 -179
  160. package/plugins/specweave/hooks/v2/integrations/github-auto-create-handler.sh +0 -553
  161. package/plugins/specweave/hooks/v2/integrations/github-post-task.sh +0 -345
  162. package/plugins/specweave/hooks/v2/integrations/jira-post-task.sh +0 -180
  163. package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +0 -52
  164. package/plugins/specweave/hooks/v2/queue/enqueue.sh +0 -81
  165. package/plugins/specweave/hooks/v2/session-end.sh +0 -139
  166. package/plugins/specweave/hooks/validate-skill-activations.sh +0 -227
@@ -1,268 +0,0 @@
1
- #!/bin/bash
2
- # tdd-enforcement-guard.sh - Warn on TDD discipline violations (v1.0.105)
3
- #
4
- # Called from: post-tool-use.sh when tasks.md is edited
5
- # Action: WARNING only (not blocking) - educates users
6
- #
7
- # TDD Violations detected:
8
- # 1. GREEN task completed before RED task
9
- # 2. REFACTOR task completed before GREEN task
10
- #
11
- # IMPORTANT: This is a WARNING-ONLY hook. It never blocks operations.
12
- # The goal is to educate users about TDD discipline, not punish them.
13
- #
14
- # COMPATIBILITY: Works on macOS (bash 3.2) and Linux (bash 4+)
15
-
16
- set +e # CRITICAL: Never exit on error - this is a warning-only hook
17
-
18
- # ============================================================================
19
- # CONFIGURATION
20
- # ============================================================================
21
-
22
- PROJECT_ROOT="${1:-$(pwd)}"
23
- FILE_PATH="${2:-}"
24
- TOOL_NAME="${3:-Edit}"
25
-
26
- # Debug logging
27
- LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
28
- DEBUG_LOG="$LOGS_DIR/tdd-enforcement.log"
29
- mkdir -p "$LOGS_DIR" 2>/dev/null || true
30
-
31
- log_debug() {
32
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$DEBUG_LOG" 2>/dev/null || true
33
- }
34
-
35
- log_debug "tdd-enforcement-guard invoked: FILE_PATH=$FILE_PATH TOOL_NAME=$TOOL_NAME"
36
-
37
- # ============================================================================
38
- # VALIDATION
39
- # ============================================================================
40
-
41
- # Only process tasks.md files
42
- case "$FILE_PATH" in
43
- *tasks.md) ;;
44
- *)
45
- log_debug "Not a tasks.md file, skipping"
46
- exit 0
47
- ;;
48
- esac
49
-
50
- # Extract increment directory
51
- INC_DIR=$(dirname "$FILE_PATH")
52
- META_FILE="$INC_DIR/metadata.json"
53
- TASKS_FILE="$FILE_PATH"
54
-
55
- # Check if files exist
56
- if [ ! -f "$META_FILE" ]; then
57
- log_debug "No metadata.json found at $META_FILE, skipping"
58
- exit 0
59
- fi
60
-
61
- if [ ! -f "$TASKS_FILE" ]; then
62
- log_debug "No tasks.md found at $TASKS_FILE, skipping"
63
- exit 0
64
- fi
65
-
66
- # ============================================================================
67
- # READ TEST MODE FROM METADATA
68
- # ============================================================================
69
-
70
- TEST_MODE=""
71
-
72
- if command -v jq >/dev/null 2>&1; then
73
- TEST_MODE=$(jq -r '.testMode // "test-after"' "$META_FILE" 2>/dev/null || echo "test-after")
74
- else
75
- # Fallback: portable grep parsing (no -P flag for macOS compatibility)
76
- TEST_MODE=$(grep '"testMode"' "$META_FILE" 2>/dev/null | sed 's/.*"testMode"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || echo "test-after")
77
- fi
78
-
79
- # Default to test-after if empty
80
- TEST_MODE="${TEST_MODE:-test-after}"
81
-
82
- log_debug "testMode detected: $TEST_MODE"
83
-
84
- # Skip if not TDD mode
85
- if [ "$TEST_MODE" != "TDD" ]; then
86
- log_debug "testMode is not TDD ($TEST_MODE), skipping enforcement"
87
- exit 0
88
- fi
89
-
90
- # ============================================================================
91
- # READ ENFORCEMENT LEVEL FROM CONFIG (v1.0.111+)
92
- # ============================================================================
93
-
94
- TDD_ENFORCEMENT="warn" # Default: warn but allow
95
-
96
- CONFIG_FILE="$PROJECT_ROOT/.specweave/config.json"
97
- if [ -f "$CONFIG_FILE" ]; then
98
- if command -v jq >/dev/null 2>&1; then
99
- TDD_ENFORCEMENT=$(jq -r '.testing.tddEnforcement // "warn"' "$CONFIG_FILE" 2>/dev/null || echo "warn")
100
- else
101
- # Fallback: grep parsing
102
- TDD_ENFORCEMENT=$(grep '"tddEnforcement"' "$CONFIG_FILE" 2>/dev/null | sed 's/.*"tddEnforcement"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' || echo "warn")
103
- fi
104
- fi
105
-
106
- # Validate enforcement level
107
- case "$TDD_ENFORCEMENT" in
108
- strict|warn|off) ;;
109
- *) TDD_ENFORCEMENT="warn" ;;
110
- esac
111
-
112
- log_debug "tddEnforcement level: $TDD_ENFORCEMENT"
113
-
114
- # Skip if enforcement is off
115
- if [ "$TDD_ENFORCEMENT" = "off" ]; then
116
- log_debug "TDD enforcement is off, skipping"
117
- exit 0
118
- fi
119
-
120
- # ============================================================================
121
- # PARSE TASKS FOR TDD VIOLATIONS (macOS-compatible, no associative arrays)
122
- # ============================================================================
123
-
124
- VIOLATION_LOG="$LOGS_DIR/tdd-violations.log"
125
-
126
- # Use temp files for cross-platform compatibility (no associative arrays)
127
- COMPLETED_TASKS_FILE=$(mktemp)
128
- cleanup() {
129
- rm -f "$COMPLETED_TASKS_FILE" 2>/dev/null || true
130
- }
131
- trap cleanup EXIT
132
-
133
- # Parse task sections and find completed TDD tasks
134
- # Format: TASK_ID:PHASE
135
- current_task=""
136
- current_phase=""
137
-
138
- while IFS= read -r line; do
139
- # Task header: ### T-001: [RED] ... or ### T-001: [GREEN] ... or ### T-001: [REFACTOR] ...
140
- case "$line" in
141
- "### T-"*": ["*"]"*)
142
- # Extract task ID (T-XXX)
143
- current_task=$(echo "$line" | sed -n 's/^### \(T-[0-9]*\):.*/\1/p')
144
- # Extract phase
145
- case "$line" in
146
- *"[RED]"*) current_phase="RED" ;;
147
- *"[GREEN]"*) current_phase="GREEN" ;;
148
- *"[REFACTOR]"*) current_phase="REFACTOR" ;;
149
- *) current_phase="" ;;
150
- esac
151
- log_debug "Found task $current_task with phase $current_phase"
152
- ;;
153
- esac
154
-
155
- # Status line: **Status**: [x] completed
156
- case "$line" in
157
- "**Status**: [x]"*)
158
- if [ -n "$current_task" ] && [ -n "$current_phase" ]; then
159
- echo "$current_task:$current_phase" >> "$COMPLETED_TASKS_FILE"
160
- log_debug "Task $current_task ($current_phase) is completed"
161
- fi
162
- current_task=""
163
- current_phase=""
164
- ;;
165
- esac
166
- done < "$TASKS_FILE"
167
-
168
- # ============================================================================
169
- # CHECK FOR VIOLATIONS
170
- # ============================================================================
171
-
172
- VIOLATIONS=""
173
- VIOLATION_COUNT=0
174
-
175
- # Helper to check if a task is completed with a specific phase
176
- is_completed_with_phase() {
177
- local task_id="$1"
178
- local expected_phase="$2"
179
- grep -q "^${task_id}:${expected_phase}$" "$COMPLETED_TASKS_FILE" 2>/dev/null
180
- }
181
-
182
- # Check each completed task
183
- while IFS=: read -r task_id phase; do
184
- [ -z "$task_id" ] && continue
185
-
186
- if [ "$phase" = "GREEN" ]; then
187
- # GREEN task completed - check if corresponding RED is done
188
- # Extract number, subtract 1, format back
189
- task_num=$(echo "$task_id" | sed 's/T-0*//')
190
- red_task_num=$((task_num - 1))
191
- red_task_id=$(printf "T-%03d" "$red_task_num")
192
-
193
- if ! is_completed_with_phase "$red_task_id" "RED"; then
194
- VIOLATIONS="$VIOLATIONS
195
- • $task_id (GREEN) completed but $red_task_id (RED) not found or not completed"
196
- VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
197
- log_debug "VIOLATION: $task_id GREEN completed before $red_task_id RED"
198
- fi
199
- fi
200
-
201
- if [ "$phase" = "REFACTOR" ]; then
202
- # REFACTOR task completed - check if corresponding GREEN is done
203
- task_num=$(echo "$task_id" | sed 's/T-0*//')
204
- green_task_num=$((task_num - 1))
205
- green_task_id=$(printf "T-%03d" "$green_task_num")
206
-
207
- if ! is_completed_with_phase "$green_task_id" "GREEN"; then
208
- VIOLATIONS="$VIOLATIONS
209
- • $task_id (REFACTOR) completed but $green_task_id (GREEN) not found or not completed"
210
- VIOLATION_COUNT=$((VIOLATION_COUNT + 1))
211
- log_debug "VIOLATION: $task_id REFACTOR completed before $green_task_id GREEN"
212
- fi
213
- fi
214
- done < "$COMPLETED_TASKS_FILE"
215
-
216
- # ============================================================================
217
- # OUTPUT WARNINGS
218
- # ============================================================================
219
-
220
- if [ "$VIOLATION_COUNT" -gt 0 ]; then
221
- # Log violations
222
- {
223
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] TDD violations in $(basename "$INC_DIR") (enforcement: $TDD_ENFORCEMENT):"
224
- echo "$VIOLATIONS" | while IFS= read -r v; do
225
- [ -n "$v" ] && echo " -$v"
226
- done
227
- echo ""
228
- } >> "$VIOLATION_LOG" 2>/dev/null || true
229
-
230
- # Handle based on enforcement level
231
- if [ "$TDD_ENFORCEMENT" = "strict" ]; then
232
- echo ""
233
- echo "❌ TDD ENFORCEMENT BLOCKED"
234
- echo " ────────────────────────"
235
- echo " Your increment is configured for TDD mode with STRICT enforcement."
236
- echo ""
237
- echo " Violations detected:$VIOLATIONS"
238
- echo ""
239
- echo " 💡 TDD Discipline: RED → GREEN → REFACTOR"
240
- echo " 1. 🔴 Complete RED (test) task FIRST"
241
- echo " 2. 🟢 Then complete GREEN (implementation) task"
242
- echo " 3. 🔵 Finally complete REFACTOR task"
243
- echo ""
244
- echo " To bypass: Set testing.tddEnforcement: \"warn\" in .specweave/config.json"
245
- echo ""
246
- log_debug "BLOCKING due to TDD violations (strict mode)"
247
- exit 1 # BLOCK in strict mode
248
- else
249
- # warn mode
250
- echo ""
251
- echo "⚠️ TDD DISCIPLINE WARNING"
252
- echo " ────────────────────────"
253
- echo " Your increment is configured for TDD mode (testMode: TDD)"
254
- echo ""
255
- echo " Potential violations detected:$VIOLATIONS"
256
- echo ""
257
- echo " 💡 TDD Best Practice: RED → GREEN → REFACTOR"
258
- echo " 1. 🔴 Write failing test FIRST"
259
- echo " 2. 🟢 Make test pass with minimal code"
260
- echo " 3. 🔵 Refactor while keeping tests green"
261
- echo ""
262
- echo " 💡 To enforce strictly: Set testing.tddEnforcement: \"strict\" in config.json"
263
- echo ""
264
- fi
265
- fi
266
-
267
- # Exit 0 for warn mode (allow), exit 1 for strict mode (handled above)
268
- exit 0
@@ -1,332 +0,0 @@
1
- #!/bin/bash
2
-
3
- # SpecWeave Provider-Agnostic AC Sync Dispatcher (v1.0.255+)
4
- # Background handler: syncs AC progress to ALL enabled providers (GitHub, JIRA, ADO).
5
- #
6
- # Replaces the GitHub-only github-ac-sync-handler.sh with a unified dispatcher
7
- # that calls syncACProgressToProviders() for all configured providers.
8
- #
9
- # Triggered by post-tool-use.sh after task-ac-sync-guard updates spec.md ACs.
10
- # Runs in BACKGROUND via safe_run_background — never blocks the main chain.
11
- #
12
- # Features:
13
- # - 5s debounce (batches rapid AC changes)
14
- # - Per-provider circuit breakers (managed in TypeScript)
15
- # - File locking (prevents concurrent handler executions)
16
- # - Non-blocking (all errors → exit 0 with logging)
17
- #
18
- # Usage: ac-sync-dispatcher.sh <INCREMENT_ID>
19
- # Called by: safe_run_background in post-tool-use.sh
20
-
21
- set +e # Never crash Claude Code
22
-
23
- # EMERGENCY KILL SWITCH
24
- if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
25
- exit 0
26
- fi
27
-
28
- # ============================================================================
29
- # PROJECT ROOT DETECTION
30
- # ============================================================================
31
-
32
- find_project_root() {
33
- local dir="$1"
34
- while [ "$dir" != "/" ]; do
35
- if [ -f "$dir/.specweave/config.json" ]; then
36
- echo "$dir"
37
- return 0
38
- fi
39
- dir="$(dirname "$dir")"
40
- done
41
- return 1
42
- }
43
-
44
- PROJECT_ROOT="$(find_project_root "$(pwd)")"
45
- if [[ -z "$PROJECT_ROOT" ]]; then
46
- exit 0
47
- fi
48
- cd "$PROJECT_ROOT" 2>/dev/null || exit 0
49
-
50
- # ============================================================================
51
- # ARGUMENTS
52
- # ============================================================================
53
-
54
- INC_ID="$1"
55
- if [[ -z "$INC_ID" ]]; then
56
- exit 0
57
- fi
58
-
59
- # Validate INC_ID format (defense-in-depth against injection)
60
- if [[ ! "$INC_ID" =~ ^[0-9]{4}[A-Za-z0-9_-]*$ ]]; then
61
- exit 0
62
- fi
63
-
64
- SPEC_PATH="$PROJECT_ROOT/.specweave/increments/$INC_ID/spec.md"
65
- METADATA_PATH="$PROJECT_ROOT/.specweave/increments/$INC_ID/metadata.json"
66
- CONFIG_PATH="$PROJECT_ROOT/.specweave/config.json"
67
-
68
- if [[ ! -f "$SPEC_PATH" ]]; then
69
- exit 0
70
- fi
71
-
72
- # ============================================================================
73
- # LOGGING
74
- # ============================================================================
75
-
76
- LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
77
- LOG_FILE="$LOGS_DIR/ac-sync-dispatcher.log"
78
- mkdir -p "$LOGS_DIR" 2>/dev/null || true
79
-
80
- log() {
81
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ac-sync] $1" >> "$LOG_FILE" 2>/dev/null || true
82
- }
83
-
84
- # ============================================================================
85
- # CHECK ANY PROVIDER ENABLED
86
- # ============================================================================
87
-
88
- if [[ ! -f "$CONFIG_PATH" ]] || ! command -v jq >/dev/null 2>&1; then
89
- log "Config not found or jq unavailable. Skipping."
90
- exit 0
91
- fi
92
-
93
- # Use shared provider detection (supports PROFILES, LEGACY DIRECT, LEGACY PROVIDER formats)
94
- HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
95
- SHARED_LIB="$HANDLER_DIR/../lib/check-provider-enabled.sh"
96
- if [[ -f "$SHARED_LIB" ]]; then
97
- source "$SHARED_LIB"
98
- fi
99
-
100
- # Source resolve-package.sh for dynamic specweave path resolution
101
- RESOLVE_LIB="$HANDLER_DIR/../../lib/resolve-package.sh"
102
- if [[ -f "$RESOLVE_LIB" ]]; then
103
- source "$RESOLVE_LIB"
104
- fi
105
-
106
- GH_ENABLED="false"
107
- JIRA_ENABLED="false"
108
- ADO_ENABLED="false"
109
-
110
- if type check_provider_enabled &>/dev/null; then
111
- check_provider_enabled "$CONFIG_PATH" "github" && GH_ENABLED="true"
112
- check_provider_enabled "$CONFIG_PATH" "jira" && JIRA_ENABLED="true"
113
- check_provider_enabled "$CONFIG_PATH" "ado" && ADO_ENABLED="true"
114
- else
115
- # Fallback to legacy jq check if shared lib not available
116
- GH_ENABLED=$(jq -r '.sync.github.enabled // false' "$CONFIG_PATH" 2>/dev/null)
117
- JIRA_ENABLED=$(jq -r '.sync.jira.enabled // false' "$CONFIG_PATH" 2>/dev/null)
118
- ADO_ENABLED=$(jq -r '.sync.ado.enabled // false' "$CONFIG_PATH" 2>/dev/null)
119
- fi
120
-
121
- if [[ "$GH_ENABLED" != "true" && "$JIRA_ENABLED" != "true" && "$ADO_ENABLED" != "true" ]]; then
122
- log "No providers enabled. Skipping."
123
- exit 0
124
- fi
125
-
126
- # ============================================================================
127
- # FILE LOCKING
128
- # ============================================================================
129
-
130
- STATE_DIR="$PROJECT_ROOT/.specweave/state"
131
- mkdir -p "$STATE_DIR" 2>/dev/null || true
132
-
133
- LOCK_FILE="$STATE_DIR/.hook-ac-sync-dispatcher.lock"
134
- LOCK_TIMEOUT=15
135
-
136
- LOCK_ACQUIRED=false
137
- for i in {1..10}; do
138
- if mkdir "$LOCK_FILE" 2>/dev/null; then
139
- LOCK_ACQUIRED=true
140
- trap 'rmdir "$LOCK_FILE" 2>/dev/null || true' EXIT
141
- break
142
- fi
143
-
144
- # Check for stale lock
145
- if [[ -d "$LOCK_FILE" ]]; then
146
- LOCK_AGE=$(($(date +%s) - $(stat -f%m "$LOCK_FILE" 2>/dev/null || stat -c%Y "$LOCK_FILE" 2>/dev/null || echo 0)))
147
- if (( LOCK_AGE > LOCK_TIMEOUT )); then
148
- rmdir "$LOCK_FILE" 2>/dev/null || true
149
- continue
150
- fi
151
- fi
152
-
153
- sleep 0.3
154
- done
155
-
156
- if [[ "$LOCK_ACQUIRED" == "false" ]]; then
157
- log "Lock not acquired. Another instance running. Skipping."
158
- exit 0
159
- fi
160
-
161
- # ============================================================================
162
- # DEBOUNCE (5s window)
163
- # ============================================================================
164
-
165
- SIGNAL_FILE="$STATE_DIR/.ac-sync-pending-$INC_ID"
166
-
167
- if [[ -f "$SIGNAL_FILE" ]]; then
168
- SIGNAL_AGE=$(($(date +%s) - $(stat -f%m "$SIGNAL_FILE" 2>/dev/null || stat -c%Y "$SIGNAL_FILE" 2>/dev/null || echo 0)))
169
- if (( SIGNAL_AGE < 5 )); then
170
- log "Debounce: signal file age ${SIGNAL_AGE}s < 5s. Deferring."
171
- exit 0
172
- fi
173
- fi
174
-
175
- # Create/update signal file and wait for debounce window
176
- echo "$(date +%s)" > "$SIGNAL_FILE" 2>/dev/null || true
177
- sleep 5
178
-
179
- # After sleeping, check if a NEWER invocation took over
180
- if [[ -f "$SIGNAL_FILE" ]]; then
181
- CURRENT_SIGNAL=$(cat "$SIGNAL_FILE" 2>/dev/null || echo 0)
182
- NOW=$(date +%s)
183
- SIGNAL_AGE=$((NOW - CURRENT_SIGNAL))
184
- if (( SIGNAL_AGE > 6 )); then
185
- log "Debounce: newer invocation detected. Exiting."
186
- exit 0
187
- fi
188
- fi
189
-
190
- rm -f "$SIGNAL_FILE" 2>/dev/null || true
191
-
192
- # ============================================================================
193
- # PRECONDITIONS
194
- # ============================================================================
195
-
196
- if ! command -v node &>/dev/null; then
197
- log "Node.js not found. Skipping."
198
- exit 0
199
- fi
200
-
201
- # ============================================================================
202
- # EXTRACT AFFECTED USER STORY IDS
203
- # ============================================================================
204
-
205
- # Get all US IDs that have external links from metadata.json
206
- # Reads BOTH new format (externalLinks.github.issues) and old format (github.issues[].userStory)
207
- AFFECTED_US_IDS="[]"
208
- if [[ -f "$METADATA_PATH" ]]; then
209
- AFFECTED_US_IDS=$(jq -r '
210
- [
211
- (.externalLinks.github.issues // {} | keys[]),
212
- (.externalLinks.jira.userStories // {} | keys[]),
213
- (.externalLinks.ado.userStories // {} | keys[]),
214
- (.github.issues // [] | .[].userStory // empty)
215
- ] | flatten | unique
216
- ' "$METADATA_PATH" 2>/dev/null) || AFFECTED_US_IDS="[]"
217
- fi
218
-
219
- if [[ "$AFFECTED_US_IDS" == "[]" || -z "$AFFECTED_US_IDS" ]]; then
220
- log "No affected US IDs found. Skipping."
221
- exit 0
222
- fi
223
-
224
- # Validate AFFECTED_US_IDS is valid JSON (defense-in-depth against injection)
225
- if ! echo "$AFFECTED_US_IDS" | jq empty 2>/dev/null; then
226
- log "Invalid US IDs JSON. Skipping."
227
- exit 0
228
- fi
229
-
230
- # ============================================================================
231
- # BUILD CONFIG FROM SPECWEAVE CONFIG + METADATA
232
- # ============================================================================
233
-
234
- # Find the sync module (compiled output) — check multiple locations
235
- # Same fallback pattern as universal-auto-create-dispatcher.sh
236
- SYNC_MODULE=""
237
- # Derive package root from script location (handlers/ → v2/ → hooks/ → specweave/ → plugins/ → package root)
238
- PKG_ROOT="$(cd "$HANDLER_DIR/../../../../.." 2>/dev/null && pwd)"
239
- # 0. SPECWEAVE_PKG (set by Claude Code hook infrastructure, most reliable)
240
- if [[ -n "${SPECWEAVE_PKG:-}" ]]; then
241
- CANDIDATE="${SPECWEAVE_PKG}/dist/src/core/ac-progress-sync.js"
242
- [[ -f "$CANDIDATE" ]] && SYNC_MODULE="$CANDIDATE"
243
- fi
244
- # 1. Package root (derived from script location — works for both npm and dev)
245
- if [[ -z "$SYNC_MODULE" ]]; then
246
- CANDIDATE="${PKG_ROOT:-$PROJECT_ROOT}/dist/src/core/ac-progress-sync.js"
247
- [[ -f "$CANDIDATE" ]] && SYNC_MODULE="$CANDIDATE"
248
- fi
249
- # 2. resolve-package.sh (dynamic resolution)
250
- if [[ -z "$SYNC_MODULE" ]]; then
251
- CANDIDATE=$(find_specweave_script "dist/src/core/ac-progress-sync.js" 2>/dev/null)
252
- [[ -n "$CANDIDATE" ]] && SYNC_MODULE="$CANDIDATE"
253
- fi
254
- # 3. Legacy: PROJECT_ROOT/dist/ (dev-only, running from source repo)
255
- if [[ -z "$SYNC_MODULE" ]]; then
256
- CANDIDATE="$PROJECT_ROOT/dist/src/core/ac-progress-sync.js"
257
- [[ -f "$CANDIDATE" ]] && SYNC_MODULE="$CANDIDATE"
258
- fi
259
-
260
- if [[ -z "$SYNC_MODULE" ]]; then
261
- log "Sync module not found at any known path. Checked: SPECWEAVE_PKG=${SPECWEAVE_PKG:-unset}, PKG_ROOT=${PKG_ROOT:-unset}, node_modules, PROJECT_ROOT/dist. Skipping."
262
- exit 0
263
- fi
264
- log "Using sync module: $SYNC_MODULE"
265
-
266
- log "Syncing AC progress for increment $INC_ID to enabled providers..."
267
- log "Providers: github=$GH_ENABLED jira=$JIRA_ENABLED ado=$ADO_ENABLED"
268
- log "Affected US IDs: $AFFECTED_US_IDS"
269
-
270
- # ============================================================================
271
- # RUN PROVIDER-AGNOSTIC SYNC
272
- # ============================================================================
273
-
274
- # Build inline Node.js script that constructs config and calls sync
275
- # Pass all values via environment variables to prevent command injection
276
- OUTPUT=$(SW_SYNC_MODULE="$SYNC_MODULE" \
277
- SW_CONFIG_PATH="$CONFIG_PATH" \
278
- SW_METADATA_PATH="$METADATA_PATH" \
279
- SW_SPEC_PATH="$SPEC_PATH" \
280
- SW_INC_ID="$INC_ID" \
281
- SW_AFFECTED_US_IDS="$AFFECTED_US_IDS" \
282
- SW_CLOSE_ALL="${SPECWEAVE_CLOSE_ALL:-0}" \
283
- node --input-type=module -e "
284
- import { readFile } from 'fs/promises';
285
-
286
- const { SW_SYNC_MODULE, SW_CONFIG_PATH, SW_METADATA_PATH,
287
- SW_SPEC_PATH, SW_INC_ID, SW_AFFECTED_US_IDS, SW_CLOSE_ALL } = process.env;
288
-
289
- const mod = await import(SW_SYNC_MODULE);
290
- const affectedUSIds = JSON.parse(SW_AFFECTED_US_IDS);
291
-
292
- try {
293
- const rawConfig = JSON.parse(await readFile(SW_CONFIG_PATH, 'utf-8'));
294
- const metadata = JSON.parse(await readFile(SW_METADATA_PATH, 'utf-8'));
295
-
296
- const config = {
297
- sync: {
298
- github: { enabled: rawConfig?.sync?.github?.enabled === true },
299
- jira: { enabled: rawConfig?.sync?.jira?.enabled === true },
300
- ado: { enabled: rawConfig?.sync?.ado?.enabled === true },
301
- },
302
- github: rawConfig?.sync?.github || {},
303
- jira: rawConfig?.sync?.jira || {},
304
- ado: rawConfig?.sync?.ado || {},
305
- externalLinks: metadata?.externalLinks || {},
306
- };
307
-
308
- let result;
309
- if (SW_CLOSE_ALL === '1' && mod.closeIncrementIssues) {
310
- // Force-close all external issues for completed increment
311
- result = await mod.closeIncrementIssues(SW_INC_ID, SW_SPEC_PATH, config);
312
- } else {
313
- result = await mod.syncACProgressToProviders(
314
- SW_INC_ID, affectedUSIds, SW_SPEC_PATH, config,
315
- );
316
- }
317
-
318
- console.log(JSON.stringify(result, null, 2));
319
- } catch (err) {
320
- console.error('AC sync dispatcher error:', err.message || err);
321
- process.exit(1);
322
- }
323
- " 2>&1)
324
- EXIT_CODE=$?
325
-
326
- if [[ $EXIT_CODE -ne 0 ]]; then
327
- log "Sync failed (exit $EXIT_CODE): $OUTPUT"
328
- exit 0
329
- fi
330
-
331
- log "Sync completed: $OUTPUT"
332
- exit 0
@@ -1,50 +0,0 @@
1
- #!/bin/bash
2
- # ac-validation-handler.sh - Validate AC completion status
3
- # Checks that completed tasks have their ACs checked in spec.md
4
- # Non-blocking, logs warnings only
5
- #
6
- # IMPORTANT: Never crash Claude, always exit 0
7
- set +e
8
-
9
- [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
10
-
11
- INC_ID="${1:-}"
12
- [[ -z "$INC_ID" ]] && exit 0
13
-
14
- # Find project root
15
- PROJECT_ROOT="$PWD"
16
- while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
17
- PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
18
- done
19
- [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
20
-
21
- INC_DIR="$PROJECT_ROOT/.specweave/increments/$INC_ID"
22
- TASKS_FILE="$INC_DIR/tasks.md"
23
- SPEC_FILE="$INC_DIR/spec.md"
24
- LOG_FILE="$PROJECT_ROOT/.specweave/logs/ac-validation.log"
25
-
26
- [[ ! -f "$TASKS_FILE" ]] || [[ ! -f "$SPEC_FILE" ]] && exit 0
27
-
28
- mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null
29
-
30
- # Find completed tasks and their ACs
31
- WARNINGS=""
32
- while IFS= read -r line; do
33
- if [[ "$line" =~ ^\*\*Satisfies\ ACs\*\*:\ (.+)$ ]]; then
34
- ACS="${BASH_REMATCH[1]}"
35
- # Check each AC
36
- for ac in $(echo "$ACS" | tr ',' ' '); do
37
- ac=$(echo "$ac" | tr -d ' ')
38
- [[ -z "$ac" ]] && continue
39
- # Check if AC is checked in spec.md
40
- if ! grep -qE "^\s*-\s*\[x\]\s*\*\*${ac}\*\*" "$SPEC_FILE" 2>/dev/null; then
41
- WARNINGS="$WARNINGS\n - $ac not checked in spec.md"
42
- fi
43
- done
44
- fi
45
- done < <(grep -A5 "\[x\] completed" "$TASKS_FILE" 2>/dev/null | grep "Satisfies ACs")
46
-
47
- if [[ -n "$WARNINGS" ]]; then
48
- echo "[$(date)] $INC_ID: AC validation warnings:$WARNINGS" >> "$LOG_FILE"
49
- fi
50
- exit 0