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,347 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# github-sync-handler.sh - Sync increment to GitHub (create/update issues for User Stories)
|
|
3
|
-
# Called async by processor, non-blocking, error-tolerant
|
|
4
|
-
#
|
|
5
|
-
# Argument formats supported:
|
|
6
|
-
# 1. (event_type, increment_id) - from lifecycle/spec.updated events
|
|
7
|
-
# 2. (event_type, INC_ID:US_ID) - from user-story.completed/reopened events (v1.0.45+)
|
|
8
|
-
# 3. (increment_id) - from metadata.changed events (legacy)
|
|
9
|
-
#
|
|
10
|
-
# CRITICAL FIX (v1.0.45): Added user-story.completed/reopened support
|
|
11
|
-
# Root cause: GitHub issues were created but NEVER UPDATED when User Stories completed!
|
|
12
|
-
#
|
|
13
|
-
# IMPORTANT: Never crash Claude, always exit 0
|
|
14
|
-
# v1.0.71 - Fixed: Use specweave package location, not PROJECT_ROOT/dist
|
|
15
|
-
set +e
|
|
16
|
-
|
|
17
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
18
|
-
|
|
19
|
-
# Resolve specweave package location (do this early, before PROJECT_ROOT)
|
|
20
|
-
HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
-
source "$HANDLER_DIR/../../lib/resolve-package.sh" 2>/dev/null || true
|
|
22
|
-
|
|
23
|
-
# Parse arguments - support multiple formats
|
|
24
|
-
EVENT_TYPE="${1:-}"
|
|
25
|
-
EVENT_DATA="${2:-}"
|
|
26
|
-
INC_ID=""
|
|
27
|
-
US_ID=""
|
|
28
|
-
|
|
29
|
-
if [[ "$EVENT_TYPE" == user-story.* ]]; then
|
|
30
|
-
# user-story.completed/reopened: $2 = INC_ID:US_ID
|
|
31
|
-
INC_ID="${EVENT_DATA%%:*}"
|
|
32
|
-
US_ID="${EVENT_DATA##*:}"
|
|
33
|
-
elif [[ "$EVENT_TYPE" == increment.* ]] || [[ "$EVENT_TYPE" == spec.* ]] || [[ "$EVENT_TYPE" == metadata.* ]]; then
|
|
34
|
-
# Lifecycle events: $2 = increment_id
|
|
35
|
-
INC_ID="$EVENT_DATA"
|
|
36
|
-
else
|
|
37
|
-
# Legacy format: $1 = increment_id directly
|
|
38
|
-
INC_ID="$EVENT_TYPE"
|
|
39
|
-
fi
|
|
40
|
-
|
|
41
|
-
[[ -z "$INC_ID" ]] && exit 0
|
|
42
|
-
|
|
43
|
-
# Find project root
|
|
44
|
-
PROJECT_ROOT="$PWD"
|
|
45
|
-
while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
|
|
46
|
-
PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
|
|
47
|
-
done
|
|
48
|
-
[[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
|
|
49
|
-
|
|
50
|
-
CONFIG_FILE="$PROJECT_ROOT/.specweave/config.json"
|
|
51
|
-
[[ ! -f "$CONFIG_FILE" ]] && exit 0
|
|
52
|
-
|
|
53
|
-
# Initialize throttle log early (used throughout the script for diagnostics)
|
|
54
|
-
THROTTLE_LOG="$PROJECT_ROOT/.specweave/logs/throttle.log"
|
|
55
|
-
mkdir -p "$(dirname "$THROTTLE_LOG")" 2>/dev/null
|
|
56
|
-
|
|
57
|
-
# Check if GitHub sync is enabled
|
|
58
|
-
# FIXED (v1.0.46): Support BOTH config formats:
|
|
59
|
-
#
|
|
60
|
-
# FORMAT 1 - PROFILES (current, multi-project):
|
|
61
|
-
# sync.profiles["sw-content-repurposer-api"]: { provider: "github", config: {...} }
|
|
62
|
-
# + sync.settings.canUpdateExternalItems: true
|
|
63
|
-
#
|
|
64
|
-
# FORMAT 2 - LEGACY (direct github section):
|
|
65
|
-
# sync.github: { enabled: true, owner, repo }
|
|
66
|
-
#
|
|
67
|
-
# FORMAT 3 - LEGACY (provider field):
|
|
68
|
-
# sync: { enabled: true, provider: "github" }
|
|
69
|
-
#
|
|
70
|
-
# NOTE: The actual permission gates (canUpdateExternalItems, etc.) are checked
|
|
71
|
-
# downstream by GitHubFeatureSync, which respects the full permission model.
|
|
72
|
-
GITHUB_ENABLED=""
|
|
73
|
-
|
|
74
|
-
# Method 1: Check for PROFILES format (sync.profiles with provider: "github")
|
|
75
|
-
# This is the current recommended format for multi-project setups
|
|
76
|
-
if grep -q '"profiles"[[:space:]]*:' "$CONFIG_FILE" 2>/dev/null; then
|
|
77
|
-
# Check if ANY profile has provider: "github"
|
|
78
|
-
if grep -q '"provider"[[:space:]]*:[[:space:]]*"github"' "$CONFIG_FILE" 2>/dev/null; then
|
|
79
|
-
# Also check if canUpdateExternalItems is true (required for GitHub sync)
|
|
80
|
-
if grep -q '"canUpdateExternalItems"[[:space:]]*:[[:space:]]*true' "$CONFIG_FILE" 2>/dev/null; then
|
|
81
|
-
GITHUB_ENABLED="true"
|
|
82
|
-
else
|
|
83
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] WARNING: GitHub profile found but canUpdateExternalItems=false" >> "$THROTTLE_LOG" 2>/dev/null
|
|
84
|
-
fi
|
|
85
|
-
fi
|
|
86
|
-
fi
|
|
87
|
-
|
|
88
|
-
# Method 2: Check for explicit sync.github.enabled (legacy direct style)
|
|
89
|
-
if [[ -z "$GITHUB_ENABLED" ]]; then
|
|
90
|
-
if grep -q '"github"[[:space:]]*:' "$CONFIG_FILE" 2>/dev/null; then
|
|
91
|
-
if grep -A5 '"github"[[:space:]]*:' "$CONFIG_FILE" 2>/dev/null | grep -q '"enabled"[[:space:]]*:[[:space:]]*true'; then
|
|
92
|
-
GITHUB_ENABLED="true"
|
|
93
|
-
fi
|
|
94
|
-
fi
|
|
95
|
-
fi
|
|
96
|
-
|
|
97
|
-
# Method 3: Check for provider: github with sync.enabled (legacy style)
|
|
98
|
-
if [[ -z "$GITHUB_ENABLED" ]]; then
|
|
99
|
-
# Only check this if there are NO profiles (pure legacy config)
|
|
100
|
-
if ! grep -q '"profiles"[[:space:]]*:' "$CONFIG_FILE" 2>/dev/null; then
|
|
101
|
-
if grep -q '"provider"[[:space:]]*:[[:space:]]*"github"' "$CONFIG_FILE" 2>/dev/null; then
|
|
102
|
-
if grep -q '"sync"' "$CONFIG_FILE" && grep -A2 '"sync"' "$CONFIG_FILE" | grep -q '"enabled"[[:space:]]*:[[:space:]]*true'; then
|
|
103
|
-
GITHUB_ENABLED="true"
|
|
104
|
-
fi
|
|
105
|
-
fi
|
|
106
|
-
fi
|
|
107
|
-
fi
|
|
108
|
-
|
|
109
|
-
if [[ -z "$GITHUB_ENABLED" ]]; then
|
|
110
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] SKIPPED: No GitHub config found or canUpdateExternalItems=false" >> "$THROTTLE_LOG" 2>/dev/null
|
|
111
|
-
exit 0
|
|
112
|
-
fi
|
|
113
|
-
|
|
114
|
-
# Throttle configuration:
|
|
115
|
-
# - Full sync (increment lifecycle): 5 minutes (creates all issues)
|
|
116
|
-
# - US completion sync: 60 seconds (more targeted, less aggressive)
|
|
117
|
-
# Note: THROTTLE_LOG already initialized above (line 49)
|
|
118
|
-
|
|
119
|
-
if [[ -n "$US_ID" ]]; then
|
|
120
|
-
# Per-US throttle (60 seconds) - more frequent for targeted updates
|
|
121
|
-
THROTTLE_FILE="$PROJECT_ROOT/.specweave/state/.github-sync-$INC_ID-$US_ID"
|
|
122
|
-
THROTTLE_WINDOW=60
|
|
123
|
-
SYNC_TYPE="US:$US_ID"
|
|
124
|
-
else
|
|
125
|
-
# Per-increment throttle (5 minutes) - less frequent for full sync
|
|
126
|
-
THROTTLE_FILE="$PROJECT_ROOT/.specweave/state/.github-sync-$INC_ID"
|
|
127
|
-
THROTTLE_WINDOW=300
|
|
128
|
-
SYNC_TYPE="increment"
|
|
129
|
-
fi
|
|
130
|
-
|
|
131
|
-
if [[ -f "$THROTTLE_FILE" ]]; then
|
|
132
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
133
|
-
AGE=$(($(date +%s) - $(stat -f %m "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
134
|
-
else
|
|
135
|
-
AGE=$(($(date +%s) - $(stat -c %Y "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
136
|
-
fi
|
|
137
|
-
if [[ $AGE -lt $THROTTLE_WINDOW ]]; then
|
|
138
|
-
REMAINING=$((THROTTLE_WINDOW - AGE))
|
|
139
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] THROTTLED $INC_ID ($SYNC_TYPE, wait ${REMAINING}s)" >> "$THROTTLE_LOG" 2>/dev/null
|
|
140
|
-
exit 0
|
|
141
|
-
fi
|
|
142
|
-
fi
|
|
143
|
-
touch "$THROTTLE_FILE"
|
|
144
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] EXECUTING $INC_ID ($SYNC_TYPE) event=$EVENT_TYPE" >> "$THROTTLE_LOG" 2>/dev/null
|
|
145
|
-
|
|
146
|
-
# Cross-platform timeout wrapper
|
|
147
|
-
# FIXED (v1.0.302): Don't suppress stderr from inner commands — only suppress
|
|
148
|
-
# stderr from timeout/gtimeout binary itself (e.g., "command not found").
|
|
149
|
-
# The caller already redirects stderr to log files via 2>&1.
|
|
150
|
-
run_with_timeout() {
|
|
151
|
-
local timeout_secs="$1"
|
|
152
|
-
shift
|
|
153
|
-
if command -v timeout >/dev/null 2>&1; then
|
|
154
|
-
timeout "$timeout_secs" "$@" || true
|
|
155
|
-
elif command -v gtimeout >/dev/null 2>&1; then
|
|
156
|
-
gtimeout "$timeout_secs" "$@" || true
|
|
157
|
-
else
|
|
158
|
-
"$@" || true
|
|
159
|
-
fi
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
# Load GitHub token - fallback chain mirrors auth-helpers.ts:
|
|
163
|
-
# 1. .env GITHUB_TOKEN (explicit config)
|
|
164
|
-
# 2. .env GH_TOKEN (alternative name)
|
|
165
|
-
# 3. gh auth token (gh CLI - most common for local dev!)
|
|
166
|
-
# FIXED (v1.0.57): Added GH_TOKEN and gh auth fallback - critical for local development!
|
|
167
|
-
GITHUB_TOKEN=""
|
|
168
|
-
|
|
169
|
-
# Try .env GITHUB_TOKEN first
|
|
170
|
-
if [[ -f "$PROJECT_ROOT/.env" ]]; then
|
|
171
|
-
GITHUB_TOKEN=$(grep -E "^GITHUB_TOKEN=" "$PROJECT_ROOT/.env" | cut -d'=' -f2- | tr -d '"'"'")
|
|
172
|
-
# Try GH_TOKEN as alternative
|
|
173
|
-
[[ -z "$GITHUB_TOKEN" ]] && GITHUB_TOKEN=$(grep -E "^GH_TOKEN=" "$PROJECT_ROOT/.env" | cut -d'=' -f2- | tr -d '"'"'")
|
|
174
|
-
fi
|
|
175
|
-
|
|
176
|
-
# Fallback to gh CLI (most common for local development!)
|
|
177
|
-
if [[ -z "$GITHUB_TOKEN" ]] && command -v gh >/dev/null 2>&1; then
|
|
178
|
-
GITHUB_TOKEN=$(gh auth token 2>/dev/null || true)
|
|
179
|
-
if [[ -n "$GITHUB_TOKEN" ]]; then
|
|
180
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Using token from gh auth (not .env)" >> "$THROTTLE_LOG" 2>/dev/null
|
|
181
|
-
fi
|
|
182
|
-
fi
|
|
183
|
-
|
|
184
|
-
if [[ -z "$GITHUB_TOKEN" ]]; then
|
|
185
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] ERROR: No GitHub token found" >> "$THROTTLE_LOG" 2>/dev/null
|
|
186
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Checked: $PROJECT_ROOT/.env (GITHUB_TOKEN, GH_TOKEN)" >> "$THROTTLE_LOG" 2>/dev/null
|
|
187
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Checked: gh auth token (gh CLI not authenticated?)" >> "$THROTTLE_LOG" 2>/dev/null
|
|
188
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Fix: Run 'gh auth login' OR add GITHUB_TOKEN to .env" >> "$THROTTLE_LOG" 2>/dev/null
|
|
189
|
-
exit 0
|
|
190
|
-
fi
|
|
191
|
-
|
|
192
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Token found (length: ${#GITHUB_TOKEN})" >> "$THROTTLE_LOG" 2>/dev/null
|
|
193
|
-
|
|
194
|
-
# Find sync script
|
|
195
|
-
# FIXED (v1.0.46): Support compiled JS AND TypeScript with tsx
|
|
196
|
-
# Priority order:
|
|
197
|
-
# 1. Local development dist/ (compiled JS)
|
|
198
|
-
# 2. Local plugins/ source (TypeScript via tsx)
|
|
199
|
-
# 3. Marketplace cache (compiled JS)
|
|
200
|
-
# 4. Marketplace source (TypeScript via tsx)
|
|
201
|
-
# 5. Legacy CLAUDE_PLUGIN_ROOT
|
|
202
|
-
#
|
|
203
|
-
# Note: Marketplace installations often have .ts source only, not compiled .js
|
|
204
|
-
# We detect this and use tsx (fast TypeScript runner) when available
|
|
205
|
-
|
|
206
|
-
SYNC_SCRIPT=""
|
|
207
|
-
NEEDS_TSX=false
|
|
208
|
-
|
|
209
|
-
# Paths to check - JS files first, then TS files
|
|
210
|
-
# SPECWEAVE_PKG takes priority (resolved from npm package location)
|
|
211
|
-
JS_PATHS=(
|
|
212
|
-
"${SPECWEAVE_PKG:-}/dist/plugins/specweave-github/lib/github-feature-sync-cli.js"
|
|
213
|
-
"$PROJECT_ROOT/dist/plugins/specweave-github/lib/github-feature-sync-cli.js"
|
|
214
|
-
"$HOME/.claude/plugins/cache/specweave/sw-github/*/lib/github-feature-sync-cli.js"
|
|
215
|
-
"${CLAUDE_PLUGIN_ROOT:-}/lib/github-feature-sync-cli.js"
|
|
216
|
-
)
|
|
217
|
-
|
|
218
|
-
TS_PATHS=(
|
|
219
|
-
"${SPECWEAVE_PKG:-}/plugins/specweave-github/lib/github-feature-sync-cli.ts"
|
|
220
|
-
"$PROJECT_ROOT/plugins/specweave-github/lib/github-feature-sync-cli.ts"
|
|
221
|
-
"$HOME/.claude/plugins/marketplaces/specweave/plugins/specweave-github/lib/github-feature-sync-cli.ts"
|
|
222
|
-
"$HOME/.claude/plugins/cache/specweave/sw-github/*/lib/github-feature-sync-cli.ts"
|
|
223
|
-
)
|
|
224
|
-
|
|
225
|
-
# Try JS files first (no tsx needed)
|
|
226
|
-
for pattern in "${JS_PATHS[@]}"; do
|
|
227
|
-
# Handle glob patterns
|
|
228
|
-
for path in $pattern; do
|
|
229
|
-
if [[ -f "$path" ]]; then
|
|
230
|
-
SYNC_SCRIPT="$path"
|
|
231
|
-
break 2
|
|
232
|
-
fi
|
|
233
|
-
done
|
|
234
|
-
done
|
|
235
|
-
|
|
236
|
-
# If no JS found, try TS files (need tsx)
|
|
237
|
-
if [[ -z "$SYNC_SCRIPT" ]]; then
|
|
238
|
-
for pattern in "${TS_PATHS[@]}"; do
|
|
239
|
-
for path in $pattern; do
|
|
240
|
-
if [[ -f "$path" ]]; then
|
|
241
|
-
SYNC_SCRIPT="$path"
|
|
242
|
-
NEEDS_TSX=true
|
|
243
|
-
break 2
|
|
244
|
-
fi
|
|
245
|
-
done
|
|
246
|
-
done
|
|
247
|
-
fi
|
|
248
|
-
|
|
249
|
-
if [[ -z "$SYNC_SCRIPT" ]]; then
|
|
250
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] ERROR: github-feature-sync-cli not found" >> "$THROTTLE_LOG" 2>/dev/null
|
|
251
|
-
echo " Searched JS paths:" >> "$THROTTLE_LOG" 2>/dev/null
|
|
252
|
-
for p in "${JS_PATHS[@]}"; do echo " - $p" >> "$THROTTLE_LOG" 2>/dev/null; done
|
|
253
|
-
echo " Searched TS paths:" >> "$THROTTLE_LOG" 2>/dev/null
|
|
254
|
-
for p in "${TS_PATHS[@]}"; do echo " - $p" >> "$THROTTLE_LOG" 2>/dev/null; done
|
|
255
|
-
exit 0
|
|
256
|
-
fi
|
|
257
|
-
|
|
258
|
-
# Verify tsx is available if needed
|
|
259
|
-
if [[ "$NEEDS_TSX" == "true" ]]; then
|
|
260
|
-
if ! command -v tsx >/dev/null 2>&1 && ! command -v npx >/dev/null 2>&1; then
|
|
261
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] ERROR: Found TS file but tsx/npx not available" >> "$THROTTLE_LOG" 2>/dev/null
|
|
262
|
-
echo " Install tsx: npm install -g tsx" >> "$THROTTLE_LOG" 2>/dev/null
|
|
263
|
-
exit 0
|
|
264
|
-
fi
|
|
265
|
-
fi
|
|
266
|
-
|
|
267
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Found sync script: $SYNC_SCRIPT (tsx=$NEEDS_TSX)" >> "$THROTTLE_LOG" 2>/dev/null
|
|
268
|
-
|
|
269
|
-
# Extract feature ID - check multiple locations in priority order
|
|
270
|
-
# FIXED (v1.0.58): Per ADR-0140, feature_id was REMOVED from metadata.json in v0.29.0
|
|
271
|
-
# Feature ID is now DERIVED from increment ID: 0149-... → FS-149
|
|
272
|
-
#
|
|
273
|
-
# Priority order (v1.0.58):
|
|
274
|
-
# 1. DERIVE from increment ID (PRIMARY - per ADR-0140)
|
|
275
|
-
# 2. metadata.json: epic_id field (for external/brownfield increments)
|
|
276
|
-
# 3. spec.md YAML frontmatter: feature_id: or epic: (explicit override)
|
|
277
|
-
#
|
|
278
|
-
META_FILE="$PROJECT_ROOT/.specweave/increments/$INC_ID/metadata.json"
|
|
279
|
-
SPEC_FILE="$PROJECT_ROOT/.specweave/increments/$INC_ID/spec.md"
|
|
280
|
-
FEATURE_ID=""
|
|
281
|
-
|
|
282
|
-
# Method 0 (v1.0.58): DERIVE from increment ID (PRIMARY method per ADR-0140)
|
|
283
|
-
# Extract leading digits and optional E suffix, format as FS-XXX
|
|
284
|
-
# Examples: 0149-usage-analytics → FS-149, 0111E-external → FS-111E
|
|
285
|
-
INC_NUMBER=$(echo "$INC_ID" | grep -oE '^[0-9]+')
|
|
286
|
-
INC_EXTERNAL=$(echo "$INC_ID" | grep -oE '^[0-9]+E' | grep -o 'E$' || echo "")
|
|
287
|
-
if [[ -n "$INC_NUMBER" ]]; then
|
|
288
|
-
# Remove leading zeros for numeric value, then pad to 3 digits
|
|
289
|
-
INC_NUM_CLEAN=$((10#$INC_NUMBER)) # Force decimal interpretation
|
|
290
|
-
FEATURE_ID=$(printf "FS-%03d%s" "$INC_NUM_CLEAN" "$INC_EXTERNAL")
|
|
291
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Derived feature_id=$FEATURE_ID from increment $INC_ID" >> "$THROTTLE_LOG" 2>/dev/null
|
|
292
|
-
fi
|
|
293
|
-
|
|
294
|
-
# Method 1: Check metadata.json for epic_id (external/brownfield increments only)
|
|
295
|
-
if [[ -z "$FEATURE_ID" ]] && [[ -f "$META_FILE" ]]; then
|
|
296
|
-
FEATURE_ID=$(grep -o '"epic_id"[[:space:]]*:[[:space:]]*"[^"]*"' "$META_FILE" | head -1 | sed 's/.*:[[:space:]]*"\([^"]*\)".*/\1/')
|
|
297
|
-
[[ "$FEATURE_ID" == "null" ]] && FEATURE_ID=""
|
|
298
|
-
fi
|
|
299
|
-
|
|
300
|
-
# Method 2: Check spec.md YAML frontmatter (explicit override)
|
|
301
|
-
if [[ -z "$FEATURE_ID" ]] && [[ -f "$SPEC_FILE" ]]; then
|
|
302
|
-
# Try start-of-line format: feature_id: FS-001 or epic: FS-001
|
|
303
|
-
FEATURE_ID=$(grep -E "^(epic|feature_id|feature):" "$SPEC_FILE" | head -1 | sed 's/.*:[[:space:]]*//' | tr -d '"'"'" | tr -d ' ')
|
|
304
|
-
# Also try indented YAML frontmatter style
|
|
305
|
-
if [[ -z "$FEATURE_ID" ]]; then
|
|
306
|
-
FEATURE_ID=$(grep -E "^[[:space:]]*(epic|feature_id|feature):" "$SPEC_FILE" | head -1 | sed 's/.*:[[:space:]]*//' | tr -d '"'"'" | tr -d ' ')
|
|
307
|
-
fi
|
|
308
|
-
fi
|
|
309
|
-
|
|
310
|
-
if [[ -z "$FEATURE_ID" ]]; then
|
|
311
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] WARNING: No feature ID found" >> "$THROTTLE_LOG" 2>/dev/null
|
|
312
|
-
echo " Increment ID: $INC_ID" >> "$THROTTLE_LOG" 2>/dev/null
|
|
313
|
-
echo " This should not happen - derivation from increment ID should always work" >> "$THROTTLE_LOG" 2>/dev/null
|
|
314
|
-
exit 0
|
|
315
|
-
fi
|
|
316
|
-
|
|
317
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Found feature_id=$FEATURE_ID" >> "$THROTTLE_LOG" 2>/dev/null
|
|
318
|
-
|
|
319
|
-
# Run sync (timeout 60s)
|
|
320
|
-
# The github-feature-sync-cli script will:
|
|
321
|
-
# 1. Find all User Stories in the feature
|
|
322
|
-
# 2. For each US, call updateUserStoryIssue() which:
|
|
323
|
-
# - Updates issue body with latest content
|
|
324
|
-
# - Calculates completion via CompletionCalculator (verifies [x] checkboxes)
|
|
325
|
-
# - CLOSES the issue if ALL ACs and tasks are verified complete
|
|
326
|
-
# - Updates status labels (status:complete, status:active, status:not_started)
|
|
327
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
328
|
-
|
|
329
|
-
# Build the run command based on file type
|
|
330
|
-
if [[ "$NEEDS_TSX" == "true" ]]; then
|
|
331
|
-
# TypeScript file - use tsx or npx tsx
|
|
332
|
-
if command -v tsx >/dev/null 2>&1; then
|
|
333
|
-
RUN_CMD="tsx"
|
|
334
|
-
else
|
|
335
|
-
RUN_CMD="npx tsx"
|
|
336
|
-
fi
|
|
337
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Running: $RUN_CMD $SYNC_SCRIPT $FEATURE_ID" >> "$THROTTLE_LOG" 2>/dev/null
|
|
338
|
-
GITHUB_TOKEN="$GITHUB_TOKEN" run_with_timeout 60 $RUN_CMD "$SYNC_SCRIPT" "$FEATURE_ID" >> "$THROTTLE_LOG" 2>&1
|
|
339
|
-
else
|
|
340
|
-
# JavaScript file - use node directly
|
|
341
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Running: node $SYNC_SCRIPT $FEATURE_ID" >> "$THROTTLE_LOG" 2>/dev/null
|
|
342
|
-
GITHUB_TOKEN="$GITHUB_TOKEN" run_with_timeout 60 node "$SYNC_SCRIPT" "$FEATURE_ID" >> "$THROTTLE_LOG" 2>&1
|
|
343
|
-
fi
|
|
344
|
-
|
|
345
|
-
SYNC_EXIT=$?
|
|
346
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] COMPLETED $INC_ID ($SYNC_TYPE) exit=$SYNC_EXIT" >> "$THROTTLE_LOG" 2>/dev/null
|
|
347
|
-
exit 0
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# living-docs-handler.sh - Sync increment to living docs
|
|
3
|
-
# Called async by processor, non-blocking, error-tolerant
|
|
4
|
-
#
|
|
5
|
-
# IMPORTANT: Never crash Claude, always exit 0
|
|
6
|
-
# v1.0.71 - Fixed: Use specweave package location, not PROJECT_ROOT/dist
|
|
7
|
-
set +e
|
|
8
|
-
|
|
9
|
-
[[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
|
|
10
|
-
|
|
11
|
-
INC_ID="${1:-}"
|
|
12
|
-
[[ -z "$INC_ID" ]] && exit 0
|
|
13
|
-
|
|
14
|
-
# Find project root
|
|
15
|
-
PROJECT_ROOT="$PWD"
|
|
16
|
-
while [[ "$PROJECT_ROOT" != "/" ]] && [[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]]; do
|
|
17
|
-
PROJECT_ROOT=$(dirname "$PROJECT_ROOT")
|
|
18
|
-
done
|
|
19
|
-
[[ ! -f "$PROJECT_ROOT/.specweave/config.json" ]] && exit 0
|
|
20
|
-
|
|
21
|
-
# Resolve specweave package location
|
|
22
|
-
HANDLER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
23
|
-
source "$HANDLER_DIR/../../lib/resolve-package.sh" 2>/dev/null || true
|
|
24
|
-
|
|
25
|
-
# Throttle: max once per minute per increment
|
|
26
|
-
THROTTLE_FILE="$PROJECT_ROOT/.specweave/state/.living-docs-$INC_ID"
|
|
27
|
-
THROTTLE_LOG="$PROJECT_ROOT/.specweave/logs/throttle.log"
|
|
28
|
-
THROTTLE_WINDOW=60 # 1 minute
|
|
29
|
-
mkdir -p "$(dirname "$THROTTLE_LOG")" 2>/dev/null
|
|
30
|
-
|
|
31
|
-
if [[ -f "$THROTTLE_FILE" ]]; then
|
|
32
|
-
if [[ "$(uname)" == "Darwin" ]]; then
|
|
33
|
-
AGE=$(($(date +%s) - $(stat -f %m "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
34
|
-
else
|
|
35
|
-
AGE=$(($(date +%s) - $(stat -c %Y "$THROTTLE_FILE" 2>/dev/null || echo 0)))
|
|
36
|
-
fi
|
|
37
|
-
if [[ $AGE -lt $THROTTLE_WINDOW ]]; then
|
|
38
|
-
REMAINING=$((THROTTLE_WINDOW - AGE))
|
|
39
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [living-docs] THROTTLED $INC_ID (wait ${REMAINING}s)" >> "$THROTTLE_LOG" 2>/dev/null
|
|
40
|
-
exit 0
|
|
41
|
-
fi
|
|
42
|
-
fi
|
|
43
|
-
touch "$THROTTLE_FILE"
|
|
44
|
-
echo "[$(date '+%Y-%m-%d %H:%M:%S')] [living-docs] EXECUTING $INC_ID" >> "$THROTTLE_LOG" 2>/dev/null
|
|
45
|
-
|
|
46
|
-
# Cross-platform timeout wrapper
|
|
47
|
-
run_with_timeout() {
|
|
48
|
-
local timeout_secs="$1"
|
|
49
|
-
shift
|
|
50
|
-
if command -v timeout >/dev/null 2>&1; then
|
|
51
|
-
timeout "$timeout_secs" "$@" 2>/dev/null || true
|
|
52
|
-
elif command -v gtimeout >/dev/null 2>&1; then
|
|
53
|
-
gtimeout "$timeout_secs" "$@" 2>/dev/null || true
|
|
54
|
-
else
|
|
55
|
-
"$@" 2>/dev/null || true
|
|
56
|
-
fi
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
# Find sync script (check SPECWEAVE_PKG first)
|
|
60
|
-
SYNC_SCRIPT=""
|
|
61
|
-
for path in \
|
|
62
|
-
"${SPECWEAVE_PKG:-}/dist/plugins/specweave/lib/hooks/sync-living-docs.js" \
|
|
63
|
-
"${SPECWEAVE_PKG:-}/plugins/specweave/lib/hooks/sync-living-docs.js" \
|
|
64
|
-
"${CLAUDE_PLUGIN_ROOT:-}/lib/hooks/sync-living-docs.js" \
|
|
65
|
-
"$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/sync-living-docs.js" \
|
|
66
|
-
"$PROJECT_ROOT/plugins/specweave/lib/hooks/sync-living-docs.js"; do
|
|
67
|
-
[[ -f "$path" ]] && { SYNC_SCRIPT="$path"; break; }
|
|
68
|
-
done
|
|
69
|
-
[[ -z "$SYNC_SCRIPT" ]] && exit 0
|
|
70
|
-
|
|
71
|
-
# Extract feature ID from spec.md
|
|
72
|
-
SPEC_FILE="$PROJECT_ROOT/.specweave/increments/$INC_ID/spec.md"
|
|
73
|
-
FEATURE_ID=""
|
|
74
|
-
[[ -f "$SPEC_FILE" ]] && FEATURE_ID=$(grep -E "^(epic|feature_id):" "$SPEC_FILE" | head -1 | sed 's/.*:[[:space:]]*//' | tr -d '"'"'")
|
|
75
|
-
|
|
76
|
-
# Run sync (timeout 30s)
|
|
77
|
-
cd "$PROJECT_ROOT" || exit 0
|
|
78
|
-
if [[ -n "$FEATURE_ID" ]]; then
|
|
79
|
-
FEATURE_ID="$FEATURE_ID" run_with_timeout 30 node "$SYNC_SCRIPT" "$INC_ID" >/dev/null 2>&1
|
|
80
|
-
else
|
|
81
|
-
run_with_timeout 30 node "$SYNC_SCRIPT" "$INC_ID" >/dev/null 2>&1
|
|
82
|
-
fi
|
|
83
|
-
exit 0
|