@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
@@ -0,0 +1,674 @@
1
+ "use strict";
2
+ // Worktree lifecycle writer (CLI-WORKTREE-001).
3
+ //
4
+ // Composes:
5
+ // - kernel worktree functions (bindWorktree, deriveBindingState,
6
+ // assertOwnership) for legality/derivation
7
+ // - applyRegistryPatch for worktrees.json + agents.json writes
8
+ // - yaml-patch for spec.worktree field mutations
9
+ // - lifecycle-transaction for atomic multi-file writes + event append
10
+ // - specs-writer.closeSpec for auto-close on merge
11
+ //
12
+ // What this module owns:
13
+ // - createWorktree: git worktree add + registry entry + spec binding
14
+ // + worktree_created + worktree_bound events (two distinct facts)
15
+ // - bindWorktree: bidirectional binding repair (one-sided → bound)
16
+ // - destroyWorktree: safe destroy (refuses dirty, foreign, unmerged
17
+ // unless explicit non-default flag). NO --force.
18
+ // - mergeWorktree: dry-run + git merge --no-ff + auto-close via
19
+ // specs-writer + worktree_merged event + destroy
20
+ //
21
+ // What this module does NOT do:
22
+ // - Re-implement v10 worktree-manager.js behavior (repair, prune,
23
+ // reconcile, auto-register, materializeWorktreeSpec — all out).
24
+ // - Append events directly to events.jsonl.
25
+ // - Mutate worktrees.json without going through applyRegistryPatch.
26
+ // - Run rm -rf on any path.
27
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ var desc = Object.getOwnPropertyDescriptor(m, k);
30
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
31
+ desc = { enumerable: true, get: function() { return m[k]; } };
32
+ }
33
+ Object.defineProperty(o, k2, desc);
34
+ }) : (function(o, m, k, k2) {
35
+ if (k2 === undefined) k2 = k;
36
+ o[k2] = m[k];
37
+ }));
38
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
39
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
40
+ }) : function(o, v) {
41
+ o["default"] = v;
42
+ });
43
+ var __importStar = (this && this.__importStar) || (function () {
44
+ var ownKeys = function(o) {
45
+ ownKeys = Object.getOwnPropertyNames || function (o) {
46
+ var ar = [];
47
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
48
+ return ar;
49
+ };
50
+ return ownKeys(o);
51
+ };
52
+ return function (mod) {
53
+ if (mod && mod.__esModule) return mod;
54
+ var result = {};
55
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
56
+ __setModuleDefault(result, mod);
57
+ return result;
58
+ };
59
+ })();
60
+ Object.defineProperty(exports, "__esModule", { value: true });
61
+ exports.loadSpecs = void 0;
62
+ exports.createWorktree = createWorktree;
63
+ exports.bindWorktreeRepair = bindWorktreeRepair;
64
+ exports.destroyWorktree = destroyWorktree;
65
+ exports.mergeWorktree = mergeWorktree;
66
+ exports.listWorktreesPretty = listWorktreesPretty;
67
+ const child_process_1 = require("child_process");
68
+ const fs = __importStar(require("fs"));
69
+ const path = __importStar(require("path"));
70
+ const caws_kernel_1 = require("@paths.design/caws-kernel");
71
+ const apply_patch_1 = require("./apply-patch");
72
+ const specs_writer_1 = require("./specs-writer");
73
+ const specs_store_1 = require("./specs-store");
74
+ Object.defineProperty(exports, "loadSpecs", { enumerable: true, get: function () { return specs_store_1.loadSpecs; } });
75
+ const worktrees_store_1 = require("./worktrees-store");
76
+ const lifecycle_transaction_1 = require("./lifecycle-transaction");
77
+ const lifecycle_lock_1 = require("./lifecycle-lock");
78
+ const repo_root_1 = require("./repo-root");
79
+ const rules_1 = require("./rules");
80
+ const yaml_patch_1 = require("./yaml-patch");
81
+ const yaml_store_1 = require("./yaml-store");
82
+ // ─── Path helpers ────────────────────────────────────────────────────────
83
+ function specPath(cawsDir, id) {
84
+ return path.join(cawsDir, 'specs', `${id}.yaml`);
85
+ }
86
+ function worktreePathFor(cawsDir, name) {
87
+ return path.join(cawsDir, 'worktrees', name);
88
+ }
89
+ // ─── Git helpers ─────────────────────────────────────────────────────────
90
+ function runGit(args, cwd) {
91
+ try {
92
+ const stdout = (0, child_process_1.execFileSync)('git', [...args], {
93
+ cwd,
94
+ encoding: 'utf8',
95
+ stdio: ['ignore', 'pipe', 'pipe'],
96
+ });
97
+ return { ok: true, stdout: stdout.toString() };
98
+ }
99
+ catch (e) {
100
+ const cause = e;
101
+ const stderr = cause.stderr instanceof Buffer
102
+ ? cause.stderr.toString()
103
+ : typeof cause.stderr === 'string'
104
+ ? cause.stderr
105
+ : '';
106
+ const message = typeof cause.message === 'string' ? cause.message : '';
107
+ return { ok: false, reason: stderr || message || 'unknown git error' };
108
+ }
109
+ }
110
+ function repoRootFromCawsDir(cawsDir) {
111
+ return path.dirname(cawsDir);
112
+ }
113
+ function getCurrentBranch(repoRoot) {
114
+ const r = runGit(['rev-parse', '--abbrev-ref', 'HEAD'], repoRoot);
115
+ if (!r.ok)
116
+ return null;
117
+ return r.stdout.trim();
118
+ }
119
+ function isWorkingTreeClean(worktreePath) {
120
+ const r = runGit(['status', '--porcelain'], worktreePath);
121
+ if (!r.ok)
122
+ return false;
123
+ return r.stdout.trim().length === 0;
124
+ }
125
+ function isBranchMerged(repoRoot, branch, base) {
126
+ const r = runGit(['merge-base', '--is-ancestor', branch, base], repoRoot);
127
+ // Git exits 0 when branch is ancestor of base (i.e., branch is fully merged).
128
+ return r.ok;
129
+ }
130
+ // ─── ID + name validation ────────────────────────────────────────────────
131
+ const WORKTREE_NAME_REGEX = /^[a-zA-Z0-9_-]+$/;
132
+ const SPEC_ID_PATTERN = /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*-\d+[a-z]*$/;
133
+ function validateWorktreeName(name) {
134
+ if (!WORKTREE_NAME_REGEX.test(name)) {
135
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Worktree name "${name}" does not match the v11 pattern (alphanumeric, hyphen, underscore).`, { subject: name }));
136
+ }
137
+ return (0, caws_kernel_1.ok)(true);
138
+ }
139
+ function validateSpecId(id) {
140
+ if (!SPEC_ID_PATTERN.test(id)) {
141
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Spec id "${id}" does not match the v11 pattern.`, { subject: id }));
142
+ }
143
+ return (0, caws_kernel_1.ok)(true);
144
+ }
145
+ // ─── Spec lookup with strict active-only enforcement ─────────────────────
146
+ function loadSpecOrError(cawsDir, specId) {
147
+ const p = specPath(cawsDir, specId);
148
+ if (!fs.existsSync(p)) {
149
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Spec "${specId}" not found at ${p}.`, { subject: specId }));
150
+ }
151
+ const srcResult = (0, yaml_store_1.readYamlSource)(p);
152
+ if (!(0, caws_kernel_1.isOk)(srcResult))
153
+ return (0, caws_kernel_1.err)(srcResult.errors);
154
+ const parsed = (0, caws_kernel_1.parseAndValidateSpec)(srcResult.value);
155
+ if (!(0, caws_kernel_1.isOk)(parsed)) {
156
+ return (0, caws_kernel_1.err)(parsed.errors.map((d) => (0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, d.message, {
157
+ subject: d.subject ?? specId,
158
+ data: { source_rule: d.rule },
159
+ })));
160
+ }
161
+ const spec = parsed.value;
162
+ return (0, caws_kernel_1.ok)({
163
+ source: srcResult.value,
164
+ path: p,
165
+ spec: parsed.value,
166
+ lifecycleState: spec.lifecycle_state,
167
+ currentWorktree: spec.worktree,
168
+ });
169
+ }
170
+ // ─── Spec YAML mutation for worktree binding ─────────────────────────────
171
+ /** Set `worktree: <name>` on a spec via raw-byte patching. Inserts the
172
+ * field after `lifecycle_state` if absent. Returns patched bytes. */
173
+ function patchSpecSetWorktree(source, worktreeName) {
174
+ const hasField = /^worktree:/m.test(source);
175
+ if (hasField) {
176
+ return (0, yaml_patch_1.setTopLevelScalar)(source, 'worktree', worktreeName);
177
+ }
178
+ return (0, yaml_patch_1.insertTopLevelScalarAfter)(source, 'lifecycle_state', 'worktree', worktreeName);
179
+ }
180
+ /** Remove `worktree:` from a spec (sets to empty string via patch and
181
+ * trims). For destroy. */
182
+ function patchSpecClearWorktree(source) {
183
+ const hasField = /^worktree:/m.test(source);
184
+ if (!hasField)
185
+ return (0, caws_kernel_1.ok)(source);
186
+ // Replace with empty value to keep the surface minimal; future
187
+ // doctor logic may treat empty as "unset" or we may insert a
188
+ // remove operation later. For now, set to '' which the kernel
189
+ // tolerates as no binding.
190
+ return (0, yaml_patch_1.setTopLevelScalar)(source, 'worktree', "''");
191
+ }
192
+ // ─── createWorktree ──────────────────────────────────────────────────────
193
+ function createWorktree(cawsDir, input) {
194
+ // ─ Pre-flight validation (no git, no file writes) ─
195
+ const nameValidation = validateWorktreeName(input.name);
196
+ if (!nameValidation.ok)
197
+ return nameValidation;
198
+ const specValidation = validateSpecId(input.specId);
199
+ if (!specValidation.ok)
200
+ return specValidation;
201
+ const specInfo = loadSpecOrError(cawsDir, input.specId);
202
+ if (!(0, caws_kernel_1.isOk)(specInfo))
203
+ return (0, caws_kernel_1.err)(specInfo.errors);
204
+ if (specInfo.value.lifecycleState !== 'active') {
205
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Spec "${input.specId}" is in lifecycle_state "${specInfo.value.lifecycleState}"; only active specs can be bound to a new worktree.`, { subject: input.specId }));
206
+ }
207
+ if (specInfo.value.currentWorktree !== undefined &&
208
+ specInfo.value.currentWorktree.length > 0 &&
209
+ specInfo.value.currentWorktree !== input.name) {
210
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Spec "${input.specId}" is already bound to worktree "${specInfo.value.currentWorktree}".`, { subject: input.specId }));
211
+ }
212
+ // Refuse if a worktree with this name already exists in the registry.
213
+ const registry = (0, worktrees_store_1.loadWorktrees)(cawsDir);
214
+ if (!(0, caws_kernel_1.isOk)(registry))
215
+ return (0, caws_kernel_1.err)(registry.errors);
216
+ if (registry.value[input.name] !== undefined) {
217
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Worktree "${input.name}" already exists in registry.`, { subject: input.name }));
218
+ }
219
+ const repoRoot = repoRootFromCawsDir(cawsDir);
220
+ const baseBranch = input.baseBranch ?? getCurrentBranch(repoRoot);
221
+ if (baseBranch === null) {
222
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Could not determine base branch for new worktree.`, { subject: input.name }));
223
+ }
224
+ const branch = input.branch ?? input.name;
225
+ const wtPath = worktreePathFor(cawsDir, input.name);
226
+ // ─ Git operation: outside lifecycle-transaction ─
227
+ const gitResult = runGit(['worktree', 'add', '-b', branch, wtPath, baseBranch], repoRoot);
228
+ if (!gitResult.ok) {
229
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `git worktree add failed: ${gitResult.reason}`, { subject: input.name, data: { git_stderr: gitResult.reason } }));
230
+ }
231
+ // ─ Lifecycle transaction: spec.worktree patch + worktrees.json patch
232
+ // + two events. If anything fails, run git worktree remove as
233
+ // compensation. ─
234
+ const now = (input.now ?? (() => new Date()))().toISOString();
235
+ const newSpecBytes = patchSpecSetWorktree(specInfo.value.source, input.name);
236
+ if (!(0, caws_kernel_1.isOk)(newSpecBytes)) {
237
+ rollbackGitWorktree(repoRoot, wtPath);
238
+ return (0, caws_kernel_1.err)(newSpecBytes.errors);
239
+ }
240
+ // Build the worktree_created event (no spec_id — binding is a
241
+ // separate fact emitted next).
242
+ const createdEvent = {
243
+ event: 'worktree_created',
244
+ ts: now,
245
+ actor: input.actor,
246
+ data: {
247
+ name: input.name,
248
+ branch,
249
+ base_branch: baseBranch,
250
+ path: wtPath,
251
+ owner_session_id: input.session.session_id,
252
+ },
253
+ };
254
+ const boundEvent = {
255
+ event: 'worktree_bound',
256
+ ts: now,
257
+ actor: input.actor,
258
+ spec_id: input.specId,
259
+ data: {
260
+ worktree_name: input.name,
261
+ },
262
+ };
263
+ const txnOutcome = (0, lifecycle_lock_1.withLifecycleLock)(cawsDir, () => {
264
+ // Use kernel bindWorktree with the actual parsed Spec so it can
265
+ // verify lifecycle_state etc.
266
+ const bindResult = (0, caws_kernel_1.bindWorktree)(specInfo.value.spec, registry.value, input.name, input.session, { rebind: false }, new Date(now));
267
+ if (!(0, caws_kernel_1.isOk)(bindResult))
268
+ return (0, caws_kernel_1.err)(bindResult.errors);
269
+ // Apply the bind_worktree patch (writes worktrees.json with the
270
+ // kernel-modeled fields: specId, owner, last_heartbeat).
271
+ const applyResult = (0, apply_patch_1.applyRegistryPatch)(cawsDir, bindResult.value);
272
+ if (!(0, caws_kernel_1.isOk)(applyResult))
273
+ return (0, caws_kernel_1.err)(applyResult.errors);
274
+ // Augment the entry with descriptive metadata the kernel does NOT
275
+ // model (branch, baseBranch, path). These are governance metadata
276
+ // for merge/destroy decisions, not authority claims.
277
+ augmentRegistryEntry(cawsDir, input.name, { branch, baseBranch, path: wtPath });
278
+ // Then run the lifecycle transaction for spec YAML + events.
279
+ return (0, lifecycle_transaction_1.runLifecycleTransaction)({
280
+ cawsDir,
281
+ plannedWrites: [{ path: specInfo.value.path, contents: newSpecBytes.value }],
282
+ events: [createdEvent, boundEvent],
283
+ });
284
+ });
285
+ if (!txnOutcome.ok) {
286
+ // Compensation: remove the git worktree we created.
287
+ rollbackGitWorktree(repoRoot, wtPath);
288
+ // Also remove the registry entry that bind_worktree wrote.
289
+ rollbackRegistryEntry(cawsDir, input.name);
290
+ return (0, caws_kernel_1.err)(txnOutcome.errors);
291
+ }
292
+ if (txnOutcome.value.kind !== 'success') {
293
+ rollbackGitWorktree(repoRoot, wtPath);
294
+ rollbackRegistryEntry(cawsDir, input.name);
295
+ return (0, caws_kernel_1.ok)({
296
+ kind: 'partial_failure_recovered',
297
+ cause: txnOutcome.value.cause,
298
+ });
299
+ }
300
+ return (0, caws_kernel_1.ok)({
301
+ kind: 'success',
302
+ name: input.name,
303
+ action: 'created',
304
+ data: { branch, base_branch: baseBranch, path: wtPath, spec_id: input.specId },
305
+ });
306
+ }
307
+ function rollbackGitWorktree(repoRoot, wtPath) {
308
+ // Best-effort. We're already in an error path.
309
+ runGit(['worktree', 'remove', '--force', wtPath], repoRoot);
310
+ }
311
+ function rollbackRegistryEntry(cawsDir, name) {
312
+ // Direct file mutation for rollback — applyRegistryPatch has no
313
+ // "remove entry" mode. This is best-effort recovery.
314
+ const p = path.join(cawsDir, 'worktrees.json');
315
+ try {
316
+ const raw = fs.readFileSync(p, 'utf8');
317
+ const obj = JSON.parse(raw);
318
+ if (obj && typeof obj === 'object' && obj[name] !== undefined) {
319
+ delete obj[name];
320
+ fs.writeFileSync(p, JSON.stringify(obj, null, 2));
321
+ }
322
+ }
323
+ catch {
324
+ /* best-effort */
325
+ }
326
+ }
327
+ /** Augment a registry entry with descriptive metadata the kernel
328
+ * doesn't model (branch, baseBranch, path). These fields are used by
329
+ * merge/destroy for prerequisite checks but are not authority claims.
330
+ * applyRegistryPatch only touches the kernel-modeled fields, so we
331
+ * layer in the rest via a direct merge. Best-effort — read failure
332
+ * is logged but doesn't fail the caller. */
333
+ function augmentRegistryEntry(cawsDir, name, extra) {
334
+ const p = path.join(cawsDir, 'worktrees.json');
335
+ try {
336
+ const raw = fs.readFileSync(p, 'utf8');
337
+ const obj = JSON.parse(raw);
338
+ if (!obj || typeof obj !== 'object')
339
+ return;
340
+ const entry = obj[name];
341
+ if (!entry || typeof entry !== 'object')
342
+ return;
343
+ obj[name] = { ...entry, ...extra };
344
+ fs.writeFileSync(p, JSON.stringify(obj, null, 2));
345
+ }
346
+ catch {
347
+ /* best-effort */
348
+ }
349
+ }
350
+ // ─── bindWorktree (repair) ───────────────────────────────────────────────
351
+ function bindWorktreeRepair(cawsDir, input) {
352
+ const nameValidation = validateWorktreeName(input.name);
353
+ if (!nameValidation.ok)
354
+ return nameValidation;
355
+ const specValidation = validateSpecId(input.specId);
356
+ if (!specValidation.ok)
357
+ return specValidation;
358
+ const specInfo = loadSpecOrError(cawsDir, input.specId);
359
+ if (!(0, caws_kernel_1.isOk)(specInfo))
360
+ return (0, caws_kernel_1.err)(specInfo.errors);
361
+ const registry = (0, worktrees_store_1.loadWorktrees)(cawsDir);
362
+ if (!(0, caws_kernel_1.isOk)(registry))
363
+ return (0, caws_kernel_1.err)(registry.errors);
364
+ const existingEntry = registry.value[input.name];
365
+ if (existingEntry === undefined) {
366
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Worktree "${input.name}" has no registry entry. Use caws worktree create to create a new worktree.`, { subject: input.name }));
367
+ }
368
+ // Patch the spec YAML to set worktree: <name>.
369
+ const newSpecBytes = patchSpecSetWorktree(specInfo.value.source, input.name);
370
+ if (!(0, caws_kernel_1.isOk)(newSpecBytes))
371
+ return (0, caws_kernel_1.err)(newSpecBytes.errors);
372
+ // Apply registry patch to set specId on the entry. We use the
373
+ // kernel bindWorktree to get the right patch shape.
374
+ const now = (input.now ?? (() => new Date()))().toISOString();
375
+ const txnOutcome = (0, lifecycle_lock_1.withLifecycleLock)(cawsDir, () => {
376
+ const bindResult = (0, caws_kernel_1.bindWorktree)(specInfo.value.spec, registry.value, input.name, input.session, { rebind: existingEntry.specId !== undefined && existingEntry.specId !== input.specId }, new Date(now));
377
+ if (!(0, caws_kernel_1.isOk)(bindResult))
378
+ return (0, caws_kernel_1.err)(bindResult.errors);
379
+ const applyResult = (0, apply_patch_1.applyRegistryPatch)(cawsDir, bindResult.value);
380
+ if (!(0, caws_kernel_1.isOk)(applyResult))
381
+ return (0, caws_kernel_1.err)(applyResult.errors);
382
+ const eventData = { worktree_name: input.name };
383
+ if (existingEntry.specId !== undefined &&
384
+ existingEntry.specId !== input.specId) {
385
+ eventData.previously_bound_to = existingEntry.specId;
386
+ }
387
+ const event = {
388
+ event: 'worktree_bound',
389
+ ts: now,
390
+ actor: input.actor,
391
+ spec_id: input.specId,
392
+ data: eventData,
393
+ };
394
+ return (0, lifecycle_transaction_1.runLifecycleTransaction)({
395
+ cawsDir,
396
+ plannedWrites: [{ path: specInfo.value.path, contents: newSpecBytes.value }],
397
+ events: [event],
398
+ });
399
+ });
400
+ if (!txnOutcome.ok)
401
+ return (0, caws_kernel_1.err)(txnOutcome.errors);
402
+ if (txnOutcome.value.kind !== 'success') {
403
+ return (0, caws_kernel_1.ok)({ kind: 'partial_failure_recovered', cause: txnOutcome.value.cause });
404
+ }
405
+ return (0, caws_kernel_1.ok)({ kind: 'success', name: input.name, action: 'bound' });
406
+ }
407
+ // ─── destroyWorktree ─────────────────────────────────────────────────────
408
+ function destroyWorktree(cawsDir, input) {
409
+ const nameValidation = validateWorktreeName(input.name);
410
+ if (!nameValidation.ok)
411
+ return nameValidation;
412
+ const registry = (0, worktrees_store_1.loadWorktrees)(cawsDir);
413
+ if (!(0, caws_kernel_1.isOk)(registry))
414
+ return (0, caws_kernel_1.err)(registry.errors);
415
+ const entry = registry.value[input.name];
416
+ if (entry === undefined) {
417
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Worktree "${input.name}" not found in registry.`, { subject: input.name }));
418
+ }
419
+ // Ownership check: refuse foreign session unless takeover already
420
+ // happened in a separate step (caws claim --takeover writes a
421
+ // prior_owners audit; ownership then matches and we proceed).
422
+ if (entry.owner !== undefined &&
423
+ entry.owner.session_id !== input.session.session_id) {
424
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Worktree "${input.name}" is owned by a different session (${entry.owner.session_id}). Run 'caws claim ${input.name} --takeover' first if you need to take ownership.`, { subject: input.name }));
425
+ }
426
+ // Dirty-tree check.
427
+ const wtPath = entry.path ?? worktreePathFor(cawsDir, input.name);
428
+ if (fs.existsSync(wtPath) && !isWorkingTreeClean(wtPath)) {
429
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Worktree "${input.name}" has uncommitted changes. Commit or stash before destroying.`, { subject: input.name }));
430
+ }
431
+ // Unmerged-branch check (skipped when --abandon-unmerged is passed).
432
+ const repoRoot = repoRootFromCawsDir(cawsDir);
433
+ if (entry.branch !== undefined &&
434
+ entry.baseBranch !== undefined &&
435
+ input.abandonUnmerged !== true &&
436
+ !isBranchMerged(repoRoot, entry.branch, entry.baseBranch)) {
437
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Branch "${entry.branch}" is not merged into "${entry.baseBranch}". Pass --abandon-unmerged to destroy anyway.`, { subject: input.name }));
438
+ }
439
+ // Run git worktree remove. Never rm -rf.
440
+ let removedGitWorktree = false;
441
+ if (fs.existsSync(wtPath)) {
442
+ const removeResult = runGit(['worktree', 'remove', wtPath], repoRoot);
443
+ if (!removeResult.ok) {
444
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_WRITE_FAILED, `git worktree remove failed: ${removeResult.reason}`, { subject: input.name }));
445
+ }
446
+ removedGitWorktree = true;
447
+ }
448
+ // Clear spec.worktree field if a spec was bound.
449
+ const now = (input.now ?? (() => new Date()))().toISOString();
450
+ const plannedWrites = [];
451
+ if (entry.specId !== undefined) {
452
+ const specInfo = loadSpecOrError(cawsDir, entry.specId);
453
+ if ((0, caws_kernel_1.isOk)(specInfo)) {
454
+ const newSpecBytes = patchSpecClearWorktree(specInfo.value.source);
455
+ if ((0, caws_kernel_1.isOk)(newSpecBytes) && newSpecBytes.value !== specInfo.value.source) {
456
+ plannedWrites.push({
457
+ path: specInfo.value.path,
458
+ contents: newSpecBytes.value,
459
+ });
460
+ }
461
+ }
462
+ }
463
+ const eventData = {
464
+ worktree_name: input.name,
465
+ branch: entry.branch ?? 'unknown',
466
+ path: wtPath,
467
+ removed_git_worktree: removedGitWorktree,
468
+ };
469
+ if (entry.specId !== undefined)
470
+ eventData.spec_id = entry.specId;
471
+ if (entry.owner !== undefined)
472
+ eventData.owner_session_id = entry.owner.session_id;
473
+ const event = {
474
+ event: 'worktree_destroyed',
475
+ ts: now,
476
+ actor: input.actor,
477
+ data: eventData,
478
+ };
479
+ const txnOutcome = (0, lifecycle_lock_1.withLifecycleLock)(cawsDir, () => {
480
+ // Remove the registry entry first.
481
+ rollbackRegistryEntry(cawsDir, input.name); // misnomer — also used here as the canonical remover
482
+ return (0, lifecycle_transaction_1.runLifecycleTransaction)({
483
+ cawsDir,
484
+ plannedWrites,
485
+ events: [event],
486
+ });
487
+ });
488
+ if (!txnOutcome.ok)
489
+ return (0, caws_kernel_1.err)(txnOutcome.errors);
490
+ if (txnOutcome.value.kind !== 'success') {
491
+ return (0, caws_kernel_1.ok)({ kind: 'partial_failure_recovered', cause: txnOutcome.value.cause });
492
+ }
493
+ return (0, caws_kernel_1.ok)({
494
+ kind: 'success',
495
+ name: input.name,
496
+ action: 'destroyed',
497
+ data: { removed_git_worktree: removedGitWorktree },
498
+ });
499
+ }
500
+ // ─── mergeWorktree ───────────────────────────────────────────────────────
501
+ function mergeWorktree(cawsDir, input) {
502
+ const nameValidation = validateWorktreeName(input.name);
503
+ if (!nameValidation.ok)
504
+ return nameValidation;
505
+ const registry = (0, worktrees_store_1.loadWorktrees)(cawsDir);
506
+ if (!(0, caws_kernel_1.isOk)(registry))
507
+ return (0, caws_kernel_1.err)(registry.errors);
508
+ const entry = registry.value[input.name];
509
+ if (entry === undefined) {
510
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `Worktree "${input.name}" not found in registry.`, { subject: input.name }));
511
+ }
512
+ // Validate prerequisites.
513
+ const findings = [];
514
+ if (entry.owner !== undefined && entry.owner.session_id !== input.session.session_id) {
515
+ findings.push(`worktree is owned by a different session (${entry.owner.session_id})`);
516
+ }
517
+ const wtPath = entry.path ?? worktreePathFor(cawsDir, input.name);
518
+ if (fs.existsSync(wtPath) && !isWorkingTreeClean(wtPath)) {
519
+ findings.push('worktree has uncommitted changes');
520
+ }
521
+ if (entry.specId === undefined) {
522
+ findings.push('no spec_id binding on this worktree');
523
+ }
524
+ if (entry.branch === undefined || entry.baseBranch === undefined) {
525
+ findings.push('missing branch or base_branch on registry entry');
526
+ }
527
+ // Dry-run: report and return without mutation.
528
+ if (input.dryRun === true) {
529
+ return (0, caws_kernel_1.ok)({
530
+ kind: 'dry_run',
531
+ name: input.name,
532
+ canProceed: findings.length === 0,
533
+ findings,
534
+ });
535
+ }
536
+ if (findings.length > 0) {
537
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PLAN_REJECTED, `caws worktree merge ${input.name}: prerequisites unmet (${findings.join('; ')}).`, { subject: input.name, data: { findings } }));
538
+ }
539
+ // Perform the merge: git checkout base + git merge --no-ff.
540
+ const repoRoot = repoRootFromCawsDir(cawsDir);
541
+ const baseBranch = entry.baseBranch;
542
+ const branch = entry.branch;
543
+ const specId = entry.specId;
544
+ const checkoutResult = runGit(['checkout', baseBranch], repoRoot);
545
+ if (!checkoutResult.ok) {
546
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_WRITE_FAILED, `git checkout ${baseBranch} failed: ${checkoutResult.reason}`, { subject: input.name }));
547
+ }
548
+ const message = input.message ?? `merge(worktree): ${input.name}`;
549
+ const mergeResult = runGit(['merge', '--no-ff', '-m', message, branch], repoRoot);
550
+ if (!mergeResult.ok) {
551
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_WRITE_FAILED, `git merge --no-ff ${branch} failed: ${mergeResult.reason}`, { subject: input.name }));
552
+ }
553
+ // Obtain the merge commit SHA.
554
+ const shaResult = runGit(['rev-parse', 'HEAD'], repoRoot);
555
+ if (!shaResult.ok) {
556
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_WRITE_FAILED, `git rev-parse HEAD failed: ${shaResult.reason}`, { subject: input.name }));
557
+ }
558
+ const mergeCommit = shaResult.stdout.trim();
559
+ if (!/^[0-9a-f]{7,40}$/.test(mergeCommit)) {
560
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_WRITE_FAILED, `Unexpected merge commit shape from git: ${mergeCommit}`, { subject: input.name }));
561
+ }
562
+ // Auto-close the bound spec through the canonical specs-writer
563
+ // path. This appends spec_closed. We then append worktree_merged
564
+ // with auto_closed_spec: true.
565
+ //
566
+ // `mergeNow` is captured once and reused for every sub-operation
567
+ // (close, worktree_merged append, destroy). Composed merge is one
568
+ // governance moment; emitted events must share that baseline so
569
+ // ts order matches seq order in the chain. Without this, sub-calls
570
+ // re-read the wall clock at append time and can produce timestamps
571
+ // that disagree with seq (seq remains the causal authority, but
572
+ // human-readable timestamps should not contradict it).
573
+ const mergeNow = new Date((input.now ?? (() => new Date()))().getTime());
574
+ const now = mergeNow.toISOString();
575
+ const sharedNowFactory = () => mergeNow;
576
+ const closeResult = (0, specs_writer_1.closeSpec)(cawsDir, {
577
+ id: specId,
578
+ resolution: 'completed',
579
+ reason: `Auto-closed by caws worktree merge ${input.name} at ${mergeCommit}`,
580
+ mergeCommit,
581
+ actor: input.actor,
582
+ now: sharedNowFactory,
583
+ });
584
+ if (!(0, caws_kernel_1.isOk)(closeResult)) {
585
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PARTIAL_FAILURE_UNRECOVERED, `Merge succeeded (commit ${mergeCommit}) but spec close failed. The bound spec remains active.`, {
586
+ subject: input.name,
587
+ data: {
588
+ merge_commit: mergeCommit,
589
+ spec_id: specId,
590
+ close_errors: closeResult.errors.map((d) => d.message),
591
+ recovery_instruction: `Manually run: caws specs close ${specId} --resolution completed --merge-commit ${mergeCommit}`,
592
+ },
593
+ }));
594
+ }
595
+ // Append worktree_merged AFTER spec_closed so the chain reflects
596
+ // the actual order of state transitions.
597
+ const mergedEvent = {
598
+ event: 'worktree_merged',
599
+ ts: now,
600
+ actor: input.actor,
601
+ spec_id: specId,
602
+ data: {
603
+ worktree_name: input.name,
604
+ merge_commit: mergeCommit,
605
+ base_branch: baseBranch,
606
+ auto_closed_spec: true,
607
+ },
608
+ };
609
+ // The worktree_merged event is appended via runLifecycleTransaction
610
+ // even though we have no file writes for this step; the substrate's
611
+ // append path is the only sanctioned writer for events.jsonl.
612
+ const mergedTxn = (0, lifecycle_lock_1.withLifecycleLock)(cawsDir, () => (0, lifecycle_transaction_1.runLifecycleTransaction)({
613
+ cawsDir,
614
+ plannedWrites: [],
615
+ events: [mergedEvent],
616
+ }));
617
+ if (!mergedTxn.ok) {
618
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PARTIAL_FAILURE_UNRECOVERED, `Merge succeeded and spec_closed event appended, but worktree_merged event append failed. The worktree was not destroyed.`, {
619
+ subject: input.name,
620
+ data: {
621
+ merge_commit: mergeCommit,
622
+ recovery_instruction: `Manually destroy the worktree: caws worktree destroy ${input.name}`,
623
+ },
624
+ }));
625
+ }
626
+ // Destroy the worktree last. Reuse the same merge-baseline clock
627
+ // so worktree_destroyed.ts matches the rest of the composed merge.
628
+ const destroyResult = destroyWorktree(cawsDir, {
629
+ name: input.name,
630
+ session: input.session,
631
+ actor: input.actor,
632
+ now: sharedNowFactory,
633
+ });
634
+ if (!(0, caws_kernel_1.isOk)(destroyResult)) {
635
+ // The merge + close + merged event all succeeded. The destroy
636
+ // failed. Surface as partial-failure with a manual recovery hint.
637
+ return (0, caws_kernel_1.err)((0, repo_root_1.storeDiagnostic)(rules_1.STORE_RULES.LIFECYCLE_PARTIAL_FAILURE_UNRECOVERED, `Merge succeeded but post-merge worktree destroy failed. Run caws worktree destroy ${input.name} manually.`, {
638
+ subject: input.name,
639
+ data: {
640
+ merge_commit: mergeCommit,
641
+ destroy_errors: destroyResult.errors.map((d) => d.message),
642
+ },
643
+ }));
644
+ }
645
+ return (0, caws_kernel_1.ok)({
646
+ kind: 'success',
647
+ name: input.name,
648
+ action: 'merged',
649
+ data: { merge_commit: mergeCommit, spec_id: specId, auto_closed_spec: true },
650
+ });
651
+ }
652
+ function listWorktreesPretty(cawsDir) {
653
+ const registry = (0, worktrees_store_1.loadWorktrees)(cawsDir);
654
+ if (!(0, caws_kernel_1.isOk)(registry))
655
+ return (0, caws_kernel_1.err)(registry.errors);
656
+ const entries = [];
657
+ for (const [name, record] of Object.entries(registry.value)) {
658
+ if (typeof record !== 'object' || record === null)
659
+ continue;
660
+ entries.push({
661
+ name,
662
+ path: record.path ?? worktreePathFor(cawsDir, name),
663
+ branch: record.branch ?? 'unknown',
664
+ baseBranch: record.baseBranch ?? 'unknown',
665
+ specId: record.specId ?? null,
666
+ owner: record.owner ?? null,
667
+ status: 'active',
668
+ });
669
+ }
670
+ // Sort for deterministic output.
671
+ entries.sort((a, b) => a.name.localeCompare(b.name));
672
+ return (0, caws_kernel_1.ok)({ entries });
673
+ }
674
+ //# sourceMappingURL=worktrees-writer.js.map