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,283 +0,0 @@
1
- #!/bin/bash
2
- # stop-sync.sh - Batched external tool sync at session end
3
- #
4
- # NEW ARCHITECTURE (v1.0.148):
5
- # - NO background processor - sync happens at session end
6
- # - Batches all pending events, deduplicates, syncs once per increment
7
- # - Calls project-bridge-handler for universal sync (GitHub/JIRA/ADO)
8
- #
9
- # This runs AFTER stop-reflect.sh and stop-auto.sh in the Stop hook chain.
10
- #
11
- # Design:
12
- # 1. Read pending events from .specweave/state/event-queue/pending.jsonl
13
- # 2. Deduplicate by increment ID (process each increment ONCE)
14
- # 3. Call project-bridge-handler for each unique increment
15
- # 4. Clean up processed events
16
- #
17
- # IMPORTANT: Always returns approve, never blocks session exit
18
-
19
- set +e # Never fail
20
-
21
- # Read input from stdin (required by Claude Code)
22
- INPUT=$(cat)
23
-
24
- # Project root detection (walk up to find .specweave/ — prevents pollution of subdirectories)
25
- if [[ -n "${PROJECT_ROOT:-}" ]] && [[ -f "$PROJECT_ROOT/.specweave/config.json" ]]; then
26
- : # env var already set and valid
27
- else
28
- PROJECT_ROOT="$PWD"
29
- while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
30
- PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
31
- done
32
- fi
33
-
34
- # Silent approve helper
35
- silent_approve() {
36
- echo '{"decision":"approve"}'
37
- exit 0
38
- }
39
-
40
- # Not a SpecWeave project — approve and exit (MUST be before any mkdir)
41
- [ ! -f "$PROJECT_ROOT/.specweave/config.json" ] && silent_approve
42
-
43
- STATE_DIR="$PROJECT_ROOT/.specweave/state"
44
- QUEUE_DIR="$STATE_DIR/event-queue"
45
- PENDING_FILE="$QUEUE_DIR/pending.jsonl"
46
- LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
47
- LOG_FILE="$LOGS_DIR/stop-sync.log"
48
- HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/v2/handlers" 2>/dev/null && pwd)"
49
-
50
- # Create logs directory
51
- mkdir -p "$LOGS_DIR" 2>/dev/null || true
52
-
53
- log() {
54
- echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $1" >> "$LOG_FILE" 2>/dev/null
55
- }
56
-
57
- log "Stop-sync started"
58
-
59
- # Check if there are pending events
60
- if [ ! -f "$PENDING_FILE" ] || [ ! -s "$PENDING_FILE" ]; then
61
- # Also check old-style .event files for migration
62
- OLD_EVENTS=$(find "$QUEUE_DIR" -name "*.event" 2>/dev/null | head -1)
63
- if [ -z "$OLD_EVENTS" ]; then
64
- log "No pending events to sync"
65
- silent_approve
66
- fi
67
- fi
68
-
69
- # Check if project-bridge-handler exists
70
- BRIDGE_HANDLER="$HANDLER_DIR/project-bridge-handler.sh"
71
- if [ ! -f "$BRIDGE_HANDLER" ]; then
72
- log "WARN: project-bridge-handler.sh not found at $BRIDGE_HANDLER"
73
- silent_approve
74
- fi
75
-
76
- # Cross-platform timeout wrapper
77
- # FIXED (v1.0.302): Don't suppress stderr from inner commands
78
- run_with_timeout() {
79
- local timeout_secs="$1"
80
- shift
81
- if command -v timeout >/dev/null 2>&1; then
82
- timeout "$timeout_secs" "$@" || true
83
- elif command -v gtimeout >/dev/null 2>&1; then
84
- gtimeout "$timeout_secs" "$@" || true
85
- else
86
- "$@" || true
87
- fi
88
- }
89
-
90
- # ============================================================================
91
- # COLLECT UNIQUE INCREMENTS TO SYNC
92
- # Deduplication: each increment synced only ONCE regardless of event count
93
- # ============================================================================
94
-
95
- INCREMENTS_TO_SYNC=""
96
- PROCESSED_FILE="$QUEUE_DIR/.processed-$$"
97
- EVENT_TYPES_FILE="$QUEUE_DIR/.event-types-$$"
98
- > "$EVENT_TYPES_FILE" 2>/dev/null || true
99
-
100
- # Process new-style pending.jsonl
101
- if [ -f "$PENDING_FILE" ] && [ -s "$PENDING_FILE" ]; then
102
- log "Processing pending.jsonl..."
103
-
104
- # Extract unique increment IDs and track event types
105
- while IFS= read -r line; do
106
- [ -z "$line" ] && continue
107
-
108
- # Extract increment ID from event data
109
- # Format: {"type":"task.updated","data":"0001-feature-name","ts":"..."}
110
- INC_ID=$(echo "$line" | grep -o '"data":"[^"]*"' | cut -d'"' -f4 | grep -o '^[0-9][0-9][0-9][0-9]-[^:]*' | head -1)
111
- EVENT_TYPE=$(echo "$line" | grep -o '"type":"[^"]*"' | cut -d'"' -f4)
112
-
113
- if [ -n "$INC_ID" ]; then
114
- # Add to list if not already present
115
- if ! echo "$INCREMENTS_TO_SYNC" | grep -q "$INC_ID"; then
116
- INCREMENTS_TO_SYNC="$INCREMENTS_TO_SYNC $INC_ID"
117
- log "Queued for sync: $INC_ID"
118
- fi
119
- # Track event type for this increment
120
- if [ -n "$EVENT_TYPE" ]; then
121
- echo "${INC_ID}|${EVENT_TYPE}" >> "$EVENT_TYPES_FILE" 2>/dev/null
122
- fi
123
- fi
124
- done < "$PENDING_FILE"
125
- fi
126
-
127
- # Process old-style .event files (migration path)
128
- # Use nullglob to handle empty glob (no matching files)
129
- shopt -s nullglob
130
- for event_file in "$QUEUE_DIR"/*.event; do
131
- [ ! -f "$event_file" ] && continue
132
-
133
- # Extract increment ID from event
134
- INC_ID=$(cat "$event_file" 2>/dev/null | grep -o '"data":"[^"]*"' | cut -d'"' -f4 | grep -o '^[0-9][0-9][0-9][0-9]-[^:]*' | head -1)
135
-
136
- if [ -n "$INC_ID" ]; then
137
- if ! echo "$INCREMENTS_TO_SYNC" | grep -q "$INC_ID"; then
138
- INCREMENTS_TO_SYNC="$INCREMENTS_TO_SYNC $INC_ID"
139
- log "Queued for sync (legacy): $INC_ID"
140
- fi
141
- fi
142
-
143
- # Mark for cleanup
144
- echo "$event_file" >> "$PROCESSED_FILE"
145
- done
146
- shopt -u nullglob # Restore default glob behavior
147
-
148
- # ============================================================================
149
- # SYNC EACH INCREMENT (batched, deduplicated)
150
- # ============================================================================
151
-
152
- SYNC_COUNT=0
153
- SYNC_FAILED=0
154
-
155
- # Determine best event type for an increment from queued events
156
- # Priority: done > created > user-story.completed > reopened > user-story.reopened > sync (catch-all)
157
- get_best_event_type() {
158
- local inc_id="$1"
159
- if [ -f "$EVENT_TYPES_FILE" ]; then
160
- if grep -q "^${inc_id}|increment\.done$" "$EVENT_TYPES_FILE" 2>/dev/null; then
161
- echo "increment.done"
162
- elif grep -q "^${inc_id}|increment\.created$" "$EVENT_TYPES_FILE" 2>/dev/null; then
163
- echo "increment.created"
164
- elif grep -q "^${inc_id}|user-story\.completed$" "$EVENT_TYPES_FILE" 2>/dev/null; then
165
- echo "user-story.completed"
166
- elif grep -q "^${inc_id}|increment\.reopened$" "$EVENT_TYPES_FILE" 2>/dev/null; then
167
- echo "increment.reopened"
168
- elif grep -q "^${inc_id}|user-story\.reopened$" "$EVENT_TYPES_FILE" 2>/dev/null; then
169
- echo "user-story.reopened"
170
- else
171
- echo "increment.sync"
172
- fi
173
- else
174
- echo "increment.sync"
175
- fi
176
- }
177
-
178
- # Resolve github-sync-handler path (for user-story event routing)
179
- GITHUB_SYNC_HANDLER="$HANDLER_DIR/github-sync-handler.sh"
180
-
181
- # Resolve living-specs-handler path (for lifecycle event routing)
182
- # BUGFIX: living-specs-handler was never called after v1.0.148 migration from processor.js
183
- # This handler updates .specweave/docs/internal/specs/ on lifecycle changes
184
- LIVING_SPECS_HANDLER="$HANDLER_DIR/living-specs-handler.sh"
185
-
186
- for INC_ID in $INCREMENTS_TO_SYNC; do
187
- [ -z "$INC_ID" ] && continue
188
-
189
- # Preserve original event type from pending.jsonl (best priority wins)
190
- EVENT_TYPE=$(get_best_event_type "$INC_ID")
191
- log "Syncing increment: $INC_ID (event: $EVENT_TYPE)"
192
-
193
- if run_with_timeout 30 bash "$BRIDGE_HANDLER" "$EVENT_TYPE" "$INC_ID"; then
194
- SYNC_COUNT=$((SYNC_COUNT + 1))
195
- log "Sync succeeded: $INC_ID"
196
- else
197
- SYNC_FAILED=$((SYNC_FAILED + 1))
198
- log "Sync failed: $INC_ID"
199
- fi
200
-
201
- # Route lifecycle events to living-specs-handler
202
- # Updates living docs (specs/) on increment create/done/archive/reopen
203
- if [ -f "$LIVING_SPECS_HANDLER" ]; then
204
- case "$EVENT_TYPE" in
205
- increment.created|increment.done|increment.archived|increment.reopened)
206
- log "Routing lifecycle event to living-specs-handler: $EVENT_TYPE $INC_ID"
207
- run_with_timeout 30 bash "$LIVING_SPECS_HANDLER" "$EVENT_TYPE" "$INC_ID"
208
- ;;
209
- esac
210
- fi
211
-
212
- # Route user-story events to github-sync-handler (v1.0.262+)
213
- # github-sync-handler understands user-story.completed/reopened with INC_ID:US_ID data
214
- # FIXED (v1.0.302): Filter by BOTH event type AND increment ID to prevent
215
- # routing all events to the first matching increment's US event.
216
- if [ -f "$GITHUB_SYNC_HANDLER" ] && [ -f "$EVENT_TYPES_FILE" ]; then
217
- while IFS='|' read -r _inc_id us_event_type; do
218
- [ -z "$us_event_type" ] && continue
219
- # Extract US data (INC_ID:US_ID) from pending.jsonl for THIS increment
220
- # Must match both the event type AND the increment ID in the data field
221
- US_DATA=$(grep "\"type\":\"${us_event_type}\"" "$PENDING_FILE" 2>/dev/null \
222
- | grep "\"data\":\"${INC_ID}:" \
223
- | grep -o '"data":"[^"]*"' | cut -d'"' -f4 | head -1)
224
- if [ -n "$US_DATA" ]; then
225
- log "Routing user-story event to github-sync-handler: $us_event_type $US_DATA"
226
- run_with_timeout 30 bash "$GITHUB_SYNC_HANDLER" "$us_event_type" "$US_DATA"
227
- fi
228
- done < <(grep "^${INC_ID}|user-story\." "$EVENT_TYPES_FILE" 2>/dev/null | sort -u)
229
- fi
230
- done
231
-
232
- # ============================================================================
233
- # CLEANUP PROCESSED EVENTS
234
- # ============================================================================
235
-
236
- # Clear pending.jsonl (all events processed)
237
- if [ -f "$PENDING_FILE" ]; then
238
- > "$PENDING_FILE" # Truncate file
239
- log "Cleared pending.jsonl"
240
- fi
241
-
242
- # Remove old-style .event files
243
- if [ -f "$PROCESSED_FILE" ]; then
244
- while IFS= read -r event_file; do
245
- rm -f "$event_file" 2>/dev/null
246
- done < "$PROCESSED_FILE"
247
- rm -f "$PROCESSED_FILE"
248
- log "Cleaned up legacy .event files"
249
- fi
250
-
251
- # Clean up event-types temp file
252
- rm -f "$EVENT_TYPES_FILE" 2>/dev/null
253
-
254
- # ============================================================================
255
- # REPORT RESULTS
256
- # ============================================================================
257
-
258
- if [ "$SYNC_COUNT" -gt 0 ] || [ "$SYNC_FAILED" -gt 0 ]; then
259
- log "Sync complete: $SYNC_COUNT succeeded, $SYNC_FAILED failed"
260
-
261
- if [ "$SYNC_FAILED" -gt 0 ]; then
262
- # Show warning but don't block
263
- SYNC_MSG="
264
- ┌─────────────────────────────────────────────────────────────────────────────┐
265
- │ 🔄 EXTERNAL SYNC: $SYNC_COUNT synced, $SYNC_FAILED failed │
266
- ├─────────────────────────────────────────────────────────────────────────────┤
267
- │ Some increments failed to sync to external tools. │
268
- │ Check logs: .specweave/logs/stop-sync.log │
269
- │ │
270
- │ 💡 Run /sw-github:sync or /sw-jira:sync manually to retry │
271
- └─────────────────────────────────────────────────────────────────────────────┘"
272
-
273
- jq -n \
274
- --arg decision "approve" \
275
- --arg reason "External sync completed with $SYNC_FAILED failures" \
276
- --arg systemMessage "$SYNC_MSG" \
277
- '{decision: $decision, reason: $reason, systemMessage: $systemMessage}'
278
- exit 0
279
- fi
280
- fi
281
-
282
- # Silent success
283
- silent_approve
@@ -1,126 +0,0 @@
1
- #!/bin/bash
2
- # Integration test: scored selection + enriched feedback (T-012, AC-US1-01, AC-US2-01, AC-US3-01)
3
- # Creates a mock .specweave/ project, scores increments, and verifies enrichment helpers.
4
-
5
- set -e
6
-
7
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
- SCORE_SCRIPT="$SCRIPT_DIR/../lib/score-increment.sh"
9
- STOP_HOOK="$SCRIPT_DIR/../stop-auto-v5.sh"
10
- TMPDIR_ROOT=$(mktemp -d)
11
- trap 'rm -rf "$TMPDIR_ROOT"' EXIT
12
-
13
- PASS=0; FAIL=0
14
-
15
- assert_eq() {
16
- if [ "$1" = "$2" ]; then
17
- echo " ✓ $3"; PASS=$((PASS+1))
18
- else
19
- echo " ✗ $3 (expected '$2', got '$1')"; FAIL=$((FAIL+1))
20
- fi
21
- }
22
-
23
- assert_gt() {
24
- if [ "$1" -gt "$2" ]; then
25
- echo " ✓ $3 ($1 > $2)"; PASS=$((PASS+1))
26
- else
27
- echo " ✗ $3 (expected $1 > $2)"; FAIL=$((FAIL+1))
28
- fi
29
- }
30
-
31
- assert_contains() {
32
- if echo "$1" | grep -q "$2"; then
33
- echo " ✓ $3"; PASS=$((PASS+1))
34
- else
35
- echo " ✗ $3 (expected '$1' to contain '$2')"; FAIL=$((FAIL+1))
36
- fi
37
- }
38
-
39
- echo "Integration: scored selection + enriched feedback"
40
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
41
-
42
- # Setup mock .specweave/ structure
43
- SW="$TMPDIR_ROOT/.specweave"
44
- INC_DIR="$SW/increments"
45
- STATE_DIR="$SW/state"
46
- LOGS_DIR="$SW/logs"
47
- mkdir -p "$INC_DIR/0100-user-auth" "$INC_DIR/0101-deploy-pipeline" "$STATE_DIR" "$LOGS_DIR"
48
-
49
- # Create increment 0100: auth
50
- echo '{"title":"User Authentication Feature","status":"active","lastActivity":"2026-02-18T10:00:00Z"}' \
51
- > "$INC_DIR/0100-user-auth/metadata.json"
52
- cat > "$INC_DIR/0100-user-auth/spec.md" << 'EOF'
53
- # User Authentication Feature
54
-
55
- Implement login, signup, and OAuth for user authentication.
56
- EOF
57
- cat > "$INC_DIR/0100-user-auth/tasks.md" << 'EOF'
58
- ### T-001: Add login endpoint
59
- **Status**: [x] completed
60
- ### T-002: Add signup endpoint
61
- **Status**: [x] completed
62
- ### T-003: OAuth integration
63
- **Status**: [ ] pending
64
- ### T-004: Session management
65
- **Status**: [ ] pending
66
- EOF
67
-
68
- # Create increment 0101: deploy
69
- echo '{"title":"CI/CD Deploy Pipeline","status":"active","lastActivity":"2026-02-17T10:00:00Z"}' \
70
- > "$INC_DIR/0101-deploy-pipeline/metadata.json"
71
- cat > "$INC_DIR/0101-deploy-pipeline/spec.md" << 'EOF'
72
- # CI/CD Deploy Pipeline
73
-
74
- Setup continuous integration and deployment pipeline with Docker and GitHub Actions.
75
- EOF
76
- cat > "$INC_DIR/0101-deploy-pipeline/tasks.md" << 'EOF'
77
- ### T-001: Create Dockerfile
78
- **Status**: [x] completed
79
- ### T-002: Configure GitHub Actions
80
- **Status**: [ ] pending
81
- ### T-003: Set up staging environment
82
- **Status**: [ ] pending
83
- EOF
84
-
85
- # TC-015: Scored selection — auth scores higher for "fix authentication"
86
- s_auth=$(bash "$SCORE_SCRIPT" "$INC_DIR/0100-user-auth" "fix authentication" 2>/dev/null)
87
- s_deploy=$(bash "$SCORE_SCRIPT" "$INC_DIR/0101-deploy-pipeline" "fix authentication" 2>/dev/null)
88
- assert_gt "$s_auth" "$s_deploy" "TC-015a: auth scores higher than deploy for auth prompt"
89
-
90
- # TC-015b: Deploy scores higher for "deploy pipeline docker"
91
- s_auth2=$(bash "$SCORE_SCRIPT" "$INC_DIR/0100-user-auth" "deploy pipeline docker" 2>/dev/null)
92
- s_deploy2=$(bash "$SCORE_SCRIPT" "$INC_DIR/0101-deploy-pipeline" "deploy pipeline docker" 2>/dev/null)
93
- assert_gt "$s_deploy2" "$s_auth2" "TC-015b: deploy scores higher for deploy prompt"
94
-
95
- # TC-015c: userGoal wiring — verify logic matches setup-auto.sh
96
- AUTO_MODE_FILE="$STATE_DIR/auto-mode.json"
97
- PROMPT="fix authentication"
98
- if [ -f "$AUTO_MODE_FILE" ]; then
99
- if [ -n "$PROMPT" ]; then
100
- _UPDATED=$(jq --arg g "$PROMPT" '.userGoal = $g' "$AUTO_MODE_FILE" 2>/dev/null)
101
- else
102
- _UPDATED=$(jq '.userGoal = null' "$AUTO_MODE_FILE" 2>/dev/null)
103
- fi
104
- [ -n "$_UPDATED" ] && echo "$_UPDATED" > "$AUTO_MODE_FILE"
105
- elif [ -n "$PROMPT" ]; then
106
- jq -n --arg g "$PROMPT" '{"active":false,"userGoal":$g}' > "$AUTO_MODE_FILE"
107
- fi
108
- goal=$(jq -r '.userGoal' "$AUTO_MODE_FILE")
109
- assert_eq "$goal" "fix authentication" "TC-015c: userGoal written to auto-mode.json"
110
-
111
- # TC-015d: Stop hook enrichment — source hook, test helpers
112
- export PROJECT_ROOT="$TMPDIR_ROOT"
113
- export __STOP_AUTO_V5_SOURCED=1
114
- source "$STOP_HOOK" 2>/dev/null
115
-
116
- next_auth=$(get_next_task_title "$INC_DIR/0100-user-auth/tasks.md")
117
- assert_eq "$next_auth" "OAuth integration" "TC-015d: enriched next task from auth increment"
118
-
119
- done_auth=$(count_completed_tasks "$INC_DIR/0100-user-auth/tasks.md")
120
- pending_auth=$(count_pending_tasks "$INC_DIR/0100-user-auth/tasks.md")
121
- assert_eq "$done_auth" "2" "TC-015e: auth increment done count = 2"
122
- assert_eq "$pending_auth" "2" "TC-015f: auth increment pending count = 2"
123
-
124
- echo ""
125
- echo "Results: $PASS passed, $FAIL failed"
126
- [ "$FAIL" -eq 0 ] || exit 1
@@ -1,128 +0,0 @@
1
- #!/bin/bash
2
- # Tests for enriched stop hook feedback (AC-US3-01, AC-US3-02, AC-US3-03, AC-US4-01, AC-US4-03)
3
- # Sources stop-auto-v5.sh to load helper functions only.
4
-
5
- set -e
6
-
7
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
- STOP_HOOK="$SCRIPT_DIR/../stop-auto-v5.sh"
9
- TMPDIR_ROOT=$(mktemp -d)
10
- trap 'rm -rf "$TMPDIR_ROOT"' EXIT
11
-
12
- PASS=0; FAIL=0
13
-
14
- assert_eq() {
15
- if [ "$1" = "$2" ]; then
16
- echo " ✓ $3"; PASS=$((PASS+1))
17
- else
18
- echo " ✗ $3 (expected '$2', got '$1')"; FAIL=$((FAIL+1))
19
- fi
20
- }
21
-
22
- assert_ge() {
23
- if [ "$1" -ge "$2" ]; then
24
- echo " ✓ $3 ($1 >= $2)"; PASS=$((PASS+1))
25
- else
26
- echo " ✗ $3 (expected >= $2, got $1)"; FAIL=$((FAIL+1))
27
- fi
28
- }
29
-
30
- # Set up minimal .specweave structure so sourcing succeeds
31
- export PROJECT_ROOT="$TMPDIR_ROOT"
32
- mkdir -p "$TMPDIR_ROOT/.specweave/logs" "$TMPDIR_ROOT/.specweave/state" "$TMPDIR_ROOT/.specweave/increments"
33
-
34
- # Source only (loads helper functions, skips main execution)
35
- export __STOP_AUTO_V5_SOURCED=1
36
- source "$STOP_HOOK" 2>/dev/null
37
-
38
- echo "stop-auto-v5.sh enrichment function tests"
39
- echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
40
-
41
- # Create a tasks.md with known counts
42
- TASKS_FILE="$TMPDIR_ROOT/tasks.md"
43
- cat > "$TASKS_FILE" << 'EOF'
44
- ### T-001: Setup database
45
- **User Story**: US-001 | **Status**: [x] completed
46
-
47
- ### T-002: Implement login
48
- **User Story**: US-001 | **Status**: [x] completed
49
-
50
- ### T-003: Add unit tests
51
- **User Story**: US-001 | **Status**: [x] completed
52
-
53
- ### T-004: Write integration tests
54
- **User Story**: US-001 | **Status**: [x] completed
55
-
56
- ### T-005: Deploy to staging
57
- **User Story**: US-001 | **Status**: [x] completed
58
-
59
- ### T-006: Configure auth middleware
60
- **User Story**: US-001 | **Status**: [ ] pending
61
-
62
- ### T-007: Add error handling
63
- **User Story**: US-001 | **Status**: [ ] pending
64
-
65
- ### T-008: Final review and cleanup
66
- **User Story**: US-001 | **Status**: [ ] pending
67
- EOF
68
-
69
- # TC-010: Block message includes next task title (AC-US3-01)
70
- result=$(get_next_task_title "$TASKS_FILE")
71
- assert_eq "$result" "Configure auth middleware" "TC-010: get_next_task_title returns first pending task"
72
-
73
- # TC-011: count_completed_tasks counts [x] entries
74
- done_count=$(count_completed_tasks "$TASKS_FILE")
75
- assert_eq "$done_count" "5" "TC-011: count_completed_tasks = 5"
76
-
77
- # TC-012: count_pending_tasks counts [ ] entries (AC-US3-03)
78
- pending_count=$(count_pending_tasks "$TASKS_FILE")
79
- assert_eq "$pending_count" "3" "TC-012: count_pending_tasks = 3"
80
-
81
- # TC-012b: Progress fraction calculation
82
- total=$((done_count + pending_count))
83
- assert_eq "$total" "8" "TC-012b: total = done + pending = 8"
84
-
85
- # TC-013: Empty tasks file → zeros
86
- EMPTY_FILE="$TMPDIR_ROOT/empty.md"
87
- touch "$EMPTY_FILE"
88
- done_empty=$(count_completed_tasks "$EMPTY_FILE")
89
- pending_empty=$(count_pending_tasks "$EMPTY_FILE")
90
- assert_eq "$done_empty" "0" "TC-013: empty file → 0 completed"
91
- assert_eq "$pending_empty" "0" "TC-013b: empty file → 0 pending"
92
-
93
- # TC-013c: get_next_task_title on empty file → empty string
94
- next_empty=$(get_next_task_title "$EMPTY_FILE")
95
- assert_eq "$next_empty" "" "TC-013c: empty file → no next title"
96
-
97
- # TC-014: Missing file → zeros
98
- done_missing=$(count_completed_tasks "/nonexistent/tasks.md")
99
- assert_eq "$done_missing" "0" "TC-014: missing file → 0 completed"
100
-
101
- # TC-015: get_next_task_title with all completed → empty
102
- ALL_DONE_FILE="$TMPDIR_ROOT/all-done.md"
103
- cat > "$ALL_DONE_FILE" << 'EOF'
104
- ### T-001: Done task one
105
- **Status**: [x] completed
106
-
107
- ### T-002: Done task two
108
- **Status**: [x] completed
109
- EOF
110
- next_done=$(get_next_task_title "$ALL_DONE_FILE")
111
- assert_eq "$next_done" "" "TC-015: all done → no next title"
112
-
113
- # TC-016: get_next_task_title with task without title pattern
114
- MIXED_FILE="$TMPDIR_ROOT/mixed.md"
115
- cat > "$MIXED_FILE" << 'EOF'
116
- ### T-001: First Task Title
117
- **Status**: [x] completed
118
- ### T-002: Second Task Title
119
- **Status**: [ ] pending
120
- ### T-003: Third Task Title
121
- **Status**: [ ] pending
122
- EOF
123
- next_mixed=$(get_next_task_title "$MIXED_FILE")
124
- assert_eq "$next_mixed" "Second Task Title" "TC-016: returns first pending task title"
125
-
126
- echo ""
127
- echo "Results: $PASS passed, $FAIL failed"
128
- [ "$FAIL" -eq 0 ] || exit 1