@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,1143 +0,0 @@
1
- /**
2
- * @fileoverview Provenance Command Handler
3
- * Manages CAWS provenance tracking and audit trails
4
- * @author @darianrosebrook
5
- */
6
-
7
- /* global fetch */
8
-
9
- const fs = require('fs-extra');
10
- const path = require('path');
11
- const crypto = require('crypto');
12
- const yaml = require('js-yaml');
13
- const { execSync } = require('child_process');
14
- const { commandWrapper } = require('../utils/command-wrapper');
15
- const { resolveSpec } = require('../utils/spec-resolver');
16
-
17
- async function resolveProvenanceSpec(options = {}) {
18
- try {
19
- return await resolveSpec({
20
- specId: options.specId,
21
- specFile: options.specFile,
22
- warnLegacy: false,
23
- });
24
- } catch (error) {
25
- const shouldFallbackToLegacy =
26
- !options.specId &&
27
- !options.specFile &&
28
- error.message.includes('schema violations');
29
-
30
- if (!shouldFallbackToLegacy) {
31
- throw error;
32
- }
33
-
34
- const legacyPath = path.join(process.cwd(), '.caws', 'working-spec.yaml');
35
- if (!(await fs.pathExists(legacyPath))) {
36
- throw error;
37
- }
38
-
39
- const legacyContent = await fs.readFile(legacyPath, 'utf8');
40
- const legacySpec = yaml.load(legacyContent);
41
-
42
- return {
43
- path: legacyPath,
44
- type: 'legacy',
45
- spec: legacySpec,
46
- degradedValidation: true,
47
- };
48
- }
49
- }
50
-
51
- /**
52
- * Get quality gates status from saved report
53
- * @returns {Object} Quality gates status
54
- */
55
- function getQualityGatesStatus() {
56
- const reportPath = path.join(process.cwd(), '.caws', 'quality-gates-report.json');
57
-
58
- if (fs.existsSync(reportPath)) {
59
- try {
60
- const report = JSON.parse(fs.readFileSync(reportPath, 'utf8'));
61
- return {
62
- status: report.passed ? 'passing' : 'failing',
63
- last_validated: report.timestamp || new Date().toISOString(),
64
- violations: report.violations || 0,
65
- gates: report.gates || {}
66
- };
67
- } catch (error) {
68
- // Fall through to default
69
- }
70
- }
71
-
72
- return {
73
- status: 'not_validated',
74
- last_validated: null,
75
- violations: null
76
- };
77
- }
78
-
79
- /**
80
- * Provenance command handler
81
- * @param {string} subcommand - The subcommand to execute
82
- * @param {Object} options - Command options
83
- */
84
- async function provenanceCommand(subcommand, options) {
85
- return commandWrapper(
86
- async () => {
87
- switch (subcommand) {
88
- case 'update':
89
- return await updateProvenance(options);
90
- case 'show':
91
- return await showProvenance(options);
92
- case 'verify':
93
- return await verifyProvenance(options);
94
- case 'analyze-ai':
95
- return await analyzeAIProvenance(options);
96
- case 'init':
97
- return await initProvenance(options);
98
- case 'install-hooks':
99
- return await installHooks(options);
100
- default:
101
- throw new Error(
102
- `Unknown provenance subcommand: ${subcommand}.\n` +
103
- 'Available commands: update, show, verify, analyze-ai, init, install-hooks'
104
- );
105
- }
106
- },
107
- {
108
- commandName: `provenance ${subcommand}`,
109
- context: { subcommand, options },
110
- }
111
- );
112
- }
113
-
114
- /**
115
- * Update provenance with new commit information
116
- * @param {Object} options - Command options
117
- */
118
- async function updateProvenance(options) {
119
- const { commit, message, author, quiet = false, output = '.caws/provenance' } = options;
120
-
121
- if (!commit) {
122
- throw new Error('Commit hash is required for provenance update');
123
- }
124
-
125
- // Ensure output directory exists
126
- await fs.ensureDir(output);
127
-
128
- const resolved = await resolveProvenanceSpec(options);
129
- const spec = resolved.spec;
130
-
131
- // Load existing provenance chain
132
- const provenanceChain = await loadProvenanceChain(output);
133
-
134
- // Create new provenance entry
135
- const newEntry = {
136
- id: `prov-${Date.now()}`,
137
- timestamp: new Date().toISOString(),
138
- commit: {
139
- hash: commit,
140
- message: message || '',
141
- author: author || 'Unknown',
142
- },
143
- working_spec: {
144
- id: spec.id,
145
- title: spec.title,
146
- risk_tier: spec.risk_tier,
147
- mode: spec.mode,
148
- type: resolved.type,
149
- path: resolved.path,
150
- status: spec.status || null,
151
- waiver_ids: spec.waiver_ids || [],
152
- },
153
- quality_gates: getQualityGatesStatus(),
154
- agent: {
155
- type: detectAgentType(),
156
- confidence_level: null, // Would be populated by agent actions
157
- },
158
- cursor_tracking: await getCursorTrackingData(commit), // AI code tracking data
159
- checkpoints: await getCursorCheckpoints(), // Composer checkpoint data
160
- };
161
-
162
- // Calculate hash including previous chain
163
- const previousHash =
164
- provenanceChain.length > 0 ? provenanceChain[provenanceChain.length - 1].hash : '';
165
- newEntry.previous_hash = previousHash;
166
-
167
- const hashContent = JSON.stringify(
168
- {
169
- ...newEntry,
170
- hash: undefined, // Exclude hash from hash calculation
171
- },
172
- Object.keys(newEntry).sort()
173
- );
174
-
175
- newEntry.hash = crypto.createHash('sha256').update(hashContent).digest('hex');
176
-
177
- // Add to chain and save
178
- provenanceChain.push(newEntry);
179
- await saveProvenanceChain(provenanceChain, output);
180
-
181
- if (!quiet) {
182
- console.log(`Provenance updated for commit ${commit.substring(0, 8)}`);
183
- console.log(` Spec: ${spec.id} (${resolved.type}) -> ${resolved.path}`);
184
- if (resolved.degradedValidation) {
185
- console.log(' Note: using legacy spec metadata despite schema validation issues');
186
- }
187
- console.log(` Chain length: ${provenanceChain.length} entries`);
188
- console.log(` Hash: ${newEntry.hash.substring(0, 16)}...`);
189
- }
190
- }
191
-
192
- /**
193
- * Show current provenance information
194
- * @param {Object} options - Command options
195
- */
196
- async function showProvenance(options) {
197
- const { output = '.caws/provenance', format = 'text' } = options;
198
-
199
- const chain = await loadProvenanceChain(output);
200
-
201
- if (chain.length === 0) {
202
- if (format === 'dashboard') {
203
- console.log('┌- CAWS Provenance Dashboard ----------------------┐');
204
- console.log('│ No provenance data found │');
205
- console.log('│ │');
206
- console.log('│ Run "caws provenance init" to get started │');
207
- console.log('└-------------------------------------------------┘');
208
- } else {
209
- console.log('No provenance data found');
210
- console.log(`Run "caws provenance init" to get started`);
211
- }
212
- return;
213
- }
214
-
215
- if (format === 'json') {
216
- console.log(JSON.stringify(chain, null, 2));
217
- return;
218
- }
219
-
220
- if (format === 'dashboard') {
221
- await showDashboardFormat(chain, output);
222
- return;
223
- }
224
-
225
- console.log('CAWS Provenance Chain');
226
- console.log('==============================================');
227
- console.log(`Total entries: ${chain.length}`);
228
- console.log('');
229
-
230
- // Show last 5 entries
231
- const recent = chain.slice(-5);
232
- recent.forEach((entry, index) => {
233
- const commit = entry.commit.hash.substring(0, 8);
234
- const time = new Date(entry.timestamp).toLocaleString();
235
- const offset = chain.length - recent.length + index + 1;
236
-
237
- console.log(`${offset}. ${commit} - ${time}`);
238
- console.log(` ${entry.commit.message.split('\n')[0]}`);
239
- console.log(` ${entry.commit.author}`);
240
- if (entry.working_spec) {
241
- console.log(` Spec: ${entry.working_spec.id} (${entry.working_spec.risk_tier})`);
242
- }
243
- if (entry.agent && entry.agent.type !== 'human') {
244
- console.log(` Agent: ${entry.agent.type}`);
245
- }
246
-
247
- // Display AI code tracking if available
248
- if (entry.cursor_tracking && entry.cursor_tracking.available) {
249
- const tracking = entry.cursor_tracking;
250
- console.log(
251
- ` AI Code: ${tracking.ai_code_breakdown.composer_chat.percentage}% composer, ${tracking.ai_code_breakdown.tab_completions.percentage}% tab-complete, ${tracking.ai_code_breakdown.manual_human.percentage}% manual`
252
- );
253
- console.log(
254
- ` Quality: ${Math.round(tracking.quality_metrics.ai_code_quality_score * 100)}% AI score, ${Math.round(tracking.quality_metrics.acceptance_rate * 100)}% acceptance`
255
- );
256
- }
257
-
258
- // Display checkpoint info if available
259
- if (entry.checkpoints && entry.checkpoints.available && entry.checkpoints.checkpoints) {
260
- console.log(` Checkpoints: ${entry.checkpoints.checkpoints.length} created`);
261
- }
262
-
263
- console.log('');
264
- });
265
-
266
- if (chain.length > 5) {
267
- console.log(`... and ${chain.length - 5} earlier entries`);
268
- }
269
- }
270
-
271
- /**
272
- * Verify provenance chain integrity
273
- * @param {Object} options - Command options
274
- */
275
- async function verifyProvenance(options) {
276
- const { output = '.caws/provenance' } = options;
277
-
278
- const chain = await loadProvenanceChain(output);
279
-
280
- if (chain.length === 0) {
281
- console.log('No provenance data to verify');
282
- return;
283
- }
284
-
285
- console.log('Verifying provenance chain integrity...');
286
-
287
- let valid = true;
288
- for (let i = 0; i < chain.length; i++) {
289
- const entry = chain[i];
290
-
291
- // Verify hash integrity
292
- const expectedPreviousHash = i === 0 ? '' : chain[i - 1].hash;
293
- if (entry.previous_hash !== expectedPreviousHash) {
294
- console.error(`Chain break at entry ${i + 1}: previous hash mismatch`);
295
- valid = false;
296
- }
297
-
298
- // Recalculate and verify current hash
299
- const entryForHash = { ...entry };
300
- delete entryForHash.hash; // Remove hash field before calculation
301
-
302
- const hashContent = JSON.stringify(entryForHash, Object.keys(entryForHash).sort());
303
-
304
- const calculatedHash = crypto.createHash('sha256').update(hashContent).digest('hex');
305
-
306
- if (calculatedHash !== entry.hash) {
307
- console.error(`Hash verification failed at entry ${i + 1}`);
308
- console.error(` Expected: ${entry.hash}`);
309
- console.error(` Calculated: ${calculatedHash}`);
310
- valid = false;
311
- }
312
- }
313
-
314
- if (valid) {
315
- console.log('Provenance chain integrity verified');
316
- console.log(` ${chain.length} entries, all hashes valid`);
317
- } else {
318
- console.error('Provenance chain integrity compromised');
319
- process.exit(1);
320
- }
321
- }
322
-
323
- /**
324
- * Load existing provenance chain from files
325
- * @param {string} outputDir - Directory containing provenance files
326
- * @returns {Array} Array of provenance entries
327
- */
328
- async function loadProvenanceChain(outputDir) {
329
- const chainFile = path.join(outputDir, 'chain.json');
330
-
331
- if (!(await fs.pathExists(chainFile))) {
332
- return [];
333
- }
334
-
335
- try {
336
- const content = await fs.readFile(chainFile, 'utf8');
337
- return JSON.parse(content);
338
- } catch (error) {
339
- console.warn(`Warning: Could not load provenance chain: ${error.message}`);
340
- return [];
341
- }
342
- }
343
-
344
- /**
345
- * Save provenance chain to file
346
- * @param {Array} chain - Provenance entries array
347
- * @param {string} outputDir - Directory to save to
348
- */
349
- async function saveProvenanceChain(chain, outputDir) {
350
- const chainFile = path.join(outputDir, 'chain.json');
351
- await fs.writeFile(chainFile, JSON.stringify(chain, null, 2));
352
- }
353
-
354
- /**
355
- * Analyze AI patterns and effectiveness from provenance data
356
- * @param {Object} options - Command options
357
- */
358
- async function analyzeAIProvenance(options) {
359
- const { output = '.caws/provenance' } = options;
360
-
361
- const chain = await loadProvenanceChain(output);
362
-
363
- if (chain.length === 0) {
364
- console.log('No provenance data to analyze');
365
- return;
366
- }
367
-
368
- console.log('AI Code Effectiveness Analysis');
369
- console.log('==============================================');
370
-
371
- // Filter entries with AI tracking data
372
- const aiEntries = chain.filter(
373
- (entry) =>
374
- entry.cursor_tracking &&
375
- entry.cursor_tracking.available &&
376
- entry.agent &&
377
- entry.agent.type !== 'human'
378
- );
379
-
380
- if (aiEntries.length === 0) {
381
- console.log('No AI tracking data found in provenance');
382
- console.log('Configure CURSOR_TRACKING_API and CURSOR_CHECKPOINT_API environment variables');
383
- return;
384
- }
385
-
386
- console.log(`Analyzed ${aiEntries.length} AI-assisted commits`);
387
- console.log('');
388
-
389
- // Analyze AI code contribution patterns
390
- const contributionPatterns = analyzeContributionPatterns(aiEntries);
391
- const qualityMetrics = analyzeQualityMetrics(aiEntries);
392
- const checkpointAnalysis = analyzeCheckpointUsage(aiEntries);
393
-
394
- console.log('AI Contribution Patterns:');
395
- console.log(` Average Composer/Chat contribution: ${contributionPatterns.avgComposerPercent}%`);
396
- console.log(
397
- ` Average Tab completion contribution: ${contributionPatterns.avgTabCompletePercent}%`
398
- );
399
- console.log(` Average Manual override rate: ${contributionPatterns.avgManualPercent}%`);
400
- console.log('');
401
-
402
- console.log('Quality Metrics:');
403
- console.log(
404
- ` Average AI code quality score: ${Math.round(qualityMetrics.avgQualityScore * 100)}%`
405
- );
406
- console.log(` Average acceptance rate: ${Math.round(qualityMetrics.avgAcceptanceRate * 100)}%`);
407
- console.log(
408
- ` Average human override rate: ${Math.round(qualityMetrics.avgOverrideRate * 100)}%`
409
- );
410
- console.log('');
411
-
412
- console.log('Checkpoint Analysis:');
413
- console.log(
414
- ` Commits with checkpoints: ${checkpointAnalysis.entriesWithCheckpoints}/${aiEntries.length}`
415
- );
416
- console.log(` Average checkpoints per commit: ${checkpointAnalysis.avgCheckpointsPerEntry}`);
417
- console.log(` Checkpoint revert rate: ${Math.round(checkpointAnalysis.revertRate * 100)}%`);
418
- console.log('');
419
-
420
- // Provide insights and recommendations
421
- provideAIInsights(contributionPatterns, qualityMetrics, checkpointAnalysis);
422
- }
423
-
424
- /**
425
- * Analyze AI contribution patterns across entries
426
- */
427
- function analyzeContributionPatterns(aiEntries) {
428
- const contributions = aiEntries
429
- .filter((entry) => entry.cursor_tracking?.ai_code_breakdown)
430
- .map((entry) => entry.cursor_tracking.ai_code_breakdown);
431
-
432
- if (contributions.length === 0) return {};
433
-
434
- const avgComposer =
435
- contributions.reduce((sum, c) => sum + c.composer_chat.percentage, 0) / contributions.length;
436
- const avgTab =
437
- contributions.reduce((sum, c) => sum + c.tab_completions.percentage, 0) / contributions.length;
438
- const avgManual =
439
- contributions.reduce((sum, c) => sum + c.manual_human.percentage, 0) / contributions.length;
440
-
441
- return {
442
- avgComposerPercent: Math.round(avgComposer),
443
- avgTabCompletePercent: Math.round(avgTab),
444
- avgManualPercent: Math.round(avgManual),
445
- };
446
- }
447
-
448
- /**
449
- * Analyze AI quality metrics across entries
450
- */
451
- function analyzeQualityMetrics(aiEntries) {
452
- const metrics = aiEntries
453
- .filter((entry) => entry.cursor_tracking?.quality_metrics)
454
- .map((entry) => entry.cursor_tracking.quality_metrics);
455
-
456
- if (metrics.length === 0) return {};
457
-
458
- const avgQuality = metrics.reduce((sum, m) => sum + m.ai_code_quality_score, 0) / metrics.length;
459
- const avgAcceptance = metrics.reduce((sum, m) => sum + m.acceptance_rate, 0) / metrics.length;
460
- const avgOverride = metrics.reduce((sum, m) => sum + m.human_override_rate, 0) / metrics.length;
461
-
462
- return {
463
- avgQualityScore: avgQuality,
464
- avgAcceptanceRate: avgAcceptance,
465
- avgOverrideRate: avgOverride,
466
- };
467
- }
468
-
469
- /**
470
- * Analyze checkpoint usage patterns
471
- */
472
- /**
473
- * Calculate actual revert rate from git history
474
- * Analyzes commits for revert patterns and calculates the percentage
475
- * @param {number} maxCommits - Maximum number of commits to analyze
476
- * @returns {number} Revert rate as a decimal (0.0 - 1.0)
477
- */
478
- function calculateRevertRate(maxCommits = 500) {
479
- try {
480
- // Get total commit count (limited)
481
- const logOutput = execSync(`git log --oneline -n ${maxCommits} 2>/dev/null`, {
482
- encoding: 'utf8',
483
- cwd: process.cwd(),
484
- }).trim();
485
-
486
- if (!logOutput) {
487
- return 0;
488
- }
489
-
490
- const totalCommits = logOutput.split('\n').filter(Boolean).length;
491
-
492
- // Count revert commits (commits with "revert" in the message)
493
- const revertOutput = execSync(
494
- `git log --oneline -n ${maxCommits} --grep="[Rr]evert" 2>/dev/null || true`,
495
- {
496
- encoding: 'utf8',
497
- cwd: process.cwd(),
498
- }
499
- ).trim();
500
-
501
- const revertCommits = revertOutput ? revertOutput.split('\n').filter(Boolean).length : 0;
502
-
503
- // Also check for reset/force-push patterns in reflog if available
504
- let additionalReverts = 0;
505
- try {
506
- const reflogOutput = execSync(`git reflog --oneline -n ${maxCommits} 2>/dev/null || true`, {
507
- encoding: 'utf8',
508
- cwd: process.cwd(),
509
- }).trim();
510
-
511
- if (reflogOutput) {
512
- const reflogLines = reflogOutput.split('\n').filter(Boolean);
513
- additionalReverts = reflogLines.filter(
514
- (line) => line.includes('reset:') || line.includes('checkout:')
515
- ).length;
516
- // Weight reflog reverts less since they may not be actual code reverts
517
- additionalReverts = Math.floor(additionalReverts * 0.1);
518
- }
519
- } catch {
520
- // Reflog not available or failed
521
- }
522
-
523
- const totalReverts = revertCommits + additionalReverts;
524
- const revertRate = totalCommits > 0 ? totalReverts / totalCommits : 0;
525
-
526
- return Math.min(1.0, revertRate); // Cap at 100%
527
- } catch {
528
- // Git not available or not a repo
529
- return 0;
530
- }
531
- }
532
-
533
- function analyzeCheckpointUsage(aiEntries) {
534
- const entriesWithCheckpoints = aiEntries.filter(
535
- (entry) => entry.checkpoints?.available && entry.checkpoints.checkpoints?.length > 0
536
- ).length;
537
-
538
- const totalCheckpoints = aiEntries
539
- .filter((entry) => entry.checkpoints?.available)
540
- .reduce((sum, entry) => sum + (entry.checkpoints.checkpoints?.length || 0), 0);
541
-
542
- // Calculate actual revert rate from git history
543
- const revertRate = calculateRevertRate();
544
-
545
- return {
546
- entriesWithCheckpoints,
547
- avgCheckpointsPerEntry:
548
- entriesWithCheckpoints > 0 ? (totalCheckpoints / entriesWithCheckpoints).toFixed(1) : 0,
549
- revertRate,
550
- };
551
- }
552
-
553
- /**
554
- * Install git hooks for automatic provenance updates
555
- * @param {Object} options - Command options
556
- */
557
- async function installHooks(options) {
558
- const { output = '.caws/provenance', skipPreCommit = false, skipPostCommit = false } = options;
559
-
560
- console.log('Installing CAWS Provenance Git Hooks');
561
- console.log('==================================================');
562
-
563
- // Check if we're in a git repository
564
- if (!(await fs.pathExists('.git'))) {
565
- console.log('Not in a git repository');
566
- console.log('Initialize git first: git init');
567
- process.exit(1);
568
- }
569
-
570
- // Check if provenance is initialized
571
- if (!(await fs.pathExists(path.join(output, 'chain.json')))) {
572
- console.log('Provenance not initialized');
573
- console.log('Run "caws provenance init" first');
574
- process.exit(1);
575
- }
576
-
577
- console.log('Found git repository and provenance setup');
578
-
579
- // Ensure hooks directory exists
580
- const hooksDir = '.git/hooks';
581
- await fs.ensureDir(hooksDir);
582
- console.log('Ensured hooks directory exists');
583
-
584
- let hooksInstalled = 0;
585
-
586
- // Install pre-commit hook for validation
587
- if (!skipPreCommit) {
588
- try {
589
- const preCommitHook = await createPreCommitHook(output);
590
- const preCommitPath = path.join(hooksDir, 'pre-commit');
591
-
592
- await fs.writeFile(preCommitPath, preCommitHook);
593
- await fs.chmod(preCommitPath, '755');
594
- console.log('Installed pre-commit hook for provenance validation');
595
- hooksInstalled++;
596
- } catch (error) {
597
- console.warn('Failed to install pre-commit hook:', error.message);
598
- }
599
- }
600
-
601
- // Install post-commit hook for provenance updates
602
- if (!skipPostCommit) {
603
- try {
604
- const postCommitHook = await createPostCommitHook(output);
605
- const postCommitPath = path.join(hooksDir, 'post-commit');
606
-
607
- await fs.writeFile(postCommitPath, postCommitHook);
608
- await fs.chmod(postCommitPath, '755');
609
- console.log('Installed post-commit hook for provenance updates');
610
- hooksInstalled++;
611
- } catch (error) {
612
- console.warn('Failed to install post-commit hook:', error.message);
613
- }
614
- }
615
-
616
- console.log('');
617
- console.log('Git hooks installation complete!');
618
- console.log('');
619
- console.log(`Installed ${hooksInstalled} hook(s):`);
620
- if (!skipPreCommit) {
621
- console.log(' - pre-commit: Validates provenance before commits');
622
- }
623
- if (!skipPostCommit) {
624
- console.log(' - post-commit: Updates provenance after commits');
625
- }
626
- console.log('');
627
- console.log('Your commits will now automatically maintain provenance!');
628
- console.log(' Run "caws provenance show" to view the updated chain');
629
- }
630
-
631
- /**
632
- * Create pre-commit hook script for provenance validation
633
- * @param {string} outputDir - Provenance output directory
634
- * @returns {string} Hook script content
635
- */
636
- async function createPreCommitHook(outputDir) {
637
- const scriptPath = path.resolve('node_modules/.bin/caws');
638
- const fallbackPath = path.resolve('packages/caws-cli/dist/index.js');
639
-
640
- return `#!/bin/sh
641
- # CAWS Provenance Pre-commit Hook
642
- # Validates provenance integrity before allowing commits
643
-
644
- echo "Validating CAWS provenance..."
645
-
646
- # Find caws CLI
647
- if command -v caws >/dev/null 2>&1; then
648
- CAWS_CMD="caws"
649
- elif [ -x "${scriptPath}" ]; then
650
- CAWS_CMD="${scriptPath}"
651
- elif [ -x "${fallbackPath}" ]; then
652
- CAWS_CMD="node ${fallbackPath}"
653
- else
654
- echo "CAWS CLI not found, skipping provenance validation"
655
- exit 0
656
- fi
657
-
658
- # Run provenance verification
659
- if $CAWS_CMD provenance verify --output "${outputDir}" >/dev/null 2>&1; then
660
- echo "Provenance validation passed"
661
- exit 0
662
- else
663
- echo "Provenance validation failed"
664
- echo "Run 'caws provenance show' to investigate"
665
- exit 1
666
- fi
667
- `;
668
- }
669
-
670
- /**
671
- * Create post-commit hook script for provenance updates
672
- * @param {string} outputDir - Provenance output directory
673
- * @returns {string} Hook script content
674
- */
675
- async function createPostCommitHook(outputDir) {
676
- const scriptPath = path.resolve('node_modules/.bin/caws');
677
- const fallbackPath = path.resolve('packages/caws-cli/dist/index.js');
678
-
679
- return `#!/bin/sh
680
- # CAWS Provenance Post-commit Hook
681
- # Updates provenance chain after successful commits
682
-
683
- echo "Updating CAWS provenance..."
684
-
685
- # Get the current commit hash
686
- COMMIT_HASH=$(git rev-parse HEAD)
687
- COMMIT_MSG=$(git log -1 --pretty=%B | head -n 1)
688
- AUTHOR=$(git log -1 --pretty=%an)
689
-
690
- # Find caws CLI
691
- if command -v caws >/dev/null 2>&1; then
692
- CAWS_CMD="caws"
693
- elif [ -x "${scriptPath}" ]; then
694
- CAWS_CMD="${scriptPath}"
695
- elif [ -x "${fallbackPath}" ]; then
696
- CAWS_CMD="node ${fallbackPath}"
697
- else
698
- echo "CAWS CLI not found, skipping provenance update"
699
- exit 0
700
- fi
701
-
702
- # Update provenance
703
- if $CAWS_CMD provenance update --commit "$COMMIT_HASH" --message "$COMMIT_MSG" --author "$AUTHOR" --output "${outputDir}" --quiet; then
704
- echo "Provenance updated for commit \${COMMIT_HASH:0:8}"
705
- else
706
- echo "Failed to update provenance (non-fatal)"
707
- fi
708
-
709
- exit 0
710
- `;
711
- }
712
-
713
- /**
714
- * Show provenance data in dashboard format
715
- * @param {Array} chain - Provenance chain entries
716
- * @param {string} outputDir - Output directory path
717
- */
718
- async function showDashboardFormat(chain, outputDir) {
719
- // Calculate key metrics
720
- const totalEntries = chain.length;
721
- const aiEntries = chain.filter(
722
- (entry) => entry.cursor_tracking?.available && entry.agent?.type !== 'human'
723
- ).length;
724
-
725
- const avgQualityScore =
726
- aiEntries > 0
727
- ? chain
728
- .filter((entry) => entry.cursor_tracking?.quality_metrics?.ai_code_quality_score)
729
- .reduce(
730
- (sum, entry) => sum + entry.cursor_tracking.quality_metrics.ai_code_quality_score,
731
- 0
732
- ) /
733
- chain.filter((entry) => entry.cursor_tracking?.quality_metrics?.ai_code_quality_score)
734
- .length
735
- : 0;
736
-
737
- const avgAcceptanceRate =
738
- aiEntries > 0
739
- ? chain
740
- .filter((entry) => entry.cursor_tracking?.quality_metrics?.acceptance_rate)
741
- .reduce((sum, entry) => sum + entry.cursor_tracking.quality_metrics.acceptance_rate, 0) /
742
- chain.filter((entry) => entry.cursor_tracking?.quality_metrics?.acceptance_rate).length
743
- : 0;
744
-
745
- // Check config
746
- let configStatus = 'Not configured';
747
- try {
748
- const configPath = path.join(outputDir, 'config.json');
749
- if (await fs.pathExists(configPath)) {
750
- const config = JSON.parse(await fs.readFile(configPath, 'utf8'));
751
- const configured = [
752
- config.cursor_tracking_api !== 'not_configured',
753
- config.cursor_checkpoint_api !== 'not_configured',
754
- config.cursor_project_id !== 'not_configured',
755
- ].filter(Boolean).length;
756
- configStatus = configured === 3 ? 'Fully configured' : `${configured}/3 configured`;
757
- }
758
- } catch (error) {
759
- // Ignore config read errors
760
- }
761
-
762
- // Display dashboard
763
- console.log('┌- CAWS Provenance Dashboard ----------------------┐');
764
- console.log(`│ Total Entries: ${totalEntries.toString().padEnd(33)} │`);
765
- console.log(`│ AI-Assisted: ${aiEntries.toString().padEnd(35)} │`);
766
- console.log(
767
- `│ Avg Quality: ${(avgQualityScore * 100).toFixed(0).padEnd(2)}%${' '.repeat(33)} │`
768
- );
769
- console.log(
770
- `│ Avg Acceptance: ${(avgAcceptanceRate * 100).toFixed(0).padEnd(2)}%${' '.repeat(30)} │`
771
- );
772
- console.log(`│ Config Status: ${configStatus.padEnd(31)} │`);
773
- console.log('├-------------------------------------------------┤');
774
-
775
- if (totalEntries > 0) {
776
- console.log('│ Recent Activity: │');
777
- const recent = chain.slice(-3);
778
- recent.forEach((entry, index) => {
779
- const commit = entry.commit.hash.substring(0, 8);
780
- const time = new Date(entry.timestamp).toLocaleDateString();
781
- const msg = entry.commit.message.split('\n')[0].substring(0, 30);
782
- const line = `${index + 1}. ${commit} ${time} ${msg}`;
783
- console.log(`│ ${line.padEnd(47)} │`);
784
- });
785
-
786
- if (aiEntries > 0) {
787
- console.log('├-------------------------------------------------┤');
788
- console.log('│ AI Contribution Breakdown: │');
789
-
790
- const contributions = chain
791
- .filter((entry) => entry.cursor_tracking?.ai_code_breakdown)
792
- .map((entry) => entry.cursor_tracking.ai_code_breakdown);
793
-
794
- if (contributions.length > 0) {
795
- const avgComposer =
796
- contributions.reduce((sum, c) => sum + c.composer_chat.percentage, 0) /
797
- contributions.length;
798
- const avgTab =
799
- contributions.reduce((sum, c) => sum + c.tab_completions.percentage, 0) /
800
- contributions.length;
801
- const avgManual =
802
- contributions.reduce((sum, c) => sum + c.manual_human.percentage, 0) /
803
- contributions.length;
804
-
805
- const composerBar = '█'.repeat(Math.round(avgComposer / 5));
806
- const tabBar = '█'.repeat(Math.round(avgTab / 5));
807
- const manualBar = '█'.repeat(Math.round(avgManual / 5));
808
-
809
- console.log(
810
- `│ Composer/Chat: ${composerBar.padEnd(10)} ${Math.round(avgComposer).toString().padStart(2)}%${' '.repeat(18)} │`
811
- );
812
- console.log(
813
- `│ Tab Complete: ${tabBar.padEnd(10)} ${Math.round(avgTab).toString().padStart(2)}%${' '.repeat(18)} │`
814
- );
815
- console.log(
816
- `│ Manual: ${manualBar.padEnd(10)} ${Math.round(avgManual).toString().padStart(2)}%${' '.repeat(18)} │`
817
- );
818
- }
819
- }
820
- }
821
-
822
- console.log('└-------------------------------------------------┘');
823
-
824
- // Add insights
825
- if (aiEntries > 0) {
826
- console.log('');
827
- console.log('Insights:');
828
- if (avgAcceptanceRate > 0.9) {
829
- console.log(' High AI acceptance rate indicates effective collaboration');
830
- } else if (avgAcceptanceRate < 0.7) {
831
- console.log(' Lower acceptance rate may indicate AI refinement needed');
832
- }
833
-
834
- if (avgQualityScore > 0.8) {
835
- console.log(' Excellent AI code quality - great results!');
836
- }
837
- }
838
- }
839
-
840
- /**
841
- * Provide insights and recommendations based on AI analysis
842
- */
843
- function provideAIInsights(contributionPatterns, qualityMetrics, checkpointAnalysis) {
844
- console.log('AI Effectiveness Insights:');
845
-
846
- if (contributionPatterns.avgComposerPercent > 60) {
847
- console.log(' High Composer usage suggests complex feature development');
848
- console.log(' → Consider breaking large features into smaller, focused sessions');
849
- }
850
-
851
- if (qualityMetrics.avgOverrideRate > 0.2) {
852
- console.log(' High human override rate indicates AI suggestions need refinement');
853
- console.log(' → Review AI confidence thresholds or provide clearer requirements');
854
- }
855
-
856
- if (checkpointAnalysis.avgCheckpointsPerEntry < 2) {
857
- console.log(' Low checkpoint usage may limit ability to recover from bad AI directions');
858
- console.log(' → Encourage more frequent checkpointing in Composer sessions');
859
- }
860
-
861
- if (qualityMetrics.avgAcceptanceRate > 0.9) {
862
- console.log(' High acceptance rate indicates effective AI assistance');
863
- console.log(' → Current AI integration is working well');
864
- }
865
-
866
- console.log('');
867
- console.log('Recommendations:');
868
- console.log(
869
- ` - Target Composer contribution: ${Math.max(40, contributionPatterns.avgComposerPercent - 10)}-${Math.min(80, contributionPatterns.avgComposerPercent + 10)}%`
870
- );
871
- console.log(
872
- ` - Acceptable override rate: <${Math.round((qualityMetrics.avgOverrideRate + 0.1) * 100)}%`
873
- );
874
- console.log(' - Checkpoint frequency: Every 10-15 minutes in active sessions');
875
- }
876
-
877
- /**
878
- * Get Cursor AI code tracking data for a commit
879
- * Uses Cursor's AI Code Tracking API (Enterprise feature)
880
- * @see https://cursor.com/docs/account/teams/ai-code-tracking-api
881
- * @param {string} commitHash - Git commit hash to analyze
882
- * @returns {Promise<Object>} AI code tracking data
883
- */
884
- async function getCursorTrackingData(commitHash) {
885
- const apiUrl = process.env.CURSOR_TRACKING_API;
886
- const apiKey = process.env.CURSOR_API_KEY;
887
-
888
- if (!apiUrl || !apiKey) {
889
- return {
890
- available: false,
891
- reason: 'Cursor API not configured. Set CURSOR_TRACKING_API and CURSOR_API_KEY environment variables.',
892
- documentation: 'https://cursor.com/docs/account/teams/ai-code-tracking-api'
893
- };
894
- }
895
-
896
- try {
897
- // Basic auth: base64(apiKey:) - Cursor API uses API key with empty password
898
- const auth = Buffer.from(`${apiKey}:`).toString('base64');
899
-
900
- const response = await fetch(`${apiUrl}/analytics/ai-code/commits`, {
901
- method: 'GET',
902
- headers: {
903
- 'Authorization': `Basic ${auth}`,
904
- 'Content-Type': 'application/json',
905
- }
906
- });
907
-
908
- if (!response.ok) {
909
- return {
910
- available: false,
911
- reason: `Cursor API error: ${response.status} ${response.statusText}`
912
- };
913
- }
914
-
915
- const data = await response.json();
916
-
917
- // Find commit-specific data if available
918
- const commitData = data.commits?.find(c => c.commit_hash === commitHash) || data;
919
-
920
- // Transform API response to our internal format
921
- return {
922
- available: true,
923
- commit_hash: commitHash,
924
- ai_code_breakdown: commitData.ai_code_breakdown || {
925
- tab_completions: { lines_added: 0, percentage: 0, files_affected: [] },
926
- composer_chat: { lines_added: 0, percentage: 0, files_affected: [], checkpoints_created: 0 },
927
- manual_human: { lines_added: 0, percentage: 0, files_affected: [] },
928
- },
929
- change_groups: commitData.change_groups || [],
930
- quality_metrics: commitData.quality_metrics || {
931
- ai_code_quality_score: 0,
932
- human_override_rate: 0,
933
- acceptance_rate: 0,
934
- },
935
- };
936
- } catch (error) {
937
- return {
938
- available: false,
939
- error: error.message,
940
- reason: 'Failed to retrieve Cursor tracking data',
941
- };
942
- }
943
- }
944
-
945
- /**
946
- * Initialize provenance tracking for the project
947
- * @param {Object} options - Command options
948
- */
949
- async function initProvenance(options) {
950
- const { output = '.caws/provenance', cursorApi } = options;
951
-
952
- console.log('Initializing CAWS Provenance Tracking');
953
- console.log('===================================================');
954
-
955
- // Check if already initialized
956
- if (await fs.pathExists(path.join(output, 'chain.json'))) {
957
- console.log('Provenance already initialized');
958
- console.log(` Chain exists at: ${output}/chain.json`);
959
- console.log('');
960
- console.log('To reset, delete the provenance directory and run again');
961
- return;
962
- }
963
-
964
- // Ensure output directory exists
965
- await fs.ensureDir(output);
966
- console.log(`Created provenance directory: ${output}`);
967
-
968
- const resolved = await resolveProvenanceSpec(options);
969
- console.log(`Found CAWS spec: ${resolved.spec.id} (${resolved.type})`);
970
- if (resolved.degradedValidation) {
971
- console.log(' Proceeding with legacy spec metadata despite schema validation issues');
972
- }
973
-
974
- // Initialize empty chain
975
- const initialChain = [];
976
- await saveProvenanceChain(initialChain, output);
977
- console.log('Initialized empty provenance chain');
978
-
979
- // Create environment configuration hints
980
- const envConfig = {
981
- spec: {
982
- id: resolved.spec.id,
983
- path: resolved.path,
984
- type: resolved.type,
985
- },
986
- cursor_tracking_api: cursorApi || process.env.CURSOR_TRACKING_API || 'not_configured',
987
- cursor_checkpoint_api: process.env.CURSOR_CHECKPOINT_API || 'not_configured',
988
- cursor_project_id: process.env.CURSOR_PROJECT_ID || 'not_configured',
989
- notes: [
990
- 'Configure CURSOR_TRACKING_API for AI code tracking',
991
- 'Configure CURSOR_CHECKPOINT_API for session recovery data',
992
- 'Configure CURSOR_PROJECT_ID to link with Cursor IDE',
993
- ],
994
- };
995
-
996
- await fs.writeFile(path.join(output, 'config.json'), JSON.stringify(envConfig, null, 2));
997
- console.log('Created configuration template');
998
-
999
- console.log('');
1000
- console.log('Provenance tracking initialized!');
1001
- console.log('');
1002
- console.log('Next steps:');
1003
- console.log('1. Install git hooks for automatic provenance (recommended):');
1004
- console.log(' caws provenance install-hooks');
1005
- console.log('');
1006
- console.log('2. Configure environment variables (optional):');
1007
- console.log(' export CURSOR_TRACKING_API="your-api-endpoint"');
1008
- console.log(' export CURSOR_CHECKPOINT_API="your-checkpoint-endpoint"');
1009
- console.log(' export CURSOR_PROJECT_ID="your-project-id"');
1010
- console.log('');
1011
- console.log('3. Manual provenance updates (if not using hooks):');
1012
- console.log(' caws provenance update --commit <hash>');
1013
- console.log('');
1014
- console.log('4. View provenance history:');
1015
- console.log(' caws provenance show');
1016
- }
1017
-
1018
- /**
1019
- * Get Cursor Composer/Chat checkpoint data
1020
- * Reads from local .cursor/ directory since checkpoints are stored locally by Cursor Agent
1021
- * @returns {Promise<Object>} Checkpoint data
1022
- */
1023
- async function getCursorCheckpoints() {
1024
- const cursorDir = path.join(process.cwd(), '.cursor');
1025
-
1026
- if (!fs.existsSync(cursorDir)) {
1027
- return {
1028
- available: false,
1029
- reason: 'No .cursor directory found. Checkpoints are only available when using Cursor IDE.'
1030
- };
1031
- }
1032
-
1033
- try {
1034
- // Look for checkpoint metadata in .cursor directory
1035
- // Cursor stores checkpoints locally during Composer/Agent sessions
1036
- const checkpointPatterns = [
1037
- '.cursor/**/checkpoint*.json',
1038
- '.cursor/**/checkpoints.json',
1039
- '.cursor/composer/checkpoints/*.json',
1040
- '.cursor/agent/checkpoints/*.json',
1041
- ];
1042
-
1043
- let checkpointFiles = [];
1044
- for (const pattern of checkpointPatterns) {
1045
- const glob = require('glob');
1046
- const matches = glob.sync(pattern, { cwd: process.cwd(), absolute: true });
1047
- checkpointFiles = checkpointFiles.concat(matches);
1048
- }
1049
-
1050
- // Remove duplicates
1051
- checkpointFiles = [...new Set(checkpointFiles)];
1052
-
1053
- if (checkpointFiles.length === 0) {
1054
- return {
1055
- available: false,
1056
- reason: 'No checkpoints found in current session. Checkpoints are created during Cursor Composer/Agent sessions.'
1057
- };
1058
- }
1059
-
1060
- // Parse checkpoint files and aggregate data
1061
- const checkpoints = [];
1062
- for (const file of checkpointFiles) {
1063
- try {
1064
- const content = await fs.readFile(file, 'utf8');
1065
- const data = JSON.parse(content);
1066
-
1067
- // Handle both single checkpoint and array of checkpoints
1068
- if (Array.isArray(data)) {
1069
- checkpoints.push(...data);
1070
- } else if (data.checkpoints) {
1071
- checkpoints.push(...data.checkpoints);
1072
- } else if (data.id || data.timestamp) {
1073
- checkpoints.push(data);
1074
- }
1075
- } catch (parseError) {
1076
- // Skip invalid checkpoint files
1077
- continue;
1078
- }
1079
- }
1080
-
1081
- if (checkpoints.length === 0) {
1082
- return {
1083
- available: false,
1084
- reason: 'No valid checkpoints found in checkpoint files.'
1085
- };
1086
- }
1087
-
1088
- // Sort by timestamp (newest first)
1089
- checkpoints.sort((a, b) => {
1090
- const timeA = new Date(a.timestamp || 0).getTime();
1091
- const timeB = new Date(b.timestamp || 0).getTime();
1092
- return timeB - timeA;
1093
- });
1094
-
1095
- // Mark latest checkpoint as non-revertible
1096
- if (checkpoints.length > 0) {
1097
- checkpoints[0].can_revert = false;
1098
- }
1099
-
1100
- return { available: true, checkpoints };
1101
- } catch (error) {
1102
- return {
1103
- available: false,
1104
- error: error.message,
1105
- reason: 'Failed to read Cursor checkpoint data',
1106
- };
1107
- }
1108
- }
1109
-
1110
- /**
1111
- * Attempt to detect the type of agent/system making changes
1112
- * @returns {string} Agent type identifier
1113
- */
1114
- function detectAgentType() {
1115
- // Check environment variables and context clues
1116
- if (
1117
- process.env.CURSOR_AGENT === 'true' ||
1118
- process.env.CURSOR_TRACKING_API ||
1119
- process.env.CURSOR_CHECKPOINT_API
1120
- ) {
1121
- return 'cursor-ide';
1122
- }
1123
-
1124
- if (process.env.GITHUB_ACTIONS === 'true') {
1125
- return 'github-actions';
1126
- }
1127
-
1128
- if (process.env.CI === 'true') {
1129
- return 'ci-system';
1130
- }
1131
-
1132
- // Default to human unless we can detect otherwise
1133
- return 'human';
1134
- }
1135
-
1136
- module.exports = {
1137
- provenanceCommand,
1138
- updateProvenance,
1139
- showProvenance,
1140
- verifyProvenance,
1141
- initProvenance,
1142
- installHooks,
1143
- };