specweave 0.32.10 → 0.33.3

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 (224) hide show
  1. package/CLAUDE.md +162 -1
  2. package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts +120 -0
  3. package/dist/plugins/specweave-ado/lib/per-us-sync.d.ts.map +1 -0
  4. package/dist/plugins/specweave-ado/lib/per-us-sync.js +276 -0
  5. package/dist/plugins/specweave-ado/lib/per-us-sync.js.map +1 -0
  6. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts +4 -1
  7. package/dist/plugins/specweave-github/lib/github-client-v2.d.ts.map +1 -1
  8. package/dist/plugins/specweave-github/lib/github-client-v2.js +13 -3
  9. package/dist/plugins/specweave-github/lib/github-client-v2.js.map +1 -1
  10. package/dist/plugins/specweave-github/lib/per-us-sync.d.ts +97 -0
  11. package/dist/plugins/specweave-github/lib/per-us-sync.d.ts.map +1 -0
  12. package/dist/plugins/specweave-github/lib/per-us-sync.js +274 -0
  13. package/dist/plugins/specweave-github/lib/per-us-sync.js.map +1 -0
  14. package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts +113 -0
  15. package/dist/plugins/specweave-jira/lib/per-us-sync.d.ts.map +1 -0
  16. package/dist/plugins/specweave-jira/lib/per-us-sync.js +254 -0
  17. package/dist/plugins/specweave-jira/lib/per-us-sync.js.map +1 -0
  18. package/dist/src/cli/add-child-pid.d.ts +11 -0
  19. package/dist/src/cli/add-child-pid.d.ts.map +1 -0
  20. package/dist/src/cli/add-child-pid.js +42 -0
  21. package/dist/src/cli/add-child-pid.js.map +1 -0
  22. package/dist/src/cli/add-child-process.d.ts +15 -0
  23. package/dist/src/cli/add-child-process.d.ts.map +1 -0
  24. package/dist/src/cli/add-child-process.js +40 -0
  25. package/dist/src/cli/add-child-process.js.map +1 -0
  26. package/dist/src/cli/check-watchdog.d.ts +15 -0
  27. package/dist/src/cli/check-watchdog.d.ts.map +1 -0
  28. package/dist/src/cli/check-watchdog.js +47 -0
  29. package/dist/src/cli/check-watchdog.js.map +1 -0
  30. package/dist/src/cli/cleanup-zombies.d.ts +14 -0
  31. package/dist/src/cli/cleanup-zombies.d.ts.map +1 -0
  32. package/dist/src/cli/cleanup-zombies.js +268 -0
  33. package/dist/src/cli/cleanup-zombies.js.map +1 -0
  34. package/dist/src/cli/find-session-by-pid.d.ts +14 -0
  35. package/dist/src/cli/find-session-by-pid.d.ts.map +1 -0
  36. package/dist/src/cli/find-session-by-pid.js +45 -0
  37. package/dist/src/cli/find-session-by-pid.js.map +1 -0
  38. package/dist/src/cli/get-stale-sessions.d.ts +17 -0
  39. package/dist/src/cli/get-stale-sessions.d.ts.map +1 -0
  40. package/dist/src/cli/get-stale-sessions.js +36 -0
  41. package/dist/src/cli/get-stale-sessions.js.map +1 -0
  42. package/dist/src/cli/register-session.d.ts +16 -0
  43. package/dist/src/cli/register-session.d.ts.map +1 -0
  44. package/dist/src/cli/register-session.js +48 -0
  45. package/dist/src/cli/register-session.js.map +1 -0
  46. package/dist/src/cli/remove-session.d.ts +11 -0
  47. package/dist/src/cli/remove-session.d.ts.map +1 -0
  48. package/dist/src/cli/remove-session.js +36 -0
  49. package/dist/src/cli/remove-session.js.map +1 -0
  50. package/dist/src/cli/update-heartbeat.d.ts +11 -0
  51. package/dist/src/cli/update-heartbeat.d.ts.map +1 -0
  52. package/dist/src/cli/update-heartbeat.js +36 -0
  53. package/dist/src/cli/update-heartbeat.js.map +1 -0
  54. package/dist/src/config/types.d.ts +1208 -203
  55. package/dist/src/config/types.d.ts.map +1 -1
  56. package/dist/src/core/background/job-manager.d.ts +16 -0
  57. package/dist/src/core/background/job-manager.d.ts.map +1 -1
  58. package/dist/src/core/background/job-manager.js +110 -15
  59. package/dist/src/core/background/job-manager.js.map +1 -1
  60. package/dist/src/core/config/config-manager.d.ts.map +1 -1
  61. package/dist/src/core/config/config-manager.js +58 -0
  62. package/dist/src/core/config/config-manager.js.map +1 -1
  63. package/dist/src/core/config/types.d.ts +80 -0
  64. package/dist/src/core/config/types.d.ts.map +1 -1
  65. package/dist/src/core/config/types.js.map +1 -1
  66. package/dist/src/core/increment/increment-utils.d.ts +26 -1
  67. package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
  68. package/dist/src/core/increment/increment-utils.js +66 -4
  69. package/dist/src/core/increment/increment-utils.js.map +1 -1
  70. package/dist/src/core/increment/status-change-sync-trigger.d.ts +3 -1
  71. package/dist/src/core/increment/status-change-sync-trigger.d.ts.map +1 -1
  72. package/dist/src/core/increment/status-change-sync-trigger.js +5 -2
  73. package/dist/src/core/increment/status-change-sync-trigger.js.map +1 -1
  74. package/dist/src/core/living-docs/cross-project-sync.d.ts +87 -15
  75. package/dist/src/core/living-docs/cross-project-sync.d.ts.map +1 -1
  76. package/dist/src/core/living-docs/cross-project-sync.js +147 -28
  77. package/dist/src/core/living-docs/cross-project-sync.js.map +1 -1
  78. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts.map +1 -1
  79. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +48 -12
  80. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -1
  81. package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.d.ts +70 -0
  82. package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.d.ts.map +1 -0
  83. package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.js +188 -0
  84. package/dist/src/core/living-docs/intelligent-analyzer/cache-manager.js.map +1 -0
  85. package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.d.ts +33 -0
  86. package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.d.ts.map +1 -0
  87. package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.js +290 -0
  88. package/dist/src/core/living-docs/intelligent-analyzer/dashboard-generator.js.map +1 -0
  89. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts.map +1 -1
  90. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js +114 -11
  91. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js.map +1 -1
  92. package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.d.ts +23 -0
  93. package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.d.ts.map +1 -0
  94. package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.js +283 -0
  95. package/dist/src/core/living-docs/intelligent-analyzer/graph-visualizer.js.map +1 -0
  96. package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.d.ts +44 -0
  97. package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.d.ts.map +1 -0
  98. package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.js +61 -0
  99. package/dist/src/core/living-docs/intelligent-analyzer/mermaid-generator.js.map +1 -0
  100. package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.d.ts +126 -0
  101. package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.d.ts.map +1 -0
  102. package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.js +378 -0
  103. package/dist/src/core/living-docs/intelligent-analyzer/orchestrator.js.map +1 -0
  104. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -1
  105. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +57 -0
  106. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -1
  107. package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.d.ts +82 -0
  108. package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.d.ts.map +1 -0
  109. package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.js +430 -0
  110. package/dist/src/core/living-docs/intelligent-analyzer/pattern-analyzer.js.map +1 -0
  111. package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.d.ts +84 -0
  112. package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.d.ts.map +1 -0
  113. package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.js +387 -0
  114. package/dist/src/core/living-docs/intelligent-analyzer/repo-scanner.js.map +1 -0
  115. package/dist/src/core/living-docs/intelligent-analyzer/report-writer.d.ts +61 -0
  116. package/dist/src/core/living-docs/intelligent-analyzer/report-writer.d.ts.map +1 -0
  117. package/dist/src/core/living-docs/intelligent-analyzer/report-writer.js +174 -0
  118. package/dist/src/core/living-docs/intelligent-analyzer/report-writer.js.map +1 -0
  119. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +1 -1
  120. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -1
  121. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  122. package/dist/src/core/living-docs/living-docs-sync.js +26 -22
  123. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  124. package/dist/src/core/living-docs/module-analyzer.d.ts +3 -0
  125. package/dist/src/core/living-docs/module-analyzer.d.ts.map +1 -1
  126. package/dist/src/core/living-docs/module-analyzer.js +40 -1
  127. package/dist/src/core/living-docs/module-analyzer.js.map +1 -1
  128. package/dist/src/core/living-docs/types.d.ts +24 -3
  129. package/dist/src/core/living-docs/types.d.ts.map +1 -1
  130. package/dist/src/core/qa/qa-runner.js +1 -1
  131. package/dist/src/core/qa/qa-runner.js.map +1 -1
  132. package/dist/src/core/scheduler/session-sync-executor.js +1 -1
  133. package/dist/src/core/scheduler/session-sync-executor.js.map +1 -1
  134. package/dist/src/core/status-line/status-line-updater.d.ts +1 -1
  135. package/dist/src/core/status-line/status-line-updater.d.ts.map +1 -1
  136. package/dist/src/core/status-line/status-line-updater.js +4 -3
  137. package/dist/src/core/status-line/status-line-updater.js.map +1 -1
  138. package/dist/src/core/types/config.d.ts +79 -0
  139. package/dist/src/core/types/config.d.ts.map +1 -1
  140. package/dist/src/core/types/config.js.map +1 -1
  141. package/dist/src/importers/jira-importer.d.ts.map +1 -1
  142. package/dist/src/importers/jira-importer.js +18 -9
  143. package/dist/src/importers/jira-importer.js.map +1 -1
  144. package/dist/src/init/architecture/types.d.ts +140 -33
  145. package/dist/src/init/architecture/types.d.ts.map +1 -1
  146. package/dist/src/init/compliance/types.d.ts +27 -30
  147. package/dist/src/init/compliance/types.d.ts.map +1 -1
  148. package/dist/src/init/repo/types.d.ts +34 -11
  149. package/dist/src/init/repo/types.d.ts.map +1 -1
  150. package/dist/src/init/research/src/config/types.d.ts +82 -15
  151. package/dist/src/init/research/src/config/types.d.ts.map +1 -1
  152. package/dist/src/init/research/types.d.ts +93 -38
  153. package/dist/src/init/research/types.d.ts.map +1 -1
  154. package/dist/src/init/team/types.d.ts +42 -4
  155. package/dist/src/init/team/types.d.ts.map +1 -1
  156. package/dist/src/sync/ado-reconciler.js +1 -1
  157. package/dist/src/sync/ado-reconciler.js.map +1 -1
  158. package/dist/src/sync/github-reconciler.js +1 -1
  159. package/dist/src/sync/github-reconciler.js.map +1 -1
  160. package/dist/src/sync/jira-reconciler.js +1 -1
  161. package/dist/src/sync/jira-reconciler.js.map +1 -1
  162. package/dist/src/sync/sync-coordinator.d.ts +20 -0
  163. package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
  164. package/dist/src/sync/sync-coordinator.js +258 -33
  165. package/dist/src/sync/sync-coordinator.js.map +1 -1
  166. package/dist/src/types/session.d.ts +65 -0
  167. package/dist/src/types/session.d.ts.map +1 -0
  168. package/dist/src/types/session.js +8 -0
  169. package/dist/src/types/session.js.map +1 -0
  170. package/dist/src/utils/lock-manager.d.ts +48 -0
  171. package/dist/src/utils/lock-manager.d.ts.map +1 -0
  172. package/dist/src/utils/lock-manager.js +195 -0
  173. package/dist/src/utils/lock-manager.js.map +1 -0
  174. package/dist/src/utils/notification-manager.d.ts +45 -0
  175. package/dist/src/utils/notification-manager.d.ts.map +1 -0
  176. package/dist/src/utils/notification-manager.js +130 -0
  177. package/dist/src/utils/notification-manager.js.map +1 -0
  178. package/dist/src/utils/platform-utils.d.ts +136 -0
  179. package/dist/src/utils/platform-utils.d.ts.map +1 -0
  180. package/dist/src/utils/platform-utils.js +366 -0
  181. package/dist/src/utils/platform-utils.js.map +1 -0
  182. package/dist/src/utils/project-resolver.d.ts +156 -0
  183. package/dist/src/utils/project-resolver.d.ts.map +1 -0
  184. package/dist/src/utils/project-resolver.js +587 -0
  185. package/dist/src/utils/project-resolver.js.map +1 -0
  186. package/dist/src/utils/session-registry.d.ts +142 -0
  187. package/dist/src/utils/session-registry.d.ts.map +1 -0
  188. package/dist/src/utils/session-registry.js +480 -0
  189. package/dist/src/utils/session-registry.js.map +1 -0
  190. package/package.json +5 -2
  191. package/plugins/specweave/commands/specweave-living-docs.md +42 -0
  192. package/plugins/specweave/hooks/hooks.json +20 -0
  193. package/plugins/specweave/hooks/lib/update-active-increment.sh +2 -2
  194. package/plugins/specweave/hooks/lib/update-status-line.sh +1 -1
  195. package/plugins/specweave/hooks/post-increment-status-change.sh +3 -3
  196. package/plugins/specweave/hooks/post-metadata-change.sh +1 -1
  197. package/plugins/specweave/hooks/universal/hook-wrapper.cmd +26 -26
  198. package/plugins/specweave/hooks/universal/session-start.cmd +16 -16
  199. package/plugins/specweave/hooks/universal/session-start.ps1 +16 -16
  200. package/plugins/specweave/hooks/user-prompt-submit.sh +107 -5
  201. package/plugins/specweave/hooks/v2/guards/increment-root-guard.sh +61 -0
  202. package/plugins/specweave/hooks/v2/guards/per-us-project-validator.sh +281 -0
  203. package/plugins/specweave/hooks/v2/handlers/living-specs-handler.sh +29 -0
  204. package/plugins/specweave/hooks/v2/session-end.sh +69 -0
  205. package/plugins/specweave/hooks/v2/session-start.sh +81 -0
  206. package/plugins/specweave/lib/vendor/sync/github-reconciler.js +1 -1
  207. package/plugins/specweave/lib/vendor/sync/github-reconciler.js.map +1 -1
  208. package/plugins/specweave/scripts/heartbeat.sh +110 -0
  209. package/plugins/specweave/scripts/progress.js +34 -4
  210. package/plugins/specweave/scripts/read-jobs.sh +1 -1
  211. package/plugins/specweave/scripts/read-progress.sh +50 -5
  212. package/plugins/specweave/scripts/read-workflow.sh +1 -1
  213. package/plugins/specweave/scripts/session-watchdog.sh +65 -0
  214. package/plugins/specweave/scripts/status.js +28 -11
  215. package/plugins/specweave-ado/lib/per-us-sync.js +247 -0
  216. package/plugins/specweave-ado/lib/per-us-sync.ts +410 -0
  217. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +738 -0
  218. package/plugins/specweave-github/lib/github-client-v2.js +10 -3
  219. package/plugins/specweave-github/lib/github-client-v2.ts +15 -3
  220. package/plugins/specweave-github/lib/per-us-sync.js +241 -0
  221. package/plugins/specweave-github/lib/per-us-sync.ts +375 -0
  222. package/plugins/specweave-jira/lib/per-us-sync.js +224 -0
  223. package/plugins/specweave-jira/lib/per-us-sync.ts +366 -0
  224. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1107 -0
@@ -31,6 +31,7 @@ Launch the Living Docs Builder independently of `specweave init`. This is essent
31
31
  | `--sources <folders>` | Additional doc folders (comma-separated): `docs/,wiki/` |
32
32
  | `--depends-on <jobIds>` | Wait for jobs before starting (comma-separated) |
33
33
  | `--foreground` | Run in current session instead of background |
34
+ | `--full` | Force full rebuild by clearing cache and checkpoints (bypasses incremental mode) |
34
35
 
35
36
  ---
36
37
 
@@ -73,6 +74,9 @@ Launch the Living Docs Builder independently of `specweave init`. This is essent
73
74
 
74
75
  # AI-powered deep analysis (FREE with MAX subscription)
75
76
  /specweave:living-docs --depth deep-native --priority core,api
77
+
78
+ # Force full rebuild (clears cache and checkpoints)
79
+ /specweave:living-docs --full --depth standard
76
80
  ```
77
81
 
78
82
  ---
@@ -220,6 +224,44 @@ The job will:
220
224
 
221
225
  ---
222
226
 
227
+ ## Update Summary (v0.33.0+)
228
+
229
+ After completion, you'll see a detailed summary showing:
230
+
231
+ ```
232
+ ✅ LIVING DOCS UPDATE COMPLETE
233
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
234
+
235
+ 📊 SUMMARY:
236
+
237
+ Discovery: Discovered 3 repos (2,845 files)
238
+ Duration: 5s
239
+
240
+ Analysis: Analyzed 3 repos
241
+ Duration: 127s
242
+
243
+ Synthesis: Generated 12 ADRs, 4 teams
244
+ Duration: 43s
245
+
246
+ Files Created: 47
247
+ • .specweave/docs/internal/repos/main/overview.md
248
+ • .specweave/docs/internal/repos/main/api-surface.md
249
+ • .specweave/docs/internal/architecture/system-architecture.md
250
+ • .specweave/docs/internal/architecture/adr/0001-typescript-migration.md
251
+ • .specweave/docs/internal/architecture/adr/0002-plugin-system.md
252
+ ... and 42 more
253
+
254
+ Files Updated: 8
255
+ • .specweave/docs/internal/modules/auth.md
256
+ • .specweave/docs/internal/modules/payments.md
257
+ ... and 6 more
258
+
259
+ Total Duration: 175s
260
+ Mode: INCREMENTAL (cache used)
261
+
262
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
263
+ ```
264
+
223
265
  ## Output Files
224
266
 
225
267
  After completion:
@@ -50,6 +50,16 @@
50
50
  }
51
51
  ]
52
52
  },
53
+ {
54
+ "matcher": "Write",
55
+ "matcher_content": "\\.specweave/increments/\\d{3,4}E?-[^/]+/spec\\.md",
56
+ "hooks": [
57
+ {
58
+ "type": "command",
59
+ "command": "bash -c 'W=\"${CLAUDE_PLUGIN_ROOT}/hooks/universal/fail-fast-wrapper.sh\"; S=\"${CLAUDE_PLUGIN_ROOT}/hooks/v2/guards/per-us-project-validator.sh\"; [[ -x \"$W\" ]] && exec \"$W\" \"$S\" || (cat >/dev/null && printf \"{\\\"decision\\\":\\\"allow\\\"}\")'"
60
+ }
61
+ ]
62
+ },
53
63
  {
54
64
  "matcher": "Write|Edit",
55
65
  "matcher_content": "\\.specweave/docs/internal/specs/_features/",
@@ -69,6 +79,16 @@
69
79
  "command": "bash -c 'W=\"${CLAUDE_PLUGIN_ROOT}/hooks/universal/fail-fast-wrapper.sh\"; S=\"${CLAUDE_PLUGIN_ROOT}/hooks/v2/guards/increment-duplicate-guard.sh\"; [[ -x \"$W\" ]] && exec \"$W\" \"$S\" || (cat >/dev/null && printf \"{\\\"decision\\\":\\\"allow\\\"}\")'"
70
80
  }
71
81
  ]
82
+ },
83
+ {
84
+ "matcher": "Write",
85
+ "matcher_content": "\\.specweave/increments/\\d{3,4}E?-[^/]+/[^/]+$",
86
+ "hooks": [
87
+ {
88
+ "type": "command",
89
+ "command": "bash -c 'W=\"${CLAUDE_PLUGIN_ROOT}/hooks/universal/fail-fast-wrapper.sh\"; S=\"${CLAUDE_PLUGIN_ROOT}/hooks/v2/guards/increment-root-guard.sh\"; [[ -x \"$W\" ]] && exec \"$W\" \"$S\" || (cat >/dev/null && printf \"{\\\"decision\\\":\\\"allow\\\"}\")'"
90
+ }
91
+ ]
72
92
  }
73
93
  ],
74
94
  "PostToolUse": [
@@ -37,7 +37,7 @@ mkdir -p "$STATE_DIR" 2>/dev/null || true
37
37
  # ============================================================================
38
38
  # SCAN ALL INCREMENTS FOR ACTIVE STATUS
39
39
  # ============================================================================
40
- # Strategy: Scan metadata.json files for status=active|planning|in-progress
40
+ # Strategy: Scan metadata.json files for status=active|planning|backlog|ready_for_review
41
41
  # This matches what ActiveIncrementManager.smartUpdate() does in TypeScript
42
42
 
43
43
  ACTIVE_IDS=()
@@ -54,7 +54,7 @@ while IFS= read -r metadata_file; do
54
54
  fi
55
55
 
56
56
  # Check if status is active-like
57
- if [[ "$status" == "active" ]] || [[ "$status" == "planning" ]] || [[ "$status" == "in-progress" ]]; then
57
+ if [[ "$status" == "active" ]] || [[ "$status" == "planning" ]] || [[ "$status" == "backlog" ]] || [[ "$status" == "ready_for_review" ]]; then
58
58
  increment_id=$(basename "$(dirname "$metadata_file")")
59
59
  ACTIVE_IDS+=("$increment_id")
60
60
  echo "[$(date)] update-active-increment: Found active: $increment_id (status: $status)" >> "$DEBUG_LOG" 2>/dev/null || true
@@ -129,7 +129,7 @@ while IFS= read -r metadata_file; do
129
129
  fi
130
130
 
131
131
  # Check if active
132
- if [[ "$status" == "active" || "$status" == "planning" || "$status" == "in-progress" ]]; then
132
+ if [[ "$status" == "active" || "$status" == "planning" || "$status" == "backlog" || "$status" == "ready_for_review" ]]; then
133
133
  OPEN_COUNT=$((OPEN_COUNT + 1))
134
134
  increment_id=$(basename "$(dirname "$metadata_file")")
135
135
 
@@ -62,7 +62,7 @@ echo "[$(date)] 📊 Status changed: $NEW_STATUS" >> "$DEBUG_LOG" 2>/dev/null ||
62
62
 
63
63
  # Validate status
64
64
  case "$NEW_STATUS" in
65
- paused|resumed|abandoned|active|in-progress)
65
+ paused|abandoned|active|planning|backlog|ready_for_review|completed)
66
66
  ;;
67
67
  *)
68
68
  echo "[$(date)] ⚠️ Unknown status: $NEW_STATUS (skipping sync)" >> "$DEBUG_LOG" 2>/dev/null || true
@@ -107,11 +107,11 @@ fi
107
107
  # ============================================================================
108
108
 
109
109
  case "$NEW_STATUS" in
110
- resumed|active|in-progress)
110
+ active|planning|backlog|ready_for_review)
111
111
  # ========================================================================
112
112
  # REOPEN GitHub Issues (NEW)
113
113
  # ========================================================================
114
- # When increment is resumed, reopen all closed GitHub issues
114
+ # When increment becomes active (including resumed from pause), reopen all closed GitHub issues
115
115
  echo "[$(date)] ▶️ Status is $NEW_STATUS - checking if issues need reopening" >> "$DEBUG_LOG" 2>/dev/null || true
116
116
 
117
117
  if command -v node &> /dev/null; then
@@ -224,7 +224,7 @@ case "$CURRENT_STATUS" in
224
224
  bash "$HOOK_DIR/lib/update-status-line.sh" --force 2>/dev/null || true
225
225
  ;;
226
226
 
227
- active|planning|in-progress)
227
+ active|planning|backlog|ready_for_review)
228
228
  # Increment became active - MUST register in active-increment.json!
229
229
  # CRITICAL FIX (v0.26.15): post-task-completion.sh depends on this file
230
230
  # Without registration, ALL sync operations are skipped!
@@ -1,26 +1,26 @@
1
- @echo off
2
- REM hook-wrapper.cmd - Windows resilient hook launcher
3
- REM Prevents crashes when dispatcher.mjs is temporarily unavailable
4
-
5
- setlocal enabledelayedexpansion
6
-
7
- set "HOOK_TYPE=%~1"
8
- if "%HOOK_TYPE%"=="" set "HOOK_TYPE=unknown"
9
-
10
- set "SCRIPT_DIR=%~dp0"
11
- set "DISPATCHER=%SCRIPT_DIR%dispatcher.mjs"
12
-
13
- REM Check if dispatcher exists
14
- if not exist "%DISPATCHER%" (
15
- echo {"continue":true,"systemMessage":"Hook skipped: dispatcher.mjs not found"}
16
- exit /b 0
17
- )
18
-
19
- REM Run dispatcher with error suppression
20
- node "%DISPATCHER%" "%HOOK_TYPE%" 2>nul
21
- if errorlevel 1 (
22
- echo {"continue":true,"systemMessage":"Hook error, continuing"}
23
- exit /b 0
24
- )
25
-
26
- exit /b 0
1
+ @echo off
2
+ REM hook-wrapper.cmd - Windows resilient hook launcher
3
+ REM Prevents crashes when dispatcher.mjs is temporarily unavailable
4
+
5
+ setlocal enabledelayedexpansion
6
+
7
+ set "HOOK_TYPE=%~1"
8
+ if "%HOOK_TYPE%"=="" set "HOOK_TYPE=unknown"
9
+
10
+ set "SCRIPT_DIR=%~dp0"
11
+ set "DISPATCHER=%SCRIPT_DIR%dispatcher.mjs"
12
+
13
+ REM Check if dispatcher exists
14
+ if not exist "%DISPATCHER%" (
15
+ echo {"continue":true,"systemMessage":"Hook skipped: dispatcher.mjs not found"}
16
+ exit /b 0
17
+ )
18
+
19
+ REM Run dispatcher with error suppression
20
+ node "%DISPATCHER%" "%HOOK_TYPE%" 2>nul
21
+ if errorlevel 1 (
22
+ echo {"continue":true,"systemMessage":"Hook error, continuing"}
23
+ exit /b 0
24
+ )
25
+
26
+ exit /b 0
@@ -1,16 +1,16 @@
1
- @echo off
2
- :: Universal Session Start Hook for Windows
3
- :: Calls the Node.js dispatcher
4
-
5
- :: Find node.exe
6
- where node >nul 2>&1
7
- if %ERRORLEVEL% neq 0 (
8
- echo {"continue": true, "error": "Node.js not found"}
9
- exit /b 0
10
- )
11
-
12
- :: Get the directory of this script
13
- set "SCRIPT_DIR=%~dp0"
14
-
15
- :: Run the dispatcher
16
- node "%SCRIPT_DIR%dispatcher.mjs" session-start
1
+ @echo off
2
+ :: Universal Session Start Hook for Windows
3
+ :: Calls the Node.js dispatcher
4
+
5
+ :: Find node.exe
6
+ where node >nul 2>&1
7
+ if %ERRORLEVEL% neq 0 (
8
+ echo {"continue": true, "error": "Node.js not found"}
9
+ exit /b 0
10
+ )
11
+
12
+ :: Get the directory of this script
13
+ set "SCRIPT_DIR=%~dp0"
14
+
15
+ :: Run the dispatcher
16
+ node "%SCRIPT_DIR%dispatcher.mjs" session-start
@@ -1,16 +1,16 @@
1
- # Universal Session Start Hook for Windows PowerShell
2
- # Calls the Node.js dispatcher for cross-platform compatibility
3
-
4
- # Find node.exe
5
- $nodePath = Get-Command node -ErrorAction SilentlyContinue
6
-
7
- if (-not $nodePath) {
8
- Write-Host '{"continue": true, "error": "Node.js not found"}'
9
- exit 0
10
- }
11
-
12
- # Get script directory
13
- $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
14
-
15
- # Run the dispatcher
16
- & node "$scriptDir\dispatcher.mjs" session-start
1
+ # Universal Session Start Hook for Windows PowerShell
2
+ # Calls the Node.js dispatcher for cross-platform compatibility
3
+
4
+ # Find node.exe
5
+ $nodePath = Get-Command node -ErrorAction SilentlyContinue
6
+
7
+ if (-not $nodePath) {
8
+ Write-Host '{"continue": true, "error": "Node.js not found"}'
9
+ exit 0
10
+ }
11
+
12
+ # Get script directory
13
+ $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
14
+
15
+ # Run the dispatcher
16
+ & node "$scriptDir\dispatcher.mjs" session-start
@@ -151,7 +151,7 @@ if echo "$PROMPT" | grep -qE "^/specweave:do($| )"; then
151
151
  else
152
152
  status=$(grep -oP '"status"\s*:\s*"\K[^"]*' "$meta" 2>/dev/null || echo "unknown")
153
153
  fi
154
- if [[ "$status" == "active" || "$status" == "in-progress" ]]; then
154
+ if [[ "$status" == "active" || "$status" == "planning" || "$status" == "backlog" || "$status" == "ready_for_review" ]]; then
155
155
  DO_INCREMENT_ID=$(basename "$(dirname "$meta")")
156
156
  break
157
157
  fi
@@ -191,7 +191,7 @@ if [[ -d "$SPECWEAVE_DIR/increments" ]]; then
191
191
  inc_type=$(grep -oP '"type"\s*:\s*"\K[^"]*' "$metadata_file" 2>/dev/null || echo "feature")
192
192
  fi
193
193
 
194
- if [[ "$status" == "active" || "$status" == "planning" || "$status" == "in-progress" ]]; then
194
+ if [[ "$status" == "active" || "$status" == "planning" || "$status" == "backlog" || "$status" == "ready_for_review" ]]; then
195
195
  inc_id=$(basename "$(dirname "$metadata_file")")
196
196
  ACTIVE_COUNT=$((ACTIVE_COUNT + 1))
197
197
  ACTIVE_LIST="${ACTIVE_LIST} - $inc_id [$inc_type]\n"
@@ -204,7 +204,91 @@ fi
204
204
  # DISCIPLINE VALIDATION: Warn about WIP limits (configurable, not hard block!)
205
205
  # ==============================================================================
206
206
 
207
- if echo "$PROMPT" | grep -q "/specweave:increment"; then
207
+ # ==============================================================================
208
+ # PROJECT CONTEXT + WIP LIMITS FOR /specweave:increment (v0.34.0)
209
+ # ==============================================================================
210
+ # CRITICAL: Inject project/board context BEFORE Claude generates spec.md
211
+ # This ensures Claude knows available projects and uses correct IDs
212
+ # ALSO: Check WIP limits in same block to avoid duplicate command detection
213
+
214
+ if echo "$PROMPT" | grep -qE "^/specweave:increment"; then
215
+ # Get project context (uses specweave CLI if available)
216
+ PROJECT_CONTEXT=""
217
+
218
+ if command -v specweave >/dev/null 2>&1; then
219
+ # Use CLI for accurate project/board detection
220
+ CONTEXT_JSON=$(specweave context projects 2>/dev/null || echo '{}')
221
+
222
+ # Validate JSON before parsing (defensive coding)
223
+ if [[ -n "$CONTEXT_JSON" ]] && [[ "$CONTEXT_JSON" != "{}" ]]; then
224
+ if command -v jq >/dev/null 2>&1; then
225
+ # Verify JSON is parseable before extracting fields
226
+ if ! echo "$CONTEXT_JSON" | jq empty 2>/dev/null; then
227
+ CONTEXT_JSON='{}' # Invalid JSON - reset to empty
228
+ fi
229
+ fi
230
+ fi
231
+
232
+ if [[ -n "$CONTEXT_JSON" ]] && [[ "$CONTEXT_JSON" != "{}" ]]; then
233
+ # Parse JSON with jq
234
+ if command -v jq >/dev/null 2>&1; then
235
+ LEVEL=$(echo "$CONTEXT_JSON" | jq -r '.level // 1')
236
+ PROJECTS=$(echo "$CONTEXT_JSON" | jq -r '.projects | map(.id) | join(", ")' 2>/dev/null || echo "")
237
+
238
+ if [[ "$LEVEL" == "2" ]]; then
239
+ # 2-level structure: include boards
240
+ BOARDS_JSON=$(echo "$CONTEXT_JSON" | jq -r '.boardsByProject // {}' 2>/dev/null)
241
+ if [[ -n "$BOARDS_JSON" ]] && [[ "$BOARDS_JSON" != "{}" ]]; then
242
+ PROJECT_CONTEXT="\\n\\n📦 PROJECT CONTEXT (2-LEVEL STRUCTURE)\\n\\n"
243
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}⚠️ MANDATORY: Each User Story MUST have both:\\n"
244
+ PROJECT_CONTEXT="${PROJECT_CONTEXT} - **Project**: <project_id>\\n"
245
+ PROJECT_CONTEXT="${PROJECT_CONTEXT} - **Board**: <board_id>\\n\\n"
246
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}Available projects: ${PROJECTS}\\n"
247
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}Boards by project:\\n"
248
+
249
+ # Format boards
250
+ for proj in $(echo "$CONTEXT_JSON" | jq -r '.projects[].id' 2>/dev/null); do
251
+ PROJ_BOARDS=$(echo "$CONTEXT_JSON" | jq -r ".boardsByProject[\"$proj\"] | map(.id) | join(\", \")" 2>/dev/null || echo "")
252
+ [[ -n "$PROJ_BOARDS" ]] && PROJECT_CONTEXT="${PROJECT_CONTEXT} - ${proj}: ${PROJ_BOARDS}\\n"
253
+ done
254
+
255
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}\\n❌ FORBIDDEN: Comma-separated values (e.g., **Project**: fe, be)\\n"
256
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}✅ REQUIRED: One project + one board per User Story"
257
+ fi
258
+ elif [[ -n "$PROJECTS" ]]; then
259
+ # 1-level structure: projects only
260
+ PROJECT_COUNT=$(echo "$CONTEXT_JSON" | jq '.projects | length' 2>/dev/null || echo "0")
261
+
262
+ if [[ "$PROJECT_COUNT" -gt 1 ]]; then
263
+ PROJECT_CONTEXT="\\n\\n📦 PROJECT CONTEXT (MULTI-PROJECT)\\n\\n"
264
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}⚠️ MANDATORY: Each User Story MUST have:\\n"
265
+ PROJECT_CONTEXT="${PROJECT_CONTEXT} - **Project**: <project_id>\\n\\n"
266
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}Available projects: ${PROJECTS}\\n"
267
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}\\n❌ FORBIDDEN: Comma-separated values\\n"
268
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}✅ REQUIRED: One project per User Story"
269
+ elif [[ "$PROJECT_COUNT" -eq 1 ]]; then
270
+ # Single project: auto-select
271
+ SINGLE_PROJECT=$(echo "$CONTEXT_JSON" | jq -r '.projects[0].id' 2>/dev/null)
272
+ PROJECT_CONTEXT="\\n\\n📦 PROJECT CONTEXT\\n"
273
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}Single project detected: ${SINGLE_PROJECT} (auto-selected)"
274
+ fi
275
+ fi
276
+ fi
277
+ fi
278
+ else
279
+ # Fallback: Check for multi-project folders
280
+ if [[ -d "$SPECWEAVE_DIR/docs/internal/specs" ]]; then
281
+ PROJ_COUNT=$(find "$SPECWEAVE_DIR/docs/internal/specs" -maxdepth 1 -type d | wc -l)
282
+ if [[ "$PROJ_COUNT" -gt 2 ]]; then
283
+ PROJ_LIST=$(ls -1 "$SPECWEAVE_DIR/docs/internal/specs" 2>/dev/null | grep -v "_" | tr '\n' ', ' | sed 's/,$//')
284
+ PROJECT_CONTEXT="\\n\\n📦 PROJECT CONTEXT (MULTI-PROJECT)\\n"
285
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}⚠️ MANDATORY: Each User Story MUST have **Project**: field\\n"
286
+ PROJECT_CONTEXT="${PROJECT_CONTEXT}Available folders: ${PROJ_LIST}"
287
+ fi
288
+ fi
289
+ fi
290
+
291
+ # WIP LIMITS CHECK (inside same block - no duplicate command detection)
208
292
  # Read limits from config.json (respect user's settings!)
209
293
  CONFIG_FILE="$SPECWEAVE_DIR/config.json"
210
294
  SOFT_LIMIT=1
@@ -226,13 +310,31 @@ if echo "$PROMPT" | grep -q "/specweave:increment"; then
226
310
 
227
311
  # Above hard cap: strong warning but NOT a block (user decides!)
228
312
  if [[ "$ACTIVE_COUNT" -ge "$HARD_CAP" ]]; then
229
- printf '{"decision":"approve","systemMessage":"⚠️ WIP LIMIT EXCEEDED (%s/%s)\\n\\nYou have %s active increments (configured maximum: %s)\\n\\nActive increments:\\n%s\\n\\n🧠 Research shows 3+ concurrent tasks = 40%% slower + more bugs\\n\\n💡 Options:\\n 1️⃣ Complete an increment: /specweave:done <id>\\n 2️⃣ Pause an increment: /specweave:pause <id>\\n 3️⃣ Increase limit: Edit .specweave/config.json limits.hardCap\\n 4️⃣ Continue anyway (not recommended)\\n\\n📝 To proceed anyway, just confirm your intent."}\n' "$ACTIVE_COUNT" "$HARD_CAP" "$ACTIVE_COUNT" "$HARD_CAP" "$ACTIVE_LIST"
313
+ WIP_MSG="⚠️ WIP LIMIT EXCEEDED (${ACTIVE_COUNT}/${HARD_CAP})\\n\\nYou have ${ACTIVE_COUNT} active increments (configured maximum: ${HARD_CAP})\\n\\nActive increments:\\n${ACTIVE_LIST}\\n\\n🧠 Research shows 3+ concurrent tasks = 40%% slower + more bugs\\n\\n💡 Options:\\n 1️⃣ Complete an increment: /specweave:done <id>\\n 2️⃣ Pause an increment: /specweave:pause <id>\\n 3️⃣ Increase limit: Edit .specweave/config.json limits.hardCap\\n 4️⃣ Continue anyway (not recommended)\\n\\n📝 To proceed anyway, just confirm your intent."
314
+ # Prepend project context if available
315
+ if [[ -n "$PROJECT_CONTEXT" ]]; then
316
+ printf '{"decision":"approve","systemMessage":"%s%s"}\n' "$PROJECT_CONTEXT" "$WIP_MSG"
317
+ else
318
+ printf '{"decision":"approve","systemMessage":"%s"}\n' "$WIP_MSG"
319
+ fi
230
320
  exit 0
231
321
  fi
232
322
 
233
323
  # At soft limit: mild warning, approve
234
324
  if [[ "$ACTIVE_COUNT" -ge "$SOFT_LIMIT" ]]; then
235
- printf '{"decision":"approve","systemMessage":"⚠️ WIP LIMIT REACHED (%s/%s)\\n\\nYou have %s active increment(s) (recommended limit: %s)\\n\\nActive increments:\\n%s\\n\\n🧠 Focus Principle: Fewer active increments = maximum productivity\\n\\n💡 Consider:\\n 1️⃣ Complete current work (recommended)\\n 2️⃣ Pause current work (/specweave:pause)\\n 3️⃣ Continue anyway\\n\\n⚠️ Emergency hotfix/bug? Use --type=hotfix or --type=bug"}\n' "$ACTIVE_COUNT" "$SOFT_LIMIT" "$ACTIVE_COUNT" "$SOFT_LIMIT" "$ACTIVE_LIST"
325
+ WIP_MSG="⚠️ WIP LIMIT REACHED (${ACTIVE_COUNT}/${SOFT_LIMIT})\\n\\nYou have ${ACTIVE_COUNT} active increment(s) (recommended limit: ${SOFT_LIMIT})\\n\\nActive increments:\\n${ACTIVE_LIST}\\n\\n🧠 Focus Principle: Fewer active increments = maximum productivity\\n\\n💡 Consider:\\n 1️⃣ Complete current work (recommended)\\n 2️⃣ Pause current work (/specweave:pause)\\n 3️⃣ Continue anyway\\n\\n⚠️ Emergency hotfix/bug? Use --type=hotfix or --type=bug"
326
+ # Prepend project context if available
327
+ if [[ -n "$PROJECT_CONTEXT" ]]; then
328
+ printf '{"decision":"approve","systemMessage":"%s%s"}\n' "$PROJECT_CONTEXT" "$WIP_MSG"
329
+ else
330
+ printf '{"decision":"approve","systemMessage":"%s"}\n' "$WIP_MSG"
331
+ fi
332
+ exit 0
333
+ fi
334
+
335
+ # No WIP limit warning, but we may have project context to inject
336
+ if [[ -n "$PROJECT_CONTEXT" ]]; then
337
+ printf '{"decision":"approve","systemMessage":"%s"}\n' "$PROJECT_CONTEXT"
236
338
  exit 0
237
339
  fi
238
340
  fi
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+ # increment-root-guard.sh - Block files at increment root (except allowed)
3
+ #
4
+ # ROOT CAUSE: Agents sometimes create files like COMPLETION_REPORT.md,
5
+ # COMPLETION_SUMMARY.md, or other .md files at increment root instead of
6
+ # placing them in appropriate subfolders (reports/, scripts/, logs/, etc.)
7
+ #
8
+ # SOLUTION: Block Write operations to increment root for non-standard files.
9
+ # Only allow: metadata.json, spec.md, plan.md, tasks.md
10
+ # Everything else MUST go in subfolders: reports/, scripts/, logs/, backups/, docs/
11
+ #
12
+ # PreToolUse hook for Write command - exit 0 allows, exit 2 blocks
13
+ #
14
+ # v0.33.0 - Initial implementation based on bug analysis from 2025-12-09
15
+
16
+ set +e
17
+
18
+ [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]] && exit 0
19
+
20
+ # Read stdin for tool input
21
+ INPUT=$(cat)
22
+
23
+ # Extract the file_path being written
24
+ if command -v jq &> /dev/null; then
25
+ FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // empty' 2>/dev/null)
26
+ else
27
+ FILE_PATH=$(echo "$INPUT" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' | head -1 | sed 's/.*"file_path"[[:space:]]*:[[:space:]]*"\(.*\)"/\1/')
28
+ fi
29
+
30
+ # If no file_path found, allow (safety)
31
+ if [[ -z "$FILE_PATH" ]]; then
32
+ exit 0
33
+ fi
34
+
35
+ # === PATTERN DETECTION ===
36
+ # Block files at increment root that should be in subfolders
37
+
38
+ # Pattern: .specweave/increments/####-name/FILE.md (at root, not in subfolder)
39
+ # Allowed at root: metadata.json, spec.md, plan.md, tasks.md
40
+ if [[ "$FILE_PATH" =~ \.specweave/increments/[0-9]{3,4}E?-[^/]+/([^/]+)$ ]]; then
41
+ FILENAME="${BASH_REMATCH[1]}"
42
+
43
+ # Allow standard increment files at root
44
+ if [[ "$FILENAME" =~ ^(metadata\.json|spec\.md|plan\.md|tasks\.md)$ ]]; then
45
+ printf '{"decision":"allow"}'
46
+ exit 0
47
+ fi
48
+
49
+ # Block everything else at increment root
50
+ cat << EOF
51
+ {
52
+ "decision": "block",
53
+ "reason": "🚫 BLOCKED: File '$FILENAME' should be in a subfolder, not at increment root\n\n⚠️ CLAUDE.md Folder Structure Rule:\n Inside increment folders - ONLY at root: spec.md, plan.md, tasks.md, metadata.json\n Everything else → subfolders: reports/, scripts/, logs/, backups/, docs/\n\n📋 CORRECT structure:\n .specweave/increments/####-name/reports/COMPLETION_REPORT.md ✅\n .specweave/increments/####-name/reports/COMPLETION_SUMMARY.md ✅\n .specweave/increments/####-name/scripts/analyze.sh ✅\n\n❌ WRONG structure:\n .specweave/increments/####-name/COMPLETION_REPORT.md ❌\n .specweave/increments/####-name/COMPLETION_SUMMARY.md ❌\n\n🔧 To fix: Create file in reports/ subfolder instead.\nUse: Write({ file_path: \".specweave/increments/####-name/reports/$FILENAME\", ... })\n\nSee: CLAUDE.md section 'Folder Structure'"
54
+ }
55
+ EOF
56
+ exit 2
57
+ fi
58
+
59
+ # Allow all other writes (files in subfolders, or outside increments)
60
+ printf '{"decision":"allow"}'
61
+ exit 0