@paths.design/caws-cli 10.2.0 → 11.1.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 (493) hide show
  1. package/README.md +125 -374
  2. package/dist/index.js +45 -787
  3. package/dist/init/harness-detect.d.ts +18 -0
  4. package/dist/init/harness-detect.d.ts.map +1 -0
  5. package/dist/init/harness-detect.js +90 -0
  6. package/dist/init/harness-detect.js.map +1 -0
  7. package/dist/init/hook-install.d.ts +53 -0
  8. package/dist/init/hook-install.d.ts.map +1 -0
  9. package/dist/init/hook-install.js +421 -0
  10. package/dist/init/hook-install.js.map +1 -0
  11. package/dist/init/hook-packs/manifest-claude-code.d.ts +4 -0
  12. package/dist/init/hook-packs/manifest-claude-code.d.ts.map +1 -0
  13. package/dist/init/hook-packs/manifest-claude-code.js +190 -0
  14. package/dist/init/hook-packs/manifest-claude-code.js.map +1 -0
  15. package/dist/init/hook-packs/register.d.ts +19 -0
  16. package/dist/init/hook-packs/register.d.ts.map +1 -0
  17. package/dist/init/hook-packs/register.js +37 -0
  18. package/dist/init/hook-packs/register.js.map +1 -0
  19. package/dist/init/hook-packs/types.d.ts +123 -0
  20. package/dist/init/hook-packs/types.d.ts.map +1 -0
  21. package/dist/init/hook-packs/types.js +29 -0
  22. package/dist/init/hook-packs/types.js.map +1 -0
  23. package/dist/shell/binding/resolve-binding.d.ts +4 -0
  24. package/dist/shell/binding/resolve-binding.d.ts.map +1 -0
  25. package/dist/shell/binding/resolve-binding.js +228 -0
  26. package/dist/shell/binding/resolve-binding.js.map +1 -0
  27. package/dist/shell/binding/types.d.ts +42 -0
  28. package/dist/shell/binding/types.d.ts.map +1 -0
  29. package/dist/shell/binding/types.js +21 -0
  30. package/dist/shell/binding/types.js.map +1 -0
  31. package/dist/shell/commands/claim.d.ts +14 -0
  32. package/dist/shell/commands/claim.d.ts.map +1 -0
  33. package/dist/shell/commands/claim.js +197 -0
  34. package/dist/shell/commands/claim.js.map +1 -0
  35. package/dist/shell/commands/doctor.d.ts +13 -0
  36. package/dist/shell/commands/doctor.d.ts.map +1 -0
  37. package/dist/shell/commands/doctor.js +97 -0
  38. package/dist/shell/commands/doctor.js.map +1 -0
  39. package/dist/shell/commands/evidence.d.ts +28 -0
  40. package/dist/shell/commands/evidence.d.ts.map +1 -0
  41. package/dist/shell/commands/evidence.js +166 -0
  42. package/dist/shell/commands/evidence.js.map +1 -0
  43. package/dist/shell/commands/gates.d.ts +19 -0
  44. package/dist/shell/commands/gates.d.ts.map +1 -0
  45. package/dist/shell/commands/gates.js +208 -0
  46. package/dist/shell/commands/gates.js.map +1 -0
  47. package/dist/shell/commands/init.d.ts +17 -0
  48. package/dist/shell/commands/init.d.ts.map +1 -0
  49. package/dist/shell/commands/init.js +168 -0
  50. package/dist/shell/commands/init.js.map +1 -0
  51. package/dist/shell/commands/scope.d.ts +11 -0
  52. package/dist/shell/commands/scope.d.ts.map +1 -0
  53. package/dist/shell/commands/scope.js +92 -0
  54. package/dist/shell/commands/scope.js.map +1 -0
  55. package/dist/shell/commands/specs.d.ts +41 -0
  56. package/dist/shell/commands/specs.d.ts.map +1 -0
  57. package/dist/shell/commands/specs.js +264 -0
  58. package/dist/shell/commands/specs.js.map +1 -0
  59. package/dist/shell/commands/status.d.ts +15 -0
  60. package/dist/shell/commands/status.d.ts.map +1 -0
  61. package/dist/shell/commands/status.js +106 -0
  62. package/dist/shell/commands/status.js.map +1 -0
  63. package/dist/shell/commands/waiver.d.ts +38 -0
  64. package/dist/shell/commands/waiver.d.ts.map +1 -0
  65. package/dist/shell/commands/waiver.js +240 -0
  66. package/dist/shell/commands/waiver.js.map +1 -0
  67. package/dist/shell/commands/worktree.d.ts +38 -0
  68. package/dist/shell/commands/worktree.d.ts.map +1 -0
  69. package/dist/shell/commands/worktree.js +286 -0
  70. package/dist/shell/commands/worktree.js.map +1 -0
  71. package/dist/shell/gates/disposition.d.ts +23 -0
  72. package/dist/shell/gates/disposition.d.ts.map +1 -0
  73. package/dist/shell/gates/disposition.js +117 -0
  74. package/dist/shell/gates/disposition.js.map +1 -0
  75. package/dist/shell/gates/gate-result-contract.d.ts +39 -0
  76. package/dist/shell/gates/gate-result-contract.d.ts.map +1 -0
  77. package/dist/shell/gates/gate-result-contract.js +150 -0
  78. package/dist/shell/gates/gate-result-contract.js.map +1 -0
  79. package/dist/shell/gates/local-evaluators/budget-limit.d.ts +24 -0
  80. package/dist/shell/gates/local-evaluators/budget-limit.d.ts.map +1 -0
  81. package/dist/shell/gates/local-evaluators/budget-limit.js +67 -0
  82. package/dist/shell/gates/local-evaluators/budget-limit.js.map +1 -0
  83. package/dist/shell/gates/local-evaluators/diff-helpers.d.ts +25 -0
  84. package/dist/shell/gates/local-evaluators/diff-helpers.d.ts.map +1 -0
  85. package/dist/shell/gates/local-evaluators/diff-helpers.js +74 -0
  86. package/dist/shell/gates/local-evaluators/diff-helpers.js.map +1 -0
  87. package/dist/shell/gates/local-evaluators/index.d.ts +28 -0
  88. package/dist/shell/gates/local-evaluators/index.d.ts.map +1 -0
  89. package/dist/shell/gates/local-evaluators/index.js +67 -0
  90. package/dist/shell/gates/local-evaluators/index.js.map +1 -0
  91. package/dist/shell/gates/local-evaluators/scope-boundary.d.ts +23 -0
  92. package/dist/shell/gates/local-evaluators/scope-boundary.d.ts.map +1 -0
  93. package/dist/shell/gates/local-evaluators/scope-boundary.js +67 -0
  94. package/dist/shell/gates/local-evaluators/scope-boundary.js.map +1 -0
  95. package/dist/shell/gates/local-evaluators/spec-completeness.d.ts +12 -0
  96. package/dist/shell/gates/local-evaluators/spec-completeness.d.ts.map +1 -0
  97. package/dist/shell/gates/local-evaluators/spec-completeness.js +73 -0
  98. package/dist/shell/gates/local-evaluators/spec-completeness.js.map +1 -0
  99. package/dist/shell/gates/quality-gates-adapter.d.ts +55 -0
  100. package/dist/shell/gates/quality-gates-adapter.d.ts.map +1 -0
  101. package/dist/shell/gates/quality-gates-adapter.js +161 -0
  102. package/dist/shell/gates/quality-gates-adapter.js.map +1 -0
  103. package/dist/shell/gates/waiver-filter.d.ts +58 -0
  104. package/dist/shell/gates/waiver-filter.d.ts.map +1 -0
  105. package/dist/shell/gates/waiver-filter.js +119 -0
  106. package/dist/shell/gates/waiver-filter.js.map +1 -0
  107. package/dist/shell/index.d.ts +54 -0
  108. package/dist/shell/index.d.ts.map +1 -0
  109. package/dist/shell/index.js +85 -0
  110. package/dist/shell/index.js.map +1 -0
  111. package/dist/shell/register.d.ts +11 -0
  112. package/dist/shell/register.d.ts.map +1 -0
  113. package/dist/shell/register.js +464 -0
  114. package/dist/shell/register.js.map +1 -0
  115. package/dist/shell/render/claim.d.ts +22 -0
  116. package/dist/shell/render/claim.d.ts.map +1 -0
  117. package/dist/shell/render/claim.js +75 -0
  118. package/dist/shell/render/claim.js.map +1 -0
  119. package/dist/shell/render/decision.d.ts +15 -0
  120. package/dist/shell/render/decision.d.ts.map +1 -0
  121. package/dist/shell/render/decision.js +66 -0
  122. package/dist/shell/render/decision.js.map +1 -0
  123. package/dist/shell/render/diagnostic.d.ts +19 -0
  124. package/dist/shell/render/diagnostic.d.ts.map +1 -0
  125. package/dist/shell/render/diagnostic.js +76 -0
  126. package/dist/shell/render/diagnostic.js.map +1 -0
  127. package/dist/shell/render/finding.d.ts +15 -0
  128. package/dist/shell/render/finding.d.ts.map +1 -0
  129. package/dist/shell/render/finding.js +57 -0
  130. package/dist/shell/render/finding.js.map +1 -0
  131. package/dist/shell/render/gates.d.ts +3 -0
  132. package/dist/shell/render/gates.d.ts.map +1 -0
  133. package/dist/shell/render/gates.js +56 -0
  134. package/dist/shell/render/gates.js.map +1 -0
  135. package/dist/shell/render/init-hook-pack.d.ts +16 -0
  136. package/dist/shell/render/init-hook-pack.d.ts.map +1 -0
  137. package/dist/shell/render/init-hook-pack.js +206 -0
  138. package/dist/shell/render/init-hook-pack.js.map +1 -0
  139. package/dist/shell/render/init.d.ts +11 -0
  140. package/dist/shell/render/init.d.ts.map +1 -0
  141. package/dist/shell/render/init.js +32 -0
  142. package/dist/shell/render/init.js.map +1 -0
  143. package/dist/shell/render/status.d.ts +26 -0
  144. package/dist/shell/render/status.d.ts.map +1 -0
  145. package/dist/shell/render/status.js +143 -0
  146. package/dist/shell/render/status.js.map +1 -0
  147. package/dist/shell/render/waiver.d.ts +21 -0
  148. package/dist/shell/render/waiver.d.ts.map +1 -0
  149. package/dist/shell/render/waiver.js +94 -0
  150. package/dist/shell/render/waiver.js.map +1 -0
  151. package/dist/shell/rules.d.ts +37 -0
  152. package/dist/shell/rules.d.ts.map +1 -0
  153. package/dist/shell/rules.js +51 -0
  154. package/dist/shell/rules.js.map +1 -0
  155. package/dist/shell/session/actor.d.ts +14 -0
  156. package/dist/shell/session/actor.d.ts.map +1 -0
  157. package/dist/shell/session/actor.js +34 -0
  158. package/dist/shell/session/actor.js.map +1 -0
  159. package/dist/shell/session/resolve-session.d.ts +5 -0
  160. package/dist/shell/session/resolve-session.d.ts.map +1 -0
  161. package/dist/shell/session/resolve-session.js +239 -0
  162. package/dist/shell/session/resolve-session.js.map +1 -0
  163. package/dist/shell/session/types.d.ts +56 -0
  164. package/dist/shell/session/types.d.ts.map +1 -0
  165. package/dist/shell/session/types.js +15 -0
  166. package/dist/shell/session/types.js.map +1 -0
  167. package/dist/store/agents-store.d.ts +3 -0
  168. package/dist/store/agents-store.d.ts.map +1 -0
  169. package/dist/store/agents-store.js +63 -0
  170. package/dist/store/agents-store.js.map +1 -0
  171. package/dist/store/apply-patch.d.ts +16 -0
  172. package/dist/store/apply-patch.d.ts.map +1 -0
  173. package/dist/store/apply-patch.js +191 -0
  174. package/dist/store/apply-patch.js.map +1 -0
  175. package/dist/store/atomic-write.d.ts +34 -0
  176. package/dist/store/atomic-write.d.ts.map +1 -0
  177. package/dist/store/atomic-write.js +174 -0
  178. package/dist/store/atomic-write.js.map +1 -0
  179. package/dist/store/doctor-snapshot.d.ts +20 -0
  180. package/dist/store/doctor-snapshot.d.ts.map +1 -0
  181. package/dist/store/doctor-snapshot.js +176 -0
  182. package/dist/store/doctor-snapshot.js.map +1 -0
  183. package/dist/store/events-store.d.ts +33 -0
  184. package/dist/store/events-store.d.ts.map +1 -0
  185. package/dist/store/events-store.js +297 -0
  186. package/dist/store/events-store.js.map +1 -0
  187. package/dist/store/index.d.ts +21 -0
  188. package/dist/store/index.d.ts.map +1 -0
  189. package/dist/store/index.js +47 -0
  190. package/dist/store/index.js.map +1 -0
  191. package/dist/store/init-store.d.ts +21 -0
  192. package/dist/store/init-store.d.ts.map +1 -0
  193. package/dist/store/init-store.js +295 -0
  194. package/dist/store/init-store.js.map +1 -0
  195. package/dist/store/json-store.d.ts +3 -0
  196. package/dist/store/json-store.d.ts.map +1 -0
  197. package/dist/store/json-store.js +65 -0
  198. package/dist/store/json-store.js.map +1 -0
  199. package/dist/store/lifecycle-lock.d.ts +34 -0
  200. package/dist/store/lifecycle-lock.d.ts.map +1 -0
  201. package/dist/store/lifecycle-lock.js +168 -0
  202. package/dist/store/lifecycle-lock.js.map +1 -0
  203. package/dist/store/lifecycle-transaction.d.ts +79 -0
  204. package/dist/store/lifecycle-transaction.d.ts.map +1 -0
  205. package/dist/store/lifecycle-transaction.js +319 -0
  206. package/dist/store/lifecycle-transaction.js.map +1 -0
  207. package/dist/store/policy-store.d.ts +3 -0
  208. package/dist/store/policy-store.d.ts.map +1 -0
  209. package/dist/store/policy-store.js +65 -0
  210. package/dist/store/policy-store.js.map +1 -0
  211. package/dist/store/repo-root.d.ts +46 -0
  212. package/dist/store/repo-root.d.ts.map +1 -0
  213. package/dist/store/repo-root.js +145 -0
  214. package/dist/store/repo-root.js.map +1 -0
  215. package/dist/store/rules.d.ts +69 -0
  216. package/dist/store/rules.d.ts.map +1 -0
  217. package/dist/store/rules.js +95 -0
  218. package/dist/store/rules.js.map +1 -0
  219. package/dist/store/specs-store.d.ts +3 -0
  220. package/dist/store/specs-store.d.ts.map +1 -0
  221. package/dist/store/specs-store.js +131 -0
  222. package/dist/store/specs-store.js.map +1 -0
  223. package/dist/store/specs-writer.d.ts +61 -0
  224. package/dist/store/specs-writer.d.ts.map +1 -0
  225. package/dist/store/specs-writer.js +506 -0
  226. package/dist/store/specs-writer.js.map +1 -0
  227. package/dist/store/types.d.ts +84 -0
  228. package/dist/store/types.d.ts.map +1 -0
  229. package/dist/store/types.js +14 -0
  230. package/dist/store/types.js.map +1 -0
  231. package/dist/store/waivers-store.d.ts +25 -0
  232. package/dist/store/waivers-store.d.ts.map +1 -0
  233. package/dist/store/waivers-store.js +232 -0
  234. package/dist/store/waivers-store.js.map +1 -0
  235. package/dist/store/worktrees-store.d.ts +3 -0
  236. package/dist/store/worktrees-store.d.ts.map +1 -0
  237. package/dist/store/worktrees-store.js +62 -0
  238. package/dist/store/worktrees-store.js.map +1 -0
  239. package/dist/store/worktrees-writer.d.ts +77 -0
  240. package/dist/store/worktrees-writer.d.ts.map +1 -0
  241. package/dist/store/worktrees-writer.js +674 -0
  242. package/dist/store/worktrees-writer.js.map +1 -0
  243. package/dist/store/yaml-patch.d.ts +7 -0
  244. package/dist/store/yaml-patch.d.ts.map +1 -0
  245. package/dist/store/yaml-patch.js +250 -0
  246. package/dist/store/yaml-patch.js.map +1 -0
  247. package/dist/store/yaml-store.d.ts +9 -0
  248. package/dist/store/yaml-store.d.ts.map +1 -0
  249. package/dist/store/yaml-store.js +121 -0
  250. package/dist/store/yaml-store.js.map +1 -0
  251. package/package.json +15 -13
  252. package/dist/budget-derivation.js +0 -751
  253. package/dist/cicd-optimizer.js +0 -504
  254. package/dist/commands/agents.js +0 -124
  255. package/dist/commands/archive.js +0 -500
  256. package/dist/commands/burnup.js +0 -198
  257. package/dist/commands/diagnose.js +0 -525
  258. package/dist/commands/evaluate.js +0 -314
  259. package/dist/commands/gates.js +0 -149
  260. package/dist/commands/init.js +0 -857
  261. package/dist/commands/iterate.js +0 -417
  262. package/dist/commands/mode.js +0 -269
  263. package/dist/commands/parallel.js +0 -242
  264. package/dist/commands/plan.js +0 -438
  265. package/dist/commands/provenance.js +0 -1143
  266. package/dist/commands/quality-monitor.js +0 -284
  267. package/dist/commands/scope.js +0 -264
  268. package/dist/commands/session.js +0 -312
  269. package/dist/commands/sidecar.js +0 -74
  270. package/dist/commands/specs.js +0 -1656
  271. package/dist/commands/status.js +0 -1172
  272. package/dist/commands/templates.js +0 -237
  273. package/dist/commands/tool.js +0 -136
  274. package/dist/commands/tutorial.js +0 -480
  275. package/dist/commands/validate.js +0 -357
  276. package/dist/commands/verify-acs.js +0 -443
  277. package/dist/commands/waivers.js +0 -599
  278. package/dist/commands/workflow.js +0 -243
  279. package/dist/commands/worktree.js +0 -502
  280. package/dist/config/lite-scope.js +0 -158
  281. package/dist/config/modes.js +0 -347
  282. package/dist/constants/spec-types.js +0 -65
  283. package/dist/gates/budget-limit.js +0 -121
  284. package/dist/gates/feedback.js +0 -260
  285. package/dist/gates/format.js +0 -179
  286. package/dist/gates/god-object.js +0 -117
  287. package/dist/gates/pipeline.js +0 -167
  288. package/dist/gates/scope-boundary.js +0 -112
  289. package/dist/gates/spec-completeness.js +0 -109
  290. package/dist/gates/todo-detection.js +0 -205
  291. package/dist/generators/jest-config-generator.js +0 -242
  292. package/dist/generators/working-spec.js +0 -237
  293. package/dist/minimal-cli.js +0 -88
  294. package/dist/parallel/parallel-manager.js +0 -433
  295. package/dist/policy/PolicyManager.js +0 -470
  296. package/dist/scaffold/claude-hooks.js +0 -443
  297. package/dist/scaffold/cursor-hooks.js +0 -177
  298. package/dist/scaffold/git-hooks.js +0 -928
  299. package/dist/scaffold/index.js +0 -794
  300. package/dist/session/session-manager.js +0 -653
  301. package/dist/sidecars/index.js +0 -33
  302. package/dist/sidecars/listeners.js +0 -40
  303. package/dist/sidecars/provenance-summary.js +0 -238
  304. package/dist/sidecars/quality-gaps.js +0 -258
  305. package/dist/sidecars/schema.js +0 -149
  306. package/dist/sidecars/spec-drift.js +0 -151
  307. package/dist/sidecars/waiver-draft.js +0 -176
  308. package/dist/spec/SpecFileManager.js +0 -419
  309. package/dist/templates/.caws/schemas/policy.schema.json +0 -117
  310. package/dist/templates/.caws/schemas/scope.schema.json +0 -52
  311. package/dist/templates/.caws/schemas/waivers.schema.json +0 -106
  312. package/dist/templates/.caws/schemas/working-spec.schema.json +0 -340
  313. package/dist/templates/.caws/schemas/worktrees.schema.json +0 -38
  314. package/dist/templates/.caws/templates/working-spec.template.yml +0 -80
  315. package/dist/templates/.caws/tools/README.md +0 -18
  316. package/dist/templates/.caws/tools/scope-guard.js +0 -203
  317. package/dist/templates/.caws/tools-allow.json +0 -331
  318. package/dist/templates/.caws/waivers.yml +0 -19
  319. package/dist/templates/.claude/README.md +0 -190
  320. package/dist/templates/.claude/hooks/audit.sh +0 -121
  321. package/dist/templates/.claude/hooks/block-dangerous.sh +0 -203
  322. package/dist/templates/.claude/hooks/classify_command.py +0 -592
  323. package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
  324. package/dist/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
  325. package/dist/templates/.claude/hooks/naming-check.sh +0 -100
  326. package/dist/templates/.claude/hooks/protected-paths.sh +0 -39
  327. package/dist/templates/.claude/hooks/quality-check.sh +0 -81
  328. package/dist/templates/.claude/hooks/scan-secrets.sh +0 -85
  329. package/dist/templates/.claude/hooks/scope-guard.sh +0 -381
  330. package/dist/templates/.claude/hooks/session-caws-status.sh +0 -117
  331. package/dist/templates/.claude/hooks/session-log.sh +0 -634
  332. package/dist/templates/.claude/hooks/simplification-guard.sh +0 -92
  333. package/dist/templates/.claude/hooks/stop-worktree-check.sh +0 -46
  334. package/dist/templates/.claude/hooks/test_classify_command.py +0 -370
  335. package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
  336. package/dist/templates/.claude/hooks/validate-spec.sh +0 -76
  337. package/dist/templates/.claude/hooks/worktree-guard.sh +0 -220
  338. package/dist/templates/.claude/hooks/worktree-write-guard.sh +0 -190
  339. package/dist/templates/.claude/rules/git-safety.md +0 -26
  340. package/dist/templates/.claude/rules/worktree-isolation.md +0 -101
  341. package/dist/templates/.claude/settings.json +0 -141
  342. package/dist/templates/.cursor/README.md +0 -299
  343. package/dist/templates/.cursor/hooks/audit.sh +0 -55
  344. package/dist/templates/.cursor/hooks/block-dangerous.sh +0 -84
  345. package/dist/templates/.cursor/hooks/caws-quality-check.sh +0 -52
  346. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
  347. package/dist/templates/.cursor/hooks/format.sh +0 -38
  348. package/dist/templates/.cursor/hooks/naming-check.sh +0 -64
  349. package/dist/templates/.cursor/hooks/scan-secrets.sh +0 -51
  350. package/dist/templates/.cursor/hooks/scope-guard.sh +0 -52
  351. package/dist/templates/.cursor/hooks/session-log.sh +0 -924
  352. package/dist/templates/.cursor/hooks/validate-spec.sh +0 -83
  353. package/dist/templates/.cursor/hooks.json +0 -76
  354. package/dist/templates/.cursor/rules/00-claims-verification.mdc +0 -144
  355. package/dist/templates/.cursor/rules/01-working-style.mdc +0 -50
  356. package/dist/templates/.cursor/rules/02-quality-gates.mdc +0 -368
  357. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
  358. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
  359. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
  360. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
  361. package/dist/templates/.cursor/rules/07-process-ops.mdc +0 -20
  362. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
  363. package/dist/templates/.cursor/rules/09-docstrings.mdc +0 -89
  364. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
  365. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
  366. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
  367. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
  368. package/dist/templates/.cursor/rules/README.md +0 -148
  369. package/dist/templates/.github/copilot-instructions.md +0 -82
  370. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
  371. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
  372. package/dist/templates/.junie/guidelines.md +0 -73
  373. package/dist/templates/.vscode/launch.json +0 -17
  374. package/dist/templates/.vscode/settings.json +0 -95
  375. package/dist/templates/.windsurf/rules/caws-quality-standards.md +0 -54
  376. package/dist/templates/.windsurf/workflows/caws-guided-development.md +0 -92
  377. package/dist/templates/CLAUDE.md +0 -196
  378. package/dist/templates/COMMIT_CONVENTIONS.md +0 -86
  379. package/dist/templates/OIDC_SETUP.md +0 -300
  380. package/dist/templates/agents.md +0 -171
  381. package/dist/templates/codemod/README.md +0 -1
  382. package/dist/templates/codemod/test.js +0 -93
  383. package/dist/templates/docs/README.md +0 -151
  384. package/dist/templates/scripts/new_feature.sh +0 -80
  385. package/dist/templates/scripts/quality-gates/check-god-objects.js +0 -146
  386. package/dist/templates/scripts/quality-gates/run-quality-gates.js +0 -50
  387. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +0 -1997
  388. package/dist/test-analysis.js +0 -786
  389. package/dist/tool-interface.js +0 -314
  390. package/dist/tool-loader.js +0 -303
  391. package/dist/tool-validator.js +0 -393
  392. package/dist/utils/agent-display.js +0 -210
  393. package/dist/utils/agent-session.js +0 -344
  394. package/dist/utils/async-utils.js +0 -188
  395. package/dist/utils/command-wrapper.js +0 -200
  396. package/dist/utils/event-log.js +0 -584
  397. package/dist/utils/event-renderer.js +0 -521
  398. package/dist/utils/finalization.js +0 -230
  399. package/dist/utils/git-lock.js +0 -119
  400. package/dist/utils/gitignore-updater.js +0 -158
  401. package/dist/utils/ide-detection.js +0 -133
  402. package/dist/utils/lifecycle-events.js +0 -94
  403. package/dist/utils/project-analysis.js +0 -367
  404. package/dist/utils/promise-utils.js +0 -72
  405. package/dist/utils/quality-gates-errors.js +0 -520
  406. package/dist/utils/quality-gates-utils.js +0 -387
  407. package/dist/utils/schema-validator.js +0 -50
  408. package/dist/utils/spec-resolver.js +0 -711
  409. package/dist/utils/typescript-detector.js +0 -369
  410. package/dist/utils/working-state.js +0 -530
  411. package/dist/utils/yaml-validation.js +0 -156
  412. package/dist/validation/spec-validation.js +0 -924
  413. package/dist/waivers-manager.js +0 -732
  414. package/dist/worktree/worktree-manager.js +0 -1735
  415. package/templates/.caws/schemas/policy.schema.json +0 -117
  416. package/templates/.caws/schemas/scope.schema.json +0 -52
  417. package/templates/.caws/schemas/waivers.schema.json +0 -106
  418. package/templates/.caws/schemas/working-spec.schema.json +0 -340
  419. package/templates/.caws/schemas/worktrees.schema.json +0 -38
  420. package/templates/.caws/templates/working-spec.template.yml +0 -80
  421. package/templates/.caws/tools/README.md +0 -18
  422. package/templates/.caws/tools/scope-guard.js +0 -203
  423. package/templates/.caws/tools-allow.json +0 -331
  424. package/templates/.caws/waivers.yml +0 -19
  425. package/templates/.claude/README.md +0 -190
  426. package/templates/.claude/hooks/audit.sh +0 -121
  427. package/templates/.claude/hooks/block-dangerous.sh +0 -203
  428. package/templates/.claude/hooks/classify_command.py +0 -592
  429. package/templates/.claude/hooks/doc-frontmatter-check.sh +0 -173
  430. package/templates/.claude/hooks/lite-sprawl-check.sh +0 -145
  431. package/templates/.claude/hooks/naming-check.sh +0 -100
  432. package/templates/.claude/hooks/protected-paths.sh +0 -39
  433. package/templates/.claude/hooks/quality-check.sh +0 -81
  434. package/templates/.claude/hooks/scan-secrets.sh +0 -85
  435. package/templates/.claude/hooks/scope-guard.sh +0 -381
  436. package/templates/.claude/hooks/session-caws-status.sh +0 -117
  437. package/templates/.claude/hooks/session-log.sh +0 -634
  438. package/templates/.claude/hooks/simplification-guard.sh +0 -92
  439. package/templates/.claude/hooks/stop-worktree-check.sh +0 -46
  440. package/templates/.claude/hooks/test_classify_command.py +0 -370
  441. package/templates/.claude/hooks/test_wrapper_smoke.sh +0 -96
  442. package/templates/.claude/hooks/validate-spec.sh +0 -76
  443. package/templates/.claude/hooks/worktree-guard.sh +0 -220
  444. package/templates/.claude/hooks/worktree-write-guard.sh +0 -190
  445. package/templates/.claude/rules/git-safety.md +0 -26
  446. package/templates/.claude/rules/worktree-isolation.md +0 -101
  447. package/templates/.claude/settings.json +0 -141
  448. package/templates/.cursor/README.md +0 -299
  449. package/templates/.cursor/hooks/audit.sh +0 -55
  450. package/templates/.cursor/hooks/block-dangerous.sh +0 -84
  451. package/templates/.cursor/hooks/caws-quality-check.sh +0 -52
  452. package/templates/.cursor/hooks/caws-scope-guard.sh +0 -130
  453. package/templates/.cursor/hooks/format.sh +0 -38
  454. package/templates/.cursor/hooks/naming-check.sh +0 -64
  455. package/templates/.cursor/hooks/scan-secrets.sh +0 -51
  456. package/templates/.cursor/hooks/scope-guard.sh +0 -52
  457. package/templates/.cursor/hooks/session-log.sh +0 -924
  458. package/templates/.cursor/hooks/validate-spec.sh +0 -83
  459. package/templates/.cursor/hooks.json +0 -76
  460. package/templates/.cursor/rules/00-claims-verification.mdc +0 -144
  461. package/templates/.cursor/rules/01-working-style.mdc +0 -50
  462. package/templates/.cursor/rules/02-quality-gates.mdc +0 -368
  463. package/templates/.cursor/rules/03-naming-and-refactor.mdc +0 -33
  464. package/templates/.cursor/rules/04-logging-language-style.mdc +0 -23
  465. package/templates/.cursor/rules/05-safe-defaults-guards.mdc +0 -23
  466. package/templates/.cursor/rules/06-typescript-conventions.mdc +0 -36
  467. package/templates/.cursor/rules/07-process-ops.mdc +0 -20
  468. package/templates/.cursor/rules/08-solid-and-architecture.mdc +0 -16
  469. package/templates/.cursor/rules/09-docstrings.mdc +0 -89
  470. package/templates/.cursor/rules/10-documentation-quality-standards.mdc +0 -385
  471. package/templates/.cursor/rules/11-scope-management-waivers.mdc +0 -381
  472. package/templates/.cursor/rules/12-implementation-completeness.mdc +0 -516
  473. package/templates/.cursor/rules/13-language-agnostic-standards.mdc +0 -578
  474. package/templates/.cursor/rules/README.md +0 -148
  475. package/templates/.github/copilot-instructions.md +0 -82
  476. package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +0 -5
  477. package/templates/.idea/runConfigurations/CAWS_Validate.xml +0 -5
  478. package/templates/.junie/guidelines.md +0 -73
  479. package/templates/.vscode/launch.json +0 -17
  480. package/templates/.vscode/settings.json +0 -95
  481. package/templates/.windsurf/rules/caws-quality-standards.md +0 -54
  482. package/templates/.windsurf/workflows/caws-guided-development.md +0 -92
  483. package/templates/CLAUDE.md +0 -196
  484. package/templates/COMMIT_CONVENTIONS.md +0 -86
  485. package/templates/OIDC_SETUP.md +0 -300
  486. package/templates/agents.md +0 -171
  487. package/templates/codemod/README.md +0 -1
  488. package/templates/codemod/test.js +0 -93
  489. package/templates/docs/README.md +0 -151
  490. package/templates/scripts/new_feature.sh +0 -80
  491. package/templates/scripts/quality-gates/check-god-objects.js +0 -146
  492. package/templates/scripts/quality-gates/run-quality-gates.js +0 -50
  493. package/templates/scripts/v3/analysis/todo_analyzer.py +0 -1997
@@ -1,599 +0,0 @@
1
- /**
2
- * CAWS Waivers Command
3
- *
4
- * Manage quality gate waivers for exceptional circumstances.
5
- * Waivers allow temporary exceptions to quality requirements
6
- * with proper documentation and approval.
7
- *
8
- * @author @darianrosebrook
9
- */
10
-
11
- const fs = require('fs');
12
- const path = require('path');
13
- const yaml = require('js-yaml');
14
- const chalk = require('chalk');
15
- const { initializeGlobalSetup } = require('../config');
16
- const { getAgentSessionId } = require('../utils/agent-session');
17
- const WaiversManager = require('../waivers-manager');
18
- const { commandWrapper, Output } = require('../utils/command-wrapper');
19
-
20
- const WAIVER_DIR = '.caws/waivers';
21
-
22
- /**
23
- * Valid gate identifiers recognized by the quality-gates package.
24
- * These must match the gate names used in processViolations() calls
25
- * within the check-*.mjs files.
26
- */
27
- const VALID_GATES = [
28
- 'budget_limit',
29
- 'spec_completeness',
30
- 'scope_boundary',
31
- 'god_object',
32
- 'todo_detection',
33
- '*', // wildcard — waiver applies to all gates
34
- ];
35
-
36
- /**
37
- * Waivers command handler
38
- *
39
- * @param {string} subcommand - create, list, show, revoke
40
- * @param {object} options - Command options
41
- */
42
- async function waiversCommand(subcommand = 'list', options = {}) {
43
- return commandWrapper(
44
- async () => {
45
- Output.info('Detecting CAWS setup...');
46
- const setup = initializeGlobalSetup();
47
-
48
- if (setup.hasWorkingSpec) {
49
- Output.success(`Detected ${setup.type} CAWS setup`, {
50
- capabilities: setup.capabilities,
51
- });
52
- }
53
-
54
- // Ensure waivers directory exists
55
- const waiversDir = path.join(process.cwd(), WAIVER_DIR);
56
- if (!fs.existsSync(waiversDir)) {
57
- fs.mkdirSync(waiversDir, { recursive: true });
58
- }
59
-
60
- switch (subcommand) {
61
- case 'create':
62
- return await createWaiver(options);
63
- case 'list':
64
- return await listWaivers(options);
65
- case 'show':
66
- return await showWaiver(options.id, options);
67
- case 'revoke':
68
- return await revokeWaiver(options.id, options);
69
- case 'prune':
70
- return await pruneWaivers(options);
71
- default:
72
- throw new Error(
73
- `Unknown waiver subcommand: ${subcommand}.\n` +
74
- 'Available subcommands: create, list, show, revoke, prune'
75
- );
76
- }
77
- },
78
- {
79
- commandName: `waivers ${subcommand}`,
80
- context: { subcommand, options },
81
- }
82
- );
83
- }
84
-
85
- /**
86
- * Create a new waiver
87
- */
88
- async function createWaiver(options) {
89
- // Validate all required fields upfront (report all missing at once)
90
- const required = [
91
- { field: 'title', flag: '--title', example: '"Emergency hotfix waiver"' },
92
- { field: 'reason', flag: '--reason', example: 'emergency_hotfix' },
93
- { field: 'description', flag: '--description', example: '"Critical production bug requires immediate fix"' },
94
- { field: 'gates', flag: '--gates', example: `placeholders,naming (valid: ${VALID_GATES.join(', ')})` },
95
- { field: 'expiresAt', flag: '--expires-at', example: '2025-12-31T23:59:59Z' },
96
- { field: 'approvedBy', flag: '--approved-by', example: '"@manager"' },
97
- { field: 'impactLevel', flag: '--impact-level', example: 'high' },
98
- { field: 'mitigationPlan', flag: '--mitigation-plan', example: '"Will add tests in follow-up PR within 48h"' },
99
- ];
100
- const missing = required.filter((r) => !options[r.field]);
101
-
102
- if (missing.length > 0) {
103
- console.error(chalk.red(`\nMissing ${missing.length} required option(s):\n`));
104
- missing.forEach((r) => {
105
- console.error(` ${chalk.yellow(r.flag)} e.g. ${r.example}`);
106
- });
107
- console.log(chalk.dim('\nFull example:'));
108
- console.log(' caws waivers create \\');
109
- required.forEach((r, i) => {
110
- const sep = i < required.length - 1 ? ' \\' : '';
111
- console.log(` ${r.flag}=${r.example}${sep}`);
112
- });
113
- process.exit(1);
114
- }
115
-
116
- // Parse gates
117
- const gates =
118
- typeof options.gates === 'string'
119
- ? options.gates.split(',').map((g) => g.trim())
120
- : options.gates;
121
-
122
- // Validate gate names against known identifiers
123
- const invalidGates = gates.filter((g) => !VALID_GATES.includes(g));
124
- if (invalidGates.length > 0) {
125
- console.error(chalk.red(`\nUnrecognized gate name(s): ${invalidGates.join(', ')}`));
126
- console.log(`\nValid gate names: ${VALID_GATES.join(', ')}`);
127
-
128
- // Suggest close matches
129
- invalidGates.forEach((bad) => {
130
- const suggestion = VALID_GATES.find(
131
- (v) => v !== '*' && (v.includes(bad) || bad.includes(v))
132
- );
133
- if (suggestion) {
134
- console.log(chalk.yellow(` "${bad}" -> did you mean "${suggestion}"?`));
135
- }
136
- });
137
- process.exit(1);
138
- }
139
-
140
- // Self-approval prevention: creator cannot be approver
141
- // Uses strict equality — the previous .includes() check was an asymmetric
142
- // substring match that produced false positives (blocking legitimate approvers
143
- // whose name happened to contain the session ID) while missing the reverse
144
- // case (approver is a prefix of the session ID).
145
- // When CLAUDE_SESSION_ID is unset or empty, we can't identify the creator,
146
- // so self-approval prevention is skipped ('' || null → null → falsy guard).
147
- const creatorSession = getAgentSessionId(process.cwd());
148
- if (creatorSession && options.approvedBy) {
149
- if (options.approvedBy === creatorSession) {
150
- throw new Error(
151
- 'Waiver creator cannot be the approver.\n' +
152
- 'A different agent or human must approve this waiver.\n' +
153
- `Creator session: ${creatorSession}`
154
- );
155
- }
156
- }
157
-
158
- // Generate waiver ID
159
- const waiverId = `WV-${Date.now().toString().slice(-4)}`;
160
- const timestamp = new Date().toISOString();
161
-
162
- // Create waiver object
163
- const waiver = {
164
- id: waiverId,
165
- title: options.title,
166
- reason: options.reason,
167
- description: options.description,
168
- gates: gates,
169
- created_at: timestamp,
170
- expires_at: options.expiresAt,
171
- approved_by: options.approvedBy,
172
- impact_level: options.impactLevel,
173
- mitigation_plan: options.mitigationPlan,
174
- status: 'active',
175
- created_by_session: creatorSession,
176
- };
177
-
178
- // Validate waiver against schema before persisting
179
- try {
180
- const { createValidator, getSchemaPath } = require('../utils/schema-validator');
181
- const schemaPath = getSchemaPath('waivers.schema.json', process.cwd());
182
- const validate = createValidator(schemaPath);
183
- // waivers.schema.json validates a single waiver document directly (CAWSFIX-17)
184
- const result = validate(waiver);
185
- if (!result.valid) {
186
- console.warn(chalk.yellow('Waiver has schema violations:'));
187
- result.errors.forEach((err) => {
188
- console.warn(chalk.yellow(` ${err.instancePath}: ${err.message}`));
189
- });
190
- }
191
- } catch (schemaErr) {
192
- // Non-fatal — don't block waiver creation on schema issues
193
- }
194
-
195
- // Save individual waiver file
196
- const waiverPath = path.join(process.cwd(), WAIVER_DIR, `${waiverId}.yaml`);
197
- fs.writeFileSync(waiverPath, yaml.dump(waiver, { lineWidth: -1 }));
198
-
199
- // Also add to active waivers file
200
- try {
201
- await addToActiveWaivers(waiver);
202
- } catch (error) {
203
- console.error(`Failed to add waiver to active waivers: ${error.message}`);
204
- console.error(error.stack);
205
- }
206
-
207
- console.log(chalk.green(`\nWaiver created: ${waiverId}`));
208
- console.log(` Title: ${waiver.title}`);
209
- console.log(` Reason: ${waiver.reason}`);
210
- console.log(` Gates: ${waiver.gates.join(', ')}`);
211
- console.log(` Expires: ${waiver.expires_at}`);
212
- console.log(` Approved by: ${waiver.approved_by}`);
213
- console.log(` Impact: ${waiver.impact_level}`);
214
- console.log(chalk.yellow(`\n Note: This waiver expires on ${waiver.expires_at}`));
215
- console.log(chalk.yellow(` Mitigation plan: ${waiver.mitigation_plan}\n`));
216
- }
217
-
218
- /**
219
- * List all waivers
220
- */
221
- async function listWaivers(_options) {
222
- const waiversDir = path.join(process.cwd(), WAIVER_DIR);
223
-
224
- if (!fs.existsSync(waiversDir)) {
225
- console.log(chalk.yellow('\nNo waivers found.\n'));
226
- return;
227
- }
228
-
229
- const waiverFiles = fs.readdirSync(waiversDir).filter((f) => f.endsWith('.yaml'));
230
-
231
- if (waiverFiles.length === 0) {
232
- console.log(chalk.yellow('\nNo waivers found.\n'));
233
- return;
234
- }
235
-
236
- // Load a schema validator once for all waiver files (if available)
237
- let waiverValidate = null;
238
- try {
239
- const { createValidator, getSchemaPath } = require('../utils/schema-validator');
240
- const schemaPath = getSchemaPath('waivers.schema.json', process.cwd());
241
- waiverValidate = createValidator(schemaPath);
242
- } catch {
243
- // Schema not available — skip validation
244
- }
245
-
246
- const waivers = waiverFiles.map((file) => {
247
- const content = fs.readFileSync(path.join(waiversDir, file), 'utf8');
248
- const waiver = yaml.load(content);
249
-
250
- // Validate each loaded waiver against schema
251
- if (waiverValidate && waiver && waiver.id) {
252
- const result = waiverValidate(waiver);
253
- if (!result.valid) {
254
- console.warn(chalk.yellow(`Schema warning for ${file}:`));
255
- result.errors.forEach((err) => {
256
- console.warn(chalk.yellow(` ${err.instancePath}: ${err.message}`));
257
- });
258
- }
259
- }
260
-
261
- return waiver;
262
- });
263
-
264
- // Filter by status
265
- const activeWaivers = waivers.filter(
266
- (w) => w.status === 'active' && new Date(w.expires_at) > new Date()
267
- );
268
- const expiredWaivers = waivers.filter(
269
- (w) => w.status === 'active' && new Date(w.expires_at) <= new Date()
270
- );
271
- const revokedWaivers = waivers.filter((w) => w.status === 'revoked');
272
-
273
- console.log(chalk.blue('\nCAWS Quality Gate Waivers\n'));
274
- console.log('-'.repeat(60));
275
-
276
- if (activeWaivers.length > 0) {
277
- console.log(chalk.green('\nActive Waivers:\n'));
278
- activeWaivers.forEach((waiver) => {
279
- const daysLeft = Math.ceil(
280
- (new Date(waiver.expires_at) - new Date()) / (1000 * 60 * 60 * 24)
281
- );
282
- console.log(` ${chalk.bold(waiver.id)}: ${waiver.title}`);
283
- console.log(` Reason: ${waiver.reason}`);
284
- console.log(` Gates: ${waiver.gates.join(', ')}`);
285
- console.log(` Expires: ${waiver.expires_at} (${daysLeft} days)`);
286
- console.log(` Impact: ${waiver.impact_level}`);
287
- console.log();
288
- });
289
- }
290
-
291
- if (expiredWaivers.length > 0) {
292
- console.log(chalk.yellow('\nExpired Waivers:\n'));
293
- expiredWaivers.forEach((waiver) => {
294
- console.log(` ${chalk.bold(waiver.id)}: ${waiver.title}`);
295
- console.log(` Expired: ${waiver.expires_at}`);
296
- console.log();
297
- });
298
- }
299
-
300
- if (revokedWaivers.length > 0) {
301
- console.log(chalk.red('\nRevoked Waivers:\n'));
302
- revokedWaivers.forEach((waiver) => {
303
- console.log(` ${chalk.bold(waiver.id)}: ${waiver.title}`);
304
- console.log(` Revoked: ${waiver.revoked_at}`);
305
- console.log();
306
- });
307
- }
308
-
309
- console.log(chalk.blue('Summary:\n'));
310
- console.log(` Active: ${activeWaivers.length}`);
311
- console.log(` Expired: ${expiredWaivers.length}`);
312
- console.log(` Revoked: ${revokedWaivers.length}`);
313
- console.log(` Total: ${waivers.length}\n`);
314
- }
315
-
316
- /**
317
- * Show waiver details
318
- */
319
- async function showWaiver(waiverId, _options) {
320
- if (!waiverId) {
321
- console.error(chalk.red('\nWaiver ID required'));
322
- console.log(chalk.yellow('Usage: caws waivers show WV-1234\n'));
323
- process.exit(1);
324
- }
325
-
326
- const waiverPath = path.join(process.cwd(), WAIVER_DIR, `${waiverId}.yaml`);
327
-
328
- if (!fs.existsSync(waiverPath)) {
329
- console.error(chalk.red(`\nWaiver not found: ${waiverId}\n`));
330
- process.exit(1);
331
- }
332
-
333
- const content = fs.readFileSync(waiverPath, 'utf8');
334
- const waiver = yaml.load(content);
335
-
336
- const isExpired = new Date(waiver.expires_at) <= new Date();
337
- const isActive = waiver.status === 'active' && !isExpired;
338
- const statusLabel = isActive ? chalk.green('Active') : isExpired ? chalk.yellow('Expired') : chalk.red(waiver.status);
339
-
340
- console.log(chalk.blue('\nWaiver Details\n'));
341
- console.log('-'.repeat(60));
342
- console.log(`\nStatus: ${statusLabel}`);
343
- console.log(`\n${chalk.bold(waiver.title)}`);
344
- console.log(` ID: ${waiver.id}`);
345
- console.log(` Reason: ${waiver.reason}`);
346
- console.log(` Impact Level: ${waiver.impact_level}`);
347
- console.log(`\nDescription:`);
348
- console.log(` ${waiver.description}`);
349
- console.log(`\nWaived Quality Gates:`);
350
- waiver.gates.forEach((gate) => {
351
- console.log(` - ${gate}`);
352
- });
353
- console.log(`\nMitigation Plan:`);
354
- console.log(` ${waiver.mitigation_plan}`);
355
- console.log(`\nTimeline:`);
356
- console.log(` Created: ${waiver.created_at}`);
357
- console.log(` Expires: ${waiver.expires_at}`);
358
- if (waiver.revoked_at) {
359
- console.log(` Revoked: ${waiver.revoked_at}`);
360
- }
361
- console.log(`\nApproved by: ${waiver.approved_by}\n`);
362
-
363
- if (isExpired && waiver.status === 'active') {
364
- console.log(chalk.yellow('Warning: This waiver has expired. Consider revoking it.\n'));
365
- }
366
- }
367
-
368
- /**
369
- * Revoke a waiver
370
- */
371
- async function revokeWaiver(waiverId, options) {
372
- if (!waiverId) {
373
- console.error(chalk.red('\nWaiver ID required'));
374
- console.log(chalk.yellow('Usage: caws waivers revoke WV-1234\n'));
375
- process.exit(1);
376
- }
377
-
378
- const waiverPath = path.join(process.cwd(), WAIVER_DIR, `${waiverId}.yaml`);
379
-
380
- if (!fs.existsSync(waiverPath)) {
381
- console.error(chalk.red(`\nWaiver not found: ${waiverId}\n`));
382
- process.exit(1);
383
- }
384
-
385
- const content = fs.readFileSync(waiverPath, 'utf8');
386
- const waiver = yaml.load(content);
387
-
388
- if (waiver.status === 'revoked') {
389
- console.log(chalk.yellow(`\nWaiver ${waiverId} is already revoked\n`));
390
- return;
391
- }
392
-
393
- // Update waiver status
394
- waiver.status = 'revoked';
395
- waiver.revoked_at = new Date().toISOString();
396
- waiver.revoked_by = options.revokedBy || 'system';
397
- waiver.revocation_reason = options.reason || 'Manual revocation';
398
-
399
- // Save updated waiver
400
- fs.writeFileSync(waiverPath, yaml.dump(waiver, { lineWidth: -1 }));
401
-
402
- console.log(chalk.green(`\nWaiver revoked: ${waiverId}`));
403
- console.log(` Title: ${waiver.title}`);
404
- console.log(` Revoked at: ${waiver.revoked_at}`);
405
- console.log(` Revoked by: ${waiver.revoked_by}`);
406
- console.log(` Reason: ${waiver.revocation_reason}\n`);
407
- }
408
-
409
- /**
410
- * Prune expired waivers.
411
- *
412
- * Behavior per CAWSFIX-04 AC3-A6:
413
- * --expired : dry run — list prunable waivers, no disk changes,
414
- * no events emitted. Exit 0.
415
- * --expired --apply : transition each prunable waiver from
416
- * `status: active` to `status: expired` in place
417
- * (file is updated, NOT deleted, to preserve the
418
- * audit trail) and append a `waiver_pruned` event
419
- * to the event log for each.
420
- *
421
- * A waiver is "prunable" iff `status === 'active'` AND `expires_at < now`.
422
- * Waivers already `expired` or `revoked` are untouched (A4). Non-expired
423
- * active waivers are untouched (A5). Empty registries exit 0 with a
424
- * friendly message (A6).
425
- *
426
- * @param {object} options
427
- * @param {boolean} [options.expired] — currently the only prune criterion
428
- * @param {boolean} [options.apply] — if false, dry-run (default)
429
- * @param {boolean} [options.json] — machine-readable output
430
- */
431
- async function pruneWaivers(options = {}) {
432
- if (!options.expired) {
433
- console.error(chalk.red('\n`caws waivers prune` requires --expired\n'));
434
- console.log(chalk.yellow('Usage: caws waivers prune --expired [--apply]\n'));
435
- process.exit(1);
436
- }
437
-
438
- const waiversManager = new WaiversManager();
439
-
440
- // Fast path: no waivers directory or no waiver files at all.
441
- const allWaivers = waiversManager.enumerateWaiverFiles();
442
- if (allWaivers.length === 0) {
443
- const msg = 'No active waivers to check.';
444
- if (options.json) {
445
- console.log(JSON.stringify({ status: 'ok', pruned: [], message: msg }));
446
- } else {
447
- console.log(chalk.yellow(`\n${msg}\n`));
448
- }
449
- return { pruned: [], applied: false };
450
- }
451
-
452
- const candidates = waiversManager.findExpiredWaivers();
453
-
454
- // No prunable waivers — report and return.
455
- if (candidates.length === 0) {
456
- const msg = 'No expired waivers to prune.';
457
- if (options.json) {
458
- console.log(JSON.stringify({ status: 'ok', pruned: [], message: msg }));
459
- } else {
460
- console.log(chalk.green(`\n${msg}\n`));
461
- }
462
- return { pruned: [], applied: false };
463
- }
464
-
465
- const apply = Boolean(options.apply);
466
-
467
- if (!apply) {
468
- // Dry run — report only, no disk changes, no events.
469
- if (options.json) {
470
- console.log(
471
- JSON.stringify({
472
- status: 'dry_run',
473
- applied: false,
474
- pruned: candidates.map((c) => ({ id: c.id, expires_at: c.expires_at })),
475
- })
476
- );
477
- } else {
478
- console.log(chalk.yellow(`\nDry run — ${candidates.length} waiver(s) would be pruned:\n`));
479
- candidates.forEach((c) => {
480
- console.log(` ${chalk.bold(c.id)} expired at ${c.expires_at}`);
481
- });
482
- console.log(chalk.dim('\nRe-run with --apply to transition status to expired.\n'));
483
- }
484
- return { pruned: candidates, applied: false };
485
- }
486
-
487
- // Apply path — transition each file and emit events.
488
- const { appendEvent } = require('../utils/event-log');
489
- const pruned = [];
490
- const failures = [];
491
-
492
- for (const c of candidates) {
493
- try {
494
- const updated = waiversManager.markWaiverExpired(c.path);
495
-
496
- // Emit waiver_pruned event. spec_id is optional for this event
497
- // (waivers may or may not be tied to a spec). Using the waiver's
498
- // applies_to field when available, otherwise omitting.
499
- const spec_id =
500
- updated && typeof updated.applies_to === 'string' && updated.applies_to.trim() !== ''
501
- ? updated.applies_to
502
- : undefined;
503
-
504
- await appendEvent({
505
- actor: 'cli',
506
- event: 'waiver_pruned',
507
- spec_id,
508
- data: {
509
- waiver_id: c.id,
510
- expires_at: c.expires_at,
511
- previous_status: 'active',
512
- new_status: 'expired',
513
- },
514
- });
515
-
516
- pruned.push({ id: c.id, expires_at: c.expires_at });
517
- } catch (err) {
518
- failures.push({ id: c.id, error: err.message });
519
- }
520
- }
521
-
522
- if (options.json) {
523
- console.log(
524
- JSON.stringify({
525
- status: failures.length === 0 ? 'ok' : 'partial',
526
- applied: true,
527
- pruned,
528
- failures,
529
- })
530
- );
531
- } else {
532
- console.log(
533
- chalk.green(`\nPruned ${pruned.length} expired waiver(s):\n`)
534
- );
535
- pruned.forEach((p) => {
536
- console.log(` ${chalk.bold(p.id)} (was expired at ${p.expires_at})`);
537
- });
538
- if (failures.length > 0) {
539
- console.log(chalk.red(`\n${failures.length} failure(s):\n`));
540
- failures.forEach((f) => {
541
- console.log(` ${chalk.bold(f.id)}: ${f.error}`);
542
- });
543
- }
544
- console.log();
545
- }
546
-
547
- return { pruned, applied: true, failures };
548
- }
549
-
550
- /**
551
- * Add waiver to active waivers file for quality gates integration
552
- */
553
- async function addToActiveWaivers(waiver) {
554
- try {
555
- const waiversManager = new WaiversManager();
556
-
557
- // Load existing active waivers
558
- const activeWaivers = await waiversManager.loadActiveWaivers();
559
-
560
- // Check if waiver already exists
561
- const existingIndex = activeWaivers.findIndex((w) => w.id === waiver.id);
562
-
563
- // Normalize waiver format
564
- const normalizedWaiver = {
565
- id: waiver.id,
566
- title: waiver.title || waiver.description || waiver.id,
567
- reason: waiver.reason || waiver.reason_code || 'unknown',
568
- description: waiver.description || waiver.title || waiver.id,
569
- gates: Array.isArray(waiver.gates) ? waiver.gates : [waiver.gates],
570
- expires_at: waiver.expires_at,
571
- approved_by: waiver.approved_by || waiver.risk_owner || 'unknown',
572
- created_at: waiver.created_at || waiver.approved_at || new Date().toISOString(),
573
- risk_assessment: waiver.risk_assessment || {
574
- impact_level: waiver.impact_level || 'medium',
575
- mitigation_plan: waiver.mitigation || waiver.mitigation_plan || 'Unknown mitigation',
576
- },
577
- metadata: waiver.metadata || {},
578
- };
579
-
580
- if (existingIndex >= 0) {
581
- // Update existing waiver
582
- activeWaivers[existingIndex] = normalizedWaiver;
583
- } else {
584
- // Add new waiver
585
- activeWaivers.push(normalizedWaiver);
586
- }
587
-
588
- // Save updated active waivers
589
- await waiversManager.saveActiveWaivers(activeWaivers);
590
- } catch (error) {
591
- // Enhanced error logging
592
- console.error(`Error adding waiver to active waivers: ${error.message}`);
593
- console.error(error.stack);
594
- console.warn(`Warning: Could not add waiver to active waivers file: ${error.message}`);
595
- // Don't fail the waiver creation if this fails
596
- }
597
- }
598
-
599
- module.exports = { waiversCommand };