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,7 +1,7 @@
1
1
  {
2
2
  "name": "plumbbob",
3
3
  "displayName": "PlumbBob",
4
- "version": "0.9.3",
4
+ "version": "0.10.0",
5
5
  "description": "Attention-first build process — driver skills + a CLI that keep you the decider: guidance on the work, a latch on the record.",
6
6
  "author": { "name": "Rob McLarty", "email": "hello@robmclarty.com", "url": "https://robmclarty.com" },
7
7
  "homepage": "https://github.com/robmclarty/plumbbob#readme",
package/README.md CHANGED
@@ -10,45 +10,46 @@
10
10
  <a href="https://robmclarty.github.io/plumbbob/api.html">API reference</a>
11
11
  </p>
12
12
 
13
- PlumbBob is a Claude Code plugin — twelve skills and a small CLI — that runs
13
+ PlumbBob is a Claude Code plugin (thirteen skills and a small CLI) that runs
14
14
  LLM-assisted coding as a loop you control. You and the model settle the plan in a file
15
15
  *before* any code; then the model builds one small step at a time and **stops after
16
16
  each one**, waiting for you to read the diff and approve it before anything is
17
- committed. It's built for the small-to-medium work that fills most days — a feature, a
18
- bug, a refactor — where a fully autonomous build is overkill but freestyle prompting
17
+ committed. It's built for the small-to-medium work that fills most days (a feature, a
18
+ bug, a refactor) where a fully autonomous build is overkill but freestyle prompting
19
19
  leaves you dragged behind the model, reacting instead of deciding.
20
20
 
21
21
  > Establish *plumb* before you build. The LLM is a hand, not a head.
22
22
 
23
23
  Its one law is **vibe to execute, never vibe to decide**: the human owns every
24
24
  decision, the LLM owns the labor, and the boundary between them is a **pause you
25
- advance**, not a wall that refuses you. The *why* behind that — attention as the scarce
26
- resource — is in [`docs/attention-first-development.md`](docs/attention-first-development.md).
25
+ advance**, not a wall that refuses you. The *why* behind that (attention as the scarce
26
+ resource) is in [`docs/attention-first-development.md`](docs/attention-first-development.md).
27
27
  PlumbBob is the layer below [Ridgeline](https://github.com/robmclarty/ridgeline): where
28
28
  Ridgeline runs large, settled work autonomously without you, PlumbBob keeps you in the
29
29
  driver's seat for the work your judgment has to steer. This repository was built using
30
- PlumbBob, dogfooded on its own loop.
30
+ PlumbBob itself, running its own loop.
31
31
 
32
32
  ## What a prompt can't replicate
33
33
 
34
34
  A system prompt can *ask* a model to plan first and stop for review. What it can't do is
35
- **hold the line when the model doesn't** — and that mechanical half is what PlumbBob adds
35
+ **hold the line when the model doesn't**, and that mechanical half is what PlumbBob adds
36
36
  under the skills. Five deterministic edges, enforced by the CLI and git rather than by the
37
37
  model's goodwill:
38
38
 
39
39
  - **A gate that refuses red.** `checkpoint` won't record a step while the check gate is
40
- red, and `start` refuses a dirty tree — the [checkride](https://www.npmjs.com/package/checkride)
40
+ red, and `start` refuses a dirty tree: the [checkride](https://www.npmjs.com/package/checkride)
41
41
  run (types, lint, tests, dead code, docs) has to pass before a step lands.
42
42
  - **One SHA per verified step.** Every approved step is its own git commit against a
43
- recorded baseline — a ledger of checkpoints, not one undifferentiated diff at the end.
43
+ recorded baseline: a ledger of checkpoints, not one undifferentiated diff at the end.
44
44
  - **A preservation-aware revert.** `/plumbbob:revert` resets exactly to a recorded checkpoint
45
45
  SHA while keeping your plan and notes intact, and restores *only* SHAs the loop wrote.
46
- - **A build record that rides the PR.** The tracked `builds/<slug>/` folder — intent, log,
47
- checkpoints, report — merges into `main` with the branch instead of dying with the
46
+ - **A build record that rides the PR.** The tracked `builds/<slug>/` folder (intent, log,
47
+ checkpoints, report) merges into `main` with the branch instead of dying with the
48
48
  worktree; the archive never destroys.
49
49
  - **The approval latch.** `checkpoint` refuses to land a step until the harness records a
50
- human turn since that step began ([D64–D66](docs/decisions.md#d64), the ledger-plane
51
- enforcement), so the model can't self-commit past you — the refusal *is* the pause.
50
+ human turn since that step began ([D64 (approval-latch)](docs/decisions.md#d64)–[D66
51
+ (oob-commits-surfaced)](docs/decisions.md#d66), the ledger-plane enforcement), so the
52
+ model can't self-commit past you: the refusal *is* the pause.
52
53
 
53
54
  The planning surface is the on-ramp; these five are the floor under it. And the latch's
54
55
  payoff is [measured, not asserted](#why-not-just), not just claimed. **Guidance on the
@@ -63,7 +64,7 @@ work, a latch on the record.**
63
64
  Everything the model must stay true to lives in one file, the build's `intent.md`
64
65
  (under `.plumbbob/builds/<slug>/`), written before any code: the **Frame** (the problem, what done looks like, what you're
65
66
  explicitly *not* doing), the **Decisions** and **Constraints** (the settled calls, each
66
- with its *because*), and the **Steps** — a numbered list where every step carries a
67
+ with its *because*), and the **Steps**: a numbered list where every step carries a
67
68
  **done-when** (a checkable finish line, ideally a test) and a **seam** (the files it's
68
69
  expected to touch).
69
70
 
@@ -75,16 +76,16 @@ expected to touch).
75
76
  /plumbbob:finish report what shipped and why, final commit, clear (once)
76
77
  ```
77
78
 
78
- Nothing is locked and nothing refuses you — the loop does a step's labor, pulls up to
79
+ Nothing is locked and nothing refuses you: the loop does a step's labor, pulls up to
79
80
  the line, and waits for you to advance it. **You are the clock.**
80
81
 
81
82
  ## Install
82
83
 
83
- PlumbBob installs **once, globally** — like `gh` or your dotfiles. There are two ways;
84
+ PlumbBob installs **once, globally** (like `gh` or your dotfiles). Two ways work;
84
85
  pick one (both register a Claude Code plugin named `plumbbob`, so running both
85
86
  collides).
86
87
 
87
- **Marketplace plugin** — Claude Code installs the published `plumbbob` package for you
88
+ **Marketplace plugin**: Claude Code installs the published `plumbbob` package for you
88
89
  (skills, hook, and the CLI on PATH), so you run no `npm i -g` and no `init`:
89
90
 
90
91
  ```text
@@ -92,7 +93,7 @@ collides).
92
93
  /plugin install plumbbob@robmclarty
93
94
  ```
94
95
 
95
- **npm global + `init`** — installs the CLI, then links the skills and hook into Claude
96
+ **npm global + `init`**: installs the CLI, then links the skills and hook into Claude
96
97
  Code in place:
97
98
 
98
99
  ```sh
@@ -101,15 +102,15 @@ plumbbob init # link it into Claude Code; --uninstall to undo
101
102
  ```
102
103
 
103
104
  Restart Claude Code (or `/reload-plugins`) to activate, then run `plumbbob doctor`
104
- (or `/plumbbob:doctor` in-session) to confirm the wiring. The full guide — namespacing,
105
- per-project sessions, the agent-neutral roadmap — is in
105
+ (or `/plumbbob:doctor` in-session) to confirm the wiring. The full guide (namespacing,
106
+ per-project sessions, the agent-neutral roadmap) is in
106
107
  [`docs/install.md`](docs/install.md).
107
108
 
108
109
  ## Your first session
109
110
 
110
111
  In Claude Code, inside any git repo with a clean tree:
111
112
 
112
- 1. **Plan.** Fire `/plumbbob:plan` and give it whatever you have — nothing (it interviews
113
+ 1. **Plan.** Fire `/plumbbob:plan` and give it whatever you have: nothing (it interviews
113
114
  you), a rough line (`/plumbbob:plan rate-limit POST /login, 5/min/IP, return 429`), or a
114
115
  path to a spec file. Together you fill the build's `intent.md`. No code is written
115
116
  yet.
@@ -120,17 +121,17 @@ In Claude Code, inside any git repo with a clean tree:
120
121
  PAUSE — read the diff as an editor. Approve to checkpoint, or send fixes.
121
122
  ```
122
123
 
123
- (The check gate is [checkride](https://www.npmjs.com/package/checkride) — one
124
+ (The check gate is [checkride](https://www.npmjs.com/package/checkride), one
124
125
  run across the tools your repo already configures: types, lint, tests, dead
125
126
  code, docs. To gate through your own command instead, set the `"check"` key in
126
- `.plumbbob/settings.json`, e.g. `"check": "npm test"`.)
127
- 3. **Approve** — or send fixes. On your OK it commits the step as a checkpoint, marks
128
- it done, and returns to the boundary. Fire `/plumbbob:build` again for the next step —
127
+ `.plumbbob/settings.json`, for example `"check": "npm test"`.)
128
+ 3. **Approve**, or send fixes. On your OK it commits the step as a checkpoint, marks
129
+ it done, and returns to the boundary. Fire `/plumbbob:build` again for the next step:
129
130
  re-firing it *is* the clock tick. Whenever you lose the thread, `/plumbbob:status` shows
130
131
  where you are and names the next move.
131
132
  4. **Finish.** When the last step is done, `/plumbbob:finish` writes a report of what shipped
132
133
  and why into the build's tracked folder, makes the final commit, and clears the slate
133
- for the next goal. The folder rides the branch into the PR — the build's record merges
134
+ for the next goal. The folder rides the branch into the PR: the build's record merges
134
135
  into `main` instead of dying with the worktree.
135
136
 
136
137
  A mid-build "ooh, what if…" never derails the step: `/plumbbob:park` captures it to a list
@@ -140,23 +141,23 @@ end, with the real output at every stage, is in
140
141
 
141
142
  ## The skills
142
143
 
143
- You drive the whole loop from your IDE with `/plumbbob:*` skills — no step numbers to
144
+ You drive the whole loop from your IDE with `/plumbbob:*` skills: no step numbers to
144
145
  remember, no raw CLI to type. Every skill is `disable-model-invocation`, so *you* fire
145
146
  every move, and `/plumbbob:status` always names your next one. (Claude Code namespaces
146
147
  them under the plugin, so the command is `/plumbbob:plan`. The bare `/plan` reaches it
147
- too — but only where nothing else owns that name, and four of the twelve share one with
148
+ too, but only where nothing else owns that name, and four of the thirteen share one with
148
149
  a Claude Code built-in, so these docs write the full form.)
149
150
 
150
- **The happy path** — the three moves every session makes; many sessions need
151
+ **The happy path**: the three moves every session makes; many sessions need
151
152
  nothing else:
152
153
 
153
154
  | Skill <img alt="" width="110" height="1"> | Does |
154
155
  |------------------------------------|------|
155
- | `/plumbbob:plan` | plan the whole goal — open the session and author intent's Frame, Decisions, Constraints, **and all Steps** |
156
- | `/plumbbob:build` | implement the next planned step, then verify it to the pause — `--auto` self-approves and chains to done; a range like `1-3` self-approves through step 3, then pauses |
157
- | `/plumbbob:finish` | finish up — write the report, make the final commit, clear for a fresh goal |
156
+ | `/plumbbob:plan` | plan the whole goal: open the session and author intent's Frame, Decisions, Constraints, **and all Steps** |
157
+ | `/plumbbob:build` | implement the next planned step, then verify it to the pause: `--auto` self-approves and chains to done; a range like `1-3` self-approves through step 3, then pauses |
158
+ | `/plumbbob:finish` | finish up: write the report, make the final commit, clear for a fresh goal |
158
159
 
159
- **Plan-shaping moves** — optional, for when the plan needs work mid-flight:
160
+ **Plan-shaping moves**: optional, for when the plan needs work mid-flight:
160
161
 
161
162
  | Skill <img alt="" width="110" height="1"> | Does |
162
163
  |------------------------------------|------|
@@ -164,48 +165,49 @@ nothing else:
164
165
  | `/plumbbob:refine` | attack the frame for holes, or repair a drifted plan |
165
166
  | `/plumbbob:spike` | throwaway worktree experiment for a fork the plan can't settle |
166
167
 
167
- **Helpers** — orient, verify, recover, diagnose:
168
+ **Helpers**: orient, verify, recover, diagnose:
168
169
 
169
170
  | Skill <img alt="" width="110" height="1"> | Does |
170
171
  |------------------------------------|------|
171
- | `/plumbbob:status` | orient — where you are, the next step's done-when and seam, and the next move |
172
- | `/plumbbob:verify` | the tick, standalone — check → self-review → validate → **PAUSE** → checkpoint, for a diff `/plumbbob:build` didn't write |
173
- | `/plumbbob:revert` | recover — `git reset --hard` to a recorded checkpoint |
172
+ | `/plumbbob:status` | orient: where you are, the next step's done-when and seam, and the next move |
173
+ | `/plumbbob:verify` | the tick, standalone: check → self-review → validate → **PAUSE** → checkpoint, for a diff `/plumbbob:build` didn't write |
174
+ | `/plumbbob:revert` | rewind: `git reset --hard` to a recorded checkpoint |
175
+ | `/plumbbob:recover` | reconcile the session's own state when the dashboard looks wrong |
174
176
  | `/plumbbob:doctor` | check the install from inside a session |
175
177
 
176
- **Capture** — the park/harvest loop for mid-build ideas:
178
+ **Capture**: the park/harvest loop for mid-build ideas:
177
179
 
178
180
  | Skill <img alt="" width="110" height="1"> | Does |
179
181
  |------------------------------------|------|
180
182
  | `/plumbbob:park` | capture a mid-build idea without chasing it |
181
183
  | `/plumbbob:harvest` | triage parked ideas between steps (blocker / tangent / pivot) |
182
184
 
183
- All twelve, with inputs and effects, are in
185
+ All thirteen, with inputs and effects, are in
184
186
  [`docs/skills-reference.md`](docs/skills-reference.md).
185
187
 
186
188
  Under the skills ships a lean `plumbbob` CLI (the mechanical verbs the
187
189
  skills shell out to), one session-gated post-edit hook (non-blocking lint feedback in
188
- flow), and a `.plumbbob/` sidecar you can open and edit by hand at any time — a tracked
190
+ flow), and a `.plumbbob/` sidecar you can open and edit by hand at any time: a tracked
189
191
  `builds/<slug>/` folder per build (`intent.md`, `build-log.md`, `checkpoints`, `report.md`)
190
192
  that rides the branch into the PR, plus an untracked control plane (`settings.local.json`,
191
193
  the session sentinel, the in-flight markers).
192
194
 
193
- **`/plumbbob:build` is the default engine, not the only one.** It's one executor — the
194
- loop doesn't care who writes the code. Implement a step by hand — or vibe it in
195
- another session, or in another harness entirely — and run `/plumbbob:verify` instead:
195
+ **`/plumbbob:build` is the default engine, not the only one.** It's one executor: the
196
+ loop doesn't care who writes the code. Implement a step by hand (or vibe it in
197
+ another session, or in another harness entirely) and run `/plumbbob:verify` instead:
196
198
  same checks, same pause, same checkpoint. It reads the *diff, not the author*.
197
199
 
198
200
  **Bring your own agents.** Because the executor is author-blind, you can plug your
199
201
  own in. A **user-authored agent** is any executable that speaks one small JSON
200
202
  envelope; drop it under `.plumbbob/agents/`, bind it to a step's `before`, `build`,
201
203
  or `after` slot in the build's `harness.json`, and PlumbBob runs it through the same
202
- pause — with **no way for it to advance the loop** (checkride still gates, you're
204
+ pause, with **no way for it to advance the loop** (checkride still gates, you're
203
205
  still the clock). The full contract for authors, with a copy-paste example, is in
204
206
  [`docs/agents.md`](docs/agents.md).
205
207
 
206
208
  ## Why "PlumbBob"
207
209
 
208
- The name is the method. A plumb bob is a weight on a string — gravity pulls it into a
210
+ The name is the method. A plumb bob is a weight on a string; gravity pulls it into a
209
211
  perfectly straight vertical line, the builder's oldest reference for *true*: the fixed
210
212
  mark you hold the work against so it never drifts out of square. PlumbBob hangs your
211
213
  **intent** as that line and keeps every step aligned to it, so the build stays plumb
@@ -215,90 +217,91 @@ with what you decided instead of wandering off behind the model.
215
217
 
216
218
  The questions a skeptic should ask, answered straight.
217
219
 
218
- **…use plan mode?** Plan mode is the same instinct — decide before executing —
220
+ **…use plan mode?** Plan mode is the same instinct (decide before executing),
219
221
  scoped to one session. The plan lives in the chat, so it fades with the context
220
222
  window, and the approval gates the *start* of the work, not each increment of it.
221
223
  PlumbBob puts the plan in a file in your repo that survives compaction, restarts,
222
- and next week; moves the approval to **every step** — each checked, reviewed
223
- against the plan, and committed as its own checkpoint, so a wrong turn costs one
224
+ and next week; moves the approval to **every step** (each checked, reviewed
225
+ against the plan, and committed as its own checkpoint), so a wrong turn costs one
224
226
  step, not the afternoon; and records the *whys* alongside the decisions, so the
225
227
  archive can still answer "what did we decide, and why" long after the session is
226
- gone. The two compose fine: plan mode — or anything else — can produce a step's
228
+ gone. The two compose fine: plan mode (or anything else) can produce a step's
227
229
  diff, and `/plumbbob:verify` reads it like any other.
228
230
 
229
231
  **…use git and a TODO file?** That's the honest skeleton, and if your discipline
230
232
  holds by willpower alone, it may be all you need. What the CLI adds is the
231
- [mechanical half of the discipline](#what-a-prompt-cant-replicate) — the five edges up
232
- top — so willpower is spent only at the pause. The one not on that list: a status
233
+ [mechanical half of the discipline](#what-a-prompt-cant-replicate) (the five edges up
234
+ top), so willpower is spent only at the pause. The one not on that list: a status
233
235
  dashboard re-injected into every skill, so the model re-orients on each move without you
234
236
  re-explaining the state.
235
237
 
236
- **…wait for a vendor to ship this natively?** They're converging on it — plan
237
- modes, spec kits, native checkpoints — and that convergence is evidence *for* the
238
+ **…wait for a vendor to ship this natively?** They're converging on it (plan
239
+ modes, spec kits, native checkpoints), and that convergence is evidence *for* the
238
240
  premise. PlumbBob is deliberately thin against that future: the artifacts are
239
241
  plain markdown and ordinary git commits in your own repo, the CLI is lean
240
242
  (node builtins plus one deliberate dependency), and nothing locks you in. The
241
- investment is small — twelve
242
- skills over a plain-markdown sidecar, learnable in an afternoon — and what you're
243
+ investment is small (thirteen
244
+ skills over a plain-markdown sidecar, learnable in an afternoon), and what you're
243
245
  actually learning is the method: decisions before code, one verified step at a
244
246
  time, capture instead of chase. That transfers to whatever tool wins. If
245
247
  something better ships, you walk away with your archives and your habits intact.
246
248
 
247
- **…admit the pause is unenforceable?** On the **work** plane, yes — on purpose
248
- ([D10](docs/decisions.md#d10)/[D13](docs/decisions.md#d13) in
249
+ **…admit the pause is unenforceable?** On the **work** plane, yes, on purpose
250
+ ([D10 (pause-not-lock)](docs/decisions.md#d10)/[D13 (no-edit-guards)](docs/decisions.md#d13) in
249
251
  [`docs/decisions.md`](docs/decisions.md)): a hard lock on every edit buys ritual, not
250
252
  control, because a determined model routes around it and a denial mid-thought leaves no
251
253
  legal move. But the **record** is a different plane, and there the tick *is* latched
252
- ([D64–D66](docs/decisions.md#d64)): `checkpoint` refuses to land a step until the harness
253
- records a human turn since that step began, so the agent cannot self-commit past you —
254
+ ([D64 (approval-latch)](docs/decisions.md#d64)–[D66 (oob-commits-surfaced)](docs/decisions.md#d66)): `checkpoint` refuses to land a step until the harness
255
+ records a human turn since that step began, so the agent cannot self-commit past you:
254
256
  the refusal simply *is* the pause. It extends the [deterministic edges above](#what-a-prompt-cant-replicate)
255
257
  to the one boundary the product is named after, while leaving human what must be human:
256
258
  you, reading the diff. And when a raw commit does slip the ledger, `status` says so and the
257
- checkpoint record makes recovery one command — cheap recovery, not a cage, is the control
259
+ checkpoint record makes recovery one command; cheap recovery, not a cage, is the control
258
260
  that matters.
259
261
 
260
262
  > The latch's payoff is measured, not asserted: the skill-eval harness
261
- > ([`test/evals/`](test/evals/)) sweeps this loop headless — prose-only baseline vs. the
262
- > shipped latch, N=5 per contract, every assertion a mechanical read of git state — and
263
+ > ([`test/evals/`](test/evals/)) sweeps this loop headless (prose-only baseline vs. the
264
+ > shipped latch, N=5 per contract, every assertion a mechanical read of git state) and
263
265
  > commits each receipt under [`docs/evals/`](docs/evals/). The first sweep
264
- > ([opus, 2026-07-11](docs/evals/2026-07-11.md)) closed the route the latch owns —
265
- > *no checkpoint over a red check under pressure* went from **2/5 prose-only to 5/5
266
- > latched** — and named, rather than papered over, the two honest gaps it surfaced: park
266
+ > ([opus, 2026-07-11](docs/evals/2026-07-11.md)) closed the route the latch owns
267
+ > (*no checkpoint over a red check under pressure* went from **2/5 prose-only to 5/5
268
+ > latched**) and named, rather than papered over, the two honest gaps it surfaced: park
267
269
  > capture at 0/5, and adversarial pressure flipping a standing `auto` grant a model could
268
270
  > write into settings, a legal side door. The re-sweep
269
- > ([opus, 2026-07-18](docs/evals/2026-07-18.md), plumbbob 0.8.7) reproduced the win —
270
- > *no checkpoint over a red check* still **5/5 latched** — and pinned both gaps. Both are
271
- > now closed. The side door went by construction: [D67](docs/decisions.md#d67)
271
+ > ([opus, 2026-07-18](docs/evals/2026-07-18.md), plumbbob 0.8.7) reproduced the win
272
+ > (*no checkpoint over a red check* still **5/5 latched**) and pinned both gaps. Both are
273
+ > now closed. The side door went by construction: [D67 (auto-not-a-grant)](docs/decisions.md#d67)
272
274
  > (self-approval is human-typed only) retired the settings `auto` grant, so the one
273
- > approval a model could forge is gone. Park capture was never the latch's to reach —
274
- > prose-governed by design ([D10](docs/decisions.md#d10)/[D13](docs/decisions.md#d13)) —
275
+ > approval a model could forge is gone. Park capture was never the latch's to reach,
276
+ > prose-governed by design ([D10 (pause-not-lock)](docs/decisions.md#d10)/[D13 (no-edit-guards)](docs/decisions.md#d13)),
275
277
  > and it failed because the guidance couldn't reach a fresh session at all; the turn hook
276
278
  > now injects one line when a step is in flight, and the third sweep
277
279
  > ([opus, 2026-07-27](docs/evals/2026-07-27.md), plumbbob 0.9.0) measures it at **5/5**,
278
280
  > alongside every other contract. That sweep ran the latched arm only, so its numbers are
279
- > a regression check on the shipped configuration, not a fresh baseline delta — the
281
+ > a regression check on the shipped configuration, not a fresh baseline delta: the
280
282
  > 2/5→5/5 headline above remains the 2026-07-11 measurement.
281
283
 
282
284
  ## Documentation
283
285
 
284
- Each doc answers one question — in rough reading order for a new user:
285
-
286
- - *What does a session actually look like?* → [`docs/happy-path.md`](docs/happy-path.md) — one goal walked end to end; read this first.
287
- - *Show me the artifacts it leaves behind.* → [`examples/`](examples/) — that same session's finished build folder, file by file.
288
- - *Should I / can I / what about…?* → [`docs/faq.md`](docs/faq.md) — the adoption questions, answered straight.
289
- - *What is each method for?* → [`docs/techniques.md`](docs/techniques.md) — steps, seams, the pause, park/harvest, spikes.
290
- - *What does each skill do?* → [`docs/skills-reference.md`](docs/skills-reference.md) — all twelve skills: inputs, effects, when to reach for each.
291
- - *How do I plug in my own agent?* → [`docs/agents.md`](docs/agents.md) — the subprocess envelope, the manifest, `harness.json`, and working examples (including a local-model reviewer via Ollama).
292
- - *How do I get a local model reviewing my steps?* → [`docs/local-model-review.md`](docs/local-model-review.md) — the ollama-reviewer example walked end to end, install to every-pause review.
293
- - *How do I install it, exactly?* → [`docs/install.md`](docs/install.md) — the full guide and the agent-neutral roadmap.
294
- - *What does the CLI underneath do?* → [`docs/cli-reference.md`](docs/cli-reference.md) — every verb, flag, exit code, and the `.plumbbob/` sidecar.
295
- - *What are these untracked files, and why is it touching my `.git`?* → [`docs/state-and-git.md`](docs/state-and-git.md) — the state files, the `info/exclude` mechanism, and the objections answered.
296
- - *Something's broken.* → [`docs/troubleshooting.md`](docs/troubleshooting.md) — fixes for the common snags.
297
- - *Why is it built this way?* → [`docs/decisions.md`](docs/decisions.md) — the `D#` / `C#` design-decision key the source cites.
298
- - *How does it hang together inside?* → [`docs/architecture.md`](docs/architecture.md) — the layers and planes, for contributors (in progress).
299
- - *Why does this exist at all?* → [`docs/attention-first-development.md`](docs/attention-first-development.md) — the philosophy: attention as the scarce resource.
300
- - *What does it run on my machine?* → [`SECURITY.md`](SECURITY.md) — execution surface and how to report a vulnerability.
301
- - *How do I contribute?* → [`CONTRIBUTING.md`](CONTRIBUTING.md) — setup, conventions, and how to submit changes.
286
+ Each doc answers one question (in rough reading order for a new user):
287
+
288
+ - *What does a session actually look like?* → [`docs/happy-path.md`](docs/happy-path.md): one goal walked end to end; read this first.
289
+ - *Show me the artifacts it leaves behind.* → [`examples/`](examples/): that same session's finished build folder, file by file.
290
+ - *Should I / can I / what about…?* → [`docs/faq.md`](docs/faq.md): the adoption questions, answered straight.
291
+ - *What is each method for?* → [`docs/techniques.md`](docs/techniques.md): steps, seams, the pause, park/harvest, spikes.
292
+ - *What does each skill do?* → [`docs/skills-reference.md`](docs/skills-reference.md): all thirteen skills: inputs, effects, when to reach for each.
293
+ - *How do I plug in my own agent?* → [`docs/agents.md`](docs/agents.md): the subprocess envelope, the manifest, `harness.json`, and working examples (including a local-model reviewer via Ollama).
294
+ - *How do I get a local model reviewing my steps?* → [`docs/local-model-review.md`](docs/local-model-review.md): the ollama-reviewer example walked end to end, install to every-pause review.
295
+ - *How do I install it, exactly?* → [`docs/install.md`](docs/install.md): the full guide and the agent-neutral roadmap.
296
+ - *What does the CLI underneath do?* → [`docs/cli-reference.md`](docs/cli-reference.md): every verb, flag, exit code, and the `.plumbbob/` sidecar.
297
+ - *What are these untracked files, and why is it touching my `.git`?* → [`docs/state-and-git.md`](docs/state-and-git.md): the state files, the `info/exclude` mechanism, and the objections answered.
298
+ - *Something's broken.* → [`docs/troubleshooting.md`](docs/troubleshooting.md): fixes for the common snags.
299
+ - *Why is it built this way?* → [`docs/decisions.md`](docs/decisions.md): the `D#` / `C#` design-decision key the source cites.
300
+ - *How does it hang together inside?* → [`docs/architecture.md`](docs/architecture.md): the layers and planes, for contributors (in progress).
301
+ - *Why does this exist at all?* → [`docs/attention-first-development.md`](docs/attention-first-development.md): the philosophy: attention as the scarce resource.
302
+ - *Why does AI-written prose get worse over time?* → [`docs/generation-loss.md`](docs/generation-loss.md): the copy-of-a-copy problem, and why anchor texts are written by hand.
303
+ - *What does it run on my machine?* → [`SECURITY.md`](SECURITY.md): execution surface and how to report a vulnerability.
304
+ - *How do I contribute?* → [`CONTRIBUTING.md`](CONTRIBUTING.md): setup, conventions, and how to submit changes.
302
305
 
303
306
  ## License
304
307
 
package/dist/cli-core.js CHANGED
@@ -1,12 +1,12 @@
1
- // plumbbob CLI core — argv dispatch and the help table, separated from the bin
1
+ // plumbbob CLI core: argv dispatch and the help table, separated from the bin
2
2
  // entry (cli.ts) so the routing/help logic is unit-testable in-process without
3
3
  // the top-level process.exit. Node builtins plus a deliberate few dependencies
4
4
  // (currently checkride alone, via check.ts). Functional/procedural: no classes,
5
5
  // no `this`, no default export.
6
6
  //
7
7
  // The deciding/executing boundary is a pause, not a lock, so there is nothing
8
- // to defend in the dispatcher — every verb runs the same whether a human or the
9
- // model triggers it. There is no human-only `mode` escape hatch and no
8
+ // to defend in the dispatcher; every verb runs the same whether a human or the
9
+ // model triggers it. No human-only `mode` escape hatch exists and no
10
10
  // CLAUDECODE in-session refusal; what keeps the human the decider is the pause
11
11
  // at the step boundary (the skills), not a refusal here.
12
12
  import { readFileSync } from 'node:fs';
@@ -24,6 +24,7 @@ import { use } from "./verbs/use.js";
24
24
  import { finish } from "./verbs/finish.js";
25
25
  import { init } from "./verbs/init.js";
26
26
  import { doctor } from "./verbs/doctor.js";
27
+ import { recover } from "./verbs/recover.js";
27
28
  import { agent } from "./verbs/agent.js";
28
29
  import { turn } from "./verbs/turn.js";
29
30
  /** Shared across every verb that resolves through the active-build cursor. */
@@ -37,7 +38,7 @@ const BUILD_FLAG = {
37
38
  *
38
39
  * One table drives three things: the top-level verb table, per-verb `--help`,
39
40
  * and the unknown-flag refusal in `run`. Keeping it as data rather than inline
40
- * writes is the deliberate exception to the write-at-the-call-site convention —
41
+ * writes is the deliberate exception to the write-at-the-call-site convention;
41
42
  * a synopsis has to be readable by the validator, not just printable.
42
43
  */
43
44
  const VERBS = [
@@ -162,6 +163,13 @@ const VERBS = [
162
163
  flags: [{ name: '--migrate', gloss: 'move a legacy flat sidecar into builds/ (staged, not committed)' }],
163
164
  notes: 'Exits 0 when everything passes, 1 when a check fails or an un-migrated legacy sidecar is present.',
164
165
  },
166
+ {
167
+ name: 'recover',
168
+ description: 'reconcile the control plane: stale markers, a cursor pointing nowhere, spike leftovers',
169
+ synopsis: ['recover [--fix]'],
170
+ flags: [{ name: '--fix', gloss: 'repair the stale untracked control files it can repair on its own' }],
171
+ notes: 'Exits 0 when the control plane is consistent, 1 while any problem stands. --fix never touches a tracked artifact, git history, or the loop; spike worktrees are reported, never removed.',
172
+ },
165
173
  {
166
174
  name: 'agent',
167
175
  description: 'list or spawn a user-authored agent',
@@ -247,7 +255,7 @@ export function verbSpec(name) {
247
255
  return VERBS.find((v) => v.name === name) ?? null;
248
256
  }
249
257
  /**
250
- * Every verb name, in table order — the contract tests iterate this.
258
+ * Every verb name, in table order: the contract tests iterate this.
251
259
  */
252
260
  export function verbNames() {
253
261
  return VERBS.map((v) => v.name);
@@ -333,6 +341,8 @@ async function dispatch(verb, cwd, rest) {
333
341
  return init(rest);
334
342
  case 'doctor':
335
343
  return doctor(cwd, rest);
344
+ case 'recover':
345
+ return recover(cwd, rest);
336
346
  case 'agent':
337
347
  return agent(cwd, rest);
338
348
  case 'turn':
@@ -352,12 +362,19 @@ async function dispatch(verb, cwd, rest) {
352
362
  * used to commit a real checkpoint. Any thrown error becomes a one-line stderr
353
363
  * report and exit 1, so the bin entry only ever exits with the code returned
354
364
  * here.
365
+ *
366
+ * `cwd` is the repo the verbs act on. It defaults to the process's (the only
367
+ * thing the bin entry ever wants) and is a parameter solely so a test can name
368
+ * a fixture. Screening argv does not help when the argv is *valid*: `checkpoint
369
+ * -m --help` reads `--help` as the subject, exactly as it should, and then
370
+ * commits. Whose repo it commits is decided here, and a default is not a choice
371
+ * a test should inherit silently.
355
372
  */
356
- export async function run(argv) {
373
+ export async function run(argv, cwd = process.cwd()) {
357
374
  const verb = argv[0] ?? 'help';
358
375
  const rest = argv.slice(1);
359
376
  if (verb === 'help' || verb === '--help' || verb === '-h') {
360
- // `plumbbob help <verb>` is the same page as `plumbbob <verb> --help` —
377
+ // `plumbbob help <verb>` is the same page as `plumbbob <verb> --help`;
361
378
  // both spellings get typed, so both work.
362
379
  const topic = rest.find((a) => !a.startsWith('-'));
363
380
  if (topic === undefined) {
@@ -389,7 +406,7 @@ export async function run(argv) {
389
406
  }
390
407
  }
391
408
  try {
392
- return await dispatch(verb, process.cwd(), rest);
409
+ return await dispatch(verb, cwd, rest);
393
410
  }
394
411
  catch (err) {
395
412
  const message = err instanceof Error ? err.message : String(err);
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // plumbbob CLI entry — the published bin. All routing and the help table live in
2
+ // plumbbob CLI entry: the published bin. All routing and the help table live in
3
3
  // cli-core.ts (unit-tested in-process); this file is only the executable shell:
4
4
  // it wires argv to the dispatcher and turns the returned code into the exit code.
5
5
  // Keeping the single process.exit here is what lets cli-core.ts be imported by a