claude-auto 0.12.4

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 (327) hide show
  1. package/.claude-auto/.claude.hooks.json +25 -0
  2. package/.claude-auto/reminders/reminder-auto.md +145 -0
  3. package/.claude-auto/reminders/reminder-documentation.md +30 -0
  4. package/.claude-auto/reminders/reminder-emergent-design.md +41 -0
  5. package/.claude-auto/reminders/reminder-extreme-ownership.md +27 -0
  6. package/.claude-auto/reminders/reminder-ide-diagnostics.md +25 -0
  7. package/.claude-auto/reminders/reminder-parallelization.md +27 -0
  8. package/.claude-auto/reminders/reminder-rethink-after-revert.md +25 -0
  9. package/.claude-auto/reminders/reminder-sub-agent-rules.md +27 -0
  10. package/.claude-auto/reminders/reminder-test-title-matches-spec.md +37 -0
  11. package/.claude-auto/validators/appeal-system.md +55 -0
  12. package/.claude-auto/validators/backwards-compat.md +33 -0
  13. package/.claude-auto/validators/burst-atomicity.md +37 -0
  14. package/.claude-auto/validators/coverage-rules.md +34 -0
  15. package/.claude-auto/validators/dead-code.md +36 -0
  16. package/.claude-auto/validators/hygiene.md +34 -0
  17. package/.claude-auto/validators/infra-commit-format.md +37 -0
  18. package/.claude-auto/validators/ketchup-plan-format.md +42 -0
  19. package/.claude-auto/validators/new-code-requires-tests.md +36 -0
  20. package/.claude-auto/validators/no-comments.md +35 -0
  21. package/.claude-auto/validators/no-dangerous-git.md +35 -0
  22. package/.claude-auto/validators/tcr-workflow.md +31 -0
  23. package/.claude-auto/validators/testing-no-state-peeking.md +37 -0
  24. package/.claude-auto/validators/testing-structure.md +37 -0
  25. package/.claude-auto/validators/testing-stubs-over-mocks.md +42 -0
  26. package/.claude-auto/validators/testing-weak-assertions.md +36 -0
  27. package/.claude-auto/validators/type-organization.md +30 -0
  28. package/README.md +172 -0
  29. package/bin/cli.ts +6 -0
  30. package/dist/bin/cli.d.ts +3 -0
  31. package/dist/bin/cli.d.ts.map +1 -0
  32. package/dist/bin/cli.js +7 -0
  33. package/dist/bin/cli.js.map +1 -0
  34. package/dist/bundle/scripts/auto-continue.js +5045 -0
  35. package/dist/bundle/scripts/pre-tool-use.js +11719 -0
  36. package/dist/bundle/scripts/session-start.js +8571 -0
  37. package/dist/bundle/scripts/user-prompt-submit.js +8585 -0
  38. package/dist/scripts/auto-continue.d.ts +3 -0
  39. package/dist/scripts/auto-continue.d.ts.map +1 -0
  40. package/dist/scripts/auto-continue.js +65 -0
  41. package/dist/scripts/auto-continue.js.map +1 -0
  42. package/dist/scripts/generate-changeset.d.ts +13 -0
  43. package/dist/scripts/generate-changeset.d.ts.map +1 -0
  44. package/dist/scripts/generate-changeset.js +322 -0
  45. package/dist/scripts/generate-changeset.js.map +1 -0
  46. package/dist/scripts/pre-tool-use.d.ts +3 -0
  47. package/dist/scripts/pre-tool-use.d.ts.map +1 -0
  48. package/dist/scripts/pre-tool-use.js +78 -0
  49. package/dist/scripts/pre-tool-use.js.map +1 -0
  50. package/dist/scripts/session-start.d.ts +3 -0
  51. package/dist/scripts/session-start.d.ts.map +1 -0
  52. package/dist/scripts/session-start.js +76 -0
  53. package/dist/scripts/session-start.js.map +1 -0
  54. package/dist/scripts/user-prompt-submit.d.ts +3 -0
  55. package/dist/scripts/user-prompt-submit.d.ts.map +1 -0
  56. package/dist/scripts/user-prompt-submit.js +76 -0
  57. package/dist/scripts/user-prompt-submit.js.map +1 -0
  58. package/dist/src/activity-logger.d.ts +2 -0
  59. package/dist/src/activity-logger.d.ts.map +1 -0
  60. package/dist/src/activity-logger.js +47 -0
  61. package/dist/src/activity-logger.js.map +1 -0
  62. package/dist/src/activity-logger.test.d.ts +2 -0
  63. package/dist/src/activity-logger.test.d.ts.map +1 -0
  64. package/dist/src/activity-logger.test.js +121 -0
  65. package/dist/src/activity-logger.test.js.map +1 -0
  66. package/dist/src/clean-logs.d.ts +6 -0
  67. package/dist/src/clean-logs.d.ts.map +1 -0
  68. package/dist/src/clean-logs.js +38 -0
  69. package/dist/src/clean-logs.js.map +1 -0
  70. package/dist/src/clean-logs.test.d.ts +2 -0
  71. package/dist/src/clean-logs.test.d.ts.map +1 -0
  72. package/dist/src/clean-logs.test.js +101 -0
  73. package/dist/src/clean-logs.test.js.map +1 -0
  74. package/dist/src/cli/cli.d.ts +3 -0
  75. package/dist/src/cli/cli.d.ts.map +1 -0
  76. package/dist/src/cli/cli.js +32 -0
  77. package/dist/src/cli/cli.js.map +1 -0
  78. package/dist/src/cli/cli.test.d.ts +2 -0
  79. package/dist/src/cli/cli.test.d.ts.map +1 -0
  80. package/dist/src/cli/cli.test.js +27 -0
  81. package/dist/src/cli/cli.test.js.map +1 -0
  82. package/dist/src/cli/doctor.d.ts +7 -0
  83. package/dist/src/cli/doctor.d.ts.map +1 -0
  84. package/dist/src/cli/doctor.js +67 -0
  85. package/dist/src/cli/doctor.js.map +1 -0
  86. package/dist/src/cli/doctor.test.d.ts +2 -0
  87. package/dist/src/cli/doctor.test.d.ts.map +1 -0
  88. package/dist/src/cli/doctor.test.js +87 -0
  89. package/dist/src/cli/doctor.test.js.map +1 -0
  90. package/dist/src/cli/install.d.ts +10 -0
  91. package/dist/src/cli/install.d.ts.map +1 -0
  92. package/dist/src/cli/install.js +116 -0
  93. package/dist/src/cli/install.js.map +1 -0
  94. package/dist/src/cli/install.test.d.ts +2 -0
  95. package/dist/src/cli/install.test.d.ts.map +1 -0
  96. package/dist/src/cli/install.test.js +217 -0
  97. package/dist/src/cli/install.test.js.map +1 -0
  98. package/dist/src/cli/reminders.d.ts +12 -0
  99. package/dist/src/cli/reminders.d.ts.map +1 -0
  100. package/dist/src/cli/reminders.js +52 -0
  101. package/dist/src/cli/reminders.js.map +1 -0
  102. package/dist/src/cli/reminders.test.d.ts +2 -0
  103. package/dist/src/cli/reminders.test.d.ts.map +1 -0
  104. package/dist/src/cli/reminders.test.js +72 -0
  105. package/dist/src/cli/reminders.test.js.map +1 -0
  106. package/dist/src/cli/repair.d.ts +11 -0
  107. package/dist/src/cli/repair.d.ts.map +1 -0
  108. package/dist/src/cli/repair.js +91 -0
  109. package/dist/src/cli/repair.js.map +1 -0
  110. package/dist/src/cli/repair.test.d.ts +2 -0
  111. package/dist/src/cli/repair.test.d.ts.map +1 -0
  112. package/dist/src/cli/repair.test.js +95 -0
  113. package/dist/src/cli/repair.test.js.map +1 -0
  114. package/dist/src/cli/status.d.ts +10 -0
  115. package/dist/src/cli/status.d.ts.map +1 -0
  116. package/dist/src/cli/status.js +55 -0
  117. package/dist/src/cli/status.js.map +1 -0
  118. package/dist/src/cli/status.test.d.ts +2 -0
  119. package/dist/src/cli/status.test.d.ts.map +1 -0
  120. package/dist/src/cli/status.test.js +80 -0
  121. package/dist/src/cli/status.test.js.map +1 -0
  122. package/dist/src/clue-collector.d.ts +23 -0
  123. package/dist/src/clue-collector.d.ts.map +1 -0
  124. package/dist/src/clue-collector.js +221 -0
  125. package/dist/src/clue-collector.js.map +1 -0
  126. package/dist/src/clue-collector.test.d.ts +2 -0
  127. package/dist/src/clue-collector.test.d.ts.map +1 -0
  128. package/dist/src/clue-collector.test.js +278 -0
  129. package/dist/src/clue-collector.test.js.map +1 -0
  130. package/dist/src/commit-validator.d.ts +53 -0
  131. package/dist/src/commit-validator.d.ts.map +1 -0
  132. package/dist/src/commit-validator.js +356 -0
  133. package/dist/src/commit-validator.js.map +1 -0
  134. package/dist/src/commit-validator.test.d.ts +2 -0
  135. package/dist/src/commit-validator.test.d.ts.map +1 -0
  136. package/dist/src/commit-validator.test.js +733 -0
  137. package/dist/src/commit-validator.test.js.map +1 -0
  138. package/dist/src/config-loader.d.ts +15 -0
  139. package/dist/src/config-loader.d.ts.map +1 -0
  140. package/dist/src/config-loader.js +12 -0
  141. package/dist/src/config-loader.js.map +1 -0
  142. package/dist/src/config-loader.test.d.ts +2 -0
  143. package/dist/src/config-loader.test.d.ts.map +1 -0
  144. package/dist/src/config-loader.test.js +69 -0
  145. package/dist/src/config-loader.test.js.map +1 -0
  146. package/dist/src/debug-logger.d.ts +2 -0
  147. package/dist/src/debug-logger.d.ts.map +1 -0
  148. package/dist/src/debug-logger.js +23 -0
  149. package/dist/src/debug-logger.js.map +1 -0
  150. package/dist/src/debug-logger.test.d.ts +2 -0
  151. package/dist/src/debug-logger.test.d.ts.map +1 -0
  152. package/dist/src/debug-logger.test.js +63 -0
  153. package/dist/src/debug-logger.test.js.map +1 -0
  154. package/dist/src/default-validators.test.d.ts +2 -0
  155. package/dist/src/default-validators.test.d.ts.map +1 -0
  156. package/dist/src/default-validators.test.js +119 -0
  157. package/dist/src/default-validators.test.js.map +1 -0
  158. package/dist/src/deny-list.d.ts +3 -0
  159. package/dist/src/deny-list.d.ts.map +1 -0
  160. package/dist/src/deny-list.js +62 -0
  161. package/dist/src/deny-list.js.map +1 -0
  162. package/dist/src/deny-list.test.d.ts +2 -0
  163. package/dist/src/deny-list.test.d.ts.map +1 -0
  164. package/dist/src/deny-list.test.js +93 -0
  165. package/dist/src/deny-list.test.js.map +1 -0
  166. package/dist/src/e2e.test.d.ts +2 -0
  167. package/dist/src/e2e.test.d.ts.map +1 -0
  168. package/dist/src/e2e.test.js +82 -0
  169. package/dist/src/e2e.test.js.map +1 -0
  170. package/dist/src/gitignore-manager.d.ts +2 -0
  171. package/dist/src/gitignore-manager.d.ts.map +1 -0
  172. package/dist/src/gitignore-manager.js +45 -0
  173. package/dist/src/gitignore-manager.js.map +1 -0
  174. package/dist/src/gitignore-manager.test.d.ts +2 -0
  175. package/dist/src/gitignore-manager.test.d.ts.map +1 -0
  176. package/dist/src/gitignore-manager.test.js +65 -0
  177. package/dist/src/gitignore-manager.test.js.map +1 -0
  178. package/dist/src/hook-input.d.ts +9 -0
  179. package/dist/src/hook-input.d.ts.map +1 -0
  180. package/dist/src/hook-input.js +7 -0
  181. package/dist/src/hook-input.js.map +1 -0
  182. package/dist/src/hook-input.test.d.ts +2 -0
  183. package/dist/src/hook-input.test.d.ts.map +1 -0
  184. package/dist/src/hook-input.test.js +20 -0
  185. package/dist/src/hook-input.test.js.map +1 -0
  186. package/dist/src/hook-logger.d.ts +16 -0
  187. package/dist/src/hook-logger.d.ts.map +1 -0
  188. package/dist/src/hook-logger.js +90 -0
  189. package/dist/src/hook-logger.js.map +1 -0
  190. package/dist/src/hook-logger.test.d.ts +2 -0
  191. package/dist/src/hook-logger.test.d.ts.map +1 -0
  192. package/dist/src/hook-logger.test.js +205 -0
  193. package/dist/src/hook-logger.test.js.map +1 -0
  194. package/dist/src/hook-state.d.ts +44 -0
  195. package/dist/src/hook-state.d.ts.map +1 -0
  196. package/dist/src/hook-state.js +128 -0
  197. package/dist/src/hook-state.js.map +1 -0
  198. package/dist/src/hook-state.test.d.ts +2 -0
  199. package/dist/src/hook-state.test.d.ts.map +1 -0
  200. package/dist/src/hook-state.test.js +204 -0
  201. package/dist/src/hook-state.test.js.map +1 -0
  202. package/dist/src/hooks/auto-continue.d.ts +21 -0
  203. package/dist/src/hooks/auto-continue.d.ts.map +1 -0
  204. package/dist/src/hooks/auto-continue.js +70 -0
  205. package/dist/src/hooks/auto-continue.js.map +1 -0
  206. package/dist/src/hooks/auto-continue.test.d.ts +2 -0
  207. package/dist/src/hooks/auto-continue.test.d.ts.map +1 -0
  208. package/dist/src/hooks/auto-continue.test.js +171 -0
  209. package/dist/src/hooks/auto-continue.test.js.map +1 -0
  210. package/dist/src/hooks/pre-tool-use.d.ts +14 -0
  211. package/dist/src/hooks/pre-tool-use.d.ts.map +1 -0
  212. package/dist/src/hooks/pre-tool-use.js +66 -0
  213. package/dist/src/hooks/pre-tool-use.js.map +1 -0
  214. package/dist/src/hooks/pre-tool-use.test.d.ts +2 -0
  215. package/dist/src/hooks/pre-tool-use.test.d.ts.map +1 -0
  216. package/dist/src/hooks/pre-tool-use.test.js +255 -0
  217. package/dist/src/hooks/pre-tool-use.test.js.map +1 -0
  218. package/dist/src/hooks/session-start.d.ts +20 -0
  219. package/dist/src/hooks/session-start.d.ts.map +1 -0
  220. package/dist/src/hooks/session-start.js +27 -0
  221. package/dist/src/hooks/session-start.js.map +1 -0
  222. package/dist/src/hooks/session-start.test.d.ts +2 -0
  223. package/dist/src/hooks/session-start.test.d.ts.map +1 -0
  224. package/dist/src/hooks/session-start.test.js +125 -0
  225. package/dist/src/hooks/session-start.test.js.map +1 -0
  226. package/dist/src/hooks/user-prompt-submit.d.ts +17 -0
  227. package/dist/src/hooks/user-prompt-submit.d.ts.map +1 -0
  228. package/dist/src/hooks/user-prompt-submit.js +28 -0
  229. package/dist/src/hooks/user-prompt-submit.js.map +1 -0
  230. package/dist/src/hooks/user-prompt-submit.test.d.ts +2 -0
  231. package/dist/src/hooks/user-prompt-submit.test.d.ts.map +1 -0
  232. package/dist/src/hooks/user-prompt-submit.test.js +119 -0
  233. package/dist/src/hooks/user-prompt-submit.test.js.map +1 -0
  234. package/dist/src/hooks/validate-commit.d.ts +12 -0
  235. package/dist/src/hooks/validate-commit.d.ts.map +1 -0
  236. package/dist/src/hooks/validate-commit.js +58 -0
  237. package/dist/src/hooks/validate-commit.js.map +1 -0
  238. package/dist/src/hooks/validate-commit.test.d.ts +2 -0
  239. package/dist/src/hooks/validate-commit.test.d.ts.map +1 -0
  240. package/dist/src/hooks/validate-commit.test.js +150 -0
  241. package/dist/src/hooks/validate-commit.test.js.map +1 -0
  242. package/dist/src/index.d.ts +18 -0
  243. package/dist/src/index.d.ts.map +1 -0
  244. package/dist/src/index.js +42 -0
  245. package/dist/src/index.js.map +1 -0
  246. package/dist/src/linker.d.ts +6 -0
  247. package/dist/src/linker.d.ts.map +1 -0
  248. package/dist/src/linker.js +78 -0
  249. package/dist/src/linker.js.map +1 -0
  250. package/dist/src/linker.test.d.ts +2 -0
  251. package/dist/src/linker.test.d.ts.map +1 -0
  252. package/dist/src/linker.test.js +192 -0
  253. package/dist/src/linker.test.js.map +1 -0
  254. package/dist/src/logger.d.ts +21 -0
  255. package/dist/src/logger.d.ts.map +1 -0
  256. package/dist/src/logger.js +117 -0
  257. package/dist/src/logger.js.map +1 -0
  258. package/dist/src/logger.test.d.ts +2 -0
  259. package/dist/src/logger.test.d.ts.map +1 -0
  260. package/dist/src/logger.test.js +159 -0
  261. package/dist/src/logger.test.js.map +1 -0
  262. package/dist/src/path-resolver.d.ts +9 -0
  263. package/dist/src/path-resolver.d.ts.map +1 -0
  264. package/dist/src/path-resolver.js +52 -0
  265. package/dist/src/path-resolver.js.map +1 -0
  266. package/dist/src/reminder-loader.d.ts +24 -0
  267. package/dist/src/reminder-loader.d.ts.map +1 -0
  268. package/dist/src/reminder-loader.js +84 -0
  269. package/dist/src/reminder-loader.js.map +1 -0
  270. package/dist/src/reminder-loader.test.d.ts +2 -0
  271. package/dist/src/reminder-loader.test.d.ts.map +1 -0
  272. package/dist/src/reminder-loader.test.js +152 -0
  273. package/dist/src/reminder-loader.test.js.map +1 -0
  274. package/dist/src/root-finder.d.ts +2 -0
  275. package/dist/src/root-finder.d.ts.map +1 -0
  276. package/dist/src/root-finder.js +71 -0
  277. package/dist/src/root-finder.js.map +1 -0
  278. package/dist/src/root-finder.test.d.ts +2 -0
  279. package/dist/src/root-finder.test.d.ts.map +1 -0
  280. package/dist/src/root-finder.test.js +111 -0
  281. package/dist/src/root-finder.test.js.map +1 -0
  282. package/dist/src/settings-merger.d.ts +2 -0
  283. package/dist/src/settings-merger.d.ts.map +1 -0
  284. package/dist/src/settings-merger.js +133 -0
  285. package/dist/src/settings-merger.js.map +1 -0
  286. package/dist/src/settings-merger.test.d.ts +2 -0
  287. package/dist/src/settings-merger.test.d.ts.map +1 -0
  288. package/dist/src/settings-merger.test.js +379 -0
  289. package/dist/src/settings-merger.test.js.map +1 -0
  290. package/dist/src/settings-template.test.d.ts +2 -0
  291. package/dist/src/settings-template.test.d.ts.map +1 -0
  292. package/dist/src/settings-template.test.js +88 -0
  293. package/dist/src/settings-template.test.js.map +1 -0
  294. package/dist/src/state-manager.d.ts +5 -0
  295. package/dist/src/state-manager.d.ts.map +1 -0
  296. package/dist/src/state-manager.js +55 -0
  297. package/dist/src/state-manager.js.map +1 -0
  298. package/dist/src/state-manager.test.d.ts +2 -0
  299. package/dist/src/state-manager.test.d.ts.map +1 -0
  300. package/dist/src/state-manager.test.js +85 -0
  301. package/dist/src/state-manager.test.js.map +1 -0
  302. package/dist/src/subagent-classifier.d.ts +4 -0
  303. package/dist/src/subagent-classifier.d.ts.map +1 -0
  304. package/dist/src/subagent-classifier.js +53 -0
  305. package/dist/src/subagent-classifier.js.map +1 -0
  306. package/dist/src/subagent-classifier.test.d.ts +2 -0
  307. package/dist/src/subagent-classifier.test.d.ts.map +1 -0
  308. package/dist/src/subagent-classifier.test.js +84 -0
  309. package/dist/src/subagent-classifier.test.js.map +1 -0
  310. package/dist/src/validator-loader.d.ts +9 -0
  311. package/dist/src/validator-loader.d.ts.map +1 -0
  312. package/dist/src/validator-loader.js +71 -0
  313. package/dist/src/validator-loader.js.map +1 -0
  314. package/dist/src/validator-loader.test.d.ts +2 -0
  315. package/dist/src/validator-loader.test.d.ts.map +1 -0
  316. package/dist/src/validator-loader.test.js +140 -0
  317. package/dist/src/validator-loader.test.js.map +1 -0
  318. package/package.json +91 -0
  319. package/scripts/auto-continue.ts +39 -0
  320. package/scripts/generate-changeset.ts +405 -0
  321. package/scripts/pre-tool-use.ts +44 -0
  322. package/scripts/session-start.ts +42 -0
  323. package/scripts/tail-logs.sh +17 -0
  324. package/scripts/test-hooks.sh +910 -0
  325. package/scripts/user-prompt-submit.ts +42 -0
  326. package/templates/settings.json +48 -0
  327. package/templates/settings.local.json +48 -0
@@ -0,0 +1,25 @@
1
+ {
2
+ "autoContinue": {
3
+ "mode": "smart",
4
+ "maxIterations": 0,
5
+ "iteration": 0,
6
+ "skipModes": ["plan"]
7
+ },
8
+ "validateCommit": {
9
+ "mode": "strict"
10
+ },
11
+ "denyList": {
12
+ "enabled": true,
13
+ "extraPatterns": []
14
+ },
15
+ "promptReminder": {
16
+ "enabled": true
17
+ },
18
+ "subagentHooks": {
19
+ "validateCommitOnExplore": false,
20
+ "validateCommitOnWork": true,
21
+ "validateCommitOnUnknown": true
22
+ },
23
+ "updatedAt": "2026-02-02T03:14:27.243Z",
24
+ "updatedBy": "init"
25
+ }
@@ -0,0 +1,145 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # Claude Auto Core Reminder
8
+
9
+ > Controlled Bursts | TDD | TCR | 100% Coverage
10
+
11
+ ## Core Loop
12
+
13
+ ```
14
+ Red → Green → TCR → Refactor → TCR → Done
15
+ TCR: test && commit || revert
16
+ - Pass → commit → continue
17
+ - Fail → REVERT → RETHINK (smaller steps or new design)
18
+ ```
19
+
20
+ Never patch failing code. Revert, learn, try differently.
21
+
22
+ ## Bursts
23
+
24
+ One test, one behavior, one commit. No exceptions.
25
+
26
+ Each burst: independent, valuable, small, testable, reviewable.
27
+
28
+ The constraint is scope, not time. Keep bursts small enough that:
29
+
30
+ - You stay focused on one thing
31
+ - The operator can verify quickly
32
+ - A revert loses minimal work
33
+
34
+ E2E exception: E2E tests may combine 2 tightly-coupled bursts when splitting creates artificial boundaries.
35
+
36
+ ## Workflow
37
+
38
+ 1. Create `ketchup-plan.md` with TODO/DONE sections, commit before coding
39
+ 2. Write ONE failing test
40
+ 3. Write MINIMAL passing code
41
+ 4. TCR (update plan in same commit)
42
+ 5. Refactor if needed → TCR
43
+ 6. Move burst to DONE → TCR
44
+ 7. Next burst
45
+
46
+ ```markdown
47
+ # Ketchup Plan: [Feature]
48
+
49
+ ## TODO
50
+
51
+ - [ ] Burst 1: [description]
52
+
53
+ ## DONE
54
+
55
+ - [x] Burst N: [description] (hash)
56
+ ```
57
+
58
+ ## Refactoring
59
+
60
+ Refactor for readability, not for explanation. If code is complex, rename variables or extract functions. Do not add comments.
61
+
62
+ ## Coverage
63
+
64
+ 100% enforced. No escape hatches.
65
+
66
+ Exclusions allowed ONLY for: barrel `index.ts` re-exports, `*.test.ts` files
67
+
68
+ Forbidden:
69
+
70
+ - Excluding files to avoid testing them
71
+ - Standalone type files (`types.ts`, `interfaces.ts`) — types live inline where used
72
+ - `@ts-ignore`, `any`, `as SomeType` casts
73
+
74
+ | Do | Don't |
75
+ | ------------------------------- | ---------------------------------------- |
76
+ | Let tests drive all code | Write code without a failing test first |
77
+ | Add branches only when tested | Defensive `??`, `?:`, `if/else` untested |
78
+ | Test all error paths | Leave error handling unverified |
79
+ | Remove dead code after each run | Keep unused code "just in case" |
80
+
81
+ ## Testing Rules
82
+
83
+ **Assertion Strength:** Never use weak assertions (`toBeDefined`, `toBeTruthy`, `not.toBeNull`). Assert the exact shape and value. If you don't know the exact value, use `expect.any(String)` or `expect.any(Number)`.
84
+
85
+ **Stubs over mocks:** Deterministic stubs preferred. Mock only at boundaries.
86
+
87
+ **Assert whole objects:** `expect(result).toEqual({...})` not cherry-picked properties.
88
+
89
+ **Squint test:** All tests must follow: SETUP (data) → EXECUTE (function call) → VERIFY (whole object assertion). No multiple execute/verify cycles in one test.
90
+
91
+ **No state peeking:** Test observable behavior, not internal state.
92
+
93
+ Litmus Test: "If I changed the internal data structure (e.g., Map to Array), would this test still pass?" If no, the test is coupled to implementation.
94
+
95
+ | Forbidden (Implementation) | Allowed (Behavior) |
96
+ | ------------------------------------------------------- | ------------------------------------------------------------------------- |
97
+ | `expect(tracker.getActiveCount()).toBe(0)` | Test via callbacks/events |
98
+ | `expect(manager.clientCount).toBe(3)` | `tracker.onEvent(e => events.push(e))` |
99
+ | `expect(service["internalMap"].size).toBe(2)` | Test via return values |
100
+ | `tracker.cleanup(); expect(tracker.getCount()).toBe(0)` | Test cleanup by re-triggering: start same id, verify callback fires again |
101
+
102
+ **Do NOT expose methods solely for testing.** If you're adding `.getCount()` or `.getActiveSessionCount()` just to make tests pass, you're testing implementation, not behavior.
103
+
104
+ ## Guardrails
105
+
106
+ - No comments — write self-expressing code
107
+ - No excuses, no "you're right" — keep working
108
+ - JS files only in `dist/`
109
+ - When tests fail, assume you broke it. CI passed before; your change is the variable.
110
+
111
+ **Backwards compatibility:** Ask first. Default to clean breaks. No silent preservation unless explicitly requested.
112
+
113
+ Backwards-compatibility hacks to avoid:
114
+
115
+ - Re-exporting moved/renamed symbols
116
+ - Keeping unused parameters with `_` prefix
117
+ - Adding `// @deprecated` comments for removed code
118
+ - Wrapper functions that delegate to new implementations
119
+
120
+ ## Infrastructure Commits
121
+
122
+ Config files need no tests: `package.json`, `tsconfig.json`, `wrangler.toml`, `vite.config.ts`, `vitest.config.ts`, `.gitignore`, `ketchup-plan.md`
123
+
124
+ Format: `chore(scope): description`
125
+
126
+ First behavioral `.ts` file requires a test.
127
+
128
+ ## Plea System
129
+
130
+ If the commit validator rejects your commit but you believe it's valid, add `plea: <reason>` to your commit message.
131
+
132
+ **Valid pleas:**
133
+
134
+ - Files must be committed together for coherence
135
+ - Existing code lacked coverage before your changes
136
+
137
+ **Invalid pleas (will be rejected):**
138
+
139
+ - Skipping tests for new code
140
+ - Untested code paths
141
+ - Any other CLAUDE.md rule bypass
142
+
143
+ ## Misc
144
+
145
+ - No "Generated with Claude Code" in commits
@@ -0,0 +1,30 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # Documentation Reminder
8
+
9
+ Documentation is code. Outdated docs are bugs.
10
+
11
+ ## When to Update Docs
12
+
13
+ Update documentation when:
14
+ - Adding features
15
+ - Changing APIs
16
+ - Completing milestones
17
+
18
+ ## When NOT to Create New Docs
19
+
20
+ Do not create new documentation files unless the feature explicitly requires them.
21
+
22
+ Avoid:
23
+ - Creating README files proactively
24
+ - Adding markdown files "for completeness"
25
+ - Documenting internal implementation details
26
+
27
+ Prefer:
28
+ - Self-documenting code
29
+ - Updating existing docs
30
+ - Inline JSDoc for public APIs only
@@ -0,0 +1,41 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # Emergent Design Reminder
8
+
9
+ Behavior first. Types/interfaces emerge from tests.
10
+
11
+ ## The Principle
12
+
13
+ Don't design types upfront. Let them emerge from what the tests require.
14
+
15
+ ## Example
16
+
17
+ ```typescript
18
+ // First: Write a test that calls a function and asserts output
19
+ it("creates user with generated id", () => {
20
+ const result = createUser({ name: "Alice" });
21
+ expect(result).toEqual({ id: expect.any(String), name: "Alice" });
22
+ });
23
+
24
+ // Then: Types emerge because the function needs them
25
+ // The test drove the need for: input type, output type, id generation
26
+ ```
27
+
28
+ ## Anti-Pattern
29
+
30
+ ```typescript
31
+ // Don't do this: types/user.ts
32
+ interface User {
33
+ id: string;
34
+ name: string;
35
+ email: string;
36
+ createdAt: Date;
37
+ // ... 20 more fields "just in case"
38
+ }
39
+ ```
40
+
41
+ Types should be minimal and driven by actual test requirements, not speculative design.
@@ -0,0 +1,27 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # Extreme Ownership Reminder
8
+
9
+ Every problem is your problem. No deflection. No explaining why something is broken.
10
+
11
+ ## The Rule
12
+
13
+ See a problem → fix it or add a burst to fix it. No third option.
14
+
15
+ If you read a file, you're responsible for its state when you're done.
16
+
17
+ ## Wrong vs Right Responses
18
+
19
+ | Situation | Wrong Response | Ownership Response |
20
+ | ------------------------ | --------------------------------------- | ----------------------------- |
21
+ | Bug in existing code | "The existing code has a bug where..." | Fix it or add burst to fix it |
22
+ | Test suite has gaps | "Coverage was incomplete before..." | Add the missing tests |
23
+ | Confusing function names | "The naming is unclear in this file..." | Rename in refactor step |
24
+ | Missing error handling | "Error handling wasn't implemented..." | Add it now |
25
+ | Flaky test | "This test appears to be unreliable..." | Stabilize it or add burst |
26
+
27
+ No excuses. No "you're right." Keep working.
@@ -0,0 +1,25 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # IDE Diagnostics Reminder
8
+
9
+ Before committing, check IDE diagnostics on all uncommitted files.
10
+
11
+ ## Pre-Commit Checklist
12
+
13
+ 1. Review all files with uncommitted changes
14
+ 2. Check for TypeScript errors (red squiggles)
15
+ 3. Check for warnings (yellow squiggles)
16
+ 4. Ensure no linting errors remain
17
+ 5. Verify imports are correctly resolved
18
+
19
+ ## TCR Command
20
+
21
+ ```bash
22
+ pnpm test --run && git add -A && git commit -m "<MSG>" || git checkout -- .
23
+ ```
24
+
25
+ The tests will catch most issues, but IDE diagnostics can catch type errors and import issues before you even run tests.
@@ -0,0 +1,27 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # Parallelization Reminder
8
+
9
+ Maximize parallel execution. Launch multiple sub-agents when:
10
+
11
+ - Bursts have no dependencies on each other (`[depends: none]`)
12
+ - Exploration can be split by area (e.g., "search tests" + "search implementation")
13
+ - Multiple files need similar changes
14
+
15
+ ## Dependency Notation
16
+
17
+ ```markdown
18
+ ### Bottle: Authentication
19
+ - [ ] Burst 10: createUser returns user object [depends: none]
20
+ - [ ] Burst 11: hashPassword uses bcrypt [depends: none]
21
+ - [ ] Burst 12: validatePassword checks hash [depends: 11]
22
+ ```
23
+
24
+ **Rules:**
25
+ - `[depends: none]` - can start immediately, parallelizable with other `none` bursts
26
+ - `[depends: N]` - must wait for burst N to complete
27
+ - Bursts at the same dependency level can run in parallel
@@ -0,0 +1,25 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # RETHINK After Revert Reminder
8
+
9
+ After a revert, do NOT immediately retry the same approach.
10
+
11
+ ## Ask These Questions First
12
+
13
+ 1. **Was the burst too big?** → Split it into smaller bursts
14
+ 2. **Was the design flawed?** → Try a different approach entirely
15
+ 3. **Was the test wrong?** → Clarify the requirement before writing code
16
+
17
+ ## Then
18
+
19
+ Only after answering these questions, write the next failing test.
20
+
21
+ Never patch failing code. The TCR pattern means:
22
+ - Pass → commit → continue
23
+ - Fail → REVERT → RETHINK (smaller steps or new design)
24
+
25
+ A revert is a signal to change your approach, not to try harder at the same thing.
@@ -0,0 +1,27 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # Sub-Agent Rules Reminder
8
+
9
+ When spawning a Task agent (sub-agent), ensure:
10
+
11
+ 1. **Include CLAUDE.md context** - Sub-agents must receive and follow these rules
12
+ 2. **Include ketchup-plan.md** - Sub-agents work from the same plan
13
+ 3. **No orphan work** - Sub-agent output must be committed by parent or sub-agent
14
+
15
+ Sub-agents follow identical rules to the parent. They are not exempt from any CLAUDE.md requirements.
16
+
17
+ ## Prompt Pattern
18
+
19
+ ```
20
+ You are working on [bottle name]. Follow CLAUDE.md rules exactly.
21
+
22
+ Your burst: [burst description]
23
+ Dependencies: [list completed bursts this depends on, or "none"]
24
+ Parallel with: [list of bursts running concurrently]
25
+
26
+ [specific instructions]
27
+ ```
@@ -0,0 +1,37 @@
1
+ ---
2
+ when:
3
+ hook: SessionStart
4
+ priority: 100
5
+ ---
6
+
7
+ # Test Title = Spec Reminder
8
+
9
+ The test body must prove exactly what `it('should...')` claims.
10
+
11
+ ## The Principle
12
+
13
+ **Title = Spec:** One assertion per behavior. The test title is the specification; the test body is the proof.
14
+
15
+ ## Example
16
+
17
+ ```typescript
18
+ // Good: Title matches what's being tested
19
+ it("creates user with generated id", () => {
20
+ const result = createUser({ name: "Alice" });
21
+ expect(result).toEqual({ id: expect.any(String), name: "Alice" });
22
+ });
23
+
24
+ // Bad: Title doesn't match assertion
25
+ it("creates user with generated id", () => {
26
+ const result = createUser({ name: "Alice" });
27
+ expect(result.name).toBe("Alice"); // Not testing the ID!
28
+ });
29
+ ```
30
+
31
+ ## Ask Yourself
32
+
33
+ "Does this test body prove exactly what the `it()` description claims?"
34
+
35
+ If not, either:
36
+ 1. Fix the test body to prove the claim
37
+ 2. Fix the title to match what you're actually testing
@@ -0,0 +1,55 @@
1
+ ---
2
+ name: appeal-system
3
+ description: Evaluates appeals against validator NACKs
4
+ enabled: true
5
+ ---
6
+
7
+ You are the appeal system. You receive validator results and an appeal, and decide whether the appeal justifies overriding the NACKs.
8
+
9
+ You MUST respond with ONLY a JSON object, no other text.
10
+
11
+ Valid responses:
12
+ {"decision":"ACK"}
13
+ {"decision":"NACK","reason":"one sentence explanation"}
14
+
15
+ **Input you receive:**
16
+ - Full commit context (diff, files, commit message)
17
+ - All validator results (which validators ran, their decisions, their reasons)
18
+ - Appeal text extracted from the commit message
19
+
20
+ **Valid appeal scenarios:**
21
+
22
+ 1. **Coherence**: Files must be committed together for coherence. The changes are tightly coupled and splitting them would create an inconsistent state.
23
+
24
+ 2. **Existing Gap**: Existing code lacked coverage before these changes. The violation existed before this commit and is not introduced by the current changes.
25
+
26
+ 3. **Debug Branchless**: Test coverage not required for branchless debug statements. Simple logging or debug output that contains no conditional logic.
27
+
28
+ **ALWAYS NACK if:**
29
+ - The `no-dangerous-git` validator appears in the results with a NACK (this is non-appealable - dangerous git operations cannot be overridden)
30
+ - The appeal text does not describe one of the valid scenarios above
31
+ - The appeal does not justify each NACK - every rejected validator must be addressed by the appeal
32
+
33
+ **ACK if:**
34
+ - The appeal text describes a valid scenario from the list above
35
+ - The appeal reasonably justifies each appealable NACK
36
+ - The `no-dangerous-git` validator either did not run or returned ACK
37
+
38
+ **Examples:**
39
+
40
+ Appeal: "these files are tightly coupled and must be committed together"
41
+ → Valid coherence appeal
42
+
43
+ Appeal: "the coverage gap existed before my changes"
44
+ → Valid existing-gap appeal
45
+
46
+ Appeal: "this is just a console.log with no branches"
47
+ → Valid debug-branchless appeal
48
+
49
+ Appeal: "I don't have time to write tests"
50
+ → Invalid - not a valid scenario
51
+
52
+ Appeal: "please let this through"
53
+ → Invalid - not a valid scenario
54
+
55
+ RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: backwards-compat
3
+ description: Enforces clean breaks over compatibility hacks
4
+ enabled: true
5
+ ---
6
+
7
+ You are a commit validator. You MUST respond with ONLY a JSON object, no other text.
8
+
9
+ Valid responses:
10
+ {"decision":"ACK"}
11
+ {"decision":"NACK","reason":"one sentence explanation"}
12
+
13
+ **Scope:** Validate any .ts file changes in the diff.
14
+
15
+ Default to clean breaks. No silent preservation of old APIs.
16
+
17
+ **NACK if the diff contains:**
18
+ - Re-exports of moved/renamed symbols for backwards compatibility
19
+ - `@deprecated` comments or JSDoc tags
20
+ - Wrapper functions that only delegate to new implementations
21
+ - Unused parameters with `_` prefix kept for signature compatibility
22
+ - Shim files that import from new location and re-export
23
+ - `// removed` or similar comments for deleted code
24
+
25
+ **ACK if:**
26
+ - The diff makes clean changes without compatibility layers
27
+ - Old code is simply removed, not shimmed
28
+ - The diff only contains non-.ts files
29
+ - Refactoring removes old code entirely
30
+
31
+ **Plea override:** If files must be committed together for coherence during a rename/refactor, use `plea: files must be committed together for coherence` in the commit message.
32
+
33
+ RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: burst-atomicity
3
+ description: Validates commits are single focused bursts
4
+ enabled: true
5
+ ---
6
+
7
+ You are a commit validator. You MUST respond with ONLY a JSON object, no other text.
8
+
9
+ Valid responses:
10
+ {"decision":"ACK"}
11
+ {"decision":"NACK","reason":"one sentence explanation"}
12
+
13
+ **Scope:** Validate that each commit represents a single, focused burst.
14
+
15
+ Enforce the burst principle: One test, one behavior, one commit.
16
+
17
+ **ACK if:**
18
+ - The commit appears to be one logical unit of work
19
+ - Files changed are related to the same feature/fix/refactor
20
+ - Test files accompany their implementation files (this is expected, not a violation)
21
+ - ketchup-plan.md updates accompany the code they describe (per workflow)
22
+ - E2E tests combine 2 tightly-coupled behaviors (this exception is allowed)
23
+
24
+ **NACK if:**
25
+ - The commit combines clearly unrelated changes (e.g., feature code + unrelated config cleanup)
26
+ - Multiple distinct features or fixes are bundled together
27
+ - Files from different subsystems are modified without clear connection
28
+ - The commit tries to do too much in one burst
29
+
30
+ **Burst qualities to verify:**
31
+ - Independent: can be understood alone
32
+ - Valuable: adds something useful
33
+ - Small: minimal scope
34
+ - Testable: has corresponding test
35
+ - Reviewable: can be verified quickly
36
+
37
+ RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: coverage-rules
3
+ description: Enforces 100% code coverage requirements
4
+ enabled: true
5
+ ---
6
+
7
+ You are a commit validator. You MUST respond with ONLY a JSON object, no other text.
8
+
9
+ Valid responses:
10
+ {"decision":"ACK"}
11
+ {"decision":"NACK","reason":"one sentence explanation"}
12
+
13
+ **Scope:** Only validate .ts and .tsx files in the diff (ignore .md, .json, config files).
14
+
15
+ Enforce 100% coverage with no escape hatches:
16
+
17
+ **NACK if the diff contains:**
18
+ - `@ts-ignore` or `@ts-expect-error` comments
19
+ - `any` type annotations (except in test mocks at system boundaries)
20
+ - `as SomeType` type casts that bypass type safety
21
+ - Coverage exclusion patterns: `/* istanbul ignore */`, `/* c8 ignore */`, `/* v8 ignore */`
22
+
23
+ **Allowed exclusions (do not NACK):**
24
+ - Barrel `index.ts` files that only contain re-exports
25
+ - `*.test.ts` and `*.test.tsx` files
26
+
27
+ **ACK if:**
28
+ - No forbidden patterns are found in .ts/.tsx source files
29
+ - The diff only contains .md, .json, or config files
30
+ - The forbidden patterns appear only in allowed exclusion files
31
+
32
+ **Note:** This validator checks for escape hatches. Actual coverage percentage is verified by the test runner.
33
+
34
+ RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: dead-code
3
+ description: Detects unused code that should be removed
4
+ enabled: true
5
+ ---
6
+
7
+ You are a commit validator. You MUST respond with ONLY a JSON object, no other text.
8
+
9
+ Valid responses:
10
+ {"decision":"ACK"}
11
+ {"decision":"NACK","reason":"one sentence explanation"}
12
+
13
+ **Scope:** Validate .ts and .tsx files in the diff.
14
+
15
+ Remove dead code after each change. No unused code kept "just in case."
16
+
17
+ **NACK if the diff contains:**
18
+ - Unused imports (imported but never referenced)
19
+ - Unused variables (declared but never used)
20
+ - Unused functions (defined but never called)
21
+ - Commented-out code blocks
22
+ - Unreachable code after return/throw statements
23
+ - Empty function bodies with no implementation
24
+
25
+ **ACK if:**
26
+ - All imports are used
27
+ - All declared variables are referenced
28
+ - All functions are called or exported
29
+ - No commented-out code exists
30
+ - The diff only contains .md, .json, or config files
31
+
32
+ **Note:** This validator checks for obvious dead code patterns. Complex unused code detection may require static analysis tools.
33
+
34
+ **Exception:** Exported functions in library code that are part of the public API are not dead code even if not used internally.
35
+
36
+ RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: hygiene
3
+ description: Enforces codebase hygiene and organization rules
4
+ enabled: true
5
+ ---
6
+
7
+ You are a commit validator. You MUST respond with ONLY a JSON object, no other text.
8
+
9
+ Valid responses:
10
+ {"decision":"ACK"}
11
+ {"decision":"NACK","reason":"one sentence explanation"}
12
+
13
+ **Scope:** Validate file organization and commit message content.
14
+
15
+ Enforce these hygiene rules:
16
+
17
+ **NACK if the diff contains:**
18
+ - `.js` files outside of `dist/` directory (JS files should only be build output)
19
+ - Commit message contains any of:
20
+ - "Co-Authored-By: Claude"
21
+ - "Generated with Claude Code"
22
+ - "Claude" attribution of any kind
23
+ - AI/LLM attribution in commit messages
24
+
25
+ **ACK if:**
26
+ - All `.js` files are within `dist/` directory
27
+ - Commit message has no Claude/AI attribution
28
+ - The diff only modifies existing files without violating the above rules
29
+
30
+ **Rationale:**
31
+ - Source code should be TypeScript (.ts), not JavaScript
32
+ - Commits should not contain AI attribution per project rules
33
+
34
+ RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.