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,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