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