Two-stage commit and push gates with Husky and Clawpatch
# The two-stage Husky gates used by this CMS: formatting, types, tests, and secret checks at commit time; structure, E2E, dependency audit, and review before push.
This CMS uses Husky pre-commit and pre-push as two different gates: fast feedback before a commit and repository-specific verification before a push. The exact commands matter more than a generic checklist.
Two-stage quality gate routing a code change through fast pre-commit checks and deeper pre-push verification
*Diagram: return fast failures before commit and reserve repository-wide verification for pre-push.*
Read the hooks as the source of truth
Both hooks invoke pnpm; they do not hard-code an old Corepack release. package.json declares the package-manager version and the Nix development shell enables Corepack. Because .npmrc disables install scripts, a fresh install should not be assumed to have activated hooks: verify git config core.hooksPath after the approved setup.
Pre-commit
bash
set -eupnpm run format:checkpnpm run typecheckpnpm run testpnpm run secrets:stagedpnpm run clawpatch:precommit
Biome, TypeScript, Node tests, redacted staged-secret scanning, and the Clawpatch status gate run in order. set -eu stops the commit at the first non-zero exit. This hook does not independently run ESLint or a production build.
Pre-push
bash
set -eupnpm run verify:pushpnpm run secrets:history
verify:push adds admin structure coverage, ad-slot auditing, admin-route E2E, dependency auditing, and a dirty-tree Clawpatch review. Gitleaks then scans Git history. These checks cover the failure modes of this CMS rather than pretending that one generic test command is sufficient.
Audit all installed dependencies
An unqualified pnpm audit checks installed production and development dependencies. Build, test, hook, and deployment tooling are part of this repository's execution surface, so the release gate uses the full audit rather than narrowing it with --prod.
Clawpatch turns review state into an exit code
The pre-commit wrapper parses clawpatch status --json and fails when open findings or active locks remain. The push wrapper runs a bounded review including dirty changes, then applies the same state check. A previous zero count is never embedded as a permanent claim; every push evaluates current JSON.
Hooks can be bypassed or absent, so they are feedback, not the only protection. Release verification also runs a production build, and protected branches should have equivalent server-side checks.