specweave 0.32.0 → 0.32.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 (347) hide show
  1. package/CLAUDE.md +215 -2
  2. package/README.md +22 -0
  3. package/bin/specweave.js +52 -1
  4. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts +100 -0
  5. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.d.ts.map +1 -0
  6. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js +291 -0
  7. package/dist/plugins/specweave-ado/lib/ado-duplicate-detector.js.map +1 -0
  8. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts +103 -0
  9. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.d.ts.map +1 -0
  10. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js +310 -0
  11. package/dist/plugins/specweave-jira/lib/jira-duplicate-detector.js.map +1 -0
  12. package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts +126 -0
  13. package/dist/plugins/specweave-jira/lib/jira-permission-gate.d.ts.map +1 -0
  14. package/dist/plugins/specweave-jira/lib/jira-permission-gate.js +207 -0
  15. package/dist/plugins/specweave-jira/lib/jira-permission-gate.js.map +1 -0
  16. package/dist/src/adapters/codex/README.md +1 -1
  17. package/dist/src/adapters/codex/adapter.js +1 -1
  18. package/dist/src/cli/commands/archive.d.ts +2 -0
  19. package/dist/src/cli/commands/archive.d.ts.map +1 -1
  20. package/dist/src/cli/commands/archive.js +33 -0
  21. package/dist/src/cli/commands/archive.js.map +1 -1
  22. package/dist/src/cli/commands/cache.d.ts +17 -0
  23. package/dist/src/cli/commands/cache.d.ts.map +1 -0
  24. package/dist/src/cli/commands/cache.js +126 -0
  25. package/dist/src/cli/commands/cache.js.map +1 -0
  26. package/dist/src/cli/commands/context.d.ts +92 -0
  27. package/dist/src/cli/commands/context.d.ts.map +1 -0
  28. package/dist/src/cli/commands/context.js +205 -0
  29. package/dist/src/cli/commands/context.js.map +1 -0
  30. package/dist/src/cli/commands/init.d.ts.map +1 -1
  31. package/dist/src/cli/commands/init.js +112 -70
  32. package/dist/src/cli/commands/init.js.map +1 -1
  33. package/dist/src/cli/commands/plan/increment-detector.js +2 -2
  34. package/dist/src/cli/commands/plan/increment-detector.js.map +1 -1
  35. package/dist/src/cli/commands/sync-spec-commits.js +1 -1
  36. package/dist/src/cli/commands/sync-spec-commits.js.map +1 -1
  37. package/dist/src/cli/commands/sync-specs.js +2 -2
  38. package/dist/src/cli/commands/sync-specs.js.map +1 -1
  39. package/dist/src/cli/helpers/github/increment-profile-selector.js +1 -1
  40. package/dist/src/cli/helpers/github/increment-profile-selector.js.map +1 -1
  41. package/dist/src/cli/helpers/init/external-import.d.ts +3 -0
  42. package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
  43. package/dist/src/cli/helpers/init/external-import.js +17 -4
  44. package/dist/src/cli/helpers/init/external-import.js.map +1 -1
  45. package/dist/src/cli/helpers/init/index.d.ts +1 -0
  46. package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
  47. package/dist/src/cli/helpers/init/index.js +2 -0
  48. package/dist/src/cli/helpers/init/index.js.map +1 -1
  49. package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts +70 -0
  50. package/dist/src/cli/helpers/init/jira-ado-auto-detect.d.ts.map +1 -1
  51. package/dist/src/cli/helpers/init/jira-ado-auto-detect.js +214 -4
  52. package/dist/src/cli/helpers/init/jira-ado-auto-detect.js.map +1 -1
  53. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts +4 -0
  54. package/dist/src/cli/helpers/init/living-docs-preflight.d.ts.map +1 -1
  55. package/dist/src/cli/helpers/init/living-docs-preflight.js +34 -3
  56. package/dist/src/cli/helpers/init/living-docs-preflight.js.map +1 -1
  57. package/dist/src/cli/helpers/init/testing-config.d.ts +3 -0
  58. package/dist/src/cli/helpers/init/testing-config.d.ts.map +1 -1
  59. package/dist/src/cli/helpers/init/testing-config.js +9 -2
  60. package/dist/src/cli/helpers/init/testing-config.js.map +1 -1
  61. package/dist/src/cli/helpers/init/translation-config.d.ts +3 -0
  62. package/dist/src/cli/helpers/init/translation-config.d.ts.map +1 -1
  63. package/dist/src/cli/helpers/init/translation-config.js +21 -4
  64. package/dist/src/cli/helpers/init/translation-config.js.map +1 -1
  65. package/dist/src/cli/helpers/init/wizard-navigation.d.ts +45 -0
  66. package/dist/src/cli/helpers/init/wizard-navigation.d.ts.map +1 -0
  67. package/dist/src/cli/helpers/init/wizard-navigation.js +97 -0
  68. package/dist/src/cli/helpers/init/wizard-navigation.js.map +1 -0
  69. package/dist/src/cli/workers/living-docs-worker.js +66 -1
  70. package/dist/src/cli/workers/living-docs-worker.js.map +1 -1
  71. package/dist/src/config/types.d.ts +203 -1208
  72. package/dist/src/config/types.d.ts.map +1 -1
  73. package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -1
  74. package/dist/src/core/discrepancy/increment-generator.js +5 -2
  75. package/dist/src/core/discrepancy/increment-generator.js.map +1 -1
  76. package/dist/src/core/increment/duplicate-detector.js +2 -2
  77. package/dist/src/core/increment/duplicate-detector.js.map +1 -1
  78. package/dist/src/core/increment/increment-archiver.d.ts +49 -4
  79. package/dist/src/core/increment/increment-archiver.d.ts.map +1 -1
  80. package/dist/src/core/increment/increment-archiver.js +123 -22
  81. package/dist/src/core/increment/increment-archiver.js.map +1 -1
  82. package/dist/src/core/increment/increment-status.js +2 -2
  83. package/dist/src/core/increment/increment-status.js.map +1 -1
  84. package/dist/src/core/increment/increment-utils.d.ts +150 -0
  85. package/dist/src/core/increment/increment-utils.d.ts.map +1 -1
  86. package/dist/src/core/increment/increment-utils.js +216 -4
  87. package/dist/src/core/increment/increment-utils.js.map +1 -1
  88. package/dist/src/core/increment/metadata-validator.js +1 -1
  89. package/dist/src/core/increment/metadata-validator.js.map +1 -1
  90. package/dist/src/core/living-docs/feature-archiver.d.ts +4 -0
  91. package/dist/src/core/living-docs/feature-archiver.d.ts.map +1 -1
  92. package/dist/src/core/living-docs/feature-archiver.js +32 -10
  93. package/dist/src/core/living-docs/feature-archiver.js.map +1 -1
  94. package/dist/src/core/living-docs/feature-id-manager.d.ts.map +1 -1
  95. package/dist/src/core/living-docs/feature-id-manager.js +8 -4
  96. package/dist/src/core/living-docs/feature-id-manager.js.map +1 -1
  97. package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts +38 -0
  98. package/dist/src/core/living-docs/governance/ecosystem-detector.d.ts.map +1 -0
  99. package/dist/src/core/living-docs/governance/ecosystem-detector.js +325 -0
  100. package/dist/src/core/living-docs/governance/ecosystem-detector.js.map +1 -0
  101. package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts +74 -0
  102. package/dist/src/core/living-docs/governance/frontend-standards-parser.d.ts.map +1 -0
  103. package/dist/src/core/living-docs/governance/frontend-standards-parser.js +366 -0
  104. package/dist/src/core/living-docs/governance/frontend-standards-parser.js.map +1 -0
  105. package/dist/src/core/living-docs/governance/go-standards-parser.d.ts +64 -0
  106. package/dist/src/core/living-docs/governance/go-standards-parser.d.ts.map +1 -0
  107. package/dist/src/core/living-docs/governance/go-standards-parser.js +229 -0
  108. package/dist/src/core/living-docs/governance/go-standards-parser.js.map +1 -0
  109. package/dist/src/core/living-docs/governance/index.d.ts +50 -0
  110. package/dist/src/core/living-docs/governance/index.d.ts.map +1 -0
  111. package/dist/src/core/living-docs/governance/index.js +56 -0
  112. package/dist/src/core/living-docs/governance/index.js.map +1 -0
  113. package/dist/src/core/living-docs/governance/java-standards-parser.d.ts +89 -0
  114. package/dist/src/core/living-docs/governance/java-standards-parser.d.ts.map +1 -0
  115. package/dist/src/core/living-docs/governance/java-standards-parser.js +356 -0
  116. package/dist/src/core/living-docs/governance/java-standards-parser.js.map +1 -0
  117. package/dist/src/core/living-docs/governance/python-standards-parser.d.ts +83 -0
  118. package/dist/src/core/living-docs/governance/python-standards-parser.d.ts.map +1 -0
  119. package/dist/src/core/living-docs/governance/python-standards-parser.js +347 -0
  120. package/dist/src/core/living-docs/governance/python-standards-parser.js.map +1 -0
  121. package/dist/src/core/living-docs/governance/standards-generator.d.ts +38 -0
  122. package/dist/src/core/living-docs/governance/standards-generator.d.ts.map +1 -0
  123. package/dist/src/core/living-docs/governance/standards-generator.js +476 -0
  124. package/dist/src/core/living-docs/governance/standards-generator.js.map +1 -0
  125. package/dist/src/core/living-docs/hierarchy-mapper.js +3 -3
  126. package/dist/src/core/living-docs/hierarchy-mapper.js.map +1 -1
  127. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts +18 -0
  128. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.d.ts.map +1 -0
  129. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js +299 -0
  130. package/dist/src/core/living-docs/intelligent-analyzer/architecture-generator.js.map +1 -0
  131. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts +15 -0
  132. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.d.ts.map +1 -0
  133. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js +138 -0
  134. package/dist/src/core/living-docs/intelligent-analyzer/deep-repo-analyzer.js.map +1 -0
  135. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts +24 -0
  136. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.d.ts.map +1 -0
  137. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js +198 -0
  138. package/dist/src/core/living-docs/intelligent-analyzer/file-sampler.js.map +1 -0
  139. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts +17 -0
  140. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts.map +1 -0
  141. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js +241 -0
  142. package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js.map +1 -0
  143. package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts +28 -0
  144. package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts.map +1 -0
  145. package/dist/src/core/living-docs/intelligent-analyzer/index.js +197 -0
  146. package/dist/src/core/living-docs/intelligent-analyzer/index.js.map +1 -0
  147. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts +22 -0
  148. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.d.ts.map +1 -0
  149. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js +482 -0
  150. package/dist/src/core/living-docs/intelligent-analyzer/organization-synthesizer.js.map +1 -0
  151. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts +42 -0
  152. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.d.ts.map +1 -0
  153. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js +343 -0
  154. package/dist/src/core/living-docs/intelligent-analyzer/strategy-generator.js.map +1 -0
  155. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +190 -0
  156. package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -0
  157. package/dist/src/core/living-docs/intelligent-analyzer/types.js +7 -0
  158. package/dist/src/core/living-docs/intelligent-analyzer/types.js.map +1 -0
  159. package/dist/src/core/living-docs/living-docs-sync.d.ts +11 -3
  160. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  161. package/dist/src/core/living-docs/living-docs-sync.js +53 -10
  162. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  163. package/dist/src/core/living-docs/module-analyzer.d.ts +22 -0
  164. package/dist/src/core/living-docs/module-analyzer.d.ts.map +1 -1
  165. package/dist/src/core/living-docs/module-analyzer.js +123 -19
  166. package/dist/src/core/living-docs/module-analyzer.js.map +1 -1
  167. package/dist/src/core/llm/provider-factory.js +2 -2
  168. package/dist/src/core/llm/provider-factory.js.map +1 -1
  169. package/dist/src/core/llm/providers/anthropic-provider.js +1 -1
  170. package/dist/src/core/llm/providers/bedrock-provider.d.ts.map +1 -1
  171. package/dist/src/core/llm/providers/bedrock-provider.js +8 -4
  172. package/dist/src/core/llm/providers/bedrock-provider.js.map +1 -1
  173. package/dist/src/core/sync/spec-increment-mapper.js +3 -3
  174. package/dist/src/core/sync/spec-increment-mapper.js.map +1 -1
  175. package/dist/src/importers/item-converter.d.ts +25 -0
  176. package/dist/src/importers/item-converter.d.ts.map +1 -1
  177. package/dist/src/importers/item-converter.js +135 -5
  178. package/dist/src/importers/item-converter.js.map +1 -1
  179. package/dist/src/importers/jira-importer.d.ts +14 -0
  180. package/dist/src/importers/jira-importer.d.ts.map +1 -1
  181. package/dist/src/importers/jira-importer.js +75 -0
  182. package/dist/src/importers/jira-importer.js.map +1 -1
  183. package/dist/src/init/architecture/types.d.ts +33 -140
  184. package/dist/src/init/architecture/types.d.ts.map +1 -1
  185. package/dist/src/init/compliance/types.d.ts +30 -27
  186. package/dist/src/init/compliance/types.d.ts.map +1 -1
  187. package/dist/src/init/repo/types.d.ts +11 -34
  188. package/dist/src/init/repo/types.d.ts.map +1 -1
  189. package/dist/src/init/research/src/config/types.d.ts +15 -82
  190. package/dist/src/init/research/src/config/types.d.ts.map +1 -1
  191. package/dist/src/init/research/types.d.ts +38 -93
  192. package/dist/src/init/research/types.d.ts.map +1 -1
  193. package/dist/src/init/team/types.d.ts +4 -42
  194. package/dist/src/init/team/types.d.ts.map +1 -1
  195. package/dist/src/integrations/jira/jira-token-provider.d.ts +93 -0
  196. package/dist/src/integrations/jira/jira-token-provider.d.ts.map +1 -0
  197. package/dist/src/integrations/jira/jira-token-provider.js +160 -0
  198. package/dist/src/integrations/jira/jira-token-provider.js.map +1 -0
  199. package/dist/src/sync/ado-reconciler.d.ts +92 -0
  200. package/dist/src/sync/ado-reconciler.d.ts.map +1 -0
  201. package/dist/src/sync/ado-reconciler.js +335 -0
  202. package/dist/src/sync/ado-reconciler.js.map +1 -0
  203. package/dist/src/sync/jira-reconciler.d.ts +106 -0
  204. package/dist/src/sync/jira-reconciler.d.ts.map +1 -0
  205. package/dist/src/sync/jira-reconciler.js +405 -0
  206. package/dist/src/sync/jira-reconciler.js.map +1 -0
  207. package/dist/src/types/dashboard-cache.d.ts +181 -0
  208. package/dist/src/types/dashboard-cache.d.ts.map +1 -0
  209. package/dist/src/types/dashboard-cache.js +65 -0
  210. package/dist/src/types/dashboard-cache.js.map +1 -0
  211. package/dist/src/types/model-selection.d.ts +6 -4
  212. package/dist/src/types/model-selection.d.ts.map +1 -1
  213. package/dist/src/types/model-selection.js +3 -1
  214. package/dist/src/types/model-selection.js.map +1 -1
  215. package/dist/src/utils/docs-validator.d.ts +131 -0
  216. package/dist/src/utils/docs-validator.d.ts.map +1 -0
  217. package/dist/src/utils/docs-validator.js +529 -0
  218. package/dist/src/utils/docs-validator.js.map +1 -0
  219. package/dist/src/utils/external-tool-drift-detector.d.ts +1 -1
  220. package/dist/src/utils/external-tool-drift-detector.d.ts.map +1 -1
  221. package/dist/src/utils/external-tool-drift-detector.js +5 -4
  222. package/dist/src/utils/external-tool-drift-detector.js.map +1 -1
  223. package/dist/src/utils/feature-id-collision.js +1 -1
  224. package/dist/src/utils/feature-id-collision.js.map +1 -1
  225. package/dist/src/utils/feature-id-derivation.d.ts +8 -3
  226. package/dist/src/utils/feature-id-derivation.d.ts.map +1 -1
  227. package/dist/src/utils/feature-id-derivation.js +14 -6
  228. package/dist/src/utils/feature-id-derivation.js.map +1 -1
  229. package/dist/src/utils/html-to-mdx.d.ts +1 -0
  230. package/dist/src/utils/html-to-mdx.d.ts.map +1 -1
  231. package/dist/src/utils/html-to-mdx.js +43 -5
  232. package/dist/src/utils/html-to-mdx.js.map +1 -1
  233. package/dist/src/utils/model-selection.d.ts +3 -4
  234. package/dist/src/utils/model-selection.d.ts.map +1 -1
  235. package/dist/src/utils/model-selection.js +3 -4
  236. package/dist/src/utils/model-selection.js.map +1 -1
  237. package/package.json +1 -1
  238. package/plugins/specweave/agents/code-standards-detective/AGENT.md +48 -0
  239. package/plugins/specweave/agents/pm/AGENT.md +10 -7
  240. package/plugins/specweave/commands/specweave-archive-features.md +5 -7
  241. package/plugins/specweave/commands/specweave-archive.md +2 -1
  242. package/plugins/specweave/commands/specweave-costs.md +4 -4
  243. package/plugins/specweave/commands/specweave-do.md +44 -10
  244. package/plugins/specweave/commands/specweave-done.md +109 -0
  245. package/plugins/specweave/commands/specweave-import-external.md +45 -18
  246. package/plugins/specweave/commands/specweave-increment.md +331 -33
  247. package/plugins/specweave/commands/specweave-jobs.md +2 -2
  248. package/plugins/specweave/commands/specweave-progress.md +4 -4
  249. package/plugins/specweave/commands/specweave-restore-feature.md +5 -4
  250. package/plugins/specweave/commands/specweave-sync-docs.md +1 -1
  251. package/plugins/specweave/commands/specweave-sync-specs.md +216 -322
  252. package/plugins/specweave/commands/specweave-validate-features.md +13 -8
  253. package/plugins/specweave/commands/specweave-validate.md +27 -1
  254. package/plugins/specweave/hooks/docs-changed.sh.backup +79 -0
  255. package/plugins/specweave/hooks/hooks.json +43 -4
  256. package/plugins/specweave/hooks/human-input-required.sh.backup +75 -0
  257. package/plugins/specweave/hooks/lib/common-setup.sh +375 -0
  258. package/plugins/specweave/hooks/lib/crash-prevention.sh +336 -0
  259. package/plugins/specweave/hooks/post-first-increment.sh.backup +61 -0
  260. package/plugins/specweave/hooks/post-increment-change.sh.backup +98 -0
  261. package/plugins/specweave/hooks/post-increment-completion.sh.backup +231 -0
  262. package/plugins/specweave/hooks/post-increment-planning.sh.backup +1048 -0
  263. package/plugins/specweave/hooks/post-increment-status-change.sh.backup +147 -0
  264. package/plugins/specweave/hooks/post-spec-update.sh.backup +158 -0
  265. package/plugins/specweave/hooks/post-task-completion.sh +4 -23
  266. package/plugins/specweave/hooks/post-user-story-complete.sh.backup +179 -0
  267. package/plugins/specweave/hooks/pre-command-deduplication.sh +1 -6
  268. package/plugins/specweave/hooks/pre-command-deduplication.sh.backup +83 -0
  269. package/plugins/specweave/hooks/pre-implementation.sh.backup +67 -0
  270. package/plugins/specweave/hooks/pre-task-completion.sh +8 -37
  271. package/plugins/specweave/hooks/pre-task-completion.sh.backup +194 -0
  272. package/plugins/specweave/hooks/pre-tool-use.sh +2 -11
  273. package/plugins/specweave/hooks/pre-tool-use.sh.backup +133 -0
  274. package/plugins/specweave/hooks/spec-project-validator.sh +80 -25
  275. package/plugins/specweave/hooks/universal/dispatcher.mjs +135 -42
  276. package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +183 -0
  277. package/plugins/specweave/hooks/user-prompt-submit.sh +140 -38
  278. package/plugins/specweave/hooks/user-prompt-submit.sh.backup +386 -0
  279. package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +12 -0
  280. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +89 -0
  281. package/plugins/specweave/hooks/v2/guards/bash-file-guard.sh +211 -0
  282. package/plugins/specweave/hooks/v2/guards/bash-file-guard.test.sh +163 -0
  283. package/plugins/specweave/hooks/v2/guards/completion-guard.sh +26 -28
  284. package/plugins/specweave/hooks/v2/guards/features-folder-guard.sh +50 -0
  285. package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +135 -0
  286. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js +2 -2
  287. package/plugins/specweave/lib/vendor/core/increment/duplicate-detector.js.map +1 -1
  288. package/plugins/specweave/scripts/README.md +166 -0
  289. package/plugins/specweave/scripts/cleanup-state.sh +142 -0
  290. package/plugins/specweave/scripts/force-kill.sh +142 -0
  291. package/plugins/specweave/scripts/jobs.js +171 -0
  292. package/plugins/specweave/scripts/progress.js +170 -0
  293. package/plugins/specweave/scripts/read-costs.sh +132 -0
  294. package/plugins/specweave/scripts/read-jobs.sh +324 -0
  295. package/plugins/specweave/scripts/read-progress.sh +185 -0
  296. package/plugins/specweave/scripts/read-status.sh +146 -0
  297. package/plugins/specweave/scripts/read-workflow.sh +173 -0
  298. package/plugins/specweave/scripts/rebuild-dashboard-cache.sh +327 -0
  299. package/plugins/specweave/scripts/session-watchdog.sh +192 -0
  300. package/plugins/specweave/scripts/status.js +154 -0
  301. package/plugins/specweave/scripts/update-dashboard-cache.sh +281 -0
  302. package/plugins/specweave/skills/code-standards-analyzer/SKILL.md +58 -6
  303. package/plugins/specweave/skills/increment-planner/SKILL.md +388 -48
  304. package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +17 -7
  305. package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +6 -1
  306. package/plugins/specweave/skills/increment-planner/templates/tasks-multi-project.md +1 -1
  307. package/plugins/specweave/skills/increment-planner/templates/tasks-single-project.md +1 -1
  308. package/plugins/specweave/skills/instant-status/SKILL.md +70 -0
  309. package/plugins/specweave-ado/commands/cleanup-duplicates.md +212 -0
  310. package/plugins/specweave-ado/commands/reconcile.md +120 -0
  311. package/plugins/specweave-ado/hooks/post-living-docs-update.sh.backup +353 -0
  312. package/plugins/specweave-ado/hooks/post-task-completion.sh.backup +172 -0
  313. package/plugins/specweave-ado/lib/ado-duplicate-detector.js +279 -0
  314. package/plugins/specweave-ado/lib/ado-duplicate-detector.ts +407 -0
  315. package/plugins/specweave-ado/lib/enhanced-ado-sync.js +170 -0
  316. package/plugins/specweave-docs/commands/build.md +32 -4
  317. package/plugins/specweave-docs/commands/preview.md +43 -1
  318. package/plugins/specweave-docs/commands/validate.md +250 -0
  319. package/plugins/specweave-github/agents/github-manager/AGENT.md +2 -2
  320. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +1262 -0
  321. package/plugins/specweave-github/hooks/post-task-completion.sh.backup +258 -0
  322. package/plugins/specweave-github/lib/enhanced-github-sync.js +220 -0
  323. package/plugins/specweave-infrastructure/skills/hetzner-provisioner/README.md +1 -1
  324. package/plugins/specweave-jira/agents/jira-manager/AGENT.md +1 -1
  325. package/plugins/specweave-jira/agents/jira-multi-project-mapper/AGENT.md +530 -0
  326. package/plugins/specweave-jira/agents/jira-sync-judge/AGENT.md +438 -0
  327. package/plugins/specweave-jira/commands/cleanup-duplicates.md +219 -0
  328. package/plugins/specweave-jira/commands/close.md +297 -0
  329. package/plugins/specweave-jira/commands/create.md +198 -0
  330. package/plugins/specweave-jira/commands/reconcile.md +123 -0
  331. package/plugins/specweave-jira/commands/status.md +215 -0
  332. package/plugins/specweave-jira/hooks/post-task-completion.sh.backup +172 -0
  333. package/plugins/specweave-jira/lib/enhanced-jira-sync.js +134 -0
  334. package/plugins/specweave-jira/lib/jira-duplicate-detector.js +296 -0
  335. package/plugins/specweave-jira/lib/jira-duplicate-detector.ts +434 -0
  336. package/plugins/specweave-jira/lib/jira-permission-gate.js +160 -0
  337. package/plugins/specweave-jira/lib/jira-permission-gate.ts +276 -0
  338. package/plugins/specweave-jira/lib/jira-profile-resolver.js +222 -0
  339. package/plugins/specweave-jira/lib/jira-profile-resolver.ts +427 -0
  340. package/plugins/specweave-jira/reference/jira-specweave-mapping.md +16 -11
  341. package/plugins/specweave-release/commands/specweave-release-npm.md +140 -14
  342. package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +1254 -0
  343. package/plugins/specweave-release/hooks/post-task-completion.sh.backup +110 -0
  344. package/plugins/specweave/hooks/post-edit-spec.sh +0 -265
  345. package/plugins/specweave/hooks/post-write-spec.sh +0 -267
  346. package/plugins/specweave/hooks/pre-edit-spec.sh +0 -151
  347. package/plugins/specweave/hooks/pre-write-spec.sh +0 -151
@@ -0,0 +1,375 @@
1
+ #!/bin/bash
2
+ # common-setup.sh - Unified Hook Library for Crash Prevention
3
+ #
4
+ # This library consolidates ALL common patterns from 19+ hooks into
5
+ # a single source of truth. Extracted from ADRs: 0060, 0068, 0073,
6
+ # 0128, 0130, 0157, 0189.
7
+ #
8
+ # USAGE:
9
+ # source "${CLAUDE_PLUGIN_ROOT}/hooks/lib/common-setup.sh"
10
+ # setup_hook_environment || exit 0
11
+ #
12
+ # v0.33.0 - Consolidated from 7 ADRs (2,500+ lines → 200 lines)
13
+
14
+ set +e # NEVER use set -e in hooks (ADR-0157 Rule 2)
15
+
16
+ # ============================================================================
17
+ # CONFIGURATION
18
+ # ============================================================================
19
+
20
+ export HOOK_VERSION="0.33.0"
21
+ export HOOK_TIMEOUT="${HOOK_TIMEOUT:-5}"
22
+ export HOOK_DEBUG="${HOOK_DEBUG:-0}"
23
+
24
+ # State directories (lazy-created)
25
+ _STATE_DIR=""
26
+ _CACHE_DIR=""
27
+ _LOG_DIR=""
28
+
29
+ # ============================================================================
30
+ # 1. PROJECT ROOT DETECTION (ADR-0068, ADR-0128)
31
+ # ============================================================================
32
+
33
+ find_project_root() {
34
+ local dir="${1:-$(pwd)}"
35
+ while [[ "$dir" != "/" ]]; do
36
+ if [[ -d "$dir/.specweave" ]]; then
37
+ echo "$dir"
38
+ return 0
39
+ fi
40
+ dir=$(dirname "$dir")
41
+ done
42
+ return 1
43
+ }
44
+
45
+ # ============================================================================
46
+ # 2. EMERGENCY KILL SWITCH (ADR-0068 Layer 1, ADR-0157 Rule 4)
47
+ # ============================================================================
48
+
49
+ check_kill_switch() {
50
+ if [[ "${SPECWEAVE_DISABLE_HOOKS:-0}" == "1" ]]; then
51
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Kill switch active" >&2
52
+ return 1
53
+ fi
54
+ return 0
55
+ }
56
+
57
+ # ============================================================================
58
+ # 3. CIRCUIT BREAKER (ADR-0068 Layer 2)
59
+ # ============================================================================
60
+
61
+ # Circuit breaker state (3 failures = trip)
62
+ _CIRCUIT_BREAKER_FILE=""
63
+ _CIRCUIT_BREAKER_THRESHOLD=3
64
+
65
+ init_circuit_breaker() {
66
+ local project_root="$1"
67
+ _CIRCUIT_BREAKER_FILE="${project_root}/.specweave/state/.hook-circuit-breaker"
68
+ mkdir -p "$(dirname "$_CIRCUIT_BREAKER_FILE")" 2>/dev/null
69
+ }
70
+
71
+ check_circuit_breaker() {
72
+ [[ -z "$_CIRCUIT_BREAKER_FILE" ]] && return 0
73
+
74
+ if [[ -f "$_CIRCUIT_BREAKER_FILE" ]]; then
75
+ local failures
76
+ failures=$(cat "$_CIRCUIT_BREAKER_FILE" 2>/dev/null || echo "0")
77
+ if [[ "$failures" -ge "$_CIRCUIT_BREAKER_THRESHOLD" ]]; then
78
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Circuit breaker OPEN ($failures failures)" >&2
79
+ return 1
80
+ fi
81
+ fi
82
+ return 0
83
+ }
84
+
85
+ record_circuit_breaker_failure() {
86
+ [[ -z "$_CIRCUIT_BREAKER_FILE" ]] && return
87
+
88
+ local failures
89
+ failures=$(cat "$_CIRCUIT_BREAKER_FILE" 2>/dev/null || echo "0")
90
+ echo "$((failures + 1))" > "$_CIRCUIT_BREAKER_FILE"
91
+ }
92
+
93
+ reset_circuit_breaker() {
94
+ [[ -n "$_CIRCUIT_BREAKER_FILE" ]] && rm -f "$_CIRCUIT_BREAKER_FILE"
95
+ }
96
+
97
+ # ============================================================================
98
+ # 4. FILE-BASED RECURSION GUARD (ADR-0073 - replaces failed env var approach)
99
+ # ============================================================================
100
+
101
+ _RECURSION_GUARD_FILE=""
102
+
103
+ init_recursion_guard() {
104
+ local project_root="$1"
105
+ _RECURSION_GUARD_FILE="${project_root}/.specweave/state/.hook-recursion-guard"
106
+ }
107
+
108
+ check_recursion_guard() {
109
+ [[ -z "$_RECURSION_GUARD_FILE" ]] && return 0
110
+
111
+ if [[ -f "$_RECURSION_GUARD_FILE" ]]; then
112
+ # Check if guard is stale (>30s old)
113
+ local guard_age
114
+ if [[ "$(uname)" == "Darwin" ]]; then
115
+ guard_age=$(( $(date +%s) - $(stat -f %m "$_RECURSION_GUARD_FILE" 2>/dev/null || echo "0") ))
116
+ else
117
+ guard_age=$(( $(date +%s) - $(stat -c %Y "$_RECURSION_GUARD_FILE" 2>/dev/null || echo "0") ))
118
+ fi
119
+
120
+ if [[ "$guard_age" -lt 30 ]]; then
121
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Recursion guard active (${guard_age}s old)" >&2
122
+ return 1
123
+ else
124
+ # Stale guard - clean it up
125
+ rm -f "$_RECURSION_GUARD_FILE"
126
+ fi
127
+ fi
128
+ return 0
129
+ }
130
+
131
+ acquire_recursion_guard() {
132
+ [[ -z "$_RECURSION_GUARD_FILE" ]] && return 1
133
+
134
+ touch "$_RECURSION_GUARD_FILE"
135
+ # Auto-cleanup on exit
136
+ trap 'rm -f "$_RECURSION_GUARD_FILE" 2>/dev/null' EXIT
137
+ return 0
138
+ }
139
+
140
+ release_recursion_guard() {
141
+ [[ -n "$_RECURSION_GUARD_FILE" ]] && rm -f "$_RECURSION_GUARD_FILE" 2>/dev/null
142
+ }
143
+
144
+ # ============================================================================
145
+ # 5. LOCK FILE ACQUISITION (ADR-0068 Layer 3)
146
+ # ============================================================================
147
+
148
+ _LOCK_FILE=""
149
+ _LOCK_TIMEOUT=5
150
+
151
+ acquire_hook_lock() {
152
+ local lock_name="${1:-default}"
153
+ local project_root="${2:-$(find_project_root)}"
154
+
155
+ _LOCK_FILE="${project_root}/.specweave/state/.hook-${lock_name}.lock"
156
+ mkdir -p "$(dirname "$_LOCK_FILE")" 2>/dev/null
157
+
158
+ local attempts=0
159
+ while [[ $attempts -lt $((_LOCK_TIMEOUT * 5)) ]]; do
160
+ if mkdir "$_LOCK_FILE" 2>/dev/null; then
161
+ trap 'rmdir "$_LOCK_FILE" 2>/dev/null || true' EXIT
162
+ return 0
163
+ fi
164
+
165
+ # Check for stale lock (>60s old)
166
+ if [[ -d "$_LOCK_FILE" ]]; then
167
+ local lock_age
168
+ if [[ "$(uname)" == "Darwin" ]]; then
169
+ lock_age=$(( $(date +%s) - $(stat -f %m "$_LOCK_FILE" 2>/dev/null || echo "0") ))
170
+ else
171
+ lock_age=$(( $(date +%s) - $(stat -c %Y "$_LOCK_FILE" 2>/dev/null || echo "0") ))
172
+ fi
173
+
174
+ if [[ "$lock_age" -gt 60 ]]; then
175
+ rmdir "$_LOCK_FILE" 2>/dev/null
176
+ continue
177
+ fi
178
+ fi
179
+
180
+ sleep 0.2
181
+ attempts=$((attempts + 1))
182
+ done
183
+
184
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Lock acquisition timeout: $lock_name" >&2
185
+ return 1
186
+ }
187
+
188
+ release_hook_lock() {
189
+ [[ -n "$_LOCK_FILE" ]] && rmdir "$_LOCK_FILE" 2>/dev/null
190
+ _LOCK_FILE=""
191
+ }
192
+
193
+ # ============================================================================
194
+ # 6. DEBOUNCING (ADR-0060 Tier 1, ADR-0130)
195
+ # ============================================================================
196
+
197
+ _DEBOUNCE_FILE=""
198
+ _DEBOUNCE_WINDOW=5 # seconds
199
+
200
+ check_debounce() {
201
+ local debounce_key="${1:-default}"
202
+ local project_root="${2:-$(find_project_root)}"
203
+
204
+ _DEBOUNCE_FILE="${project_root}/.specweave/state/.last-hook-${debounce_key}"
205
+
206
+ if [[ -f "$_DEBOUNCE_FILE" ]]; then
207
+ local last_run
208
+ last_run=$(cat "$_DEBOUNCE_FILE" 2>/dev/null || echo "0")
209
+ local now
210
+ now=$(date +%s)
211
+
212
+ if [[ $((now - last_run)) -lt $_DEBOUNCE_WINDOW ]]; then
213
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Debounced: $debounce_key" >&2
214
+ return 1
215
+ fi
216
+ fi
217
+ return 0
218
+ }
219
+
220
+ record_debounce() {
221
+ [[ -n "$_DEBOUNCE_FILE" ]] && date +%s > "$_DEBOUNCE_FILE"
222
+ }
223
+
224
+ # ============================================================================
225
+ # 7. BULK OPERATION DETECTION (ADR-0130)
226
+ # ============================================================================
227
+
228
+ _BULK_COUNTER_FILE=""
229
+ _BULK_THRESHOLD=5 # 5+ ops in 10s = bulk mode
230
+ _BULK_WINDOW=10
231
+
232
+ is_bulk_operation() {
233
+ local project_root="${1:-$(find_project_root)}"
234
+
235
+ _BULK_COUNTER_FILE="${project_root}/.specweave/state/.bulk-op-counter"
236
+ mkdir -p "$(dirname "$_BULK_COUNTER_FILE")" 2>/dev/null
237
+
238
+ local now
239
+ now=$(date +%s)
240
+
241
+ # Read current count and timestamp
242
+ local count=0
243
+ local start_time=$now
244
+
245
+ if [[ -f "$_BULK_COUNTER_FILE" ]]; then
246
+ read -r count start_time < "$_BULK_COUNTER_FILE" 2>/dev/null || true
247
+
248
+ # Reset if window expired
249
+ if [[ $((now - start_time)) -gt $_BULK_WINDOW ]]; then
250
+ count=0
251
+ start_time=$now
252
+ fi
253
+ fi
254
+
255
+ # Increment and save
256
+ count=$((count + 1))
257
+ echo "$count $start_time" > "$_BULK_COUNTER_FILE"
258
+
259
+ if [[ $count -ge $_BULK_THRESHOLD ]]; then
260
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Bulk operation detected ($count ops in window)" >&2
261
+ return 0 # IS bulk operation
262
+ fi
263
+ return 1 # NOT bulk operation
264
+ }
265
+
266
+ # ============================================================================
267
+ # 8. LOG ROTATION (ADR-0060)
268
+ # ============================================================================
269
+
270
+ _LOG_FILE=""
271
+ _LOG_MAX_SIZE=1048576 # 1MB
272
+
273
+ init_log() {
274
+ local log_name="${1:-hooks}"
275
+ local project_root="${2:-$(find_project_root)}"
276
+
277
+ _LOG_DIR="${project_root}/.specweave/logs"
278
+ mkdir -p "$_LOG_DIR" 2>/dev/null
279
+ _LOG_FILE="${_LOG_DIR}/${log_name}.log"
280
+
281
+ # Rotate if too large
282
+ if [[ -f "$_LOG_FILE" ]]; then
283
+ local size
284
+ size=$(stat -f%z "$_LOG_FILE" 2>/dev/null || stat -c%s "$_LOG_FILE" 2>/dev/null || echo "0")
285
+ if [[ "$size" -gt "$_LOG_MAX_SIZE" ]]; then
286
+ mv "$_LOG_FILE" "${_LOG_FILE}.1" 2>/dev/null
287
+ fi
288
+ fi
289
+ }
290
+
291
+ log_hook() {
292
+ local level="$1"
293
+ shift
294
+ local msg="$*"
295
+
296
+ [[ -z "$_LOG_FILE" ]] && return
297
+ echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] [$level] $msg" >> "$_LOG_FILE"
298
+ }
299
+
300
+ # ============================================================================
301
+ # 9. UNIFIED SETUP (ALL CHECKS IN ONE CALL)
302
+ # ============================================================================
303
+
304
+ setup_hook_environment() {
305
+ local hook_name="${1:-unnamed}"
306
+ local require_lock="${2:-false}"
307
+ local enable_recursion_guard="${3:-false}"
308
+
309
+ # Find project root
310
+ PROJECT_ROOT=$(find_project_root)
311
+ if [[ -z "$PROJECT_ROOT" ]]; then
312
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Not in SpecWeave project" >&2
313
+ return 1
314
+ fi
315
+ export PROJECT_ROOT
316
+
317
+ # Initialize state directory
318
+ _STATE_DIR="${PROJECT_ROOT}/.specweave/state"
319
+ mkdir -p "$_STATE_DIR" 2>/dev/null
320
+
321
+ # Layer 1: Kill switch
322
+ check_kill_switch || return 1
323
+
324
+ # Layer 2: Circuit breaker
325
+ init_circuit_breaker "$PROJECT_ROOT"
326
+ check_circuit_breaker || return 1
327
+
328
+ # Layer 3: Recursion guard (if enabled)
329
+ if [[ "$enable_recursion_guard" == "true" ]]; then
330
+ init_recursion_guard "$PROJECT_ROOT"
331
+ check_recursion_guard || return 1
332
+ fi
333
+
334
+ # Layer 4: Lock (if required)
335
+ if [[ "$require_lock" == "true" ]]; then
336
+ acquire_hook_lock "$hook_name" "$PROJECT_ROOT" || return 1
337
+ fi
338
+
339
+ # Layer 5: Debouncing
340
+ check_debounce "$hook_name" "$PROJECT_ROOT" || return 1
341
+
342
+ # Initialize logging
343
+ init_log "hooks" "$PROJECT_ROOT"
344
+
345
+ [[ "$HOOK_DEBUG" == "1" ]] && echo "[HOOK] Environment ready: $hook_name" >&2
346
+ return 0
347
+ }
348
+
349
+ # ============================================================================
350
+ # 10. SAFE EXIT HANDLERS
351
+ # ============================================================================
352
+
353
+ # Always exit 0 from hooks (ADR-0157 Rule 6)
354
+ # Exception: PreToolUse guards exit 2 to block
355
+ hook_exit_success() {
356
+ release_hook_lock
357
+ release_recursion_guard
358
+ exit 0
359
+ }
360
+
361
+ hook_exit_block() {
362
+ release_hook_lock
363
+ release_recursion_guard
364
+ exit 2 # Block PreToolUse
365
+ }
366
+
367
+ # Record failure and exit safely
368
+ hook_exit_with_failure() {
369
+ local msg="$1"
370
+ record_circuit_breaker_failure
371
+ log_hook "ERROR" "$msg"
372
+ release_hook_lock
373
+ release_recursion_guard
374
+ exit 0 # Still exit 0 to not break Claude
375
+ }
@@ -0,0 +1,336 @@
1
+ #!/bin/bash
2
+ # crash-prevention.sh - Unified Crash Prevention Runtime
3
+ #
4
+ # Consolidates ALL crash prevention patterns from 9 crash categories:
5
+ # 1. Bash heredoc hangs (infinite wait for EOF)
6
+ # 2. Context explosion (>280KB total)
7
+ # 3. Hook recursion loops
8
+ # 4. Process storms (bulk operations)
9
+ # 5. Agent chunking violations
10
+ # 6. Direct completion bypass
11
+ # 7. Hook registration duplicates
12
+ # 8. Context compaction deadlock
13
+ # 9. MCP connection drops
14
+ #
15
+ # This is the SINGLE SOURCE OF TRUTH for crash prevention.
16
+ # Consolidated from ADRs: 0060, 0068, 0073, 0127, 0128, 0130, 0133, 0157, 0189
17
+ #
18
+ # v0.33.0 - Initial consolidation
19
+
20
+ set +e
21
+
22
+ # ============================================================================
23
+ # CRASH CATEGORY 1: BASH HEREDOC DETECTION
24
+ # ============================================================================
25
+
26
+ # Patterns that cause INFINITE HANGS (shell waits forever for EOF)
27
+ detect_bash_hang_pattern() {
28
+ local command="$1"
29
+
30
+ # Heredoc patterns (MOST DANGEROUS)
31
+ if echo "$command" | grep -qE "<<-?[[:space:]]*['\"]?[A-Za-z_]+" 2>/dev/null; then
32
+ echo "heredoc"
33
+ return 0
34
+ fi
35
+
36
+ # Cat stdin redirect (waits forever)
37
+ if echo "$command" | grep -qE "^[[:space:]]*cat[[:space:]]+>[[:space:]]*[^>]" 2>/dev/null; then
38
+ echo "cat-stdin"
39
+ return 0
40
+ fi
41
+
42
+ # DD command with output file
43
+ if echo "$command" | grep -qE "^[[:space:]]*dd[[:space:]].*of=" 2>/dev/null; then
44
+ echo "dd-stdin"
45
+ return 0
46
+ fi
47
+
48
+ # Echo/printf to file (truncation risk)
49
+ if echo "$command" | grep -qE "^[[:space:]]*(echo|printf)[[:space:]]" 2>/dev/null; then
50
+ if echo "$command" | grep -qE '>[[:space:]]*[^>]' 2>/dev/null; then
51
+ if ! echo "$command" | grep -qE '>>' 2>/dev/null; then
52
+ echo "echo-redirect"
53
+ return 0
54
+ fi
55
+ fi
56
+ fi
57
+
58
+ return 1
59
+ }
60
+
61
+ # ============================================================================
62
+ # CRASH CATEGORY 2: CONTEXT BUDGET ESTIMATION
63
+ # ============================================================================
64
+
65
+ # Rough token estimation (1 token ≈ 4 chars)
66
+ estimate_tokens() {
67
+ local file="$1"
68
+ if [[ -f "$file" ]]; then
69
+ local chars
70
+ chars=$(wc -c < "$file" 2>/dev/null || echo "0")
71
+ echo $((chars / 4))
72
+ else
73
+ echo "0"
74
+ fi
75
+ }
76
+
77
+ # Check if context is in danger zone
78
+ check_context_budget() {
79
+ local project_root="$1"
80
+ local active_increment="$2"
81
+
82
+ local total_tokens=0
83
+ local warning_threshold=150000 # ~150K tokens
84
+ local danger_threshold=200000 # ~200K tokens
85
+
86
+ # Estimate increment context
87
+ if [[ -n "$active_increment" ]] && [[ -d "$project_root/.specweave/increments/$active_increment" ]]; then
88
+ local inc_dir="$project_root/.specweave/increments/$active_increment"
89
+
90
+ local spec_tokens=$(estimate_tokens "$inc_dir/spec.md")
91
+ local plan_tokens=$(estimate_tokens "$inc_dir/plan.md")
92
+ local tasks_tokens=$(estimate_tokens "$inc_dir/tasks.md")
93
+
94
+ total_tokens=$((spec_tokens + plan_tokens + tasks_tokens))
95
+ fi
96
+
97
+ # Return status
98
+ if [[ $total_tokens -gt $danger_threshold ]]; then
99
+ echo "DANGER:$total_tokens"
100
+ return 2
101
+ elif [[ $total_tokens -gt $warning_threshold ]]; then
102
+ echo "WARNING:$total_tokens"
103
+ return 1
104
+ else
105
+ echo "OK:$total_tokens"
106
+ return 0
107
+ fi
108
+ }
109
+
110
+ # Count tasks in active increment
111
+ count_increment_tasks() {
112
+ local project_root="$1"
113
+ local active_increment="$2"
114
+
115
+ local tasks_file="$project_root/.specweave/increments/$active_increment/tasks.md"
116
+ if [[ -f "$tasks_file" ]]; then
117
+ grep -c "^### T-" "$tasks_file" 2>/dev/null || echo "0"
118
+ else
119
+ echo "0"
120
+ fi
121
+ }
122
+
123
+ # ============================================================================
124
+ # CRASH CATEGORY 3: PROCESS STORM DETECTION
125
+ # ============================================================================
126
+
127
+ # Count running hook processes
128
+ count_hook_processes() {
129
+ ps aux 2>/dev/null | grep -c "specweave.*hook" || echo "0"
130
+ }
131
+
132
+ # Detect if we're in a process storm
133
+ detect_process_storm() {
134
+ local threshold="${1:-20}"
135
+ local count
136
+ count=$(count_hook_processes)
137
+
138
+ if [[ "$count" -gt "$threshold" ]]; then
139
+ echo "STORM:$count"
140
+ return 1
141
+ fi
142
+ echo "OK:$count"
143
+ return 0
144
+ }
145
+
146
+ # ============================================================================
147
+ # CRASH CATEGORY 4: ZOMBIE PROCESS DETECTION
148
+ # ============================================================================
149
+
150
+ # Find and kill zombie heredoc processes
151
+ kill_zombie_heredocs() {
152
+ # Kill any cat processes waiting for EOF
153
+ pkill -f "cat.*EOF" 2>/dev/null || true
154
+ pkill -f "cat.*<<" 2>/dev/null || true
155
+
156
+ # Kill stale bash processes related to specweave hooks
157
+ local stale_pids
158
+ stale_pids=$(ps aux 2>/dev/null | grep -E "bash.*specweave.*hook" | grep -v grep | awk '{print $2}' | head -10)
159
+
160
+ for pid in $stale_pids; do
161
+ # Check if process is older than 30 seconds
162
+ local elapsed
163
+ elapsed=$(ps -o etimes= -p "$pid" 2>/dev/null | tr -d ' ')
164
+ if [[ -n "$elapsed" ]] && [[ "$elapsed" -gt 30 ]]; then
165
+ kill -9 "$pid" 2>/dev/null || true
166
+ fi
167
+ done
168
+ }
169
+
170
+ # ============================================================================
171
+ # CRASH CATEGORY 5: LOCK FILE CLEANUP
172
+ # ============================================================================
173
+
174
+ # Clean stale lock files (older than 60s)
175
+ clean_stale_locks() {
176
+ local project_root="$1"
177
+ local state_dir="$project_root/.specweave/state"
178
+
179
+ [[ ! -d "$state_dir" ]] && return
180
+
181
+ find "$state_dir" -name "*.lock" -type d -mmin +1 2>/dev/null | while read -r lock; do
182
+ rmdir "$lock" 2>/dev/null || true
183
+ done
184
+
185
+ # Also clean stale guard files
186
+ find "$state_dir" -name ".hook-*-guard" -type f -mmin +1 2>/dev/null | while read -r guard; do
187
+ rm -f "$guard" 2>/dev/null
188
+ done
189
+ }
190
+
191
+ # ============================================================================
192
+ # CRASH CATEGORY 6: SESSION HEALTH CHECK
193
+ # ============================================================================
194
+
195
+ # Comprehensive health check
196
+ check_session_health() {
197
+ local project_root="$1"
198
+ local issues=()
199
+
200
+ # Check 1: Process storm
201
+ local storm_status
202
+ storm_status=$(detect_process_storm 15)
203
+ if [[ "$storm_status" == STORM* ]]; then
204
+ issues+=("Process storm detected: $storm_status")
205
+ fi
206
+
207
+ # Check 2: Stale locks
208
+ local stale_locks
209
+ stale_locks=$(find "$project_root/.specweave/state" -name "*.lock" -type d -mmin +1 2>/dev/null | wc -l | tr -d ' ')
210
+ if [[ "$stale_locks" -gt 0 ]]; then
211
+ issues+=("Stale locks: $stale_locks")
212
+ fi
213
+
214
+ # Check 3: Circuit breaker status
215
+ local cb_file="$project_root/.specweave/state/.hook-circuit-breaker"
216
+ if [[ -f "$cb_file" ]]; then
217
+ local failures
218
+ failures=$(cat "$cb_file" 2>/dev/null || echo "0")
219
+ if [[ "$failures" -ge 3 ]]; then
220
+ issues+=("Circuit breaker OPEN: $failures failures")
221
+ fi
222
+ fi
223
+
224
+ # Check 4: Active increment task count
225
+ local active_inc
226
+ active_inc=$(find "$project_root/.specweave/increments" -maxdepth 1 -type d -name "[0-9]*" 2>/dev/null | head -1 | xargs basename 2>/dev/null)
227
+ if [[ -n "$active_inc" ]]; then
228
+ local task_count
229
+ task_count=$(count_increment_tasks "$project_root" "$active_inc")
230
+ if [[ "$task_count" -gt 8 ]]; then
231
+ issues+=("Task count exceeds limit: $task_count/8 in $active_inc")
232
+ fi
233
+ fi
234
+
235
+ # Report
236
+ if [[ ${#issues[@]} -eq 0 ]]; then
237
+ echo "HEALTHY"
238
+ return 0
239
+ else
240
+ echo "ISSUES:"
241
+ printf '%s\n' "${issues[@]}"
242
+ return 1
243
+ fi
244
+ }
245
+
246
+ # ============================================================================
247
+ # CRASH CATEGORY 7: EMERGENCY CLEANUP
248
+ # ============================================================================
249
+
250
+ # Nuclear option: clean ALL state
251
+ emergency_cleanup() {
252
+ local project_root="$1"
253
+
254
+ echo "=== EMERGENCY CLEANUP ==="
255
+
256
+ # 1. Kill zombie processes
257
+ echo "1. Killing zombie processes..."
258
+ kill_zombie_heredocs
259
+ pkill -9 -f "bash.*specweave" 2>/dev/null || true
260
+
261
+ # 2. Remove all locks
262
+ echo "2. Removing all locks..."
263
+ rm -rf "$project_root/.specweave/state/"*.lock 2>/dev/null
264
+ rm -f "$project_root/.specweave/state/.hook-"* 2>/dev/null
265
+ rm -f "$project_root/.specweave/state/.processor.lock" 2>/dev/null
266
+
267
+ # 3. Reset circuit breakers
268
+ echo "3. Resetting circuit breakers..."
269
+ rm -f "$project_root/.specweave/state/.hook-circuit-breaker"* 2>/dev/null
270
+
271
+ # 4. Clear dedup cache
272
+ echo "4. Clearing dedup cache..."
273
+ rm -rf "$project_root/.specweave/state/.dedup-cache" 2>/dev/null
274
+
275
+ # 5. Clear bulk operation counter
276
+ echo "5. Clearing bulk operation counter..."
277
+ rm -f "$project_root/.specweave/state/.bulk-op-counter" 2>/dev/null
278
+
279
+ echo "=== CLEANUP COMPLETE ==="
280
+ echo "Restart Claude Code to continue."
281
+ }
282
+
283
+ # ============================================================================
284
+ # RUNTIME GUARDS (for use in hooks)
285
+ # ============================================================================
286
+
287
+ # Pre-execution guard for any hook
288
+ guard_hook_execution() {
289
+ local hook_name="$1"
290
+ local project_root="$2"
291
+
292
+ # Check for process storm
293
+ local storm
294
+ storm=$(detect_process_storm 20)
295
+ if [[ "$storm" == STORM* ]]; then
296
+ echo "[GUARD] Blocking $hook_name: $storm" >&2
297
+ return 1
298
+ fi
299
+
300
+ return 0
301
+ }
302
+
303
+ # ============================================================================
304
+ # MAIN (when run directly)
305
+ # ============================================================================
306
+
307
+ if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
308
+ case "${1:-health}" in
309
+ health)
310
+ PROJECT_ROOT=$(find "$PWD" -maxdepth 3 -type d -name ".specweave" 2>/dev/null | head -1 | xargs dirname 2>/dev/null)
311
+ if [[ -n "$PROJECT_ROOT" ]]; then
312
+ check_session_health "$PROJECT_ROOT"
313
+ else
314
+ echo "Not in a SpecWeave project"
315
+ exit 1
316
+ fi
317
+ ;;
318
+ cleanup)
319
+ PROJECT_ROOT=$(find "$PWD" -maxdepth 3 -type d -name ".specweave" 2>/dev/null | head -1 | xargs dirname 2>/dev/null)
320
+ if [[ -n "$PROJECT_ROOT" ]]; then
321
+ emergency_cleanup "$PROJECT_ROOT"
322
+ else
323
+ echo "Not in a SpecWeave project"
324
+ exit 1
325
+ fi
326
+ ;;
327
+ kill-zombies)
328
+ kill_zombie_heredocs
329
+ echo "Zombie processes cleaned"
330
+ ;;
331
+ *)
332
+ echo "Usage: $0 {health|cleanup|kill-zombies}"
333
+ exit 1
334
+ ;;
335
+ esac
336
+ fi