Regression-Proof Practices: Hooks, Tests, and Repo Safety
Hooks, tests, file-length limits, and conventions so the repo stays consistent and regressions are caught locally — especially when AI writes much of your code.
Why this matters for AI-assisted development
When an LLM generates code, it doesn't run your test suite. It doesn't check your linter. It doesn't know what broke since the last commit. You are the safety net — unless you automate one. This guide is about building that automation so you can vibecode fast without fear.
See also: Vibecoding Workflow for day-to-day IDE habits with Cursor & Claude.
Adoption paths: new project or existing
Starting a new project
Set up defenses from day one so vibecoding stays safe as the codebase grows.
| Phase | What to add | Sections |
|---|---|---|
| 1 - Foundation | Pre-commit hook: linter, type-check (or compile), file-length check (500 lines). One code-quality script. Commit-msg hook if you use version prefixes. CI runs same script. | §1, §2, §4, §5 |
| 2 - Tests | Unit tests for new code on pre-commit. Integration tests for API/DB. Secret scanning (e.g. Gitleaks) and dependency audit in CI. | §3, §16 |
| 3 - Full pipeline | E2E smoke on pre-commit or CI. Translation validation if i18n. Accessibility checks if web. Lockfile verification. Bundle size budget if front-end. | §1, §4, §16 |
| 4 - Harden | Branch protection, CODEOWNERS for sensitive paths, PR checklist. Optional: coverage gate, SAST, visual regression, diff size limit. | §16 |
Order of work: Create the repo -> add code-quality script and file-length check -> install pre-commit -> add CI job -> add tests -> add optional checks as needed.
Adding to an existing project
Introduce defenses step by step so the team can adopt without a big-bang change.
| Phase | What to do | Sections |
|---|---|---|
| 1 - Align | Audit what you already have. Add one code-quality script. Install pre-commit hook. Ensure CI runs the same script. | §1, §4 |
| 2 - Conventions | Introduce file-length check (500 lines). Exclude current files or add a grace period. Add commit-msg hook if you want version prefixes. | §2, §5 |
| 3 - Tests and security | Run existing tests on pre-commit. Add tests for areas you touch often. Add secret scanning and dependency audit in CI. | §3, §16 |
| 4 - Optional defenses | Add checks from §16 by priority: secret scan and dependency audit first; then bundle size, SAST, coverage gate; then the rest. | §16 |
Minimum for vibecoding
Even with no existing automation, aim for this:
- Pre-commit: Lint + type-check/compile + file-length (500) + run tests (or tests in CI only at first).
- CI: Same as pre-commit; no merge when CI is red.
- One script: Single code-quality or "check" script that pre-commit and CI both run.
1. Use pre-commit hooks as your first line of defense
Hooks run the same checks locally as in CI, so broken code is caught before push and before merge.
CI alignment: Have CI run the same script or the same steps as pre-commit (e.g. the same code-quality-check.sh). If a check runs only in CI, add it to the local flow so it is never skipped.
What to run on pre-commit
| Check | Why it matters for vibecoding |
|---|---|
| File length (e.g. max 500 lines) | Keeps files small so AI context stays manageable and edits stay local. |
| Linter / formatter | Keeps style consistent so generated code matches the rest of the repo. |
| Type-check / compile | Catches type and build errors immediately after AI edits. |
| Unit / integration tests | Prevents regressions from partial or wrong AI suggestions. |
| Translation / i18n validation | Stops hardcoded strings and missing keys from slipping in. |
| Console / TDZ / circular-deps checks | Catches runtime and bundle issues before commit. |
| E2E smoke tests | Optional but powerful: catch chunk/route breakage before push. |
| Accessibility (e.g. color contrast) | Ensures a11y rules are applied even when AI touches CSS or theme files. |
Example: Web (Husky) pre-commit
check:console- no strayconsole.logcheck-file-length.sh 500- enforce max linesvalidate:translations- missing/unused keyscheck:tdz- Temporal Dead Zone issuescheck:cross-chunk- store/import issues across chunkscheck:circular- circular dependenciestype-check- TypeScriptcode-quality-check.sh- file length, swagger, translations, build, Dockertest:e2e:pre-commit- smoke E2E
Example: API (Go) pre-commit
- File length (500 lines)
- TODO categorization
- Swagger doc generation and staging
- Docker image build
- Conditional tests: run
go test ./...only when Go files are staged.
Bypassing hooks
Use git commit --no-verify only in rare cases (e.g. WIP). Fix and recommit before merging; CI will still run the same checks.
2. Enforce a file length limit (e.g. 500 lines)
Goal: Keep files small so AI has full file context and changes stay local.
- Script: e.g.
scripts/check-file-length.sh [MAX_LINES](default 500). - Scope: Tracked files only; exclude
node_modules,vendor, lock files, generated files, minified assets, etc. - Failure: Pre-commit fails if any included file exceeds the limit.
Vibecoding tip: When a file nears the limit, split before asking the AI to add features. Then point the AI at the new small file so it has full context.
3. Layer tests so AI edits are validated at every level
Tests turn "vibecoding" from "hope it works" into "we know it works."
Unit tests
- Where: Next to code (
*_test.go,*.test.ts,test_*.py) or intests/. - What: Pure logic, parsers, formatters, validation, small composables.
- When: Run on pre-commit (and CI).
- Vibecoding: After AI changes behavior, ask: "Add a unit test for the happy path and for invalid input."
Integration tests
- What: API clients, DB access, retry logic, auth flows.
- When: Pre-commit and CI; keep them fast (mocks, in-memory or test DB).
E2E tests
- What: Full user flows (auth, shopping, search, key pages).
- Pre-commit: A smoke subset (critical routes + console-error checks).
- CI: Full E2E on staging/production-like env.
- Vibecoding: E2E that assert "no console errors" on key routes catch chunk/initialization bugs that AI might introduce.
4. Code-quality scripts: one place for "did we break anything?"
Centralize checks in a code-quality-check.sh so pre-commit and CI run the same pipeline.
Typical steps: File length; TODO categorization; Download/validate Swagger; Translation validation; Lockfile sync; Build; Docker build (optional, can be CI-only for speed).
No drift between "what I run locally" and "what CI runs."
5. Commit-msg hooks: version and conventions
- Version prefixes: e.g.
[patch],[minor],[major]so a commit-msg hook can validate format and bump version. - Conventions: Enforce "no merge without passing checks" by making hooks the default.
6. Checklist before relying on AI edits
Use this before you prompt and again before you commit.
- File size: File (and related ones) under the limit; split if not.
- Relevant docs/audits: Opened or linked the doc for the area you're changing.
- Lint/type-check: Pass after edits.
- Tests: Unit/integration (and E2E if applicable) run.
- No
--no-verifyhabit: Prefer fixing and re-committing. - Review: Imports/APIs verified, no hardcoded secrets, style consistent.
- If tests fail: Paste the failure into the next prompt.
7. Reviewing AI-generated code
Before committing:
- Imports and dependencies: Imports exist and match the codebase (no hallucinated packages or paths).
- APIs and types: Functions, endpoints, and types are real, not invented.
- Edge cases and errors: Null/empty checks, error handling, cleanup.
- Security: No hardcoded secrets or PII in logs.
- Style and patterns: Linter/formatter; naming aligned with the repo.
- Tests: If the AI added tests, run them and ensure they assert meaningful behavior.
8. Incremental changes and commits
- Small, focused edits: Several small AI-assisted changes beat one huge "do everything" request.
- Commit often: After each logical step, commit with a clear message.
- Run checks between steps: File length, lint, type-check, tests. Fix before moving on.
- Monorepo / multi-project: One layer at a time. Run each project's code-quality and tests after that layer.
9. Common AI pitfalls to avoid
| Pitfall | What to do |
|---|---|
| Hallucinated APIs | Verify names and signatures against your code or OpenAPI. |
| Wrong or outdated deps | Check manifests for new or changed deps; prefer existing versions. |
| Generic patterns | Ask to follow patterns from a concrete file or doc. |
| Overly large diffs | Narrow scope: one file or one feature; split into follow-ups. |
| Ignoring existing tests | After edits, run the full test suite; add tests if behavior is new. |
| Copy-paste from other codebases | Insist on "our stack only" and reference repo files. |
10. Security and privacy
- No secrets in prompts: Do not paste API keys, passwords, tokens, or real PII into chat. Use placeholders.
- Sanitize before paste: Remove hostnames, internal IDs, and user data from logs.
- Sensitive code: For auth, payments, consent — prefer human design and review; use AI for boilerplate and tests.
11. Parent repo for full infrastructure
When your product spans multiple services, use a parent repository that includes each service as a sub-repo (git submodules, a monorepo with workspaces, or a meta-repo with pinned references).
Why a parent repo
| Goal | How it helps |
|---|---|
| Version and compatibility consistency | Pins a known-good combination of sub-repo versions. No "works on my machine" mismatches. |
| Documentation | Natural home for architecture overview, service diagrams, shared conventions, deployment runbooks. |
| Easy start and setup for new co-workers | A single git clone --recurse-submodules + one setup script gives the entire stack. The README becomes the onboarding guide. |
What to put in the parent repo
README.md- Onboarding: prerequisites, clone, first run, architecture overview.- Setup script -
scripts/setup.sh(orMakefile,docker compose up). - Version manifest or submodule pins - Source of truth for compatible versions.
- Cross-cutting docs - Architecture decisions, shared conventions, deployment docs.
- Shared CI / hooks - Root-level pre-commit, code-quality checks, full-stack integration tests.
Practical tips
- Pin explicit versions. Always pin to a specific commit or tag.
- Automate the "clone and run" path. Zero to running stack in under 15 minutes.
- Keep the parent repo lean. Glue only (scripts, docs, CI, version pins) — not application code.
- Use the parent for cross-service testing. Integration and E2E tests that span services belong here.
12. More defenses and quality checks (optional)
Beyond the basics, add these to harden the pipeline:
Dependency and supply-chain
| Check | Purpose | Where |
|---|---|---|
| Dependency audit | Catch vulnerable or deprecated deps the AI might add | CI, optionally pre-commit |
| License compliance | Enforce allowed licenses for new deps | CI or PR |
| Lockfile / checksum verification | Ensure lockfiles match; detect tampering | Pre-commit, CI |
Secrets and security
| Check | Purpose | Where |
|---|---|---|
| Secret scanning | Block commits with API keys, tokens, or passwords | Pre-commit, CI |
| SAST (static analysis) | Find security issues in code | CI |
Performance and front-end
| Check | Purpose | Where |
|---|---|---|
| Bundle size budget | Fail if JS/CSS bundle grows beyond a limit | CI |
| Lighthouse CI | Enforce performance and a11y budgets | CI |
Review and process
| Check | Purpose | Where |
|---|---|---|
| Branch protection | Require CI green and at least one approval before merge | Repo settings |
| CODEOWNERS | Ensure sensitive paths get review from owners | PR / GitHub/GitLab |
| PR checklist | "AI-assisted: imports verified, tests run, no secrets" | PR template |
Summary table
| Practice | Purpose | Where |
|---|---|---|
| Max 500 lines per file | Smaller context, better AI and maintainability | check-file-length.sh, pre-commit, code-quality |
| Linter / type-check / compile | Consistency and early errors | Pre-commit, code-quality, CI |
| Unit / integration tests on commit | Regression prevention | Pre-commit, CI |
| E2E smoke on commit | Chunk/route/console errors | Pre-commit (Web), CI |
| Translation / i18n validation | No missing keys or hardcoded text | Pre-commit (Web), code-quality |
| Commit-msg (version/conventions) | Consistent versioning and messages | commit-msg hook |
| Security and privacy | No secrets in prompts; human-review auth paths | Review checklist |
| Parent repo | Version pins, shared setup, cross-cutting docs | Root repo |
| More defenses (optional) | Dependency audit, secret scan, bundle size, etc. | §12 |
References
- Cursor Forum — Guides, discussions, and support.
- Anthropic — Claude Code — Claude Code overview and workflows.
- PreuJust (example repo) — Real-world hooks, test layout, and code-quality scripts.