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,245 +0,0 @@
1
- #!/bin/bash
2
-
3
- # SpecWeave Increment Work Migration Utility
4
- # Purpose: Smart migration options when WIP limit is reached
5
- #
6
- # Options:
7
- # 1. Transfer work (move incomplete tasks to new increment)
8
- # 2. Adjust WIP limit (temporarily allow 3 active)
9
- # 3. Force-close (mark as complete without transferring work)
10
-
11
- set +e # EMERGENCY FIX: Changed from set -euo pipefail to prevent Claude Code crashes
12
-
13
- # ============================================================================
14
- # CONFIGURATION
15
- # ============================================================================
16
-
17
- SPECWEAVE_DIR="${SPECWEAVE_DIR:-.specweave}"
18
- CONFIG_FILE="$SPECWEAVE_DIR/config.json"
19
-
20
- # ============================================================================
21
- # HELPER FUNCTIONS
22
- # ============================================================================
23
-
24
- # Get incomplete tasks from increment
25
- get_incomplete_tasks() {
26
- local increment_id="$1"
27
- local tasks_file="$SPECWEAVE_DIR/increments/$increment_id/tasks.md"
28
-
29
- if [[ ! -f "$tasks_file" ]]; then
30
- echo ""
31
- return
32
- fi
33
-
34
- # Extract unchecked tasks (lines starting with "- [ ]")
35
- grep -E "^\s*-\s*\[ \]" "$tasks_file" 2>/dev/null || echo ""
36
- }
37
-
38
- # Count incomplete tasks
39
- count_incomplete_tasks() {
40
- local increment_id="$1"
41
- local tasks=$(get_incomplete_tasks "$increment_id")
42
-
43
- if [[ -z "$tasks" ]]; then
44
- echo "0"
45
- else
46
- echo "$tasks" | wc -l | xargs
47
- fi
48
- }
49
-
50
- # Transfer work from old increment to new increment
51
- transfer_work() {
52
- local source_increment="$1"
53
- local target_increment="$2"
54
-
55
- echo "🔄 Transferring incomplete work from $source_increment to $target_increment..."
56
-
57
- # Get incomplete tasks
58
- local incomplete_tasks=$(get_incomplete_tasks "$source_increment")
59
-
60
- if [[ -z "$incomplete_tasks" ]]; then
61
- echo "✅ No incomplete tasks to transfer"
62
- return 0
63
- fi
64
-
65
- local task_count=$(echo "$incomplete_tasks" | wc -l | xargs)
66
- echo " 📋 Found $task_count incomplete tasks"
67
-
68
- # Append to target increment's tasks.md
69
- local target_tasks="$SPECWEAVE_DIR/increments/$target_increment/tasks.md"
70
-
71
- if [[ ! -f "$target_tasks" ]]; then
72
- echo "❌ Target increment tasks.md not found: $target_tasks"
73
- return 1
74
- fi
75
-
76
- # Add separator and transferred tasks
77
- cat >> "$target_tasks" <<EOF
78
-
79
- ---
80
-
81
- ## 🔄 Transferred from $source_increment
82
-
83
- $incomplete_tasks
84
-
85
- EOF
86
-
87
- echo " ✅ Transferred $task_count tasks to $target_tasks"
88
-
89
- # Mark source increment as completed-with-work-transfer
90
- local source_metadata="$SPECWEAVE_DIR/increments/$source_increment/metadata.json"
91
-
92
- if [[ -f "$source_metadata" ]]; then
93
- node -e "
94
- const fs = require('fs');
95
- const path = '$source_metadata';
96
- const data = JSON.parse(fs.readFileSync(path, 'utf-8'));
97
- data.status = 'completed';
98
- data.completionNote = 'Work transferred to $target_increment';
99
- data.completedAt = new Date().toISOString();
100
- data.workTransferredTo = '$target_increment';
101
- fs.writeFileSync(path, JSON.stringify(data, null, 2));
102
- "
103
- echo " ✅ Updated $source_increment metadata (status: completed, work transferred)"
104
- fi
105
-
106
- # Update target increment metadata
107
- local target_metadata="$SPECWEAVE_DIR/increments/$target_increment/metadata.json"
108
-
109
- if [[ -f "$target_metadata" ]]; then
110
- node -e "
111
- const fs = require('fs');
112
- const path = '$target_metadata';
113
- const data = JSON.parse(fs.readFileSync(path, 'utf-8'));
114
- data.workTransferredFrom = data.workTransferredFrom || [];
115
- data.workTransferredFrom.push('$source_increment');
116
- fs.writeFileSync(path, JSON.stringify(data, null, 2));
117
- "
118
- echo " ✅ Updated $target_increment metadata (work received from $source_increment)"
119
- fi
120
-
121
- echo "✅ Work transfer complete!"
122
- return 0
123
- }
124
-
125
- # Adjust WIP limit temporarily
126
- adjust_wip_limit() {
127
- local new_limit="$1"
128
-
129
- echo "⚠️ Temporarily adjusting WIP limit to $new_limit..."
130
-
131
- if [[ ! -f "$CONFIG_FILE" ]]; then
132
- echo "❌ Config file not found: $CONFIG_FILE"
133
- return 1
134
- fi
135
-
136
- # Update config.json (create backup first)
137
- cp "$CONFIG_FILE" "$CONFIG_FILE.bak"
138
-
139
- node -e "
140
- const fs = require('fs');
141
- const path = '$CONFIG_FILE';
142
- const data = JSON.parse(fs.readFileSync(path, 'utf-8'));
143
-
144
- // Ensure limits object exists
145
- if (!data.limits) {
146
- data.limits = {};
147
- }
148
-
149
- // Store original limit
150
- if (!data.limits.originalHardCap) {
151
- data.limits.originalHardCap = data.limits.hardCap || 2;
152
- }
153
-
154
- // Set new limit
155
- data.limits.hardCap = parseInt('$new_limit', 10);
156
- data.limits.wipAdjustedAt = new Date().toISOString();
157
-
158
- fs.writeFileSync(path, JSON.stringify(data, null, 2));
159
- "
160
-
161
- echo " ✅ WIP limit adjusted to $new_limit"
162
- echo " ⚠️ Remember to revert after completing one increment!"
163
- echo " 💡 Run: specweave revert-wip-limit"
164
-
165
- return 0
166
- }
167
-
168
- # Force-close increment
169
- force_close() {
170
- local increment_id="$1"
171
-
172
- echo "⚠️ Force-closing $increment_id..."
173
-
174
- local metadata_file="$SPECWEAVE_DIR/increments/$increment_id/metadata.json"
175
-
176
- if [[ ! -f "$metadata_file" ]]; then
177
- echo "❌ Metadata file not found: $metadata_file"
178
- return 1
179
- fi
180
-
181
- node -e "
182
- const fs = require('fs');
183
- const path = '$metadata_file';
184
- const data = JSON.parse(fs.readFileSync(path, 'utf-8'));
185
- data.status = 'completed';
186
- data.completionNote = 'Force-closed to start new increment (WIP limit reached)';
187
- data.completedAt = new Date().toISOString();
188
- data.forceCloseReason = 'wip-limit-reached';
189
- fs.writeFileSync(path, JSON.stringify(data, null, 2));
190
- "
191
-
192
- echo " ✅ $increment_id marked as completed (force-closed)"
193
- echo " ⚠️ Incomplete work was not transferred!"
194
-
195
- return 0
196
- }
197
-
198
- # ============================================================================
199
- # MAIN CLI
200
- # ============================================================================
201
-
202
- case "${1:-}" in
203
- transfer)
204
- if [[ $# -ne 3 ]]; then
205
- echo "Usage: $0 transfer <source_increment> <target_increment>"
206
- exit 0 # SAFETY: Never use exit 1 in hooks
207
- fi
208
- transfer_work "$2" "$3"
209
- ;;
210
-
211
- adjust-wip)
212
- if [[ $# -ne 2 ]]; then
213
- echo "Usage: $0 adjust-wip <new_limit>"
214
- exit 0 # SAFETY: Never use exit 1 in hooks
215
- fi
216
- adjust_wip_limit "$2"
217
- ;;
218
-
219
- force-close)
220
- if [[ $# -ne 2 ]]; then
221
- echo "Usage: $0 force-close <increment_id>"
222
- exit 0 # SAFETY: Never use exit 1 in hooks
223
- fi
224
- force_close "$2"
225
- ;;
226
-
227
- count-incomplete)
228
- if [[ $# -ne 2 ]]; then
229
- echo "Usage: $0 count-incomplete <increment_id>"
230
- exit 0 # SAFETY: Never use exit 1 in hooks
231
- fi
232
- count_incomplete_tasks "$2"
233
- ;;
234
-
235
- *)
236
- echo "SpecWeave Increment Work Migration Utility"
237
- echo ""
238
- echo "Usage:"
239
- echo " $0 transfer <source> <target> # Transfer work from source to target"
240
- echo " $0 adjust-wip <limit> # Adjust WIP limit temporarily"
241
- echo " $0 force-close <increment> # Force-close increment"
242
- echo " $0 count-incomplete <increment> # Count incomplete tasks"
243
- exit 0 # SAFETY: Never use exit 1 in hooks
244
- ;;
245
- esac
@@ -1,146 +0,0 @@
1
- #!/bin/bash
2
- #
3
- # Resolve SpecWeave Package Location
4
- #
5
- # Shared library for hooks to find the specweave package installation.
6
- # This is CRITICAL for hooks to work on user machines where PROJECT_ROOT
7
- # doesn't contain dist/src/cli files.
8
- #
9
- # Usage:
10
- # source "$(dirname "$0")/../lib/resolve-package.sh"
11
- # # Then use $SPECWEAVE_PKG variable
12
- #
13
- # v1.0.71 - Created to fix hooks hanging on user machines
14
-
15
- # =============================================================================
16
- # resolve_specweave_package - Find the specweave npm package location
17
- # =============================================================================
18
- # Searches in this order:
19
- # 1. CLAUDE_PLUGIN_ROOT environment variable (set by Claude Code for plugins)
20
- # 2. Relative to calling script (for hooks inside the package)
21
- # 3. Global npm installation (npm root -g)
22
- # 4. Local npm installation (which specweave)
23
- # =============================================================================
24
-
25
- resolve_specweave_package() {
26
- local caller_dir="${1:-$PWD}"
27
-
28
- # Method 1: CLAUDE_PLUGIN_ROOT (set by Claude Code when running plugin hooks)
29
- if [[ -n "${CLAUDE_PLUGIN_ROOT:-}" ]] && [[ -d "${CLAUDE_PLUGIN_ROOT}/dist/src/cli" ]]; then
30
- echo "$CLAUDE_PLUGIN_ROOT"
31
- return 0
32
- fi
33
-
34
- # Method 2: Walk up from caller directory to find package root
35
- # Handles various depths: hooks/v2/, hooks/lib/, hooks/v2/handlers/, etc.
36
- local search_dir="$caller_dir"
37
- local max_depth=6
38
- local depth=0
39
-
40
- while [[ "$search_dir" != "/" ]] && [[ $depth -lt $max_depth ]]; do
41
- if [[ -d "$search_dir/dist/src/cli" ]] && [[ -f "$search_dir/package.json" ]]; then
42
- # Verify it's actually specweave package
43
- if grep -q '"name": "specweave"' "$search_dir/package.json" 2>/dev/null; then
44
- echo "$search_dir"
45
- return 0
46
- fi
47
- fi
48
- search_dir="$(dirname "$search_dir")"
49
- depth=$((depth + 1))
50
- done
51
-
52
- # Method 3: Global npm installation
53
- local npm_root
54
- npm_root="$(npm root -g 2>/dev/null)"
55
- if [[ -d "$npm_root/specweave/dist/src/cli" ]]; then
56
- echo "$npm_root/specweave"
57
- return 0
58
- fi
59
-
60
- # Method 4: Find via which specweave
61
- local specweave_bin
62
- specweave_bin="$(which specweave 2>/dev/null)"
63
- if [[ -n "$specweave_bin" ]]; then
64
- # Handle symlinks (npm link, volta, etc.)
65
- # Use portable symlink resolution (macOS doesn't have readlink -f)
66
- local real_bin
67
- if command -v realpath >/dev/null 2>&1; then
68
- real_bin="$(realpath "$specweave_bin" 2>/dev/null || echo "$specweave_bin")"
69
- elif command -v greadlink >/dev/null 2>&1; then
70
- real_bin="$(greadlink -f "$specweave_bin" 2>/dev/null || echo "$specweave_bin")"
71
- elif [[ "$(uname)" == "Darwin" ]]; then
72
- # macOS fallback: resolve symlink chain manually
73
- real_bin="$specweave_bin"
74
- while [[ -L "$real_bin" ]]; do
75
- local link_target
76
- link_target="$(readlink "$real_bin")"
77
- if [[ "$link_target" == /* ]]; then
78
- real_bin="$link_target"
79
- else
80
- real_bin="$(dirname "$real_bin")/$link_target"
81
- fi
82
- done
83
- real_bin="$(cd "$(dirname "$real_bin")" && pwd)/$(basename "$real_bin")"
84
- else
85
- real_bin="$(readlink -f "$specweave_bin" 2>/dev/null || echo "$specweave_bin")"
86
- fi
87
- local bin_dir="$(dirname "$real_bin")"
88
- local pkg_dir="$(cd "$bin_dir/.." 2>/dev/null && pwd)"
89
- if [[ -d "$pkg_dir/dist/src/cli" ]]; then
90
- echo "$pkg_dir"
91
- return 0
92
- fi
93
- fi
94
-
95
- # Not found
96
- return 1
97
- }
98
-
99
- # Auto-resolve when sourced (convenience)
100
- # Only set if not already set (allows override)
101
- if [[ -z "${SPECWEAVE_PKG:-}" ]]; then
102
- # Get the directory of the script that sourced this
103
- _RESOLVE_CALLER_DIR="$(cd "$(dirname "${BASH_SOURCE[1]:-${BASH_SOURCE[0]}}")" && pwd)"
104
- SPECWEAVE_PKG="$(resolve_specweave_package "$_RESOLVE_CALLER_DIR")"
105
- export SPECWEAVE_PKG
106
- fi
107
-
108
- # =============================================================================
109
- # find_specweave_script - Find a script file in the specweave package
110
- # =============================================================================
111
- # Usage: find_specweave_script "dist/src/cli/register-session.js"
112
- # Returns: Full path if found, empty string otherwise
113
- # =============================================================================
114
-
115
- find_specweave_script() {
116
- local script_path="$1"
117
-
118
- if [[ -n "$SPECWEAVE_PKG" ]] && [[ -f "$SPECWEAVE_PKG/$script_path" ]]; then
119
- echo "$SPECWEAVE_PKG/$script_path"
120
- return 0
121
- fi
122
-
123
- return 1
124
- }
125
-
126
- # =============================================================================
127
- # run_specweave_cli - Run a CLI script from the specweave package
128
- # =============================================================================
129
- # Usage: run_specweave_cli "dist/src/cli/register-session.js" arg1 arg2
130
- # Returns: Exit code from node, or 1 if script not found
131
- # =============================================================================
132
-
133
- run_specweave_cli() {
134
- local script_path="$1"
135
- shift
136
-
137
- local full_path
138
- full_path="$(find_specweave_script "$script_path")"
139
-
140
- if [[ -z "$full_path" ]]; then
141
- echo "ERROR: Script not found: $script_path" >&2
142
- return 1
143
- fi
144
-
145
- node "$full_path" "$@"
146
- }
@@ -1,135 +0,0 @@
1
- #!/bin/bash
2
- # scheduler-startup.sh - Execute due sync jobs on session start
3
- # Called from session-start hook to run overdue scheduled jobs
4
- #
5
- # This implements the "pragmatic hybrid" approach:
6
- # - No background daemon required
7
- # - Sync runs at Claude Code session boundaries
8
- # - Respects permission gates (canUpdateExternalItems, etc.)
9
- #
10
- # CRITICAL (v0.28.70): NEVER use 'set -e' in hooks - causes Claude Code crashes
11
- set +e
12
-
13
- # Skip if hooks disabled
14
- [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
15
-
16
- # Find project root
17
- PROJECT_ROOT="$PWD"
18
- while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
19
- PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
20
- done
21
-
22
- # Exit if no .specweave/config.json
23
- [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
24
-
25
- # Source resolve-package.sh for dynamic specweave path resolution
26
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
27
- if [[ -f "$SCRIPT_DIR/resolve-package.sh" ]]; then
28
- source "$SCRIPT_DIR/resolve-package.sh"
29
- fi
30
-
31
- # Paths
32
- SCHEDULED_JOBS_FILE="$PROJECT_ROOT/.specweave/state/scheduled-jobs.json"
33
- CONFIG_FILE="$PROJECT_ROOT/.specweave/config.json"
34
- LOG_FILE="$PROJECT_ROOT/.specweave/logs/scheduler.log"
35
-
36
- # Ensure logs directory exists
37
- mkdir -p "$PROJECT_ROOT/.specweave/logs" 2>/dev/null || true
38
-
39
- # Check if scheduler is enabled
40
- if [[ -f "$CONFIG_FILE" ]]; then
41
- # Check if sync.orchestration.scheduler.enabled is true
42
- SCHEDULER_ENABLED=$(node -e "
43
- try {
44
- const config = require('$CONFIG_FILE');
45
- const enabled = config?.sync?.orchestration?.scheduler?.enabled ?? false;
46
- console.log(enabled ? 'true' : 'false');
47
- } catch(e) {
48
- console.log('false');
49
- }
50
- " 2>/dev/null || echo "false")
51
-
52
- if [[ "$SCHEDULER_ENABLED" != "true" ]]; then
53
- exit 0
54
- fi
55
-
56
- # Check autoSyncOnSessionStart (defaults to true)
57
- AUTO_SYNC=$(node -e "
58
- try {
59
- const config = require('$CONFIG_FILE');
60
- const auto = config?.sync?.orchestration?.scheduler?.autoSyncOnSessionStart ?? true;
61
- console.log(auto ? 'true' : 'false');
62
- } catch(e) {
63
- console.log('true');
64
- }
65
- " 2>/dev/null || echo "true")
66
-
67
- if [[ "$AUTO_SYNC" != "true" ]]; then
68
- exit 0
69
- fi
70
- fi
71
-
72
- # Check if scheduled jobs file exists
73
- if [[ ! -f "$SCHEDULED_JOBS_FILE" ]]; then
74
- exit 0
75
- fi
76
-
77
- # Use node to check for due jobs (robust JSON parsing)
78
- DUE_JOBS=$(node -e "
79
- const fs = require('fs');
80
- try {
81
- const data = JSON.parse(fs.readFileSync('$SCHEDULED_JOBS_FILE', 'utf-8'));
82
- const now = Date.now();
83
- const dueJobs = (data.jobs || []).filter(job => {
84
- if (!job.schedule.enabled || job.status !== 'idle') return false;
85
- if (!job.schedule.nextRun) return true;
86
- return new Date(job.schedule.nextRun).getTime() <= now;
87
- });
88
- console.log(JSON.stringify(dueJobs.map(j => j.id)));
89
- } catch(e) {
90
- console.log('[]');
91
- }
92
- " 2>/dev/null || echo "[]")
93
-
94
- # Exit if no due jobs
95
- if [[ "$DUE_JOBS" == "[]" ]]; then
96
- exit 0
97
- fi
98
-
99
- # Log due jobs
100
- TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
101
- echo "[$TIMESTAMP] Session start - due jobs: $DUE_JOBS" >> "$LOG_FILE" 2>/dev/null || true
102
-
103
- # Execute due sync jobs using the TypeScript executor
104
- # Resolve executor path via resolve-package.sh (not hardcoded node_modules)
105
- EXECUTOR_PATH=$(find_specweave_script "dist/src/core/scheduler/session-sync-executor.js" 2>/dev/null)
106
- if [[ -z "$EXECUTOR_PATH" ]]; then
107
- echo '{"error":"Executor not found — specweave package not resolved"}' >> "$LOG_FILE" 2>/dev/null || true
108
- exit 0
109
- fi
110
-
111
- RESULT=$(node -e "
112
- const { executeSessionSync } = require('$EXECUTOR_PATH');
113
- executeSessionSync('$PROJECT_ROOT', { silent: false })
114
- .then(r => console.log(r))
115
- .catch(e => console.log(JSON.stringify({ error: e.message })));
116
- " 2>&1) || RESULT='{"error":"Executor not found"}'
117
-
118
- # Log result
119
- echo "[$TIMESTAMP] Execution result: $RESULT" >> "$LOG_FILE" 2>/dev/null || true
120
-
121
- # Parse result for system message
122
- EXECUTED_COUNT=$(echo "$RESULT" | node -e "
123
- const data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf-8'));
124
- console.log(data.executedCount || 0);
125
- " 2>/dev/null || echo "0")
126
-
127
- SUCCESS_COUNT=$(echo "$RESULT" | node -e "
128
- const data = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf-8'));
129
- console.log(data.successCount || 0);
130
- " 2>/dev/null || echo "0")
131
-
132
- # Output status message if jobs were executed
133
- if [[ "$EXECUTED_COUNT" != "0" ]]; then
134
- echo "{\"continue\": true, \"systemMessage\": \"📅 Session sync: $SUCCESS_COUNT/$EXECUTED_COUNT sync jobs executed successfully.\"}"
135
- fi
@@ -1,87 +0,0 @@
1
- #!/bin/bash
2
- # score-increment.sh — Score an increment against a text query using keyword overlap.
3
- #
4
- # Usage: score-increment.sh <increment_dir> <query>
5
- # Output: integer 0-100 (higher = better match)
6
- #
7
- # Corpus: increment directory name + metadata title + spec.md overview + task titles
8
-
9
- set -e
10
-
11
- INCREMENT_DIR="$1"
12
- QUERY="$2"
13
-
14
- if [ -z "$INCREMENT_DIR" ] || [ -z "$QUERY" ]; then
15
- echo "0"
16
- exit 0
17
- fi
18
-
19
- if [ ! -d "$INCREMENT_DIR" ]; then
20
- echo "0"
21
- exit 0
22
- fi
23
-
24
- # Build corpus from multiple sources
25
- CORPUS=""
26
-
27
- # 1. Directory name (e.g. "0257-auto-context-aware-selection" → words)
28
- DIR_NAME=$(basename "$INCREMENT_DIR")
29
- CORPUS="$CORPUS ${DIR_NAME//-/ }"
30
-
31
- # 2. Title from metadata.json
32
- META_FILE="$INCREMENT_DIR/metadata.json"
33
- if [ -f "$META_FILE" ]; then
34
- TITLE=$(jq -r '.title // .name // ""' "$META_FILE" 2>/dev/null || echo "")
35
- CORPUS="$CORPUS $TITLE"
36
- fi
37
-
38
- # 3. First 500 chars of spec.md (overview/problem statement)
39
- SPEC_FILE="$INCREMENT_DIR/spec.md"
40
- if [ -f "$SPEC_FILE" ]; then
41
- OVERVIEW=$(head -c 500 "$SPEC_FILE" 2>/dev/null || echo "")
42
- CORPUS="$CORPUS $OVERVIEW"
43
- fi
44
-
45
- # 4. Task titles from tasks.md (lines starting with ### T-)
46
- TASKS_FILE="$INCREMENT_DIR/tasks.md"
47
- if [ -f "$TASKS_FILE" ]; then
48
- TASK_TITLES=$(grep '^### T-' "$TASKS_FILE" 2>/dev/null | sed 's/^### T-[0-9]*: //' || echo "")
49
- CORPUS="$CORPUS $TASK_TITLES"
50
- fi
51
-
52
- # Normalize corpus: lowercase, non-alphanumeric → space
53
- CORPUS_LC=$(echo "$CORPUS" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' ' ')
54
-
55
- # Extract unique query keywords: lowercase, length > 2, skip common stopwords
56
- STOPWORDS="the and for with from that this are was were has have been will not"
57
- KEYWORDS=$(echo "$QUERY" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '\n' | \
58
- awk 'length > 2' | \
59
- grep -vxF -e "the" -e "and" -e "for" -e "with" -e "from" -e "that" -e "this" \
60
- -e "are" -e "was" -e "were" -e "has" -e "have" -e "been" -e "will" \
61
- -e "not" -e "into" -e "use" -e "its" | \
62
- sort -u)
63
-
64
- if [ -z "$KEYWORDS" ]; then
65
- echo "0"
66
- exit 0
67
- fi
68
-
69
- # Count matches
70
- TOTAL=0
71
- MATCHED=0
72
- while IFS= read -r keyword; do
73
- [ -z "$keyword" ] && continue
74
- TOTAL=$((TOTAL + 1))
75
- if echo "$CORPUS_LC" | grep -qw "$keyword" 2>/dev/null; then
76
- MATCHED=$((MATCHED + 1))
77
- fi
78
- done <<< "$KEYWORDS"
79
-
80
- if [ "$TOTAL" -eq 0 ]; then
81
- echo "0"
82
- exit 0
83
- fi
84
-
85
- # Score = matched_keywords / total_keywords * 100
86
- SCORE=$(( MATCHED * 100 / TOTAL ))
87
- echo "$SCORE"