plumbbob 0.9.3 → 0.10.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 (320) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +92 -89
  3. package/dist/cli-core.js +25 -8
  4. package/dist/cli.js +1 -1
  5. package/dist/lib/agents.js +26 -26
  6. package/dist/lib/buildlog.js +11 -11
  7. package/dist/lib/buildlogsync.js +8 -8
  8. package/dist/lib/check.js +55 -22
  9. package/dist/lib/commitbody.js +72 -0
  10. package/dist/lib/commitmsg.js +7 -7
  11. package/dist/lib/git.js +44 -15
  12. package/dist/lib/intent.js +21 -20
  13. package/dist/lib/latch.js +19 -19
  14. package/dist/lib/orient.js +36 -17
  15. package/dist/lib/reentry.js +70 -0
  16. package/dist/lib/settings.js +16 -16
  17. package/dist/lib/sidecar.js +54 -54
  18. package/dist/lib/templates.js +1 -1
  19. package/dist/verbs/agent.js +27 -27
  20. package/dist/verbs/build.js +9 -9
  21. package/dist/verbs/check.js +6 -6
  22. package/dist/verbs/checkpoint.js +48 -47
  23. package/dist/verbs/doctor.js +31 -30
  24. package/dist/verbs/finish.js +28 -41
  25. package/dist/verbs/handoff.js +9 -8
  26. package/dist/verbs/init.js +9 -9
  27. package/dist/verbs/park.js +3 -3
  28. package/dist/verbs/recover.js +297 -0
  29. package/dist/verbs/revert.js +13 -13
  30. package/dist/verbs/spike.js +25 -19
  31. package/dist/verbs/start.js +49 -19
  32. package/dist/verbs/status.js +8 -8
  33. package/dist/verbs/turn.js +16 -16
  34. package/dist/verbs/use.js +4 -4
  35. package/hooks/post-edit.sh +4 -4
  36. package/hooks/pre-bash-commit.sh +3 -3
  37. package/node_modules/checkride/.claude-plugin/plugin.json +11 -0
  38. package/node_modules/checkride/CHANGELOG.md +1404 -0
  39. package/node_modules/checkride/LICENSE +201 -21
  40. package/node_modules/checkride/README.md +197 -38
  41. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts +15 -0
  42. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts.map +1 -0
  43. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js +17 -0
  44. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js.map +1 -0
  45. package/node_modules/checkride/dist/adapters.d.ts +30 -10
  46. package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
  47. package/node_modules/checkride/dist/adapters.js +62 -23
  48. package/node_modules/checkride/dist/adapters.js.map +1 -1
  49. package/node_modules/checkride/dist/agent-setup/claude.d.ts +88 -0
  50. package/node_modules/checkride/dist/agent-setup/claude.d.ts.map +1 -0
  51. package/node_modules/checkride/dist/agent-setup/claude.js +305 -0
  52. package/node_modules/checkride/dist/agent-setup/claude.js.map +1 -0
  53. package/node_modules/checkride/dist/agent-setup/command.d.ts +43 -0
  54. package/node_modules/checkride/dist/agent-setup/command.d.ts.map +1 -0
  55. package/node_modules/checkride/dist/agent-setup/command.js +77 -0
  56. package/node_modules/checkride/dist/agent-setup/command.js.map +1 -0
  57. package/node_modules/checkride/dist/agent-setup/cursor.d.ts +69 -0
  58. package/node_modules/checkride/dist/agent-setup/cursor.d.ts.map +1 -0
  59. package/node_modules/checkride/dist/agent-setup/cursor.js +247 -0
  60. package/node_modules/checkride/dist/agent-setup/cursor.js.map +1 -0
  61. package/node_modules/checkride/dist/agent-setup/files.d.ts +50 -0
  62. package/node_modules/checkride/dist/agent-setup/files.d.ts.map +1 -0
  63. package/node_modules/checkride/dist/agent-setup/files.js +80 -0
  64. package/node_modules/checkride/dist/agent-setup/files.js.map +1 -0
  65. package/node_modules/checkride/dist/agent-setup/harness.d.ts +101 -0
  66. package/node_modules/checkride/dist/agent-setup/harness.d.ts.map +1 -0
  67. package/node_modules/checkride/dist/agent-setup/harness.js +93 -0
  68. package/node_modules/checkride/dist/agent-setup/harness.js.map +1 -0
  69. package/node_modules/checkride/dist/agent-setup/hook.d.ts +45 -52
  70. package/node_modules/checkride/dist/agent-setup/hook.d.ts.map +1 -1
  71. package/node_modules/checkride/dist/agent-setup/hook.js +64 -95
  72. package/node_modules/checkride/dist/agent-setup/hook.js.map +1 -1
  73. package/node_modules/checkride/dist/agent-setup/index.d.ts +10 -4
  74. package/node_modules/checkride/dist/agent-setup/index.d.ts.map +1 -1
  75. package/node_modules/checkride/dist/agent-setup/index.js +9 -4
  76. package/node_modules/checkride/dist/agent-setup/index.js.map +1 -1
  77. package/node_modules/checkride/dist/agent-setup/scripts.d.ts +81 -0
  78. package/node_modules/checkride/dist/agent-setup/scripts.d.ts.map +1 -0
  79. package/node_modules/checkride/dist/agent-setup/scripts.js +604 -0
  80. package/node_modules/checkride/dist/agent-setup/scripts.js.map +1 -0
  81. package/node_modules/checkride/dist/agent-setup/skills.d.ts +31 -0
  82. package/node_modules/checkride/dist/agent-setup/skills.d.ts.map +1 -0
  83. package/node_modules/checkride/dist/agent-setup/skills.js +56 -0
  84. package/node_modules/checkride/dist/agent-setup/skills.js.map +1 -0
  85. package/node_modules/checkride/dist/artifacts/configured.d.ts +30 -0
  86. package/node_modules/checkride/dist/artifacts/configured.d.ts.map +1 -0
  87. package/node_modules/checkride/dist/artifacts/configured.js +45 -0
  88. package/node_modules/checkride/dist/artifacts/configured.js.map +1 -0
  89. package/node_modules/checkride/dist/artifacts/format.d.ts +33 -0
  90. package/node_modules/checkride/dist/artifacts/format.d.ts.map +1 -0
  91. package/node_modules/checkride/dist/artifacts/format.js +56 -0
  92. package/node_modules/checkride/dist/artifacts/format.js.map +1 -0
  93. package/node_modules/checkride/dist/artifacts/freshness.d.ts +32 -0
  94. package/node_modules/checkride/dist/artifacts/freshness.d.ts.map +1 -0
  95. package/node_modules/checkride/dist/artifacts/freshness.js +37 -0
  96. package/node_modules/checkride/dist/artifacts/freshness.js.map +1 -0
  97. package/node_modules/checkride/dist/artifacts/index.d.ts +22 -0
  98. package/node_modules/checkride/dist/artifacts/index.d.ts.map +1 -0
  99. package/node_modules/checkride/dist/artifacts/index.js +19 -0
  100. package/node_modules/checkride/dist/artifacts/index.js.map +1 -0
  101. package/node_modules/checkride/dist/artifacts/json.d.ts +31 -0
  102. package/node_modules/checkride/dist/artifacts/json.d.ts.map +1 -0
  103. package/node_modules/checkride/dist/artifacts/json.js +47 -0
  104. package/node_modules/checkride/dist/artifacts/json.js.map +1 -0
  105. package/node_modules/checkride/dist/artifacts/raw.d.ts +60 -0
  106. package/node_modules/checkride/dist/artifacts/raw.d.ts.map +1 -0
  107. package/node_modules/checkride/dist/artifacts/raw.js +91 -0
  108. package/node_modules/checkride/dist/artifacts/raw.js.map +1 -0
  109. package/node_modules/checkride/dist/artifacts/summary.d.ts +69 -0
  110. package/node_modules/checkride/dist/artifacts/summary.d.ts.map +1 -0
  111. package/node_modules/checkride/dist/artifacts/summary.js +108 -0
  112. package/node_modules/checkride/dist/artifacts/summary.js.map +1 -0
  113. package/node_modules/checkride/dist/atomic.d.ts +16 -1
  114. package/node_modules/checkride/dist/atomic.d.ts.map +1 -1
  115. package/node_modules/checkride/dist/atomic.js +25 -3
  116. package/node_modules/checkride/dist/atomic.js.map +1 -1
  117. package/node_modules/checkride/dist/baseline/fallow.d.ts +9 -5
  118. package/node_modules/checkride/dist/baseline/fallow.d.ts.map +1 -1
  119. package/node_modules/checkride/dist/baseline/fallow.js +163 -60
  120. package/node_modules/checkride/dist/baseline/fallow.js.map +1 -1
  121. package/node_modules/checkride/dist/baseline/fingerprint.d.ts +20 -11
  122. package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
  123. package/node_modules/checkride/dist/baseline/fingerprint.js +73 -23
  124. package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
  125. package/node_modules/checkride/dist/baseline/history.d.ts +98 -0
  126. package/node_modules/checkride/dist/baseline/history.d.ts.map +1 -0
  127. package/node_modules/checkride/dist/baseline/history.js +232 -0
  128. package/node_modules/checkride/dist/baseline/history.js.map +1 -0
  129. package/node_modules/checkride/dist/baseline/index.d.ts +7 -5
  130. package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
  131. package/node_modules/checkride/dist/baseline/index.js +5 -4
  132. package/node_modules/checkride/dist/baseline/index.js.map +1 -1
  133. package/node_modules/checkride/dist/baseline/store.d.ts +41 -10
  134. package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -1
  135. package/node_modules/checkride/dist/baseline/store.js +65 -24
  136. package/node_modules/checkride/dist/baseline/store.js.map +1 -1
  137. package/node_modules/checkride/dist/baseline-command.d.ts +5 -5
  138. package/node_modules/checkride/dist/baseline-command.js +7 -7
  139. package/node_modules/checkride/dist/baseline-command.js.map +1 -1
  140. package/node_modules/checkride/dist/cli.d.ts +21 -4
  141. package/node_modules/checkride/dist/cli.d.ts.map +1 -1
  142. package/node_modules/checkride/dist/cli.js +350 -36
  143. package/node_modules/checkride/dist/cli.js.map +1 -1
  144. package/node_modules/checkride/dist/config.d.ts +114 -9
  145. package/node_modules/checkride/dist/config.d.ts.map +1 -1
  146. package/node_modules/checkride/dist/config.js +142 -23
  147. package/node_modules/checkride/dist/config.js.map +1 -1
  148. package/node_modules/checkride/dist/digest/digest.d.ts +5 -5
  149. package/node_modules/checkride/dist/digest/digest.js +6 -6
  150. package/node_modules/checkride/dist/digest/index.d.ts +2 -2
  151. package/node_modules/checkride/dist/digest/index.js +2 -2
  152. package/node_modules/checkride/dist/doctor.d.ts +27 -6
  153. package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
  154. package/node_modules/checkride/dist/doctor.js +231 -27
  155. package/node_modules/checkride/dist/doctor.js.map +1 -1
  156. package/node_modules/checkride/dist/gate.d.ts +180 -0
  157. package/node_modules/checkride/dist/gate.d.ts.map +1 -0
  158. package/node_modules/checkride/dist/gate.js +617 -0
  159. package/node_modules/checkride/dist/gate.js.map +1 -0
  160. package/node_modules/checkride/dist/init.d.ts +79 -12
  161. package/node_modules/checkride/dist/init.d.ts.map +1 -1
  162. package/node_modules/checkride/dist/init.js +385 -81
  163. package/node_modules/checkride/dist/init.js.map +1 -1
  164. package/node_modules/checkride/dist/json.d.ts +21 -0
  165. package/node_modules/checkride/dist/json.d.ts.map +1 -0
  166. package/node_modules/checkride/dist/json.js +21 -0
  167. package/node_modules/checkride/dist/json.js.map +1 -0
  168. package/node_modules/checkride/dist/links.d.ts +31 -5
  169. package/node_modules/checkride/dist/links.d.ts.map +1 -1
  170. package/node_modules/checkride/dist/links.js +141 -32
  171. package/node_modules/checkride/dist/links.js.map +1 -1
  172. package/node_modules/checkride/dist/node-pin.d.ts +129 -0
  173. package/node_modules/checkride/dist/node-pin.d.ts.map +1 -0
  174. package/node_modules/checkride/dist/node-pin.js +211 -0
  175. package/node_modules/checkride/dist/node-pin.js.map +1 -0
  176. package/node_modules/checkride/dist/orchestrator.d.ts +53 -10
  177. package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
  178. package/node_modules/checkride/dist/orchestrator.js +312 -113
  179. package/node_modules/checkride/dist/orchestrator.js.map +1 -1
  180. package/node_modules/checkride/dist/pack.d.ts +8 -9
  181. package/node_modules/checkride/dist/pack.d.ts.map +1 -1
  182. package/node_modules/checkride/dist/pack.js +53 -17
  183. package/node_modules/checkride/dist/pack.js.map +1 -1
  184. package/node_modules/checkride/dist/pm/detect.d.ts +6 -1
  185. package/node_modules/checkride/dist/pm/detect.d.ts.map +1 -1
  186. package/node_modules/checkride/dist/pm/detect.js +6 -1
  187. package/node_modules/checkride/dist/pm/detect.js.map +1 -1
  188. package/node_modules/checkride/dist/pm/index.d.ts +7 -2
  189. package/node_modules/checkride/dist/pm/index.d.ts.map +1 -1
  190. package/node_modules/checkride/dist/pm/index.js +6 -2
  191. package/node_modules/checkride/dist/pm/index.js.map +1 -1
  192. package/node_modules/checkride/dist/pm/launch.d.ts +72 -0
  193. package/node_modules/checkride/dist/pm/launch.d.ts.map +1 -0
  194. package/node_modules/checkride/dist/pm/launch.js +108 -0
  195. package/node_modules/checkride/dist/pm/launch.js.map +1 -0
  196. package/node_modules/checkride/dist/pm/tools.d.ts +73 -0
  197. package/node_modules/checkride/dist/pm/tools.d.ts.map +1 -0
  198. package/node_modules/checkride/dist/pm/tools.js +124 -0
  199. package/node_modules/checkride/dist/pm/tools.js.map +1 -0
  200. package/node_modules/checkride/dist/pm/translate.d.ts +35 -9
  201. package/node_modules/checkride/dist/pm/translate.d.ts.map +1 -1
  202. package/node_modules/checkride/dist/pm/translate.js +78 -18
  203. package/node_modules/checkride/dist/pm/translate.js.map +1 -1
  204. package/node_modules/checkride/dist/proc.d.ts +30 -0
  205. package/node_modules/checkride/dist/proc.d.ts.map +1 -0
  206. package/node_modules/checkride/dist/proc.js +42 -0
  207. package/node_modules/checkride/dist/proc.js.map +1 -0
  208. package/node_modules/checkride/dist/qa/cli.d.ts +20 -0
  209. package/node_modules/checkride/dist/qa/cli.d.ts.map +1 -0
  210. package/node_modules/checkride/dist/qa/cli.js +24 -0
  211. package/node_modules/checkride/dist/qa/cli.js.map +1 -0
  212. package/node_modules/checkride/dist/qa/dead.d.ts +39 -0
  213. package/node_modules/checkride/dist/qa/dead.d.ts.map +1 -0
  214. package/node_modules/checkride/dist/qa/dead.js +88 -0
  215. package/node_modules/checkride/dist/qa/dead.js.map +1 -0
  216. package/node_modules/checkride/dist/qa/dupes.d.ts +45 -0
  217. package/node_modules/checkride/dist/qa/dupes.d.ts.map +1 -0
  218. package/node_modules/checkride/dist/qa/dupes.js +62 -0
  219. package/node_modules/checkride/dist/qa/dupes.js.map +1 -0
  220. package/node_modules/checkride/dist/qa/health.d.ts +85 -0
  221. package/node_modules/checkride/dist/qa/health.d.ts.map +1 -0
  222. package/node_modules/checkride/dist/qa/health.js +109 -0
  223. package/node_modules/checkride/dist/qa/health.js.map +1 -0
  224. package/node_modules/checkride/dist/qa/index.d.ts +23 -0
  225. package/node_modules/checkride/dist/qa/index.d.ts.map +1 -0
  226. package/node_modules/checkride/dist/qa/index.js +22 -0
  227. package/node_modules/checkride/dist/qa/index.js.map +1 -0
  228. package/node_modules/checkride/dist/qa/mutation.d.ts +80 -0
  229. package/node_modules/checkride/dist/qa/mutation.d.ts.map +1 -0
  230. package/node_modules/checkride/dist/qa/mutation.js +195 -0
  231. package/node_modules/checkride/dist/qa/mutation.js.map +1 -0
  232. package/node_modules/checkride/dist/qa/qa.d.ts +71 -0
  233. package/node_modules/checkride/dist/qa/qa.d.ts.map +1 -0
  234. package/node_modules/checkride/dist/qa/qa.js +158 -0
  235. package/node_modules/checkride/dist/qa/qa.js.map +1 -0
  236. package/node_modules/checkride/dist/qa/read.d.ts +40 -0
  237. package/node_modules/checkride/dist/qa/read.d.ts.map +1 -0
  238. package/node_modules/checkride/dist/qa/read.js +47 -0
  239. package/node_modules/checkride/dist/qa/read.js.map +1 -0
  240. package/node_modules/checkride/dist/qa/render.d.ts +26 -0
  241. package/node_modules/checkride/dist/qa/render.d.ts.map +1 -0
  242. package/node_modules/checkride/dist/qa/render.js +310 -0
  243. package/node_modules/checkride/dist/qa/render.js.map +1 -0
  244. package/node_modules/checkride/dist/recover.d.ts +48 -0
  245. package/node_modules/checkride/dist/recover.d.ts.map +1 -0
  246. package/node_modules/checkride/dist/recover.js +220 -0
  247. package/node_modules/checkride/dist/recover.js.map +1 -0
  248. package/node_modules/checkride/dist/security.d.ts +45 -0
  249. package/node_modules/checkride/dist/security.d.ts.map +1 -0
  250. package/node_modules/checkride/dist/security.js +86 -0
  251. package/node_modules/checkride/dist/security.js.map +1 -0
  252. package/node_modules/checkride/dist/smoke.d.ts +6 -6
  253. package/node_modules/checkride/dist/smoke.js +6 -6
  254. package/node_modules/checkride/dist/snippets.d.ts +27 -30
  255. package/node_modules/checkride/dist/snippets.d.ts.map +1 -1
  256. package/node_modules/checkride/dist/snippets.js +26 -30
  257. package/node_modules/checkride/dist/snippets.js.map +1 -1
  258. package/node_modules/checkride/dist/tool-json.d.ts +33 -0
  259. package/node_modules/checkride/dist/tool-json.d.ts.map +1 -0
  260. package/node_modules/checkride/dist/tool-json.js +58 -0
  261. package/node_modules/checkride/dist/tool-json.js.map +1 -0
  262. package/node_modules/checkride/dist/triage/cli.d.ts +21 -0
  263. package/node_modules/checkride/dist/triage/cli.d.ts.map +1 -0
  264. package/node_modules/checkride/dist/triage/cli.js +26 -0
  265. package/node_modules/checkride/dist/triage/cli.js.map +1 -0
  266. package/node_modules/checkride/dist/triage/doctor-fold.d.ts +51 -0
  267. package/node_modules/checkride/dist/triage/doctor-fold.d.ts.map +1 -0
  268. package/node_modules/checkride/dist/triage/doctor-fold.js +88 -0
  269. package/node_modules/checkride/dist/triage/doctor-fold.js.map +1 -0
  270. package/node_modules/checkride/dist/triage/env.d.ts +54 -0
  271. package/node_modules/checkride/dist/triage/env.d.ts.map +1 -0
  272. package/node_modules/checkride/dist/triage/env.js +81 -0
  273. package/node_modules/checkride/dist/triage/env.js.map +1 -0
  274. package/node_modules/checkride/dist/triage/gate.d.ts +61 -0
  275. package/node_modules/checkride/dist/triage/gate.d.ts.map +1 -0
  276. package/node_modules/checkride/dist/triage/gate.js +121 -0
  277. package/node_modules/checkride/dist/triage/gate.js.map +1 -0
  278. package/node_modules/checkride/dist/triage/index.d.ts +22 -0
  279. package/node_modules/checkride/dist/triage/index.d.ts.map +1 -0
  280. package/node_modules/checkride/dist/triage/index.js +20 -0
  281. package/node_modules/checkride/dist/triage/index.js.map +1 -0
  282. package/node_modules/checkride/dist/triage/render.d.ts +19 -0
  283. package/node_modules/checkride/dist/triage/render.d.ts.map +1 -0
  284. package/node_modules/checkride/dist/triage/render.js +419 -0
  285. package/node_modules/checkride/dist/triage/render.js.map +1 -0
  286. package/node_modules/checkride/dist/triage/triage.d.ts +83 -0
  287. package/node_modules/checkride/dist/triage/triage.d.ts.map +1 -0
  288. package/node_modules/checkride/dist/triage/triage.js +131 -0
  289. package/node_modules/checkride/dist/triage/triage.js.map +1 -0
  290. package/node_modules/checkride/package.json +18 -15
  291. package/node_modules/checkride/schema/checkride.config.schema.json +70 -5
  292. package/node_modules/checkride/schema/checkride.summary.schema.json +1 -1
  293. package/node_modules/checkride/skills/check/SKILL.md +265 -0
  294. package/node_modules/checkride/skills/qa/SKILL.md +231 -0
  295. package/node_modules/checkride/templates/shared/cspell.json +1 -0
  296. package/node_modules/checkride/templates/shared/oxlintrc.json +1 -1
  297. package/node_modules/checkride/templates/shared/styles/Repo/Drift.yml +41 -0
  298. package/node_modules/checkride/templates/shared/styles/Repo/Latin.yml +14 -0
  299. package/node_modules/checkride/templates/shared/styles/Repo/LyHyphen.yml +28 -0
  300. package/node_modules/checkride/templates/shared/styles/Repo/Minted.yml +33 -0
  301. package/node_modules/checkride/templates/shared/styles/Repo/ThereIs.yml +16 -0
  302. package/node_modules/checkride/templates/shared/styles/Repo/Weasel.yml +26 -0
  303. package/node_modules/checkride/templates/shared/vale.ini +34 -0
  304. package/package.json +10 -9
  305. package/skills/build/SKILL.md +85 -76
  306. package/skills/doctor/SKILL.md +11 -11
  307. package/skills/finish/SKILL.md +21 -18
  308. package/skills/harvest/SKILL.md +13 -11
  309. package/skills/park/SKILL.md +10 -10
  310. package/skills/plan/SKILL.md +69 -59
  311. package/skills/recover/SKILL.md +28 -0
  312. package/skills/refine/SKILL.md +21 -18
  313. package/skills/revert/SKILL.md +6 -6
  314. package/skills/spike/SKILL.md +9 -9
  315. package/skills/status/SKILL.md +5 -5
  316. package/skills/step/SKILL.md +20 -15
  317. package/skills/verify/SKILL.md +56 -46
  318. package/templates/build-log.md +7 -7
  319. package/templates/intent.md +52 -41
  320. package/templates/spike-report.md +10 -10
@@ -1,63 +1,56 @@
1
1
  /**
2
- * Claude Code Stop hook — the mechanical half of the agent contract.
2
+ * Agent hooks — the mechanical half of the agent contract.
3
3
  *
4
- * `init` and `checkride agent-setup` write an idempotent Stop hook into
5
- * `.claude/settings.json`. It runs the project's `check` script as a hard gate:
6
- * exit 2 blocks the agent from finishing while the pipeline is red, so "exit 0 =
7
- * done" becomes enforcement, not just advice. The command uses the *detected*
8
- * package manager's run form (`pnpm run check`, `npm run check`, `yarn run
9
- * check`, `bun run check`) so the hook works in any repo, not only pnpm ones
10
- * (b7). Merging is surgical: unrelated hooks, other Stop groups, and every other
11
- * settings key are preserved, and re-applying with the same PM is a no-op.
4
+ * `init` and `checkride agent-setup` write a small registry of hooks into every
5
+ * selected harness's config. The load-bearing one is the gate: it runs the
6
+ * project's `check` script when the turn ends and refuses to let the agent
7
+ * finish while the pipeline is red, so "exit 0 = done" becomes enforcement, not
8
+ * just advice.
12
9
  *
13
- * This module owns only the hook; the AGENTS.md stanza and the higher-level
14
- * `agent-setup` command live in `init.ts`, which imports the writer here — a
15
- * single direction, so there is no cycle.
16
- */
17
- import { type PackageManager } from '../pm/index.js';
18
- /** Project-shared Claude Code settings (committed), relative to the repo root. */
19
- export declare const CLAUDE_SETTINGS_FILE = ".claude/settings.json";
20
- /** A single Claude Code command hook (fields optional — settings.json is untrusted). */
21
- type CommandHook = {
22
- type?: string;
23
- command?: string;
24
- };
25
- /** A Stop-hook group. Only `hooks` is meaningful for Stop; other keys pass through. */
26
- type StopGroup = {
27
- hooks?: CommandHook[];
28
- } & Record<string, unknown>;
29
- /** The subset of `.claude/settings.json` we touch; every other key is preserved. */
30
- type ClaudeSettings = {
31
- hooks?: {
32
- Stop?: StopGroup[];
33
- } & Record<string, unknown>;
34
- } & Record<string, unknown>;
35
- /**
36
- * The Stop-hook command for `pm`: run the gate, and on red print guidance and
37
- * exit 2 (the blocking code — a plain exit 1 lets the agent stop anyway).
10
+ * This module is the harness-neutral half — which hooks exist, which harnesses a
11
+ * repo wants, and the fan-out. Everything harness-shaped lives in a sibling:
12
+ * `./claude.ts` and `./cursor.ts` own their config schemas, `./scripts.ts` owns
13
+ * the generated scripts, and `../gate.ts` owns the verdict those scripts hand
14
+ * back. Adding a third harness means one more sibling and one more entry in
15
+ * `HARNESS_NAMES`, not a change here.
16
+ *
17
+ * The AGENTS.md stanza and the higher-level `agent-setup` command live in
18
+ * `init.ts`, which imports the writers here — a single direction, so there is no
19
+ * cycle.
38
20
  */
39
- export declare function stopHookCommand(pm: PackageManager): string;
21
+ import { type HarnessName } from '../gate.js';
22
+ import type { PackageManager } from '../pm/index.js';
23
+ import type { HookFile } from './files.js';
24
+ import { HOOK_NAMES, type HookName } from './harness.js';
25
+ export { HOOK_NAMES, type HookName };
40
26
  /**
41
- * Merge checkride's Stop hook into parsed settings, idempotently. An existing
42
- * checkride hook (found by its sentinel) has its command refreshed in place;
43
- * otherwise a new Stop group is appended. Sibling hooks in the same group, other
44
- * Stop groups, and every unrelated settings key are left untouched, so applying
45
- * twice with the same command yields deep-equal settings.
27
+ * Which harnesses to wire up when `--harness` was not given.
28
+ *
29
+ * Claude Code is always included: it is the harness checkride was built against,
30
+ * and writing its hooks into a repo that never opens Claude costs two ignored
31
+ * files. Cursor is included only on evidence (`.cursor/` exists), because the
32
+ * inverse — seeding `.cursor/` into every repo checkride touches — would put
33
+ * config in front of people who never asked for it.
46
34
  */
47
- export declare function applyStopHook(settings: ClaudeSettings, command: string): ClaudeSettings;
48
- export type StopHookResult = {
49
- path: string;
50
- changed: boolean;
51
- };
35
+ export declare function detectHarnesses(cwd: string): HarnessName[];
52
36
  /**
53
- * Write or refresh the Stop hook in `cwd/.claude/settings.json` for the detected
54
- * (or provided) package manager, preserving any other settings. Returns whether
55
- * the file changed: a second run with the same PM leaves it byte-identical, so
56
- * `changed` is `false`. `dryRun` computes the result without writing.
37
+ * Write or refresh the selected hooks (default: all) for the selected harnesses
38
+ * (default: detected) in `cwd`, and tear out any named in `remove`. Every write
39
+ * is idempotent — a second run reports `changed: false` per file — and `dryRun`
40
+ * computes the result without writing.
41
+ *
42
+ * Removal is how a hook goes away *after the fact*: unselecting one with
43
+ * `hooks` only declines to refresh it, which leaves an already-installed gate
44
+ * firing. The two compose — `{ hooks: [], remove: ['gate'] }` removes the gate
45
+ * and leaves everything else exactly as it stands.
57
46
  */
58
- export declare function writeStopHook(cwd: string, opts?: {
47
+ export declare function writeHooks(cwd: string, opts?: {
59
48
  pm?: PackageManager;
60
49
  dryRun?: boolean;
61
- }): Promise<StopHookResult>;
62
- export {};
50
+ hooks?: readonly HookName[];
51
+ remove?: readonly HookName[];
52
+ harnesses?: readonly HarnessName[];
53
+ }): Promise<{
54
+ files: HookFile[];
55
+ }>;
63
56
  //# sourceMappingURL=hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/agent-setup/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,EAAwB,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE3E,kFAAkF;AAClF,eAAO,MAAM,oBAAoB,0BAA0B,CAAC;AAS5D,wFAAwF;AACxF,KAAK,WAAW,GAAG;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACvD,uFAAuF;AACvF,KAAK,SAAS,GAAG;IAAE,KAAK,CAAC,EAAE,WAAW,EAAE,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACrE,oFAAoF;AACpF,KAAK,cAAc,GAAG;IAAE,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,SAAS,EAAE,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAO7G;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,cAAc,GAAG,MAAM,CAI1D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,cAAc,CAcvF;AAwBD,MAAM,MAAM,cAAc,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhE;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IAAE,EAAE,CAAC,EAAE,cAAc,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACnD,OAAO,CAAC,cAAc,CAAC,CAazB"}
1
+ {"version":3,"file":"hook.d.ts","sourceRoot":"","sources":["../../src/agent-setup/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAKH,OAAO,EAAiB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAqB,MAAM,cAAc,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,CAAC;AAcrC;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE,CAE1D;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE;IACJ,EAAE,CAAC,EAAE,cAAc,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC5B,MAAM,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;CAC/B,GACL,OAAO,CAAC;IAAE,KAAK,EAAE,QAAQ,EAAE,CAAA;CAAE,CAAC,CAahC"}
@@ -1,106 +1,75 @@
1
1
  /**
2
- * Claude Code Stop hook — the mechanical half of the agent contract.
2
+ * Agent hooks — the mechanical half of the agent contract.
3
3
  *
4
- * `init` and `checkride agent-setup` write an idempotent Stop hook into
5
- * `.claude/settings.json`. It runs the project's `check` script as a hard gate:
6
- * exit 2 blocks the agent from finishing while the pipeline is red, so "exit 0 =
7
- * done" becomes enforcement, not just advice. The command uses the *detected*
8
- * package manager's run form (`pnpm run check`, `npm run check`, `yarn run
9
- * check`, `bun run check`) so the hook works in any repo, not only pnpm ones
10
- * (b7). Merging is surgical: unrelated hooks, other Stop groups, and every other
11
- * settings key are preserved, and re-applying with the same PM is a no-op.
4
+ * `init` and `checkride agent-setup` write a small registry of hooks into every
5
+ * selected harness's config. The load-bearing one is the gate: it runs the
6
+ * project's `check` script when the turn ends and refuses to let the agent
7
+ * finish while the pipeline is red, so "exit 0 = done" becomes enforcement, not
8
+ * just advice.
12
9
  *
13
- * This module owns only the hook; the AGENTS.md stanza and the higher-level
14
- * `agent-setup` command live in `init.ts`, which imports the writer here — a
15
- * single direction, so there is no cycle.
16
- */
17
- import { mkdir, readFile, writeFile } from 'node:fs/promises';
18
- import { dirname, join } from 'node:path';
19
- import { detectPackageManager } from '../pm/index.js';
20
- /** Project-shared Claude Code settings (committed), relative to the repo root. */
21
- export const CLAUDE_SETTINGS_FILE = '.claude/settings.json';
22
- /**
23
- * Stable, package-manager-independent marker identifying checkride's Stop hook
24
- * inside a settings file. The run prefix varies by PM, so identity keys on the
25
- * guidance message, which does not.
26
- */
27
- const HOOK_SENTINEL = 'checkride: the gate is red';
28
- /** True when a hook entry is checkride's (matched by the PM-independent sentinel). */
29
- function isCheckrideHook(hook) {
30
- return hook.type === 'command' && typeof hook.command === 'string' && hook.command.includes(HOOK_SENTINEL);
31
- }
32
- /**
33
- * The Stop-hook command for `pm`: run the gate, and on red print guidance and
34
- * exit 2 (the blocking code — a plain exit 1 lets the agent stop anyway).
35
- */
36
- export function stopHookCommand(pm) {
37
- const run = `${pm} run check`;
38
- const guidance = `${HOOK_SENTINEL} — read .check/summary.json, fix the failing slot, then finish (do not stop while checkride is red).`;
39
- return `${run} || { echo '${guidance}' >&2; exit 2; }`;
40
- }
41
- /**
42
- * Merge checkride's Stop hook into parsed settings, idempotently. An existing
43
- * checkride hook (found by its sentinel) has its command refreshed in place;
44
- * otherwise a new Stop group is appended. Sibling hooks in the same group, other
45
- * Stop groups, and every unrelated settings key are left untouched, so applying
46
- * twice with the same command yields deep-equal settings.
10
+ * This module is the harness-neutral half — which hooks exist, which harnesses a
11
+ * repo wants, and the fan-out. Everything harness-shaped lives in a sibling:
12
+ * `./claude.ts` and `./cursor.ts` own their config schemas, `./scripts.ts` owns
13
+ * the generated scripts, and `../gate.ts` owns the verdict those scripts hand
14
+ * back. Adding a third harness means one more sibling and one more entry in
15
+ * `HARNESS_NAMES`, not a change here.
16
+ *
17
+ * The AGENTS.md stanza and the higher-level `agent-setup` command live in
18
+ * `init.ts`, which imports the writers here — a single direction, so there is no
19
+ * cycle.
47
20
  */
48
- export function applyStopHook(settings, command) {
49
- const hooks = { ...settings.hooks };
50
- const stop = Array.isArray(hooks.Stop) ? hooks.Stop.map((g) => ({ ...g })) : [];
51
- const idx = stop.findIndex((g) => (g.hooks ?? []).some(isCheckrideHook));
52
- const existing = idx >= 0 ? stop[idx] : undefined;
53
- if (existing) {
54
- stop[idx] = {
55
- ...existing,
56
- hooks: (existing.hooks ?? []).map((h) => (isCheckrideHook(h) ? { ...h, command } : h)),
57
- };
58
- }
59
- else {
60
- stop.push({ hooks: [{ type: 'command', command }] });
61
- }
62
- return { ...settings, hooks: { ...hooks, Stop: stop } };
63
- }
64
- async function readIfExists(path) {
65
- try {
66
- return await readFile(path, 'utf8');
67
- }
68
- catch {
69
- return null;
70
- }
71
- }
21
+ import { existsSync } from 'node:fs';
22
+ import { join } from 'node:path';
23
+ import { HARNESS_NAMES } from '../gate.js';
24
+ import { writeClaudeHooks } from './claude.js';
25
+ import { writeCursorHooks } from './cursor.js';
26
+ import { HOOK_NAMES } from './harness.js';
27
+ export { HOOK_NAMES };
28
+ /** The per-harness writers, keyed so the fan-out is a lookup, not a switch. */
29
+ const WRITERS = {
30
+ claude: writeClaudeHooks,
31
+ cursor: writeCursorHooks,
32
+ };
33
+ /** The directory whose presence means a repo is already using that harness. */
34
+ const HARNESS_MARKER = {
35
+ claude: '.claude',
36
+ cursor: '.cursor',
37
+ };
72
38
  /**
73
- * Parse an existing settings file, naming the file on malformed JSON so a
74
- * consumer sees `invalid .claude/settings.json: <reason>` instead of a bare
75
- * `SyntaxError` stack (mirrors `invalidConfig` in `config.ts`).
39
+ * Which harnesses to wire up when `--harness` was not given.
40
+ *
41
+ * Claude Code is always included: it is the harness checkride was built against,
42
+ * and writing its hooks into a repo that never opens Claude costs two ignored
43
+ * files. Cursor is included only on evidence (`.cursor/` exists), because the
44
+ * inverse — seeding `.cursor/` into every repo checkride touches — would put
45
+ * config in front of people who never asked for it.
76
46
  */
77
- function parseSettings(raw) {
78
- try {
79
- return JSON.parse(raw);
80
- }
81
- catch (err) {
82
- const reason = err instanceof Error ? err.message : String(err);
83
- throw new Error(`invalid ${CLAUDE_SETTINGS_FILE}: ${reason}`, { cause: err });
84
- }
47
+ export function detectHarnesses(cwd) {
48
+ return HARNESS_NAMES.filter((h) => h === 'claude' || existsSync(join(cwd, HARNESS_MARKER[h])));
85
49
  }
86
50
  /**
87
- * Write or refresh the Stop hook in `cwd/.claude/settings.json` for the detected
88
- * (or provided) package manager, preserving any other settings. Returns whether
89
- * the file changed: a second run with the same PM leaves it byte-identical, so
90
- * `changed` is `false`. `dryRun` computes the result without writing.
51
+ * Write or refresh the selected hooks (default: all) for the selected harnesses
52
+ * (default: detected) in `cwd`, and tear out any named in `remove`. Every write
53
+ * is idempotent — a second run reports `changed: false` per file — and `dryRun`
54
+ * computes the result without writing.
55
+ *
56
+ * Removal is how a hook goes away *after the fact*: unselecting one with
57
+ * `hooks` only declines to refresh it, which leaves an already-installed gate
58
+ * firing. The two compose — `{ hooks: [], remove: ['gate'] }` removes the gate
59
+ * and leaves everything else exactly as it stands.
91
60
  */
92
- export async function writeStopHook(cwd, opts = {}) {
93
- const path = join(cwd, CLAUDE_SETTINGS_FILE);
94
- const pm = opts.pm ?? detectPackageManager({ cwd });
95
- const raw = await readIfExists(path);
96
- const settings = raw ? parseSettings(raw) : {};
97
- const next = applyStopHook(settings, stopHookCommand(pm));
98
- const nextRaw = `${JSON.stringify(next, null, 2)}\n`;
99
- const changed = raw !== nextRaw;
100
- if (changed && !opts.dryRun) {
101
- await mkdir(dirname(path), { recursive: true });
102
- await writeFile(path, nextRaw);
103
- }
104
- return { path: CLAUDE_SETTINGS_FILE, changed };
61
+ export async function writeHooks(cwd, opts = {}) {
62
+ const hooks = opts.hooks ?? HOOK_NAMES;
63
+ const harnesses = opts.harnesses ?? detectHarnesses(cwd);
64
+ const write = {
65
+ ...(opts.pm ? { pm: opts.pm } : {}),
66
+ ...(opts.remove ? { remove: opts.remove } : {}),
67
+ dryRun: opts.dryRun ?? false,
68
+ hooks,
69
+ };
70
+ // Concurrent: no two harnesses share a path, and `Promise.all` keeps the
71
+ // reported order tied to the selection rather than to who finished first.
72
+ const perHarness = await Promise.all(harnesses.map((h) => WRITERS[h](cwd, write)));
73
+ return { files: perHarness.flat() };
105
74
  }
106
75
  //# sourceMappingURL=hook.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/agent-setup/hook.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"hook.js","sourceRoot":"","sources":["../../src/agent-setup/hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EAAE,UAAU,EAAoC,MAAM,cAAc,CAAC;AAE5E,OAAO,EAAE,UAAU,EAAiB,CAAC;AAErC,+EAA+E;AAC/E,MAAM,OAAO,GAAkF;IAC7F,MAAM,EAAE,gBAAgB;IACxB,MAAM,EAAE,gBAAgB;CACzB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,cAAc,GAAgC;IAClD,MAAM,EAAE,SAAS;IACjB,MAAM,EAAE,SAAS;CAClB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjG,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,GAAW,EACX,OAMI,EAAE;IAEN,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,UAAU,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC;IACzD,MAAM,KAAK,GAAiB;QAC1B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK;QAC5B,KAAK;KACN,CAAC;IACF,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACnF,OAAO,EAAE,KAAK,EAAE,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC;AACtC,CAAC"}
@@ -1,7 +1,13 @@
1
1
  /**
2
- * Agent-setup module — the Claude Code Stop hook (step 12). This barrel is the
3
- * module's only public surface (C2): siblings import from `../agent-setup`,
4
- * never from `./hook.js` directly.
2
+ * Agent-setup module — the hooks every supported harness gets (the stop gate and
3
+ * kin). This barrel is the module's only public surface: siblings import from
4
+ * `../agent-setup`, never from `./hook.js` or a per-harness writer directly.
5
5
  */
6
- export { applyStopHook, CLAUDE_SETTINGS_FILE, stopHookCommand, writeStopHook } from './hook.js';
6
+ export { applyHooks, CLAUDE_SETTINGS_FILE, GATE_SCRIPT_FILE, PROTECT_SCRIPT_FILE, removeHooks, } from './claude.js';
7
+ export { type HooksOptions, runHooks } from './command.js';
8
+ export { applyCursorHooks, CURSOR_HOOKS_FILE, removeCursorHooks } from './cursor.js';
9
+ export type { HookFile } from './files.js';
10
+ export { detectHarnesses, HOOK_NAMES, type HookName, writeHooks } from './hook.js';
11
+ export { dirtyScript, gateScript, protectScript } from './scripts.js';
12
+ export { CURSOR_SKILLS_DIR, renameSkill, writeCursorSkills } from './skills.js';
7
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-setup/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agent-setup/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,KAAK,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErF,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,KAAK,QAAQ,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEnF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
@@ -1,7 +1,12 @@
1
1
  /**
2
- * Agent-setup module — the Claude Code Stop hook (step 12). This barrel is the
3
- * module's only public surface (C2): siblings import from `../agent-setup`,
4
- * never from `./hook.js` directly.
2
+ * Agent-setup module — the hooks every supported harness gets (the stop gate and
3
+ * kin). This barrel is the module's only public surface: siblings import from
4
+ * `../agent-setup`, never from `./hook.js` or a per-harness writer directly.
5
5
  */
6
- export { applyStopHook, CLAUDE_SETTINGS_FILE, stopHookCommand, writeStopHook } from './hook.js';
6
+ export { applyHooks, CLAUDE_SETTINGS_FILE, GATE_SCRIPT_FILE, PROTECT_SCRIPT_FILE, removeHooks, } from './claude.js';
7
+ export { runHooks } from './command.js';
8
+ export { applyCursorHooks, CURSOR_HOOKS_FILE, removeCursorHooks } from './cursor.js';
9
+ export { detectHarnesses, HOOK_NAMES, writeHooks } from './hook.js';
10
+ export { dirtyScript, gateScript, protectScript } from './scripts.js';
11
+ export { CURSOR_SKILLS_DIR, renameSkill, writeCursorSkills } from './skills.js';
7
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent-setup/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agent-setup/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,UAAU,EACV,oBAAoB,EACpB,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAqB,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIrF,OAAO,EAAE,eAAe,EAAE,UAAU,EAAiB,UAAU,EAAE,MAAM,WAAW,CAAC;AAEnF,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The hook scripts checkride generates into a consumer repo.
3
+ *
4
+ * checkride owns these files and overwrites them on every `agent-setup`/`init`,
5
+ * so consumer customization belongs beside them, never in them. That is also why
6
+ * the settings entry each harness gets is a stable one-liner invoking a script
7
+ * rather than the behavior inline: a refresh rewrites the script freely without
8
+ * ever clobbering an entry a human may have edited.
9
+ *
10
+ * **Every script here is one a harness's configuration could not express.** A
11
+ * generated file in someone's repo is a standing cost — reviewed, kept in sync,
12
+ * wondered about — so it is written only where config falls short. Claude Code
13
+ * takes just the gate: its `protect` is a `permissions.deny` rule and its
14
+ * `dirty` an inline command. Cursor, whose config is hooks and nothing else,
15
+ * still takes all three. The gate is the one both need, because it alone has a
16
+ * branch neither config can carry (see {@link gateTail}).
17
+ */
18
+ import { type HarnessName } from '../gate.js';
19
+ import { type PackageManager } from '../pm/index.js';
20
+ /**
21
+ * The gate script: `cd` to the repo, hand off to `checkride gate`, and translate
22
+ * the result into the harness's protocol.
23
+ *
24
+ * `dirtyGuard` (on when the `dirty` hook is written alongside — the default)
25
+ * makes the gate conditional on the edit marker, so pure-conversation turns
26
+ * don't pay for a full pipeline run. Without the marker hook the guard would
27
+ * disarm the gate entirely, so a `--hook gate` selection writes it unguarded.
28
+ *
29
+ * `preflight` is the repo's own script, from `gate.preflight` in
30
+ * checkride.config.json, baked in here rather than looked up at run time — see
31
+ * {@link preflight} and `../gate.ts` `gatePreflight`. It runs *before* the edit
32
+ * marker is consulted, because a repo that cannot run the gate at all wants to
33
+ * say so on every turn, not only on the ones that edited a file.
34
+ */
35
+ export declare function gateScript(pm: PackageManager, opts: {
36
+ harness: HarnessName;
37
+ dirtyGuard?: boolean;
38
+ preflight?: string;
39
+ }): string;
40
+ /**
41
+ * The dirty script: mark that this turn edited a file. A stop hook fires on
42
+ * every turn, including pure-conversation ones; the marker is what lets the gate
43
+ * skip those instead of taxing every reply with a full pipeline run.
44
+ *
45
+ * It exits 0 unconditionally. A failure to record an edit must never block the
46
+ * edit itself — the cost of a missed marker is one skipped gate, and the cost of
47
+ * a hard failure here is a repo where no file can be written.
48
+ */
49
+ export declare function dirtyScript(): string;
50
+ /**
51
+ * The `protect` deny script: "never add to the baseline to make a check pass" as
52
+ * enforcement, not README advice. A Node script (not sh) because the hook
53
+ * protocol is JSON on stdin, and every checkride repo has node by construction;
54
+ * `.cjs` so it runs regardless of the repo's module type. Only edit tools are
55
+ * matched — reads are never denied, because triage depends on reading `.check/`
56
+ * artifacts.
57
+ *
58
+ * Two Cursor events land here. `preToolUse` carries a file-tool call, whose
59
+ * target is read from {@link PATH_KEYS}. `beforeShellExecution` carries a
60
+ * command line, which is scanned for a write *to* an accounting path — the gap
61
+ * a tool-name matcher cannot close, since `echo … > checkride.baseline.json` is
62
+ * a shell call and not a `Write`.
63
+ *
64
+ * The command scan is deliberately timid, because a guard that fires on a wrong
65
+ * parse is worse than a known hole. It denies only on demonstrated write intent
66
+ * — a `>`/`>>` redirect target, or a positional argument of a known mutating
67
+ * verb — and anything it cannot read that way is allowed. `cat`, `grep`, `jq`
68
+ * and `cp … /tmp/x` over `.check/` all pass, which they must: triage reads those
69
+ * artifacts. The hook's own `matcher` narrows the input further, so a command
70
+ * that never names an accounting path is not parsed at all.
71
+ *
72
+ * **Cursor only.** Claude Code enforces the same paths through
73
+ * `permissions.deny`, which is checked below the hook layer and costs nothing
74
+ * per tool call, so it needs no script. Cursor has no documented equivalent —
75
+ * its config is hooks — so the script survives for the harness that still
76
+ * requires one. If Cursor grows a file-path deny list, this file goes away.
77
+ * (Claude Code's deny rules have the same shell-redirect hole and no script to
78
+ * close it with; that half of the gap is still open. See docs/cursor.md.)
79
+ */
80
+ export declare function protectScript(): string;
81
+ //# sourceMappingURL=scripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scripts.d.ts","sourceRoot":"","sources":["../../src/agent-setup/scripts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAgC,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAe,KAAK,cAAc,EAAa,MAAM,gBAAgB,CAAC;AA4T7E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,cAAc,EAClB,IAAI,EAAE;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE,MAAM,CAuBR;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAepC;AA6DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,aAAa,IAAI,MAAM,CA+ItC"}