claude-code-superkit 0.0.0-stage → 1.5.3
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/LICENSE +21 -0
- package/README.md +374 -2
- package/bin/cli.js +153 -0
- package/bin/inject-tokens.js +224 -0
- package/bin/measure-tokens.js +17 -0
- package/bin/superkit-counts-verify.sh +30 -0
- package/lib/codex.js +246 -0
- package/lib/docs-scaffold.js +147 -0
- package/lib/installer.js +499 -0
- package/lib/prompts.js +51 -0
- package/lib/settings-builder.js +51 -0
- package/lib/superpowers.js +99 -0
- package/lib/utils.js +117 -0
- package/lib/validator.js +84 -0
- package/package.json +49 -4
- package/packages/codex/AGENTS.md +396 -0
- package/packages/codex/INSTALL.md +342 -0
- package/packages/codex/config.toml +22 -0
- package/packages/codex/hooks/superkit.mjs +203 -0
- package/packages/codex/hooks.json +30 -0
- package/packages/codex/legacy-baseline.json +88 -0
- package/packages/codex/native-skills.txt +65 -0
- package/packages/codex/rules/default.rules +565 -0
- package/packages/codex/skills/ai-slop-cleaner/SKILL.md +44 -0
- package/packages/codex/skills/api-contract-sync/SKILL.md +96 -0
- package/packages/codex/skills/architect/SKILL.md +49 -0
- package/packages/codex/skills/audit-backend/SKILL.md +80 -0
- package/packages/codex/skills/audit-frontend/SKILL.md +82 -0
- package/packages/codex/skills/audit-infra/SKILL.md +87 -0
- package/packages/codex/skills/audit-orchestrator/SKILL.md +114 -0
- package/packages/codex/skills/behavioral-nudge-engine/SKILL.md +110 -0
- package/packages/codex/skills/benchmark/SKILL.md +49 -0
- package/packages/codex/skills/bot-reviewer/SKILL.md +94 -0
- package/packages/codex/skills/code-reviewer/SKILL.md +67 -0
- package/packages/codex/skills/codebase-onboarding-engineer/SKILL.md +46 -0
- package/packages/codex/skills/comment-rot-analyzer/SKILL.md +75 -0
- package/packages/codex/skills/commit-helper/SKILL.md +101 -0
- package/packages/codex/skills/critic/SKILL.md +56 -0
- package/packages/codex/skills/database-reviewer/SKILL.md +79 -0
- package/packages/codex/skills/debug-observer/SKILL.md +107 -0
- package/packages/codex/skills/dependency-checker/SKILL.md +69 -0
- package/packages/codex/skills/design-system-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/dev-orchestrator/SKILL.md +304 -0
- package/packages/codex/skills/docs-reviewer/SKILL.md +86 -0
- package/packages/codex/skills/drizzle-orm-expert/SKILL.md +246 -0
- package/packages/codex/skills/e2e-test-generator/SKILL.md +95 -0
- package/packages/codex/skills/evaluator/SKILL.md +63 -0
- package/packages/codex/skills/frontend-perf-reviewer/SKILL.md +95 -0
- package/packages/codex/skills/frontend-ui-color-reviewer/SKILL.md +68 -0
- package/packages/codex/skills/frontend-ui-design-critic/SKILL.md +99 -0
- package/packages/codex/skills/frontend-ui-interaction-reviewer/SKILL.md +102 -0
- package/packages/codex/skills/frontend-ui-motion-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/frontend-ui-reviewer/SKILL.md +81 -0
- package/packages/codex/skills/frontend-ui-typography-reviewer/SKILL.md +62 -0
- package/packages/codex/skills/gltf-debugging/SKILL.md +128 -0
- package/packages/codex/skills/go-benchmark/SKILL.md +217 -0
- package/packages/codex/skills/go-concurrency-reviewer/SKILL.md +113 -0
- package/packages/codex/skills/go-error-reviewer/SKILL.md +107 -0
- package/packages/codex/skills/go-grpc-patterns/SKILL.md +285 -0
- package/packages/codex/skills/go-modernizer/SKILL.md +111 -0
- package/packages/codex/skills/go-observability-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/go-performance-reviewer/SKILL.md +112 -0
- package/packages/codex/skills/go-reviewer/SKILL.md +109 -0
- package/packages/codex/skills/go-samber-do/SKILL.md +158 -0
- package/packages/codex/skills/go-samber-lo/SKILL.md +178 -0
- package/packages/codex/skills/go-samber-oops/SKILL.md +174 -0
- package/packages/codex/skills/goal-verifier/SKILL.md +53 -0
- package/packages/codex/skills/health-checker/SKILL.md +109 -0
- package/packages/codex/skills/html-to-3d-texture/SKILL.md +153 -0
- package/packages/codex/skills/impeccable-craft/SKILL.md +101 -0
- package/packages/codex/skills/lint-runner/SKILL.md +85 -0
- package/packages/codex/skills/migrate/SKILL.md +60 -0
- package/packages/codex/skills/migration-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/minimal-change-engineer/SKILL.md +44 -0
- package/packages/codex/skills/new-migration/SKILL.md +59 -0
- package/packages/codex/skills/nextjs-supabase-auth/SKILL.md +227 -0
- package/packages/codex/skills/output-enforcement/SKILL.md +71 -0
- package/packages/codex/skills/plan-checker/SKILL.md +53 -0
- package/packages/codex/skills/postgresql-optimization/SKILL.md +159 -0
- package/packages/codex/skills/pre-deploy-validator/SKILL.md +111 -0
- package/packages/codex/skills/presentation-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/product-3d-lighting/SKILL.md +137 -0
- package/packages/codex/skills/project-architecture/SKILL.md +52 -0
- package/packages/codex/skills/py-reviewer/SKILL.md +100 -0
- package/packages/codex/skills/r3f-scene-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/r3f-scroll-driven-3d/SKILL.md +162 -0
- package/packages/codex/skills/reality-checker/SKILL.md +61 -0
- package/packages/codex/skills/redis-patterns/SKILL.md +260 -0
- package/packages/codex/skills/review-orchestrator/SKILL.md +151 -0
- package/packages/codex/skills/rs-reviewer/SKILL.md +98 -0
- package/packages/codex/skills/ru-text/SKILL.md +132 -0
- package/packages/codex/skills/scaffold-endpoint/SKILL.md +44 -0
- package/packages/codex/skills/security-scanner/SKILL.md +94 -0
- package/packages/codex/skills/silent-failure-hunter/SKILL.md +176 -0
- package/packages/codex/skills/telegram-bot-builder/SKILL.md +120 -0
- package/packages/codex/skills/test-generator/SKILL.md +79 -0
- package/packages/codex/skills/test-runner/SKILL.md +101 -0
- package/packages/codex/skills/threejs-color-management/SKILL.md +97 -0
- package/packages/codex/skills/tree-generator/SKILL.md +63 -0
- package/packages/codex/skills/ts-reviewer/SKILL.md +90 -0
- package/packages/codex/skills/ui-design-reviewer/SKILL.md +89 -0
- package/packages/codex/skills/ui-reviewer/SKILL.md +103 -0
- package/packages/codex/skills/visual-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/writing-agents/SKILL.md +165 -0
- package/packages/codex/skills/writing-commands/SKILL.md +173 -0
- package/packages/core/CLAUDE.md +118 -0
- package/packages/core/INTERNAL-FILES +16 -0
- package/packages/core/agents/ai-slop-cleaner.md +187 -0
- package/packages/core/agents/api-contract-sync.md +127 -0
- package/packages/core/agents/architect.md +205 -0
- package/packages/core/agents/audit-backend.md +137 -0
- package/packages/core/agents/audit-frontend.md +129 -0
- package/packages/core/agents/audit-infra.md +182 -0
- package/packages/core/agents/behavioral-nudge-engine.md +170 -0
- package/packages/core/agents/code-reviewer.md +195 -0
- package/packages/core/agents/codebase-onboarding-engineer.md +172 -0
- package/packages/core/agents/comment-rot-analyzer.md +115 -0
- package/packages/core/agents/critic.md +172 -0
- package/packages/core/agents/database-reviewer.md +201 -0
- package/packages/core/agents/debug-observer.md +261 -0
- package/packages/core/agents/dependency-checker.md +199 -0
- package/packages/core/agents/docs-reviewer.md +206 -0
- package/packages/core/agents/e2e-test-generator.md +261 -0
- package/packages/core/agents/evaluator.md +141 -0
- package/packages/core/agents/goal-verifier.md +130 -0
- package/packages/core/agents/health-checker.md +194 -0
- package/packages/core/agents/migration-reviewer.md +161 -0
- package/packages/core/agents/minimal-change-engineer.md +219 -0
- package/packages/core/agents/plan-checker.md +139 -0
- package/packages/core/agents/pre-deploy-validator.md +189 -0
- package/packages/core/agents/reality-checker.md +175 -0
- package/packages/core/agents/scaffold-endpoint.md +162 -0
- package/packages/core/agents/security-scanner.md +236 -0
- package/packages/core/agents/silent-failure-hunter.md +276 -0
- package/packages/core/agents/test-generator.md +146 -0
- package/packages/core/agents/tree-generator.md +141 -0
- package/packages/core/agents/ui-reviewer.md +172 -0
- package/packages/core/agents/visual-reviewer.md +211 -0
- package/packages/core/commands/audit.md +166 -0
- package/packages/core/commands/benchmark.md +130 -0
- package/packages/core/commands/commit.md +148 -0
- package/packages/core/commands/dev.md +302 -0
- package/packages/core/commands/docs-init.md +75 -0
- package/packages/core/commands/lint.md +137 -0
- package/packages/core/commands/migrate.md +146 -0
- package/packages/core/commands/new-migration.md +182 -0
- package/packages/core/commands/pair.md +209 -0
- package/packages/core/commands/review.md +195 -0
- package/packages/core/commands/security-scan.md +142 -0
- package/packages/core/commands/superkit-evolve.md +231 -0
- package/packages/core/commands/superkit-init.md +274 -0
- package/packages/core/commands/test.md +108 -0
- package/packages/core/commands/workflow.md +150 -0
- package/packages/core/docs/guide/01-getting-started.md +41 -0
- package/packages/core/docs-templates/README.md +33 -0
- package/packages/core/docs-templates/adr-template.md +62 -0
- package/packages/core/docs-templates/architecture/api-contracts.md +26 -0
- package/packages/core/docs-templates/architecture/api-reference.md +48 -0
- package/packages/core/docs-templates/architecture/auth-and-sessions.md +38 -0
- package/packages/core/docs-templates/architecture/backend-layers.md +42 -0
- package/packages/core/docs-templates/architecture/data-flow.md +26 -0
- package/packages/core/docs-templates/architecture/database-schema.md +51 -0
- package/packages/core/docs-templates/architecture/deployment.md +41 -0
- package/packages/core/docs-templates/architecture/frontend-state.md +46 -0
- package/packages/core/helpers/statusline.cjs +370 -0
- package/packages/core/hooks/CHAIN-SEMANTICS.md +84 -0
- package/packages/core/hooks/audit-settings-source.sh +98 -0
- package/packages/core/hooks/audit-trail.sh +120 -0
- package/packages/core/hooks/block-dangerous-git.sh +189 -0
- package/packages/core/hooks/bundle-import-check.sh +64 -0
- package/packages/core/hooks/compact-state-inject.sh +84 -0
- package/packages/core/hooks/config-protection.sh +68 -0
- package/packages/core/hooks/console-log-warning.sh +28 -0
- package/packages/core/hooks/context-monitor.sh +35 -0
- package/packages/core/hooks/dev-edit-counter.sh +59 -0
- package/packages/core/hooks/dev-marker-set.sh +55 -0
- package/packages/core/hooks/dev-required-on-commit.sh +426 -0
- package/packages/core/hooks/doc-check-on-commit.sh +396 -0
- package/packages/core/hooks/edit-streak-check.sh +63 -0
- package/packages/core/hooks/evolve-check.sh +78 -0
- package/packages/core/hooks/gateguard-pre-edit.sh +154 -0
- package/packages/core/hooks/gateguard-record-facts.sh +37 -0
- package/packages/core/hooks/intake-classifier.py +449 -0
- package/packages/core/hooks/lib/profile.sh +141 -0
- package/packages/core/hooks/loop-guard.sh +75 -0
- package/packages/core/hooks/migration-safety.sh +56 -0
- package/packages/core/hooks/plan-completion-gate.sh +61 -0
- package/packages/core/hooks/pre-compact-save.sh +89 -0
- package/packages/core/hooks/security-patterns.sh +119 -0
- package/packages/core/hooks/session-context-restore.sh +76 -0
- package/packages/core/hooks/subagent-stop-validate.sh +73 -0
- package/packages/core/hooks/superkit-counts-verify.sh +346 -0
- package/packages/core/hooks/superkit-update.sh +367 -0
- package/packages/core/hooks/tests/README.md +42 -0
- package/packages/core/hooks/tests/audit-trail-chain_test.sh +62 -0
- package/packages/core/hooks/tests/block-dangerous-git_test.sh +144 -0
- package/packages/core/hooks/tests/chain-semantics/h1.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/h2.sh +9 -0
- package/packages/core/hooks/tests/chain-semantics/h3.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/run-experiment.sh +65 -0
- package/packages/core/hooks/tests/chain-semantics/settings-experiment.json +15 -0
- package/packages/core/hooks/tests/counts-verify_test.sh +118 -0
- package/packages/core/hooks/tests/dev-required-on-commit_test.sh +207 -0
- package/packages/core/hooks/tests/dev-required-wip-on-main_test.sh +20 -0
- package/packages/core/hooks/tests/doc-check-on-commit_test.sh +122 -0
- package/packages/core/hooks/tests/edit-streak-check_test.sh +106 -0
- package/packages/core/hooks/tests/internal-manifest_test.sh +130 -0
- package/packages/core/hooks/tests/json-path_test.sh +108 -0
- package/packages/core/hooks/tests/mirror-invariants_test.sh +139 -0
- package/packages/core/hooks/tests/nudge-throttle_test.sh +95 -0
- package/packages/core/hooks/tests/profile-helper_test.sh +21 -0
- package/packages/core/hooks/tests/run-all.sh +47 -0
- package/packages/core/hooks/tests/session-key-helper_test.sh +17 -0
- package/packages/core/hooks/tests/superkit-update_test.sh +311 -0
- package/packages/core/hooks/tests/warn-visibility_test.sh +59 -0
- package/packages/core/hooks/user-intent-detect.sh +44 -0
- package/packages/core/hooks/verify-hooks.sh +69 -0
- package/packages/core/rules/auto-commands.md +124 -0
- package/packages/core/rules/coding-style.md +68 -0
- package/packages/core/rules/dev-workflow.md +77 -0
- package/packages/core/rules/documentation.md +106 -0
- package/packages/core/rules/frontend-aesthetics.md +53 -0
- package/packages/core/rules/git-workflow.md +14 -0
- package/packages/core/rules/security.md +29 -0
- package/packages/core/rules/superkit-integrity.md +114 -0
- package/packages/core/settings.json +229 -0
- package/packages/core/skills/drizzle-orm-expert/SKILL.md +260 -0
- package/packages/core/skills/nextjs-supabase-auth/SKILL.md +259 -0
- package/packages/core/skills/postgresql-optimization/SKILL.md +150 -0
- package/packages/core/skills/project-architecture/SKILL.md +31 -0
- package/packages/core/skills/project-scanner/SKILL.md +132 -0
- package/packages/core/skills/redis-patterns/SKILL.md +261 -0
- package/packages/core/skills/ru-text/SKILL.md +156 -0
- package/packages/core/skills/telegram-bot-builder/SKILL.md +145 -0
- package/packages/core/skills/writing-agents/SKILL.md +220 -0
- package/packages/core/skills/writing-commands/SKILL.md +176 -0
- package/packages/core/skills/writing-hooks/SKILL.md +335 -0
- package/packages/extras/bot-reviewer.md +279 -0
- package/packages/extras/design-system-reviewer.md +234 -0
- package/packages/extras/red-blue-auditor/README.md +117 -0
- package/packages/extras/red-blue-auditor/agent.md +128 -0
- package/packages/extras/red-blue-auditor/patterns/agent-config.txt +4 -0
- package/packages/extras/red-blue-auditor/patterns/hook-injection.txt +8 -0
- package/packages/extras/red-blue-auditor/patterns/mcp-risk.txt +5 -0
- package/packages/extras/red-blue-auditor/patterns/permission-abuse.txt +6 -0
- package/packages/extras/red-blue-auditor/patterns/secrets.txt +17 -0
- package/packages/extras/red-blue-auditor/scan.sh +88 -0
- package/packages/extras/skillsmp-search/SKILL.md +134 -0
- package/packages/frontend-3d/README.md +62 -0
- package/packages/frontend-3d/agents/frontend-perf-reviewer.md +164 -0
- package/packages/frontend-3d/agents/presentation-reviewer.md +146 -0
- package/packages/frontend-3d/agents/r3f-scene-reviewer.md +128 -0
- package/packages/frontend-3d/agents/ui-design-reviewer.md +169 -0
- package/packages/frontend-3d/commands/capture-screen.md +166 -0
- package/packages/frontend-3d/hooks/bundle-size-warn.sh +93 -0
- package/packages/frontend-3d/hooks/gsap-pattern-check.sh +74 -0
- package/packages/frontend-3d/hooks/r3f-color-check.sh +76 -0
- package/packages/frontend-3d/hooks/tailwind-version-guard.sh +98 -0
- package/packages/frontend-3d/rules/frontend-aesthetics-3d.md +81 -0
- package/packages/frontend-3d/rules/gsap-conventions.md +129 -0
- package/packages/frontend-3d/rules/threejs-conventions.md +116 -0
- package/packages/frontend-3d/skills/gltf-debugging/SKILL.md +145 -0
- package/packages/frontend-3d/skills/html-to-3d-texture/SKILL.md +183 -0
- package/packages/frontend-3d/skills/output-enforcement/SKILL.md +79 -0
- package/packages/frontend-3d/skills/product-3d-lighting/SKILL.md +166 -0
- package/packages/frontend-3d/skills/r3f-scroll-driven-3d/SKILL.md +209 -0
- package/packages/frontend-3d/skills/threejs-color-management/SKILL.md +111 -0
- package/packages/frontend-ui/NOTICE.md +99 -0
- package/packages/frontend-ui/README.md +59 -0
- package/packages/frontend-ui/agents/ui-color-reviewer.md +174 -0
- package/packages/frontend-ui/agents/ui-design-critic.md +198 -0
- package/packages/frontend-ui/agents/ui-interaction-reviewer.md +259 -0
- package/packages/frontend-ui/agents/ui-motion-reviewer.md +266 -0
- package/packages/frontend-ui/agents/ui-reviewer.md +251 -0
- package/packages/frontend-ui/agents/ui-typography-reviewer.md +222 -0
- package/packages/frontend-ui/hooks/tests/ui-animation-easing-check_test.sh +78 -0
- package/packages/frontend-ui/hooks/tests/ui-banned-fonts-check_test.sh +77 -0
- package/packages/frontend-ui/hooks/tests/ui-color-check_test.sh +75 -0
- package/packages/frontend-ui/hooks/ui-animation-easing-check.sh +86 -0
- package/packages/frontend-ui/hooks/ui-banned-fonts-check.sh +90 -0
- package/packages/frontend-ui/hooks/ui-color-check.sh +102 -0
- package/packages/frontend-ui/rules/color-and-contrast.md +230 -0
- package/packages/frontend-ui/rules/frontend-design-aesthetics.md +124 -0
- package/packages/frontend-ui/rules/interaction-polish.md +335 -0
- package/packages/frontend-ui/rules/motion-and-animation.md +283 -0
- package/packages/frontend-ui/rules/spatial-and-layout.md +212 -0
- package/packages/frontend-ui/rules/typography-guidelines.md +185 -0
- package/packages/frontend-ui/rules/ui-anti-patterns.md +309 -0
- package/packages/frontend-ui/settings.json +24 -0
- package/packages/frontend-ui/skills/impeccable-craft/SKILL.md +187 -0
- package/packages/gan/README.md +232 -0
- package/packages/gan/agents/gan-evaluator.md +214 -0
- package/packages/gan/agents/gan-generator.md +171 -0
- package/packages/gan/agents/gan-planner.md +206 -0
- package/packages/gan/rubrics/functionality.md +66 -0
- package/packages/gan/rubrics/ui-quality.md +77 -0
- package/packages/gan/skills/gan-evaluator/SKILL.md +91 -0
- package/packages/gan/skills/gan-generator/SKILL.md +72 -0
- package/packages/gan/skills/gan-planner/SKILL.md +93 -0
- package/packages/stack-agents/go/go-concurrency-reviewer.md +210 -0
- package/packages/stack-agents/go/go-error-reviewer.md +187 -0
- package/packages/stack-agents/go/go-modernizer.md +160 -0
- package/packages/stack-agents/go/go-observability-reviewer.md +185 -0
- package/packages/stack-agents/go/go-performance-reviewer.md +160 -0
- package/packages/stack-agents/go/go-reviewer.md +277 -0
- package/packages/stack-agents/go/references/benchmark-methodology.md +280 -0
- package/packages/stack-agents/go/references/channel-patterns.md +384 -0
- package/packages/stack-agents/go/references/cli-cobra-viper.md +190 -0
- package/packages/stack-agents/go/references/code-style.md +262 -0
- package/packages/stack-agents/go/references/context-propagation.md +317 -0
- package/packages/stack-agents/go/references/data-structures.md +315 -0
- package/packages/stack-agents/go/references/database-patterns.md +334 -0
- package/packages/stack-agents/go/references/design-patterns.md +411 -0
- package/packages/stack-agents/go/references/di-frameworks.md +146 -0
- package/packages/stack-agents/go/references/error-creation.md +251 -0
- package/packages/stack-agents/go/references/error-inspection.md +348 -0
- package/packages/stack-agents/go/references/error-wrapping.md +230 -0
- package/packages/stack-agents/go/references/gopls-driving.md +62 -0
- package/packages/stack-agents/go/references/goroutine-lifecycle.md +351 -0
- package/packages/stack-agents/go/references/graphql-patterns.md +221 -0
- package/packages/stack-agents/go/references/grpc-patterns.md +373 -0
- package/packages/stack-agents/go/references/modernize-guide.md +522 -0
- package/packages/stack-agents/go/references/module-management.md +191 -0
- package/packages/stack-agents/go/references/naming-conventions.md +176 -0
- package/packages/stack-agents/go/references/observability-pipeline.md +352 -0
- package/packages/stack-agents/go/references/performance-profiling.md +250 -0
- package/packages/stack-agents/go/references/refactoring-mechanics.md +127 -0
- package/packages/stack-agents/go/references/rest-openapi-patterns.md +160 -0
- package/packages/stack-agents/go/references/samber-do.md +201 -0
- package/packages/stack-agents/go/references/samber-libraries.md +363 -0
- package/packages/stack-agents/go/references/samber-lo.md +260 -0
- package/packages/stack-agents/go/references/samber-oops.md +200 -0
- package/packages/stack-agents/go/references/security-checklist.md +441 -0
- package/packages/stack-agents/go/references/standard-stdlib-now.md +181 -0
- package/packages/stack-agents/go/references/stay-updated.md +147 -0
- package/packages/stack-agents/go/references/structs-interfaces.md +312 -0
- package/packages/stack-agents/go/references/sync-primitives.md +395 -0
- package/packages/stack-agents/go/references/testing-patterns.md +483 -0
- package/packages/stack-agents/go/references/troubleshooting.md +98 -0
- package/packages/stack-agents/python/py-reviewer.md +194 -0
- package/packages/stack-agents/rust/rs-reviewer.md +188 -0
- package/packages/stack-agents/typescript/ts-reviewer.md +135 -0
- package/packages/stack-hooks/go/go-context-check-on-edit.sh +56 -0
- package/packages/stack-hooks/go/go-error-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-format-on-edit.sh +32 -0
- package/packages/stack-hooks/go/go-safety-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-vet-on-edit.sh +61 -0
- package/packages/stack-hooks/go/golangci-lint-on-edit.sh +54 -0
- package/packages/stack-hooks/python/ruff-on-edit.sh +67 -0
- package/packages/stack-hooks/rust/cargo-check-on-edit.sh +64 -0
- package/packages/stack-hooks/typescript/typecheck-on-edit.sh +76 -0
- package/packages/stack-rules/go/go-conventions.md +44 -0
- package/packages/stack-rules/go/go-safety.md +35 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# run-experiment.sh — runs h1, h2, h3 directly (not via Claude Code) using
|
|
3
|
+
# both sequential and background modes, so we can observe the mechanics of
|
|
4
|
+
# each approach in isolation.
|
|
5
|
+
#
|
|
6
|
+
# For the TRUE Claude Code behaviour you must copy settings-experiment.json
|
|
7
|
+
# into a test project's .claude/settings.json, open it in Claude Code,
|
|
8
|
+
# invoke a Bash tool, and inspect the log. This script only proves the hook
|
|
9
|
+
# scripts themselves work — not how Claude Code schedules them.
|
|
10
|
+
#
|
|
11
|
+
# Usage: bash run-experiment.sh
|
|
12
|
+
|
|
13
|
+
set -u
|
|
14
|
+
DIR=$(cd "$(dirname "$0")" && pwd)
|
|
15
|
+
export CHAIN_TEST_LOG="${TMPDIR:-/tmp}/claude-chain-test.log"
|
|
16
|
+
export CHAIN_TEST_MARKER="${TMPDIR:-/tmp}/claude-chain-test-h3-ran"
|
|
17
|
+
|
|
18
|
+
rm -f "$CHAIN_TEST_LOG" "$CHAIN_TEST_MARKER"
|
|
19
|
+
|
|
20
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
21
|
+
echo "▶ SEQUENTIAL mode (what settings.json LOOKS like it does)"
|
|
22
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
23
|
+
bash "$DIR/h1.sh" >/dev/null 2>&1 && echo " h1 exit=0"
|
|
24
|
+
H1_EXIT=$?
|
|
25
|
+
echo " h1 exit=$H1_EXIT"
|
|
26
|
+
bash "$DIR/h2.sh" >/dev/null 2>&1
|
|
27
|
+
echo " h2 exit=$?"
|
|
28
|
+
bash "$DIR/h3.sh" >/dev/null 2>&1
|
|
29
|
+
echo " h3 exit=$?"
|
|
30
|
+
echo ""
|
|
31
|
+
echo " LOG:"
|
|
32
|
+
sed 's/^/ /' "$CHAIN_TEST_LOG"
|
|
33
|
+
echo ""
|
|
34
|
+
[ -f "$CHAIN_TEST_MARKER" ] && echo " h3 marker exists: YES" || echo " h3 marker exists: NO"
|
|
35
|
+
rm -f "$CHAIN_TEST_LOG" "$CHAIN_TEST_MARKER"
|
|
36
|
+
|
|
37
|
+
echo ""
|
|
38
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
39
|
+
echo "▶ PARALLEL mode (what Anthropic docs say Claude Code actually does)"
|
|
40
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
41
|
+
bash "$DIR/h1.sh" >/dev/null 2>&1 &
|
|
42
|
+
bash "$DIR/h2.sh" >/dev/null 2>&1 &
|
|
43
|
+
bash "$DIR/h3.sh" >/dev/null 2>&1 &
|
|
44
|
+
wait
|
|
45
|
+
echo ""
|
|
46
|
+
echo " LOG (sorted by timestamp — interleaving proves parallelism):"
|
|
47
|
+
sort "$CHAIN_TEST_LOG" | sed 's/^/ /'
|
|
48
|
+
echo ""
|
|
49
|
+
[ -f "$CHAIN_TEST_MARKER" ] && echo " h3 marker exists: YES (h3 ran despite h1 exit 2)" || echo " h3 marker exists: NO"
|
|
50
|
+
|
|
51
|
+
echo ""
|
|
52
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
53
|
+
echo "▶ How to verify inside real Claude Code"
|
|
54
|
+
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
55
|
+
cat <<'HELP'
|
|
56
|
+
1. Create a throwaway project: mkdir /tmp/cc-chain-test && cd /tmp/cc-chain-test
|
|
57
|
+
2. Copy the experiment settings: mkdir -p .claude && \
|
|
58
|
+
cp <superkit>/packages/core/hooks/tests/chain-semantics/settings-experiment.json \
|
|
59
|
+
.claude/settings.json
|
|
60
|
+
(edit ${CLAUDE_PROJECT_DIR} substitutions to point at the superkit clone)
|
|
61
|
+
3. Open Claude Code in that directory.
|
|
62
|
+
4. Ask it to run any Bash command — e.g. "run: ls".
|
|
63
|
+
5. Inspect /tmp/claude-chain-test.log (interleaving) and /tmp/claude-chain-test-h3-ran (presence).
|
|
64
|
+
6. Record observations in CHAIN-SEMANTICS.md.
|
|
65
|
+
HELP
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "Temporary Claude Code settings for the hook-chain-semantics experiment. Place the file at .claude/settings.json inside a throwaway project directory, then open it with Claude Code and run a single `ls` command. The three hooks h1/h2/h3 will fire simultaneously. Observe /tmp/claude-chain-test.log for interleaving and /tmp/claude-chain-test-h3-ran for h3's marker. Restore your real settings.json afterwards.",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PreToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "Bash",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/packages/core/hooks/tests/chain-semantics/h1.sh" },
|
|
9
|
+
{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/packages/core/hooks/tests/chain-semantics/h2.sh" },
|
|
10
|
+
{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/packages/core/hooks/tests/chain-semantics/h3.sh" }
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
]
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# counts-verify_test.sh — regression test for superkit-counts-verify.sh (Task 19)
|
|
3
|
+
#
|
|
4
|
+
# Asserts:
|
|
5
|
+
# 1. the verifier PASSES (exit 0) on the current, correct repo (local commit)
|
|
6
|
+
# 2. a skewed README count is DETECTED (exit 2), then the README is restored
|
|
7
|
+
# 3. the network About check is gated: a local commit does NOT call `gh`,
|
|
8
|
+
# while --check-remote / git push opt in
|
|
9
|
+
#
|
|
10
|
+
# Hermetic: README.md is backed up and restored via a trap, even on failure.
|
|
11
|
+
# The verifier resolves CLAUDE.md / README.md / packages/* relative to CWD,
|
|
12
|
+
# so the test runs from the repo root.
|
|
13
|
+
set -uo pipefail
|
|
14
|
+
|
|
15
|
+
REPO_ROOT="$(cd "$(dirname "$0")/../../../.." && pwd)"
|
|
16
|
+
HOOK="$REPO_ROOT/packages/core/hooks/superkit-counts-verify.sh"
|
|
17
|
+
[ -x "$HOOK" ] || { echo "FAIL: hook not executable at $HOOK"; exit 1; }
|
|
18
|
+
[ -f "$REPO_ROOT/README.md" ] || { echo "FAIL: README.md not found at repo root $REPO_ROOT"; exit 1; }
|
|
19
|
+
|
|
20
|
+
README="$REPO_ROOT/README.md"
|
|
21
|
+
BACKUP="$(mktemp "${TMPDIR:-/tmp}/counts-verify-readme-backup.XXXXXX")"
|
|
22
|
+
cp "$README" "$BACKUP"
|
|
23
|
+
|
|
24
|
+
restore() { cp "$BACKUP" "$README"; rm -f "$BACKUP"; }
|
|
25
|
+
trap restore EXIT
|
|
26
|
+
|
|
27
|
+
run_commit() {
|
|
28
|
+
# Run the verifier as a git-commit PreToolUse payload from the repo root.
|
|
29
|
+
# Force CHECK_REMOTE off so the test never makes a network call.
|
|
30
|
+
( cd "$REPO_ROOT" && echo '{"tool_input":{"command":"git commit -m test"}}' \
|
|
31
|
+
| SUPERKIT_VERIFY_CHECK_REMOTE=0 bash "$HOOK" >/dev/null 2>&1 )
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# ── Test 1: clean repo passes ─────────────────────────────────────────
|
|
35
|
+
if run_commit; then
|
|
36
|
+
echo "PASS: verifier passes on the current correct repo"
|
|
37
|
+
else
|
|
38
|
+
echo "FAIL: verifier should pass on the unmodified repo (exit non-zero)"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# ── Test 2: skewed README count is detected ───────────────────────────
|
|
43
|
+
# Bump the "Core Agents" row number to a bogus value and confirm a block.
|
|
44
|
+
# Uses the same label anchor the verifier relies on.
|
|
45
|
+
LINE=$(grep -nE '^\| \*\*Core Agents\*\* \|' "$README" | head -1 | cut -d: -f1)
|
|
46
|
+
if [ -z "$LINE" ]; then
|
|
47
|
+
echo "FAIL: could not find '| **Core Agents** |' row to skew"
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
ORIG=$(sed -n "${LINE}p" "$README")
|
|
51
|
+
# Replace the first integer in the row cell with a clearly-wrong 999.
|
|
52
|
+
SKEWED=$(printf '%s' "$ORIG" | sed -E 's/(\| \*\*Core Agents\*\* \| )[0-9]+/\1999/')
|
|
53
|
+
if [ "$SKEWED" = "$ORIG" ]; then
|
|
54
|
+
echo "FAIL: could not skew the Core Agents count (regex did not match)"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
# Write the skewed line back in place.
|
|
58
|
+
TMP_README="$(mktemp "${TMPDIR:-/tmp}/counts-verify-skewed.XXXXXX")"
|
|
59
|
+
awk -v ln="$LINE" -v repl="$SKEWED" 'NR==ln{print repl; next} {print}' "$README" > "$TMP_README"
|
|
60
|
+
cp "$TMP_README" "$README"
|
|
61
|
+
rm -f "$TMP_README"
|
|
62
|
+
|
|
63
|
+
if run_commit; then
|
|
64
|
+
echo "FAIL: verifier should BLOCK when a README count is skewed"
|
|
65
|
+
restore; trap - EXIT
|
|
66
|
+
exit 1
|
|
67
|
+
else
|
|
68
|
+
echo "PASS: verifier blocks on skewed README count"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Restore and confirm the repo is green again.
|
|
72
|
+
restore
|
|
73
|
+
trap - EXIT
|
|
74
|
+
if run_commit; then
|
|
75
|
+
echo "PASS: verifier green again after restore"
|
|
76
|
+
else
|
|
77
|
+
echo "FAIL: verifier should pass after restoring README"
|
|
78
|
+
exit 1
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# ── Test 3: network check is gated off for local commits ──────────────
|
|
82
|
+
# Stub `gh` to touch a sentinel file when invoked. The verifier suppresses
|
|
83
|
+
# gh's stderr (2>/dev/null), so signal via a file instead of stderr.
|
|
84
|
+
# Prepend the stub dir to PATH so it wins over any real gh.
|
|
85
|
+
STUB_DIR="$(mktemp -d "${TMPDIR:-/tmp}/counts-verify-stub.XXXXXX")"
|
|
86
|
+
SENTINEL="$STUB_DIR/gh-was-called"
|
|
87
|
+
cat > "$STUB_DIR/gh" <<STUB
|
|
88
|
+
#!/bin/sh
|
|
89
|
+
touch "$SENTINEL"
|
|
90
|
+
# Emit an empty description so the verifier's [ -n "\$GH_DESC" ] guard skips
|
|
91
|
+
# the About comparison (no false block).
|
|
92
|
+
exit 0
|
|
93
|
+
STUB
|
|
94
|
+
chmod +x "$STUB_DIR/gh"
|
|
95
|
+
|
|
96
|
+
rm -f "$SENTINEL"
|
|
97
|
+
( cd "$REPO_ROOT" && echo '{"tool_input":{"command":"git commit -m test"}}' \
|
|
98
|
+
| PATH="$STUB_DIR:$PATH" SUPERKIT_VERIFY_CHECK_REMOTE=0 bash "$HOOK" >/dev/null 2>&1 ) || true
|
|
99
|
+
if [ -f "$SENTINEL" ]; then
|
|
100
|
+
echo "FAIL: local commit invoked gh (network check should be gated off)"
|
|
101
|
+
rm -rf "$STUB_DIR"; exit 1
|
|
102
|
+
fi
|
|
103
|
+
echo "PASS: local commit does not invoke gh (network gated off)"
|
|
104
|
+
|
|
105
|
+
# --check-remote opts in: the stub gh IS called.
|
|
106
|
+
rm -f "$SENTINEL"
|
|
107
|
+
( cd "$REPO_ROOT" && echo '{"tool_input":{"command":"git commit -m test"}}' \
|
|
108
|
+
| PATH="$STUB_DIR:$PATH" bash "$HOOK" --check-remote >/dev/null 2>&1 ) || true
|
|
109
|
+
if [ -f "$SENTINEL" ]; then
|
|
110
|
+
echo "PASS: --check-remote invokes gh"
|
|
111
|
+
else
|
|
112
|
+
echo "FAIL: --check-remote should invoke gh"
|
|
113
|
+
rm -rf "$STUB_DIR"; exit 1
|
|
114
|
+
fi
|
|
115
|
+
rm -rf "$STUB_DIR"
|
|
116
|
+
|
|
117
|
+
echo ""
|
|
118
|
+
echo "ALL COUNTS-VERIFY TESTS PASSED"
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# dev-required-on-commit_test.sh — regression tests for dev-required-on-commit.sh
|
|
3
|
+
# Usage: bash packages/core/hooks/tests/dev-required-on-commit_test.sh
|
|
4
|
+
# Exit codes: 0 if all cases pass, 1 on first failure.
|
|
5
|
+
|
|
6
|
+
set -u
|
|
7
|
+
|
|
8
|
+
HOOK=$(cd "$(dirname "$0")/.." && pwd)/dev-required-on-commit.sh
|
|
9
|
+
TMP=$(mktemp -d)
|
|
10
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
11
|
+
|
|
12
|
+
SID="test-dev-required-$$"
|
|
13
|
+
COUNTER="${TMPDIR:-/tmp}/claude-edit-count-${SID}"
|
|
14
|
+
MARKER="${TMPDIR:-/tmp}/claude-dev-marker-${SID}"
|
|
15
|
+
# Long-lived anti-reset cycle log — the hook derives this path from
|
|
16
|
+
# SESSION_KEY (= session_id = SID).
|
|
17
|
+
CYCLES_FILE="$HOME/.claude/state/dev-cycles-${SID}.jsonl"
|
|
18
|
+
|
|
19
|
+
PASS=0
|
|
20
|
+
FAIL=0
|
|
21
|
+
FAIL_DETAILS=""
|
|
22
|
+
|
|
23
|
+
# Clear ALL session state between cases — including the anti-reset cycle log,
|
|
24
|
+
# so override cases never inherit a consecutive-override penalty from earlier
|
|
25
|
+
# cases. (The final call also cleans up the long-lived file on the way out.)
|
|
26
|
+
reset_state() { rm -f "$COUNTER" "$MARKER" "$CYCLES_FILE"; }
|
|
27
|
+
|
|
28
|
+
run_case() {
|
|
29
|
+
local name="$1"
|
|
30
|
+
local expected="$2"
|
|
31
|
+
shift 2
|
|
32
|
+
local repo="$TMP/case-$PASS-$FAIL"
|
|
33
|
+
rm -rf "$repo"
|
|
34
|
+
mkdir -p "$repo"
|
|
35
|
+
(cd "$repo" && git init -q && git -c user.email=t@t -c user.name=t commit --allow-empty -qm init)
|
|
36
|
+
# NOTE: caller manages counter/marker state so we don't wipe pre-set values.
|
|
37
|
+
# shellcheck disable=SC2068
|
|
38
|
+
$@ "$repo"
|
|
39
|
+
local payload
|
|
40
|
+
payload=$(printf '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"git -C %s commit -m %s"},"session_id":"%s"}' "$repo" "${COMMIT_MSG:-test}" "$SID")
|
|
41
|
+
local actual
|
|
42
|
+
actual=$(echo "$payload" | bash "$HOOK" >/dev/null 2>&1; echo $?)
|
|
43
|
+
if [ "$actual" = "$expected" ]; then
|
|
44
|
+
echo " ✓ $name (exit=$actual)"
|
|
45
|
+
PASS=$((PASS + 1))
|
|
46
|
+
else
|
|
47
|
+
echo " ✗ $name — expected $expected, got $actual"
|
|
48
|
+
FAIL=$((FAIL + 1))
|
|
49
|
+
FAIL_DETAILS="${FAIL_DETAILS}\n - $name (expected=$expected actual=$actual)"
|
|
50
|
+
fi
|
|
51
|
+
unset COMMIT_MSG
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# ── Case helpers ──────────────────────────────────────────────────────────
|
|
55
|
+
|
|
56
|
+
stage_code() {
|
|
57
|
+
local r="$1"
|
|
58
|
+
(cd "$r" && mkdir -p backend && \
|
|
59
|
+
echo "package main" > backend/main.go && \
|
|
60
|
+
git add backend/main.go)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
stage_docs_only() {
|
|
64
|
+
local r="$1"
|
|
65
|
+
(cd "$r" && \
|
|
66
|
+
echo "# readme" > README.md && \
|
|
67
|
+
git add README.md)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Exempt-path stagers: a CODE file under memory/ or .claude/ must still be
|
|
71
|
+
# treated as exempt (HAS_CODE stays false) — the D3 regression target.
|
|
72
|
+
stage_memory() {
|
|
73
|
+
local r="$1"
|
|
74
|
+
(cd "$r" && mkdir -p memory && \
|
|
75
|
+
echo "package mem" > memory/snippet.go && \
|
|
76
|
+
git add memory/snippet.go)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
stage_claude() {
|
|
80
|
+
local r="$1"
|
|
81
|
+
(cd "$r" && mkdir -p .claude && \
|
|
82
|
+
echo "package cfg" > .claude/config.go && \
|
|
83
|
+
git add .claude/config.go)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
set_counter() { echo "$1" > "$COUNTER"; }
|
|
87
|
+
set_marker() { touch "$MARKER"; }
|
|
88
|
+
|
|
89
|
+
# ── Run suite ──────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
echo "dev-required-on-commit_test.sh — regression suite"
|
|
92
|
+
echo ""
|
|
93
|
+
|
|
94
|
+
# Case A: 0 edits + code staged → allow
|
|
95
|
+
reset_state
|
|
96
|
+
run_case "A: 0 edits + code staged → ALLOW" 0 stage_code
|
|
97
|
+
|
|
98
|
+
# Case B: 3 edits + code + no /dev marker → BLOCK
|
|
99
|
+
reset_state; set_counter 3
|
|
100
|
+
run_case "B: 3 edits + code + no /dev → BLOCK" 2 stage_code
|
|
101
|
+
|
|
102
|
+
# Case C: 3 edits + [quick: <rationale≥15 chars>] → ALLOW (Task 12)
|
|
103
|
+
reset_state; set_counter 3
|
|
104
|
+
COMMIT_MSG="'[quick: minor config path adjustment, no logic change]'"
|
|
105
|
+
run_case "C: 3 edits + [quick: …] rationale → ALLOW" 0 stage_code
|
|
106
|
+
[ ! -f "$COUNTER" ] && [ ! -f "$MARKER" ] && echo " (state reset verified)" || echo " WARN: state not reset after C"
|
|
107
|
+
|
|
108
|
+
# Case D: 3 edits + marker present → ALLOW
|
|
109
|
+
reset_state; set_counter 3; set_marker
|
|
110
|
+
run_case "D: 3 edits + /dev marker → ALLOW" 0 stage_code
|
|
111
|
+
|
|
112
|
+
# Case E: 5 edits + docs-only staged → ALLOW (docs-only exempt)
|
|
113
|
+
reset_state; set_counter 5
|
|
114
|
+
run_case "E: 5 edits + docs-only → ALLOW (exempt)" 0 stage_docs_only
|
|
115
|
+
|
|
116
|
+
# Case F: [no-dev: <rationale>] override on any count → ALLOW
|
|
117
|
+
reset_state; set_counter 10
|
|
118
|
+
COMMIT_MSG="'[no-dev: infra-only change, .claude settings]'"
|
|
119
|
+
run_case "F: [no-dev: …] rationale → ALLOW" 0 stage_code
|
|
120
|
+
|
|
121
|
+
# ── Task 12 cases ─────────────────────────────────────────────────────────
|
|
122
|
+
|
|
123
|
+
# Case G: bare [quick] without rationale → BLOCK (Task 12)
|
|
124
|
+
reset_state; set_counter 3
|
|
125
|
+
COMMIT_MSG="'[quick] typo'"
|
|
126
|
+
run_case "G: bare [quick] (no rationale) → BLOCK" 2 stage_code
|
|
127
|
+
|
|
128
|
+
# Case H: [quick: short] rationale <15 chars → BLOCK
|
|
129
|
+
reset_state; set_counter 3
|
|
130
|
+
COMMIT_MSG="'[quick: tiny]'"
|
|
131
|
+
run_case "H: [quick: tiny] under 15 chars → BLOCK" 2 stage_code
|
|
132
|
+
|
|
133
|
+
# Case I: [hotfix] without ticket → BLOCK
|
|
134
|
+
reset_state; set_counter 3
|
|
135
|
+
COMMIT_MSG="'[hotfix] emergency'"
|
|
136
|
+
run_case "I: bare [hotfix] (no ticket) → BLOCK" 2 stage_code
|
|
137
|
+
|
|
138
|
+
# Case J: [hotfix: #42 fix] → ALLOW (ticket present)
|
|
139
|
+
reset_state; set_counter 3
|
|
140
|
+
COMMIT_MSG="'[hotfix: #42 urgent auth regression]'"
|
|
141
|
+
run_case "J: [hotfix: #42 …] ticket → ALLOW" 0 stage_code
|
|
142
|
+
|
|
143
|
+
# Case K: [hotfix: no-ticket: <reason ≥15>] → ALLOW
|
|
144
|
+
reset_state; set_counter 3
|
|
145
|
+
COMMIT_MSG="'[hotfix: no-ticket: customer-reported 500 on payment flow]'"
|
|
146
|
+
run_case "K: [hotfix: no-ticket: …] explicit justification → ALLOW" 0 stage_code
|
|
147
|
+
|
|
148
|
+
# ── D3 regression: exempt short-circuit + intentional tag match ────────────
|
|
149
|
+
|
|
150
|
+
# Case L: memory-only commit whose message MENTIONS a tag in prose → ALLOW.
|
|
151
|
+
# (Old bug: the override regex grepped the whole command string, so a prose
|
|
152
|
+
# mention of [no-dev: x] — reason <15 chars — hard-blocked an exempt commit.)
|
|
153
|
+
reset_state
|
|
154
|
+
COMMIT_MSG="'note explaining the [no-dev: x] override tag for future readers'"
|
|
155
|
+
run_case "L: memory-only + prose tag mention → ALLOW (exempt)" 0 stage_memory
|
|
156
|
+
|
|
157
|
+
# Case M: memory-only, no tag at all → ALLOW
|
|
158
|
+
reset_state
|
|
159
|
+
run_case "M: memory-only + no tag → ALLOW (exempt)" 0 stage_memory
|
|
160
|
+
|
|
161
|
+
# Case N: .claude-only commit → ALLOW
|
|
162
|
+
reset_state
|
|
163
|
+
run_case "N: .claude-only → ALLOW (exempt)" 0 stage_claude
|
|
164
|
+
|
|
165
|
+
# Case O: code commit under anti-reset penalty (OVERRIDE_DISABLED) carrying a
|
|
166
|
+
# real LEADING override tag → BLOCK. Seed 3 consecutive override cycles so
|
|
167
|
+
# consecutive_override_tail ≥ 3 flips OVERRIDE_DISABLED=true.
|
|
168
|
+
reset_state; set_counter 3
|
|
169
|
+
mkdir -p "$(dirname "$CYCLES_FILE")"
|
|
170
|
+
_now=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
171
|
+
{
|
|
172
|
+
printf '{"ts":"%s","outcome":"allow-override","tag":"[quick]","counter":0}\n' "$_now"
|
|
173
|
+
printf '{"ts":"%s","outcome":"allow-override","tag":"[quick]","counter":0}\n' "$_now"
|
|
174
|
+
printf '{"ts":"%s","outcome":"allow-override","tag":"[quick]","counter":0}\n' "$_now"
|
|
175
|
+
} > "$CYCLES_FILE"
|
|
176
|
+
COMMIT_MSG="'[no-dev: real infra change, but override path is locked now]'"
|
|
177
|
+
run_case "O: code + penalty + real leading tag → BLOCK (penalty)" 2 stage_code
|
|
178
|
+
|
|
179
|
+
# Case P: code commit with a valid LEADING tag, no penalty → ALLOW *and* a
|
|
180
|
+
# cycle must be appended to the anti-reset log (feeds cycles_last_hour).
|
|
181
|
+
reset_state; set_counter 3
|
|
182
|
+
COMMIT_MSG="'[quick: legitimate small fix with enough rationale text]'"
|
|
183
|
+
run_case "P: code + valid leading tag, no penalty → ALLOW" 0 stage_code
|
|
184
|
+
if grep -q '"outcome":"allow-override"' "$CYCLES_FILE" 2>/dev/null; then
|
|
185
|
+
echo " ✓ P-state: allow-override cycle appended"
|
|
186
|
+
PASS=$((PASS + 1))
|
|
187
|
+
else
|
|
188
|
+
echo " ✗ P-state: expected allow-override cycle in cycle log"
|
|
189
|
+
FAIL=$((FAIL + 1))
|
|
190
|
+
FAIL_DETAILS="${FAIL_DETAILS}\n - P-state: no allow-override cycle appended"
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
# Case Q: code commit whose message mentions a tag only MID-SENTENCE → NOT an
|
|
194
|
+
# override; control falls to the normal edit-budget block (count 3, no /dev
|
|
195
|
+
# marker) → BLOCK.
|
|
196
|
+
reset_state; set_counter 3
|
|
197
|
+
COMMIT_MSG="'fix the [no-dev: handling] path in the commit parser code'"
|
|
198
|
+
run_case "Q: code + mid-sentence tag mention → BLOCK (not an override)" 2 stage_code
|
|
199
|
+
|
|
200
|
+
echo ""
|
|
201
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
202
|
+
reset_state
|
|
203
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
204
|
+
echo -e "Failures:${FAIL_DETAILS}"
|
|
205
|
+
exit 1
|
|
206
|
+
fi
|
|
207
|
+
exit 0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Regression: [wip] commit on main must be BLOCKED (exit 2).
|
|
3
|
+
set -u
|
|
4
|
+
HOOK="$(cd "$(dirname "$0")/.." && pwd)/dev-required-on-commit.sh"
|
|
5
|
+
TMP=$(mktemp -d); cd "$TMP"
|
|
6
|
+
git init -q && git -c user.email=t@t -c user.name=t checkout -q -b main
|
|
7
|
+
git -c user.email=t@t -c user.name=t commit -q --allow-empty -m "init"
|
|
8
|
+
# Stage a CODE file: the wip-on-main rule lives in the override branch, which
|
|
9
|
+
# (after the D3 fix) is reached only for non-exempt code commits. A non-code
|
|
10
|
+
# ([wip] on a .txt) commit now correctly short-circuits to exit 0.
|
|
11
|
+
echo "package main" > a.go && git add a.go
|
|
12
|
+
|
|
13
|
+
PAYLOAD='{"tool_name":"Bash","tool_input":{"command":"git commit -m \"[wip] x\""}}'
|
|
14
|
+
OUT=$(printf '%s' "$PAYLOAD" | bash "$HOOK" 2>&1); RC=$?
|
|
15
|
+
|
|
16
|
+
if [ "$RC" -eq 2 ] && printf '%s' "$OUT" | grep -q "not allowed on main"; then
|
|
17
|
+
echo "PASS: [wip] on main blocked"; cd /; rm -rf "$TMP"; exit 0
|
|
18
|
+
else
|
|
19
|
+
echo "FAIL: rc=$RC out=$OUT"; cd /; rm -rf "$TMP"; exit 1
|
|
20
|
+
fi
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# doc-check-on-commit_test.sh — regression tests for packages/core/hooks/doc-check-on-commit.sh
|
|
3
|
+
#
|
|
4
|
+
# Usage: bash packages/core/hooks/tests/doc-check-on-commit_test.sh
|
|
5
|
+
# Exit codes: 0 if all cases pass, 1 on first failure.
|
|
6
|
+
|
|
7
|
+
set -u
|
|
8
|
+
|
|
9
|
+
HOOK=$(cd "$(dirname "$0")/.." && pwd)/doc-check-on-commit.sh
|
|
10
|
+
TMP=$(mktemp -d)
|
|
11
|
+
trap 'rm -rf "$TMP"' EXIT
|
|
12
|
+
|
|
13
|
+
PASS=0
|
|
14
|
+
FAIL=0
|
|
15
|
+
FAIL_DETAILS=""
|
|
16
|
+
|
|
17
|
+
run_case() {
|
|
18
|
+
local name="$1"
|
|
19
|
+
local expected="$2"
|
|
20
|
+
shift 2
|
|
21
|
+
# Each case prepares its own repo state in a subshell + checks exit.
|
|
22
|
+
local repo="$TMP/case-$PASS-$FAIL"
|
|
23
|
+
rm -rf "$repo"
|
|
24
|
+
mkdir -p "$repo"
|
|
25
|
+
(cd "$repo" && git init -q && git -c user.email=t@t -c user.name=t commit --allow-empty -qm init)
|
|
26
|
+
# shellcheck disable=SC2068
|
|
27
|
+
$@ "$repo"
|
|
28
|
+
# Payload uses `git -C <repo> commit` so the hook runs `git diff` against
|
|
29
|
+
# the right repo regardless of caller's cwd.
|
|
30
|
+
local payload
|
|
31
|
+
payload=$(printf '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"git -C %s commit -m test"}}' "$repo")
|
|
32
|
+
local actual
|
|
33
|
+
actual=$(echo "$payload" | CLAUDE_PROJECT_DIR="$repo" bash "$HOOK" >/dev/null 2>&1; echo $?)
|
|
34
|
+
if [ "$actual" = "$expected" ]; then
|
|
35
|
+
echo " ✓ $name (exit=$actual)"
|
|
36
|
+
PASS=$((PASS + 1))
|
|
37
|
+
else
|
|
38
|
+
echo " ✗ $name — expected $expected, got $actual"
|
|
39
|
+
FAIL=$((FAIL + 1))
|
|
40
|
+
FAIL_DETAILS="${FAIL_DETAILS}\n - $name (expected=$expected actual=$actual)"
|
|
41
|
+
fi
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
# ── Case setup helpers ─────────────────────────────────────────────────────
|
|
45
|
+
|
|
46
|
+
stage_code_only() {
|
|
47
|
+
local r="$1"
|
|
48
|
+
(cd "$r" && mkdir -p backend/migrations && \
|
|
49
|
+
echo "CREATE TABLE foo();" > backend/migrations/001_foo.up.sql && \
|
|
50
|
+
git add backend/migrations/001_foo.up.sql)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
stage_code_plus_plan() {
|
|
54
|
+
local r="$1"
|
|
55
|
+
(cd "$r" && mkdir -p backend/migrations docs/superpowers/plans && \
|
|
56
|
+
echo "CREATE TABLE foo();" > backend/migrations/001_foo.up.sql && \
|
|
57
|
+
echo "# plan" > docs/superpowers/plans/2026-04-14-foo.md && \
|
|
58
|
+
git add backend/migrations/001_foo.up.sql docs/superpowers/plans/2026-04-14-foo.md)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
stage_code_plus_memory() {
|
|
62
|
+
local r="$1"
|
|
63
|
+
(cd "$r" && mkdir -p backend/migrations memory && \
|
|
64
|
+
echo "CREATE TABLE foo();" > backend/migrations/001_foo.up.sql && \
|
|
65
|
+
echo "# memory note" > memory/note.md && \
|
|
66
|
+
git add backend/migrations/001_foo.up.sql memory/note.md)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
stage_code_plus_changelog() {
|
|
70
|
+
local r="$1"
|
|
71
|
+
(cd "$r" && mkdir -p backend/migrations && \
|
|
72
|
+
echo "CREATE TABLE foo();" > backend/migrations/001_foo.up.sql && \
|
|
73
|
+
echo "# changelog" > CHANGELOG.md && \
|
|
74
|
+
git add backend/migrations/001_foo.up.sql CHANGELOG.md)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
stage_code_plus_arch_doc() {
|
|
78
|
+
local r="$1"
|
|
79
|
+
(cd "$r" && mkdir -p backend/migrations docs/architecture && \
|
|
80
|
+
echo "CREATE TABLE foo();" > backend/migrations/001_foo.up.sql && \
|
|
81
|
+
echo "# Database schema\nTable foo added" > docs/architecture/database-schema.md && \
|
|
82
|
+
echo "# CLAUDE" > CLAUDE.md && \
|
|
83
|
+
git add backend/migrations/001_foo.up.sql docs/architecture/database-schema.md CLAUDE.md)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
stage_new_jobs_file() {
|
|
87
|
+
local r="$1"
|
|
88
|
+
(cd "$r" && mkdir -p backend/jobs && \
|
|
89
|
+
echo "package jobs" > backend/jobs/cleanup.go && \
|
|
90
|
+
git add backend/jobs/cleanup.go)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
stage_modified_middleware() {
|
|
94
|
+
local r="$1"
|
|
95
|
+
(cd "$r" && mkdir -p backend/middleware && \
|
|
96
|
+
echo "package middleware // v1" > backend/middleware/auth.go && \
|
|
97
|
+
git add backend/middleware/auth.go && \
|
|
98
|
+
git -c user.email=t@t -c user.name=t commit -qm init-middleware && \
|
|
99
|
+
echo "package middleware // v2" > backend/middleware/auth.go && \
|
|
100
|
+
git add backend/middleware/auth.go)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# ── Run suite ──────────────────────────────────────────────────────────────
|
|
104
|
+
|
|
105
|
+
echo "doc-check-on-commit_test.sh — regression suite"
|
|
106
|
+
echo ""
|
|
107
|
+
|
|
108
|
+
run_case "code-only commit (migration, no docs) → BLOCK" 2 stage_code_only
|
|
109
|
+
run_case "code + plan file → BLOCK (plan does not satisfy)" 2 stage_code_plus_plan
|
|
110
|
+
run_case "code + memory/*.md → BLOCK (memory does not satisfy)" 2 stage_code_plus_memory
|
|
111
|
+
run_case "code + CHANGELOG → BLOCK (CHANGELOG does not satisfy)" 2 stage_code_plus_changelog
|
|
112
|
+
run_case "code + matching arch doc + CLAUDE.md → ALLOW" 0 stage_code_plus_arch_doc
|
|
113
|
+
run_case "new */jobs/**/*.go → BLOCK (backend-layers + tree)" 2 stage_new_jobs_file
|
|
114
|
+
run_case "modified */middleware/*.go → BLOCK (backend-layers)" 2 stage_modified_middleware
|
|
115
|
+
|
|
116
|
+
echo ""
|
|
117
|
+
echo "Results: $PASS passed, $FAIL failed"
|
|
118
|
+
if [ "$FAIL" -gt 0 ]; then
|
|
119
|
+
echo -e "Failures:${FAIL_DETAILS}"
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
exit 0
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# edit-streak-check_test.sh — regression test for edit-streak-check.sh
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
HOOK="$(cd "$(dirname "$0")/.." && pwd)/edit-streak-check.sh"
|
|
6
|
+
[ -x "$HOOK" ] || { echo "FAIL: hook not executable at $HOOK"; exit 1; }
|
|
7
|
+
|
|
8
|
+
TMPDIR="${TMPDIR:-/tmp}"
|
|
9
|
+
STREAK_FILE="$TMPDIR/claude-edit-streak-test-$$"
|
|
10
|
+
export CLAUDE_EDIT_STREAK_FILE="$STREAK_FILE"
|
|
11
|
+
rm -f "$STREAK_FILE"
|
|
12
|
+
|
|
13
|
+
fire_edit() {
|
|
14
|
+
echo '{"tool_name":"Edit","tool_input":{"file_path":"/tmp/fake.txt"}}' | bash "$HOOK" 2>&1 >/dev/null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fire_bash() {
|
|
18
|
+
echo '{"tool_name":"Bash","tool_input":{"command":"echo hi"}}' | bash "$HOOK" 2>&1 >/dev/null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# Test 1: 4 edits — no warning yet
|
|
22
|
+
for i in 1 2 3 4; do
|
|
23
|
+
OUT=$(fire_edit || true)
|
|
24
|
+
if echo "$OUT" | grep -q "edit streak"; then
|
|
25
|
+
echo "FAIL: warning fired at edit $i (should start at 5)"
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
done
|
|
29
|
+
echo "PASS: edits 1-4 silent"
|
|
30
|
+
|
|
31
|
+
# Test 2: 5th edit — warning fires
|
|
32
|
+
OUT=$(fire_edit || true)
|
|
33
|
+
if ! echo "$OUT" | grep -q "edit streak — 5"; then
|
|
34
|
+
echo "FAIL: 5th edit should warn"
|
|
35
|
+
echo "stderr was: $OUT"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
echo "PASS: 5th edit warns"
|
|
39
|
+
|
|
40
|
+
# Test 3: Bash call resets counter
|
|
41
|
+
fire_bash
|
|
42
|
+
if [ -f "$STREAK_FILE" ]; then
|
|
43
|
+
echo "FAIL: Bash did not clear streak file"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
echo "PASS: Bash resets streak"
|
|
47
|
+
|
|
48
|
+
# Test 4: After reset, next edit is 1 again (silent)
|
|
49
|
+
OUT=$(fire_edit || true)
|
|
50
|
+
if echo "$OUT" | grep -q "edit streak"; then
|
|
51
|
+
echo "FAIL: first edit after reset should be silent"
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
echo "PASS: post-reset silent"
|
|
55
|
+
|
|
56
|
+
# Test 5: CLAUDE_DISABLE_EDIT_STREAK=1 silences even at 10+
|
|
57
|
+
rm -f "$STREAK_FILE"
|
|
58
|
+
for i in 1 2 3 4 5 6 7 8 9 10; do
|
|
59
|
+
OUT=$(CLAUDE_DISABLE_EDIT_STREAK=1 fire_edit || true)
|
|
60
|
+
if echo "$OUT" | grep -q "edit streak"; then
|
|
61
|
+
echo "FAIL: CLAUDE_DISABLE_EDIT_STREAK=1 should silence"
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|
|
64
|
+
done
|
|
65
|
+
echo "PASS: opt-out silences"
|
|
66
|
+
|
|
67
|
+
# Test 6: fast profile skips entirely
|
|
68
|
+
rm -f "$STREAK_FILE"
|
|
69
|
+
OUT=$(CLAUDE_HOOK_PROFILE=fast fire_edit || true)
|
|
70
|
+
# In fast, no file should be written
|
|
71
|
+
if [ -f "$STREAK_FILE" ]; then
|
|
72
|
+
echo "FAIL: fast profile should not update streak file"
|
|
73
|
+
exit 1
|
|
74
|
+
fi
|
|
75
|
+
echo "PASS: fast profile skips"
|
|
76
|
+
|
|
77
|
+
# Test 7: cross-call accumulation via SESSION_ID
|
|
78
|
+
# Empirically proves whether per-session state survives across hook invocations.
|
|
79
|
+
# Without fix: each `bash "$HOOK"` spawns a new PID → different PPID → count resets.
|
|
80
|
+
# With fix (superkit_session_key): SESSION_ID wins, all 5 calls share one state file.
|
|
81
|
+
export SESSION_ID="test-sess-$$"
|
|
82
|
+
unset CLAUDE_EDIT_STREAK_FILE
|
|
83
|
+
SESS_STREAK_FILE="${TMPDIR}/claude-edit-streak-${SESSION_ID}"
|
|
84
|
+
rm -f "$SESS_STREAK_FILE"
|
|
85
|
+
|
|
86
|
+
for i in 1 2 3 4 5; do
|
|
87
|
+
echo '{"tool_name":"Edit","tool_input":{"file_path":"/tmp/fake.txt"}}' | bash "$HOOK" 2>/dev/null || true
|
|
88
|
+
done
|
|
89
|
+
|
|
90
|
+
SESS_COUNT=$(cat "$SESS_STREAK_FILE" 2>/dev/null || echo 0)
|
|
91
|
+
if [ "$SESS_COUNT" -lt 5 ]; then
|
|
92
|
+
echo "FAIL: cross-call accumulation — state did not accumulate across invocations (count=$SESS_COUNT, expected 5)"
|
|
93
|
+
echo " Likely cause: hook uses bare \$PPID instead of superkit_session_key()"
|
|
94
|
+
unset SESSION_ID
|
|
95
|
+
rm -f "$SESS_STREAK_FILE"
|
|
96
|
+
exit 1
|
|
97
|
+
fi
|
|
98
|
+
echo "PASS: cross-call accumulation via SESSION_ID (count=$SESS_COUNT)"
|
|
99
|
+
|
|
100
|
+
unset SESSION_ID
|
|
101
|
+
rm -f "$SESS_STREAK_FILE"
|
|
102
|
+
|
|
103
|
+
# Cleanup
|
|
104
|
+
rm -f "$STREAK_FILE"
|
|
105
|
+
echo ""
|
|
106
|
+
echo "ALL EDIT-STREAK TESTS PASSED (7/7)"
|