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,268 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# living-specs-handler.sh - Update living SPECS on lifecycle events
|
|
3
|
-
# Events: increment.created, increment.done, increment.archived, increment.reopened
|
|
4
|
-
#
|
|
5
|
-
# This handler updates the specs/ folder structure when increment lifecycle changes.
|
|
6
|
-
# It is called by the event processor, NOT directly by post-tool-use.
|
|
7
|
-
#
|
|
8
|
-
# IMPORTANT: This script must be fast (<100ms) and never crash Claude
|
|
9
|
-
# v1.0.71 - Fixed: Use specweave package location, not PROJECT_ROOT/dist
|
|
10
|
-
set +e
|
|
11
|
-
|
|
12
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
13
|
-
|
|
14
|
-
EVENT="${1:-}"
|
|
15
|
-
INC_ID="${2:-}"
|
|
16
|
-
|
|
17
|
-
[[ -z "$EVENT" ]] && exit 0
|
|
18
|
-
[[ -z "$INC_ID" ]] && exit 0
|
|
19
|
-
|
|
20
|
-
# Find project root
|
|
21
|
-
PROJECT_ROOT="$PWD"
|
|
22
|
-
while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
|
|
23
|
-
PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
|
|
24
|
-
done
|
|
25
|
-
[[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
|
|
26
|
-
|
|
27
|
-
# Resolve specweave package location
|
|
28
|
-
HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
29
|
-
source "$HANDLER_DIR/../../lib/resolve-package.sh" 2>/dev/null || true
|
|
30
|
-
|
|
31
|
-
# Throttle: max once per 60 seconds per increment
|
|
32
|
-
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
33
|
-
THROTTLE_FILE="$STATE_DIR/.living-specs-$INC_ID"
|
|
34
|
-
mkdir -p "$STATE_DIR" 2>/dev/null
|
|
35
|
-
|
|
36
|
-
if [[ -f "$THROTTLE_FILE" ]]; then
|
|
37
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
38
|
-
AGE=$(($(date +%s) - $(stat -f %m "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
39
|
-
else
|
|
40
|
-
AGE=$(($(date +%s) - $(stat -c %Y "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
41
|
-
fi
|
|
42
|
-
[[ $AGE -lt 60 ]] && exit 0
|
|
43
|
-
fi
|
|
44
|
-
touch "$THROTTLE_FILE"
|
|
45
|
-
|
|
46
|
-
# Find the sync script (check SPECWEAVE_PKG first, then fallbacks)
|
|
47
|
-
SYNC_SCRIPT=""
|
|
48
|
-
for path in \
|
|
49
|
-
"${SPECWEAVE_PKG:-}/dist/plugins/specweave/lib/hooks/sync-living-docs.js" \
|
|
50
|
-
"${SPECWEAVE_PKG:-}/plugins/specweave/lib/hooks/sync-living-docs.js" \
|
|
51
|
-
"${CLAUDE_PLUGIN_ROOT:-}/lib/hooks/sync-living-docs.js" \
|
|
52
|
-
"$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/sync-living-docs.js" \
|
|
53
|
-
"$PROJECT_ROOT/plugins/specweave/lib/hooks/sync-living-docs.js"; do
|
|
54
|
-
[[ -f "$path" ]] && { SYNC_SCRIPT="$path"; break; }
|
|
55
|
-
done
|
|
56
|
-
|
|
57
|
-
# Log event (silent, async)
|
|
58
|
-
LOG_FILE="$PROJECT_ROOT/.specweave/logs/hooks.log"
|
|
59
|
-
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null
|
|
60
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] living-specs-handler: $EVENT $INC_ID" >> "$LOG_FILE" 2>/dev/null
|
|
61
|
-
|
|
62
|
-
# Get increment paths
|
|
63
|
-
INC_DIR="$PROJECT_ROOT/.specweave/increments/$INC_ID"
|
|
64
|
-
ARCHIVE_DIR="$PROJECT_ROOT/.specweave/increments/_archive/$INC_ID"
|
|
65
|
-
SPEC_FILE="$INC_DIR/spec.md"
|
|
66
|
-
ARCHIVE_SPEC="$ARCHIVE_DIR/spec.md"
|
|
67
|
-
|
|
68
|
-
# Extract feature ID from spec.md (fast grep)
|
|
69
|
-
get_feature_id() {
|
|
70
|
-
local spec="$1"
|
|
71
|
-
[[ -f "$spec" ]] && grep -E "^(epic|feature_id):" "$spec" 2>/dev/null | head -1 | sed 's/.*:[[:space:]]*//' | tr -d '"'"'"
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
# Cross-platform timeout wrapper
|
|
75
|
-
# Uses GNU timeout, gtimeout (macOS with coreutils), or fallback
|
|
76
|
-
run_with_timeout() {
|
|
77
|
-
local timeout_secs="$1"
|
|
78
|
-
shift
|
|
79
|
-
if command -v timeout >/dev/null 2>&1; then
|
|
80
|
-
timeout "$timeout_secs" "$@" 2>/dev/null || true
|
|
81
|
-
elif command -v gtimeout >/dev/null 2>&1; then
|
|
82
|
-
gtimeout "$timeout_secs" "$@" 2>/dev/null || true
|
|
83
|
-
else
|
|
84
|
-
"$@" 2>/dev/null || true
|
|
85
|
-
fi
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
case "$EVENT" in
|
|
89
|
-
increment.created)
|
|
90
|
-
# Create spec entry in living docs via Node.js script
|
|
91
|
-
if [[ -n "$SYNC_SCRIPT" ]] && [[ -f "$SPEC_FILE" ]]; then
|
|
92
|
-
FEATURE_ID=$(get_feature_id "$SPEC_FILE")
|
|
93
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
94
|
-
if [[ -n "$FEATURE_ID" ]]; then
|
|
95
|
-
FEATURE_ID="$FEATURE_ID" run_with_timeout 30 node "$SYNC_SCRIPT" "$INC_ID" >/dev/null 2>&1 &
|
|
96
|
-
else
|
|
97
|
-
run_with_timeout 30 node "$SYNC_SCRIPT" "$INC_ID" >/dev/null 2>&1 &
|
|
98
|
-
fi
|
|
99
|
-
fi
|
|
100
|
-
;;
|
|
101
|
-
|
|
102
|
-
increment.done)
|
|
103
|
-
# Update status to complete in living docs
|
|
104
|
-
if [[ -n "$SYNC_SCRIPT" ]] && [[ -f "$SPEC_FILE" ]]; then
|
|
105
|
-
FEATURE_ID=$(get_feature_id "$SPEC_FILE")
|
|
106
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
107
|
-
|
|
108
|
-
# Mark as complete in FEATURE.md if it exists
|
|
109
|
-
if [[ -n "$FEATURE_ID" ]]; then
|
|
110
|
-
SPECS_DIR="$PROJECT_ROOT/.specweave/docs/internal/specs"
|
|
111
|
-
# Find FEATURE.md for this feature
|
|
112
|
-
FEATURE_FILE=$(find "$SPECS_DIR" -path "*/$FEATURE_ID/FEATURE.md" 2>/dev/null | head -1)
|
|
113
|
-
|
|
114
|
-
if [[ -f "$FEATURE_FILE" ]]; then
|
|
115
|
-
# Update status in FEATURE.md (in-progress -> complete)
|
|
116
|
-
sed -i.bak 's/status: in-progress/status: complete/g' "$FEATURE_FILE" 2>/dev/null
|
|
117
|
-
rm -f "${FEATURE_FILE}.bak" 2>/dev/null
|
|
118
|
-
|
|
119
|
-
# Update increment row status
|
|
120
|
-
sed -i.bak "s/\[$INC_ID\].*in-progress/[$INC_ID](..\/..\/..\/..\/increments\/$INC_ID\/spec.md) | complete/g" "$FEATURE_FILE" 2>/dev/null
|
|
121
|
-
rm -f "${FEATURE_FILE}.bak" 2>/dev/null
|
|
122
|
-
fi
|
|
123
|
-
|
|
124
|
-
# Also run full sync for completeness
|
|
125
|
-
FEATURE_ID="$FEATURE_ID" run_with_timeout 30 node "$SYNC_SCRIPT" "$INC_ID" >/dev/null 2>&1 &
|
|
126
|
-
else
|
|
127
|
-
run_with_timeout 30 node "$SYNC_SCRIPT" "$INC_ID" >/dev/null 2>&1 &
|
|
128
|
-
fi
|
|
129
|
-
fi
|
|
130
|
-
|
|
131
|
-
# ========================================================================
|
|
132
|
-
# CRITICAL FIX (v0.34.0): Close GitHub/JIRA/ADO issues on increment.done
|
|
133
|
-
# ========================================================================
|
|
134
|
-
# Root cause: sync-increment-closure.js was NEVER being called when
|
|
135
|
-
# increments completed. The EDA architecture routes increment.done to
|
|
136
|
-
# this handler, but only sync-living-docs.js was called (updates docs).
|
|
137
|
-
#
|
|
138
|
-
# sync-increment-closure.js contains the actual logic to:
|
|
139
|
-
# - Close GitHub issues linked to User Stories
|
|
140
|
-
# - Close JIRA/ADO issues (with proper gates)
|
|
141
|
-
# - Post completion comments on external issues
|
|
142
|
-
#
|
|
143
|
-
# Without this, GitHub issues stayed OPEN forever after increment closure!
|
|
144
|
-
# See: GitHub Issues #817-#822 (increment 0136) stayed open until manual fix
|
|
145
|
-
CLOSURE_SCRIPT=""
|
|
146
|
-
for path in \
|
|
147
|
-
"${SPECWEAVE_PKG:-}/dist/plugins/specweave/lib/hooks/sync-increment-closure.js" \
|
|
148
|
-
"${SPECWEAVE_PKG:-}/plugins/specweave/lib/hooks/sync-increment-closure.js" \
|
|
149
|
-
"${CLAUDE_PLUGIN_ROOT:-}/lib/hooks/sync-increment-closure.js" \
|
|
150
|
-
"$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/sync-increment-closure.js" \
|
|
151
|
-
"$PROJECT_ROOT/plugins/specweave/lib/hooks/sync-increment-closure.js"; do
|
|
152
|
-
[[ -f "$path" ]] && { CLOSURE_SCRIPT="$path"; break; }
|
|
153
|
-
done
|
|
154
|
-
|
|
155
|
-
if [[ -n "$CLOSURE_SCRIPT" ]]; then
|
|
156
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
157
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Calling sync-increment-closure.js for $INC_ID" >> "$LOG_FILE" 2>/dev/null
|
|
158
|
-
# Run closure sync in background (can take 10-30s for multiple issues)
|
|
159
|
-
run_with_timeout 60 node "$CLOSURE_SCRIPT" "$INC_ID" >> "$LOG_FILE" 2>&1 &
|
|
160
|
-
fi
|
|
161
|
-
|
|
162
|
-
# ========================================================================
|
|
163
|
-
# CODEBASE RESCAN (v1.0.47): Update living docs based on actual code
|
|
164
|
-
# ========================================================================
|
|
165
|
-
# When an increment closes, we MUST rescan the actual source code to ensure
|
|
166
|
-
# living docs reflect implementation reality (code as source of truth).
|
|
167
|
-
#
|
|
168
|
-
# This launches a background job that:
|
|
169
|
-
# 1. Scans files modified since increment started
|
|
170
|
-
# 2. Extracts implementation details (exports, functions, classes)
|
|
171
|
-
# 3. Updates living docs with actual code structure
|
|
172
|
-
# 4. Generates implementation summary report
|
|
173
|
-
#
|
|
174
|
-
# The job runs asynchronously to not block increment closure.
|
|
175
|
-
RESCAN_SCRIPT=""
|
|
176
|
-
for path in \
|
|
177
|
-
"${SPECWEAVE_PKG:-}/dist/plugins/specweave/lib/hooks/launch-codebase-rescan.js" \
|
|
178
|
-
"${SPECWEAVE_PKG:-}/plugins/specweave/lib/hooks/launch-codebase-rescan.js" \
|
|
179
|
-
"${CLAUDE_PLUGIN_ROOT:-}/lib/hooks/launch-codebase-rescan.js" \
|
|
180
|
-
"$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/launch-codebase-rescan.js" \
|
|
181
|
-
"$PROJECT_ROOT/plugins/specweave/lib/hooks/launch-codebase-rescan.js"; do
|
|
182
|
-
[[ -f "$path" ]] && { RESCAN_SCRIPT="$path"; break; }
|
|
183
|
-
done
|
|
184
|
-
|
|
185
|
-
if [[ -n "$RESCAN_SCRIPT" ]]; then
|
|
186
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
187
|
-
FEATURE_ID=$(get_feature_id "$SPEC_FILE")
|
|
188
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Launching codebase rescan job for $INC_ID (feature: ${FEATURE_ID:-none})" >> "$LOG_FILE" 2>/dev/null
|
|
189
|
-
# Run rescan in background - non-blocking, fire-and-forget
|
|
190
|
-
if [[ -n "$FEATURE_ID" ]]; then
|
|
191
|
-
run_with_timeout 10 node "$RESCAN_SCRIPT" "$INC_ID" "$FEATURE_ID" >> "$LOG_FILE" 2>&1 &
|
|
192
|
-
else
|
|
193
|
-
run_with_timeout 10 node "$RESCAN_SCRIPT" "$INC_ID" >> "$LOG_FILE" 2>&1 &
|
|
194
|
-
fi
|
|
195
|
-
else
|
|
196
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Codebase rescan script not found, skipping" >> "$LOG_FILE" 2>/dev/null
|
|
197
|
-
fi
|
|
198
|
-
;;
|
|
199
|
-
|
|
200
|
-
increment.archived)
|
|
201
|
-
# Move spec entry to _archive section in living docs
|
|
202
|
-
if [[ -f "$ARCHIVE_SPEC" ]]; then
|
|
203
|
-
FEATURE_ID=$(get_feature_id "$ARCHIVE_SPEC")
|
|
204
|
-
|
|
205
|
-
if [[ -n "$FEATURE_ID" ]]; then
|
|
206
|
-
SPECS_DIR="$PROJECT_ROOT/.specweave/docs/internal/specs"
|
|
207
|
-
ACTIVE_FEATURE=$(find "$SPECS_DIR" -path "*/$FEATURE_ID/FEATURE.md" -not -path "*/_archive/*" 2>/dev/null | head -1)
|
|
208
|
-
ARCHIVE_SPECS="$SPECS_DIR/specweave/_archive"
|
|
209
|
-
|
|
210
|
-
if [[ -f "$ACTIVE_FEATURE" ]]; then
|
|
211
|
-
# Check if all increments for this feature are archived
|
|
212
|
-
FEATURE_DIR=$(dirname "$ACTIVE_FEATURE")
|
|
213
|
-
ACTIVE_INC_COUNT=$(ls -1 "$FEATURE_DIR"/*.md 2>/dev/null | grep -v FEATURE.md | grep -v README.md | wc -l | tr -d ' ')
|
|
214
|
-
|
|
215
|
-
if [[ "$ACTIVE_INC_COUNT" -eq 0 ]]; then
|
|
216
|
-
# Move entire feature folder to archive
|
|
217
|
-
mkdir -p "$ARCHIVE_SPECS" 2>/dev/null
|
|
218
|
-
mv "$FEATURE_DIR" "$ARCHIVE_SPECS/" 2>/dev/null
|
|
219
|
-
else
|
|
220
|
-
# Just update status in FEATURE.md
|
|
221
|
-
sed -i.bak "s/\[$INC_ID\].*|.*$/[$INC_ID](..\/..\/..\/..\/increments\/_archive\/$INC_ID\/spec.md) | archived/g" "$ACTIVE_FEATURE" 2>/dev/null
|
|
222
|
-
rm -f "${ACTIVE_FEATURE}.bak" 2>/dev/null
|
|
223
|
-
fi
|
|
224
|
-
fi
|
|
225
|
-
fi
|
|
226
|
-
fi
|
|
227
|
-
;;
|
|
228
|
-
|
|
229
|
-
increment.reopened)
|
|
230
|
-
# Restore from archive section in living docs
|
|
231
|
-
if [[ -f "$SPEC_FILE" ]]; then
|
|
232
|
-
FEATURE_ID=$(get_feature_id "$SPEC_FILE")
|
|
233
|
-
|
|
234
|
-
if [[ -n "$FEATURE_ID" ]]; then
|
|
235
|
-
SPECS_DIR="$PROJECT_ROOT/.specweave/docs/internal/specs"
|
|
236
|
-
ARCHIVE_FEATURE="$SPECS_DIR/specweave/_archive/$FEATURE_ID"
|
|
237
|
-
ACTIVE_SPECS="$SPECS_DIR/specweave"
|
|
238
|
-
|
|
239
|
-
# Check if feature was archived, restore it
|
|
240
|
-
if [[ -d "$ARCHIVE_FEATURE" ]]; then
|
|
241
|
-
mv "$ARCHIVE_FEATURE" "$ACTIVE_SPECS/" 2>/dev/null
|
|
242
|
-
|
|
243
|
-
# Update status back to in-progress
|
|
244
|
-
FEATURE_FILE="$ACTIVE_SPECS/$FEATURE_ID/FEATURE.md"
|
|
245
|
-
if [[ -f "$FEATURE_FILE" ]]; then
|
|
246
|
-
sed -i.bak 's/status: archived/status: in-progress/g' "$FEATURE_FILE" 2>/dev/null
|
|
247
|
-
sed -i.bak 's/status: complete/status: in-progress/g' "$FEATURE_FILE" 2>/dev/null
|
|
248
|
-
rm -f "${FEATURE_FILE}.bak" 2>/dev/null
|
|
249
|
-
fi
|
|
250
|
-
else
|
|
251
|
-
# Feature still exists, just update increment status
|
|
252
|
-
FEATURE_FILE=$(find "$SPECS_DIR" -path "*/$FEATURE_ID/FEATURE.md" -not -path "*/_archive/*" 2>/dev/null | head -1)
|
|
253
|
-
if [[ -f "$FEATURE_FILE" ]]; then
|
|
254
|
-
sed -i.bak "s/\[$INC_ID\].*archived/[$INC_ID](..\/..\/..\/..\/increments\/$INC_ID\/spec.md) | in-progress/g" "$FEATURE_FILE" 2>/dev/null
|
|
255
|
-
sed -i.bak "s/\[$INC_ID\].*complete/[$INC_ID](..\/..\/..\/..\/increments\/$INC_ID\/spec.md) | in-progress/g" "$FEATURE_FILE" 2>/dev/null
|
|
256
|
-
rm -f "${FEATURE_FILE}.bak" 2>/dev/null
|
|
257
|
-
fi
|
|
258
|
-
fi
|
|
259
|
-
|
|
260
|
-
# Run full sync to restore any missing content
|
|
261
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
262
|
-
FEATURE_ID="$FEATURE_ID" run_with_timeout 30 node "$SYNC_SCRIPT" "$INC_ID" >/dev/null 2>&1 &
|
|
263
|
-
fi
|
|
264
|
-
fi
|
|
265
|
-
;;
|
|
266
|
-
esac
|
|
267
|
-
|
|
268
|
-
exit 0
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# project-bridge-handler.sh - Bridge increment events to project-level EDA
|
|
3
|
-
#
|
|
4
|
-
# This handler connects the increment-level EDA (hooks v2) to the
|
|
5
|
-
# project-level EDA (ProjectRegistry + Adapters).
|
|
6
|
-
#
|
|
7
|
-
# Events bridged:
|
|
8
|
-
# - increment.created -> May create project labels in GitHub
|
|
9
|
-
# - increment.done -> Triggers project sync to all external tools
|
|
10
|
-
# - increment.archived -> Updates project sync status
|
|
11
|
-
# - increment.reopened -> Triggers project sync
|
|
12
|
-
#
|
|
13
|
-
# Architecture:
|
|
14
|
-
# [Increment Event] -> [This Handler] -> [project-bridge.js] -> [ProjectService]
|
|
15
|
-
# |
|
|
16
|
-
# v
|
|
17
|
-
# [ProjectEventBus]
|
|
18
|
-
# |
|
|
19
|
-
# +----------------+----------------+
|
|
20
|
-
# v v v
|
|
21
|
-
# [GitHub] [ADO] [JIRA]
|
|
22
|
-
# Adapter Adapter Adapter
|
|
23
|
-
#
|
|
24
|
-
# IMPORTANT: Never crash Claude, always exit 0
|
|
25
|
-
# v1.0.71 - Fixed: Use specweave package location, not PROJECT_ROOT/dist
|
|
26
|
-
set +e
|
|
27
|
-
|
|
28
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
29
|
-
|
|
30
|
-
EVENT_TYPE="${1:-}"
|
|
31
|
-
EVENT_DATA="${2:-}"
|
|
32
|
-
|
|
33
|
-
[[ -z "$EVENT_TYPE" ]] && exit 0
|
|
34
|
-
[[ -z "$EVENT_DATA" ]] && exit 0
|
|
35
|
-
|
|
36
|
-
# Find project root
|
|
37
|
-
PROJECT_ROOT="$PWD"
|
|
38
|
-
while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
|
|
39
|
-
PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
|
|
40
|
-
done
|
|
41
|
-
[[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
|
|
42
|
-
|
|
43
|
-
# Resolve specweave package location
|
|
44
|
-
HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
45
|
-
source "$HANDLER_DIR/../../lib/resolve-package.sh" 2>/dev/null || true
|
|
46
|
-
|
|
47
|
-
# Throttle: max once per 2 minutes per increment for project sync
|
|
48
|
-
# (More aggressive throttle since this triggers external API calls)
|
|
49
|
-
INC_ID="${EVENT_DATA%%:*}" # Extract increment ID from INC_ID:US_ID format
|
|
50
|
-
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
51
|
-
THROTTLE_FILE="$STATE_DIR/.project-bridge-$INC_ID"
|
|
52
|
-
THROTTLE_WINDOW=120 # 2 minutes
|
|
53
|
-
mkdir -p "$STATE_DIR" 2>/dev/null
|
|
54
|
-
|
|
55
|
-
if [[ -f "$THROTTLE_FILE" ]]; then
|
|
56
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
57
|
-
AGE=$(($(date +%s) - $(stat -f %m "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
58
|
-
else
|
|
59
|
-
AGE=$(($(date +%s) - $(stat -c %Y "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
60
|
-
fi
|
|
61
|
-
[[ $AGE -lt $THROTTLE_WINDOW ]] && exit 0
|
|
62
|
-
fi
|
|
63
|
-
touch "$THROTTLE_FILE"
|
|
64
|
-
|
|
65
|
-
# Log event
|
|
66
|
-
LOG_FILE="$PROJECT_ROOT/.specweave/logs/hooks.log"
|
|
67
|
-
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null
|
|
68
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] project-bridge-handler: $EVENT_TYPE $EVENT_DATA" >> "$LOG_FILE" 2>/dev/null
|
|
69
|
-
|
|
70
|
-
# Find the bridge script (check SPECWEAVE_PKG first)
|
|
71
|
-
BRIDGE_SCRIPT=""
|
|
72
|
-
for path in \
|
|
73
|
-
"${SPECWEAVE_PKG:-}/dist/plugins/specweave/lib/hooks/project-bridge.js" \
|
|
74
|
-
"${SPECWEAVE_PKG:-}/plugins/specweave/lib/hooks/project-bridge.js" \
|
|
75
|
-
"${CLAUDE_PLUGIN_ROOT:-}/lib/hooks/project-bridge.js" \
|
|
76
|
-
"$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/project-bridge.js" \
|
|
77
|
-
"$PROJECT_ROOT/plugins/specweave/lib/hooks/project-bridge.js"; do
|
|
78
|
-
[[ -f "$path" ]] && { BRIDGE_SCRIPT="$path"; break; }
|
|
79
|
-
done
|
|
80
|
-
|
|
81
|
-
# Cross-platform timeout wrapper
|
|
82
|
-
# FIXED (v1.0.302): Don't suppress stderr from inner commands
|
|
83
|
-
run_with_timeout() {
|
|
84
|
-
local timeout_secs="$1"
|
|
85
|
-
shift
|
|
86
|
-
if command -v timeout >/dev/null 2>&1; then
|
|
87
|
-
timeout "$timeout_secs" "$@" || true
|
|
88
|
-
elif command -v gtimeout >/dev/null 2>&1; then
|
|
89
|
-
gtimeout "$timeout_secs" "$@" || true
|
|
90
|
-
else
|
|
91
|
-
"$@" || true
|
|
92
|
-
fi
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
# Run bridge script if available
|
|
96
|
-
if [[ -n "$BRIDGE_SCRIPT" ]]; then
|
|
97
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
98
|
-
# Run with 60s timeout (external API calls can be slow)
|
|
99
|
-
run_with_timeout 60 node "$BRIDGE_SCRIPT" "$EVENT_TYPE" "$EVENT_DATA" >> "$LOG_FILE" 2>&1 &
|
|
100
|
-
else
|
|
101
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] project-bridge-handler: No bridge script found, skipping" >> "$LOG_FILE" 2>/dev/null
|
|
102
|
-
fi
|
|
103
|
-
|
|
104
|
-
exit 0
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# status-line-handler.sh - Event-driven status line updates
|
|
3
|
-
# Events: user-story.completed, user-story.reopened, increment.done, increment.archived, increment.reopened
|
|
4
|
-
#
|
|
5
|
-
# This handler updates the status line ONLY when meaningful events occur:
|
|
6
|
-
# - User story completed (all ACs + tasks done for that US)
|
|
7
|
-
# - User story reopened (US tasks/ACs unchecked)
|
|
8
|
-
# - Increment lifecycle changes (done, archived, reopened)
|
|
9
|
-
#
|
|
10
|
-
# It does NOT update on every task.md edit - that would cause:
|
|
11
|
-
# - Race conditions (multiple rapid updates)
|
|
12
|
-
# - Performance issues (too frequent writes)
|
|
13
|
-
# - Status line flickering
|
|
14
|
-
#
|
|
15
|
-
# IMPORTANT: This script must be fast (<20ms) and never crash Claude
|
|
16
|
-
set +e
|
|
17
|
-
|
|
18
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
19
|
-
|
|
20
|
-
EVENT="${1:-}"
|
|
21
|
-
EVENT_DATA="${2:-}"
|
|
22
|
-
|
|
23
|
-
[[ -z "$EVENT" ]] && exit 0
|
|
24
|
-
[[ -z "$EVENT_DATA" ]] && exit 0
|
|
25
|
-
|
|
26
|
-
# Find project root
|
|
27
|
-
PROJECT_ROOT="$PWD"
|
|
28
|
-
while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
|
|
29
|
-
PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
|
|
30
|
-
done
|
|
31
|
-
[[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
|
|
32
|
-
|
|
33
|
-
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
34
|
-
CACHE_FILE="$STATE_DIR/status-line.json"
|
|
35
|
-
mkdir -p "$STATE_DIR" 2>/dev/null
|
|
36
|
-
|
|
37
|
-
# Log event (silent, async)
|
|
38
|
-
LOG_FILE="$PROJECT_ROOT/.specweave/logs/hooks.log"
|
|
39
|
-
mkdir -p "$(dirname "$LOG_FILE")" 2>/dev/null
|
|
40
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] status-line-handler: $EVENT $EVENT_DATA" >> "$LOG_FILE" 2>/dev/null
|
|
41
|
-
|
|
42
|
-
# Parse event data
|
|
43
|
-
# Format: INC_ID:US_ID (for user-story events) or just INC_ID (for lifecycle events)
|
|
44
|
-
if [[ "$EVENT_DATA" == *":"* ]]; then
|
|
45
|
-
INC_ID="${EVENT_DATA%%:*}"
|
|
46
|
-
US_ID="${EVENT_DATA##*:}"
|
|
47
|
-
else
|
|
48
|
-
INC_ID="$EVENT_DATA"
|
|
49
|
-
US_ID=""
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
# Handle events
|
|
53
|
-
case "$EVENT" in
|
|
54
|
-
user-story.completed)
|
|
55
|
-
# User story completed - update status line with US progress
|
|
56
|
-
# This is the RIGHT time to update (not on every checkbox click)
|
|
57
|
-
;;
|
|
58
|
-
|
|
59
|
-
user-story.reopened)
|
|
60
|
-
# User story reopened - update status line
|
|
61
|
-
;;
|
|
62
|
-
|
|
63
|
-
increment.done)
|
|
64
|
-
# Increment completed - update status line to show completion
|
|
65
|
-
;;
|
|
66
|
-
|
|
67
|
-
increment.archived)
|
|
68
|
-
# Increment archived - clear from status line, find next active
|
|
69
|
-
INC_ID="" # Force finding a new active increment
|
|
70
|
-
;;
|
|
71
|
-
|
|
72
|
-
increment.reopened)
|
|
73
|
-
# Increment reopened - show it as active again
|
|
74
|
-
;;
|
|
75
|
-
|
|
76
|
-
*)
|
|
77
|
-
# Unknown event - ignore
|
|
78
|
-
exit 0
|
|
79
|
-
;;
|
|
80
|
-
esac
|
|
81
|
-
|
|
82
|
-
# Find active increment if not determined or was archived
|
|
83
|
-
if [[ -z "$INC_ID" ]] || [[ "$EVENT" == "increment.archived" ]]; then
|
|
84
|
-
INC_ID=""
|
|
85
|
-
for meta in "$PROJECT_ROOT/.specweave/increments"/[0-9]*/metadata.json; do
|
|
86
|
-
[[ -f "$meta" ]] || continue
|
|
87
|
-
STATUS=$(grep -o '"status"[[:space:]]*:[[:space:]]*"[^"]*"' "$meta" | grep -o '"[^"]*"$' | tr -d '"')
|
|
88
|
-
[[ "$STATUS" == "active" || "$STATUS" == "planning" ]] && {
|
|
89
|
-
INC_ID=$(basename "$(dirname "$meta")")
|
|
90
|
-
break
|
|
91
|
-
}
|
|
92
|
-
done
|
|
93
|
-
fi
|
|
94
|
-
|
|
95
|
-
# If no active increment, write null status
|
|
96
|
-
if [[ -z "$INC_ID" ]]; then
|
|
97
|
-
cat > "$CACHE_FILE" << 'EOF'
|
|
98
|
-
{"current":null,"event":"increment.archived","ts":"__TS__"}
|
|
99
|
-
EOF
|
|
100
|
-
sed -i.bak "s/__TS__/$(date +%s)/" "$CACHE_FILE" 2>/dev/null
|
|
101
|
-
rm -f "${CACHE_FILE}.bak" 2>/dev/null
|
|
102
|
-
exit 0
|
|
103
|
-
fi
|
|
104
|
-
|
|
105
|
-
# Get increment paths
|
|
106
|
-
TASKS_FILE="$PROJECT_ROOT/.specweave/increments/$INC_ID/tasks.md"
|
|
107
|
-
SPEC_FILE="$PROJECT_ROOT/.specweave/increments/$INC_ID/spec.md"
|
|
108
|
-
META_FILE="$PROJECT_ROOT/.specweave/increments/$INC_ID/metadata.json"
|
|
109
|
-
|
|
110
|
-
# Check files exist
|
|
111
|
-
[[ ! -f "$TASKS_FILE" ]] && exit 0
|
|
112
|
-
|
|
113
|
-
# Count tasks (pure bash, fast)
|
|
114
|
-
TOTAL=$(grep -c "^###\? T-" "$TASKS_FILE" 2>/dev/null || echo 0)
|
|
115
|
-
DONE=$(grep -c "\[x\]" "$TASKS_FILE" 2>/dev/null || echo 0)
|
|
116
|
-
PCT=0; [[ $TOTAL -gt 0 ]] && PCT=$((DONE * 100 / TOTAL))
|
|
117
|
-
|
|
118
|
-
# Count user stories completed
|
|
119
|
-
US_TOTAL=0
|
|
120
|
-
US_DONE=0
|
|
121
|
-
if [[ -f "$SPEC_FILE" ]]; then
|
|
122
|
-
# Count user story headers (## US-XXX or similar)
|
|
123
|
-
US_TOTAL=$(grep -c "^##.*US-" "$SPEC_FILE" 2>/dev/null || echo 0)
|
|
124
|
-
|
|
125
|
-
# Count by checking if all ACs for each US are checked
|
|
126
|
-
# This is a simplified count - the actual detection is done by us-completion-detector.sh
|
|
127
|
-
US_STATE_FILE="$STATE_DIR/.us-completion-$INC_ID"
|
|
128
|
-
if [[ -f "$US_STATE_FILE" ]]; then
|
|
129
|
-
US_DONE=$(grep -c "=yes$" "$US_STATE_FILE" 2>/dev/null || echo 0)
|
|
130
|
-
fi
|
|
131
|
-
fi
|
|
132
|
-
|
|
133
|
-
# Get increment status
|
|
134
|
-
INC_STATUS="active"
|
|
135
|
-
if [[ -f "$META_FILE" ]]; then
|
|
136
|
-
INC_STATUS=$(grep -o '"status"[[:space:]]*:[[:space:]]*"[^"]*"' "$META_FILE" | grep -o '"[^"]*"$' | tr -d '"')
|
|
137
|
-
fi
|
|
138
|
-
|
|
139
|
-
# Build detailed status JSON with event info
|
|
140
|
-
TMP_FILE="$CACHE_FILE.tmp.$$"
|
|
141
|
-
cat > "$TMP_FILE" << EOF
|
|
142
|
-
{
|
|
143
|
-
"current": {
|
|
144
|
-
"id": "$INC_ID",
|
|
145
|
-
"completed": $DONE,
|
|
146
|
-
"total": $TOTAL,
|
|
147
|
-
"percentage": $PCT,
|
|
148
|
-
"status": "$INC_STATUS",
|
|
149
|
-
"userStories": {
|
|
150
|
-
"completed": $US_DONE,
|
|
151
|
-
"total": $US_TOTAL
|
|
152
|
-
}
|
|
153
|
-
},
|
|
154
|
-
"lastEvent": {
|
|
155
|
-
"type": "$EVENT",
|
|
156
|
-
"data": "$EVENT_DATA"
|
|
157
|
-
},
|
|
158
|
-
"ts": "$(date +%s)"
|
|
159
|
-
}
|
|
160
|
-
EOF
|
|
161
|
-
|
|
162
|
-
# Atomic write (mv is atomic on same filesystem)
|
|
163
|
-
mv "$TMP_FILE" "$CACHE_FILE" 2>/dev/null
|
|
164
|
-
|
|
165
|
-
exit 0
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# status-update.sh - Fast status line update (synchronous)
|
|
3
|
-
# Goal: <20ms execution, pure bash, no external processes
|
|
4
|
-
#
|
|
5
|
-
# NOTE: This is the LEGACY handler. New EDA architecture uses
|
|
6
|
-
# status-line-handler.sh which is EVENT-DRIVEN.
|
|
7
|
-
#
|
|
8
|
-
# IMPORTANT: Never crash Claude, always exit 0
|
|
9
|
-
set +e
|
|
10
|
-
|
|
11
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
12
|
-
|
|
13
|
-
INC_ID="${1:-}"
|
|
14
|
-
|
|
15
|
-
# Find project root
|
|
16
|
-
PROJECT_ROOT="$PWD"
|
|
17
|
-
while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
|
|
18
|
-
PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
|
|
19
|
-
done
|
|
20
|
-
[[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
|
|
21
|
-
|
|
22
|
-
STATE_DIR="$PROJECT_ROOT/.specweave/state"
|
|
23
|
-
CACHE_FILE="$STATE_DIR/status-line.json"
|
|
24
|
-
mkdir -p "$STATE_DIR" 2>/dev/null
|
|
25
|
-
|
|
26
|
-
# TTL check (10 seconds)
|
|
27
|
-
if [[ -f "$CACHE_FILE" ]]; then
|
|
28
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
29
|
-
CACHE_AGE=$(($(date +%s) - $(stat -f %m "$CACHE_FILE" 2>/dev/null || echo 0)))
|
|
30
|
-
else
|
|
31
|
-
CACHE_AGE=$(($(date +%s) - $(stat -c %Y "$CACHE_FILE" 2>/dev/null || echo 0)))
|
|
32
|
-
fi
|
|
33
|
-
[[ $CACHE_AGE -lt 10 ]] && exit 0
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# Find active increment if not provided
|
|
37
|
-
if [[ -z "$INC_ID" ]]; then
|
|
38
|
-
for meta in "$PROJECT_ROOT/.specweave/increments"/[0-9]*/metadata.json; do
|
|
39
|
-
[[ -f "$meta" ]] || continue
|
|
40
|
-
STATUS=$(grep -o '"status"[[:space:]]*:[[:space:]]*"[^"]*"' "$meta" | grep -o '"[^"]*"$' | tr -d '"')
|
|
41
|
-
[[ "$STATUS" == "active" || "$STATUS" == "planning" ]] && {
|
|
42
|
-
INC_ID=$(basename "$(dirname "$meta")")
|
|
43
|
-
break
|
|
44
|
-
}
|
|
45
|
-
done
|
|
46
|
-
fi
|
|
47
|
-
[[ -z "$INC_ID" ]] && { echo '{"current":null}' > "$CACHE_FILE"; exit 0; }
|
|
48
|
-
|
|
49
|
-
TASKS_FILE="$PROJECT_ROOT/.specweave/increments/$INC_ID/tasks.md"
|
|
50
|
-
[[ ! -f "$TASKS_FILE" ]] && exit 0
|
|
51
|
-
|
|
52
|
-
# Count tasks (pure bash, fast)
|
|
53
|
-
TOTAL=$(grep -c "^###\? T-" "$TASKS_FILE" 2>/dev/null || echo 0)
|
|
54
|
-
DONE=$(grep -c "\[x\]" "$TASKS_FILE" 2>/dev/null || echo 0)
|
|
55
|
-
PCT=0; [[ $TOTAL -gt 0 ]] && PCT=$((DONE * 100 / TOTAL))
|
|
56
|
-
|
|
57
|
-
# Write cache (atomic)
|
|
58
|
-
cat > "$CACHE_FILE" << EOF
|
|
59
|
-
{"current":{"id":"$INC_ID","completed":$DONE,"total":$TOTAL,"percentage":$PCT},"ts":"$(date +%s)"}
|
|
60
|
-
EOF
|
|
61
|
-
exit 0
|