specweave 1.0.44 → 1.0.46

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 CHANGED
@@ -1,10 +1,10 @@
1
- <!-- SW:META template="claude" version="1.0.41" sections="header,start,autodetect,metarule,rules,workflow,structure,taskformat,secrets,syncing,mapping,testing,limits,troubleshooting,principles,linking,docs" -->
1
+ <!-- SW:META template="claude" version="1.0.44" sections="header,start,autodetect,metarule,rules,workflow,structure,taskformat,secrets,syncing,mapping,testing,limits,troubleshooting,principles,linking,docs" -->
2
2
 
3
- <!-- SW:SECTION:header version="1.0.41" -->
3
+ <!-- SW:SECTION:header version="1.0.44" -->
4
4
  **Framework**: SpecWeave | **Truth**: `spec.md` + `tasks.md`
5
5
  <!-- SW:END:header -->
6
6
 
7
- <!-- SW:SECTION:start version="1.0.41" -->
7
+ <!-- SW:SECTION:start version="1.0.44" -->
8
8
  ## Getting Started
9
9
 
10
10
  **Initial increment**: `0001-project-setup` (auto-created by `specweave init`)
@@ -14,7 +14,7 @@
14
14
  2. **Customize**: Edit spec.md and use for setup tasks
15
15
  <!-- SW:END:start -->
16
16
 
17
- <!-- SW:SECTION:autodetect version="1.0.41" -->
17
+ <!-- SW:SECTION:autodetect version="1.0.44" -->
18
18
  ## Auto-Detection
19
19
 
20
20
  SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
@@ -24,7 +24,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
24
24
  **Opt-out phrases**: "Just brainstorm first" | "Don't plan yet" | "Quick discussion" | "Let's explore ideas"
25
25
  <!-- SW:END:autodetect -->
26
26
 
27
- <!-- SW:SECTION:metarule version="1.0.41" -->
27
+ <!-- SW:SECTION:metarule version="1.0.44" -->
28
28
  ## Meta-Rule: Think-Before-Act
29
29
 
30
30
  **Satisfy dependencies BEFORE dependent operations.**
@@ -35,7 +35,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
35
35
  ```
36
36
  <!-- SW:END:metarule -->
37
37
 
38
- <!-- SW:SECTION:rules version="1.0.41" -->
38
+ <!-- SW:SECTION:rules version="1.0.44" -->
39
39
  ## Rules
40
40
 
41
41
  1. **Files** → `.specweave/increments/####-name/` (spec.md, plan.md, tasks.md at root; reports/, scripts/, logs/ subfolders)
@@ -45,7 +45,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
45
45
  5. **Root clean**: NEVER create .md/reports/scripts in project root → use increment folders
46
46
  <!-- SW:END:rules -->
47
47
 
48
- <!-- SW:SECTION:workflow version="1.0.41" -->
48
+ <!-- SW:SECTION:workflow version="1.0.44" -->
49
49
  ## Workflow
50
50
 
51
51
  `/sw:increment "X"` → `/sw:do` → `/sw:progress` → `/sw:done 0001`
@@ -62,7 +62,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
62
62
  **Natural language**: "Let's build X" → `/sw:increment` | "What's status?" → `/sw:progress` | "We're done" → `/sw:done`
63
63
  <!-- SW:END:workflow -->
64
64
 
65
- <!-- SW:SECTION:structure version="1.0.41" -->
65
+ <!-- SW:SECTION:structure version="1.0.44" -->
66
66
  ## Structure
67
67
 
68
68
  ```
@@ -84,7 +84,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
84
84
  **Path syntax**: `//path` = absolute | `/path` = relative to settings file | `**` = recursive | `additionalDirectories` = explicit working dirs
85
85
  <!-- SW:END:structure -->
86
86
 
87
- <!-- SW:SECTION:taskformat version="1.0.41" -->
87
+ <!-- SW:SECTION:taskformat version="1.0.44" -->
88
88
  ## Task Format
89
89
 
90
90
  ```markdown
@@ -94,7 +94,7 @@ SpecWeave auto-detects product descriptions and routes to `/sw:increment`:
94
94
  ```
95
95
  <!-- SW:END:taskformat -->
96
96
 
97
- <!-- SW:SECTION:secrets version="1.0.41" -->
97
+ <!-- SW:SECTION:secrets version="1.0.44" -->
98
98
  ## Secrets Check
99
99
 
100
100
  **BEFORE CLI tools**: Check existing config first!
@@ -105,7 +105,7 @@ gh auth status
105
105
  ```
106
106
  <!-- SW:END:secrets -->
107
107
 
108
- <!-- SW:SECTION:syncing version="1.0.41" -->
108
+ <!-- SW:SECTION:syncing version="1.0.44" -->
109
109
  ## External Sync (GitHub/JIRA/ADO)
110
110
 
111
111
  **After increment creation**: Run `/sw-github:sync {id}` to create issues!
@@ -124,7 +124,7 @@ Living docs sync ≠ External sync. They are separate:
124
124
  **Verify tokens**: `grep GITHUB_TOKEN .env` | `gh auth status`
125
125
  <!-- SW:END:syncing -->
126
126
 
127
- <!-- SW:SECTION:mapping version="1.0.41" -->
127
+ <!-- SW:SECTION:mapping version="1.0.44" -->
128
128
  ## GitHub Mapping
129
129
 
130
130
  | SpecWeave | GitHub |
@@ -134,7 +134,7 @@ Living docs sync ≠ External sync. They are separate:
134
134
  | Task T-XXX | Checkbox |
135
135
  <!-- SW:END:mapping -->
136
136
 
137
- <!-- SW:SECTION:testing version="1.0.41" -->
137
+ <!-- SW:SECTION:testing version="1.0.44" -->
138
138
  ## Testing
139
139
 
140
140
  BDD in tasks.md | Unit >80% | `.test.ts` (Vitest)
@@ -146,13 +146,13 @@ vi.mock('fs', () => ({ readFile: vi.fn() }));
146
146
  ```
147
147
  <!-- SW:END:testing -->
148
148
 
149
- <!-- SW:SECTION:limits version="1.0.41" -->
149
+ <!-- SW:SECTION:limits version="1.0.44" -->
150
150
  ## Limits
151
151
 
152
152
  **Max 1500 lines/file** — extract before adding
153
153
  <!-- SW:END:limits -->
154
154
 
155
- <!-- SW:SECTION:troubleshooting version="1.0.41" -->
155
+ <!-- SW:SECTION:troubleshooting version="1.0.44" -->
156
156
  ## Troubleshooting
157
157
 
158
158
  | Issue | Fix |
@@ -170,7 +170,7 @@ vi.mock('fs', () => ({ readFile: vi.fn() }));
170
170
  | Path patterns not working | `//path` = absolute, `/path` = relative to settings file, `additionalDirectories` for explicit working dirs |
171
171
  <!-- SW:END:troubleshooting -->
172
172
 
173
- <!-- SW:SECTION:principles version="1.0.41" -->
173
+ <!-- SW:SECTION:principles version="1.0.44" -->
174
174
  ## Principles
175
175
 
176
176
  1. **Spec-first**: `/sw:increment` before coding
@@ -180,7 +180,7 @@ vi.mock('fs', () => ({ readFile: vi.fn() }));
180
180
  5. **Clean**: All files in increment folders
181
181
  <!-- SW:END:principles -->
182
182
 
183
- <!-- SW:SECTION:linking version="1.0.41" -->
183
+ <!-- SW:SECTION:linking version="1.0.44" -->
184
184
  ## Bidirectional Linking
185
185
 
186
186
  Tasks ↔ User Stories auto-linked via AC-IDs: `AC-US1-01` → `US-001`
@@ -188,7 +188,7 @@ Tasks ↔ User Stories auto-linked via AC-IDs: `AC-US1-01` → `US-001`
188
188
  Task format: `**AC**: AC-US1-01, AC-US1-02` (CRITICAL for linking)
189
189
  <!-- SW:END:linking -->
190
190
 
191
- <!-- SW:SECTION:docs version="1.0.41" -->
191
+ <!-- SW:SECTION:docs version="1.0.44" -->
192
192
  ## Docs
193
193
 
194
194
  [spec-weave.com](https://spec-weave.com) | `.specweave/docs/internal/`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specweave",
3
- "version": "1.0.44",
3
+ "version": "1.0.46",
4
4
  "description": "Spec-driven development framework for Claude Code. AI-native workflow with living documentation, intelligent agents, and multilingual support (9 languages). Enterprise-grade traceability with permanent specs and temporary increments.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,24 +1,38 @@
1
1
  #!/bin/bash
2
- # github-sync-handler.sh - Sync increment to GitHub (create issues for User Stories)
2
+ # github-sync-handler.sh - Sync increment to GitHub (create/update issues for User Stories)
3
3
  # Called async by processor, non-blocking, error-tolerant
4
4
  #
5
5
  # Argument formats supported:
6
6
  # 1. (event_type, increment_id) - from lifecycle/spec.updated events
7
- # 2. (increment_id) - from metadata.changed events (legacy)
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!
8
12
  #
9
13
  # IMPORTANT: Never crash Claude, always exit 0
10
14
  set +e
11
15
 
12
16
  [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
13
17
 
14
- # Support both argument formats:
15
- # - Called from increment.created/spec.updated: $1 = event_type, $2 = increment_id
16
- # - Called from metadata.changed: $1 = increment_id
17
- INC_ID="${1:-}"
18
- if [[ "$INC_ID" == increment.* ]] || [[ "$INC_ID" == spec.* ]] || [[ "$INC_ID" == metadata.* ]]; then
19
- # First arg is event type, second is increment ID
20
- INC_ID="${2:-}"
18
+ # Parse arguments - support multiple formats
19
+ EVENT_TYPE="${1:-}"
20
+ EVENT_DATA="${2:-}"
21
+ INC_ID=""
22
+ US_ID=""
23
+
24
+ if [[ "$EVENT_TYPE" == user-story.* ]]; then
25
+ # user-story.completed/reopened: $2 = INC_ID:US_ID
26
+ INC_ID="${EVENT_DATA%%:*}"
27
+ US_ID="${EVENT_DATA##*:}"
28
+ elif [[ "$EVENT_TYPE" == increment.* ]] || [[ "$EVENT_TYPE" == spec.* ]] || [[ "$EVENT_TYPE" == metadata.* ]]; then
29
+ # Lifecycle events: $2 = increment_id
30
+ INC_ID="$EVENT_DATA"
31
+ else
32
+ # Legacy format: $1 = increment_id directly
33
+ INC_ID="$EVENT_TYPE"
21
34
  fi
35
+
22
36
  [[ -z "$INC_ID" ]] && exit 0
23
37
 
24
38
  # Find project root
@@ -35,12 +49,24 @@ CONFIG_FILE="$PROJECT_ROOT/.specweave/config.json"
35
49
  GITHUB_ENABLED=$(grep -o '"enabled"[[:space:]]*:[[:space:]]*true' "$CONFIG_FILE" | head -1)
36
50
  [[ -z "$GITHUB_ENABLED" ]] && exit 0
37
51
 
38
- # Throttle: max once per 5 minutes per increment
39
- THROTTLE_FILE="$PROJECT_ROOT/.specweave/state/.github-sync-$INC_ID"
52
+ # Throttle configuration:
53
+ # - Full sync (increment lifecycle): 5 minutes (creates all issues)
54
+ # - US completion sync: 60 seconds (more targeted, less aggressive)
40
55
  THROTTLE_LOG="$PROJECT_ROOT/.specweave/logs/throttle.log"
41
- THROTTLE_WINDOW=300 # 5 minutes
42
56
  mkdir -p "$(dirname "$THROTTLE_LOG")" 2>/dev/null
43
57
 
58
+ if [[ -n "$US_ID" ]]; then
59
+ # Per-US throttle (60 seconds) - more frequent for targeted updates
60
+ THROTTLE_FILE="$PROJECT_ROOT/.specweave/state/.github-sync-$INC_ID-$US_ID"
61
+ THROTTLE_WINDOW=60
62
+ SYNC_TYPE="US:$US_ID"
63
+ else
64
+ # Per-increment throttle (5 minutes) - less frequent for full sync
65
+ THROTTLE_FILE="$PROJECT_ROOT/.specweave/state/.github-sync-$INC_ID"
66
+ THROTTLE_WINDOW=300
67
+ SYNC_TYPE="increment"
68
+ fi
69
+
44
70
  if [[ -f "$THROTTLE_FILE" ]]; then
45
71
  if [[ "$(uname)" == "Darwin" ]]; then
46
72
  AGE=$(($(date +%s) - $(stat -f %m "$THROTTLE_FILE" 2>/dev/null || echo 0)))
@@ -49,12 +75,12 @@ if [[ -f "$THROTTLE_FILE" ]]; then
49
75
  fi
50
76
  if [[ $AGE -lt $THROTTLE_WINDOW ]]; then
51
77
  REMAINING=$((THROTTLE_WINDOW - AGE))
52
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] THROTTLED $INC_ID (wait ${REMAINING}s, use /sw:sync-progress to bypass)" >> "$THROTTLE_LOG" 2>/dev/null
78
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] THROTTLED $INC_ID ($SYNC_TYPE, wait ${REMAINING}s)" >> "$THROTTLE_LOG" 2>/dev/null
53
79
  exit 0
54
80
  fi
55
81
  fi
56
82
  touch "$THROTTLE_FILE"
57
- echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] EXECUTING $INC_ID" >> "$THROTTLE_LOG" 2>/dev/null
83
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] EXECUTING $INC_ID ($SYNC_TYPE) event=$EVENT_TYPE" >> "$THROTTLE_LOG" 2>/dev/null
58
84
 
59
85
  # Cross-platform timeout wrapper
60
86
  run_with_timeout() {
@@ -90,6 +116,16 @@ FEATURE_ID=""
90
116
  [[ -z "$FEATURE_ID" ]] && exit 0
91
117
 
92
118
  # Run sync (timeout 60s)
119
+ # The github-feature-sync-cli.js script will:
120
+ # 1. Find all User Stories in the feature
121
+ # 2. For each US, call updateUserStoryIssue() which:
122
+ # - Updates issue body with latest content
123
+ # - Calculates completion via CompletionCalculator (verifies [x] checkboxes)
124
+ # - CLOSES the issue if ALL ACs and tasks are verified complete
125
+ # - Updates status labels (status:complete, status:active, status:not_started)
93
126
  cd "$PROJECT_ROOT" || exit 0
94
- GITHUB_TOKEN="$GITHUB_TOKEN" run_with_timeout 60 node "$SYNC_SCRIPT" "$FEATURE_ID" >/dev/null 2>&1
127
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] Running: node $SYNC_SCRIPT $FEATURE_ID" >> "$THROTTLE_LOG" 2>/dev/null
128
+ GITHUB_TOKEN="$GITHUB_TOKEN" run_with_timeout 60 node "$SYNC_SCRIPT" "$FEATURE_ID" >> "$THROTTLE_LOG" 2>&1
129
+ SYNC_EXIT=$?
130
+ echo "[$(date '+%Y-%m-%d %H:%M:%S')] [github-sync] COMPLETED $INC_ID ($SYNC_TYPE) exit=$SYNC_EXIT" >> "$THROTTLE_LOG" 2>/dev/null
95
131
  exit 0
@@ -6,11 +6,15 @@
6
6
  #
7
7
  # Event routing (EDA v2):
8
8
  # - increment.created/done/archived/reopened -> living-specs-handler + status-line-handler + project-bridge-handler + github-sync-handler
9
- # - user-story.completed/reopened -> status-line-handler + project-bridge-handler
9
+ # - user-story.completed/reopened -> status-line-handler + project-bridge-handler + github-sync-handler (v1.0.45+: CRITICAL FIX)
10
10
  # - spec.updated -> living-docs-handler + ac-validation-handler + github-sync-handler (creates GitHub issues for User Stories)
11
11
  # - task.updated -> living-docs-handler + ac-validation-handler (legacy)
12
12
  # - metadata.changed -> github-sync-handler
13
13
  #
14
+ # CRITICAL FIX (v1.0.45): user-story.completed now triggers github-sync-handler!
15
+ # Root cause: GitHub issues were CREATED but NEVER UPDATED when User Stories completed.
16
+ # Result: Issues stayed OPEN forever even after all tasks/ACs were marked complete.
17
+ #
14
18
  # The project-bridge-handler connects increment events to project-level EDA,
15
19
  # enabling automatic sync to GitHub, ADO, and JIRA via ProjectService.
16
20
  #
@@ -167,11 +171,15 @@ process_event() {
167
171
  run_handler "$HANDLER_DIR/github-sync-handler.sh" "$EVENT_TYPE" "$EVENT_DATA"
168
172
  ;;
169
173
 
170
- # User story events -> status-line-handler + project-bridge-handler
174
+ # User story events -> status-line-handler + project-bridge-handler + github-sync-handler
175
+ # CRITICAL FIX (v1.0.45): Added github-sync-handler to update GitHub issues when US completes
176
+ # Root cause: user-story.completed was NOT triggering GitHub sync → issues stayed open!
171
177
  user-story.completed|user-story.reopened)
172
178
  run_handler "$HANDLER_DIR/status-line-handler.sh" "$EVENT_TYPE" "$EVENT_DATA"
173
179
  # Bridge to project-level EDA (may trigger issue updates)
174
180
  run_handler "$HANDLER_DIR/project-bridge-handler.sh" "$EVENT_TYPE" "$EVENT_DATA"
181
+ # Sync to GitHub (updates User Story issue status when US completes/reopens)
182
+ run_handler "$HANDLER_DIR/github-sync-handler.sh" "$EVENT_TYPE" "$EVENT_DATA"
175
183
  ;;
176
184
 
177
185
  # Spec updated -> sync to living docs + validate ACs + sync to GitHub