specweave 0.30.19 → 0.32.2
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 +176 -2
- package/README.md +22 -0
- package/bin/specweave.js +18 -1
- package/dist/src/cli/commands/cache.d.ts +17 -0
- package/dist/src/cli/commands/cache.d.ts.map +1 -0
- package/dist/src/cli/commands/cache.js +126 -0
- package/dist/src/cli/commands/cache.js.map +1 -0
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/plan/increment-detector.js +2 -2
- package/dist/src/cli/commands/plan/increment-detector.js.map +1 -1
- package/dist/src/cli/commands/sync-spec-commits.js +1 -1
- package/dist/src/cli/commands/sync-spec-commits.js.map +1 -1
- package/dist/src/cli/commands/sync-specs.js +2 -2
- package/dist/src/cli/commands/sync-specs.js.map +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.js +1 -1
- package/dist/src/cli/helpers/github/increment-profile-selector.js.map +1 -1
- package/dist/src/cli/workers/living-docs-worker.js +66 -1
- package/dist/src/cli/workers/living-docs-worker.js.map +1 -1
- package/dist/src/config/types.d.ts +203 -1208
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -1
- package/dist/src/core/discrepancy/increment-generator.js +5 -2
- package/dist/src/core/discrepancy/increment-generator.js.map +1 -1
- package/dist/src/core/external-tools/external-items-counter.d.ts +62 -0
- package/dist/src/core/external-tools/external-items-counter.d.ts.map +1 -0
- package/dist/src/core/external-tools/external-items-counter.js +206 -0
- package/dist/src/core/external-tools/external-items-counter.js.map +1 -0
- package/dist/src/core/external-tools/external-items-display.d.ts +39 -0
- package/dist/src/core/external-tools/external-items-display.d.ts.map +1 -0
- package/dist/src/core/external-tools/external-items-display.js +185 -0
- package/dist/src/core/external-tools/external-items-display.js.map +1 -0
- package/dist/src/core/external-tools/index.d.ts +8 -0
- package/dist/src/core/external-tools/index.d.ts.map +1 -0
- package/dist/src/core/external-tools/index.js +8 -0
- package/dist/src/core/external-tools/index.js.map +1 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.d.ts +39 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.js +188 -0
- package/dist/src/core/external-tools/providers/ado-items-adapter.js.map +1 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.d.ts +38 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.js +136 -0
- package/dist/src/core/external-tools/providers/github-items-adapter.js.map +1 -0
- package/dist/src/core/external-tools/providers/index.d.ts +7 -0
- package/dist/src/core/external-tools/providers/index.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/index.js +7 -0
- package/dist/src/core/external-tools/providers/index.js.map +1 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.d.ts +42 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.d.ts.map +1 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.js +153 -0
- package/dist/src/core/external-tools/providers/jira-items-adapter.js.map +1 -0
- package/dist/src/core/external-tools/types.d.ts +78 -0
- package/dist/src/core/external-tools/types.d.ts.map +1 -0
- package/dist/src/core/external-tools/types.js +19 -0
- package/dist/src/core/external-tools/types.js.map +1 -0
- package/dist/src/core/increment/duplicate-detector.js +2 -2
- package/dist/src/core/increment/duplicate-detector.js.map +1 -1
- package/dist/src/core/increment/increment-archiver.d.ts +24 -0
- package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
- package/dist/src/core/increment/increment-archiver.js +59 -2
- package/dist/src/core/increment/increment-archiver.js.map +1 -1
- package/dist/src/core/increment/increment-status.js +2 -2
- package/dist/src/core/increment/increment-status.js.map +1 -1
- package/dist/src/core/increment/increment-utils.d.ts +98 -37
- package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
- package/dist/src/core/increment/increment-utils.js +119 -68
- package/dist/src/core/increment/increment-utils.js.map +1 -1
- package/dist/src/core/increment/metadata-validator.js +1 -1
- package/dist/src/core/increment/metadata-validator.js.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.d.ts.map +1 -1
- package/dist/src/core/increment/status-change-sync-trigger.js +4 -0
- package/dist/src/core/increment/status-change-sync-trigger.js.map +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js +1 -1
- package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
- package/dist/src/core/living-docs/hierarchy-mapper.js +3 -3
- package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts +18 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +247 -0
- package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts +15 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js +138 -0
- package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts +24 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js +198 -0
- package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts +17 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js +241 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts +28 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.js +197 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts +18 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +154 -0
- package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts +42 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js +343 -0
- package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +146 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.js +7 -0
- package/dist/src/core/living-docs/intelligent-analyzer/types.js.map +1 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts +5 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +36 -2
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/llm/providers/azure-openai-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/azure-openai-provider.js +1 -0
- package/dist/src/core/llm/providers/azure-openai-provider.js.map +1 -1
- package/dist/src/core/llm/providers/bedrock-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/bedrock-provider.js +2 -0
- package/dist/src/core/llm/providers/bedrock-provider.js.map +1 -1
- package/dist/src/core/llm/providers/openai-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/openai-provider.js +1 -0
- package/dist/src/core/llm/providers/openai-provider.js.map +1 -1
- package/dist/src/core/llm/providers/vertex-ai-provider.d.ts.map +1 -1
- package/dist/src/core/llm/providers/vertex-ai-provider.js +1 -0
- package/dist/src/core/llm/providers/vertex-ai-provider.js.map +1 -1
- package/dist/src/core/sync/spec-increment-mapper.js +3 -3
- package/dist/src/core/sync/spec-increment-mapper.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +25 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +135 -5
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/init/architecture/types.d.ts +33 -140
- package/dist/src/init/architecture/types.d.ts.map +1 -1
- package/dist/src/init/compliance/types.d.ts +30 -27
- package/dist/src/init/compliance/types.d.ts.map +1 -1
- package/dist/src/init/repo/types.d.ts +11 -34
- package/dist/src/init/repo/types.d.ts.map +1 -1
- package/dist/src/init/research/src/config/types.d.ts +15 -82
- package/dist/src/init/research/src/config/types.d.ts.map +1 -1
- package/dist/src/init/research/types.d.ts +38 -93
- package/dist/src/init/research/types.d.ts.map +1 -1
- package/dist/src/init/team/types.d.ts +4 -42
- package/dist/src/init/team/types.d.ts.map +1 -1
- package/dist/src/types/dashboard-cache.d.ts +181 -0
- package/dist/src/types/dashboard-cache.d.ts.map +1 -0
- package/dist/src/types/dashboard-cache.js +65 -0
- package/dist/src/types/dashboard-cache.js.map +1 -0
- package/dist/src/utils/docs-validator.d.ts +131 -0
- package/dist/src/utils/docs-validator.d.ts.map +1 -0
- package/dist/src/utils/docs-validator.js +529 -0
- package/dist/src/utils/docs-validator.js.map +1 -0
- package/dist/src/utils/feature-id-collision.js +1 -1
- package/dist/src/utils/feature-id-collision.js.map +1 -1
- package/dist/src/utils/html-to-mdx.d.ts +1 -0
- package/dist/src/utils/html-to-mdx.d.ts.map +1 -1
- package/dist/src/utils/html-to-mdx.js +43 -5
- package/dist/src/utils/html-to-mdx.js.map +1 -1
- package/package.json +1 -5
- package/plugins/specweave/agents/pm/AGENT.md +10 -7
- package/plugins/specweave/commands/specweave-archive-features.md +5 -7
- package/plugins/specweave/commands/specweave-archive.md +2 -1
- package/plugins/specweave/commands/specweave-do.md +35 -1
- package/plugins/specweave/commands/specweave-done.md +96 -0
- package/plugins/specweave/commands/specweave-external.md +150 -0
- package/plugins/specweave/commands/specweave-import-external.md +45 -18
- package/plugins/specweave/commands/specweave-increment.md +331 -33
- package/plugins/specweave/commands/specweave-jobs.md +2 -2
- package/plugins/specweave/commands/specweave-progress.md +4 -4
- package/plugins/specweave/commands/specweave-restore-feature.md +5 -4
- package/plugins/specweave/commands/specweave-sync-docs.md +1 -1
- package/plugins/specweave/commands/specweave-sync-specs.md +216 -322
- package/plugins/specweave/commands/specweave-validate-features.md +13 -8
- package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
- package/plugins/specweave/hooks/hooks.json +33 -4
- package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
- package/plugins/specweave/hooks/lib/common-setup.sh +375 -0
- package/plugins/specweave/hooks/lib/crash-prevention.sh +336 -0
- package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
- package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
- package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
- package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
- package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
- package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
- package/plugins/specweave/hooks/post-task-completion.sh +4 -23
- package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
- package/plugins/specweave/hooks/pre-command-deduplication.sh +1 -6
- package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
- package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
- package/plugins/specweave/hooks/pre-task-completion.sh +8 -37
- package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
- package/plugins/specweave/hooks/pre-tool-use.sh +2 -11
- package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
- package/plugins/specweave/hooks/universal/dispatcher.mjs +135 -42
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +183 -0
- package/plugins/specweave/hooks/universal/hook-wrapper.cmd +26 -26
- package/plugins/specweave/hooks/universal/session-start.cmd +16 -16
- package/plugins/specweave/hooks/universal/session-start.ps1 +16 -16
- package/plugins/specweave/hooks/user-prompt-submit.sh +140 -38
- package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +12 -0
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +89 -0
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.sh +211 -0
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.test.sh +163 -0
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +26 -28
- package/plugins/specweave/hooks/v2/guards/features-folder-guard.sh +50 -0
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +2 -2
- package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -1
- package/plugins/specweave/scripts/README.md +166 -0
- package/plugins/specweave/scripts/cleanup-state.sh +142 -0
- package/plugins/specweave/scripts/force-kill.sh +142 -0
- package/plugins/specweave/scripts/jobs.js +171 -0
- package/plugins/specweave/scripts/progress.js +170 -0
- package/plugins/specweave/scripts/read-costs.sh +132 -0
- package/plugins/specweave/scripts/read-jobs.sh +324 -0
- package/plugins/specweave/scripts/read-progress.sh +185 -0
- package/plugins/specweave/scripts/read-status.sh +146 -0
- package/plugins/specweave/scripts/read-workflow.sh +173 -0
- package/plugins/specweave/scripts/rebuild-dashboard-cache.sh +327 -0
- package/plugins/specweave/scripts/session-watchdog.sh +192 -0
- package/plugins/specweave/scripts/status.js +154 -0
- package/plugins/specweave/scripts/update-dashboard-cache.sh +281 -0
- package/plugins/specweave/skills/increment-planner/SKILL.md +333 -24
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +17 -9
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +6 -2
- package/plugins/specweave/skills/instant-status/SKILL.md +70 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
- package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
- package/plugins/specweave-docs/commands/build.md +32 -4
- package/plugins/specweave-docs/commands/preview.md +43 -1
- package/plugins/specweave-docs/commands/validate.md +250 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1262 -626
- package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
- package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
- package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
- package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1254 -939
- package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
- package/plugins/specweave/hooks/post-edit-spec.sh +0 -265
- package/plugins/specweave/hooks/post-write-spec.sh +0 -267
- package/plugins/specweave/hooks/pre-edit-spec.sh +0 -151
- package/plugins/specweave/hooks/pre-write-spec.sh +0 -151
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# crash-prevention.sh - Unified Crash Prevention Runtime
|
|
3
|
+
#
|
|
4
|
+
# Consolidates ALL crash prevention patterns from 9 crash categories:
|
|
5
|
+
# 1. Bash heredoc hangs (infinite wait for EOF)
|
|
6
|
+
# 2. Context explosion (>280KB total)
|
|
7
|
+
# 3. Hook recursion loops
|
|
8
|
+
# 4. Process storms (bulk operations)
|
|
9
|
+
# 5. Agent chunking violations
|
|
10
|
+
# 6. Direct completion bypass
|
|
11
|
+
# 7. Hook registration duplicates
|
|
12
|
+
# 8. Context compaction deadlock
|
|
13
|
+
# 9. MCP connection drops
|
|
14
|
+
#
|
|
15
|
+
# This is the SINGLE SOURCE OF TRUTH for crash prevention.
|
|
16
|
+
# Consolidated from ADRs: 0060, 0068, 0073, 0127, 0128, 0130, 0133, 0157, 0189
|
|
17
|
+
#
|
|
18
|
+
# v0.33.0 - Initial consolidation
|
|
19
|
+
|
|
20
|
+
set +e
|
|
21
|
+
|
|
22
|
+
# ============================================================================
|
|
23
|
+
# CRASH CATEGORY 1: BASH HEREDOC DETECTION
|
|
24
|
+
# ============================================================================
|
|
25
|
+
|
|
26
|
+
# Patterns that cause INFINITE HANGS (shell waits forever for EOF)
|
|
27
|
+
detect_bash_hang_pattern() {
|
|
28
|
+
local command="$1"
|
|
29
|
+
|
|
30
|
+
# Heredoc patterns (MOST DANGEROUS)
|
|
31
|
+
if echo "$command" | grep -qE "<<-?[[:space:]]*['\"]?[A-Za-z_]+" 2>/dev/null; then
|
|
32
|
+
echo "heredoc"
|
|
33
|
+
return 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Cat stdin redirect (waits forever)
|
|
37
|
+
if echo "$command" | grep -qE "^[[:space:]]*cat[[:space:]]+>[[:space:]]*[^>]" 2>/dev/null; then
|
|
38
|
+
echo "cat-stdin"
|
|
39
|
+
return 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# DD command with output file
|
|
43
|
+
if echo "$command" | grep -qE "^[[:space:]]*dd[[:space:]].*of=" 2>/dev/null; then
|
|
44
|
+
echo "dd-stdin"
|
|
45
|
+
return 0
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# Echo/printf to file (truncation risk)
|
|
49
|
+
if echo "$command" | grep -qE "^[[:space:]]*(echo|printf)[[:space:]]" 2>/dev/null; then
|
|
50
|
+
if echo "$command" | grep -qE '>[[:space:]]*[^>]' 2>/dev/null; then
|
|
51
|
+
if ! echo "$command" | grep -qE '>>' 2>/dev/null; then
|
|
52
|
+
echo "echo-redirect"
|
|
53
|
+
return 0
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
return 1
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# ============================================================================
|
|
62
|
+
# CRASH CATEGORY 2: CONTEXT BUDGET ESTIMATION
|
|
63
|
+
# ============================================================================
|
|
64
|
+
|
|
65
|
+
# Rough token estimation (1 token ≈ 4 chars)
|
|
66
|
+
estimate_tokens() {
|
|
67
|
+
local file="$1"
|
|
68
|
+
if [[ -f "$file" ]]; then
|
|
69
|
+
local chars
|
|
70
|
+
chars=$(wc -c < "$file" 2>/dev/null || echo "0")
|
|
71
|
+
echo $((chars / 4))
|
|
72
|
+
else
|
|
73
|
+
echo "0"
|
|
74
|
+
fi
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# Check if context is in danger zone
|
|
78
|
+
check_context_budget() {
|
|
79
|
+
local project_root="$1"
|
|
80
|
+
local active_increment="$2"
|
|
81
|
+
|
|
82
|
+
local total_tokens=0
|
|
83
|
+
local warning_threshold=150000 # ~150K tokens
|
|
84
|
+
local danger_threshold=200000 # ~200K tokens
|
|
85
|
+
|
|
86
|
+
# Estimate increment context
|
|
87
|
+
if [[ -n "$active_increment" ]] && [[ -d "$project_root/.specweave/increments/$active_increment" ]]; then
|
|
88
|
+
local inc_dir="$project_root/.specweave/increments/$active_increment"
|
|
89
|
+
|
|
90
|
+
local spec_tokens=$(estimate_tokens "$inc_dir/spec.md")
|
|
91
|
+
local plan_tokens=$(estimate_tokens "$inc_dir/plan.md")
|
|
92
|
+
local tasks_tokens=$(estimate_tokens "$inc_dir/tasks.md")
|
|
93
|
+
|
|
94
|
+
total_tokens=$((spec_tokens + plan_tokens + tasks_tokens))
|
|
95
|
+
fi
|
|
96
|
+
|
|
97
|
+
# Return status
|
|
98
|
+
if [[ $total_tokens -gt $danger_threshold ]]; then
|
|
99
|
+
echo "DANGER:$total_tokens"
|
|
100
|
+
return 2
|
|
101
|
+
elif [[ $total_tokens -gt $warning_threshold ]]; then
|
|
102
|
+
echo "WARNING:$total_tokens"
|
|
103
|
+
return 1
|
|
104
|
+
else
|
|
105
|
+
echo "OK:$total_tokens"
|
|
106
|
+
return 0
|
|
107
|
+
fi
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Count tasks in active increment
|
|
111
|
+
count_increment_tasks() {
|
|
112
|
+
local project_root="$1"
|
|
113
|
+
local active_increment="$2"
|
|
114
|
+
|
|
115
|
+
local tasks_file="$project_root/.specweave/increments/$active_increment/tasks.md"
|
|
116
|
+
if [[ -f "$tasks_file" ]]; then
|
|
117
|
+
grep -c "^### T-" "$tasks_file" 2>/dev/null || echo "0"
|
|
118
|
+
else
|
|
119
|
+
echo "0"
|
|
120
|
+
fi
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# ============================================================================
|
|
124
|
+
# CRASH CATEGORY 3: PROCESS STORM DETECTION
|
|
125
|
+
# ============================================================================
|
|
126
|
+
|
|
127
|
+
# Count running hook processes
|
|
128
|
+
count_hook_processes() {
|
|
129
|
+
ps aux 2>/dev/null | grep -c "specweave.*hook" || echo "0"
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Detect if we're in a process storm
|
|
133
|
+
detect_process_storm() {
|
|
134
|
+
local threshold="${1:-20}"
|
|
135
|
+
local count
|
|
136
|
+
count=$(count_hook_processes)
|
|
137
|
+
|
|
138
|
+
if [[ "$count" -gt "$threshold" ]]; then
|
|
139
|
+
echo "STORM:$count"
|
|
140
|
+
return 1
|
|
141
|
+
fi
|
|
142
|
+
echo "OK:$count"
|
|
143
|
+
return 0
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
# ============================================================================
|
|
147
|
+
# CRASH CATEGORY 4: ZOMBIE PROCESS DETECTION
|
|
148
|
+
# ============================================================================
|
|
149
|
+
|
|
150
|
+
# Find and kill zombie heredoc processes
|
|
151
|
+
kill_zombie_heredocs() {
|
|
152
|
+
# Kill any cat processes waiting for EOF
|
|
153
|
+
pkill -f "cat.*EOF" 2>/dev/null || true
|
|
154
|
+
pkill -f "cat.*<<" 2>/dev/null || true
|
|
155
|
+
|
|
156
|
+
# Kill stale bash processes related to specweave hooks
|
|
157
|
+
local stale_pids
|
|
158
|
+
stale_pids=$(ps aux 2>/dev/null | grep -E "bash.*specweave.*hook" | grep -v grep | awk '{print $2}' | head -10)
|
|
159
|
+
|
|
160
|
+
for pid in $stale_pids; do
|
|
161
|
+
# Check if process is older than 30 seconds
|
|
162
|
+
local elapsed
|
|
163
|
+
elapsed=$(ps -o etimes= -p "$pid" 2>/dev/null | tr -d ' ')
|
|
164
|
+
if [[ -n "$elapsed" ]] && [[ "$elapsed" -gt 30 ]]; then
|
|
165
|
+
kill -9 "$pid" 2>/dev/null || true
|
|
166
|
+
fi
|
|
167
|
+
done
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
# ============================================================================
|
|
171
|
+
# CRASH CATEGORY 5: LOCK FILE CLEANUP
|
|
172
|
+
# ============================================================================
|
|
173
|
+
|
|
174
|
+
# Clean stale lock files (older than 60s)
|
|
175
|
+
clean_stale_locks() {
|
|
176
|
+
local project_root="$1"
|
|
177
|
+
local state_dir="$project_root/.specweave/state"
|
|
178
|
+
|
|
179
|
+
[[ ! -d "$state_dir" ]] && return
|
|
180
|
+
|
|
181
|
+
find "$state_dir" -name "*.lock" -type d -mmin +1 2>/dev/null | while read -r lock; do
|
|
182
|
+
rmdir "$lock" 2>/dev/null || true
|
|
183
|
+
done
|
|
184
|
+
|
|
185
|
+
# Also clean stale guard files
|
|
186
|
+
find "$state_dir" -name ".hook-*-guard" -type f -mmin +1 2>/dev/null | while read -r guard; do
|
|
187
|
+
rm -f "$guard" 2>/dev/null
|
|
188
|
+
done
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
# ============================================================================
|
|
192
|
+
# CRASH CATEGORY 6: SESSION HEALTH CHECK
|
|
193
|
+
# ============================================================================
|
|
194
|
+
|
|
195
|
+
# Comprehensive health check
|
|
196
|
+
check_session_health() {
|
|
197
|
+
local project_root="$1"
|
|
198
|
+
local issues=()
|
|
199
|
+
|
|
200
|
+
# Check 1: Process storm
|
|
201
|
+
local storm_status
|
|
202
|
+
storm_status=$(detect_process_storm 15)
|
|
203
|
+
if [[ "$storm_status" == STORM* ]]; then
|
|
204
|
+
issues+=("Process storm detected: $storm_status")
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
# Check 2: Stale locks
|
|
208
|
+
local stale_locks
|
|
209
|
+
stale_locks=$(find "$project_root/.specweave/state" -name "*.lock" -type d -mmin +1 2>/dev/null | wc -l | tr -d ' ')
|
|
210
|
+
if [[ "$stale_locks" -gt 0 ]]; then
|
|
211
|
+
issues+=("Stale locks: $stale_locks")
|
|
212
|
+
fi
|
|
213
|
+
|
|
214
|
+
# Check 3: Circuit breaker status
|
|
215
|
+
local cb_file="$project_root/.specweave/state/.hook-circuit-breaker"
|
|
216
|
+
if [[ -f "$cb_file" ]]; then
|
|
217
|
+
local failures
|
|
218
|
+
failures=$(cat "$cb_file" 2>/dev/null || echo "0")
|
|
219
|
+
if [[ "$failures" -ge 3 ]]; then
|
|
220
|
+
issues+=("Circuit breaker OPEN: $failures failures")
|
|
221
|
+
fi
|
|
222
|
+
fi
|
|
223
|
+
|
|
224
|
+
# Check 4: Active increment task count
|
|
225
|
+
local active_inc
|
|
226
|
+
active_inc=$(find "$project_root/.specweave/increments" -maxdepth 1 -type d -name "[0-9]*" 2>/dev/null | head -1 | xargs basename 2>/dev/null)
|
|
227
|
+
if [[ -n "$active_inc" ]]; then
|
|
228
|
+
local task_count
|
|
229
|
+
task_count=$(count_increment_tasks "$project_root" "$active_inc")
|
|
230
|
+
if [[ "$task_count" -gt 8 ]]; then
|
|
231
|
+
issues+=("Task count exceeds limit: $task_count/8 in $active_inc")
|
|
232
|
+
fi
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
# Report
|
|
236
|
+
if [[ ${#issues[@]} -eq 0 ]]; then
|
|
237
|
+
echo "HEALTHY"
|
|
238
|
+
return 0
|
|
239
|
+
else
|
|
240
|
+
echo "ISSUES:"
|
|
241
|
+
printf '%s\n' "${issues[@]}"
|
|
242
|
+
return 1
|
|
243
|
+
fi
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
# ============================================================================
|
|
247
|
+
# CRASH CATEGORY 7: EMERGENCY CLEANUP
|
|
248
|
+
# ============================================================================
|
|
249
|
+
|
|
250
|
+
# Nuclear option: clean ALL state
|
|
251
|
+
emergency_cleanup() {
|
|
252
|
+
local project_root="$1"
|
|
253
|
+
|
|
254
|
+
echo "=== EMERGENCY CLEANUP ==="
|
|
255
|
+
|
|
256
|
+
# 1. Kill zombie processes
|
|
257
|
+
echo "1. Killing zombie processes..."
|
|
258
|
+
kill_zombie_heredocs
|
|
259
|
+
pkill -9 -f "bash.*specweave" 2>/dev/null || true
|
|
260
|
+
|
|
261
|
+
# 2. Remove all locks
|
|
262
|
+
echo "2. Removing all locks..."
|
|
263
|
+
rm -rf "$project_root/.specweave/state/"*.lock 2>/dev/null
|
|
264
|
+
rm -f "$project_root/.specweave/state/.hook-"* 2>/dev/null
|
|
265
|
+
rm -f "$project_root/.specweave/state/.processor.lock" 2>/dev/null
|
|
266
|
+
|
|
267
|
+
# 3. Reset circuit breakers
|
|
268
|
+
echo "3. Resetting circuit breakers..."
|
|
269
|
+
rm -f "$project_root/.specweave/state/.hook-circuit-breaker"* 2>/dev/null
|
|
270
|
+
|
|
271
|
+
# 4. Clear dedup cache
|
|
272
|
+
echo "4. Clearing dedup cache..."
|
|
273
|
+
rm -rf "$project_root/.specweave/state/.dedup-cache" 2>/dev/null
|
|
274
|
+
|
|
275
|
+
# 5. Clear bulk operation counter
|
|
276
|
+
echo "5. Clearing bulk operation counter..."
|
|
277
|
+
rm -f "$project_root/.specweave/state/.bulk-op-counter" 2>/dev/null
|
|
278
|
+
|
|
279
|
+
echo "=== CLEANUP COMPLETE ==="
|
|
280
|
+
echo "Restart Claude Code to continue."
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
# ============================================================================
|
|
284
|
+
# RUNTIME GUARDS (for use in hooks)
|
|
285
|
+
# ============================================================================
|
|
286
|
+
|
|
287
|
+
# Pre-execution guard for any hook
|
|
288
|
+
guard_hook_execution() {
|
|
289
|
+
local hook_name="$1"
|
|
290
|
+
local project_root="$2"
|
|
291
|
+
|
|
292
|
+
# Check for process storm
|
|
293
|
+
local storm
|
|
294
|
+
storm=$(detect_process_storm 20)
|
|
295
|
+
if [[ "$storm" == STORM* ]]; then
|
|
296
|
+
echo "[GUARD] Blocking $hook_name: $storm" >&2
|
|
297
|
+
return 1
|
|
298
|
+
fi
|
|
299
|
+
|
|
300
|
+
return 0
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
# ============================================================================
|
|
304
|
+
# MAIN (when run directly)
|
|
305
|
+
# ============================================================================
|
|
306
|
+
|
|
307
|
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
308
|
+
case "${1:-health}" in
|
|
309
|
+
health)
|
|
310
|
+
PROJECT_ROOT=$(find "$PWD" -maxdepth 3 -type d -name ".specweave" 2>/dev/null | head -1 | xargs dirname 2>/dev/null)
|
|
311
|
+
if [[ -n "$PROJECT_ROOT" ]]; then
|
|
312
|
+
check_session_health "$PROJECT_ROOT"
|
|
313
|
+
else
|
|
314
|
+
echo "Not in a SpecWeave project"
|
|
315
|
+
exit 1
|
|
316
|
+
fi
|
|
317
|
+
;;
|
|
318
|
+
cleanup)
|
|
319
|
+
PROJECT_ROOT=$(find "$PWD" -maxdepth 3 -type d -name ".specweave" 2>/dev/null | head -1 | xargs dirname 2>/dev/null)
|
|
320
|
+
if [[ -n "$PROJECT_ROOT" ]]; then
|
|
321
|
+
emergency_cleanup "$PROJECT_ROOT"
|
|
322
|
+
else
|
|
323
|
+
echo "Not in a SpecWeave project"
|
|
324
|
+
exit 1
|
|
325
|
+
fi
|
|
326
|
+
;;
|
|
327
|
+
kill-zombies)
|
|
328
|
+
kill_zombie_heredocs
|
|
329
|
+
echo "Zombie processes cleaned"
|
|
330
|
+
;;
|
|
331
|
+
*)
|
|
332
|
+
echo "Usage: $0 {health|cleanup|kill-zombies}"
|
|
333
|
+
exit 1
|
|
334
|
+
;;
|
|
335
|
+
esac
|
|
336
|
+
fi
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SpecWeave Post-First-Increment Hook
|
|
3
|
+
#
|
|
4
|
+
# Triggers after the first increment is completed
|
|
5
|
+
# Congratulates the user on completing their first increment
|
|
6
|
+
#
|
|
7
|
+
# NON-INTERACTIVE: Just shows a message (hooks run in background)
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
# Get project root (where .specweave/ lives)
|
|
12
|
+
PROJECT_ROOT="$(pwd)"
|
|
13
|
+
|
|
14
|
+
# Check if .specweave directory exists
|
|
15
|
+
if [ ! -d ".specweave" ]; then
|
|
16
|
+
# Not in SpecWeave project, skip
|
|
17
|
+
exit 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Check if this is the first increment completion
|
|
21
|
+
# Count completed increments in .specweave/increments/
|
|
22
|
+
COMPLETED_COUNT=0
|
|
23
|
+
if [ -d ".specweave/increments" ]; then
|
|
24
|
+
# Count directories that have COMPLETION-REPORT.md or completion metadata
|
|
25
|
+
for inc_dir in .specweave/increments/[0-9][0-9][0-9][0-9]-*/; do
|
|
26
|
+
if [ -d "$inc_dir" ]; then
|
|
27
|
+
if [ -f "${inc_dir}reports/COMPLETION-REPORT.md" ] || \
|
|
28
|
+
[ -f "${inc_dir}COMPLETION-SUMMARY.md" ] || \
|
|
29
|
+
([ -f "${inc_dir}metadata.json" ] && grep -q '"status".*"completed"' "${inc_dir}metadata.json" 2>/dev/null); then
|
|
30
|
+
COMPLETED_COUNT=$((COMPLETED_COUNT + 1))
|
|
31
|
+
fi
|
|
32
|
+
fi
|
|
33
|
+
done
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Only trigger on first completion
|
|
37
|
+
if [ "$COMPLETED_COUNT" -ne 1 ]; then
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Show congratulations message (non-interactive)
|
|
42
|
+
echo ""
|
|
43
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
44
|
+
echo "🎉 Congratulations! You completed your first increment!"
|
|
45
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
46
|
+
echo ""
|
|
47
|
+
echo "✅ Your increment has been documented in:"
|
|
48
|
+
echo " .specweave/increments/[increment-id]/"
|
|
49
|
+
echo ""
|
|
50
|
+
echo "📚 View your documentation:"
|
|
51
|
+
echo " - Specs: .specweave/docs/internal/specs/"
|
|
52
|
+
echo " - Architecture: .specweave/docs/internal/architecture/"
|
|
53
|
+
echo ""
|
|
54
|
+
echo "🚀 Next steps:"
|
|
55
|
+
echo " - Review your increment: /specweave:status"
|
|
56
|
+
echo " - Start next increment: /specweave:increment \"feature name\""
|
|
57
|
+
echo ""
|
|
58
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
59
|
+
echo ""
|
|
60
|
+
|
|
61
|
+
exit 0
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# SpecWeave Post-Increment-Change Hook
|
|
4
|
+
# Runs automatically after increment files (spec.md, plan.md, tasks.md) are modified
|
|
5
|
+
#
|
|
6
|
+
# Trigger: File watcher or git hook (pre-commit/post-commit)
|
|
7
|
+
# Purpose: Sync increment file changes to GitHub issues
|
|
8
|
+
#
|
|
9
|
+
# What it does:
|
|
10
|
+
# 1. Detects which file changed (spec.md, plan.md, tasks.md)
|
|
11
|
+
# 2. Invokes GitHub sync for increment changes
|
|
12
|
+
# 3. Updates GitHub issue with scope/plan/task changes
|
|
13
|
+
#
|
|
14
|
+
# Usage:
|
|
15
|
+
# ./post-increment-change.sh <incrementId> <changedFile>
|
|
16
|
+
#
|
|
17
|
+
# Example:
|
|
18
|
+
# ./post-increment-change.sh 0015-hierarchical-sync spec.md
|
|
19
|
+
|
|
20
|
+
set -e
|
|
21
|
+
|
|
22
|
+
# Find project root
|
|
23
|
+
find_project_root() {
|
|
24
|
+
local dir="$1"
|
|
25
|
+
while [ "$dir" != "/" ]; do
|
|
26
|
+
if [ -d "$dir/.specweave" ]; then
|
|
27
|
+
echo "$dir"
|
|
28
|
+
return 0
|
|
29
|
+
fi
|
|
30
|
+
dir="$(dirname "$dir")"
|
|
31
|
+
done
|
|
32
|
+
pwd
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
|
|
36
|
+
cd "$PROJECT_ROOT" 2>/dev/null || true
|
|
37
|
+
|
|
38
|
+
# Configuration
|
|
39
|
+
LOGS_DIR=".specweave/logs"
|
|
40
|
+
DEBUG_LOG="$LOGS_DIR/hooks-debug.log"
|
|
41
|
+
|
|
42
|
+
mkdir -p "$LOGS_DIR" 2>/dev/null || true
|
|
43
|
+
|
|
44
|
+
# Arguments
|
|
45
|
+
INCREMENT_ID="$1"
|
|
46
|
+
CHANGED_FILE="$2"
|
|
47
|
+
|
|
48
|
+
if [ -z "$INCREMENT_ID" ] || [ -z "$CHANGED_FILE" ]; then
|
|
49
|
+
echo "Usage: $0 <incrementId> <changedFile>" >&2
|
|
50
|
+
echo "Example: $0 0015-hierarchical-sync spec.md" >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
echo "[$(date)] 📝 Increment file changed: $CHANGED_FILE" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
55
|
+
|
|
56
|
+
# Validate changed file
|
|
57
|
+
case "$CHANGED_FILE" in
|
|
58
|
+
spec.md|plan.md|tasks.md)
|
|
59
|
+
;;
|
|
60
|
+
*)
|
|
61
|
+
echo "[$(date)] ⚠️ Unknown file type: $CHANGED_FILE (skipping sync)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
62
|
+
exit 0
|
|
63
|
+
;;
|
|
64
|
+
esac
|
|
65
|
+
|
|
66
|
+
# Check if Node.js available
|
|
67
|
+
if ! command -v node &> /dev/null; then
|
|
68
|
+
echo "[$(date)] ⚠️ Node.js not found, skipping sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
69
|
+
exit 0
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
# Check if GitHub CLI available
|
|
73
|
+
if ! command -v gh &> /dev/null; then
|
|
74
|
+
echo "[$(date)] ℹ️ GitHub CLI not found, skipping sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
75
|
+
exit 0
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Check if authenticated
|
|
79
|
+
if ! gh auth status &> /dev/null; then
|
|
80
|
+
echo "[$(date)] ℹ️ GitHub CLI not authenticated, skipping sync" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
81
|
+
exit 0
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# Sync to GitHub
|
|
85
|
+
echo "[$(date)] 🔄 Syncing $CHANGED_FILE changes to GitHub..." >> "$DEBUG_LOG" 2>/dev/null || true
|
|
86
|
+
|
|
87
|
+
node dist/plugins/specweave-github/lib/github-sync-increment-changes.js "$INCREMENT_ID" "$CHANGED_FILE" 2>&1 | tee -a "$DEBUG_LOG" >/dev/null || {
|
|
88
|
+
echo "[$(date)] ⚠️ Failed to sync increment changes (non-blocking)" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
echo "[$(date)] ✅ Post-increment-change hook complete" >> "$DEBUG_LOG" 2>/dev/null || true
|
|
92
|
+
|
|
93
|
+
# Update status line cache (increment changed)
|
|
94
|
+
HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
95
|
+
bash "$HOOK_DIR/lib/update-status-line.sh" 2>/dev/null || true
|
|
96
|
+
|
|
97
|
+
# Return success (non-blocking)
|
|
98
|
+
exit 0
|