plumbbob 0.9.3 → 0.9.5

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 (278) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +15 -13
  3. package/dist/cli-core.js +19 -2
  4. package/dist/lib/check.js +46 -13
  5. package/dist/lib/intent.js +1 -1
  6. package/dist/lib/latch.js +3 -3
  7. package/dist/lib/reentry.js +70 -0
  8. package/dist/verbs/agent.js +2 -2
  9. package/dist/verbs/doctor.js +4 -4
  10. package/dist/verbs/finish.js +1 -1
  11. package/dist/verbs/recover.js +297 -0
  12. package/dist/verbs/revert.js +2 -2
  13. package/dist/verbs/spike.js +8 -2
  14. package/hooks/post-edit.sh +4 -4
  15. package/hooks/pre-bash-commit.sh +3 -3
  16. package/node_modules/checkride/.claude-plugin/plugin.json +11 -0
  17. package/node_modules/checkride/CHANGELOG.md +1003 -0
  18. package/node_modules/checkride/LICENSE +201 -21
  19. package/node_modules/checkride/README.md +171 -30
  20. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts +15 -0
  21. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts.map +1 -0
  22. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js +17 -0
  23. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js.map +1 -0
  24. package/node_modules/checkride/dist/adapters.d.ts +18 -6
  25. package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
  26. package/node_modules/checkride/dist/adapters.js +42 -23
  27. package/node_modules/checkride/dist/adapters.js.map +1 -1
  28. package/node_modules/checkride/dist/agent-setup/claude.d.ts +88 -0
  29. package/node_modules/checkride/dist/agent-setup/claude.d.ts.map +1 -0
  30. package/node_modules/checkride/dist/agent-setup/claude.js +305 -0
  31. package/node_modules/checkride/dist/agent-setup/claude.js.map +1 -0
  32. package/node_modules/checkride/dist/agent-setup/command.d.ts +43 -0
  33. package/node_modules/checkride/dist/agent-setup/command.d.ts.map +1 -0
  34. package/node_modules/checkride/dist/agent-setup/command.js +77 -0
  35. package/node_modules/checkride/dist/agent-setup/command.js.map +1 -0
  36. package/node_modules/checkride/dist/agent-setup/cursor.d.ts +61 -0
  37. package/node_modules/checkride/dist/agent-setup/cursor.d.ts.map +1 -0
  38. package/node_modules/checkride/dist/agent-setup/cursor.js +189 -0
  39. package/node_modules/checkride/dist/agent-setup/cursor.js.map +1 -0
  40. package/node_modules/checkride/dist/agent-setup/files.d.ts +50 -0
  41. package/node_modules/checkride/dist/agent-setup/files.d.ts.map +1 -0
  42. package/node_modules/checkride/dist/agent-setup/files.js +80 -0
  43. package/node_modules/checkride/dist/agent-setup/files.js.map +1 -0
  44. package/node_modules/checkride/dist/agent-setup/harness.d.ts +101 -0
  45. package/node_modules/checkride/dist/agent-setup/harness.d.ts.map +1 -0
  46. package/node_modules/checkride/dist/agent-setup/harness.js +84 -0
  47. package/node_modules/checkride/dist/agent-setup/harness.js.map +1 -0
  48. package/node_modules/checkride/dist/agent-setup/hook.d.ts +45 -52
  49. package/node_modules/checkride/dist/agent-setup/hook.d.ts.map +1 -1
  50. package/node_modules/checkride/dist/agent-setup/hook.js +64 -95
  51. package/node_modules/checkride/dist/agent-setup/hook.js.map +1 -1
  52. package/node_modules/checkride/dist/agent-setup/index.d.ts +10 -4
  53. package/node_modules/checkride/dist/agent-setup/index.d.ts.map +1 -1
  54. package/node_modules/checkride/dist/agent-setup/index.js +9 -4
  55. package/node_modules/checkride/dist/agent-setup/index.js.map +1 -1
  56. package/node_modules/checkride/dist/agent-setup/scripts.d.ts +58 -0
  57. package/node_modules/checkride/dist/agent-setup/scripts.d.ts.map +1 -0
  58. package/node_modules/checkride/dist/agent-setup/scripts.js +299 -0
  59. package/node_modules/checkride/dist/agent-setup/scripts.js.map +1 -0
  60. package/node_modules/checkride/dist/agent-setup/skills.d.ts +31 -0
  61. package/node_modules/checkride/dist/agent-setup/skills.d.ts.map +1 -0
  62. package/node_modules/checkride/dist/agent-setup/skills.js +56 -0
  63. package/node_modules/checkride/dist/agent-setup/skills.js.map +1 -0
  64. package/node_modules/checkride/dist/artifacts/configured.d.ts +30 -0
  65. package/node_modules/checkride/dist/artifacts/configured.d.ts.map +1 -0
  66. package/node_modules/checkride/dist/artifacts/configured.js +45 -0
  67. package/node_modules/checkride/dist/artifacts/configured.js.map +1 -0
  68. package/node_modules/checkride/dist/artifacts/format.d.ts +33 -0
  69. package/node_modules/checkride/dist/artifacts/format.d.ts.map +1 -0
  70. package/node_modules/checkride/dist/artifacts/format.js +56 -0
  71. package/node_modules/checkride/dist/artifacts/format.js.map +1 -0
  72. package/node_modules/checkride/dist/artifacts/freshness.d.ts +32 -0
  73. package/node_modules/checkride/dist/artifacts/freshness.d.ts.map +1 -0
  74. package/node_modules/checkride/dist/artifacts/freshness.js +37 -0
  75. package/node_modules/checkride/dist/artifacts/freshness.js.map +1 -0
  76. package/node_modules/checkride/dist/artifacts/index.d.ts +22 -0
  77. package/node_modules/checkride/dist/artifacts/index.d.ts.map +1 -0
  78. package/node_modules/checkride/dist/artifacts/index.js +19 -0
  79. package/node_modules/checkride/dist/artifacts/index.js.map +1 -0
  80. package/node_modules/checkride/dist/artifacts/json.d.ts +31 -0
  81. package/node_modules/checkride/dist/artifacts/json.d.ts.map +1 -0
  82. package/node_modules/checkride/dist/artifacts/json.js +47 -0
  83. package/node_modules/checkride/dist/artifacts/json.js.map +1 -0
  84. package/node_modules/checkride/dist/artifacts/raw.d.ts +60 -0
  85. package/node_modules/checkride/dist/artifacts/raw.d.ts.map +1 -0
  86. package/node_modules/checkride/dist/artifacts/raw.js +91 -0
  87. package/node_modules/checkride/dist/artifacts/raw.js.map +1 -0
  88. package/node_modules/checkride/dist/artifacts/summary.d.ts +69 -0
  89. package/node_modules/checkride/dist/artifacts/summary.d.ts.map +1 -0
  90. package/node_modules/checkride/dist/artifacts/summary.js +108 -0
  91. package/node_modules/checkride/dist/artifacts/summary.js.map +1 -0
  92. package/node_modules/checkride/dist/atomic.d.ts +16 -1
  93. package/node_modules/checkride/dist/atomic.d.ts.map +1 -1
  94. package/node_modules/checkride/dist/atomic.js +25 -3
  95. package/node_modules/checkride/dist/atomic.js.map +1 -1
  96. package/node_modules/checkride/dist/baseline/fallow.d.ts +9 -5
  97. package/node_modules/checkride/dist/baseline/fallow.d.ts.map +1 -1
  98. package/node_modules/checkride/dist/baseline/fallow.js +161 -58
  99. package/node_modules/checkride/dist/baseline/fallow.js.map +1 -1
  100. package/node_modules/checkride/dist/baseline/fingerprint.d.ts +7 -7
  101. package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
  102. package/node_modules/checkride/dist/baseline/fingerprint.js +16 -19
  103. package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
  104. package/node_modules/checkride/dist/baseline/index.d.ts +4 -4
  105. package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
  106. package/node_modules/checkride/dist/baseline/index.js +4 -4
  107. package/node_modules/checkride/dist/baseline/index.js.map +1 -1
  108. package/node_modules/checkride/dist/baseline/store.d.ts +12 -4
  109. package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -1
  110. package/node_modules/checkride/dist/baseline/store.js +16 -9
  111. package/node_modules/checkride/dist/baseline/store.js.map +1 -1
  112. package/node_modules/checkride/dist/baseline-command.d.ts +5 -5
  113. package/node_modules/checkride/dist/baseline-command.js +7 -7
  114. package/node_modules/checkride/dist/baseline-command.js.map +1 -1
  115. package/node_modules/checkride/dist/cli.d.ts +17 -4
  116. package/node_modules/checkride/dist/cli.d.ts.map +1 -1
  117. package/node_modules/checkride/dist/cli.js +259 -18
  118. package/node_modules/checkride/dist/cli.js.map +1 -1
  119. package/node_modules/checkride/dist/config.d.ts +84 -8
  120. package/node_modules/checkride/dist/config.d.ts.map +1 -1
  121. package/node_modules/checkride/dist/config.js +122 -18
  122. package/node_modules/checkride/dist/config.js.map +1 -1
  123. package/node_modules/checkride/dist/digest/digest.d.ts +5 -5
  124. package/node_modules/checkride/dist/digest/digest.js +5 -5
  125. package/node_modules/checkride/dist/digest/index.d.ts +2 -2
  126. package/node_modules/checkride/dist/digest/index.js +2 -2
  127. package/node_modules/checkride/dist/doctor.d.ts +25 -6
  128. package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
  129. package/node_modules/checkride/dist/doctor.js +193 -27
  130. package/node_modules/checkride/dist/doctor.js.map +1 -1
  131. package/node_modules/checkride/dist/gate.d.ts +135 -0
  132. package/node_modules/checkride/dist/gate.d.ts.map +1 -0
  133. package/node_modules/checkride/dist/gate.js +490 -0
  134. package/node_modules/checkride/dist/gate.js.map +1 -0
  135. package/node_modules/checkride/dist/init.d.ts +72 -12
  136. package/node_modules/checkride/dist/init.d.ts.map +1 -1
  137. package/node_modules/checkride/dist/init.js +324 -81
  138. package/node_modules/checkride/dist/init.js.map +1 -1
  139. package/node_modules/checkride/dist/json.d.ts +21 -0
  140. package/node_modules/checkride/dist/json.d.ts.map +1 -0
  141. package/node_modules/checkride/dist/json.js +21 -0
  142. package/node_modules/checkride/dist/json.js.map +1 -0
  143. package/node_modules/checkride/dist/links.d.ts +31 -5
  144. package/node_modules/checkride/dist/links.d.ts.map +1 -1
  145. package/node_modules/checkride/dist/links.js +141 -32
  146. package/node_modules/checkride/dist/links.js.map +1 -1
  147. package/node_modules/checkride/dist/node-pin.d.ts +129 -0
  148. package/node_modules/checkride/dist/node-pin.d.ts.map +1 -0
  149. package/node_modules/checkride/dist/node-pin.js +211 -0
  150. package/node_modules/checkride/dist/node-pin.js.map +1 -0
  151. package/node_modules/checkride/dist/orchestrator.d.ts +40 -10
  152. package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
  153. package/node_modules/checkride/dist/orchestrator.js +196 -102
  154. package/node_modules/checkride/dist/orchestrator.js.map +1 -1
  155. package/node_modules/checkride/dist/pack.d.ts +8 -9
  156. package/node_modules/checkride/dist/pack.d.ts.map +1 -1
  157. package/node_modules/checkride/dist/pack.js +53 -17
  158. package/node_modules/checkride/dist/pack.js.map +1 -1
  159. package/node_modules/checkride/dist/pm/detect.d.ts +6 -1
  160. package/node_modules/checkride/dist/pm/detect.d.ts.map +1 -1
  161. package/node_modules/checkride/dist/pm/detect.js +6 -1
  162. package/node_modules/checkride/dist/pm/detect.js.map +1 -1
  163. package/node_modules/checkride/dist/pm/index.d.ts +6 -2
  164. package/node_modules/checkride/dist/pm/index.d.ts.map +1 -1
  165. package/node_modules/checkride/dist/pm/index.js +6 -2
  166. package/node_modules/checkride/dist/pm/index.js.map +1 -1
  167. package/node_modules/checkride/dist/pm/launch.d.ts +51 -0
  168. package/node_modules/checkride/dist/pm/launch.d.ts.map +1 -0
  169. package/node_modules/checkride/dist/pm/launch.js +92 -0
  170. package/node_modules/checkride/dist/pm/launch.js.map +1 -0
  171. package/node_modules/checkride/dist/pm/tools.d.ts +73 -0
  172. package/node_modules/checkride/dist/pm/tools.d.ts.map +1 -0
  173. package/node_modules/checkride/dist/pm/tools.js +124 -0
  174. package/node_modules/checkride/dist/pm/tools.js.map +1 -0
  175. package/node_modules/checkride/dist/pm/translate.d.ts +35 -9
  176. package/node_modules/checkride/dist/pm/translate.d.ts.map +1 -1
  177. package/node_modules/checkride/dist/pm/translate.js +78 -18
  178. package/node_modules/checkride/dist/pm/translate.js.map +1 -1
  179. package/node_modules/checkride/dist/proc.d.ts +30 -0
  180. package/node_modules/checkride/dist/proc.d.ts.map +1 -0
  181. package/node_modules/checkride/dist/proc.js +42 -0
  182. package/node_modules/checkride/dist/proc.js.map +1 -0
  183. package/node_modules/checkride/dist/qa/cli.d.ts +20 -0
  184. package/node_modules/checkride/dist/qa/cli.d.ts.map +1 -0
  185. package/node_modules/checkride/dist/qa/cli.js +24 -0
  186. package/node_modules/checkride/dist/qa/cli.js.map +1 -0
  187. package/node_modules/checkride/dist/qa/dead.d.ts +39 -0
  188. package/node_modules/checkride/dist/qa/dead.d.ts.map +1 -0
  189. package/node_modules/checkride/dist/qa/dead.js +88 -0
  190. package/node_modules/checkride/dist/qa/dead.js.map +1 -0
  191. package/node_modules/checkride/dist/qa/dupes.d.ts +45 -0
  192. package/node_modules/checkride/dist/qa/dupes.d.ts.map +1 -0
  193. package/node_modules/checkride/dist/qa/dupes.js +62 -0
  194. package/node_modules/checkride/dist/qa/dupes.js.map +1 -0
  195. package/node_modules/checkride/dist/qa/health.d.ts +85 -0
  196. package/node_modules/checkride/dist/qa/health.d.ts.map +1 -0
  197. package/node_modules/checkride/dist/qa/health.js +109 -0
  198. package/node_modules/checkride/dist/qa/health.js.map +1 -0
  199. package/node_modules/checkride/dist/qa/index.d.ts +23 -0
  200. package/node_modules/checkride/dist/qa/index.d.ts.map +1 -0
  201. package/node_modules/checkride/dist/qa/index.js +22 -0
  202. package/node_modules/checkride/dist/qa/index.js.map +1 -0
  203. package/node_modules/checkride/dist/qa/mutation.d.ts +80 -0
  204. package/node_modules/checkride/dist/qa/mutation.d.ts.map +1 -0
  205. package/node_modules/checkride/dist/qa/mutation.js +195 -0
  206. package/node_modules/checkride/dist/qa/mutation.js.map +1 -0
  207. package/node_modules/checkride/dist/qa/qa.d.ts +71 -0
  208. package/node_modules/checkride/dist/qa/qa.d.ts.map +1 -0
  209. package/node_modules/checkride/dist/qa/qa.js +158 -0
  210. package/node_modules/checkride/dist/qa/qa.js.map +1 -0
  211. package/node_modules/checkride/dist/qa/read.d.ts +40 -0
  212. package/node_modules/checkride/dist/qa/read.d.ts.map +1 -0
  213. package/node_modules/checkride/dist/qa/read.js +47 -0
  214. package/node_modules/checkride/dist/qa/read.js.map +1 -0
  215. package/node_modules/checkride/dist/qa/render.d.ts +26 -0
  216. package/node_modules/checkride/dist/qa/render.d.ts.map +1 -0
  217. package/node_modules/checkride/dist/qa/render.js +310 -0
  218. package/node_modules/checkride/dist/qa/render.js.map +1 -0
  219. package/node_modules/checkride/dist/security.d.ts +45 -0
  220. package/node_modules/checkride/dist/security.d.ts.map +1 -0
  221. package/node_modules/checkride/dist/security.js +86 -0
  222. package/node_modules/checkride/dist/security.js.map +1 -0
  223. package/node_modules/checkride/dist/smoke.d.ts +5 -5
  224. package/node_modules/checkride/dist/smoke.js +5 -5
  225. package/node_modules/checkride/dist/snippets.d.ts +26 -29
  226. package/node_modules/checkride/dist/snippets.d.ts.map +1 -1
  227. package/node_modules/checkride/dist/snippets.js +26 -30
  228. package/node_modules/checkride/dist/snippets.js.map +1 -1
  229. package/node_modules/checkride/dist/tool-json.d.ts +33 -0
  230. package/node_modules/checkride/dist/tool-json.d.ts.map +1 -0
  231. package/node_modules/checkride/dist/tool-json.js +58 -0
  232. package/node_modules/checkride/dist/tool-json.js.map +1 -0
  233. package/node_modules/checkride/dist/triage/cli.d.ts +21 -0
  234. package/node_modules/checkride/dist/triage/cli.d.ts.map +1 -0
  235. package/node_modules/checkride/dist/triage/cli.js +26 -0
  236. package/node_modules/checkride/dist/triage/cli.js.map +1 -0
  237. package/node_modules/checkride/dist/triage/doctor-fold.d.ts +51 -0
  238. package/node_modules/checkride/dist/triage/doctor-fold.d.ts.map +1 -0
  239. package/node_modules/checkride/dist/triage/doctor-fold.js +88 -0
  240. package/node_modules/checkride/dist/triage/doctor-fold.js.map +1 -0
  241. package/node_modules/checkride/dist/triage/env.d.ts +54 -0
  242. package/node_modules/checkride/dist/triage/env.d.ts.map +1 -0
  243. package/node_modules/checkride/dist/triage/env.js +81 -0
  244. package/node_modules/checkride/dist/triage/env.js.map +1 -0
  245. package/node_modules/checkride/dist/triage/gate.d.ts +61 -0
  246. package/node_modules/checkride/dist/triage/gate.d.ts.map +1 -0
  247. package/node_modules/checkride/dist/triage/gate.js +121 -0
  248. package/node_modules/checkride/dist/triage/gate.js.map +1 -0
  249. package/node_modules/checkride/dist/triage/index.d.ts +22 -0
  250. package/node_modules/checkride/dist/triage/index.d.ts.map +1 -0
  251. package/node_modules/checkride/dist/triage/index.js +20 -0
  252. package/node_modules/checkride/dist/triage/index.js.map +1 -0
  253. package/node_modules/checkride/dist/triage/render.d.ts +19 -0
  254. package/node_modules/checkride/dist/triage/render.d.ts.map +1 -0
  255. package/node_modules/checkride/dist/triage/render.js +419 -0
  256. package/node_modules/checkride/dist/triage/render.js.map +1 -0
  257. package/node_modules/checkride/dist/triage/triage.d.ts +83 -0
  258. package/node_modules/checkride/dist/triage/triage.d.ts.map +1 -0
  259. package/node_modules/checkride/dist/triage/triage.js +131 -0
  260. package/node_modules/checkride/dist/triage/triage.js.map +1 -0
  261. package/node_modules/checkride/package.json +17 -15
  262. package/node_modules/checkride/schema/checkride.config.schema.json +62 -5
  263. package/node_modules/checkride/schema/checkride.summary.schema.json +1 -1
  264. package/node_modules/checkride/skills/check/SKILL.md +257 -0
  265. package/node_modules/checkride/skills/qa/SKILL.md +231 -0
  266. package/node_modules/checkride/templates/shared/cspell.json +1 -0
  267. package/node_modules/checkride/templates/shared/oxlintrc.json +1 -1
  268. package/package.json +2 -2
  269. package/skills/build/SKILL.md +23 -19
  270. package/skills/finish/SKILL.md +3 -1
  271. package/skills/harvest/SKILL.md +2 -1
  272. package/skills/plan/SKILL.md +8 -7
  273. package/skills/recover/SKILL.md +28 -0
  274. package/skills/refine/SKILL.md +5 -4
  275. package/skills/spike/SKILL.md +1 -1
  276. package/skills/step/SKILL.md +4 -4
  277. package/skills/verify/SKILL.md +19 -14
  278. package/templates/intent.md +8 -7
@@ -0,0 +1,490 @@
1
+ /**
2
+ * `checkride gate` — the stop-gate verdict, harness-neutral.
3
+ *
4
+ * Every agent harness offers some "the turn is ending" hook, and checkride's
5
+ * gate hangs off it: run the repo's `check` script, and while it is red, refuse
6
+ * to let the turn finish. What differs between harnesses is only the *wire
7
+ * format* of that refusal — Claude Code reads stderr and blocks on exit 2,
8
+ * Cursor reads a `followup_message` on stdout and submits it as the next turn.
9
+ * The decision itself (is it dirty, is it green, which artifact should the agent
10
+ * read) is identical, so it lives here once and the generated hook scripts
11
+ * become two-line adapters that name their harness.
12
+ *
13
+ * That split is the point. Before this command, the whole body was duplicated
14
+ * shell inside `.claude/hooks/checkride-gate.sh`, untestable outside an e2e run
15
+ * and impossible to share with a second harness.
16
+ *
17
+ * The gate answers three verdicts, not two. Green and red are the pipeline's;
18
+ * the third is **could not run**, for a package manager that refused to start
19
+ * the check script at all — an `engines.node` pin the hook's Node does not
20
+ * satisfy is the common cause, and it exits non-zero exactly like a failing
21
+ * test. Reading that as red produced a permanent red no code change could clear,
22
+ * pointing at a `.check/summary.json` no run had written. It still blocks, for
23
+ * the same reason every unrunnable gate does; what changes is that it names the
24
+ * cause instead of naming an artifact. See `./pm/launch.ts` for the
25
+ * classification and `./node-pin.ts` for the alignment that avoids it.
26
+ *
27
+ * Not to be confused with `../triage/gate.ts`, which also runs the `check`
28
+ * script: that one runs it *verbatim* as a reader's preflight and classifies the
29
+ * result for a report. This one appends `--strict --digest` because it IS the
30
+ * gate, and its output is a verdict for the harness, not prose for a human.
31
+ */
32
+ import { spawn } from 'node:child_process';
33
+ import { existsSync, readFileSync, rmSync } from 'node:fs';
34
+ import { join } from 'node:path';
35
+ import { formatDuration, readSummary } from './artifacts/index.js';
36
+ import { loadConfig } from './config.js';
37
+ import { DIGEST_FILE } from './digest/index.js';
38
+ import { alignNode, NODE_BIN_VAR, realPinEnv, withNodeBin } from './node-pin.js';
39
+ import { detectPackageManager, launchRefusal, runScript, SPAWN_FAILED_MARKER, } from './pm/index.js';
40
+ /**
41
+ * The edit marker: touched by the harness's "a file changed" hook, checked here
42
+ * under `--if-dirty`, and cleared by a green gate. Dot-named so it can never
43
+ * collide with a slot's `<slot>.json`/`<slot>.stdout.txt` artifacts, which the
44
+ * orchestrator deletes per slot before a re-run — the marker must survive every
45
+ * run.
46
+ *
47
+ * It lives here, not in `agent-setup`, because the gate is what reads and clears
48
+ * it; the hook writers import it from this module to build the touch command.
49
+ */
50
+ export const DIRTY_MARKER = '.check/.dirty';
51
+ /** Where the gate points a red agent when `--digest` wrote nothing. */
52
+ const SUMMARY_PATH = '.check/summary.json';
53
+ /**
54
+ * Cursor's own hook config. It lives here rather than in `agent-setup/cursor.ts`
55
+ * for the same reason {@link DIRTY_MARKER} does: the gate *reads* it (see
56
+ * {@link deferredToCursor}), and the writer importing from the gate is the
57
+ * direction that has no cycle. `agent-setup/cursor.ts` re-exports it.
58
+ */
59
+ export const CURSOR_HOOKS_FILE = '.cursor/hooks.json';
60
+ /**
61
+ * What a registered checkride gate looks like inside a harness's hook config.
62
+ * Both harnesses name the script the same, so finding it in Cursor's config is
63
+ * enough to know Cursor has a native gate of its own.
64
+ */
65
+ const GATE_SCRIPT_SENTINEL = 'checkride-gate.sh';
66
+ /** Every harness whose stop-hook protocol the gate can speak. */
67
+ export const HARNESS_NAMES = ['claude', 'cursor'];
68
+ /** Script name every checkride repo exposes; `checkride init` writes it. */
69
+ const CHECK_SCRIPT = 'check';
70
+ const spawnForward = (command, args, opts) => new Promise((resolve) => {
71
+ const proc = spawn(command, [...args], {
72
+ cwd: opts.cwd,
73
+ stdio: ['ignore', 'pipe', 'pipe'],
74
+ env: { ...opts.env, FORCE_COLOR: '0', NO_COLOR: '1' },
75
+ });
76
+ proc.stdout.setEncoding('utf8');
77
+ proc.stderr.setEncoding('utf8');
78
+ proc.stdout.on('data', (chunk) => opts.stderr.write(chunk));
79
+ proc.stderr.on('data', (chunk) => opts.stderr.write(chunk));
80
+ // A gate that cannot spawn its package manager is not a crash: the harness
81
+ // gets a verdict it can act on rather than a stack trace. The message goes
82
+ // to the stream so it is both visible and classifiable — a spawn failure
83
+ // that printed nothing at all was reported as a red with no explanation.
84
+ proc.on('error', (err) => {
85
+ opts.stderr.write(`${SPAWN_FAILED_MARKER} \`${command}\`: ${err.message}\n`);
86
+ resolve(null);
87
+ });
88
+ proc.on('close', (code) => resolve(code));
89
+ });
90
+ /**
91
+ * How much of the child's output to keep for {@link launchRefusal}.
92
+ *
93
+ * The **head**, not the tail: a package manager that refuses to launch says so
94
+ * before anything else runs, so the evidence is always in the first bytes. A
95
+ * check that fails after this much output is a pipeline red, which needs no
96
+ * classification.
97
+ */
98
+ const CAPTURE_LIMIT = 8 * 1024;
99
+ /** An `Out` that forwards everything and remembers the beginning. */
100
+ function recording(out) {
101
+ let kept = '';
102
+ return {
103
+ write: (chunk) => {
104
+ if (kept.length < CAPTURE_LIMIT)
105
+ kept += chunk;
106
+ return out.write(chunk);
107
+ },
108
+ text: () => kept,
109
+ };
110
+ }
111
+ /**
112
+ * True when this `--harness claude` invocation is really Cursor running the
113
+ * repo's `.claude/settings.json` hooks, *and* Cursor has a native checkride gate
114
+ * of its own that will run for the same turn.
115
+ *
116
+ * Cursor loads third-party (Claude Code) hook configs when "Include third-party
117
+ * Plugins, Skills, and other configs" is on, maps `Stop` onto `stop`, and — the
118
+ * load-bearing sentence — runs **all** matching hooks from **every** source. A
119
+ * repo wired for both harnesses therefore fires two full pipelines into one
120
+ * `.check/` directory, concurrently and with nothing to serialize them, where
121
+ * the orchestrator clears each slot's artifacts before re-running it.
122
+ *
123
+ * So one of the two has to stand down, and it is this one: under Cursor the
124
+ * native `.cursor/hooks.json` gate is the only one that can answer in Cursor's
125
+ * protocol, which makes it authoritative there.
126
+ *
127
+ * Deliberately narrow — it defers only when a Cursor gate is *registered*, not
128
+ * merely when Cursor is running, so the failure mode of a stale environment
129
+ * variable is a duplicate run (today's behavior) rather than no gate at all.
130
+ */
131
+ function deferredToCursor(cwd, env) {
132
+ if (!env['CURSOR_PROJECT_DIR'])
133
+ return false;
134
+ try {
135
+ return readFileSync(join(cwd, CURSOR_HOOKS_FILE), 'utf8').includes(GATE_SCRIPT_SENTINEL);
136
+ }
137
+ catch {
138
+ return false;
139
+ }
140
+ }
141
+ /**
142
+ * The gate's `check`-script invocation for `pm` (the alias `agent-setup`
143
+ * ensures exists). The hook IS a gate, so it runs `--strict` (zero checks
144
+ * running is exit 2, not a pass — docs/contract.md) and `--digest` (the
145
+ * token-bounded failure excerpt is a far better landing spot for an agent than
146
+ * raw summary.json). npm alone needs `--` to reach the script with flags;
147
+ * pnpm/yarn/bun forward them directly.
148
+ */
149
+ export function checkArgs(pm, profile = null) {
150
+ return [
151
+ 'run',
152
+ CHECK_SCRIPT,
153
+ ...(pm === 'npm' ? ['--'] : []),
154
+ '--strict',
155
+ '--digest',
156
+ ...profileArgs(profile),
157
+ ];
158
+ }
159
+ /**
160
+ * The profile's flags, appended **after** the check script's own.
161
+ *
162
+ * Last wins in `parseArgs`, so a repo whose `check` script already carries
163
+ * `--only` has the profile override it rather than fight it — the profile is the
164
+ * more specific statement, made about this hook in particular.
165
+ */
166
+ function profileArgs(profile) {
167
+ if (profile === null)
168
+ return [];
169
+ return [
170
+ ...(profile.only && profile.only.length > 0 ? ['--only', profile.only.join(',')] : []),
171
+ ...(profile.skip && profile.skip.length > 0 ? ['--skip', profile.skip.join(',')] : []),
172
+ ...(profile.changed === true ? ['--changed'] : []),
173
+ ];
174
+ }
175
+ /**
176
+ * The repo's gate profile, or `null` when it configures none and the gate should
177
+ * run the whole check.
178
+ *
179
+ * A profile with nothing in it is `null` too: `"gate": {}` narrows nothing, and
180
+ * carrying it forward would put "not the full check" on a verdict that *was* the
181
+ * full check.
182
+ */
183
+ export function gateProfile(cwd, config = loadConfig(cwd)) {
184
+ const profile = config?.gate;
185
+ if (!profile)
186
+ return null;
187
+ return profileArgs(profile).length > 0 ? profile : null;
188
+ }
189
+ /**
190
+ * How a narrowed run must describe itself — appended to every verdict the gate
191
+ * produces while a profile is active.
192
+ *
193
+ * This is the price of the profile and it is not optional. A gate that runs two
194
+ * of eighteen slots and reports a bare `✔ green` has told the reader the work is
195
+ * done, which is exactly what it does not know. Naming the profile turns a
196
+ * silent partial pass into a stated one.
197
+ */
198
+ function profileClause(profile) {
199
+ if (profile === null)
200
+ return null;
201
+ const parts = [
202
+ profile.only && profile.only.length > 0 ? `only ${profile.only.join(', ')}` : null,
203
+ profile.skip && profile.skip.length > 0 ? `without ${profile.skip.join(', ')}` : null,
204
+ profile.changed === true ? 'affected-only' : null,
205
+ ].filter((p) => p !== null);
206
+ return `gate profile: ${parts.join(', ')} — NOT the full check`;
207
+ }
208
+ /**
209
+ * Below this, naming the slowest check is noise rather than insight — every
210
+ * check in a fast repo is "the slowest" by some millisecond.
211
+ */
212
+ const SLOWEST_FLOOR_MS = 1000;
213
+ /** The checks that actually ran, in report order. */
214
+ function ranChecks(checks) {
215
+ return checks.filter((c) => c.skipped !== true);
216
+ }
217
+ /** `15 checks, slowest test 21.4s` — what a green run is worth saying about itself. */
218
+ function greenDetail(ran) {
219
+ const count = `${ran.length} check${ran.length === 1 ? '' : 's'}`;
220
+ const slowest = ran.reduce((worst, c) => (worst === null || c.duration_ms > worst.duration_ms ? c : worst), null);
221
+ if (slowest === null || slowest.duration_ms < SLOWEST_FLOOR_MS)
222
+ return count;
223
+ return `${count}, slowest ${slowest.name} ${formatDuration(slowest.duration_ms)}`;
224
+ }
225
+ /**
226
+ * Is the summary on disk the one *this* run wrote?
227
+ *
228
+ * A gate that could not run wrote none, and a report that invents "0 checks
229
+ * failed" from a missing file is exactly the vacuous green the artifact exists
230
+ * to disprove. A summary older than `startedAt` belongs to a *previous* run and
231
+ * is dropped for the same reason — not hypothetical: a check script of the shape
232
+ * `tsc --build && checkride` leaves the summary untouched when the build fails,
233
+ * so trusting whatever is on disk would report the last run's failing slots as
234
+ * this one's, confidently and wrongly.
235
+ */
236
+ function isFresh(read, startedAt) {
237
+ return read.state === 'ok' && read.mtimeMs >= startedAt;
238
+ }
239
+ /**
240
+ * What the run itself says, read back out of a summary already known to be this
241
+ * run's, or `null` when there is none. The caller still has the elapsed time,
242
+ * which is true regardless.
243
+ */
244
+ function runDetail(read, green) {
245
+ if (read.state !== 'ok')
246
+ return null;
247
+ const ran = ranChecks(read.summary.checks);
248
+ if (green)
249
+ return greenDetail(ran);
250
+ const failed = ran.filter((c) => !c.ok).map((c) => c.name);
251
+ // Red with nothing failing means the check script itself died (or --strict
252
+ // caught a vacuous run); say the honest thing rather than name no slots.
253
+ if (failed.length === 0)
254
+ return `${ran.length} checks ran, none failed — the check script itself failed`;
255
+ return `${failed.length} of ${ran.length} failed: ${failed.join(', ')}`;
256
+ }
257
+ /**
258
+ * The one line a human reads to know the gate ran, what it decided, and how long
259
+ * they waited on it.
260
+ *
261
+ * The elapsed time is the gate's own wall clock — package-manager startup,
262
+ * incremental build and all — not the pipeline's `total_duration_ms`, because
263
+ * the honest answer to "why did that pause" is the whole pause, not the part
264
+ * checkride chooses to measure.
265
+ */
266
+ function headline(verdict, elapsedMs, detail) {
267
+ return `checkride ${verdict} in ${formatDuration(elapsedMs)}${detail === null ? '' : ` — ${detail}`}`;
268
+ }
269
+ /** Join the run's own detail with the narrowing note, dropping whichever is absent. */
270
+ function detailWith(detail, profile) {
271
+ const parts = [detail, profileClause(profile)].filter((p) => p !== null);
272
+ return parts.length === 0 ? null : parts.join(' — ');
273
+ }
274
+ /** The sentence a red gate hands the agent, naming what to open first. */
275
+ function redMessage(cwd, pm, profile) {
276
+ const where = existsSync(join(cwd, '.check', DIGEST_FILE)) ? `.check/${DIGEST_FILE}` : SUMMARY_PATH;
277
+ // A narrowed red is still a red, but it is not the whole story: the slots the
278
+ // profile skipped were never asked, so fixing what it names may not be enough.
279
+ const narrowed = profile === null
280
+ ? ''
281
+ : ` This gate ran a profile, not the full check — run \`${runScript(pm, CHECK_SCRIPT)}\` for the rest.`;
282
+ return (`checkride: the gate is red — read ${where}, fix the failing slot, then finish ` +
283
+ `(do not stop while checkride is red). Run \`${pm} exec checkride triage\` for full triage.${narrowed}`);
284
+ }
285
+ /**
286
+ * The Node half of a refusal message: what this process is running, what the
287
+ * repo asked for, and the one lever that closes the gap.
288
+ *
289
+ * This clause is why the whole classification exists. The default cause of a
290
+ * refused launch is that the harness ran its hook in a non-login shell, so the
291
+ * hook got the machine's default interpreter rather than the contributor's —
292
+ * a fact no amount of reading `.check/` would ever reveal.
293
+ */
294
+ function nodeClause(alignment, running) {
295
+ const context = 'Agent harnesses run hooks in a non-login shell, so a hook gets the machine’s default ' +
296
+ 'Node rather than the one your terminal has.';
297
+ const pin = alignment?.pin ?? null;
298
+ if (pin === null) {
299
+ return (`${context} This process is on Node ${running} and the repo pins no ` +
300
+ `\`.nvmrc\`/\`.node-version\` for checkride to align to; add one, or set ${NODE_BIN_VAR} to the ` +
301
+ 'bin directory of a Node the repo accepts.');
302
+ }
303
+ return (`${context} This one is on Node ${running}, the repo pins ${pin.version} ` +
304
+ `(${pin.file}), and no matching install was found in a known version-manager layout — ` +
305
+ `so checkride could not align to it. Install that Node, or set ${NODE_BIN_VAR} to its bin directory.`);
306
+ }
307
+ /**
308
+ * The verdict for a package manager that refused to start the check script.
309
+ *
310
+ * It says the three things a red verdict would get wrong here: nothing ran, so
311
+ * `.check/` describes some earlier turn and not this one; the code is not what
312
+ * failed, so no edit will clear it; and here is the actual cause. A gate that
313
+ * sent a reader to `summary.json` for a run that never happened is the confusion
314
+ * this replaces.
315
+ */
316
+ function refusalMessage(cause, context) {
317
+ return [
318
+ `checkride: the gate could not run — ${cause}.`,
319
+ 'Nothing ran: no check executed and no artifact was written, so `.check/` holds nothing from ' +
320
+ 'this turn and the code is not what to look at.',
321
+ nodeClause(context.alignment, context.running),
322
+ `Run \`${context.pm} run check\` in a terminal to see the same failure directly.`,
323
+ ].join(' ');
324
+ }
325
+ /**
326
+ * Put the pinned Node in front of the child's `PATH`, and say so on stderr.
327
+ *
328
+ * Never silent, by rule: which interpreter the whole pipeline runs on is not
329
+ * something to change behind the reader's back, and the line is what turns a
330
+ * mysteriously-different result into an explained one. It goes to stderr with
331
+ * the rest of the run's progress rather than into the one-line verdict, so it is
332
+ * present on a red run too — which is exactly when it is worth knowing.
333
+ *
334
+ * Returns `env` unchanged when there is nothing to align, which is every repo
335
+ * that pins nothing and every hook that already arrived on the right Node.
336
+ */
337
+ function announceAlignment(alignment, env, stderr) {
338
+ if (alignment === null)
339
+ return env;
340
+ const { bin } = alignment;
341
+ if (bin === null)
342
+ return env;
343
+ const target = alignment.version ?? alignment.pin?.version ?? 'the pinned version';
344
+ const why = alignment.pin === null ? NODE_BIN_VAR : `${alignment.pin.file} pins ${alignment.pin.version}`;
345
+ stderr.write(`checkride: running the check on Node ${target} from ${bin} (${why}; this hook started on ${alignment.running}).\n`);
346
+ return withNodeBin(env, bin);
347
+ }
348
+ /**
349
+ * Classify a non-green run and phrase it.
350
+ *
351
+ * The one judgement here is whether the pipeline ran. A summary from this run
352
+ * proves it did, so on that branch nothing in the output can mean otherwise —
353
+ * the guard that keeps a check which merely *printed* a package-manager error
354
+ * code from being read as a launch refusal.
355
+ */
356
+ function failedVerdict(f) {
357
+ const refusal = f.fresh ? null : launchRefusal(f.output);
358
+ if (refusal === null) {
359
+ return {
360
+ status: headline('✘ red', f.elapsedMs, detailWith(f.fresh ? runDetail(f.summary, false) : null, f.profile)),
361
+ instruction: redMessage(f.cwd, f.pm, f.profile),
362
+ refusal: null,
363
+ };
364
+ }
365
+ // A launch refusal names no profile: nothing ran, so how much would have run
366
+ // is beside the point.
367
+ return {
368
+ status: headline('⚠ could not run', f.elapsedMs, refusal.cause),
369
+ instruction: refusalMessage(refusal.cause, { alignment: f.alignment, running: f.running, pm: f.pm }),
370
+ refusal: refusal.cause,
371
+ };
372
+ }
373
+ /**
374
+ * Answer a green run in `harness`'s protocol.
375
+ *
376
+ * Claude Code gets `{"systemMessage": …}`, which it shows the user. Without it a
377
+ * green gate is completely silent: the turn simply takes a minute longer than it
378
+ * should have, with nothing on screen to say a full pipeline just ran, which is
379
+ * indistinguishable from a hung model.
380
+ *
381
+ * Cursor gets nothing, and cannot. Its stop hook accepts one field —
382
+ * `followup_message` — and that field *submits a new turn*, so using it to
383
+ * announce a pass would put the agent back to work every time it succeeded. No
384
+ * other channel is documented for the event; see docs/cursor.md.
385
+ */
386
+ function reportGreen(harness, stdout, status) {
387
+ if (harness === 'cursor')
388
+ return;
389
+ stdout.write(`${JSON.stringify({ systemMessage: status })}\n`);
390
+ }
391
+ /**
392
+ * Answer a run that was not green in `harness`'s protocol — a pipeline red or a
393
+ * launch refusal alike, since both must block and the wire format is the same.
394
+ *
395
+ * Claude Code gets both spellings of the same verdict, because which one lands
396
+ * depends on the hook script the repo happens to have. The JSON body
397
+ * (`decision: "block"`) is what a current script forwards on its own exit 0 —
398
+ * Claude Code parses hook JSON *only* on exit 0, and that body is the one form
399
+ * that can carry a user-visible `systemMessage` alongside the block. The stderr
400
+ * line is what a script generated before that change relies on, where the block
401
+ * rides on exit 2 and stdout is ignored. Emitting both is what lets an
402
+ * already-installed hook script keep gating across the upgrade.
403
+ *
404
+ * Cursor gets `{"followup_message": …}` on stdout and **exit 0**: it reads a
405
+ * non-zero stop hook as a *failed hook* and lets the turn end anyway, so the
406
+ * verdict cannot ride on the exit code. Cursor caps those auto-followups at five
407
+ * per script by default; the hook entry `agent-setup` writes opts out
408
+ * (`loop_limit: null`), because a gate that stops replying after five turns is
409
+ * not a gate.
410
+ */
411
+ function reportRed(harness, out, verdict) {
412
+ // The agent is told what to open and what not to do; the user is told what
413
+ // happened and how long it took. Handing the user the agent's marching orders
414
+ // would bury the one line they are actually reading.
415
+ const full = `${verdict.status}\n${verdict.instruction}`;
416
+ if (harness === 'cursor') {
417
+ out.stdout.write(`${JSON.stringify({ followup_message: full })}\n`);
418
+ return 0;
419
+ }
420
+ out.stdout.write(`${JSON.stringify({ decision: 'block', reason: full, systemMessage: verdict.status })}\n`);
421
+ out.stderr.write(`${full}\n`);
422
+ return 2;
423
+ }
424
+ function gateContext(options) {
425
+ return {
426
+ cwd: options.cwd ?? process.cwd(),
427
+ harness: options.harness ?? 'claude',
428
+ stdout: options.stdout ?? process.stdout,
429
+ stderr: options.stderr ?? process.stderr,
430
+ run: options.spawn ?? spawnForward,
431
+ env: options.env ?? process.env,
432
+ pinEnv: options.pinEnv ?? realPinEnv,
433
+ now: options.now ?? Date.now,
434
+ };
435
+ }
436
+ /**
437
+ * Run the gate and answer in `harness`'s protocol.
438
+ *
439
+ * The exit code is unchanged and stays as `docs/contract.md` promises it: 2 while
440
+ * blocked under `--harness claude`, always 0 under `--harness cursor`. What each
441
+ * harness *displays* is carried by the JSON body on stdout — see
442
+ * {@link reportGreen} and {@link reportRed} — because that is the only channel
443
+ * either harness renders for a human.
444
+ */
445
+ export async function runGate(options = {}) {
446
+ const { cwd, harness, stdout, stderr, run, env, pinEnv, now } = gateContext(options);
447
+ const marker = join(cwd, DIRTY_MARKER);
448
+ // Cursor running this repo's Claude hooks alongside its own. Stand down before
449
+ // touching the marker: the native Cursor gate owns both the verdict and the
450
+ // marker for this turn.
451
+ if (harness === 'claude' && deferredToCursor(cwd, env)) {
452
+ return { exitCode: 0, ran: false, green: true, refusal: null };
453
+ }
454
+ // No edit marker → this turn touched no files → nothing to gate. Stop hooks
455
+ // fire on every turn, including pure-conversation ones; without this the gate
456
+ // taxes every reply with a full pipeline run.
457
+ if (options.ifDirty === true && !existsSync(marker)) {
458
+ return { exitCode: 0, ran: false, green: true, refusal: null };
459
+ }
460
+ const pm = options.pm ?? detectPackageManager({ cwd });
461
+ const profile = options.profile !== undefined ? options.profile : gateProfile(cwd);
462
+ const alignment = alignNode(cwd, pinEnv);
463
+ const childEnv = announceAlignment(alignment, env, stderr);
464
+ const startedAt = now();
465
+ const output = recording(stderr);
466
+ const code = await run(pm, checkArgs(pm, profile), { cwd, stderr: output, env: childEnv });
467
+ const green = code === 0;
468
+ const summary = await readSummary(cwd);
469
+ const fresh = isFresh(summary, startedAt);
470
+ if (green) {
471
+ rmSync(marker, { force: true });
472
+ const detail = detailWith(fresh ? runDetail(summary, true) : null, profile);
473
+ reportGreen(harness, stdout, headline('✔ green', now() - startedAt, detail));
474
+ return { exitCode: 0, ran: true, green: true, refusal: null };
475
+ }
476
+ const verdict = failedVerdict({
477
+ cwd,
478
+ pm,
479
+ elapsedMs: now() - startedAt,
480
+ summary,
481
+ fresh,
482
+ output: output.text(),
483
+ alignment,
484
+ running: pinEnv.running(),
485
+ profile,
486
+ });
487
+ const exitCode = reportRed(harness, { stdout, stderr }, verdict);
488
+ return { exitCode, ran: true, green: false, refusal: verdict.refusal };
489
+ }
490
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,10 @@
12
12
  * it afterward.
13
13
  */
14
14
  import type { Adapter, Slot } from './adapters.js';
15
+ import type { HookName } from './agent-setup/index.js';
16
+ import type { HarnessName } from './gate.js';
15
17
  import type { Out } from './orchestrator.js';
18
+ import type { PackageManager } from './pm/index.js';
16
19
  export type Shape = 'flat' | 'monorepo' | 'hybrid';
17
20
  export type InitOptions = {
18
21
  cwd?: string;
@@ -25,16 +28,27 @@ export type InitOptions = {
25
28
  add?: string[] | null;
26
29
  checkrideSpec?: string;
27
30
  /**
28
- * New mode: overwrite existing files instead of refusing. Without it, `init`
29
- * refuses (exit 2) rather than clobber any file it would scaffold (D4);
30
- * existing mode is already additive-only and ignores this flag.
31
+ * Overwrite instead of refusing. Without it, `init` refuses (exit 2) rather
32
+ * than clobber any file new mode would scaffold, or an AGENTS.md stanza
33
+ * existing mode would refresh that carries local edits. Existing mode is
34
+ * otherwise additive-only, so the flag reaches nothing else there.
31
35
  */
32
36
  force?: boolean;
33
37
  /**
34
- * Write the Claude Code Stop hook to `.claude/settings.json` (step 12).
38
+ * Write the agent stop-gate hooks into each selected harness's config.
35
39
  * Opt-out: defaults to on; `--no-hook` sets it `false`.
36
40
  */
37
41
  hook?: boolean;
42
+ /** Which hooks to write (`--hook <a,b>`). Omitted → all of them. */
43
+ hooks?: readonly HookName[];
44
+ /**
45
+ * Hooks to tear out of an already-wired repo (`--remove-hook <a,b>`): the
46
+ * config entry is stripped and the generated script deleted. Composes with
47
+ * `hook: false` to remove without refreshing anything else.
48
+ */
49
+ removeHooks?: readonly HookName[];
50
+ /** Which harnesses to write them for (`--harness <a,b>`). Omitted → detected. */
51
+ harnesses?: readonly HarnessName[];
38
52
  stdout?: Out;
39
53
  slots?: readonly Slot[];
40
54
  adapters?: readonly Adapter[];
@@ -42,7 +56,7 @@ export type InitOptions = {
42
56
  probeFailures?: (slots: string[], cwd: string) => Promise<string[]>;
43
57
  /**
44
58
  * Existing mode: grandfather current debt into `checkride.baseline.json`
45
- * instead of disabling failing slots (`--baseline`, step 6 / c10). A failing
59
+ * instead of disabling failing slots (`--baseline`). A failing
46
60
  * fingerprintable slot stays enabled and is masked by the baseline; a failing
47
61
  * slot with no extractor still falls back to a `false` disable.
48
62
  */
@@ -54,6 +68,8 @@ export type InitResult = {
54
68
  mode: 'new' | 'existing';
55
69
  shape: Shape | null;
56
70
  written: string[];
71
+ /** Files deleted by `--remove-hook`. */
72
+ removed: string[];
57
73
  skipped: string[];
58
74
  disabled: string[];
59
75
  /** Slots whose failing debt was grandfathered into the baseline (`--baseline`). */
@@ -65,11 +81,37 @@ export type InventoryEntry = {
65
81
  status: 'adopted' | 'empty';
66
82
  adapter: string | null;
67
83
  };
68
- /** The agent-facing contract block, parameterized by the active checks. */
69
- export declare function buildStanza(activeSlots: readonly string[]): string;
84
+ /**
85
+ * How the stanza on disk relates to the one checkride would write:
86
+ *
87
+ * - `absent` — no stanza yet; writing one takes nothing away.
88
+ * - `pristine` — checkride's own output, untouched; refreshing it is lossless.
89
+ * Either it carries a stamp that still matches, or it predates stamping and
90
+ * its wording is one checkride shipped (see {@link LEGACY_STANZA_PREAMBLES}).
91
+ * - `edited` — stamped, but the body no longer matches its stamp: a human or an
92
+ * agent customized it, and a blind refresh would silently discard that.
93
+ * - `unstamped` — predates stamping and matches no wording checkride released,
94
+ * so it has been edited too; same protection as `edited`, and the message says
95
+ * so differently because the evidence is weaker.
96
+ */
97
+ export type StanzaState = 'absent' | 'pristine' | 'edited' | 'unstamped';
98
+ /** Classify the stanza in `content` against the `body` checkride would write. */
99
+ export declare function inspectStanza(content: string, body: string): StanzaState;
100
+ /**
101
+ * The agent-facing contract block, parameterized by the active checks and the
102
+ * repo's package manager.
103
+ *
104
+ * `pm` is not cosmetic. The stanza is a list of commands an agent is told to
105
+ * run, and `pnpm check` in an npm repo is an instruction that cannot succeed —
106
+ * the agent either invents a substitute or reports the pipeline as broken.
107
+ * Everything here routes through {@link runScript}/{@link execCommand} for that
108
+ * reason; nothing spells a launcher literally.
109
+ */
110
+ export declare function buildStanza(activeSlots: readonly string[], pm?: PackageManager): string;
70
111
  /**
71
112
  * Insert or refresh the checkride stanza in an AGENTS.md body. Idempotent:
72
- * applying twice yields identical output.
113
+ * applying twice yields identical output. It rewrites the marked region without
114
+ * looking at what was there — callers gate on {@link inspectStanza} first.
73
115
  */
74
116
  export declare function applyStanza(content: string, body: string): string;
75
117
  /** For each default (non-opt-in) slot, report whether a tool config is present. */
@@ -86,23 +128,41 @@ export declare function runInit(options: InitOptions): Promise<InitResult>;
86
128
  export type AgentSetupOptions = {
87
129
  cwd?: string;
88
130
  dryRun?: boolean;
89
- /** Write the Claude Code Stop hook (opt-out; `--no-hook`). Defaults to on. */
131
+ /** Write the agent hooks (opt-out; `--no-hook`). Defaults to on. */
90
132
  hook?: boolean;
133
+ /** Which hooks to write (`--hook <a,b>`). Omitted → all of them. */
134
+ hooks?: readonly HookName[];
135
+ /**
136
+ * Hooks to tear out (`--remove-hook <a,b>`): the config entry is stripped and
137
+ * the generated script deleted. With `hook: false` it removes those and
138
+ * refreshes nothing else.
139
+ */
140
+ removeHooks?: readonly HookName[];
141
+ /** Which harnesses to write them for (`--harness <a,b>`). Omitted → detected. */
142
+ harnesses?: readonly HarnessName[];
143
+ /**
144
+ * Refresh the AGENTS.md stanza even when it carries local edits. Without it a
145
+ * customized stanza stops the run (exit 2) instead of being overwritten.
146
+ */
147
+ force?: boolean;
91
148
  stdout?: Out;
92
149
  slots?: readonly Slot[];
93
150
  adapters?: readonly Adapter[];
94
151
  };
95
152
  export type AgentSetupResult = {
96
153
  written: string[];
154
+ /** Files deleted by `--remove-hook`. */
155
+ removed: string[];
97
156
  skipped: string[];
98
157
  exitCode: number;
99
158
  };
100
159
  /**
101
160
  * `checkride agent-setup` — wire the agent contract into an *existing* repo
102
161
  * without a full `init`: the `check` alias the hook resolves to, the AGENTS.md
103
- * stanza (the human-readable contract), and the Claude Code Stop hook (the
104
- * mechanical gate). Every write is additive and idempotent — a second run is a
105
- * no-op — and the hook is opt-out (`hook: false`).
162
+ * stanza (the human-readable contract), the stop-gate hooks for every detected
163
+ * harness (the mechanical gate), and the skills a harness cannot get from the
164
+ * bundled plugin. Every write is additive and idempotent — a second run is a
165
+ * no-op — and the hooks are opt-out (`hook: false`).
106
166
  */
107
167
  export declare function runAgentSetup(options: AgentSetupOptions): Promise<AgentSetupResult>;
108
168
  //# sourceMappingURL=init.d.ts.map