@paths.design/caws-cli 10.2.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 (421) hide show
  1. package/README.md +125 -374
  2. package/dist/index.js +43 -785
  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/agents.js +0 -124
  183. package/dist/commands/archive.js +0 -500
  184. package/dist/commands/burnup.js +0 -198
  185. package/dist/commands/diagnose.js +0 -525
  186. package/dist/commands/evaluate.js +0 -314
  187. package/dist/commands/gates.js +0 -149
  188. package/dist/commands/init.js +0 -857
  189. package/dist/commands/iterate.js +0 -417
  190. package/dist/commands/mode.js +0 -269
  191. package/dist/commands/parallel.js +0 -242
  192. package/dist/commands/plan.js +0 -438
  193. package/dist/commands/provenance.js +0 -1143
  194. package/dist/commands/quality-monitor.js +0 -284
  195. package/dist/commands/scope.js +0 -264
  196. package/dist/commands/session.js +0 -312
  197. package/dist/commands/sidecar.js +0 -74
  198. package/dist/commands/specs.js +0 -1656
  199. package/dist/commands/status.js +0 -1172
  200. package/dist/commands/templates.js +0 -237
  201. package/dist/commands/tool.js +0 -136
  202. package/dist/commands/tutorial.js +0 -480
  203. package/dist/commands/validate.js +0 -357
  204. package/dist/commands/verify-acs.js +0 -443
  205. package/dist/commands/waivers.js +0 -599
  206. package/dist/commands/workflow.js +0 -243
  207. package/dist/commands/worktree.js +0 -502
  208. package/dist/config/lite-scope.js +0 -158
  209. package/dist/config/modes.js +0 -347
  210. package/dist/constants/spec-types.js +0 -65
  211. package/dist/gates/budget-limit.js +0 -121
  212. package/dist/gates/feedback.js +0 -260
  213. package/dist/gates/format.js +0 -179
  214. package/dist/gates/god-object.js +0 -117
  215. package/dist/gates/pipeline.js +0 -167
  216. package/dist/gates/scope-boundary.js +0 -112
  217. package/dist/gates/spec-completeness.js +0 -109
  218. package/dist/gates/todo-detection.js +0 -205
  219. package/dist/generators/jest-config-generator.js +0 -242
  220. package/dist/generators/working-spec.js +0 -237
  221. package/dist/minimal-cli.js +0 -88
  222. package/dist/parallel/parallel-manager.js +0 -433
  223. package/dist/policy/PolicyManager.js +0 -470
  224. package/dist/scaffold/claude-hooks.js +0 -443
  225. package/dist/scaffold/cursor-hooks.js +0 -177
  226. package/dist/scaffold/git-hooks.js +0 -928
  227. package/dist/scaffold/index.js +0 -794
  228. package/dist/session/session-manager.js +0 -653
  229. package/dist/sidecars/index.js +0 -33
  230. package/dist/sidecars/listeners.js +0 -40
  231. package/dist/sidecars/provenance-summary.js +0 -238
  232. package/dist/sidecars/quality-gaps.js +0 -258
  233. package/dist/sidecars/schema.js +0 -149
  234. package/dist/sidecars/spec-drift.js +0 -151
  235. package/dist/sidecars/waiver-draft.js +0 -176
  236. package/dist/spec/SpecFileManager.js +0 -419
  237. package/dist/templates/.caws/schemas/policy.schema.json +0 -117
  238. package/dist/templates/.caws/schemas/scope.schema.json +0 -52
  239. package/dist/templates/.caws/schemas/waivers.schema.json +0 -106
  240. package/dist/templates/.caws/schemas/working-spec.schema.json +0 -340
  241. package/dist/templates/.caws/schemas/worktrees.schema.json +0 -38
  242. package/dist/templates/.caws/templates/working-spec.template.yml +0 -80
  243. package/dist/templates/.caws/tools/README.md +0 -18
  244. package/dist/templates/.caws/tools/scope-guard.js +0 -203
  245. package/dist/templates/.caws/tools-allow.json +0 -331
  246. package/dist/templates/.caws/waivers.yml +0 -19
  247. package/dist/templates/.claude/README.md +0 -190
  248. package/dist/templates/.claude/hooks/audit.sh +0 -121
  249. package/dist/templates/.claude/hooks/block-dangerous.sh +0 -203
  250. package/dist/templates/.claude/hooks/classify_command.py +0 -592
  251. package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
  252. package/dist/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
  253. package/dist/templates/.claude/hooks/naming-check.sh +0 -100
  254. package/dist/templates/.claude/hooks/protected-paths.sh +0 -39
  255. package/dist/templates/.claude/hooks/quality-check.sh +0 -81
  256. package/dist/templates/.claude/hooks/scan-secrets.sh +0 -85
  257. package/dist/templates/.claude/hooks/scope-guard.sh +0 -381
  258. package/dist/templates/.claude/hooks/session-caws-status.sh +0 -117
  259. package/dist/templates/.claude/hooks/session-log.sh +0 -634
  260. package/dist/templates/.claude/hooks/simplification-guard.sh +0 -92
  261. package/dist/templates/.claude/hooks/stop-worktree-check.sh +0 -46
  262. package/dist/templates/.claude/hooks/test_classify_command.py +0 -370
  263. package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
  264. package/dist/templates/.claude/hooks/validate-spec.sh +0 -76
  265. package/dist/templates/.claude/hooks/worktree-guard.sh +0 -220
  266. package/dist/templates/.claude/hooks/worktree-write-guard.sh +0 -190
  267. package/dist/templates/.claude/rules/git-safety.md +0 -26
  268. package/dist/templates/.claude/rules/worktree-isolation.md +0 -101
  269. package/dist/templates/.claude/settings.json +0 -141
  270. package/dist/templates/.cursor/README.md +0 -299
  271. package/dist/templates/.cursor/hooks/audit.sh +0 -55
  272. package/dist/templates/.cursor/hooks/block-dangerous.sh +0 -84
  273. package/dist/templates/.cursor/hooks/caws-quality-check.sh +0 -52
  274. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
  275. package/dist/templates/.cursor/hooks/format.sh +0 -38
  276. package/dist/templates/.cursor/hooks/naming-check.sh +0 -64
  277. package/dist/templates/.cursor/hooks/scan-secrets.sh +0 -51
  278. package/dist/templates/.cursor/hooks/scope-guard.sh +0 -52
  279. package/dist/templates/.cursor/hooks/session-log.sh +0 -924
  280. package/dist/templates/.cursor/hooks/validate-spec.sh +0 -83
  281. package/dist/templates/.cursor/hooks.json +0 -76
  282. package/dist/templates/.cursor/rules/00-claims-verification.mdc +0 -144
  283. package/dist/templates/.cursor/rules/01-working-style.mdc +0 -50
  284. package/dist/templates/.cursor/rules/02-quality-gates.mdc +0 -368
  285. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
  286. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
  287. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
  288. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
  289. package/dist/templates/.cursor/rules/07-process-ops.mdc +0 -20
  290. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
  291. package/dist/templates/.cursor/rules/09-docstrings.mdc +0 -89
  292. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
  293. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
  294. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
  295. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
  296. package/dist/templates/.cursor/rules/README.md +0 -148
  297. package/dist/templates/.github/copilot-instructions.md +0 -82
  298. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
  299. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
  300. package/dist/templates/.junie/guidelines.md +0 -73
  301. package/dist/templates/.vscode/launch.json +0 -17
  302. package/dist/templates/.vscode/settings.json +0 -95
  303. package/dist/templates/.windsurf/rules/caws-quality-standards.md +0 -54
  304. package/dist/templates/.windsurf/workflows/caws-guided-development.md +0 -92
  305. package/dist/templates/CLAUDE.md +0 -196
  306. package/dist/templates/COMMIT_CONVENTIONS.md +0 -86
  307. package/dist/templates/OIDC_SETUP.md +0 -300
  308. package/dist/templates/agents.md +0 -171
  309. package/dist/templates/codemod/README.md +0 -1
  310. package/dist/templates/codemod/test.js +0 -93
  311. package/dist/templates/docs/README.md +0 -151
  312. package/dist/templates/scripts/new_feature.sh +0 -80
  313. package/dist/templates/scripts/quality-gates/check-god-objects.js +0 -146
  314. package/dist/templates/scripts/quality-gates/run-quality-gates.js +0 -50
  315. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +0 -1997
  316. package/dist/test-analysis.js +0 -786
  317. package/dist/tool-interface.js +0 -314
  318. package/dist/tool-loader.js +0 -303
  319. package/dist/tool-validator.js +0 -393
  320. package/dist/utils/agent-display.js +0 -210
  321. package/dist/utils/agent-session.js +0 -344
  322. package/dist/utils/async-utils.js +0 -188
  323. package/dist/utils/command-wrapper.js +0 -200
  324. package/dist/utils/event-log.js +0 -584
  325. package/dist/utils/event-renderer.js +0 -521
  326. package/dist/utils/finalization.js +0 -230
  327. package/dist/utils/git-lock.js +0 -119
  328. package/dist/utils/gitignore-updater.js +0 -158
  329. package/dist/utils/ide-detection.js +0 -133
  330. package/dist/utils/lifecycle-events.js +0 -94
  331. package/dist/utils/project-analysis.js +0 -367
  332. package/dist/utils/promise-utils.js +0 -72
  333. package/dist/utils/quality-gates-errors.js +0 -520
  334. package/dist/utils/quality-gates-utils.js +0 -387
  335. package/dist/utils/schema-validator.js +0 -50
  336. package/dist/utils/spec-resolver.js +0 -711
  337. package/dist/utils/typescript-detector.js +0 -369
  338. package/dist/utils/working-state.js +0 -530
  339. package/dist/utils/yaml-validation.js +0 -156
  340. package/dist/validation/spec-validation.js +0 -924
  341. package/dist/waivers-manager.js +0 -732
  342. package/dist/worktree/worktree-manager.js +0 -1735
  343. package/templates/.caws/schemas/policy.schema.json +0 -117
  344. package/templates/.caws/schemas/scope.schema.json +0 -52
  345. package/templates/.caws/schemas/waivers.schema.json +0 -106
  346. package/templates/.caws/schemas/working-spec.schema.json +0 -340
  347. package/templates/.caws/schemas/worktrees.schema.json +0 -38
  348. package/templates/.caws/templates/working-spec.template.yml +0 -80
  349. package/templates/.caws/tools/README.md +0 -18
  350. package/templates/.caws/tools/scope-guard.js +0 -203
  351. package/templates/.caws/tools-allow.json +0 -331
  352. package/templates/.caws/waivers.yml +0 -19
  353. package/templates/.claude/README.md +0 -190
  354. package/templates/.claude/hooks/audit.sh +0 -121
  355. package/templates/.claude/hooks/block-dangerous.sh +0 -203
  356. package/templates/.claude/hooks/classify_command.py +0 -592
  357. package/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
  358. package/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
  359. package/templates/.claude/hooks/naming-check.sh +0 -100
  360. package/templates/.claude/hooks/protected-paths.sh +0 -39
  361. package/templates/.claude/hooks/quality-check.sh +0 -81
  362. package/templates/.claude/hooks/scan-secrets.sh +0 -85
  363. package/templates/.claude/hooks/scope-guard.sh +0 -381
  364. package/templates/.claude/hooks/session-caws-status.sh +0 -117
  365. package/templates/.claude/hooks/session-log.sh +0 -634
  366. package/templates/.claude/hooks/simplification-guard.sh +0 -92
  367. package/templates/.claude/hooks/stop-worktree-check.sh +0 -46
  368. package/templates/.claude/hooks/test_classify_command.py +0 -370
  369. package/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
  370. package/templates/.claude/hooks/validate-spec.sh +0 -76
  371. package/templates/.claude/hooks/worktree-guard.sh +0 -220
  372. package/templates/.claude/hooks/worktree-write-guard.sh +0 -190
  373. package/templates/.claude/rules/git-safety.md +0 -26
  374. package/templates/.claude/rules/worktree-isolation.md +0 -101
  375. package/templates/.claude/settings.json +0 -141
  376. package/templates/.cursor/README.md +0 -299
  377. package/templates/.cursor/hooks/audit.sh +0 -55
  378. package/templates/.cursor/hooks/block-dangerous.sh +0 -84
  379. package/templates/.cursor/hooks/caws-quality-check.sh +0 -52
  380. package/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
  381. package/templates/.cursor/hooks/format.sh +0 -38
  382. package/templates/.cursor/hooks/naming-check.sh +0 -64
  383. package/templates/.cursor/hooks/scan-secrets.sh +0 -51
  384. package/templates/.cursor/hooks/scope-guard.sh +0 -52
  385. package/templates/.cursor/hooks/session-log.sh +0 -924
  386. package/templates/.cursor/hooks/validate-spec.sh +0 -83
  387. package/templates/.cursor/hooks.json +0 -76
  388. package/templates/.cursor/rules/00-claims-verification.mdc +0 -144
  389. package/templates/.cursor/rules/01-working-style.mdc +0 -50
  390. package/templates/.cursor/rules/02-quality-gates.mdc +0 -368
  391. package/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
  392. package/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
  393. package/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
  394. package/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
  395. package/templates/.cursor/rules/07-process-ops.mdc +0 -20
  396. package/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
  397. package/templates/.cursor/rules/09-docstrings.mdc +0 -89
  398. package/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
  399. package/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
  400. package/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
  401. package/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
  402. package/templates/.cursor/rules/README.md +0 -148
  403. package/templates/.github/copilot-instructions.md +0 -82
  404. package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
  405. package/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
  406. package/templates/.junie/guidelines.md +0 -73
  407. package/templates/.vscode/launch.json +0 -17
  408. package/templates/.vscode/settings.json +0 -95
  409. package/templates/.windsurf/rules/caws-quality-standards.md +0 -54
  410. package/templates/.windsurf/workflows/caws-guided-development.md +0 -92
  411. package/templates/CLAUDE.md +0 -196
  412. package/templates/COMMIT_CONVENTIONS.md +0 -86
  413. package/templates/OIDC_SETUP.md +0 -300
  414. package/templates/agents.md +0 -171
  415. package/templates/codemod/README.md +0 -1
  416. package/templates/codemod/test.js +0 -93
  417. package/templates/docs/README.md +0 -151
  418. package/templates/scripts/new_feature.sh +0 -80
  419. package/templates/scripts/quality-gates/check-god-objects.js +0 -146
  420. package/templates/scripts/quality-gates/run-quality-gates.js +0 -50
  421. 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
- };