specweave 1.0.550 → 1.0.552

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/CLAUDE.md +1 -1
  2. package/bin/specweave.js +23 -1
  3. package/dist/src/cli/commands/hook.d.ts +15 -0
  4. package/dist/src/cli/commands/hook.d.ts.map +1 -0
  5. package/dist/src/cli/commands/hook.js +61 -0
  6. package/dist/src/cli/commands/hook.js.map +1 -0
  7. package/dist/src/cli/commands/init.d.ts.map +1 -1
  8. package/dist/src/cli/commands/init.js +5 -0
  9. package/dist/src/cli/commands/init.js.map +1 -1
  10. package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
  11. package/dist/src/cli/commands/refresh-plugins.js +11 -1
  12. package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
  13. package/dist/src/cli/commands/sync-setup.d.ts.map +1 -1
  14. package/dist/src/cli/commands/sync-setup.js +7 -3
  15. package/dist/src/cli/commands/sync-setup.js.map +1 -1
  16. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts +9 -0
  17. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts.map +1 -1
  18. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js +9 -3
  19. package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js.map +1 -1
  20. package/dist/src/config/types.d.ts +2 -2
  21. package/dist/src/core/config/types.d.ts +18 -2
  22. package/dist/src/core/config/types.d.ts.map +1 -1
  23. package/dist/src/core/config/types.js.map +1 -1
  24. package/dist/src/core/hooks/handlers/hook-router.d.ts +19 -0
  25. package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -0
  26. package/dist/src/core/hooks/handlers/hook-router.js +75 -0
  27. package/dist/src/core/hooks/handlers/hook-router.js.map +1 -0
  28. package/dist/src/core/hooks/handlers/index.d.ts +10 -0
  29. package/dist/src/core/hooks/handlers/index.d.ts.map +1 -0
  30. package/dist/src/core/hooks/handlers/index.js +9 -0
  31. package/dist/src/core/hooks/handlers/index.js.map +1 -0
  32. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +11 -0
  33. package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +1 -0
  34. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +73 -0
  35. package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +1 -0
  36. package/dist/src/core/hooks/handlers/post-tool-use.d.ts +11 -0
  37. package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +1 -0
  38. package/dist/src/core/hooks/handlers/post-tool-use.js +76 -0
  39. package/dist/src/core/hooks/handlers/post-tool-use.js.map +1 -0
  40. package/dist/src/core/hooks/handlers/pre-compact.d.ts +11 -0
  41. package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
  42. package/dist/src/core/hooks/handlers/pre-compact.js +77 -0
  43. package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
  44. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts +11 -0
  45. package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -0
  46. package/dist/src/core/hooks/handlers/pre-tool-use.js +318 -0
  47. package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -0
  48. package/dist/src/core/hooks/handlers/session-start.d.ts +9 -0
  49. package/dist/src/core/hooks/handlers/session-start.d.ts.map +1 -0
  50. package/dist/src/core/hooks/handlers/session-start.js +111 -0
  51. package/dist/src/core/hooks/handlers/session-start.js.map +1 -0
  52. package/dist/src/core/hooks/handlers/stop-auto.d.ts +16 -0
  53. package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +1 -0
  54. package/dist/src/core/hooks/handlers/stop-auto.js +122 -0
  55. package/dist/src/core/hooks/handlers/stop-auto.js.map +1 -0
  56. package/dist/src/core/hooks/handlers/stop-reflect.d.ts +14 -0
  57. package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +1 -0
  58. package/dist/src/core/hooks/handlers/stop-reflect.js +43 -0
  59. package/dist/src/core/hooks/handlers/stop-reflect.js.map +1 -0
  60. package/dist/src/core/hooks/handlers/stop-sync.d.ts +15 -0
  61. package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +1 -0
  62. package/dist/src/core/hooks/handlers/stop-sync.js +68 -0
  63. package/dist/src/core/hooks/handlers/stop-sync.js.map +1 -0
  64. package/dist/src/core/hooks/handlers/types.d.ts +63 -0
  65. package/dist/src/core/hooks/handlers/types.d.ts.map +1 -0
  66. package/dist/src/core/hooks/handlers/types.js +27 -0
  67. package/dist/src/core/hooks/handlers/types.js.map +1 -0
  68. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts +14 -0
  69. package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -0
  70. package/dist/src/core/hooks/handlers/user-prompt-submit.js +173 -0
  71. package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -0
  72. package/dist/src/core/hooks/handlers/utils.d.ts +25 -0
  73. package/dist/src/core/hooks/handlers/utils.d.ts.map +1 -0
  74. package/dist/src/core/hooks/handlers/utils.js +64 -0
  75. package/dist/src/core/hooks/handlers/utils.js.map +1 -0
  76. package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
  77. package/dist/src/core/increment/completion-validator.js +32 -0
  78. package/dist/src/core/increment/completion-validator.js.map +1 -1
  79. package/dist/src/init/research/types.d.ts +1 -1
  80. package/dist/src/sync/sync-target-resolver.js.map +1 -1
  81. package/dist/src/utils/lock-manager.d.ts.map +1 -1
  82. package/dist/src/utils/lock-manager.js +5 -0
  83. package/dist/src/utils/lock-manager.js.map +1 -1
  84. package/dist/src/utils/plugin-copier.d.ts +10 -0
  85. package/dist/src/utils/plugin-copier.d.ts.map +1 -1
  86. package/dist/src/utils/plugin-copier.js +63 -35
  87. package/dist/src/utils/plugin-copier.js.map +1 -1
  88. package/package.json +1 -1
  89. package/plugins/specweave/agents/sw-closer.md +3 -2
  90. package/plugins/specweave/hooks/hooks.json +10 -10
  91. package/plugins/specweave/skills/code-reviewer/SKILL.md +180 -16
  92. package/plugins/specweave/skills/code-reviewer/agents/reviewer-comments.md +83 -0
  93. package/plugins/specweave/skills/code-reviewer/agents/reviewer-silent-failures.md +19 -0
  94. package/plugins/specweave/skills/code-reviewer/agents/reviewer-spec-compliance.md +19 -0
  95. package/plugins/specweave/skills/code-reviewer/agents/reviewer-tests.md +101 -0
  96. package/plugins/specweave/skills/code-reviewer/agents/reviewer-types.md +20 -0
  97. package/plugins/specweave/skills/done/SKILL.md +56 -21
  98. package/plugins/specweave/skills/grill/SKILL.md +1 -1
  99. package/plugins/specweave/skills/team-lead/agents/reviewer-logic.md +19 -0
  100. package/plugins/specweave/skills/team-lead/agents/reviewer-performance.md +20 -0
  101. package/plugins/specweave/skills/team-lead/agents/reviewer-security.md +20 -0
  102. package/src/templates/CLAUDE.md.template +7 -4
  103. package/plugins/specweave/hooks/README.md +0 -493
  104. package/plugins/specweave/hooks/_archive/stop-auto-v4-legacy.sh +0 -1319
  105. package/plugins/specweave/hooks/lib/common-setup.sh +0 -144
  106. package/plugins/specweave/hooks/lib/hook-errors.sh +0 -414
  107. package/plugins/specweave/hooks/lib/migrate-increment-work.sh +0 -245
  108. package/plugins/specweave/hooks/lib/resolve-package.sh +0 -146
  109. package/plugins/specweave/hooks/lib/scheduler-startup.sh +0 -135
  110. package/plugins/specweave/hooks/lib/score-increment.sh +0 -87
  111. package/plugins/specweave/hooks/lib/sync-spec-content.sh +0 -193
  112. package/plugins/specweave/hooks/lib/update-active-increment.sh +0 -95
  113. package/plugins/specweave/hooks/lib/update-status-line.sh +0 -233
  114. package/plugins/specweave/hooks/lib/validate-spec-status.sh +0 -171
  115. package/plugins/specweave/hooks/llm-judge-validator.sh +0 -219
  116. package/plugins/specweave/hooks/log-decision.sh +0 -168
  117. package/plugins/specweave/hooks/pre-compact.sh +0 -64
  118. package/plugins/specweave/hooks/startup-health-check.sh +0 -64
  119. package/plugins/specweave/hooks/stop-auto-v5.sh +0 -276
  120. package/plugins/specweave/hooks/stop-reflect.sh +0 -336
  121. package/plugins/specweave/hooks/stop-sync.sh +0 -283
  122. package/plugins/specweave/hooks/tests/test-auto-context-integration.sh +0 -126
  123. package/plugins/specweave/hooks/tests/test-stop-auto-enriched.sh +0 -128
  124. package/plugins/specweave/hooks/universal/dispatcher.mjs +0 -336
  125. package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +0 -325
  126. package/plugins/specweave/hooks/universal/hook-wrapper.cmd +0 -26
  127. package/plugins/specweave/hooks/universal/hook-wrapper.sh +0 -69
  128. package/plugins/specweave/hooks/universal/run-hook.sh +0 -20
  129. package/plugins/specweave/hooks/universal/session-start.cmd +0 -16
  130. package/plugins/specweave/hooks/universal/session-start.ps1 +0 -16
  131. package/plugins/specweave/hooks/user-prompt-submit.sh +0 -2550
  132. package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +0 -87
  133. package/plugins/specweave/hooks/v2/detectors/us-completion-detector.sh +0 -186
  134. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +0 -83
  135. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +0 -447
  136. package/plugins/specweave/hooks/v2/dispatchers/pre-tool-use.sh +0 -104
  137. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +0 -270
  138. package/plugins/specweave/hooks/v2/guards/completion-guard.sh +0 -14
  139. package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +0 -14
  140. package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +0 -240
  141. package/plugins/specweave/hooks/v2/guards/interview-enforcement-guard.sh +0 -171
  142. package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +0 -14
  143. package/plugins/specweave/hooks/v2/guards/skill-chain-enforcement-guard.sh +0 -222
  144. package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +0 -21
  145. package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +0 -14
  146. package/plugins/specweave/hooks/v2/guards/status-completion-guard.sh +0 -84
  147. package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +0 -475
  148. package/plugins/specweave/hooks/v2/guards/tdd-enforcement-guard.sh +0 -268
  149. package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +0 -332
  150. package/plugins/specweave/hooks/v2/handlers/ac-validation-handler.sh +0 -50
  151. package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +0 -347
  152. package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +0 -83
  153. package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +0 -268
  154. package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +0 -104
  155. package/plugins/specweave/hooks/v2/handlers/status-line-handler.sh +0 -165
  156. package/plugins/specweave/hooks/v2/handlers/status-update.sh +0 -61
  157. package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +0 -270
  158. package/plugins/specweave/hooks/v2/integrations/ado-post-living-docs-update.sh +0 -367
  159. package/plugins/specweave/hooks/v2/integrations/ado-post-task.sh +0 -179
  160. package/plugins/specweave/hooks/v2/integrations/github-auto-create-handler.sh +0 -553
  161. package/plugins/specweave/hooks/v2/integrations/github-post-task.sh +0 -345
  162. package/plugins/specweave/hooks/v2/integrations/jira-post-task.sh +0 -180
  163. package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +0 -52
  164. package/plugins/specweave/hooks/v2/queue/enqueue.sh +0 -81
  165. package/plugins/specweave/hooks/v2/session-end.sh +0 -139
  166. package/plugins/specweave/hooks/validate-skill-activations.sh +0 -227
@@ -1,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