specweave 1.0.22 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +95 -378
  2. package/dist/src/cli/commands/init.d.ts.map +1 -1
  3. package/dist/src/cli/commands/init.js +8 -26
  4. package/dist/src/cli/commands/init.js.map +1 -1
  5. package/dist/src/core/living-docs/cross-project-sync.d.ts +2 -0
  6. package/dist/src/core/living-docs/cross-project-sync.d.ts.map +1 -1
  7. package/dist/src/core/living-docs/cross-project-sync.js +14 -4
  8. package/dist/src/core/living-docs/cross-project-sync.js.map +1 -1
  9. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  10. package/dist/src/core/living-docs/living-docs-sync.js +6 -2
  11. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  12. package/package.json +3 -3
  13. package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
  14. package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
  15. package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
  16. package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
  17. package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
  18. package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
  19. package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
  20. package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
  21. package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
  22. package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
  23. package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
  24. package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
  25. package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
  26. package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
  27. package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
  28. package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
  29. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
  30. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1262 -0
  31. package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
  32. package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
  33. package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
  34. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
  35. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1254 -0
  36. package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
@@ -0,0 +1,79 @@
1
+ #!/bin/bash
2
+
3
+ # SpecWeave Docs-Changed Hook
4
+ # Runs after file changes are detected
5
+ # Detects if documentation was changed during implementation
6
+ # Triggers review workflow if needed
7
+
8
+ set -e
9
+
10
+ # Find project root by searching upward for .specweave/ directory
11
+ # Works regardless of where hook is installed (source or .claude/hooks/)
12
+ find_project_root() {
13
+ local dir="$1"
14
+ while [ "$dir" != "/" ]; do
15
+ if [ -d "$dir/.specweave" ]; then
16
+ echo "$dir"
17
+ return 0
18
+ fi
19
+ dir="$(dirname "$dir")"
20
+ done
21
+ # Fallback: try current directory
22
+ if [ -d "$(pwd)/.specweave" ]; then
23
+ pwd
24
+ else
25
+ echo "$(pwd)"
26
+ fi
27
+ }
28
+
29
+ PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
30
+ cd "$PROJECT_ROOT"
31
+
32
+ # Colors
33
+ RED='\033[0;31m'
34
+ YELLOW='\033[1;33m'
35
+ NC='\033[0m'
36
+
37
+ # Get changed files (git)
38
+ if ! git rev-parse --git-dir > /dev/null 2>&1; then
39
+ # Not a git repository, skip
40
+ exit 0
41
+ fi
42
+
43
+ CHANGED_FILES=$(git diff --name-only HEAD 2>/dev/null || echo "")
44
+
45
+ if [ -z "$CHANGED_FILES" ]; then
46
+ # No changes
47
+ exit 0
48
+ fi
49
+
50
+ # Check if any documentation files changed
51
+ DOC_CHANGES=$(echo "$CHANGED_FILES" | grep -E '\.specweave/(docs|increments/.*/.*\.md)' || true)
52
+
53
+ if [ -n "$DOC_CHANGES" ]; then
54
+ echo -e "${RED}⚠️ Documentation changed during implementation${NC}"
55
+ echo ""
56
+ echo "📋 Files changed:"
57
+ echo "$DOC_CHANGES" | sed 's/^/ /'
58
+ echo ""
59
+ echo -e "${YELLOW}🔔 Recommended actions:${NC}"
60
+ echo " 1. Review documentation changes"
61
+ echo " 2. Update tasks.md if architecture changed"
62
+ echo " 3. Type /review-docs to see full impact"
63
+ echo ""
64
+
65
+ # Play notification sound
66
+ case "$(uname -s)" in
67
+ Darwin)
68
+ afplay /System/Library/Sounds/Ping.aiff 2>/dev/null &
69
+ ;;
70
+ Linux)
71
+ paplay /usr/share/sounds/freedesktop/stereo/dialog-warning.oga 2>/dev/null || true
72
+ ;;
73
+ esac
74
+
75
+ # Log to hooks log
76
+ LOGS_DIR=".specweave/logs"
77
+ mkdir -p "$LOGS_DIR"
78
+ echo "[$(date)] Documentation changed: $DOC_CHANGES" >> "$LOGS_DIR/hooks.log"
79
+ fi
@@ -0,0 +1,75 @@
1
+ #!/bin/bash
2
+
3
+ # SpecWeave Human-Input-Required Hook
4
+ # Runs when Claude needs clarification or approval
5
+ #
6
+ # Actions:
7
+ # 1. Play notification sound (Ping.aiff)
8
+ # 2. Log the question/requirement
9
+ # 3. Record in current increment's work log (if applicable)
10
+
11
+ set -e
12
+
13
+ # Find project root by searching upward for .specweave/ directory
14
+ # Works regardless of where hook is installed (source or .claude/hooks/)
15
+ find_project_root() {
16
+ local dir="$1"
17
+ while [ "$dir" != "/" ]; do
18
+ if [ -d "$dir/.specweave" ]; then
19
+ echo "$dir"
20
+ return 0
21
+ fi
22
+ dir="$(dirname "$dir")"
23
+ done
24
+ # Fallback: try current directory
25
+ if [ -d "$(pwd)/.specweave" ]; then
26
+ pwd
27
+ else
28
+ echo "$(pwd)"
29
+ fi
30
+ }
31
+
32
+ PROJECT_ROOT="$(find_project_root "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")"
33
+ cd "$PROJECT_ROOT"
34
+
35
+ # Get question/requirement (passed as argument or default)
36
+ QUESTION="${1:-User input required}"
37
+
38
+ echo "❓ Human input required"
39
+
40
+ # 1. Play notification sound (cross-platform)
41
+ play_sound() {
42
+ case "$(uname -s)" in
43
+ Darwin)
44
+ afplay /System/Library/Sounds/Ping.aiff 2>/dev/null &
45
+ ;;
46
+ Linux)
47
+ paplay /usr/share/sounds/freedesktop/stereo/dialog-question.oga 2>/dev/null || \
48
+ aplay /usr/share/sounds/alsa/Side_Left.wav 2>/dev/null || true
49
+ ;;
50
+ MINGW*|MSYS*|CYGWIN*)
51
+ powershell -c "(New-Object Media.SoundPlayer 'C:\Windows\Media\notify.wav').PlaySync();" 2>/dev/null || true
52
+ ;;
53
+ esac
54
+ }
55
+
56
+ play_sound &
57
+
58
+ # 2. Log to main hooks log
59
+ LOGS_DIR=".specweave/logs"
60
+ mkdir -p "$LOGS_DIR"
61
+ echo "[$(date)] Human input required: $QUESTION" >> "$LOGS_DIR/hooks.log"
62
+
63
+ # 3. Log to current work context (if exists)
64
+ CURRENT_WORK=$(find .specweave/work -maxdepth 1 -type d -name "current-*" | head -1 || true)
65
+
66
+ if [ -n "$CURRENT_WORK" ] && [ -d "$CURRENT_WORK" ]; then
67
+ echo "" >> "$CURRENT_WORK/notes.md"
68
+ echo "## Input Required ($(date +%Y-%m-%d\ %H:%M))" >> "$CURRENT_WORK/notes.md"
69
+ echo "" >> "$CURRENT_WORK/notes.md"
70
+ echo "$QUESTION" >> "$CURRENT_WORK/notes.md"
71
+ echo "" >> "$CURRENT_WORK/notes.md"
72
+ echo "📝 Logged to $CURRENT_WORK/notes.md"
73
+ fi
74
+
75
+ echo "✅ Hook complete"
@@ -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
@@ -0,0 +1,231 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # Post-Increment-Completion Hook
4
+ # Runs after an increment is marked as complete
5
+ #
6
+ # This hook closes GitHub issues automatically when increments complete
7
+
8
+ set -e
9
+
10
+ HOOK_NAME="post-increment-completion"
11
+ INCREMENT_ID="${1:-}"
12
+
13
+ # Check if increment ID provided
14
+ if [ -z "$INCREMENT_ID" ]; then
15
+ echo "⚠️ $HOOK_NAME: No increment ID provided" >&2
16
+ exit 0
17
+ fi
18
+
19
+ # Get project root
20
+ PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)"
21
+ INCREMENT_DIR="$PROJECT_ROOT/.specweave/increments/$INCREMENT_ID"
22
+
23
+ # Check if increment exists
24
+ if [ ! -d "$INCREMENT_DIR" ]; then
25
+ echo "⚠️ $HOOK_NAME: Increment $INCREMENT_ID not found" >&2
26
+ exit 0
27
+ fi
28
+
29
+ # Read metadata.json
30
+ METADATA_FILE="$INCREMENT_DIR/metadata.json"
31
+ if [ ! -f "$METADATA_FILE" ]; then
32
+ echo "⚠️ $HOOK_NAME: No metadata.json found for $INCREMENT_ID" >&2
33
+ exit 0
34
+ fi
35
+
36
+ # Extract GitHub issue number
37
+ ISSUE_NUMBER=$(jq -r '.github.issue // empty' "$METADATA_FILE" 2>/dev/null)
38
+
39
+ if [ -z "$ISSUE_NUMBER" ] || [ "$ISSUE_NUMBER" = "null" ]; then
40
+ # No GitHub issue linked - skip GitHub closure but continue with sync
41
+ echo "ℹ️ No GitHub issue linked to increment $INCREMENT_ID"
42
+ SKIP_GITHUB_CLOSURE=true
43
+ else
44
+ SKIP_GITHUB_CLOSURE=false
45
+ fi
46
+
47
+ # ============================================================================
48
+ # GITHUB ISSUE CLOSURE (if linked)
49
+ # ============================================================================
50
+
51
+ if [ "$SKIP_GITHUB_CLOSURE" = "false" ]; then
52
+ # Check if gh CLI is available
53
+ if ! command -v gh &> /dev/null; then
54
+ echo "⚠️ $HOOK_NAME: GitHub CLI (gh) not found - skipping issue closure" >&2
55
+ else
56
+ # Check if issue is already closed
57
+ ISSUE_STATE=$(gh issue view "$ISSUE_NUMBER" --json state --jq '.state' 2>/dev/null || echo "")
58
+
59
+ if [ "$ISSUE_STATE" = "CLOSED" ]; then
60
+ echo "✓ GitHub issue #$ISSUE_NUMBER already closed"
61
+ else
62
+ # Close the GitHub issue with completion message
63
+ echo "🔗 Closing GitHub issue #$ISSUE_NUMBER for increment $INCREMENT_ID..."
64
+
65
+ # Create completion comment
66
+ COMPLETION_COMMENT="## ✅ Increment Complete
67
+
68
+ Increment \`$INCREMENT_ID\` has been marked as complete.
69
+
70
+ **Completion Details:**
71
+ - Completed: $(date -u +"%Y-%m-%dT%H:%M:%SZ")
72
+ - All tasks completed
73
+ - Tests passed
74
+ - Documentation updated
75
+
76
+ ---
77
+ 🤖 Auto-closed by SpecWeave post-increment-completion hook"
78
+
79
+ # Close issue with comment
80
+ gh issue close "$ISSUE_NUMBER" --comment "$COMPLETION_COMMENT" 2>/dev/null || {
81
+ echo "⚠️ Failed to close issue #$ISSUE_NUMBER" >&2
82
+ }
83
+
84
+ echo "✅ GitHub issue #$ISSUE_NUMBER closed successfully"
85
+ fi
86
+ fi
87
+ fi
88
+
89
+ # Update status line cache (increment no longer open)
90
+ HOOK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
91
+ bash "$HOOK_DIR/lib/update-status-line.sh" 2>/dev/null || true
92
+
93
+ # ============================================================================
94
+ # SYNC LIVING DOCS (NEW in v0.24.0 - Critical Missing Feature)
95
+ # ============================================================================
96
+ # After increment completes, perform FULL living docs sync to ensure:
97
+ # - Feature specs finalized with all user stories marked complete
98
+ # - ADRs created/updated with final architecture decisions
99
+ # - Architecture docs updated with implementation details
100
+ # - Delivery docs updated with what was shipped
101
+ # - Internal/public docs reflect completed work
102
+ #
103
+ # This is the FINAL, COMPREHENSIVE sync that happens once per increment.
104
+ # (Task-level sync in post-task-completion.sh handles incremental updates)
105
+ #
106
+ # Architecture Decision: Non-blocking execution
107
+ # - If sync fails, log error but don't crash hook (GitHub issue already closed)
108
+ # - Living docs can be manually synced later with /specweave:sync-docs
109
+ # - Failure mode: Graceful degradation (increment still completes)
110
+
111
+ if command -v node &> /dev/null; then
112
+ echo ""
113
+ echo "📚 Performing final living docs sync for increment $INCREMENT_ID..."
114
+
115
+ # ========================================================================
116
+ # EXTRACT FEATURE ID (v0.23.0+)
117
+ # ========================================================================
118
+ # Extract epic field from spec.md frontmatter (e.g., epic: FS-047)
119
+ # This ensures sync uses the explicitly defined feature ID rather than
120
+ # auto-generating one, maintaining traceability with living docs structure.
121
+
122
+ FEATURE_ID=""
123
+ SPEC_MD_PATH="$INCREMENT_DIR/spec.md"
124
+
125
+ if [ -f "$SPEC_MD_PATH" ]; then
126
+ # Extract epic field from YAML frontmatter
127
+ FEATURE_ID=$(awk '
128
+ BEGIN { in_frontmatter=0 }
129
+ /^---$/ {
130
+ if (in_frontmatter == 0) {
131
+ in_frontmatter=1; next
132
+ } else {
133
+ exit
134
+ }
135
+ }
136
+ in_frontmatter == 1 && /^epic:/ {
137
+ gsub(/^epic:[ \t]*/, "");
138
+ gsub(/["'\'']/, "");
139
+ print;
140
+ exit
141
+ }
142
+ ' "$SPEC_MD_PATH" | tr -d '\r\n')
143
+
144
+ if [ -n "$FEATURE_ID" ]; then
145
+ echo " 📎 Using feature ID from spec.md: $FEATURE_ID"
146
+ else
147
+ echo " ℹ️ No epic field found in spec.md - will auto-generate feature ID"
148
+ fi
149
+ else
150
+ echo " ⚠️ spec.md not found at $SPEC_MD_PATH" >&2
151
+ fi
152
+
153
+ # ========================================================================
154
+ # EXTRACT PROJECT ID (v0.20.0+)
155
+ # ========================================================================
156
+ # Extract activeProject from config.json (defaults to "default")
157
+ # Supports multi-project mode where specs are organized by project.
158
+
159
+ PROJECT_ID="default"
160
+ CONFIG_PATH="$PROJECT_ROOT/.specweave/config.json"
161
+
162
+ if [ -f "$CONFIG_PATH" ]; then
163
+ if command -v jq >/dev/null 2>&1; then
164
+ ACTIVE_PROJECT=$(jq -r '.activeProject // "default"' "$CONFIG_PATH" 2>/dev/null || echo "default")
165
+ if [ -n "$ACTIVE_PROJECT" ] && [ "$ACTIVE_PROJECT" != "null" ]; then
166
+ PROJECT_ID="$ACTIVE_PROJECT"
167
+ fi
168
+ fi
169
+ fi
170
+ echo " 📁 Project ID: $PROJECT_ID"
171
+
172
+ # ========================================================================
173
+ # LOCATE SYNC SCRIPT
174
+ # ========================================================================
175
+ # Find sync-living-docs.js in order of preference:
176
+ # 1. In-place compiled (development, esbuild output)
177
+ # 2. Local dist (development, tsc output)
178
+ # 3. node_modules (installed as dependency)
179
+ # 4. Plugin marketplace (Claude Code global installation)
180
+
181
+ SYNC_SCRIPT=""
182
+ if [ -f "$PROJECT_ROOT/plugins/specweave/lib/hooks/sync-living-docs.js" ]; then
183
+ # Development: Use in-place compiled hooks (esbuild, not tsc)
184
+ SYNC_SCRIPT="$PROJECT_ROOT/plugins/specweave/lib/hooks/sync-living-docs.js"
185
+ echo " 🔧 Using in-place compiled hook (development mode)"
186
+ elif [ -f "$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/sync-living-docs.js" ]; then
187
+ # Development: Use project's compiled files (has node_modules)
188
+ SYNC_SCRIPT="$PROJECT_ROOT/dist/plugins/specweave/lib/hooks/sync-living-docs.js"
189
+ echo " 🔧 Using local dist (development mode)"
190
+ elif [ -f "$PROJECT_ROOT/node_modules/specweave/dist/plugins/specweave/lib/hooks/sync-living-docs.js" ]; then
191
+ # Installed as dependency: Use node_modules version
192
+ SYNC_SCRIPT="$PROJECT_ROOT/node_modules/specweave/dist/plugins/specweave/lib/hooks/sync-living-docs.js"
193
+ echo " 📦 Using node_modules version"
194
+ elif [ -n "${CLAUDE_PLUGIN_ROOT}" ] && [ -f "${CLAUDE_PLUGIN_ROOT}/lib/hooks/sync-living-docs.js" ]; then
195
+ # Fallback: Plugin marketplace (may fail if deps missing)
196
+ SYNC_SCRIPT="${CLAUDE_PLUGIN_ROOT}/lib/hooks/sync-living-docs.js"
197
+ echo " 🌐 Using plugin marketplace version"
198
+ fi
199
+
200
+ # ========================================================================
201
+ # EXECUTE SYNC
202
+ # ========================================================================
203
+ # Run living docs sync with feature ID and project ID
204
+ # Non-blocking: Errors logged but don't crash hook
205
+
206
+ if [ -n "$SYNC_SCRIPT" ]; then
207
+ # Pass FEATURE_ID and PROJECT_ID as environment variables if available
208
+ if [ -n "$FEATURE_ID" ]; then
209
+ (cd "$PROJECT_ROOT" && FEATURE_ID="$FEATURE_ID" PROJECT_ID="$PROJECT_ID" node "$SYNC_SCRIPT" "$INCREMENT_ID") 2>&1 || {
210
+ echo " ⚠️ Failed to sync living docs (non-blocking - you can run /specweave:sync-docs manually)" >&2
211
+ }
212
+ else
213
+ # No explicit feature ID - sync will auto-generate
214
+ (cd "$PROJECT_ROOT" && PROJECT_ID="$PROJECT_ID" node "$SYNC_SCRIPT" "$INCREMENT_ID") 2>&1 || {
215
+ echo " ⚠️ Failed to sync living docs (non-blocking - you can run /specweave:sync-docs manually)" >&2
216
+ }
217
+ fi
218
+ echo " ✅ Living docs sync complete"
219
+ echo ""
220
+ else
221
+ echo " ⚠️ sync-living-docs.js not found in any location - skipping living docs sync" >&2
222
+ echo " 💡 To manually sync: /specweave:sync-docs update" >&2
223
+ echo ""
224
+ fi
225
+ else
226
+ echo " ⚠️ Node.js not found - skipping living docs sync" >&2
227
+ echo " 💡 Install Node.js to enable automatic living docs sync" >&2
228
+ echo ""
229
+ fi
230
+
231
+ exit 0