@paths.design/caws-cli 10.1.0 → 11.0.0

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 (419) hide show
  1. package/README.md +125 -374
  2. package/dist/index.js +43 -756
  3. package/dist/shell/binding/resolve-binding.d.ts +4 -0
  4. package/dist/shell/binding/resolve-binding.d.ts.map +1 -0
  5. package/dist/shell/binding/resolve-binding.js +228 -0
  6. package/dist/shell/binding/resolve-binding.js.map +1 -0
  7. package/dist/shell/binding/types.d.ts +42 -0
  8. package/dist/shell/binding/types.d.ts.map +1 -0
  9. package/dist/shell/binding/types.js +21 -0
  10. package/dist/shell/binding/types.js.map +1 -0
  11. package/dist/shell/commands/claim.d.ts +14 -0
  12. package/dist/shell/commands/claim.d.ts.map +1 -0
  13. package/dist/shell/commands/claim.js +197 -0
  14. package/dist/shell/commands/claim.js.map +1 -0
  15. package/dist/shell/commands/doctor.d.ts +13 -0
  16. package/dist/shell/commands/doctor.d.ts.map +1 -0
  17. package/dist/shell/commands/doctor.js +97 -0
  18. package/dist/shell/commands/doctor.js.map +1 -0
  19. package/dist/shell/commands/evidence.d.ts +28 -0
  20. package/dist/shell/commands/evidence.d.ts.map +1 -0
  21. package/dist/shell/commands/evidence.js +166 -0
  22. package/dist/shell/commands/evidence.js.map +1 -0
  23. package/dist/shell/commands/gates.d.ts +19 -0
  24. package/dist/shell/commands/gates.d.ts.map +1 -0
  25. package/dist/shell/commands/gates.js +181 -0
  26. package/dist/shell/commands/gates.js.map +1 -0
  27. package/dist/shell/commands/init.d.ts +8 -0
  28. package/dist/shell/commands/init.d.ts.map +1 -0
  29. package/dist/shell/commands/init.js +64 -0
  30. package/dist/shell/commands/init.js.map +1 -0
  31. package/dist/shell/commands/scope.d.ts +11 -0
  32. package/dist/shell/commands/scope.d.ts.map +1 -0
  33. package/dist/shell/commands/scope.js +92 -0
  34. package/dist/shell/commands/scope.js.map +1 -0
  35. package/dist/shell/commands/status.d.ts +15 -0
  36. package/dist/shell/commands/status.d.ts.map +1 -0
  37. package/dist/shell/commands/status.js +106 -0
  38. package/dist/shell/commands/status.js.map +1 -0
  39. package/dist/shell/commands/waiver.d.ts +38 -0
  40. package/dist/shell/commands/waiver.d.ts.map +1 -0
  41. package/dist/shell/commands/waiver.js +240 -0
  42. package/dist/shell/commands/waiver.js.map +1 -0
  43. package/dist/shell/gates/disposition.d.ts +23 -0
  44. package/dist/shell/gates/disposition.d.ts.map +1 -0
  45. package/dist/shell/gates/disposition.js +87 -0
  46. package/dist/shell/gates/disposition.js.map +1 -0
  47. package/dist/shell/gates/gate-result-contract.d.ts +39 -0
  48. package/dist/shell/gates/gate-result-contract.d.ts.map +1 -0
  49. package/dist/shell/gates/gate-result-contract.js +150 -0
  50. package/dist/shell/gates/gate-result-contract.js.map +1 -0
  51. package/dist/shell/gates/quality-gates-adapter.d.ts +55 -0
  52. package/dist/shell/gates/quality-gates-adapter.d.ts.map +1 -0
  53. package/dist/shell/gates/quality-gates-adapter.js +161 -0
  54. package/dist/shell/gates/quality-gates-adapter.js.map +1 -0
  55. package/dist/shell/gates/waiver-filter.d.ts +58 -0
  56. package/dist/shell/gates/waiver-filter.d.ts.map +1 -0
  57. package/dist/shell/gates/waiver-filter.js +119 -0
  58. package/dist/shell/gates/waiver-filter.js.map +1 -0
  59. package/dist/shell/index.d.ts +50 -0
  60. package/dist/shell/index.d.ts.map +1 -0
  61. package/dist/shell/index.js +73 -0
  62. package/dist/shell/index.js.map +1 -0
  63. package/dist/shell/register.d.ts +11 -0
  64. package/dist/shell/register.d.ts.map +1 -0
  65. package/dist/shell/register.js +274 -0
  66. package/dist/shell/register.js.map +1 -0
  67. package/dist/shell/render/claim.d.ts +22 -0
  68. package/dist/shell/render/claim.d.ts.map +1 -0
  69. package/dist/shell/render/claim.js +75 -0
  70. package/dist/shell/render/claim.js.map +1 -0
  71. package/dist/shell/render/decision.d.ts +15 -0
  72. package/dist/shell/render/decision.d.ts.map +1 -0
  73. package/dist/shell/render/decision.js +66 -0
  74. package/dist/shell/render/decision.js.map +1 -0
  75. package/dist/shell/render/diagnostic.d.ts +19 -0
  76. package/dist/shell/render/diagnostic.d.ts.map +1 -0
  77. package/dist/shell/render/diagnostic.js +76 -0
  78. package/dist/shell/render/diagnostic.js.map +1 -0
  79. package/dist/shell/render/finding.d.ts +15 -0
  80. package/dist/shell/render/finding.d.ts.map +1 -0
  81. package/dist/shell/render/finding.js +57 -0
  82. package/dist/shell/render/finding.js.map +1 -0
  83. package/dist/shell/render/gates.d.ts +3 -0
  84. package/dist/shell/render/gates.d.ts.map +1 -0
  85. package/dist/shell/render/gates.js +56 -0
  86. package/dist/shell/render/gates.js.map +1 -0
  87. package/dist/shell/render/init.d.ts +11 -0
  88. package/dist/shell/render/init.d.ts.map +1 -0
  89. package/dist/shell/render/init.js +32 -0
  90. package/dist/shell/render/init.js.map +1 -0
  91. package/dist/shell/render/status.d.ts +26 -0
  92. package/dist/shell/render/status.d.ts.map +1 -0
  93. package/dist/shell/render/status.js +143 -0
  94. package/dist/shell/render/status.js.map +1 -0
  95. package/dist/shell/render/waiver.d.ts +21 -0
  96. package/dist/shell/render/waiver.d.ts.map +1 -0
  97. package/dist/shell/render/waiver.js +94 -0
  98. package/dist/shell/render/waiver.js.map +1 -0
  99. package/dist/shell/rules.d.ts +37 -0
  100. package/dist/shell/rules.d.ts.map +1 -0
  101. package/dist/shell/rules.js +51 -0
  102. package/dist/shell/rules.js.map +1 -0
  103. package/dist/shell/session/actor.d.ts +14 -0
  104. package/dist/shell/session/actor.d.ts.map +1 -0
  105. package/dist/shell/session/actor.js +34 -0
  106. package/dist/shell/session/actor.js.map +1 -0
  107. package/dist/shell/session/resolve-session.d.ts +5 -0
  108. package/dist/shell/session/resolve-session.d.ts.map +1 -0
  109. package/dist/shell/session/resolve-session.js +239 -0
  110. package/dist/shell/session/resolve-session.js.map +1 -0
  111. package/dist/shell/session/types.d.ts +56 -0
  112. package/dist/shell/session/types.d.ts.map +1 -0
  113. package/dist/shell/session/types.js +15 -0
  114. package/dist/shell/session/types.js.map +1 -0
  115. package/dist/store/agents-store.d.ts +3 -0
  116. package/dist/store/agents-store.d.ts.map +1 -0
  117. package/dist/store/agents-store.js +63 -0
  118. package/dist/store/agents-store.js.map +1 -0
  119. package/dist/store/apply-patch.d.ts +16 -0
  120. package/dist/store/apply-patch.d.ts.map +1 -0
  121. package/dist/store/apply-patch.js +191 -0
  122. package/dist/store/apply-patch.js.map +1 -0
  123. package/dist/store/atomic-write.d.ts +16 -0
  124. package/dist/store/atomic-write.d.ts.map +1 -0
  125. package/dist/store/atomic-write.js +132 -0
  126. package/dist/store/atomic-write.js.map +1 -0
  127. package/dist/store/doctor-snapshot.d.ts +20 -0
  128. package/dist/store/doctor-snapshot.d.ts.map +1 -0
  129. package/dist/store/doctor-snapshot.js +176 -0
  130. package/dist/store/doctor-snapshot.js.map +1 -0
  131. package/dist/store/events-store.d.ts +33 -0
  132. package/dist/store/events-store.d.ts.map +1 -0
  133. package/dist/store/events-store.js +297 -0
  134. package/dist/store/events-store.js.map +1 -0
  135. package/dist/store/index.d.ts +21 -0
  136. package/dist/store/index.d.ts.map +1 -0
  137. package/dist/store/index.js +47 -0
  138. package/dist/store/index.js.map +1 -0
  139. package/dist/store/init-store.d.ts +21 -0
  140. package/dist/store/init-store.d.ts.map +1 -0
  141. package/dist/store/init-store.js +295 -0
  142. package/dist/store/init-store.js.map +1 -0
  143. package/dist/store/json-store.d.ts +3 -0
  144. package/dist/store/json-store.d.ts.map +1 -0
  145. package/dist/store/json-store.js +65 -0
  146. package/dist/store/json-store.js.map +1 -0
  147. package/dist/store/policy-store.d.ts +3 -0
  148. package/dist/store/policy-store.d.ts.map +1 -0
  149. package/dist/store/policy-store.js +65 -0
  150. package/dist/store/policy-store.js.map +1 -0
  151. package/dist/store/repo-root.d.ts +46 -0
  152. package/dist/store/repo-root.d.ts.map +1 -0
  153. package/dist/store/repo-root.js +145 -0
  154. package/dist/store/repo-root.js.map +1 -0
  155. package/dist/store/rules.d.ts +53 -0
  156. package/dist/store/rules.d.ts.map +1 -0
  157. package/dist/store/rules.js +78 -0
  158. package/dist/store/rules.js.map +1 -0
  159. package/dist/store/specs-store.d.ts +3 -0
  160. package/dist/store/specs-store.d.ts.map +1 -0
  161. package/dist/store/specs-store.js +131 -0
  162. package/dist/store/specs-store.js.map +1 -0
  163. package/dist/store/types.d.ts +84 -0
  164. package/dist/store/types.d.ts.map +1 -0
  165. package/dist/store/types.js +14 -0
  166. package/dist/store/types.js.map +1 -0
  167. package/dist/store/waivers-store.d.ts +25 -0
  168. package/dist/store/waivers-store.d.ts.map +1 -0
  169. package/dist/store/waivers-store.js +232 -0
  170. package/dist/store/waivers-store.js.map +1 -0
  171. package/dist/store/worktrees-store.d.ts +3 -0
  172. package/dist/store/worktrees-store.d.ts.map +1 -0
  173. package/dist/store/worktrees-store.js +62 -0
  174. package/dist/store/worktrees-store.js.map +1 -0
  175. package/dist/store/yaml-store.d.ts +9 -0
  176. package/dist/store/yaml-store.d.ts.map +1 -0
  177. package/dist/store/yaml-store.js +121 -0
  178. package/dist/store/yaml-store.js.map +1 -0
  179. package/package.json +15 -13
  180. package/dist/budget-derivation.js +0 -751
  181. package/dist/cicd-optimizer.js +0 -504
  182. package/dist/commands/archive.js +0 -500
  183. package/dist/commands/burnup.js +0 -198
  184. package/dist/commands/diagnose.js +0 -525
  185. package/dist/commands/evaluate.js +0 -314
  186. package/dist/commands/gates.js +0 -149
  187. package/dist/commands/init.js +0 -857
  188. package/dist/commands/iterate.js +0 -417
  189. package/dist/commands/mode.js +0 -269
  190. package/dist/commands/parallel.js +0 -242
  191. package/dist/commands/plan.js +0 -438
  192. package/dist/commands/provenance.js +0 -1143
  193. package/dist/commands/quality-monitor.js +0 -284
  194. package/dist/commands/scope.js +0 -264
  195. package/dist/commands/session.js +0 -312
  196. package/dist/commands/sidecar.js +0 -74
  197. package/dist/commands/specs.js +0 -1448
  198. package/dist/commands/status.js +0 -1151
  199. package/dist/commands/templates.js +0 -237
  200. package/dist/commands/tool.js +0 -136
  201. package/dist/commands/tutorial.js +0 -480
  202. package/dist/commands/validate.js +0 -357
  203. package/dist/commands/verify-acs.js +0 -443
  204. package/dist/commands/waivers.js +0 -599
  205. package/dist/commands/workflow.js +0 -243
  206. package/dist/commands/worktree.js +0 -386
  207. package/dist/config/lite-scope.js +0 -158
  208. package/dist/config/modes.js +0 -347
  209. package/dist/constants/spec-types.js +0 -65
  210. package/dist/gates/budget-limit.js +0 -121
  211. package/dist/gates/feedback.js +0 -260
  212. package/dist/gates/format.js +0 -179
  213. package/dist/gates/god-object.js +0 -117
  214. package/dist/gates/pipeline.js +0 -167
  215. package/dist/gates/scope-boundary.js +0 -93
  216. package/dist/gates/spec-completeness.js +0 -109
  217. package/dist/gates/todo-detection.js +0 -205
  218. package/dist/generators/jest-config-generator.js +0 -242
  219. package/dist/generators/working-spec.js +0 -237
  220. package/dist/minimal-cli.js +0 -88
  221. package/dist/parallel/parallel-manager.js +0 -433
  222. package/dist/policy/PolicyManager.js +0 -465
  223. package/dist/scaffold/claude-hooks.js +0 -443
  224. package/dist/scaffold/cursor-hooks.js +0 -177
  225. package/dist/scaffold/git-hooks.js +0 -928
  226. package/dist/scaffold/index.js +0 -794
  227. package/dist/session/session-manager.js +0 -653
  228. package/dist/sidecars/index.js +0 -33
  229. package/dist/sidecars/listeners.js +0 -40
  230. package/dist/sidecars/provenance-summary.js +0 -238
  231. package/dist/sidecars/quality-gaps.js +0 -258
  232. package/dist/sidecars/schema.js +0 -149
  233. package/dist/sidecars/spec-drift.js +0 -151
  234. package/dist/sidecars/waiver-draft.js +0 -176
  235. package/dist/spec/SpecFileManager.js +0 -419
  236. package/dist/templates/.caws/schemas/policy.schema.json +0 -112
  237. package/dist/templates/.caws/schemas/scope.schema.json +0 -52
  238. package/dist/templates/.caws/schemas/waivers.schema.json +0 -106
  239. package/dist/templates/.caws/schemas/working-spec.schema.json +0 -340
  240. package/dist/templates/.caws/schemas/worktrees.schema.json +0 -38
  241. package/dist/templates/.caws/templates/working-spec.template.yml +0 -80
  242. package/dist/templates/.caws/tools/README.md +0 -18
  243. package/dist/templates/.caws/tools/scope-guard.js +0 -203
  244. package/dist/templates/.caws/tools-allow.json +0 -331
  245. package/dist/templates/.caws/waivers.yml +0 -19
  246. package/dist/templates/.claude/README.md +0 -190
  247. package/dist/templates/.claude/hooks/audit.sh +0 -121
  248. package/dist/templates/.claude/hooks/block-dangerous.sh +0 -203
  249. package/dist/templates/.claude/hooks/classify_command.py +0 -592
  250. package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
  251. package/dist/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
  252. package/dist/templates/.claude/hooks/naming-check.sh +0 -100
  253. package/dist/templates/.claude/hooks/protected-paths.sh +0 -39
  254. package/dist/templates/.claude/hooks/quality-check.sh +0 -81
  255. package/dist/templates/.claude/hooks/scan-secrets.sh +0 -85
  256. package/dist/templates/.claude/hooks/scope-guard.sh +0 -381
  257. package/dist/templates/.claude/hooks/session-caws-status.sh +0 -117
  258. package/dist/templates/.claude/hooks/session-log.sh +0 -634
  259. package/dist/templates/.claude/hooks/simplification-guard.sh +0 -92
  260. package/dist/templates/.claude/hooks/stop-worktree-check.sh +0 -46
  261. package/dist/templates/.claude/hooks/test_classify_command.py +0 -370
  262. package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
  263. package/dist/templates/.claude/hooks/validate-spec.sh +0 -76
  264. package/dist/templates/.claude/hooks/worktree-guard.sh +0 -220
  265. package/dist/templates/.claude/hooks/worktree-write-guard.sh +0 -190
  266. package/dist/templates/.claude/rules/git-safety.md +0 -26
  267. package/dist/templates/.claude/rules/worktree-isolation.md +0 -83
  268. package/dist/templates/.claude/settings.json +0 -141
  269. package/dist/templates/.cursor/README.md +0 -299
  270. package/dist/templates/.cursor/hooks/audit.sh +0 -55
  271. package/dist/templates/.cursor/hooks/block-dangerous.sh +0 -84
  272. package/dist/templates/.cursor/hooks/caws-quality-check.sh +0 -52
  273. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
  274. package/dist/templates/.cursor/hooks/format.sh +0 -38
  275. package/dist/templates/.cursor/hooks/naming-check.sh +0 -64
  276. package/dist/templates/.cursor/hooks/scan-secrets.sh +0 -51
  277. package/dist/templates/.cursor/hooks/scope-guard.sh +0 -52
  278. package/dist/templates/.cursor/hooks/session-log.sh +0 -924
  279. package/dist/templates/.cursor/hooks/validate-spec.sh +0 -83
  280. package/dist/templates/.cursor/hooks.json +0 -76
  281. package/dist/templates/.cursor/rules/00-claims-verification.mdc +0 -144
  282. package/dist/templates/.cursor/rules/01-working-style.mdc +0 -50
  283. package/dist/templates/.cursor/rules/02-quality-gates.mdc +0 -368
  284. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
  285. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
  286. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
  287. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
  288. package/dist/templates/.cursor/rules/07-process-ops.mdc +0 -20
  289. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
  290. package/dist/templates/.cursor/rules/09-docstrings.mdc +0 -89
  291. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
  292. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
  293. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
  294. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
  295. package/dist/templates/.cursor/rules/README.md +0 -148
  296. package/dist/templates/.github/copilot-instructions.md +0 -82
  297. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
  298. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
  299. package/dist/templates/.junie/guidelines.md +0 -73
  300. package/dist/templates/.vscode/launch.json +0 -17
  301. package/dist/templates/.vscode/settings.json +0 -95
  302. package/dist/templates/.windsurf/rules/caws-quality-standards.md +0 -54
  303. package/dist/templates/.windsurf/workflows/caws-guided-development.md +0 -92
  304. package/dist/templates/CLAUDE.md +0 -174
  305. package/dist/templates/COMMIT_CONVENTIONS.md +0 -86
  306. package/dist/templates/OIDC_SETUP.md +0 -300
  307. package/dist/templates/agents.md +0 -145
  308. package/dist/templates/codemod/README.md +0 -1
  309. package/dist/templates/codemod/test.js +0 -93
  310. package/dist/templates/docs/README.md +0 -151
  311. package/dist/templates/scripts/new_feature.sh +0 -80
  312. package/dist/templates/scripts/quality-gates/check-god-objects.js +0 -146
  313. package/dist/templates/scripts/quality-gates/run-quality-gates.js +0 -50
  314. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +0 -1997
  315. package/dist/test-analysis.js +0 -786
  316. package/dist/tool-interface.js +0 -314
  317. package/dist/tool-loader.js +0 -303
  318. package/dist/tool-validator.js +0 -393
  319. package/dist/utils/agent-session.js +0 -202
  320. package/dist/utils/async-utils.js +0 -188
  321. package/dist/utils/command-wrapper.js +0 -200
  322. package/dist/utils/event-log.js +0 -584
  323. package/dist/utils/event-renderer.js +0 -521
  324. package/dist/utils/finalization.js +0 -230
  325. package/dist/utils/git-lock.js +0 -119
  326. package/dist/utils/gitignore-updater.js +0 -158
  327. package/dist/utils/ide-detection.js +0 -133
  328. package/dist/utils/lifecycle-events.js +0 -94
  329. package/dist/utils/project-analysis.js +0 -367
  330. package/dist/utils/promise-utils.js +0 -72
  331. package/dist/utils/quality-gates-errors.js +0 -520
  332. package/dist/utils/quality-gates-utils.js +0 -387
  333. package/dist/utils/schema-validator.js +0 -50
  334. package/dist/utils/spec-resolver.js +0 -711
  335. package/dist/utils/typescript-detector.js +0 -369
  336. package/dist/utils/working-state.js +0 -530
  337. package/dist/utils/yaml-validation.js +0 -156
  338. package/dist/validation/spec-validation.js +0 -921
  339. package/dist/waivers-manager.js +0 -732
  340. package/dist/worktree/worktree-manager.js +0 -1374
  341. package/templates/.caws/schemas/policy.schema.json +0 -112
  342. package/templates/.caws/schemas/scope.schema.json +0 -52
  343. package/templates/.caws/schemas/waivers.schema.json +0 -106
  344. package/templates/.caws/schemas/working-spec.schema.json +0 -340
  345. package/templates/.caws/schemas/worktrees.schema.json +0 -38
  346. package/templates/.caws/templates/working-spec.template.yml +0 -80
  347. package/templates/.caws/tools/README.md +0 -18
  348. package/templates/.caws/tools/scope-guard.js +0 -203
  349. package/templates/.caws/tools-allow.json +0 -331
  350. package/templates/.caws/waivers.yml +0 -19
  351. package/templates/.claude/README.md +0 -190
  352. package/templates/.claude/hooks/audit.sh +0 -121
  353. package/templates/.claude/hooks/block-dangerous.sh +0 -203
  354. package/templates/.claude/hooks/classify_command.py +0 -592
  355. package/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
  356. package/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
  357. package/templates/.claude/hooks/naming-check.sh +0 -100
  358. package/templates/.claude/hooks/protected-paths.sh +0 -39
  359. package/templates/.claude/hooks/quality-check.sh +0 -81
  360. package/templates/.claude/hooks/scan-secrets.sh +0 -85
  361. package/templates/.claude/hooks/scope-guard.sh +0 -381
  362. package/templates/.claude/hooks/session-caws-status.sh +0 -117
  363. package/templates/.claude/hooks/session-log.sh +0 -634
  364. package/templates/.claude/hooks/simplification-guard.sh +0 -92
  365. package/templates/.claude/hooks/stop-worktree-check.sh +0 -46
  366. package/templates/.claude/hooks/test_classify_command.py +0 -370
  367. package/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
  368. package/templates/.claude/hooks/validate-spec.sh +0 -76
  369. package/templates/.claude/hooks/worktree-guard.sh +0 -220
  370. package/templates/.claude/hooks/worktree-write-guard.sh +0 -190
  371. package/templates/.claude/rules/git-safety.md +0 -26
  372. package/templates/.claude/rules/worktree-isolation.md +0 -83
  373. package/templates/.claude/settings.json +0 -141
  374. package/templates/.cursor/README.md +0 -299
  375. package/templates/.cursor/hooks/audit.sh +0 -55
  376. package/templates/.cursor/hooks/block-dangerous.sh +0 -84
  377. package/templates/.cursor/hooks/caws-quality-check.sh +0 -52
  378. package/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
  379. package/templates/.cursor/hooks/format.sh +0 -38
  380. package/templates/.cursor/hooks/naming-check.sh +0 -64
  381. package/templates/.cursor/hooks/scan-secrets.sh +0 -51
  382. package/templates/.cursor/hooks/scope-guard.sh +0 -52
  383. package/templates/.cursor/hooks/session-log.sh +0 -924
  384. package/templates/.cursor/hooks/validate-spec.sh +0 -83
  385. package/templates/.cursor/hooks.json +0 -76
  386. package/templates/.cursor/rules/00-claims-verification.mdc +0 -144
  387. package/templates/.cursor/rules/01-working-style.mdc +0 -50
  388. package/templates/.cursor/rules/02-quality-gates.mdc +0 -368
  389. package/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
  390. package/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
  391. package/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
  392. package/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
  393. package/templates/.cursor/rules/07-process-ops.mdc +0 -20
  394. package/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
  395. package/templates/.cursor/rules/09-docstrings.mdc +0 -89
  396. package/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
  397. package/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
  398. package/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
  399. package/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
  400. package/templates/.cursor/rules/README.md +0 -148
  401. package/templates/.github/copilot-instructions.md +0 -82
  402. package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
  403. package/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
  404. package/templates/.junie/guidelines.md +0 -73
  405. package/templates/.vscode/launch.json +0 -17
  406. package/templates/.vscode/settings.json +0 -95
  407. package/templates/.windsurf/rules/caws-quality-standards.md +0 -54
  408. package/templates/.windsurf/workflows/caws-guided-development.md +0 -92
  409. package/templates/CLAUDE.md +0 -174
  410. package/templates/COMMIT_CONVENTIONS.md +0 -86
  411. package/templates/OIDC_SETUP.md +0 -300
  412. package/templates/agents.md +0 -145
  413. package/templates/codemod/README.md +0 -1
  414. package/templates/codemod/test.js +0 -93
  415. package/templates/docs/README.md +0 -151
  416. package/templates/scripts/new_feature.sh +0 -80
  417. package/templates/scripts/quality-gates/check-god-objects.js +0 -146
  418. package/templates/scripts/quality-gates/run-quality-gates.js +0 -50
  419. package/templates/scripts/v3/analysis/todo_analyzer.py +0 -1997
@@ -1,928 +0,0 @@
1
- /**
2
- * @fileoverview Git Hooks Scaffolding for CAWS Provenance
3
- * Functions for setting up git hooks that automatically update provenance
4
- * @author @darianrosebrook
5
- */
6
-
7
- const fs = require('fs-extra');
8
- const path = require('path');
9
- const { getTodoAnalyzerSuggestion } = require('../utils/project-analysis');
10
-
11
- /**
12
- * Scaffold git hooks for CAWS provenance tracking
13
- * @param {string} projectDir - Project directory path
14
- * @param {Object} options - Hook options
15
- */
16
- async function scaffoldGitHooks(projectDir, options = {}) {
17
- const { provenance = true, validation = true, qualityGates = true, force = false } = options;
18
-
19
- console.log('Setting up Git hooks for CAWS provenance...');
20
-
21
- const gitDir = path.join(projectDir, '.git');
22
- const hooksDir = path.join(gitDir, 'hooks');
23
-
24
- // Check if this is a git repository
25
- if (!(await fs.pathExists(gitDir))) {
26
- console.log('Not a git repository - skipping git hooks setup');
27
- console.log('Initialize git first: git init');
28
- return { added: 0, skipped: 0 };
29
- }
30
-
31
- // Ensure hooks directory exists
32
- await fs.ensureDir(hooksDir);
33
-
34
- let addedCount = 0;
35
- let skippedCount = 0;
36
-
37
- // Define hook configurations
38
- const hooks = [
39
- {
40
- name: 'pre-commit',
41
- description: 'Pre-commit validation and quality checks',
42
- enabled: validation || qualityGates,
43
- content: generatePreCommitHook({ validation, qualityGates, projectDir }),
44
- },
45
- {
46
- name: 'post-commit',
47
- description: 'Post-commit provenance tracking',
48
- enabled: provenance,
49
- content: generatePostCommitHook(),
50
- },
51
- {
52
- name: 'pre-push',
53
- description: 'Pre-push comprehensive validation',
54
- enabled: qualityGates,
55
- content: generatePrePushHook(),
56
- },
57
- {
58
- name: 'commit-msg',
59
- description: 'Commit message validation',
60
- enabled: validation,
61
- content: generateCommitMsgHook(),
62
- },
63
- ];
64
-
65
- for (const hook of hooks) {
66
- if (!hook.enabled) continue;
67
-
68
- const hookPath = path.join(hooksDir, hook.name);
69
-
70
- try {
71
- // Check if hook already exists
72
- const exists = await fs.pathExists(hookPath);
73
-
74
- if (exists && !force) {
75
- // Check if it's already a CAWS hook
76
- const content = await fs.readFile(hookPath, 'utf8');
77
- if (content.includes('# CAWS Hook')) {
78
- console.log(`Skipped ${hook.description} (already configured)`);
79
- skippedCount++;
80
- continue;
81
- } else {
82
- console.log(`${hook.description} exists but not CAWS-managed`);
83
- if (!options.backup) {
84
- console.log(`Use --force to replace, or --backup to preserve original`);
85
- skippedCount++;
86
- continue;
87
- }
88
- }
89
- }
90
-
91
- // Backup existing hook if requested
92
- if (exists && options.backup) {
93
- const backupPath = `${hookPath}.backup.${Date.now()}`;
94
- await fs.copy(hookPath, backupPath);
95
- console.log(`Backed up existing ${hook.name} to ${path.basename(backupPath)}`);
96
- }
97
-
98
- // Write the hook
99
- await fs.writeFile(hookPath, hook.content);
100
- await fs.chmod(hookPath, 0o755);
101
-
102
- console.log(`Configured ${hook.description}`);
103
- addedCount++;
104
- } catch (error) {
105
- console.log(`Failed to configure ${hook.description}: ${error.message}`);
106
- }
107
- }
108
-
109
- if (addedCount > 0) {
110
- console.log(`\nGit hooks configured: ${addedCount} hooks active`);
111
- console.log('Hooks will run automatically on git operations');
112
- console.log('Use --no-verify to skip commit hooks: git commit --no-verify');
113
- console.log('Note: --no-verify is BLOCKED on git push for safety');
114
- }
115
-
116
- return { added: addedCount, skipped: skippedCount };
117
- }
118
-
119
- /**
120
- * Generate pre-commit hook content with staged file quality gates
121
- * Implements fallback chain: Node script → CLI → Python scripts → Skip gracefully
122
- */
123
- function generatePreCommitHook(options) {
124
- const { qualityGates = true, stagedOnly = true, projectDir = process.cwd() } = options;
125
-
126
- // Get language-agnostic suggestions based on runtime availability
127
- const todoSuggestion = getTodoAnalyzerSuggestion(projectDir);
128
-
129
- return `#!/bin/bash
130
- # CAWS Pre-commit Hook
131
- # Runs validation and quality checks before commits
132
- # Implements graceful fallback chain to avoid blocking commits
133
-
134
- set -e
135
-
136
- echo "Running CAWS Quality Gates${qualityGates ? ' (Crisis Response Mode)' : ''}..."
137
- echo "Analyzing ${stagedOnly ? 'staged files only' : 'all files'}..."
138
-
139
- # Check if CAWS is initialized
140
- if [ ! -d ".caws" ]; then
141
- echo "CAWS not initialized - skipping validation"
142
- exit 0
143
- fi
144
-
145
- # Check for git locks before proceeding
146
- if [ -f ".git/index.lock" ]; then
147
- LOCK_AGE=$(($(date +%s) - $(stat -f %m .git/index.lock 2>/dev/null || stat -c %Y .git/index.lock 2>/dev/null || echo 0)))
148
- LOCK_AGE_MINUTES=$((LOCK_AGE / 60))
149
-
150
- if [ $LOCK_AGE_MINUTES -gt 5 ]; then
151
- echo "Stale git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
152
- echo "This may indicate a crashed git process"
153
- echo "Remove stale lock: rm .git/index.lock"
154
- echo "Warning: Check for running git/editor processes before removing"
155
- exit 1
156
- else
157
- echo "Git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
158
- echo "Another git process may be running"
159
- echo "Wait for the other process to complete, or check for running processes"
160
- exit 1
161
- fi
162
- fi
163
-
164
- # Validate YAML syntax for all CAWS spec files
165
- echo "Validating YAML syntax for CAWS spec files..."
166
- YAML_VALIDATION_FAILED=false
167
-
168
- # Find all staged .yaml/.yml files in .caws directory
169
- STAGED_YAML_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.caws/.*\\.(yaml|yml)$' || true)
170
-
171
- if [ -n "$STAGED_YAML_FILES" ]; then
172
- # Use Node.js to validate YAML if available
173
- if command -v node >/dev/null 2>&1; then
174
- # Try to use CAWS CLI for validation
175
- if command -v caws >/dev/null 2>&1; then
176
- for file in $STAGED_YAML_FILES; do
177
- if [ -f "$file" ]; then
178
- # Use Node.js to validate YAML syntax
179
- if ! node -e "
180
- const yaml = require('js-yaml');
181
- const fs = require('fs');
182
- try {
183
- const content = fs.readFileSync('$file', 'utf8');
184
- yaml.load(content);
185
- process.exit(0);
186
- } catch (error) {
187
- console.error('Invalid YAML in $file');
188
- console.error(' Error:', error.message);
189
- if (error.mark) {
190
- console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
191
- if (error.mark.snippet) console.error(' ' + error.mark.snippet);
192
- }
193
- process.exit(1);
194
- }
195
- " 2>&1; then
196
- YAML_VALIDATION_FAILED=true
197
- fi
198
- fi
199
- done
200
- else
201
- # Fallback: use node directly with js-yaml
202
- for file in $STAGED_YAML_FILES; do
203
- if [ -f "$file" ]; then
204
- if ! node -e "
205
- const yaml = require('js-yaml');
206
- const fs = require('fs');
207
- try {
208
- const content = fs.readFileSync('$file', 'utf8');
209
- yaml.load(content);
210
- process.exit(0);
211
- } catch (error) {
212
- console.error('Invalid YAML in $file');
213
- console.error(' Error:', error.message);
214
- if (error.mark) {
215
- console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
216
- if (error.mark.snippet) console.error(' ' + error.mark.snippet);
217
- }
218
- process.exit(1);
219
- }
220
- " 2>&1; then
221
- YAML_VALIDATION_FAILED=true
222
- fi
223
- fi
224
- done
225
- fi
226
- else
227
- echo "Node.js not available - skipping YAML validation"
228
- echo "Install Node.js to enable YAML syntax validation"
229
- fi
230
- fi
231
-
232
- if [ "$YAML_VALIDATION_FAILED" = true ]; then
233
- echo "YAML syntax validation failed - commit blocked"
234
- echo "Fix YAML syntax errors above before committing"
235
- echo "Consider using 'caws specs create <id>' instead of manual creation"
236
- exit 1
237
- fi
238
-
239
- # ===== CAWS Multi-Agent Safety Guard =====
240
- # Prevents unsafe concurrent operations on shared branches
241
-
242
- if [ -d ".caws" ]; then
243
- CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
244
-
245
- # Guard 1a: Block commits on base branch when parallel worktrees are active (caws parallel)
246
- if [ -f ".caws/parallel.json" ] && command -v node >/dev/null 2>&1; then
247
- PARALLEL_BASE=$(node -e "
248
- try {
249
- var reg = JSON.parse(require('fs').readFileSync('.caws/parallel.json', 'utf8'));
250
- console.log(reg.baseBranch || '');
251
- } catch(e) { console.log(''); }
252
- " 2>/dev/null)
253
-
254
- if [ -n "$PARALLEL_BASE" ] && [ "$CURRENT_BRANCH" = "$PARALLEL_BASE" ]; then
255
- AGENT_COUNT=$(node -e "
256
- try {
257
- var reg = JSON.parse(require('fs').readFileSync('.caws/parallel.json', 'utf8'));
258
- console.log((reg.agents || []).length);
259
- } catch(e) { console.log('0'); }
260
- " 2>/dev/null)
261
-
262
- if [ "$AGENT_COUNT" -gt 0 ] 2>/dev/null; then
263
- echo "BLOCKED: Committing to '$CURRENT_BRANCH' while $AGENT_COUNT parallel agent worktree(s) are active."
264
- echo " Active agents are working in isolated worktrees."
265
- echo " Committing to the base branch risks interleaved history and merge conflicts."
266
- echo ""
267
- echo " To see parallel status: caws parallel status"
268
- echo " To merge agent work: caws parallel merge"
269
- echo " To override (unsafe): git commit --no-verify"
270
- exit 1
271
- fi
272
- fi
273
- fi
274
-
275
- # Guard 1b: Block commits on base branch when ANY active worktrees exist (caws worktree create)
276
- if [ -f ".caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
277
- ACTIVE_WORKTREES=$(node -e "
278
- try {
279
- var reg = JSON.parse(require('fs').readFileSync('.caws/worktrees.json', 'utf8'));
280
- var wts = Object.values(reg.worktrees || {});
281
- var active = wts.filter(function(w) {
282
- return (w.status === 'active' || w.status === 'fresh' || w.status === 'merged') && w.baseBranch === '$CURRENT_BRANCH';
283
- });
284
- console.log(active.length + ':' + active.map(function(w) { return w.name; }).join(','));
285
- } catch(e) { console.log('0:'); }
286
- " 2>/dev/null)
287
-
288
- WT_COUNT=$(echo "$ACTIVE_WORKTREES" | cut -d: -f1)
289
- WT_NAMES=$(echo "$ACTIVE_WORKTREES" | cut -d: -f2)
290
-
291
- if [ "$WT_COUNT" -gt 0 ] 2>/dev/null; then
292
- echo "BLOCKED: Committing to '$CURRENT_BRANCH' while $WT_COUNT active worktree(s) exist: $WT_NAMES"
293
- echo " You should be working in your worktree, not on the base branch."
294
- echo " Committing here risks interleaved history with agents in worktrees."
295
- echo ""
296
- echo " To work in your worktree: cd .caws/worktrees/<name>/"
297
- echo " To see worktrees: caws worktree list"
298
- echo " To override (unsafe): git commit --no-verify"
299
- exit 1
300
- fi
301
- fi
302
-
303
- # Guard 2: Warn if multiple active sessions exist on same branch
304
- if [ -f ".caws/sessions.json" ] && command -v node >/dev/null 2>&1; then
305
- ACTIVE_ON_BRANCH=$(node -e "
306
- try {
307
- var reg = JSON.parse(require('fs').readFileSync('.caws/sessions.json', 'utf8'));
308
- var count = Object.values(reg.sessions || {}).filter(
309
- function(s) { return s.status === 'active' && s.branch === '$CURRENT_BRANCH'; }
310
- ).length;
311
- console.log(count);
312
- } catch(e) { console.log('0'); }
313
- " 2>/dev/null)
314
-
315
- if [ "$ACTIVE_ON_BRANCH" -gt 1 ] 2>/dev/null; then
316
- echo "WARNING: $ACTIVE_ON_BRANCH active sessions detected on branch '$CURRENT_BRANCH'."
317
- echo " Multiple agents committing to the same branch risks interleaved history."
318
- echo " Consider using worktrees: caws parallel setup <plan-file>"
319
- echo ""
320
- fi
321
- fi
322
-
323
- # Guard 3: Block --amend when HEAD commit may not belong to current session
324
- # Detect --amend by inspecting the parent git process arguments
325
- AMEND_FLAG=false
326
- if command -v ps >/dev/null 2>&1; then
327
- PARENT_ARGS=$(ps -o args= -p $PPID 2>/dev/null || echo "")
328
- case "$PARENT_ARGS" in
329
- *--amend*) AMEND_FLAG=true ;;
330
- esac
331
- fi
332
-
333
- if [ "$AMEND_FLAG" = true ]; then
334
- BLOCK_AMEND=false
335
- if [ -f ".caws/parallel.json" ]; then
336
- BLOCK_AMEND=true
337
- elif [ -f ".caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
338
- HAS_ACTIVE_WT=$(node -e "
339
- try {
340
- var reg = JSON.parse(require('fs').readFileSync('.caws/worktrees.json', 'utf8'));
341
- var active = Object.values(reg.worktrees || {}).filter(function(w) { return w.status === 'active' || w.status === 'fresh' || w.status === 'merged'; });
342
- console.log(active.length > 0 ? 'yes' : 'no');
343
- } catch(e) { console.log('no'); }
344
- " 2>/dev/null)
345
- if [ "$HAS_ACTIVE_WT" = "yes" ]; then
346
- BLOCK_AMEND=true
347
- fi
348
- fi
349
-
350
- if [ "$BLOCK_AMEND" = true ]; then
351
- echo "BLOCKED: --amend is not allowed while worktrees are active."
352
- echo " Amending commits risks rewriting another agent's work."
353
- echo " Create a new commit instead."
354
- echo " To override (dangerous): git commit --amend --no-verify"
355
- exit 1
356
- fi
357
- fi
358
- fi
359
- # ===== End Multi-Agent Safety Guard =====
360
-
361
- # Run CAWS quality gates
362
- QUALITY_GATES_RAN=false
363
- QUALITY_GATES_WARNED=false
364
-
365
- # Resolve spec ID from worktree context if available
366
- SPEC_ID=""
367
- WORKTREE_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
368
- if [ -f ".caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
369
- SPEC_ID=$(node -e "
370
- try {
371
- var reg = JSON.parse(require('fs').readFileSync('.caws/worktrees.json', 'utf8'));
372
- var wt = Object.values(reg.worktrees || {}).find(function(w) {
373
- return w.branch === '$WORKTREE_BRANCH';
374
- });
375
- if (wt && wt.specId) console.log(wt.specId);
376
- } catch(e) {}
377
- " 2>/dev/null || echo "")
378
- fi
379
-
380
- GATES_ARGS="--context=commit --quiet"
381
- if [ -n "$SPEC_ID" ]; then
382
- GATES_ARGS="$GATES_ARGS --spec-id $SPEC_ID"
383
- fi
384
-
385
- if command -v caws >/dev/null 2>&1; then
386
- if caws gates run $GATES_ARGS; then
387
- echo "Quality gates passed"
388
- QUALITY_GATES_RAN=true
389
- else
390
- GATE_EXIT=$?
391
- echo "Quality gates BLOCKED the commit (exit code $GATE_EXIT)"
392
- exit 1
393
- fi
394
- else
395
- echo "CAWS CLI not available — skipping quality gates"
396
- echo "Install with: npm install -g @paths.design/caws-cli"
397
- QUALITY_GATES_RAN=true
398
- fi
399
-
400
- # Run hidden TODO analysis on staged files only (if available)
401
- if [ "$QUALITY_GATES_RAN" = true ]; then
402
- echo "Checking for hidden TODOs in staged files..."
403
-
404
- TODO_CHECK_RAN=false
405
-
406
- # Option 1: Find TODO analyzer .mjs file (if installed locally)
407
- if [ "$TODO_CHECK_RAN" = false ]; then
408
- TODO_ANALYZER=""
409
-
410
- # Try quality gates package TODO analyzer (published package)
411
- if [ -f "node_modules/@paths.design/quality-gates/todo-analyzer.mjs" ]; then
412
- TODO_ANALYZER="node_modules/@paths.design/quality-gates/todo-analyzer.mjs"
413
- # Try quality gates package TODO analyzer (monorepo/local copy)
414
- elif [ -f "node_modules/@caws/quality-gates/todo-analyzer.mjs" ]; then
415
- TODO_ANALYZER="node_modules/@caws/quality-gates/todo-analyzer.mjs"
416
- # Try monorepo structure (development)
417
- elif [ -f "packages/quality-gates/todo-analyzer.mjs" ]; then
418
- TODO_ANALYZER="packages/quality-gates/todo-analyzer.mjs"
419
- # Try local copy in scripts directory (if scaffolded)
420
- elif [ -f "scripts/todo-analyzer.mjs" ]; then
421
- TODO_ANALYZER="scripts/todo-analyzer.mjs"
422
- fi
423
-
424
- # Run TODO analyzer if found
425
- if [ -n "$TODO_ANALYZER" ] && command -v node >/dev/null 2>&1; then
426
- if node "$TODO_ANALYZER" --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
427
- echo "No critical hidden TODOs found in staged files"
428
- TODO_CHECK_RAN=true
429
- else
430
- echo "Critical hidden TODOs detected in staged files - commit blocked"
431
- echo "Fix stub implementations and placeholder code before committing"
432
- echo "See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
433
- echo ""
434
- echo "Running detailed analysis on staged files..."
435
- node "$TODO_ANALYZER" --staged-only --min-confidence 0.8
436
- exit 1
437
- fi
438
- fi
439
- fi
440
-
441
- # Option 2: Fallback to legacy Python analyzer (deprecated - will be removed)
442
- if [ "$TODO_CHECK_RAN" = false ] && command -v python3 >/dev/null 2>&1 && [ -f "scripts/v3/analysis/todo_analyzer.py" ]; then
443
- echo "Using legacy Python TODO analyzer (deprecated)"
444
- if python3 scripts/v3/analysis/todo_analyzer.py --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
445
- echo "No critical hidden TODOs found in staged files"
446
- TODO_CHECK_RAN=true
447
- else
448
- echo "Critical hidden TODOs detected in staged files - commit blocked"
449
- echo "Fix stub implementations and placeholder code before committing"
450
- echo "See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
451
- echo ""
452
- echo "Running detailed analysis on staged files..."
453
- python3 scripts/v3/analysis/todo_analyzer.py --staged-only --min-confidence 0.8
454
- exit 1
455
- fi
456
- fi
457
-
458
- # Option 3: No analyzer available - show language-aware suggestions
459
- if [ "$TODO_CHECK_RAN" = false ]; then
460
- echo "TODO analyzer not available - skipping hidden TODO check"
461
- echo "Available options for TODO analysis:"
462
- ${todoSuggestion
463
- .split('\n')
464
- .map((line) => ` echo "${line.replace(/"/g, '\\"')}"`)
465
- .join('\n')}
466
- fi
467
- fi
468
-
469
- if [ "$QUALITY_GATES_WARNED" = true ]; then
470
- echo "Proceeding with commit (some quality checks had warnings)"
471
- else
472
- echo "All quality checks passed - proceeding with commit"
473
- fi
474
- exit 0
475
- `;
476
- }
477
-
478
- /**
479
- * Generate post-commit hook content
480
- */
481
- function generatePostCommitHook() {
482
- return `#!/bin/bash
483
- # CAWS Post-commit Hook
484
- # Updates provenance tracking after successful commits
485
-
486
- # Run in background to avoid blocking git operations
487
- (
488
- # Check if CAWS is initialized
489
- if [ ! -d ".caws" ]; then
490
- exit 0
491
- fi
492
-
493
- # Skip during merge operations — caws worktree merge triggers a merge
494
- # commit, and writing to .caws/provenance/chain.json here would dirty
495
- # the tree mid-merge, blocking subsequent operations.
496
- if [ -f ".git/MERGE_HEAD" ] || [ -f "$(git rev-parse --git-dir 2>/dev/null)/MERGE_HEAD" ]; then
497
- exit 0
498
- fi
499
-
500
- # Get the current commit hash
501
- COMMIT_HASH=$(git rev-parse HEAD)
502
-
503
- # Get commit details
504
- COMMIT_MESSAGE=$(git log -1 --pretty=%B | head -1)
505
- AUTHOR_NAME=$(git log -1 --pretty=%an)
506
- AUTHOR_EMAIL=$(git log -1 --pretty=%ae)
507
-
508
- # Update provenance if CAWS CLI is available
509
- if command -v caws >/dev/null 2>&1; then
510
- echo "Updating CAWS provenance for commit \${COMMIT_HASH:0:8}..."
511
-
512
- # Run provenance update in background
513
- (
514
- caws provenance update \\
515
- --commit "$COMMIT_HASH" \\
516
- --message "$COMMIT_MESSAGE" \\
517
- --author "$AUTHOR_NAME <$AUTHOR_EMAIL>" \\
518
- --quiet
519
- ) &
520
- fi
521
- ) >/dev/null 2>&1 &
522
- `;
523
- }
524
-
525
- /**
526
- * Generate pre-push hook content
527
- * Blocks --no-verify to enforce quality gates before pushing
528
- */
529
- function generatePrePushHook() {
530
- return `#!/bin/bash
531
- # CAWS Pre-push Hook
532
- # Runs comprehensive checks before pushing
533
- # BLOCKS --no-verify for safety
534
-
535
- set -e
536
-
537
- # Block --no-verify on push operations
538
- for arg in "$@"; do
539
- if [[ "$arg" == "--no-verify" ]] || [[ "$arg" == "-n" ]]; then
540
- echo "Error: --no-verify is BLOCKED on git push"
541
- echo "==================================================="
542
- echo "Push operations must pass all quality gates."
543
- echo ""
544
- echo "To fix issues locally:"
545
- echo " 1. Run: caws validate"
546
- echo " 2. Fix reported issues"
547
- echo " 3. Commit fixes: git commit --no-verify \\(allowed\\)"
548
- echo " 4. Push again: git push \\(no --no-verify\\)"
549
- exit 1
550
- fi
551
- done
552
-
553
- echo "CAWS Pre-push Validation"
554
- echo "==================================================="
555
-
556
- # Check if CAWS is initialized
557
- if [ ! -d ".caws" ]; then
558
- echo "CAWS not initialized - skipping validation"
559
- exit 0
560
- fi
561
-
562
- # Run CAWS validation (supports multi-spec projects)
563
- CAWS_VALIDATION_FAILED=false
564
- if command -v caws >/dev/null 2>&1; then
565
- echo "Running CAWS validation..."
566
-
567
- # Multi-spec project: validate each open spec individually
568
- if [ -d ".caws/specs" ] && command -v node >/dev/null 2>&1; then
569
- OPEN_SPECS=$(node -e "
570
- var fs = require('fs'), path = require('path'), dir = '.caws/specs';
571
- try {
572
- fs.readdirSync(dir).filter(function(f) { return f.endsWith('.yaml'); }).forEach(function(f) {
573
- var content = fs.readFileSync(path.join(dir, f), 'utf8');
574
- if (content.indexOf('status: closed') === -1) {
575
- var match = content.match(/^id:\\s*(.+)$/m);
576
- if (match) console.log(match[1].trim());
577
- }
578
- });
579
- } catch(e) {}
580
- " 2>/dev/null || echo "")
581
-
582
- if [ -n "$OPEN_SPECS" ]; then
583
- echo " Multi-spec project detected, validating open specs..."
584
- while IFS= read -r spec_id; do
585
- [ -z "$spec_id" ] && continue
586
- echo " Validating spec: $spec_id"
587
- if ! caws validate --spec-id "$spec_id" --quiet 2>&1; then
588
- echo " Validation failed for spec: $spec_id"
589
- CAWS_VALIDATION_FAILED=true
590
- fi
591
- done <<< "$OPEN_SPECS"
592
- if [ "$CAWS_VALIDATION_FAILED" = false ]; then
593
- echo "CAWS validation passed (all open specs)"
594
- fi
595
- else
596
- echo " No open specs found, skipping CAWS validation"
597
- fi
598
- else
599
- # Single-spec project: validate working-spec directly
600
- VALIDATION_OUTPUT=$(caws validate --quiet 2>&1)
601
- if [ $? -ne 0 ]; then
602
- echo "$VALIDATION_OUTPUT"
603
- CAWS_VALIDATION_FAILED=true
604
- else
605
- echo "CAWS validation passed"
606
- fi
607
- fi
608
-
609
- if [ "$CAWS_VALIDATION_FAILED" = true ]; then
610
- echo ""
611
- echo "==================================================="
612
- echo "CAWS validation failed"
613
- echo "==================================================="
614
- echo "Next Steps:"
615
- echo " 1. Review errors above"
616
- echo " 2. Fix issues in .caws/working-spec.yaml or .caws/specs/"
617
- echo " 3. Run: caws validate (to verify fixes)"
618
- echo " 4. Push again: git push"
619
- echo "==================================================="
620
- exit 1
621
- fi
622
- fi
623
-
624
- # Run full pre-push checks (full test suite required before push)
625
- # Note: Pre-commit uses filtered tests for speed, but push requires full suite
626
- echo ""
627
- echo "Running full pre-push checks (full test suite required)..."
628
- echo "==================================================="
629
-
630
- QUICK_CHECKS_FAILED=false
631
-
632
- # 1. Linting (fast)
633
- if [ -f "package.json" ]; then
634
- if command -v npm >/dev/null 2>&1; then
635
- if grep -q '"lint"' package.json; then
636
- echo "Running linting..."
637
- if npm run lint >/dev/null 2>&1; then
638
- echo "Linting passed"
639
- else
640
- echo "Linting failed"
641
- echo "Fix lint errors: npm run lint"
642
- QUICK_CHECKS_FAILED=true
643
- fi
644
- fi
645
- fi
646
- fi
647
-
648
- # 2. Type checking (fast for TypeScript/JavaScript)
649
- if [ -f "package.json" ]; then
650
- if command -v npm >/dev/null 2>&1; then
651
- if grep -q '"typecheck"' package.json; then
652
- echo "Running type checking..."
653
- if npm run typecheck >/dev/null 2>&1; then
654
- echo "Type checking passed"
655
- else
656
- echo "Type checking failed"
657
- echo "Fix type errors: npm run typecheck"
658
- QUICK_CHECKS_FAILED=true
659
- fi
660
- fi
661
- fi
662
- fi
663
-
664
- # 3. Run FULL test suite (required for push) - no filtering
665
- # Pre-commit uses filtered tests for speed, but push requires full suite
666
- if [ -f "package.json" ]; then
667
- if command -v npm >/dev/null 2>&1 && grep -q '"test"' package.json; then
668
- echo "Running FULL test suite (required for push)..."
669
- echo "==================================================="
670
- if npm test 2>&1 | tee /tmp/pre-push-test-full.log; then
671
- echo "Full test suite passed"
672
- rm -f /tmp/pre-push-test-full.log
673
- else
674
- FULL_TEST_EXIT_CODE=\${PIPESTATUS[0]}
675
- echo "Full test suite failed (exit code: \${FULL_TEST_EXIT_CODE})"
676
- echo "==================================================="
677
- echo "Test output (last 100 lines):"
678
- tail -100 /tmp/pre-push-test-full.log 2>/dev/null || echo "No test output captured"
679
- echo "==================================================="
680
- echo "Fix test failures before pushing: npm test"
681
- rm -f /tmp/pre-push-test-full.log
682
- QUICK_CHECKS_FAILED=true
683
- fi
684
- fi
685
- fi
686
-
687
- # 4. Security checks (non-blocking warnings)
688
- echo ""
689
- echo "Running security checks..."
690
- if [ -f "package.json" ]; then
691
- if command -v npm >/dev/null 2>&1; then
692
- echo "Checking for vulnerabilities..."
693
- if npm audit --audit-level moderate >/dev/null 2>&1; then
694
- echo "Security audit passed"
695
- else
696
- echo "Security vulnerabilities found (non-blocking)"
697
- echo "Review with: npm audit"
698
- fi
699
- fi
700
- elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
701
- if command -v pip-audit >/dev/null 2>&1; then
702
- echo "Checking Python vulnerabilities..."
703
- pip-audit --desc 2>/dev/null || echo "Install pip-audit: pip install pip-audit"
704
- fi
705
- elif [ -f "Cargo.toml" ]; then
706
- if command -v cargo-audit >/dev/null 2>&1; then
707
- echo "Checking Rust vulnerabilities..."
708
- cargo audit 2>/dev/null || echo "Install cargo-audit: cargo install cargo-audit"
709
- fi
710
- fi
711
-
712
- # Fail if any checks failed
713
- if [ "$QUICK_CHECKS_FAILED" = true ]; then
714
- echo ""
715
- echo "==================================================="
716
- echo "Pre-push checks failed"
717
- echo "==================================================="
718
- echo "All checks (linting/type checking/full test suite) must pass before push."
719
- echo ""
720
- echo "Fix failures before pushing:"
721
- echo " - Linting: npm run lint"
722
- echo " - Type checking: npm run typecheck"
723
- echo " - Tests: npm test"
724
- echo "==================================================="
725
- exit 1
726
- fi
727
-
728
- echo ""
729
- echo "Pre-push checks completed!"
730
- echo "All quality gates passed - ready to push"
731
- `;
732
- }
733
-
734
- /**
735
- * Generate commit-msg hook content
736
- */
737
- function generateCommitMsgHook() {
738
- return `#!/bin/bash
739
- # CAWS Commit Message Hook
740
- # Validates commit message format and enforces merge(worktree): convention
741
-
742
- COMMIT_MSG_FILE=$1
743
-
744
- # Read the commit message
745
- COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
746
-
747
- # Resolve CAWS root (works from worktrees too)
748
- CAWS_ROOT="."
749
- if command -v git >/dev/null 2>&1; then
750
- _GIT_COMMON=$(git rev-parse --git-common-dir 2>/dev/null || echo ".git")
751
- if [ "$_GIT_COMMON" != ".git" ]; then
752
- _CANDIDATE=$(cd "$_GIT_COMMON/.." 2>/dev/null && pwd || echo "")
753
- if [ -n "$_CANDIDATE" ] && [ -d "$_CANDIDATE/.caws" ]; then
754
- CAWS_ROOT="$_CANDIDATE"
755
- fi
756
- fi
757
- fi
758
-
759
- # Check if CAWS is initialized
760
- if [ ! -d "$CAWS_ROOT/.caws" ]; then
761
- exit 0
762
- fi
763
-
764
- # ===== Worktree merge message guard =====
765
- CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
766
- GIT_DIR=$(git rev-parse --git-dir 2>/dev/null || echo ".git")
767
- HAS_ACTIVE_WORKTREES=false
768
-
769
- if [ -f "$CAWS_ROOT/.caws/worktrees.json" ] && command -v node >/dev/null 2>&1; then
770
- WT_COUNT=$(node -e "
771
- try {
772
- var reg = JSON.parse(require('fs').readFileSync('$CAWS_ROOT/.caws/worktrees.json', 'utf8'));
773
- var active = Object.values(reg.worktrees || {}).filter(function(w) {
774
- return (w.status === 'active' || w.status === 'fresh' || w.status === 'merged') && w.baseBranch === '$CURRENT_BRANCH';
775
- });
776
- console.log(active.length);
777
- } catch(e) { console.log('0'); }
778
- " 2>/dev/null)
779
- if [ "$WT_COUNT" -gt 0 ] 2>/dev/null; then
780
- HAS_ACTIVE_WORKTREES=true
781
- fi
782
- fi
783
-
784
- if [ "$HAS_ACTIVE_WORKTREES" = true ]; then
785
- IS_GIT_MERGE=false
786
- if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
787
- IS_GIT_MERGE=true
788
- fi
789
-
790
- if [[ "$COMMIT_MSG" =~ ^merge\\(worktree\\): ]] || [ "$IS_GIT_MERGE" = true ]; then
791
- echo "Merge commit to base branch allowed (worktrees active)"
792
- elif [[ "$COMMIT_MSG" =~ ^wip\\(checkpoint\\): ]]; then
793
- echo "Checkpoint commit allowed (prior-session cleanup)"
794
- else
795
- echo "BLOCKED: Direct commit to '$CURRENT_BRANCH' while worktrees are active."
796
- echo " Only these commit types are allowed on the base branch during parallel work:"
797
- echo ""
798
- echo " merge(worktree): <description> — merge a completed worktree branch"
799
- echo " wip(checkpoint): <description> — commit prior-session dirty files"
800
- echo " git merge --no-ff <branch> — git merge commit"
801
- echo ""
802
- echo " To override (unsafe): git commit --no-verify"
803
- exit 1
804
- fi
805
- fi
806
- # ===== End worktree merge message guard =====
807
-
808
- # Basic commit message validation
809
- if [ \${#COMMIT_MSG} -lt 10 ]; then
810
- echo "Commit message too short (minimum 10 characters)"
811
- echo " Write descriptive commit messages"
812
- exit 1
813
- fi
814
-
815
- # Check for conventional commit format (optional but encouraged)
816
- if [[ $COMMIT_MSG =~ ^(feat|fix|docs|style|refactor|test|chore|merge|perf|wip)(\\(.*\\))?: ]]; then
817
- : # valid format
818
- else
819
- if [[ ! $COMMIT_MSG =~ ^Merge\\ (branch|remote) ]]; then
820
- echo "Consider using conventional commit format:"
821
- echo " feat: / fix: / docs: / refactor: / chore: / merge(worktree):"
822
- fi
823
- fi
824
-
825
- echo "Commit message validation passed"
826
- `;
827
- }
828
-
829
- /**
830
- * Remove CAWS git hooks
831
- * @param {string} projectDir - Project directory path
832
- */
833
- async function removeGitHooks(projectDir) {
834
- console.log('Removing CAWS Git hooks...');
835
-
836
- const hooksDir = path.join(projectDir, '.git', 'hooks');
837
- const cawsHooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
838
-
839
- let removedCount = 0;
840
-
841
- for (const hookName of cawsHooks) {
842
- const hookPath = path.join(hooksDir, hookName);
843
-
844
- try {
845
- if (await fs.pathExists(hookPath)) {
846
- const content = await fs.readFile(hookPath, 'utf8');
847
- if (content.includes('# CAWS Hook') || content.includes('# CAWS Pre-commit Hook')) {
848
- await fs.remove(hookPath);
849
- console.log(`Removed ${hookName} hook`);
850
- removedCount++;
851
- } else {
852
- console.log(`Skipped ${hookName} (not CAWS-managed)`);
853
- }
854
- }
855
- } catch (error) {
856
- console.log(`Failed to remove ${hookName}: ${error.message}`);
857
- }
858
- }
859
-
860
- if (removedCount > 0) {
861
- console.log(`Removed ${removedCount} CAWS git hooks`);
862
- } else {
863
- console.log('No CAWS git hooks found');
864
- }
865
- }
866
-
867
- /**
868
- * Check git hooks status
869
- * @param {string} projectDir - Project directory path
870
- */
871
- async function checkGitHooksStatus(projectDir) {
872
- const hooksDir = path.join(projectDir, '.git', 'hooks');
873
- const cawsHooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
874
-
875
- console.log('Git Hooks Status:');
876
- console.log('===================================================');
877
-
878
- let activeCount = 0;
879
- let totalCount = 0;
880
-
881
- for (const hookName of cawsHooks) {
882
- totalCount++;
883
- const hookPath = path.join(hooksDir, hookName);
884
-
885
- try {
886
- if (await fs.pathExists(hookPath)) {
887
- const content = await fs.readFile(hookPath, 'utf8');
888
- const isExecutable = (await fs.stat(hookPath)).mode & 0o111;
889
-
890
- if (content.includes('# CAWS') && isExecutable) {
891
- console.log(`${hookName}: Active`);
892
- activeCount++;
893
- } else if (content.includes('# CAWS')) {
894
- console.log(`${hookName}: Configured but not executable`);
895
- } else {
896
- console.log(`${hookName}: Not CAWS-managed`);
897
- }
898
- } else {
899
- console.log(`${hookName}: Not installed`);
900
- }
901
- } catch (error) {
902
- console.log(`${hookName}: Error checking status`);
903
- }
904
- }
905
-
906
- console.log('');
907
- console.log(`Status: ${activeCount}/${totalCount} CAWS hooks active`);
908
-
909
- if (activeCount < totalCount) {
910
- console.log('');
911
- console.log('To install missing hooks:');
912
- console.log(' caws scaffold');
913
- console.log('');
914
- console.log('To check detailed status:');
915
- console.log(' ls -la .git/hooks/');
916
- }
917
- }
918
-
919
- module.exports = {
920
- scaffoldGitHooks,
921
- removeGitHooks,
922
- checkGitHooksStatus,
923
- // Export generator functions for testing
924
- generatePrePushHook,
925
- generatePreCommitHook,
926
- generatePostCommitHook,
927
- generateCommitMsgHook,
928
- };