specweave 1.0.550 → 1.0.552
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +1 -1
- package/bin/specweave.js +23 -1
- package/dist/src/cli/commands/hook.d.ts +15 -0
- package/dist/src/cli/commands/hook.d.ts.map +1 -0
- package/dist/src/cli/commands/hook.js +61 -0
- package/dist/src/cli/commands/hook.js.map +1 -0
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +5 -0
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.d.ts.map +1 -1
- package/dist/src/cli/commands/refresh-plugins.js +11 -1
- package/dist/src/cli/commands/refresh-plugins.js.map +1 -1
- package/dist/src/cli/commands/sync-setup.d.ts.map +1 -1
- package/dist/src/cli/commands/sync-setup.js +7 -3
- package/dist/src/cli/commands/sync-setup.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts +9 -0
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.d.ts.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js +9 -3
- package/dist/src/cli/helpers/issue-tracker/project-mapping-wizard.js.map +1 -1
- package/dist/src/config/types.d.ts +2 -2
- package/dist/src/core/config/types.d.ts +18 -2
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/hooks/handlers/hook-router.d.ts +19 -0
- package/dist/src/core/hooks/handlers/hook-router.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/hook-router.js +75 -0
- package/dist/src/core/hooks/handlers/hook-router.js.map +1 -0
- package/dist/src/core/hooks/handlers/index.d.ts +10 -0
- package/dist/src/core/hooks/handlers/index.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/index.js +9 -0
- package/dist/src/core/hooks/handlers/index.js.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts +11 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js +73 -0
- package/dist/src/core/hooks/handlers/post-tool-use-analytics.js.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts +11 -0
- package/dist/src/core/hooks/handlers/post-tool-use.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/post-tool-use.js +76 -0
- package/dist/src/core/hooks/handlers/post-tool-use.js.map +1 -0
- package/dist/src/core/hooks/handlers/pre-compact.d.ts +11 -0
- package/dist/src/core/hooks/handlers/pre-compact.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/pre-compact.js +77 -0
- package/dist/src/core/hooks/handlers/pre-compact.js.map +1 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.d.ts +11 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.js +318 -0
- package/dist/src/core/hooks/handlers/pre-tool-use.js.map +1 -0
- package/dist/src/core/hooks/handlers/session-start.d.ts +9 -0
- package/dist/src/core/hooks/handlers/session-start.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/session-start.js +111 -0
- package/dist/src/core/hooks/handlers/session-start.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-auto.d.ts +16 -0
- package/dist/src/core/hooks/handlers/stop-auto.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-auto.js +122 -0
- package/dist/src/core/hooks/handlers/stop-auto.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts +14 -0
- package/dist/src/core/hooks/handlers/stop-reflect.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-reflect.js +43 -0
- package/dist/src/core/hooks/handlers/stop-reflect.js.map +1 -0
- package/dist/src/core/hooks/handlers/stop-sync.d.ts +15 -0
- package/dist/src/core/hooks/handlers/stop-sync.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/stop-sync.js +68 -0
- package/dist/src/core/hooks/handlers/stop-sync.js.map +1 -0
- package/dist/src/core/hooks/handlers/types.d.ts +63 -0
- package/dist/src/core/hooks/handlers/types.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/types.js +27 -0
- package/dist/src/core/hooks/handlers/types.js.map +1 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts +14 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.js +173 -0
- package/dist/src/core/hooks/handlers/user-prompt-submit.js.map +1 -0
- package/dist/src/core/hooks/handlers/utils.d.ts +25 -0
- package/dist/src/core/hooks/handlers/utils.d.ts.map +1 -0
- package/dist/src/core/hooks/handlers/utils.js +64 -0
- package/dist/src/core/hooks/handlers/utils.js.map +1 -0
- package/dist/src/core/increment/completion-validator.d.ts.map +1 -1
- package/dist/src/core/increment/completion-validator.js +32 -0
- package/dist/src/core/increment/completion-validator.js.map +1 -1
- package/dist/src/init/research/types.d.ts +1 -1
- package/dist/src/sync/sync-target-resolver.js.map +1 -1
- package/dist/src/utils/lock-manager.d.ts.map +1 -1
- package/dist/src/utils/lock-manager.js +5 -0
- package/dist/src/utils/lock-manager.js.map +1 -1
- package/dist/src/utils/plugin-copier.d.ts +10 -0
- package/dist/src/utils/plugin-copier.d.ts.map +1 -1
- package/dist/src/utils/plugin-copier.js +63 -35
- package/dist/src/utils/plugin-copier.js.map +1 -1
- package/package.json +1 -1
- package/plugins/specweave/agents/sw-closer.md +3 -2
- package/plugins/specweave/hooks/hooks.json +10 -10
- package/plugins/specweave/skills/code-reviewer/SKILL.md +180 -16
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-comments.md +83 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-silent-failures.md +19 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-spec-compliance.md +19 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-tests.md +101 -0
- package/plugins/specweave/skills/code-reviewer/agents/reviewer-types.md +20 -0
- package/plugins/specweave/skills/done/SKILL.md +56 -21
- package/plugins/specweave/skills/grill/SKILL.md +1 -1
- package/plugins/specweave/skills/team-lead/agents/reviewer-logic.md +19 -0
- package/plugins/specweave/skills/team-lead/agents/reviewer-performance.md +20 -0
- package/plugins/specweave/skills/team-lead/agents/reviewer-security.md +20 -0
- package/src/templates/CLAUDE.md.template +7 -4
- package/plugins/specweave/hooks/README.md +0 -493
- package/plugins/specweave/hooks/_archive/stop-auto-v4-legacy.sh +0 -1319
- package/plugins/specweave/hooks/lib/common-setup.sh +0 -144
- package/plugins/specweave/hooks/lib/hook-errors.sh +0 -414
- package/plugins/specweave/hooks/lib/migrate-increment-work.sh +0 -245
- package/plugins/specweave/hooks/lib/resolve-package.sh +0 -146
- package/plugins/specweave/hooks/lib/scheduler-startup.sh +0 -135
- package/plugins/specweave/hooks/lib/score-increment.sh +0 -87
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +0 -193
- package/plugins/specweave/hooks/lib/update-active-increment.sh +0 -95
- package/plugins/specweave/hooks/lib/update-status-line.sh +0 -233
- package/plugins/specweave/hooks/lib/validate-spec-status.sh +0 -171
- package/plugins/specweave/hooks/llm-judge-validator.sh +0 -219
- package/plugins/specweave/hooks/log-decision.sh +0 -168
- package/plugins/specweave/hooks/pre-compact.sh +0 -64
- package/plugins/specweave/hooks/startup-health-check.sh +0 -64
- package/plugins/specweave/hooks/stop-auto-v5.sh +0 -276
- package/plugins/specweave/hooks/stop-reflect.sh +0 -336
- package/plugins/specweave/hooks/stop-sync.sh +0 -283
- package/plugins/specweave/hooks/tests/test-auto-context-integration.sh +0 -126
- package/plugins/specweave/hooks/tests/test-stop-auto-enriched.sh +0 -128
- package/plugins/specweave/hooks/universal/dispatcher.mjs +0 -336
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +0 -325
- package/plugins/specweave/hooks/universal/hook-wrapper.cmd +0 -26
- package/plugins/specweave/hooks/universal/hook-wrapper.sh +0 -69
- package/plugins/specweave/hooks/universal/run-hook.sh +0 -20
- package/plugins/specweave/hooks/universal/session-start.cmd +0 -16
- package/plugins/specweave/hooks/universal/session-start.ps1 +0 -16
- package/plugins/specweave/hooks/user-prompt-submit.sh +0 -2550
- package/plugins/specweave/hooks/v2/detectors/lifecycle-detector.sh +0 -87
- package/plugins/specweave/hooks/v2/detectors/us-completion-detector.sh +0 -186
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use-analytics.sh +0 -83
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +0 -447
- package/plugins/specweave/hooks/v2/dispatchers/pre-tool-use.sh +0 -104
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +0 -270
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/increment-existence-guard.sh +0 -240
- package/plugins/specweave/hooks/v2/guards/interview-enforcement-guard.sh +0 -171
- package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/skill-chain-enforcement-guard.sh +0 -222
- package/plugins/specweave/hooks/v2/guards/spec-template-enforcement-guard.sh +0 -21
- package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +0 -14
- package/plugins/specweave/hooks/v2/guards/status-completion-guard.sh +0 -84
- package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +0 -475
- package/plugins/specweave/hooks/v2/guards/tdd-enforcement-guard.sh +0 -268
- package/plugins/specweave/hooks/v2/handlers/ac-sync-dispatcher.sh +0 -332
- package/plugins/specweave/hooks/v2/handlers/ac-validation-handler.sh +0 -50
- package/plugins/specweave/hooks/v2/handlers/github-sync-handler.sh +0 -347
- package/plugins/specweave/hooks/v2/handlers/living-docs-handler.sh +0 -83
- package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +0 -268
- package/plugins/specweave/hooks/v2/handlers/project-bridge-handler.sh +0 -104
- package/plugins/specweave/hooks/v2/handlers/status-line-handler.sh +0 -165
- package/plugins/specweave/hooks/v2/handlers/status-update.sh +0 -61
- package/plugins/specweave/hooks/v2/handlers/universal-auto-create-dispatcher.sh +0 -270
- package/plugins/specweave/hooks/v2/integrations/ado-post-living-docs-update.sh +0 -367
- package/plugins/specweave/hooks/v2/integrations/ado-post-task.sh +0 -179
- package/plugins/specweave/hooks/v2/integrations/github-auto-create-handler.sh +0 -553
- package/plugins/specweave/hooks/v2/integrations/github-post-task.sh +0 -345
- package/plugins/specweave/hooks/v2/integrations/jira-post-task.sh +0 -180
- package/plugins/specweave/hooks/v2/lib/check-provider-enabled.sh +0 -52
- package/plugins/specweave/hooks/v2/queue/enqueue.sh +0 -81
- package/plugins/specweave/hooks/v2/session-end.sh +0 -139
- package/plugins/specweave/hooks/validate-skill-activations.sh +0 -227
|
@@ -1,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"
|