claude-ketchup 0.7.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.
- package/README.md +172 -0
- package/bin/cli.ts +6 -0
- package/bin/postinstall.ts +8 -0
- package/bin/preuninstall.ts +8 -0
- package/commands/ketchup.md +107 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +7 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/postinstall.d.ts +3 -0
- package/dist/bin/postinstall.d.ts.map +1 -0
- package/dist/bin/postinstall.js +9 -0
- package/dist/bin/postinstall.js.map +1 -0
- package/dist/bin/preuninstall.d.ts +3 -0
- package/dist/bin/preuninstall.d.ts.map +1 -0
- package/dist/bin/preuninstall.js +9 -0
- package/dist/bin/preuninstall.js.map +1 -0
- package/dist/scripts/auto-continue.d.ts +3 -0
- package/dist/scripts/auto-continue.d.ts.map +1 -0
- package/dist/scripts/auto-continue.js +62 -0
- package/dist/scripts/auto-continue.js.map +1 -0
- package/dist/scripts/generate-changeset.d.ts +13 -0
- package/dist/scripts/generate-changeset.d.ts.map +1 -0
- package/dist/scripts/generate-changeset.js +322 -0
- package/dist/scripts/generate-changeset.js.map +1 -0
- package/dist/scripts/pre-tool-use.d.ts +3 -0
- package/dist/scripts/pre-tool-use.d.ts.map +1 -0
- package/dist/scripts/pre-tool-use.js +68 -0
- package/dist/scripts/pre-tool-use.js.map +1 -0
- package/dist/scripts/session-start.d.ts +3 -0
- package/dist/scripts/session-start.d.ts.map +1 -0
- package/dist/scripts/session-start.js +71 -0
- package/dist/scripts/session-start.js.map +1 -0
- package/dist/scripts/user-prompt-submit.d.ts +3 -0
- package/dist/scripts/user-prompt-submit.d.ts.map +1 -0
- package/dist/scripts/user-prompt-submit.js +71 -0
- package/dist/scripts/user-prompt-submit.js.map +1 -0
- package/dist/src/activity-logger.d.ts +2 -0
- package/dist/src/activity-logger.d.ts.map +1 -0
- package/dist/src/activity-logger.js +47 -0
- package/dist/src/activity-logger.js.map +1 -0
- package/dist/src/activity-logger.test.d.ts +2 -0
- package/dist/src/activity-logger.test.d.ts.map +1 -0
- package/dist/src/activity-logger.test.js +121 -0
- package/dist/src/activity-logger.test.js.map +1 -0
- package/dist/src/clean-logs.d.ts +6 -0
- package/dist/src/clean-logs.d.ts.map +1 -0
- package/dist/src/clean-logs.js +38 -0
- package/dist/src/clean-logs.js.map +1 -0
- package/dist/src/clean-logs.test.d.ts +2 -0
- package/dist/src/clean-logs.test.d.ts.map +1 -0
- package/dist/src/clean-logs.test.js +101 -0
- package/dist/src/clean-logs.test.js.map +1 -0
- package/dist/src/cli/cli.d.ts +3 -0
- package/dist/src/cli/cli.d.ts.map +1 -0
- package/dist/src/cli/cli.js +26 -0
- package/dist/src/cli/cli.js.map +1 -0
- package/dist/src/cli/cli.test.d.ts +2 -0
- package/dist/src/cli/cli.test.d.ts.map +1 -0
- package/dist/src/cli/cli.test.js +20 -0
- package/dist/src/cli/cli.test.js.map +1 -0
- package/dist/src/cli/doctor.d.ts +7 -0
- package/dist/src/cli/doctor.d.ts.map +1 -0
- package/dist/src/cli/doctor.js +67 -0
- package/dist/src/cli/doctor.js.map +1 -0
- package/dist/src/cli/doctor.test.d.ts +2 -0
- package/dist/src/cli/doctor.test.d.ts.map +1 -0
- package/dist/src/cli/doctor.test.js +87 -0
- package/dist/src/cli/doctor.test.js.map +1 -0
- package/dist/src/cli/install.d.ts +8 -0
- package/dist/src/cli/install.d.ts.map +1 -0
- package/dist/src/cli/install.js +8 -0
- package/dist/src/cli/install.js.map +1 -0
- package/dist/src/cli/install.test.d.ts +2 -0
- package/dist/src/cli/install.test.d.ts.map +1 -0
- package/dist/src/cli/install.test.js +106 -0
- package/dist/src/cli/install.test.js.map +1 -0
- package/dist/src/cli/reminders.d.ts +12 -0
- package/dist/src/cli/reminders.d.ts.map +1 -0
- package/dist/src/cli/reminders.js +52 -0
- package/dist/src/cli/reminders.js.map +1 -0
- package/dist/src/cli/reminders.test.d.ts +2 -0
- package/dist/src/cli/reminders.test.d.ts.map +1 -0
- package/dist/src/cli/reminders.test.js +72 -0
- package/dist/src/cli/reminders.test.js.map +1 -0
- package/dist/src/cli/repair.d.ts +11 -0
- package/dist/src/cli/repair.d.ts.map +1 -0
- package/dist/src/cli/repair.js +91 -0
- package/dist/src/cli/repair.js.map +1 -0
- package/dist/src/cli/repair.test.d.ts +2 -0
- package/dist/src/cli/repair.test.d.ts.map +1 -0
- package/dist/src/cli/repair.test.js +96 -0
- package/dist/src/cli/repair.test.js.map +1 -0
- package/dist/src/cli/status.d.ts +10 -0
- package/dist/src/cli/status.d.ts.map +1 -0
- package/dist/src/cli/status.js +55 -0
- package/dist/src/cli/status.js.map +1 -0
- package/dist/src/cli/status.test.d.ts +2 -0
- package/dist/src/cli/status.test.d.ts.map +1 -0
- package/dist/src/cli/status.test.js +83 -0
- package/dist/src/cli/status.test.js.map +1 -0
- package/dist/src/clue-collector.d.ts +23 -0
- package/dist/src/clue-collector.d.ts.map +1 -0
- package/dist/src/clue-collector.js +221 -0
- package/dist/src/clue-collector.js.map +1 -0
- package/dist/src/clue-collector.test.d.ts +2 -0
- package/dist/src/clue-collector.test.d.ts.map +1 -0
- package/dist/src/clue-collector.test.js +278 -0
- package/dist/src/clue-collector.test.js.map +1 -0
- package/dist/src/commit-validator.d.ts +35 -0
- package/dist/src/commit-validator.d.ts.map +1 -0
- package/dist/src/commit-validator.js +147 -0
- package/dist/src/commit-validator.js.map +1 -0
- package/dist/src/commit-validator.test.d.ts +2 -0
- package/dist/src/commit-validator.test.d.ts.map +1 -0
- package/dist/src/commit-validator.test.js +443 -0
- package/dist/src/commit-validator.test.js.map +1 -0
- package/dist/src/config-loader.d.ts +15 -0
- package/dist/src/config-loader.d.ts.map +1 -0
- package/dist/src/config-loader.js +12 -0
- package/dist/src/config-loader.js.map +1 -0
- package/dist/src/config-loader.test.d.ts +2 -0
- package/dist/src/config-loader.test.d.ts.map +1 -0
- package/dist/src/config-loader.test.js +69 -0
- package/dist/src/config-loader.test.js.map +1 -0
- package/dist/src/debug-logger.d.ts +2 -0
- package/dist/src/debug-logger.d.ts.map +1 -0
- package/dist/src/debug-logger.js +23 -0
- package/dist/src/debug-logger.js.map +1 -0
- package/dist/src/debug-logger.test.d.ts +2 -0
- package/dist/src/debug-logger.test.d.ts.map +1 -0
- package/dist/src/debug-logger.test.js +63 -0
- package/dist/src/debug-logger.test.js.map +1 -0
- package/dist/src/default-validators.test.d.ts +2 -0
- package/dist/src/default-validators.test.d.ts.map +1 -0
- package/dist/src/default-validators.test.js +119 -0
- package/dist/src/default-validators.test.js.map +1 -0
- package/dist/src/deny-list.d.ts +3 -0
- package/dist/src/deny-list.d.ts.map +1 -0
- package/dist/src/deny-list.js +62 -0
- package/dist/src/deny-list.js.map +1 -0
- package/dist/src/deny-list.test.d.ts +2 -0
- package/dist/src/deny-list.test.d.ts.map +1 -0
- package/dist/src/deny-list.test.js +93 -0
- package/dist/src/deny-list.test.js.map +1 -0
- package/dist/src/e2e.test.d.ts +2 -0
- package/dist/src/e2e.test.d.ts.map +1 -0
- package/dist/src/e2e.test.js +89 -0
- package/dist/src/e2e.test.js.map +1 -0
- package/dist/src/gitignore-manager.d.ts +2 -0
- package/dist/src/gitignore-manager.d.ts.map +1 -0
- package/dist/src/gitignore-manager.js +45 -0
- package/dist/src/gitignore-manager.js.map +1 -0
- package/dist/src/gitignore-manager.test.d.ts +2 -0
- package/dist/src/gitignore-manager.test.d.ts.map +1 -0
- package/dist/src/gitignore-manager.test.js +65 -0
- package/dist/src/gitignore-manager.test.js.map +1 -0
- package/dist/src/hook-input.d.ts +9 -0
- package/dist/src/hook-input.d.ts.map +1 -0
- package/dist/src/hook-input.js +7 -0
- package/dist/src/hook-input.js.map +1 -0
- package/dist/src/hook-input.test.d.ts +2 -0
- package/dist/src/hook-input.test.d.ts.map +1 -0
- package/dist/src/hook-input.test.js +20 -0
- package/dist/src/hook-input.test.js.map +1 -0
- package/dist/src/hook-logger.d.ts +16 -0
- package/dist/src/hook-logger.d.ts.map +1 -0
- package/dist/src/hook-logger.js +91 -0
- package/dist/src/hook-logger.js.map +1 -0
- package/dist/src/hook-logger.test.d.ts +2 -0
- package/dist/src/hook-logger.test.d.ts.map +1 -0
- package/dist/src/hook-logger.test.js +184 -0
- package/dist/src/hook-logger.test.js.map +1 -0
- package/dist/src/hook-state.d.ts +43 -0
- package/dist/src/hook-state.d.ts.map +1 -0
- package/dist/src/hook-state.js +124 -0
- package/dist/src/hook-state.js.map +1 -0
- package/dist/src/hook-state.test.d.ts +2 -0
- package/dist/src/hook-state.test.d.ts.map +1 -0
- package/dist/src/hook-state.test.js +190 -0
- package/dist/src/hook-state.test.js.map +1 -0
- package/dist/src/hooks/auto-continue.d.ts +21 -0
- package/dist/src/hooks/auto-continue.d.ts.map +1 -0
- package/dist/src/hooks/auto-continue.js +70 -0
- package/dist/src/hooks/auto-continue.js.map +1 -0
- package/dist/src/hooks/auto-continue.test.d.ts +2 -0
- package/dist/src/hooks/auto-continue.test.d.ts.map +1 -0
- package/dist/src/hooks/auto-continue.test.js +171 -0
- package/dist/src/hooks/auto-continue.test.js.map +1 -0
- package/dist/src/hooks/pre-tool-use.d.ts +14 -0
- package/dist/src/hooks/pre-tool-use.d.ts.map +1 -0
- package/dist/src/hooks/pre-tool-use.js +62 -0
- package/dist/src/hooks/pre-tool-use.js.map +1 -0
- package/dist/src/hooks/pre-tool-use.test.d.ts +2 -0
- package/dist/src/hooks/pre-tool-use.test.d.ts.map +1 -0
- package/dist/src/hooks/pre-tool-use.test.js +168 -0
- package/dist/src/hooks/pre-tool-use.test.js.map +1 -0
- package/dist/src/hooks/session-start.d.ts +20 -0
- package/dist/src/hooks/session-start.d.ts.map +1 -0
- package/dist/src/hooks/session-start.js +27 -0
- package/dist/src/hooks/session-start.js.map +1 -0
- package/dist/src/hooks/session-start.test.d.ts +2 -0
- package/dist/src/hooks/session-start.test.d.ts.map +1 -0
- package/dist/src/hooks/session-start.test.js +125 -0
- package/dist/src/hooks/session-start.test.js.map +1 -0
- package/dist/src/hooks/user-prompt-submit.d.ts +17 -0
- package/dist/src/hooks/user-prompt-submit.d.ts.map +1 -0
- package/dist/src/hooks/user-prompt-submit.js +28 -0
- package/dist/src/hooks/user-prompt-submit.js.map +1 -0
- package/dist/src/hooks/user-prompt-submit.test.d.ts +2 -0
- package/dist/src/hooks/user-prompt-submit.test.d.ts.map +1 -0
- package/dist/src/hooks/user-prompt-submit.test.js +119 -0
- package/dist/src/hooks/user-prompt-submit.test.js.map +1 -0
- package/dist/src/hooks/validate-commit.d.ts +12 -0
- package/dist/src/hooks/validate-commit.d.ts.map +1 -0
- package/dist/src/hooks/validate-commit.js +58 -0
- package/dist/src/hooks/validate-commit.js.map +1 -0
- package/dist/src/hooks/validate-commit.test.d.ts +2 -0
- package/dist/src/hooks/validate-commit.test.d.ts.map +1 -0
- package/dist/src/hooks/validate-commit.test.js +150 -0
- package/dist/src/hooks/validate-commit.test.js.map +1 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +39 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/linker.d.ts +6 -0
- package/dist/src/linker.d.ts.map +1 -0
- package/dist/src/linker.js +78 -0
- package/dist/src/linker.js.map +1 -0
- package/dist/src/linker.test.d.ts +2 -0
- package/dist/src/linker.test.d.ts.map +1 -0
- package/dist/src/linker.test.js +192 -0
- package/dist/src/linker.test.js.map +1 -0
- package/dist/src/logger.d.ts +21 -0
- package/dist/src/logger.d.ts.map +1 -0
- package/dist/src/logger.js +117 -0
- package/dist/src/logger.js.map +1 -0
- package/dist/src/logger.test.d.ts +2 -0
- package/dist/src/logger.test.d.ts.map +1 -0
- package/dist/src/logger.test.js +159 -0
- package/dist/src/logger.test.js.map +1 -0
- package/dist/src/npm-install.test.d.ts +2 -0
- package/dist/src/npm-install.test.d.ts.map +1 -0
- package/dist/src/npm-install.test.js +70 -0
- package/dist/src/npm-install.test.js.map +1 -0
- package/dist/src/path-resolver.d.ts +11 -0
- package/dist/src/path-resolver.d.ts.map +1 -0
- package/dist/src/path-resolver.js +65 -0
- package/dist/src/path-resolver.js.map +1 -0
- package/dist/src/postinstall.d.ts +8 -0
- package/dist/src/postinstall.d.ts.map +1 -0
- package/dist/src/postinstall.js +112 -0
- package/dist/src/postinstall.js.map +1 -0
- package/dist/src/postinstall.test.d.ts +2 -0
- package/dist/src/postinstall.test.d.ts.map +1 -0
- package/dist/src/postinstall.test.js +203 -0
- package/dist/src/postinstall.test.js.map +1 -0
- package/dist/src/preuninstall.d.ts +3 -0
- package/dist/src/preuninstall.d.ts.map +1 -0
- package/dist/src/preuninstall.js +85 -0
- package/dist/src/preuninstall.js.map +1 -0
- package/dist/src/preuninstall.test.d.ts +2 -0
- package/dist/src/preuninstall.test.d.ts.map +1 -0
- package/dist/src/preuninstall.test.js +114 -0
- package/dist/src/preuninstall.test.js.map +1 -0
- package/dist/src/reminder-loader.d.ts +24 -0
- package/dist/src/reminder-loader.d.ts.map +1 -0
- package/dist/src/reminder-loader.js +84 -0
- package/dist/src/reminder-loader.js.map +1 -0
- package/dist/src/reminder-loader.test.d.ts +2 -0
- package/dist/src/reminder-loader.test.d.ts.map +1 -0
- package/dist/src/reminder-loader.test.js +152 -0
- package/dist/src/reminder-loader.test.js.map +1 -0
- package/dist/src/root-finder.d.ts +2 -0
- package/dist/src/root-finder.d.ts.map +1 -0
- package/dist/src/root-finder.js +71 -0
- package/dist/src/root-finder.js.map +1 -0
- package/dist/src/root-finder.test.d.ts +2 -0
- package/dist/src/root-finder.test.d.ts.map +1 -0
- package/dist/src/root-finder.test.js +111 -0
- package/dist/src/root-finder.test.js.map +1 -0
- package/dist/src/settings-merger.d.ts +2 -0
- package/dist/src/settings-merger.d.ts.map +1 -0
- package/dist/src/settings-merger.js +133 -0
- package/dist/src/settings-merger.js.map +1 -0
- package/dist/src/settings-merger.test.d.ts +2 -0
- package/dist/src/settings-merger.test.d.ts.map +1 -0
- package/dist/src/settings-merger.test.js +379 -0
- package/dist/src/settings-merger.test.js.map +1 -0
- package/dist/src/settings-template.test.d.ts +2 -0
- package/dist/src/settings-template.test.d.ts.map +1 -0
- package/dist/src/settings-template.test.js +88 -0
- package/dist/src/settings-template.test.js.map +1 -0
- package/dist/src/state-manager.d.ts +5 -0
- package/dist/src/state-manager.d.ts.map +1 -0
- package/dist/src/state-manager.js +55 -0
- package/dist/src/state-manager.js.map +1 -0
- package/dist/src/state-manager.test.d.ts +2 -0
- package/dist/src/state-manager.test.d.ts.map +1 -0
- package/dist/src/state-manager.test.js +85 -0
- package/dist/src/state-manager.test.js.map +1 -0
- package/dist/src/subagent-classifier.d.ts +4 -0
- package/dist/src/subagent-classifier.d.ts.map +1 -0
- package/dist/src/subagent-classifier.js +53 -0
- package/dist/src/subagent-classifier.js.map +1 -0
- package/dist/src/subagent-classifier.test.d.ts +2 -0
- package/dist/src/subagent-classifier.test.d.ts.map +1 -0
- package/dist/src/subagent-classifier.test.js +84 -0
- package/dist/src/subagent-classifier.test.js.map +1 -0
- package/dist/src/validator-loader.d.ts +9 -0
- package/dist/src/validator-loader.d.ts.map +1 -0
- package/dist/src/validator-loader.js +71 -0
- package/dist/src/validator-loader.js.map +1 -0
- package/dist/src/validator-loader.test.d.ts +2 -0
- package/dist/src/validator-loader.test.d.ts.map +1 -0
- package/dist/src/validator-loader.test.js +140 -0
- package/dist/src/validator-loader.test.js.map +1 -0
- package/package.json +90 -0
- package/reminders/ketchup.md +24 -0
- package/reminders/reminder-documentation.md +30 -0
- package/reminders/reminder-emergent-design.md +41 -0
- package/reminders/reminder-extreme-ownership.md +27 -0
- package/reminders/reminder-ide-diagnostics.md +25 -0
- package/reminders/reminder-ketchup.md +145 -0
- package/reminders/reminder-parallelization.md +27 -0
- package/reminders/reminder-rethink-after-revert.md +25 -0
- package/reminders/reminder-sub-agent-rules.md +27 -0
- package/reminders/reminder-test-title-matches-spec.md +37 -0
- package/scripts/auto-continue.ts +34 -0
- package/scripts/generate-changeset.ts +405 -0
- package/scripts/pre-tool-use.ts +35 -0
- package/scripts/session-start.ts +38 -0
- package/scripts/tail-logs.sh +17 -0
- package/scripts/test-hooks.sh +910 -0
- package/scripts/user-prompt-submit.ts +38 -0
- package/templates/settings.json +48 -0
- package/validators/appeal-system.md +55 -0
- package/validators/backwards-compat.md +33 -0
- package/validators/burst-atomicity.md +37 -0
- package/validators/coverage-rules.md +34 -0
- package/validators/dead-code.md +36 -0
- package/validators/hygiene.md +34 -0
- package/validators/infra-commit-format.md +37 -0
- package/validators/ketchup-plan-format.md +42 -0
- package/validators/new-code-requires-tests.md +36 -0
- package/validators/no-comments.md +35 -0
- package/validators/no-dangerous-git.md +35 -0
- package/validators/tcr-workflow.md +31 -0
- package/validators/testing-no-state-peeking.md +37 -0
- package/validators/testing-structure.md +37 -0
- package/validators/testing-stubs-over-mocks.md +42 -0
- package/validators/testing-weak-assertions.md +36 -0
- package/validators/type-organization.md +30 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env npx tsx
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
|
|
5
|
+
import { parseHookInput } from '../src/hook-input.js';
|
|
6
|
+
import { writeHookLog } from '../src/hook-logger.js';
|
|
7
|
+
import { handleUserPromptSubmit } from '../src/hooks/user-prompt-submit.js';
|
|
8
|
+
|
|
9
|
+
const input = parseHookInput(fs.readFileSync(0, 'utf-8'));
|
|
10
|
+
const claudeDir = path.resolve(process.cwd(), '.claude');
|
|
11
|
+
const startTime = Date.now();
|
|
12
|
+
|
|
13
|
+
handleUserPromptSubmit(claudeDir, input.session_id, input.prompt || '')
|
|
14
|
+
.then(({ diagnostics, ...result }) => {
|
|
15
|
+
writeHookLog(claudeDir, {
|
|
16
|
+
hookName: 'user-prompt-submit',
|
|
17
|
+
timestamp: new Date().toISOString(),
|
|
18
|
+
input: { ...input, prompt: input.prompt ? `[${input.prompt.length} chars]` : undefined },
|
|
19
|
+
resolvedPaths: diagnostics.resolvedPaths,
|
|
20
|
+
reminderFiles: diagnostics.reminderFiles,
|
|
21
|
+
matchedReminders: diagnostics.matchedReminders,
|
|
22
|
+
output: { resultLength: result.result.length },
|
|
23
|
+
durationMs: Date.now() - startTime,
|
|
24
|
+
});
|
|
25
|
+
console.log(JSON.stringify(result));
|
|
26
|
+
})
|
|
27
|
+
.catch((err) => {
|
|
28
|
+
writeHookLog(claudeDir, {
|
|
29
|
+
hookName: 'user-prompt-submit',
|
|
30
|
+
timestamp: new Date().toISOString(),
|
|
31
|
+
input: { ...input, prompt: input.prompt ? `[${input.prompt.length} chars]` : undefined },
|
|
32
|
+
output: null,
|
|
33
|
+
error: String(err),
|
|
34
|
+
durationMs: Date.now() - startTime,
|
|
35
|
+
});
|
|
36
|
+
console.error('user-prompt-submit hook failed:', err);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"hooks": {
|
|
3
|
+
"SessionStart": [
|
|
4
|
+
{
|
|
5
|
+
"matcher": "",
|
|
6
|
+
"hooks": [
|
|
7
|
+
{
|
|
8
|
+
"type": "command",
|
|
9
|
+
"command": "node .claude/scripts/session-start.js"
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
],
|
|
14
|
+
"PreToolUse": [
|
|
15
|
+
{
|
|
16
|
+
"matcher": "Edit|Write|NotebookEdit|Bash",
|
|
17
|
+
"hooks": [
|
|
18
|
+
{
|
|
19
|
+
"type": "command",
|
|
20
|
+
"command": "node .claude/scripts/pre-tool-use.js"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"UserPromptSubmit": [
|
|
26
|
+
{
|
|
27
|
+
"matcher": "",
|
|
28
|
+
"hooks": [
|
|
29
|
+
{
|
|
30
|
+
"type": "command",
|
|
31
|
+
"command": "node .claude/scripts/user-prompt-submit.js"
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
"Stop": [
|
|
37
|
+
{
|
|
38
|
+
"matcher": "",
|
|
39
|
+
"hooks": [
|
|
40
|
+
{
|
|
41
|
+
"type": "command",
|
|
42
|
+
"command": "node .claude/scripts/auto-continue.js"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -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.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: infra-commit-format
|
|
3
|
+
description: Validates commit message format for config-only commits
|
|
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:** This validator ONLY applies when ALL changed files are infrastructure/config files.
|
|
14
|
+
|
|
15
|
+
**Config files include:**
|
|
16
|
+
- package.json, package-lock.json, pnpm-lock.yaml
|
|
17
|
+
- tsconfig.json, tsconfig.*.json
|
|
18
|
+
- *.config.ts, *.config.js (vite.config.ts, vitest.config.ts, etc.)
|
|
19
|
+
- wrangler.toml
|
|
20
|
+
- .gitignore, .npmignore, .eslintrc*, .prettierrc*
|
|
21
|
+
- ketchup-plan.md
|
|
22
|
+
- Any file in .claude/ directory
|
|
23
|
+
|
|
24
|
+
**ACK immediately if:**
|
|
25
|
+
- ANY .ts or .tsx file (not *.config.ts) is in the changed files list
|
|
26
|
+
- The commit includes behavioral code, not just config
|
|
27
|
+
|
|
28
|
+
**When ONLY config files are changed:**
|
|
29
|
+
- ACK if commit message starts with `chore(scope):` or `chore:` format
|
|
30
|
+
- NACK if commit message uses `feat:`, `fix:`, `test:` for config-only changes
|
|
31
|
+
|
|
32
|
+
**Examples:**
|
|
33
|
+
- Good: `chore(deps): update vitest to 1.0`
|
|
34
|
+
- Good: `chore: add ketchup-plan.md`
|
|
35
|
+
- Bad: `feat: update package.json` (for config-only commit)
|
|
36
|
+
|
|
37
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ketchup-plan-format
|
|
3
|
+
description: Validates ketchup-plan.md structure and format
|
|
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 ketchup-plan.md when it is included in the commit.
|
|
14
|
+
|
|
15
|
+
**ACK immediately if:**
|
|
16
|
+
- ketchup-plan.md is not in the changed files
|
|
17
|
+
|
|
18
|
+
**When ketchup-plan.md is changed, validate:**
|
|
19
|
+
|
|
20
|
+
**Required structure:**
|
|
21
|
+
- Must have `## TODO` section
|
|
22
|
+
- Must have `## DONE` section
|
|
23
|
+
|
|
24
|
+
**Burst format:**
|
|
25
|
+
- Bursts should include `[depends: ...]` notation
|
|
26
|
+
- Format: `- [ ] Burst N: description [depends: none]` or `[depends: N, M]`
|
|
27
|
+
- Completed bursts in DONE should show commit hash: `- [x] Burst N: description (abc1234)`
|
|
28
|
+
|
|
29
|
+
**Bottle naming:**
|
|
30
|
+
- Bottles should be named by capability, not sequence number
|
|
31
|
+
- Format: `### Bottle: SettingsMerger` not `### Bottle 1`
|
|
32
|
+
|
|
33
|
+
**NACK if:**
|
|
34
|
+
- ketchup-plan.md lacks TODO or DONE sections
|
|
35
|
+
- Bursts are missing dependency notation
|
|
36
|
+
- Bottles are named by number instead of capability
|
|
37
|
+
|
|
38
|
+
**ACK if:**
|
|
39
|
+
- ketchup-plan.md follows the required structure
|
|
40
|
+
- Or ketchup-plan.md is not in the diff
|
|
41
|
+
|
|
42
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: new-code-requires-tests
|
|
3
|
+
description: Enforces that new behavioral code has accompanying tests
|
|
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 (not config files) in the diff.
|
|
14
|
+
|
|
15
|
+
Let tests drive all code. New behavioral code requires tests.
|
|
16
|
+
|
|
17
|
+
**NACK if:**
|
|
18
|
+
- New .ts/.tsx files are added without corresponding .test.ts/.test.tsx files
|
|
19
|
+
- New conditional branches (`if`, `else`, `? :`, `??`, `||`) appear without test coverage
|
|
20
|
+
- Functions are added without any test calling them
|
|
21
|
+
|
|
22
|
+
**ACK if:**
|
|
23
|
+
- New .ts files have accompanying .test.ts files in the commit
|
|
24
|
+
- The diff only modifies existing code (not adding new files)
|
|
25
|
+
- The diff only contains config files (*.config.ts, tsconfig.json, etc.)
|
|
26
|
+
- The diff only contains test files
|
|
27
|
+
- The new code is in an `index.ts` barrel file (re-exports only)
|
|
28
|
+
|
|
29
|
+
**Config files that don't need tests:**
|
|
30
|
+
- package.json, tsconfig.json, wrangler.toml
|
|
31
|
+
- vite.config.ts, vitest.config.ts
|
|
32
|
+
- .gitignore, ketchup-plan.md
|
|
33
|
+
|
|
34
|
+
**First behavioral .ts file rule:** The first non-config .ts file in a project must have a test.
|
|
35
|
+
|
|
36
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: no-comments
|
|
3
|
+
description: Enforces self-documenting code without inline comments
|
|
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 (not .test.ts, not .md, not config files).
|
|
14
|
+
|
|
15
|
+
Code should be self-documenting. No comments to explain what code does.
|
|
16
|
+
|
|
17
|
+
**NACK if the diff adds:**
|
|
18
|
+
- Single-line comments: `// explanation`
|
|
19
|
+
- Multi-line comments: `/* explanation */`
|
|
20
|
+
- TODO comments: `// TODO:`, `// FIXME:`, `// HACK:`
|
|
21
|
+
- Explanatory comments describing what the code does
|
|
22
|
+
|
|
23
|
+
**ACK if:**
|
|
24
|
+
- No inline comments are added in .ts/.tsx source files
|
|
25
|
+
- The diff only contains .md, .json, .test.ts, or config files
|
|
26
|
+
- JSDoc comments for exported public APIs (these document the contract, not implementation)
|
|
27
|
+
- Comments that are part of string literals or template strings
|
|
28
|
+
- License headers at the top of files
|
|
29
|
+
|
|
30
|
+
**Refactoring guidance:** If code needs a comment to explain it, the code should be refactored instead:
|
|
31
|
+
- Rename variables to be self-describing
|
|
32
|
+
- Extract functions with descriptive names
|
|
33
|
+
- Simplify complex logic
|
|
34
|
+
|
|
35
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: no-dangerous-git
|
|
3
|
+
description: Blocks dangerous git commands
|
|
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 git commands for dangerous operations.
|
|
14
|
+
|
|
15
|
+
These operations are forbidden and cannot be overridden:
|
|
16
|
+
|
|
17
|
+
**ALWAYS NACK if the command contains:**
|
|
18
|
+
- `--force` or `-f` with push (destroys remote history)
|
|
19
|
+
- `--no-verify` (bypasses pre-commit hooks)
|
|
20
|
+
- `git reset --hard` on shared branches
|
|
21
|
+
- `git push` to main/master with `--force`
|
|
22
|
+
- `git commit --amend` on already-pushed commits
|
|
23
|
+
|
|
24
|
+
**NACK reasoning:**
|
|
25
|
+
- `--force` can destroy team members' work
|
|
26
|
+
- `--no-verify` bypasses all safety checks
|
|
27
|
+
- These are explicitly listed as "DO NOT EVER ALLOW" in CLAUDE.md
|
|
28
|
+
|
|
29
|
+
**ACK if:**
|
|
30
|
+
- The git command does not contain dangerous flags
|
|
31
|
+
- The command is a normal commit, push, or other safe operation
|
|
32
|
+
|
|
33
|
+
**No plea system override:** These rules cannot be bypassed with a plea. They require explicit human approval outside the commit validator system.
|
|
34
|
+
|
|
35
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tcr-workflow
|
|
3
|
+
description: Enforces Test && Commit || Revert workflow
|
|
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 commit context for TCR workflow compliance.
|
|
14
|
+
|
|
15
|
+
Enforce the TCR (Test && Commit || Revert) workflow:
|
|
16
|
+
|
|
17
|
+
**Core principle:** Red → Green → TCR → Refactor → TCR → Done
|
|
18
|
+
|
|
19
|
+
**NACK if:**
|
|
20
|
+
- The commit message or context indicates tests are failing
|
|
21
|
+
- The commit appears to be "patching" failing code rather than reverting and rethinking
|
|
22
|
+
- Evidence suggests the commit bypasses the test-first workflow
|
|
23
|
+
|
|
24
|
+
**ACK if:**
|
|
25
|
+
- The commit appears to follow the TCR pattern
|
|
26
|
+
- Tests are expected to pass (behavioral code has accompanying tests)
|
|
27
|
+
- The commit represents a clean, tested change
|
|
28
|
+
|
|
29
|
+
**Note:** This validator cannot run tests itself. It validates the commit context and message for TCR compliance indicators.
|
|
30
|
+
|
|
31
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-no-state-peeking
|
|
3
|
+
description: Prohibits testing internal state instead of behavior
|
|
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 .test.ts and .test.tsx files in the diff.
|
|
14
|
+
|
|
15
|
+
Tests must verify observable behavior, not internal state.
|
|
16
|
+
|
|
17
|
+
**NACK if the diff contains:**
|
|
18
|
+
- Private field access: `obj["privateField"]`, `service["internalMap"]`
|
|
19
|
+
- Bracket notation to access non-public properties
|
|
20
|
+
- Calls to methods that exist solely for testing: `.getCount()`, `.getActiveSessionCount()`, `.getInternalState()`
|
|
21
|
+
- Direct assertions on internal collections: `expect(tracker.items.length)`
|
|
22
|
+
|
|
23
|
+
**Litmus test:** "If I changed the internal data structure (e.g., Map to Array), would this test still pass?" If no, it's testing implementation.
|
|
24
|
+
|
|
25
|
+
**ACK if:**
|
|
26
|
+
- Tests verify via return values from public methods
|
|
27
|
+
- Tests verify via callbacks/events
|
|
28
|
+
- Tests verify via thrown exceptions
|
|
29
|
+
- Tests use the public API only
|
|
30
|
+
- The diff only contains non-test files
|
|
31
|
+
|
|
32
|
+
**Allowed patterns:**
|
|
33
|
+
- `tracker.onEvent(e => events.push(e))` - observable via callback
|
|
34
|
+
- `expect(createUser({name: 'Alice'})).toEqual({...})` - observable via return value
|
|
35
|
+
- Testing cleanup by re-triggering and verifying callback fires again
|
|
36
|
+
|
|
37
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-structure
|
|
3
|
+
description: Enforces test structure and whole object assertions
|
|
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 .test.ts and .test.tsx files in the diff.
|
|
14
|
+
|
|
15
|
+
Enforce proper test structure:
|
|
16
|
+
|
|
17
|
+
**NACK if the diff contains:**
|
|
18
|
+
- Multiple execute/verify cycles in one test (squint test violation)
|
|
19
|
+
- Cherry-picked property assertions instead of whole object assertions
|
|
20
|
+
- Bad: `expect(result.id).toBe(1); expect(result.name).toBe('foo');`
|
|
21
|
+
- Good: `expect(result).toEqual({ id: 1, name: 'foo' })`
|
|
22
|
+
- Tests with multiple `expect()` calls on different operations
|
|
23
|
+
|
|
24
|
+
**Required structure (Squint Test):**
|
|
25
|
+
1. SETUP - prepare test data
|
|
26
|
+
2. EXECUTE - single function call
|
|
27
|
+
3. VERIFY - whole object assertion
|
|
28
|
+
|
|
29
|
+
**ACK if:**
|
|
30
|
+
- Tests follow SETUP → EXECUTE → VERIFY pattern
|
|
31
|
+
- Whole objects are asserted with `toEqual({...})`
|
|
32
|
+
- One assertion per behavior
|
|
33
|
+
- The diff only contains non-test files
|
|
34
|
+
|
|
35
|
+
**Note:** Multiple `expect()` calls are OK if they assert different aspects of the SAME operation result (e.g., checking both return value and side effect callback).
|
|
36
|
+
|
|
37
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing-stubs-over-mocks
|
|
3
|
+
description: Prefers deterministic stubs over mocks
|
|
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 .test.ts and .test.tsx files in the diff.
|
|
14
|
+
|
|
15
|
+
Prefer deterministic stubs over mocks. Mock only at system boundaries.
|
|
16
|
+
|
|
17
|
+
**NACK if the diff contains:**
|
|
18
|
+
- Heavy mocking of internal modules/functions that could use stubs
|
|
19
|
+
- `jest.mock()` or `vi.mock()` for internal application code
|
|
20
|
+
- Mock implementations that could be replaced with simple stub objects
|
|
21
|
+
- Spy assertions on internal function calls (`toHaveBeenCalledWith` on non-boundary code)
|
|
22
|
+
|
|
23
|
+
**ACK if:**
|
|
24
|
+
- Deterministic stubs are used (plain objects/functions with predictable behavior)
|
|
25
|
+
- Mocks are only used at system boundaries:
|
|
26
|
+
- External APIs (fetch, axios calls)
|
|
27
|
+
- Databases
|
|
28
|
+
- File system
|
|
29
|
+
- Third-party services
|
|
30
|
+
- The diff only contains non-test files
|
|
31
|
+
|
|
32
|
+
**Stub example (preferred):**
|
|
33
|
+
```typescript
|
|
34
|
+
const fakeRepo = { findById: (id) => ({ id, name: 'Test' }) }
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Mock example (only at boundaries):**
|
|
38
|
+
```typescript
|
|
39
|
+
vi.mock('./external-api', () => ({ fetch: vi.fn() }))
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
RESPOND WITH JSON ONLY - NO PROSE, NO MARKDOWN, NO EXPLANATION OUTSIDE THE JSON.
|