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.
- package/CLAUDE.md +1 -1
- package/bin/specweave.js +23 -1
- package/dist/src/cli/commands/hook.d.ts +15 -0
- package/dist/src/cli/commands/hook.d.ts.map +1 -0
- package/dist/src/cli/commands/hook.js +61 -0
- package/dist/src/cli/commands/hook.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +5 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.js +11 -1
- package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
- package/dist/src/cli/commands/sync-setup.d.ts.map +1 -1
- package/dist/src/cli/commands/sync-setup.js +7 -3
- package/dist/src/cli/commands/sync-setup.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts +9 -0
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js +9 -3
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js.map +1 -1
- package/dist/src/config/types.d.ts +2 -2
- package/dist/src/core/config/types.d.ts +18 -2
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/hooks/handlers/hook-router.d.ts +19 -0
- package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/hook-router.js +75 -0
- package/dist/src/core/hooks/handlers/hook-router.js.map +1 -0
- package/dist/src/core/hooks/handlers/index.d.ts +10 -0
- package/dist/src/core/hooks/handlers/index.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/index.js +9 -0
- package/dist/src/core/hooks/handlers/index.js.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +11 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +73 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts +11 -0
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use.js +76 -0
- package/dist/src/core/hooks/handlers/post-tool-use.js.map +1 -0
- package/dist/src/core/hooks/handlers/pre-compact.d.ts +11 -0
- package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/pre-compact.js +77 -0
- package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.d.ts +11 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.js +318 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -0
- package/dist/src/core/hooks/handlers/session-start.d.ts +9 -0
- package/dist/src/core/hooks/handlers/session-start.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/session-start.js +111 -0
- package/dist/src/core/hooks/handlers/session-start.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-auto.d.ts +16 -0
- package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-auto.js +122 -0
- package/dist/src/core/hooks/handlers/stop-auto.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts +14 -0
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-reflect.js +43 -0
- package/dist/src/core/hooks/handlers/stop-reflect.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-sync.d.ts +15 -0
- package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-sync.js +68 -0
- package/dist/src/core/hooks/handlers/stop-sync.js.map +1 -0
- package/dist/src/core/hooks/handlers/types.d.ts +63 -0
- package/dist/src/core/hooks/handlers/types.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/types.js +27 -0
- package/dist/src/core/hooks/handlers/types.js.map +1 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts +14 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.js +173 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -0
- package/dist/src/core/hooks/handlers/utils.d.ts +25 -0
- package/dist/src/core/hooks/handlers/utils.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/utils.js +64 -0
- package/dist/src/core/hooks/handlers/utils.js.map +1 -0
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
- package/dist/src/core/increment/completion-validator.js +32 -0
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/init/research/types.d.ts +1 -1
- package/dist/src/sync/sync-target-resolver.js.map +1 -1
- package/dist/src/utils/lock-manager.d.ts.map +1 -1
- package/dist/src/utils/lock-manager.js +5 -0
- package/dist/src/utils/lock-manager.js.map +1 -1
- package/dist/src/utils/plugin-copier.d.ts +10 -0
- package/dist/src/utils/plugin-copier.d.ts.map +1 -1
- package/dist/src/utils/plugin-copier.js +63 -35
- package/dist/src/utils/plugin-copier.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/agents/sw-closer.md +3 -2
- package/plugins/specweave/hooks/hooks.json +10 -10
- package/plugins/specweave/skills/code-reviewer/SKILL.md +180 -16
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-comments.md +83 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-silent-failures.md +19 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-spec-compliance.md +19 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-tests.md +101 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-types.md +20 -0
- package/plugins/specweave/skills/done/SKILL.md +56 -21
- package/plugins/specweave/skills/grill/SKILL.md +1 -1
- package/plugins/specweave/skills/team-lead/agents/reviewer-logic.md +19 -0
- package/plugins/specweave/skills/team-lead/agents/reviewer-performance.md +20 -0
- package/plugins/specweave/skills/team-lead/agents/reviewer-security.md +20 -0
- package/src/templates/CLAUDE.md.template +7 -4
- package/plugins/specweave/hooks/README.md +0 -493
- package/plugins/specweave/hooks/_archive/stop-auto-v4-legacy.sh +0 -1319
- package/plugins/specweave/hooks/lib/common-setup.sh +0 -144
- package/plugins/specweave/hooks/lib/hook-errors.sh +0 -414
- package/plugins/specweave/hooks/lib/migrate-increment-work.sh +0 -245
- package/plugins/specweave/hooks/lib/resolve-package.sh +0 -146
- package/plugins/specweave/hooks/lib/scheduler-startup.sh +0 -135
- package/plugins/specweave/hooks/lib/score-increment.sh +0 -87
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +0 -193
- package/plugins/specweave/hooks/lib/update-active-increment.sh +0 -95
- package/plugins/specweave/hooks/lib/update-status-line.sh +0 -233
- package/plugins/specweave/hooks/lib/validate-spec-status.sh +0 -171
- package/plugins/specweave/hooks/llm-judge-validator.sh +0 -219
- package/plugins/specweave/hooks/log-decision.sh +0 -168
- package/plugins/specweave/hooks/pre-compact.sh +0 -64
- package/plugins/specweave/hooks/startup-health-check.sh +0 -64
- package/plugins/specweave/hooks/stop-auto-v5.sh +0 -276
- package/plugins/specweave/hooks/stop-reflect.sh +0 -336
- package/plugins/specweave/hooks/stop-sync.sh +0 -283
- package/plugins/specweave/hooks/tests/test-auto-context-integration.sh +0 -126
- package/plugins/specweave/hooks/tests/test-stop-auto-enriched.sh +0 -128
- package/plugins/specweave/hooks/universal/dispatcher.mjs +0 -336
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +0 -325
- package/plugins/specweave/hooks/universal/hook-wrapper.cmd +0 -26
- package/plugins/specweave/hooks/universal/hook-wrapper.sh +0 -69
- package/plugins/specweave/hooks/universal/run-hook.sh +0 -20
- package/plugins/specweave/hooks/universal/session-start.cmd +0 -16
- package/plugins/specweave/hooks/universal/session-start.ps1 +0 -16
- package/plugins/specweave/hooks/user-prompt-submit.sh +0 -2550
- package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +0 -87
- package/plugins/specweave/hooks/v2/detectors/us-completion-detector.sh +0 -186
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +0 -83
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +0 -447
- package/plugins/specweave/hooks/v2/dispatchers/pre-tool-use.sh +0 -104
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +0 -270
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +0 -240
- package/plugins/specweave/hooks/v2/guards/interview-enforcement-guard.sh +0 -171
- package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/skill-chain-enforcement-guard.sh +0 -222
- package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +0 -21
- package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/status-completion-guard.sh +0 -84
- package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +0 -475
- package/plugins/specweave/hooks/v2/guards/tdd-enforcement-guard.sh +0 -268
- package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +0 -332
- package/plugins/specweave/hooks/v2/handlers/ac-validation-handler.sh +0 -50
- package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +0 -347
- package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +0 -83
- package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +0 -268
- package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +0 -104
- package/plugins/specweave/hooks/v2/handlers/status-line-handler.sh +0 -165
- package/plugins/specweave/hooks/v2/handlers/status-update.sh +0 -61
- package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +0 -270
- package/plugins/specweave/hooks/v2/integrations/ado-post-living-docs-update.sh +0 -367
- package/plugins/specweave/hooks/v2/integrations/ado-post-task.sh +0 -179
- package/plugins/specweave/hooks/v2/integrations/github-auto-create-handler.sh +0 -553
- package/plugins/specweave/hooks/v2/integrations/github-post-task.sh +0 -345
- package/plugins/specweave/hooks/v2/integrations/jira-post-task.sh +0 -180
- package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +0 -52
- package/plugins/specweave/hooks/v2/queue/enqueue.sh +0 -81
- package/plugins/specweave/hooks/v2/session-end.sh +0 -139
- package/plugins/specweave/hooks/validate-skill-activations.sh +0 -227
|
@@ -1,270 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Universal Auto-Create Dispatcher (v1.0.256+)
|
|
3
|
-
#
|
|
4
|
-
# Creates per-user-story items in ALL enabled providers when spec.md is written.
|
|
5
|
-
# - GitHub: delegates to existing github-auto-create-handler.sh (backward compatible)
|
|
6
|
-
# - JIRA/ADO: calls src/core/universal-auto-create.ts via Node.js
|
|
7
|
-
#
|
|
8
|
-
# Usage: universal-auto-create-dispatcher.sh <INCREMENT_ID>
|
|
9
|
-
# Called by: safe_run_background in post-tool-use.sh
|
|
10
|
-
|
|
11
|
-
set +e # Never crash Claude Code
|
|
12
|
-
|
|
13
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
14
|
-
|
|
15
|
-
# ============================================================================
|
|
16
|
-
# PROJECT ROOT
|
|
17
|
-
# ============================================================================
|
|
18
|
-
|
|
19
|
-
find_project_root() {
|
|
20
|
-
local dir="$1"
|
|
21
|
-
while [ "$dir" != "/" ]; do
|
|
22
|
-
[ -f "$dir/.specweave/config.json" ] && echo "$dir" && return 0
|
|
23
|
-
dir="$(dirname "$dir")"
|
|
24
|
-
done
|
|
25
|
-
return 1
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
PROJECT_ROOT="$(find_project_root "$(pwd)")"
|
|
29
|
-
[[ -z "$PROJECT_ROOT" ]] && exit 0
|
|
30
|
-
cd "$PROJECT_ROOT" 2>/dev/null || exit 0
|
|
31
|
-
|
|
32
|
-
# ============================================================================
|
|
33
|
-
# ARGUMENTS
|
|
34
|
-
# ============================================================================
|
|
35
|
-
|
|
36
|
-
INC_ID="$1"
|
|
37
|
-
[[ -z "$INC_ID" ]] && exit 0
|
|
38
|
-
[[ ! "$INC_ID" =~ ^[0-9]{4}[A-Za-z0-9_-]*$ ]] && exit 0
|
|
39
|
-
|
|
40
|
-
SPEC_PATH="$PROJECT_ROOT/.specweave/increments/$INC_ID/spec.md"
|
|
41
|
-
METADATA_PATH="$PROJECT_ROOT/.specweave/increments/$INC_ID/metadata.json"
|
|
42
|
-
CONFIG_PATH="$PROJECT_ROOT/.specweave/config.json"
|
|
43
|
-
|
|
44
|
-
[[ ! -f "$SPEC_PATH" ]] && exit 0
|
|
45
|
-
[[ ! -f "$CONFIG_PATH" ]] && exit 0
|
|
46
|
-
|
|
47
|
-
# ============================================================================
|
|
48
|
-
# LOGGING
|
|
49
|
-
# ============================================================================
|
|
50
|
-
|
|
51
|
-
LOGS_DIR="$PROJECT_ROOT/.specweave/logs"
|
|
52
|
-
LOG_FILE="$LOGS_DIR/universal-auto-create.log"
|
|
53
|
-
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
54
|
-
|
|
55
|
-
log() {
|
|
56
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [auto-create] $1" >> "$LOG_FILE" 2>/dev/null || true
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
# Template guard: skip if spec.md still contains placeholder markers
|
|
60
|
-
grep -q '\[Story Title\]' "$SPEC_PATH" && { log "Skipping: spec.md still contains [Story Title] template markers"; exit 0; }
|
|
61
|
-
|
|
62
|
-
# ============================================================================
|
|
63
|
-
# DEBOUNCE (30s window — spec.md gets edited rapidly during planning)
|
|
64
|
-
# ============================================================================
|
|
65
|
-
|
|
66
|
-
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
67
|
-
mkdir -p "$STATE_DIR" 2>/dev/null || true
|
|
68
|
-
DEBOUNCE_FILE="$STATE_DIR/.auto-create-pending-$INC_ID"
|
|
69
|
-
|
|
70
|
-
if [[ -f "$DEBOUNCE_FILE" ]]; then
|
|
71
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
72
|
-
AGE=$(($(date +%s) - $(stat -f%m "$DEBOUNCE_FILE" 2>/dev/null || echo 0)))
|
|
73
|
-
else
|
|
74
|
-
AGE=$(($(date +%s) - $(stat -c%Y "$DEBOUNCE_FILE" 2>/dev/null || echo 0)))
|
|
75
|
-
fi
|
|
76
|
-
[[ $AGE -lt 30 ]] && exit 0
|
|
77
|
-
fi
|
|
78
|
-
|
|
79
|
-
echo "$(date +%s)" > "$DEBOUNCE_FILE" 2>/dev/null || true
|
|
80
|
-
sleep 30
|
|
81
|
-
|
|
82
|
-
# After sleeping, check if a newer invocation took over
|
|
83
|
-
if [[ -f "$DEBOUNCE_FILE" ]]; then
|
|
84
|
-
CURRENT_SIGNAL=$(cat "$DEBOUNCE_FILE" 2>/dev/null || echo 0)
|
|
85
|
-
SIGNAL_AGE=$(( $(date +%s) - CURRENT_SIGNAL ))
|
|
86
|
-
(( SIGNAL_AGE > 31 )) && exit 0
|
|
87
|
-
fi
|
|
88
|
-
rm -f "$DEBOUNCE_FILE" 2>/dev/null || true
|
|
89
|
-
|
|
90
|
-
# ============================================================================
|
|
91
|
-
# CHECK PROVIDERS
|
|
92
|
-
# ============================================================================
|
|
93
|
-
|
|
94
|
-
command -v jq >/dev/null 2>&1 || exit 0
|
|
95
|
-
|
|
96
|
-
# Use shared provider detection (supports PROFILES, LEGACY DIRECT, LEGACY PROVIDER formats)
|
|
97
|
-
HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
98
|
-
# Derive package root from script location (works for both npm install and dev):
|
|
99
|
-
# handlers/ → v2/ → hooks/ → specweave/ → plugins/ → package root (5 levels up)
|
|
100
|
-
PKG_ROOT="$(cd "$HANDLER_DIR/../../../../.." 2>/dev/null && pwd)"
|
|
101
|
-
SHARED_LIB="$HANDLER_DIR/../lib/check-provider-enabled.sh"
|
|
102
|
-
if [[ -f "$SHARED_LIB" ]]; then
|
|
103
|
-
source "$SHARED_LIB"
|
|
104
|
-
fi
|
|
105
|
-
|
|
106
|
-
# Source resolve-package.sh for dynamic specweave path resolution
|
|
107
|
-
RESOLVE_LIB="$HANDLER_DIR/../../lib/resolve-package.sh"
|
|
108
|
-
if [[ -f "$RESOLVE_LIB" ]]; then
|
|
109
|
-
source "$RESOLVE_LIB"
|
|
110
|
-
fi
|
|
111
|
-
|
|
112
|
-
GH_ENABLED="false"
|
|
113
|
-
JIRA_ENABLED="false"
|
|
114
|
-
ADO_ENABLED="false"
|
|
115
|
-
|
|
116
|
-
if type check_provider_enabled &>/dev/null; then
|
|
117
|
-
check_provider_enabled "$CONFIG_PATH" "github" && GH_ENABLED="true"
|
|
118
|
-
check_provider_enabled "$CONFIG_PATH" "jira" && JIRA_ENABLED="true"
|
|
119
|
-
check_provider_enabled "$CONFIG_PATH" "ado" && ADO_ENABLED="true"
|
|
120
|
-
else
|
|
121
|
-
# Fallback to legacy jq check if shared lib not available
|
|
122
|
-
GH_ENABLED=$(jq -r '.sync.github.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
123
|
-
JIRA_ENABLED=$(jq -r '.sync.jira.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
124
|
-
ADO_ENABLED=$(jq -r '.sync.ado.enabled // false' "$CONFIG_PATH" 2>/dev/null)
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
if [[ "$GH_ENABLED" != "true" && "$JIRA_ENABLED" != "true" && "$ADO_ENABLED" != "true" ]]; then
|
|
128
|
-
log "No providers enabled. Skipping."
|
|
129
|
-
exit 0
|
|
130
|
-
fi
|
|
131
|
-
|
|
132
|
-
# Check auto-create is enabled
|
|
133
|
-
AUTO_CREATE=$(jq -r '.sync.autoCreateOnIncrement // .sync.autoSync // .hooks.post_increment_planning.auto_create_github_issue // false' "$CONFIG_PATH" 2>/dev/null)
|
|
134
|
-
if [[ "$AUTO_CREATE" != "true" ]]; then
|
|
135
|
-
log "Auto-create disabled in config. Skipping."
|
|
136
|
-
exit 0
|
|
137
|
-
fi
|
|
138
|
-
|
|
139
|
-
log "Creating external items for $INC_ID (github=$GH_ENABLED jira=$JIRA_ENABLED ado=$ADO_ENABLED)"
|
|
140
|
-
|
|
141
|
-
# ============================================================================
|
|
142
|
-
# GITHUB: Delegate to existing handler (backward compatible)
|
|
143
|
-
# ============================================================================
|
|
144
|
-
|
|
145
|
-
if [[ "$GH_ENABLED" == "true" ]]; then
|
|
146
|
-
GITHUB_HANDLER=""
|
|
147
|
-
# 1. Sibling plugin dir — handlers/../../../../ = plugins/ (works for both npm and dev)
|
|
148
|
-
CANDIDATE="$HANDLER_DIR/../../../../specweave-github/hooks/github-auto-create-handler.sh"
|
|
149
|
-
[[ -f "$CANDIDATE" ]] && GITHUB_HANDLER="$CANDIDATE"
|
|
150
|
-
# 2. Fallback: PROJECT_ROOT/plugins/ (dev-only, when running from source repo)
|
|
151
|
-
if [[ -z "$GITHUB_HANDLER" ]]; then
|
|
152
|
-
CANDIDATE="${PROJECT_ROOT}/plugins/specweave-github/hooks/github-auto-create-handler.sh"
|
|
153
|
-
[[ -f "$CANDIDATE" ]] && GITHUB_HANDLER="$CANDIDATE"
|
|
154
|
-
fi
|
|
155
|
-
# 3. Fallback: resolve-package.sh (dynamic resolution)
|
|
156
|
-
if [[ -z "$GITHUB_HANDLER" ]]; then
|
|
157
|
-
CANDIDATE=$(find_specweave_script "plugins/specweave-github/hooks/github-auto-create-handler.sh" 2>/dev/null)
|
|
158
|
-
[[ -n "$CANDIDATE" ]] && GITHUB_HANDLER="$CANDIDATE"
|
|
159
|
-
fi
|
|
160
|
-
if [[ -n "$GITHUB_HANDLER" ]]; then
|
|
161
|
-
log "Delegating GitHub auto-create to handler at $GITHUB_HANDLER"
|
|
162
|
-
bash "$GITHUB_HANDLER" "$INC_ID" &
|
|
163
|
-
GH_PID=$!
|
|
164
|
-
else
|
|
165
|
-
log "GitHub handler not found at any known path (checked sibling, PROJECT_ROOT, node_modules)"
|
|
166
|
-
fi
|
|
167
|
-
fi
|
|
168
|
-
|
|
169
|
-
# ============================================================================
|
|
170
|
-
# JIRA/ADO: Call TypeScript module for per-user-story creation
|
|
171
|
-
# ============================================================================
|
|
172
|
-
|
|
173
|
-
if [[ "$JIRA_ENABLED" == "true" || "$ADO_ENABLED" == "true" ]]; then
|
|
174
|
-
command -v node &>/dev/null || { log "Node.js not found. Skipping JIRA/ADO."; exit 0; }
|
|
175
|
-
|
|
176
|
-
# Resolve universal-auto-create.js from multiple locations
|
|
177
|
-
CREATE_MODULE=""
|
|
178
|
-
# 0. SPECWEAVE_PKG (set by Claude Code hook infrastructure, most reliable)
|
|
179
|
-
if [[ -n "${SPECWEAVE_PKG:-}" ]]; then
|
|
180
|
-
CANDIDATE="${SPECWEAVE_PKG}/dist/src/core/universal-auto-create.js"
|
|
181
|
-
[[ -f "$CANDIDATE" ]] && CREATE_MODULE="$CANDIDATE"
|
|
182
|
-
fi
|
|
183
|
-
# 1. Package dist/ (derived from script location — works for both npm and dev)
|
|
184
|
-
if [[ -z "$CREATE_MODULE" ]]; then
|
|
185
|
-
CANDIDATE="${PKG_ROOT:-$PROJECT_ROOT}/dist/src/core/universal-auto-create.js"
|
|
186
|
-
[[ -f "$CANDIDATE" ]] && CREATE_MODULE="$CANDIDATE"
|
|
187
|
-
fi
|
|
188
|
-
# 2. Vendor directory (self-contained plugin)
|
|
189
|
-
# handlers/../../../ = plugins/specweave/ (3 levels up), then lib/vendor/
|
|
190
|
-
# NOTE: vendor path only works for GitHub-only users; JIRA/ADO dynamic imports
|
|
191
|
-
# (jira-client.js, ado-client.js) are NOT vendored and will fail if this path is used.
|
|
192
|
-
if [[ -z "$CREATE_MODULE" ]]; then
|
|
193
|
-
CANDIDATE="$HANDLER_DIR/../../../lib/vendor/core/universal-auto-create.js"
|
|
194
|
-
[[ -f "$CANDIDATE" ]] && CREATE_MODULE="$(cd "$(dirname "$CANDIDATE")" && pwd)/$(basename "$CANDIDATE")"
|
|
195
|
-
fi
|
|
196
|
-
# 3. resolve-package.sh (dynamic resolution)
|
|
197
|
-
if [[ -z "$CREATE_MODULE" ]]; then
|
|
198
|
-
CANDIDATE=$(find_specweave_script "dist/src/core/universal-auto-create.js" 2>/dev/null)
|
|
199
|
-
[[ -n "$CANDIDATE" ]] && CREATE_MODULE="$CANDIDATE"
|
|
200
|
-
fi
|
|
201
|
-
# 4. Legacy: PROJECT_ROOT/dist/ (dev-only, running from source repo)
|
|
202
|
-
if [[ -z "$CREATE_MODULE" ]]; then
|
|
203
|
-
CANDIDATE="${PROJECT_ROOT}/dist/src/core/universal-auto-create.js"
|
|
204
|
-
[[ -f "$CANDIDATE" ]] && CREATE_MODULE="$CANDIDATE"
|
|
205
|
-
fi
|
|
206
|
-
|
|
207
|
-
if [[ -z "$CREATE_MODULE" ]]; then
|
|
208
|
-
log "Module not found at any known path. Skipping JIRA/ADO. Checked: PKG_ROOT=${PKG_ROOT:-unset}, node_modules, vendor, PROJECT_ROOT"
|
|
209
|
-
else
|
|
210
|
-
# Build config JSON for the TypeScript module
|
|
211
|
-
JIRA_DOMAIN=$(jq -r '.sync.jira.domain // .issueTracker.domain // ""' "$CONFIG_PATH" 2>/dev/null)
|
|
212
|
-
JIRA_PROJECT_KEY=$(jq -r '.sync.jira.projectKey // .issueTracker.projects[0].key // ""' "$CONFIG_PATH" 2>/dev/null)
|
|
213
|
-
ADO_ORG=$(jq -r '.sync.ado.organization // .issueTracker.organization_ado // ""' "$CONFIG_PATH" 2>/dev/null)
|
|
214
|
-
ADO_PROJECT=$(jq -r '.sync.ado.project // .issueTracker.project // ""' "$CONFIG_PATH" 2>/dev/null)
|
|
215
|
-
|
|
216
|
-
OUTPUT=$(SW_CREATE_MODULE="$CREATE_MODULE" \
|
|
217
|
-
SW_INC_ID="$INC_ID" \
|
|
218
|
-
SW_SPEC_PATH="$SPEC_PATH" \
|
|
219
|
-
SW_METADATA_PATH="$METADATA_PATH" \
|
|
220
|
-
SW_JIRA_ENABLED="$JIRA_ENABLED" \
|
|
221
|
-
SW_ADO_ENABLED="$ADO_ENABLED" \
|
|
222
|
-
SW_JIRA_DOMAIN="$JIRA_DOMAIN" \
|
|
223
|
-
SW_JIRA_PROJECT_KEY="$JIRA_PROJECT_KEY" \
|
|
224
|
-
SW_ADO_ORG="$ADO_ORG" \
|
|
225
|
-
SW_ADO_PROJECT="$ADO_PROJECT" \
|
|
226
|
-
node --input-type=module -e "
|
|
227
|
-
const { SW_CREATE_MODULE, SW_INC_ID, SW_SPEC_PATH, SW_METADATA_PATH,
|
|
228
|
-
SW_JIRA_ENABLED, SW_ADO_ENABLED, SW_JIRA_DOMAIN,
|
|
229
|
-
SW_JIRA_PROJECT_KEY, SW_ADO_ORG, SW_ADO_PROJECT } = process.env;
|
|
230
|
-
|
|
231
|
-
const mod = await import(SW_CREATE_MODULE);
|
|
232
|
-
|
|
233
|
-
const config = {
|
|
234
|
-
sync: {
|
|
235
|
-
jira: { enabled: SW_JIRA_ENABLED === 'true' },
|
|
236
|
-
ado: { enabled: SW_ADO_ENABLED === 'true' },
|
|
237
|
-
},
|
|
238
|
-
jira: { domain: SW_JIRA_DOMAIN, projectKey: SW_JIRA_PROJECT_KEY },
|
|
239
|
-
ado: { organization: SW_ADO_ORG, project: SW_ADO_PROJECT },
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
try {
|
|
243
|
-
const result = await mod.createExternalIssuesForIncrement(
|
|
244
|
-
SW_INC_ID, SW_SPEC_PATH, SW_METADATA_PATH, config,
|
|
245
|
-
);
|
|
246
|
-
console.log(JSON.stringify(result, null, 2));
|
|
247
|
-
} catch (err) {
|
|
248
|
-
console.error('Universal auto-create error:', err.message || err);
|
|
249
|
-
process.exit(1);
|
|
250
|
-
}
|
|
251
|
-
" 2>&1)
|
|
252
|
-
EXIT_CODE=$?
|
|
253
|
-
|
|
254
|
-
if [[ $EXIT_CODE -ne 0 ]]; then
|
|
255
|
-
log "JIRA/ADO creation failed (exit $EXIT_CODE): $OUTPUT"
|
|
256
|
-
else
|
|
257
|
-
log "JIRA/ADO creation completed: $OUTPUT"
|
|
258
|
-
fi
|
|
259
|
-
fi
|
|
260
|
-
fi
|
|
261
|
-
|
|
262
|
-
# Wait for GitHub handler if started
|
|
263
|
-
if [[ -n "${GH_PID:-}" ]]; then
|
|
264
|
-
wait "$GH_PID" 2>/dev/null
|
|
265
|
-
GH_EXIT=$?
|
|
266
|
-
[[ $GH_EXIT -ne 0 ]] && log "GitHub handler exited with code $GH_EXIT (check github-auto-create.log for details)"
|
|
267
|
-
fi
|
|
268
|
-
|
|
269
|
-
log "Universal auto-create finished for $INC_ID"
|
|
270
|
-
exit 0
|
|
@@ -1,367 +0,0 @@
|
|
|
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 /sw:done (increment completion)
|
|
12
|
-
# 2. After /sw:sync-docs update
|
|
13
|
-
# 3. After manual spec edits
|
|
14
|
-
# 4. After webhook from ADO
|
|
15
|
-
#
|
|
16
|
-
# ============================================================================
|
|
17
|
-
|
|
18
|
-
set +e # EMERGENCY FIX: Prevents Claude Code crashes
|
|
19
|
-
|
|
20
|
-
# EMERGENCY KILL SWITCH
|
|
21
|
-
if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
|
|
22
|
-
exit 0
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
# Configuration
|
|
26
|
-
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
27
|
-
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
|
28
|
-
LIVING_DOCS_DIR="$PROJECT_ROOT/.specweave/docs/internal/specs"
|
|
29
|
-
LOG_FILE="$PROJECT_ROOT/.specweave/logs/ado-sync.log"
|
|
30
|
-
DEBUG=${DEBUG:-0}
|
|
31
|
-
|
|
32
|
-
# Ensure log directory exists
|
|
33
|
-
mkdir -p "$(dirname "$LOG_FILE")"
|
|
34
|
-
|
|
35
|
-
# ============================================================================
|
|
36
|
-
# Logging
|
|
37
|
-
# ============================================================================
|
|
38
|
-
|
|
39
|
-
log() {
|
|
40
|
-
local level=$1
|
|
41
|
-
shift
|
|
42
|
-
local message="$@"
|
|
43
|
-
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
44
|
-
echo "[$timestamp] [$level] $message" >> "$LOG_FILE"
|
|
45
|
-
[ "$DEBUG" -eq 1 ] && echo "[$level] $message" >&2
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
log_info() {
|
|
49
|
-
log "INFO" "$@"
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
log_error() {
|
|
53
|
-
log "ERROR" "$@"
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
log_debug() {
|
|
57
|
-
[ "$DEBUG" -eq 1 ] && log "DEBUG" "$@"
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
# ============================================================================
|
|
61
|
-
# External Tool Detection
|
|
62
|
-
# ============================================================================
|
|
63
|
-
|
|
64
|
-
detect_external_tool() {
|
|
65
|
-
local spec_path=$1
|
|
66
|
-
|
|
67
|
-
# Check for external links in spec metadata
|
|
68
|
-
if grep -q "externalLinks:" "$spec_path"; then
|
|
69
|
-
if grep -q "ado:" "$spec_path"; then
|
|
70
|
-
echo "ado"
|
|
71
|
-
elif grep -q "jira:" "$spec_path"; then
|
|
72
|
-
echo "jira"
|
|
73
|
-
elif grep -q "github:" "$spec_path"; then
|
|
74
|
-
echo "github"
|
|
75
|
-
fi
|
|
76
|
-
fi
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
# ============================================================================
|
|
80
|
-
# Status Mapping
|
|
81
|
-
# ============================================================================
|
|
82
|
-
|
|
83
|
-
map_ado_status_to_local() {
|
|
84
|
-
local ado_status=$1
|
|
85
|
-
|
|
86
|
-
case "$ado_status" in
|
|
87
|
-
"New")
|
|
88
|
-
echo "draft"
|
|
89
|
-
;;
|
|
90
|
-
"Active")
|
|
91
|
-
echo "in-progress"
|
|
92
|
-
;;
|
|
93
|
-
"Resolved")
|
|
94
|
-
echo "implemented"
|
|
95
|
-
;;
|
|
96
|
-
"Closed")
|
|
97
|
-
echo "complete"
|
|
98
|
-
;;
|
|
99
|
-
"In Review"|"In QA")
|
|
100
|
-
echo "in-qa"
|
|
101
|
-
;;
|
|
102
|
-
*)
|
|
103
|
-
echo "unknown"
|
|
104
|
-
;;
|
|
105
|
-
esac
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
map_local_status_to_ado() {
|
|
109
|
-
local local_status=$1
|
|
110
|
-
|
|
111
|
-
case "$local_status" in
|
|
112
|
-
"draft")
|
|
113
|
-
echo "New"
|
|
114
|
-
;;
|
|
115
|
-
"in-progress")
|
|
116
|
-
echo "Active"
|
|
117
|
-
;;
|
|
118
|
-
"implemented")
|
|
119
|
-
echo "Resolved"
|
|
120
|
-
;;
|
|
121
|
-
"complete")
|
|
122
|
-
echo "Closed"
|
|
123
|
-
;;
|
|
124
|
-
"in-qa")
|
|
125
|
-
echo "In Review"
|
|
126
|
-
;;
|
|
127
|
-
*)
|
|
128
|
-
echo "Active"
|
|
129
|
-
;;
|
|
130
|
-
esac
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
# ============================================================================
|
|
134
|
-
# ADO API Functions
|
|
135
|
-
# ============================================================================
|
|
136
|
-
|
|
137
|
-
get_ado_work_item_status() {
|
|
138
|
-
local work_item_id=$1
|
|
139
|
-
local org="${AZURE_DEVOPS_ORG}"
|
|
140
|
-
local project="${AZURE_DEVOPS_PROJECT}"
|
|
141
|
-
local pat="${AZURE_DEVOPS_PAT}"
|
|
142
|
-
|
|
143
|
-
if [ -z "$org" ] || [ -z "$pat" ]; then
|
|
144
|
-
log_error "ADO credentials not configured"
|
|
145
|
-
return 1
|
|
146
|
-
fi
|
|
147
|
-
|
|
148
|
-
local api_url="https://dev.azure.com/${org}/${project}/_apis/wit/workitems/${work_item_id}?api-version=7.0"
|
|
149
|
-
|
|
150
|
-
log_debug "Fetching ADO work item $work_item_id status"
|
|
151
|
-
|
|
152
|
-
local response=$(curl -s -u ":${pat}" \
|
|
153
|
-
-H "Content-Type: application/json" \
|
|
154
|
-
"$api_url")
|
|
155
|
-
|
|
156
|
-
if [ $? -ne 0 ]; then
|
|
157
|
-
log_error "Failed to fetch ADO work item status"
|
|
158
|
-
return 1
|
|
159
|
-
fi
|
|
160
|
-
|
|
161
|
-
# Extract status from response
|
|
162
|
-
local status=$(echo "$response" | jq -r '.fields["System.State"]')
|
|
163
|
-
|
|
164
|
-
if [ "$status" = "null" ] || [ -z "$status" ]; then
|
|
165
|
-
log_error "Could not extract status from ADO response"
|
|
166
|
-
return 1
|
|
167
|
-
fi
|
|
168
|
-
|
|
169
|
-
echo "$status"
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
update_ado_work_item() {
|
|
173
|
-
local work_item_id=$1
|
|
174
|
-
local spec_content=$2
|
|
175
|
-
local org="${AZURE_DEVOPS_ORG}"
|
|
176
|
-
local project="${AZURE_DEVOPS_PROJECT}"
|
|
177
|
-
local pat="${AZURE_DEVOPS_PAT}"
|
|
178
|
-
|
|
179
|
-
if [ -z "$org" ] || [ -z "$pat" ]; then
|
|
180
|
-
log_error "ADO credentials not configured"
|
|
181
|
-
return 1
|
|
182
|
-
fi
|
|
183
|
-
|
|
184
|
-
# Extract current status from spec
|
|
185
|
-
local local_status=$(echo "$spec_content" | grep "^status:" | cut -d: -f2 | tr -d ' ')
|
|
186
|
-
local ado_status=$(map_local_status_to_ado "$local_status")
|
|
187
|
-
|
|
188
|
-
local api_url="https://dev.azure.com/${org}/${project}/_apis/wit/workitems/${work_item_id}?api-version=7.0"
|
|
189
|
-
|
|
190
|
-
# Create update payload
|
|
191
|
-
local payload=$(cat <<EOF
|
|
192
|
-
[
|
|
193
|
-
{
|
|
194
|
-
"op": "add",
|
|
195
|
-
"path": "/fields/System.State",
|
|
196
|
-
"value": "$ado_status"
|
|
197
|
-
},
|
|
198
|
-
{
|
|
199
|
-
"op": "add",
|
|
200
|
-
"path": "/fields/System.History",
|
|
201
|
-
"value": "Updated from SpecWeave living docs"
|
|
202
|
-
}
|
|
203
|
-
]
|
|
204
|
-
EOF
|
|
205
|
-
)
|
|
206
|
-
|
|
207
|
-
log_debug "Updating ADO work item $work_item_id with status: $ado_status"
|
|
208
|
-
|
|
209
|
-
curl -s -X PATCH \
|
|
210
|
-
-u ":${pat}" \
|
|
211
|
-
-H "Content-Type: application/json-patch+json" \
|
|
212
|
-
-d "$payload" \
|
|
213
|
-
"$api_url" > /dev/null
|
|
214
|
-
|
|
215
|
-
if [ $? -ne 0 ]; then
|
|
216
|
-
log_error "Failed to update ADO work item"
|
|
217
|
-
return 1
|
|
218
|
-
fi
|
|
219
|
-
|
|
220
|
-
log_info "Updated ADO work item $work_item_id"
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
# ============================================================================
|
|
224
|
-
# Conflict Resolution - CRITICAL: External Wins!
|
|
225
|
-
# ============================================================================
|
|
226
|
-
|
|
227
|
-
resolve_status_conflict() {
|
|
228
|
-
local spec_path=$1
|
|
229
|
-
local local_status=$2
|
|
230
|
-
local external_status=$3
|
|
231
|
-
|
|
232
|
-
local mapped_external=$(map_ado_status_to_local "$external_status")
|
|
233
|
-
|
|
234
|
-
if [ "$local_status" != "$mapped_external" ]; then
|
|
235
|
-
log_info "Status conflict detected:"
|
|
236
|
-
log_info " Local: $local_status"
|
|
237
|
-
log_info " External: $external_status (mapped: $mapped_external)"
|
|
238
|
-
log_info " Resolution: EXTERNAL WINS - applying $mapped_external"
|
|
239
|
-
|
|
240
|
-
# Update local spec with external status
|
|
241
|
-
sed -i.bak "s/^status: .*/status: $mapped_external/" "$spec_path"
|
|
242
|
-
|
|
243
|
-
# Add sync metadata
|
|
244
|
-
local timestamp=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
|
|
245
|
-
|
|
246
|
-
# Check if syncedAt exists, update or add
|
|
247
|
-
if grep -q "syncedAt:" "$spec_path"; then
|
|
248
|
-
sed -i.bak "s/syncedAt: .*/syncedAt: \"$timestamp\"/" "$spec_path"
|
|
249
|
-
else
|
|
250
|
-
# Add after externalLinks section
|
|
251
|
-
sed -i.bak "/externalLinks:/a\\
|
|
252
|
-
syncedAt: \"$timestamp\"" "$spec_path"
|
|
253
|
-
fi
|
|
254
|
-
|
|
255
|
-
# Clean up backup files
|
|
256
|
-
rm -f "${spec_path}.bak"
|
|
257
|
-
|
|
258
|
-
log_info "Local spec updated with external status: $mapped_external"
|
|
259
|
-
return 0
|
|
260
|
-
else
|
|
261
|
-
log_debug "No status conflict - local and external match: $local_status"
|
|
262
|
-
return 0
|
|
263
|
-
fi
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
# ============================================================================
|
|
267
|
-
# Main Sync Function
|
|
268
|
-
# ============================================================================
|
|
269
|
-
|
|
270
|
-
sync_spec_with_ado() {
|
|
271
|
-
local spec_path=$1
|
|
272
|
-
|
|
273
|
-
if [ ! -f "$spec_path" ]; then
|
|
274
|
-
log_error "Spec file not found: $spec_path"
|
|
275
|
-
return 1
|
|
276
|
-
fi
|
|
277
|
-
|
|
278
|
-
local spec_name=$(basename "$spec_path")
|
|
279
|
-
log_info "Syncing spec: $spec_name"
|
|
280
|
-
|
|
281
|
-
# Read spec content
|
|
282
|
-
local spec_content=$(cat "$spec_path")
|
|
283
|
-
|
|
284
|
-
# Extract ADO work item ID from metadata
|
|
285
|
-
local work_item_id=$(echo "$spec_content" | grep -A5 "externalLinks:" | grep -A3 "ado:" | grep "featureId:" | cut -d: -f2 | tr -d ' ')
|
|
286
|
-
|
|
287
|
-
if [ -z "$work_item_id" ]; then
|
|
288
|
-
log_debug "No ADO work item linked to spec, skipping sync"
|
|
289
|
-
return 0
|
|
290
|
-
fi
|
|
291
|
-
|
|
292
|
-
log_info "Found ADO work item ID: $work_item_id"
|
|
293
|
-
|
|
294
|
-
# Step 1: Push updates to ADO (content changes)
|
|
295
|
-
update_ado_work_item "$work_item_id" "$spec_content"
|
|
296
|
-
|
|
297
|
-
# Step 2: CRITICAL - Pull status from ADO (external wins!)
|
|
298
|
-
local external_status=$(get_ado_work_item_status "$work_item_id")
|
|
299
|
-
|
|
300
|
-
if [ -z "$external_status" ]; then
|
|
301
|
-
log_error "Could not fetch ADO status"
|
|
302
|
-
return 1
|
|
303
|
-
fi
|
|
304
|
-
|
|
305
|
-
log_info "ADO status: $external_status"
|
|
306
|
-
|
|
307
|
-
# Step 3: Extract local status
|
|
308
|
-
local local_status=$(echo "$spec_content" | grep "^status:" | cut -d: -f2 | tr -d ' ')
|
|
309
|
-
|
|
310
|
-
log_info "Local status: $local_status"
|
|
311
|
-
|
|
312
|
-
# Step 4: Resolve conflicts - EXTERNAL WINS
|
|
313
|
-
resolve_status_conflict "$spec_path" "$local_status" "$external_status"
|
|
314
|
-
|
|
315
|
-
log_info "Sync completed for $spec_name"
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
# ============================================================================
|
|
319
|
-
# Entry Point
|
|
320
|
-
# ============================================================================
|
|
321
|
-
|
|
322
|
-
main() {
|
|
323
|
-
log_info "=== Post Living Docs Update Hook Started ==="
|
|
324
|
-
|
|
325
|
-
# Get the spec path from arguments or environment
|
|
326
|
-
local spec_path="${1:-$SPECWEAVE_UPDATED_SPEC}"
|
|
327
|
-
|
|
328
|
-
if [ -z "$spec_path" ]; then
|
|
329
|
-
log_error "No spec path provided"
|
|
330
|
-
exit 0 # SAFETY: Never use exit 1 in hooks - causes Claude Code failures
|
|
331
|
-
fi
|
|
332
|
-
|
|
333
|
-
# Detect external tool
|
|
334
|
-
local tool=$(detect_external_tool "$spec_path")
|
|
335
|
-
|
|
336
|
-
if [ "$tool" != "ado" ]; then
|
|
337
|
-
log_debug "Not an ADO-linked spec, skipping"
|
|
338
|
-
exit 0
|
|
339
|
-
fi
|
|
340
|
-
|
|
341
|
-
log_info "Detected ADO integration for spec"
|
|
342
|
-
|
|
343
|
-
# Perform sync
|
|
344
|
-
sync_spec_with_ado "$spec_path"
|
|
345
|
-
|
|
346
|
-
local exit_code=$?
|
|
347
|
-
|
|
348
|
-
if [ $exit_code -eq 0 ]; then
|
|
349
|
-
log_info "=== Sync completed successfully ==="
|
|
350
|
-
else
|
|
351
|
-
log_error "=== Sync failed with exit code: $exit_code ==="
|
|
352
|
-
# Log warning but DON'T exit with error - hooks must be non-blocking
|
|
353
|
-
echo ""
|
|
354
|
-
echo " [Hook Warning] ADO sync failed (exit $exit_code)"
|
|
355
|
-
echo " (Operation continues - hooks are non-blocking)"
|
|
356
|
-
echo ""
|
|
357
|
-
fi
|
|
358
|
-
|
|
359
|
-
# Return status for logging but function should NOT exit
|
|
360
|
-
return $exit_code
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
# Run main function (errors logged, not propagated)
|
|
364
|
-
main "$@" || true
|
|
365
|
-
|
|
366
|
-
# ALWAYS exit 0 - NEVER let hook errors crash Claude Code
|
|
367
|
-
exit 0
|