specweave 0.23.12 â 0.23.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/core/progress/error-logger.d.ts +58 -0
- package/dist/src/core/progress/error-logger.d.ts.map +1 -0
- package/dist/src/core/progress/error-logger.js +99 -0
- package/dist/src/core/progress/error-logger.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/hooks/docs-changed.sh +9 -1
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/human-input-required.sh +9 -1
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh +6 -1
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh +6 -1
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh +6 -1
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh +6 -1
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-metadata-change.sh +7 -1
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh +9 -1
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +9 -1
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh +9 -1
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh +9 -2
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh +9 -1
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-github/hooks/post-task-completion.sh +9 -1
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-jira/hooks/post-task-completion.sh +9 -1
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +24 -0
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# ============================================================================
|
|
4
|
+
# Post Living Docs Update Hook - Azure DevOps Sync
|
|
5
|
+
# ============================================================================
|
|
6
|
+
#
|
|
7
|
+
# Triggered after living docs are updated to sync with Azure DevOps.
|
|
8
|
+
# CRITICAL: External tool status ALWAYS wins in conflicts!
|
|
9
|
+
#
|
|
10
|
+
# Triggers:
|
|
11
|
+
# 1. After /specweave:done (increment completion)
|
|
12
|
+
# 2. After /specweave:sync-docs update
|
|
13
|
+
# 3. After manual spec edits
|
|
14
|
+
# 4. After webhook from ADO
|
|
15
|
+
#
|
|
16
|
+
# ============================================================================
|
|
17
|
+
|
|
18
|
+
set -e
|
|
19
|
+
|
|
20
|
+
# Configuration
|
|
21
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
22
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
23
|
+
LIVING_DOCS_DIR="$PROJECT_ROOT/.specweave/docs/internal/specs"
|
|
24
|
+
LOG_FILE="$PROJECT_ROOT/.specweave/logs/ado-sync.log"
|
|
25
|
+
DEBUG=${DEBUG:-0}
|
|
26
|
+
|
|
27
|
+
# Ensure log directory exists
|
|
28
|
+
mkdir -p "$(dirname "$LOG_FILE")"
|
|
29
|
+
|
|
30
|
+
# ============================================================================
|
|
31
|
+
# Logging
|
|
32
|
+
# ============================================================================
|
|
33
|
+
|
|
34
|
+
log() {
|
|
35
|
+
local level=$1
|
|
36
|
+
shift
|
|
37
|
+
local message="$@"
|
|
38
|
+
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
39
|
+
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
|
|
40
|
+
[ "$DEBUG" -eq 1 ] && echo "[$level] $message" >&2
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
log_info() {
|
|
44
|
+
log "INFO" "$@"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
log_error() {
|
|
48
|
+
log "ERROR" "$@"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
log_debug() {
|
|
52
|
+
[ "$DEBUG" -eq 1 ] && log "DEBUG" "$@"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# ============================================================================
|
|
56
|
+
# External Tool Detection
|
|
57
|
+
# ============================================================================
|
|
58
|
+
|
|
59
|
+
detect_external_tool() {
|
|
60
|
+
local spec_path=$1
|
|
61
|
+
|
|
62
|
+
# Check for external links in spec metadata
|
|
63
|
+
if grep -q "externalLinks:" "$spec_path"; then
|
|
64
|
+
if grep -q "ado:" "$spec_path"; then
|
|
65
|
+
echo "ado"
|
|
66
|
+
elif grep -q "jira:" "$spec_path"; then
|
|
67
|
+
echo "jira"
|
|
68
|
+
elif grep -q "github:" "$spec_path"; then
|
|
69
|
+
echo "github"
|
|
70
|
+
fi
|
|
71
|
+
fi
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
# ============================================================================
|
|
75
|
+
# Status Mapping
|
|
76
|
+
# ============================================================================
|
|
77
|
+
|
|
78
|
+
map_ado_status_to_local() {
|
|
79
|
+
local ado_status=$1
|
|
80
|
+
|
|
81
|
+
case "$ado_status" in
|
|
82
|
+
"New")
|
|
83
|
+
echo "draft"
|
|
84
|
+
;;
|
|
85
|
+
"Active")
|
|
86
|
+
echo "in-progress"
|
|
87
|
+
;;
|
|
88
|
+
"Resolved")
|
|
89
|
+
echo "implemented"
|
|
90
|
+
;;
|
|
91
|
+
"Closed")
|
|
92
|
+
echo "complete"
|
|
93
|
+
;;
|
|
94
|
+
"In Review"|"In QA")
|
|
95
|
+
echo "in-qa"
|
|
96
|
+
;;
|
|
97
|
+
*)
|
|
98
|
+
echo "unknown"
|
|
99
|
+
;;
|
|
100
|
+
esac
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
map_local_status_to_ado() {
|
|
104
|
+
local local_status=$1
|
|
105
|
+
|
|
106
|
+
case "$local_status" in
|
|
107
|
+
"draft")
|
|
108
|
+
echo "New"
|
|
109
|
+
;;
|
|
110
|
+
"in-progress")
|
|
111
|
+
echo "Active"
|
|
112
|
+
;;
|
|
113
|
+
"implemented")
|
|
114
|
+
echo "Resolved"
|
|
115
|
+
;;
|
|
116
|
+
"complete")
|
|
117
|
+
echo "Closed"
|
|
118
|
+
;;
|
|
119
|
+
"in-qa")
|
|
120
|
+
echo "In Review"
|
|
121
|
+
;;
|
|
122
|
+
*)
|
|
123
|
+
echo "Active"
|
|
124
|
+
;;
|
|
125
|
+
esac
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
# ============================================================================
|
|
129
|
+
# ADO API Functions
|
|
130
|
+
# ============================================================================
|
|
131
|
+
|
|
132
|
+
get_ado_work_item_status() {
|
|
133
|
+
local work_item_id=$1
|
|
134
|
+
local org="${AZURE_DEVOPS_ORG}"
|
|
135
|
+
local project="${AZURE_DEVOPS_PROJECT}"
|
|
136
|
+
local pat="${AZURE_DEVOPS_PAT}"
|
|
137
|
+
|
|
138
|
+
if [ -z "$org" ] || [ -z "$pat" ]; then
|
|
139
|
+
log_error "ADO credentials not configured"
|
|
140
|
+
return 1
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
local api_url="https://dev.azure.com/${org}/${project}/_apis/wit/workitems/${work_item_id}?api-version=7.0"
|
|
144
|
+
|
|
145
|
+
log_debug "Fetching ADO work item $work_item_id status"
|
|
146
|
+
|
|
147
|
+
local response=$(curl -s -u ":${pat}" \
|
|
148
|
+
-H "Content-Type: application/json" \
|
|
149
|
+
"$api_url")
|
|
150
|
+
|
|
151
|
+
if [ $? -ne 0 ]; then
|
|
152
|
+
log_error "Failed to fetch ADO work item status"
|
|
153
|
+
return 1
|
|
154
|
+
fi
|
|
155
|
+
|
|
156
|
+
# Extract status from response
|
|
157
|
+
local status=$(echo "$response" | jq -r '.fields["System.State"]')
|
|
158
|
+
|
|
159
|
+
if [ "$status" = "null" ] || [ -z "$status" ]; then
|
|
160
|
+
log_error "Could not extract status from ADO response"
|
|
161
|
+
return 1
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
echo "$status"
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
update_ado_work_item() {
|
|
168
|
+
local work_item_id=$1
|
|
169
|
+
local spec_content=$2
|
|
170
|
+
local org="${AZURE_DEVOPS_ORG}"
|
|
171
|
+
local project="${AZURE_DEVOPS_PROJECT}"
|
|
172
|
+
local pat="${AZURE_DEVOPS_PAT}"
|
|
173
|
+
|
|
174
|
+
if [ -z "$org" ] || [ -z "$pat" ]; then
|
|
175
|
+
log_error "ADO credentials not configured"
|
|
176
|
+
return 1
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
# Extract current status from spec
|
|
180
|
+
local local_status=$(echo "$spec_content" | grep "^status:" | cut -d: -f2 | tr -d ' ')
|
|
181
|
+
local ado_status=$(map_local_status_to_ado "$local_status")
|
|
182
|
+
|
|
183
|
+
local api_url="https://dev.azure.com/${org}/${project}/_apis/wit/workitems/${work_item_id}?api-version=7.0"
|
|
184
|
+
|
|
185
|
+
# Create update payload
|
|
186
|
+
local payload=$(cat <<EOF
|
|
187
|
+
[
|
|
188
|
+
{
|
|
189
|
+
"op": "add",
|
|
190
|
+
"path": "/fields/System.State",
|
|
191
|
+
"value": "$ado_status"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"op": "add",
|
|
195
|
+
"path": "/fields/System.History",
|
|
196
|
+
"value": "Updated from SpecWeave living docs"
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
EOF
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
log_debug "Updating ADO work item $work_item_id with status: $ado_status"
|
|
203
|
+
|
|
204
|
+
curl -s -X PATCH \
|
|
205
|
+
-u ":${pat}" \
|
|
206
|
+
-H "Content-Type: application/json-patch+json" \
|
|
207
|
+
-d "$payload" \
|
|
208
|
+
"$api_url" > /dev/null
|
|
209
|
+
|
|
210
|
+
if [ $? -ne 0 ]; then
|
|
211
|
+
log_error "Failed to update ADO work item"
|
|
212
|
+
return 1
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
log_info "Updated ADO work item $work_item_id"
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
# ============================================================================
|
|
219
|
+
# Conflict Resolution - CRITICAL: External Wins!
|
|
220
|
+
# ============================================================================
|
|
221
|
+
|
|
222
|
+
resolve_status_conflict() {
|
|
223
|
+
local spec_path=$1
|
|
224
|
+
local local_status=$2
|
|
225
|
+
local external_status=$3
|
|
226
|
+
|
|
227
|
+
local mapped_external=$(map_ado_status_to_local "$external_status")
|
|
228
|
+
|
|
229
|
+
if [ "$local_status" != "$mapped_external" ]; then
|
|
230
|
+
log_info "Status conflict detected:"
|
|
231
|
+
log_info " Local: $local_status"
|
|
232
|
+
log_info " External: $external_status (mapped: $mapped_external)"
|
|
233
|
+
log_info " Resolution: EXTERNAL WINS - applying $mapped_external"
|
|
234
|
+
|
|
235
|
+
# Update local spec with external status
|
|
236
|
+
sed -i.bak "s/^status: .*/status: $mapped_external/" "$spec_path"
|
|
237
|
+
|
|
238
|
+
# Add sync metadata
|
|
239
|
+
local timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
|
|
240
|
+
|
|
241
|
+
# Check if syncedAt exists, update or add
|
|
242
|
+
if grep -q "syncedAt:" "$spec_path"; then
|
|
243
|
+
sed -i.bak "s/syncedAt: .*/syncedAt: \"$timestamp\"/" "$spec_path"
|
|
244
|
+
else
|
|
245
|
+
# Add after externalLinks section
|
|
246
|
+
sed -i.bak "/externalLinks:/a\\
|
|
247
|
+
syncedAt: \"$timestamp\"" "$spec_path"
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
# Clean up backup files
|
|
251
|
+
rm -f "${spec_path}.bak"
|
|
252
|
+
|
|
253
|
+
log_info "Local spec updated with external status: $mapped_external"
|
|
254
|
+
return 0
|
|
255
|
+
else
|
|
256
|
+
log_debug "No status conflict - local and external match: $local_status"
|
|
257
|
+
return 0
|
|
258
|
+
fi
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
# ============================================================================
|
|
262
|
+
# Main Sync Function
|
|
263
|
+
# ============================================================================
|
|
264
|
+
|
|
265
|
+
sync_spec_with_ado() {
|
|
266
|
+
local spec_path=$1
|
|
267
|
+
|
|
268
|
+
if [ ! -f "$spec_path" ]; then
|
|
269
|
+
log_error "Spec file not found: $spec_path"
|
|
270
|
+
return 1
|
|
271
|
+
fi
|
|
272
|
+
|
|
273
|
+
local spec_name=$(basename "$spec_path")
|
|
274
|
+
log_info "Syncing spec: $spec_name"
|
|
275
|
+
|
|
276
|
+
# Read spec content
|
|
277
|
+
local spec_content=$(cat "$spec_path")
|
|
278
|
+
|
|
279
|
+
# Extract ADO work item ID from metadata
|
|
280
|
+
local work_item_id=$(echo "$spec_content" | grep -A5 "externalLinks:" | grep -A3 "ado:" | grep "featureId:" | cut -d: -f2 | tr -d ' ')
|
|
281
|
+
|
|
282
|
+
if [ -z "$work_item_id" ]; then
|
|
283
|
+
log_debug "No ADO work item linked to spec, skipping sync"
|
|
284
|
+
return 0
|
|
285
|
+
fi
|
|
286
|
+
|
|
287
|
+
log_info "Found ADO work item ID: $work_item_id"
|
|
288
|
+
|
|
289
|
+
# Step 1: Push updates to ADO (content changes)
|
|
290
|
+
update_ado_work_item "$work_item_id" "$spec_content"
|
|
291
|
+
|
|
292
|
+
# Step 2: CRITICAL - Pull status from ADO (external wins!)
|
|
293
|
+
local external_status=$(get_ado_work_item_status "$work_item_id")
|
|
294
|
+
|
|
295
|
+
if [ -z "$external_status" ]; then
|
|
296
|
+
log_error "Could not fetch ADO status"
|
|
297
|
+
return 1
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
log_info "ADO status: $external_status"
|
|
301
|
+
|
|
302
|
+
# Step 3: Extract local status
|
|
303
|
+
local local_status=$(echo "$spec_content" | grep "^status:" | cut -d: -f2 | tr -d ' ')
|
|
304
|
+
|
|
305
|
+
log_info "Local status: $local_status"
|
|
306
|
+
|
|
307
|
+
# Step 4: Resolve conflicts - EXTERNAL WINS
|
|
308
|
+
resolve_status_conflict "$spec_path" "$local_status" "$external_status"
|
|
309
|
+
|
|
310
|
+
log_info "Sync completed for $spec_name"
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
# ============================================================================
|
|
314
|
+
# Entry Point
|
|
315
|
+
# ============================================================================
|
|
316
|
+
|
|
317
|
+
main() {
|
|
318
|
+
log_info "=== Post Living Docs Update Hook Started ==="
|
|
319
|
+
|
|
320
|
+
# Get the spec path from arguments or environment
|
|
321
|
+
local spec_path="${1:-$SPECWEAVE_UPDATED_SPEC}"
|
|
322
|
+
|
|
323
|
+
if [ -z "$spec_path" ]; then
|
|
324
|
+
log_error "No spec path provided"
|
|
325
|
+
exit 1
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
# Detect external tool
|
|
329
|
+
local tool=$(detect_external_tool "$spec_path")
|
|
330
|
+
|
|
331
|
+
if [ "$tool" != "ado" ]; then
|
|
332
|
+
log_debug "Not an ADO-linked spec, skipping"
|
|
333
|
+
exit 0
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
log_info "Detected ADO integration for spec"
|
|
337
|
+
|
|
338
|
+
# Perform sync
|
|
339
|
+
sync_spec_with_ado "$spec_path"
|
|
340
|
+
|
|
341
|
+
local exit_code=$?
|
|
342
|
+
|
|
343
|
+
if [ $exit_code -eq 0 ]; then
|
|
344
|
+
log_info "=== Sync completed successfully ==="
|
|
345
|
+
else
|
|
346
|
+
log_error "=== Sync failed with exit code: $exit_code ==="
|
|
347
|
+
fi
|
|
348
|
+
|
|
349
|
+
exit $exit_code
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
# Run main function
|
|
353
|
+
main "$@"
|
|
@@ -13,7 +13,12 @@
|
|
|
13
13
|
# - metadata.json must have .ado.item field
|
|
14
14
|
# - Azure DevOps PAT in .env
|
|
15
15
|
|
|
16
|
-
set
|
|
16
|
+
set +e # EMERGENCY FIX: Prevents Claude Code crashes
|
|
17
|
+
|
|
18
|
+
# EMERGENCY KILL SWITCH
|
|
19
|
+
if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
17
22
|
|
|
18
23
|
# ============================================================================
|
|
19
24
|
# PROJECT ROOT DETECTION
|
|
@@ -170,3 +175,6 @@ cat <<EOF
|
|
|
170
175
|
"continue": true
|
|
171
176
|
}
|
|
172
177
|
EOF
|
|
178
|
+
|
|
179
|
+
# ALWAYS exit 0 - NEVER let hook errors crash Claude Code
|
|
180
|
+
exit 0
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Azure DevOps Sync Hook
|
|
4
|
+
# Runs after task completion to sync progress to Azure DevOps Work Items
|
|
5
|
+
#
|
|
6
|
+
# This hook is part of the specweave-ado plugin and handles:
|
|
7
|
+
# - Syncing task completion state to Azure DevOps work items
|
|
8
|
+
# - Updating ADO work item status based on increment progress
|
|
9
|
+
#
|
|
10
|
+
# Dependencies:
|
|
11
|
+
# - Node.js for running sync scripts
|
|
12
|
+
# - jq for JSON parsing
|
|
13
|
+
# - metadata.json must have .ado.item field
|
|
14
|
+
# - Azure DevOps PAT in .env
|
|
15
|
+
|
|
16
|
+
set -e
|
|
17
|
+
|
|
18
|
+
# ============================================================================
|
|
19
|
+
# PROJECT ROOT DETECTION
|
|
20
|
+
# ============================================================================
|
|
21
|
+
|
|
22
|
+
# Find project root by searching upward for .specweave/ directory
|
|
23
|
+
find_project_root() {
|
|
24
|
+
local dir="$1"
|
|
25
|
+
while [ "$dir" != "/" ]; do
|
|
26
|
+
if [ -d "$dir/.specweave" ]; then
|
|
27
|
+
echo "$dir"
|
|
28
|
+
return 0
|
|
29
|
+
fi
|
|
30
|
+
dir="$(dirname "$dir")"
|
|
31
|
+
done
|
|
32
|
+
# Fallback: try current directory
|
|
33
|
+
if [ -d "$(pwd)/.specweave" ]; then
|
|
34
|
+
pwd
|
|
35
|
+
else
|
|
36
|
+
echo "$(pwd)"
|
|
37
|
+
fi
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
41
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
42
|
+
|
|
43
|
+
# ============================================================================
|
|
44
|
+
# CONFIGURATION
|
|
45
|
+
# ============================================================================
|
|
46
|
+
|
|
47
|
+
LOGS_DIR=".specweave/logs"
|
|
48
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
49
|
+
|
|
50
|
+
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
51
|
+
|
|
52
|
+
# ============================================================================
|
|
53
|
+
# PRECONDITIONS CHECK
|
|
54
|
+
# ============================================================================
|
|
55
|
+
|
|
56
|
+
echo "[$(date)] [ADO] đ Azure DevOps sync hook fired" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
57
|
+
|
|
58
|
+
# Detect current increment
|
|
59
|
+
CURRENT_INCREMENT=$(ls -td .specweave/increments/*/ 2>/dev/null | xargs -n1 basename | grep -v "_backlog" | grep -v "_archive" | grep -v "_working" | head -1)
|
|
60
|
+
|
|
61
|
+
if [ -z "$CURRENT_INCREMENT" ]; then
|
|
62
|
+
echo "[$(date)] [ADO] âšī¸ No active increment, skipping ADO sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
63
|
+
cat <<EOF
|
|
64
|
+
{
|
|
65
|
+
"continue": true
|
|
66
|
+
}
|
|
67
|
+
EOF
|
|
68
|
+
exit 0
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Check for metadata.json
|
|
72
|
+
METADATA_FILE=".specweave/increments/$CURRENT_INCREMENT/metadata.json"
|
|
73
|
+
|
|
74
|
+
if [ ! -f "$METADATA_FILE" ]; then
|
|
75
|
+
echo "[$(date)] [ADO] âšī¸ No metadata.json for $CURRENT_INCREMENT, skipping ADO sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
76
|
+
cat <<EOF
|
|
77
|
+
{
|
|
78
|
+
"continue": true
|
|
79
|
+
}
|
|
80
|
+
EOF
|
|
81
|
+
exit 0
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# Check for ADO work item link
|
|
85
|
+
if ! command -v jq &> /dev/null; then
|
|
86
|
+
echo "[$(date)] [ADO] â ī¸ jq not found, skipping ADO sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
87
|
+
cat <<EOF
|
|
88
|
+
{
|
|
89
|
+
"continue": true
|
|
90
|
+
}
|
|
91
|
+
EOF
|
|
92
|
+
exit 0
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
ADO_ITEM=$(jq -r '.ado.item // empty' "$METADATA_FILE" 2>/dev/null)
|
|
96
|
+
|
|
97
|
+
if [ -z "$ADO_ITEM" ]; then
|
|
98
|
+
echo "[$(date)] [ADO] âšī¸ No Azure DevOps work item linked to $CURRENT_INCREMENT, skipping sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
99
|
+
cat <<EOF
|
|
100
|
+
{
|
|
101
|
+
"continue": true
|
|
102
|
+
}
|
|
103
|
+
EOF
|
|
104
|
+
exit 0
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Check for Node.js
|
|
108
|
+
if ! command -v node &> /dev/null; then
|
|
109
|
+
echo "[$(date)] [ADO] â ī¸ Node.js not found, skipping ADO sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
110
|
+
cat <<EOF
|
|
111
|
+
{
|
|
112
|
+
"continue": true
|
|
113
|
+
}
|
|
114
|
+
EOF
|
|
115
|
+
exit 0
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
# Check for ADO sync script
|
|
119
|
+
if [ ! -f "dist/commands/ado-sync.js" ]; then
|
|
120
|
+
echo "[$(date)] [ADO] â ī¸ ado-sync.js not found, skipping ADO sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
121
|
+
cat <<EOF
|
|
122
|
+
{
|
|
123
|
+
"continue": true
|
|
124
|
+
}
|
|
125
|
+
EOF
|
|
126
|
+
exit 0
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
# ============================================================================
|
|
130
|
+
# AZURE DEVOPS SYNC LOGIC
|
|
131
|
+
# ============================================================================
|
|
132
|
+
|
|
133
|
+
echo "[$(date)] [ADO] đ Syncing to Azure DevOps work item $ADO_ITEM" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
134
|
+
|
|
135
|
+
# Run ADO sync command (non-blocking)
|
|
136
|
+
node dist/commands/ado-sync.js "$CURRENT_INCREMENT" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
|
|
137
|
+
echo "[$(date)] [ADO] â ī¸ Failed to sync to Azure DevOps (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
echo "[$(date)] [ADO] â
Azure DevOps sync complete" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
141
|
+
|
|
142
|
+
# ============================================================================
|
|
143
|
+
# SPEC COMMIT SYNC (NEW!)
|
|
144
|
+
# ============================================================================
|
|
145
|
+
|
|
146
|
+
echo "[$(date)] [ADO] đ Checking for spec commit sync..." >> "$DEBUG_LOG" 2>/dev/null || true
|
|
147
|
+
|
|
148
|
+
# Call TypeScript CLI to sync commits
|
|
149
|
+
if command -v node &> /dev/null && [ -f "$PROJECT_ROOT/dist/cli/commands/sync-spec-commits.js" ]; then
|
|
150
|
+
echo "[$(date)] [ADO] đ Running spec commit sync..." >> "$DEBUG_LOG" 2>/dev/null || true
|
|
151
|
+
|
|
152
|
+
node "$PROJECT_ROOT/dist/cli/commands/sync-spec-commits.js" \
|
|
153
|
+
--increment "$PROJECT_ROOT/.specweave/increments/$CURRENT_INCREMENT" \
|
|
154
|
+
--provider ado \
|
|
155
|
+
2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
|
|
156
|
+
echo "[$(date)] [ADO] â ī¸ Spec commit sync failed (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
echo "[$(date)] [ADO] â
Spec commit sync complete" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
160
|
+
else
|
|
161
|
+
echo "[$(date)] [ADO] âšī¸ Spec commit sync not available (node or script not found)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
162
|
+
fi
|
|
163
|
+
|
|
164
|
+
# ============================================================================
|
|
165
|
+
# OUTPUT TO CLAUDE
|
|
166
|
+
# ============================================================================
|
|
167
|
+
|
|
168
|
+
cat <<EOF
|
|
169
|
+
{
|
|
170
|
+
"continue": true
|
|
171
|
+
}
|
|
172
|
+
EOF
|
|
@@ -19,7 +19,12 @@
|
|
|
19
19
|
# - GitHub CLI (gh) must be installed and authenticated
|
|
20
20
|
# - ProgressCommentBuilder (lib/progress-comment-builder.ts)
|
|
21
21
|
|
|
22
|
-
set
|
|
22
|
+
set +e # EMERGENCY FIX: Prevents Claude Code crashes
|
|
23
|
+
|
|
24
|
+
# EMERGENCY KILL SWITCH
|
|
25
|
+
if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
23
28
|
|
|
24
29
|
# ============================================================================
|
|
25
30
|
# PROJECT ROOT DETECTION
|
|
@@ -256,3 +261,6 @@ cat <<EOF
|
|
|
256
261
|
"continue": true
|
|
257
262
|
}
|
|
258
263
|
EOF
|
|
264
|
+
|
|
265
|
+
# ALWAYS exit 0 - NEVER let hook errors crash Claude Code
|
|
266
|
+
exit 0
|