| name | quality-enforcement |
| description | Use when preparing code for commit, PR, or merge - covers linting, type safety, bundle budgets, coverage thresholds, complexity limits, dependency audit, and dead code detection |
Quality Enforcement
Overview
Quality enforcement is automated, not aspirational. If it can be checked by a machine, it must be.
Core principle: A quality check that is not enforced in CI does not exist.
No exceptions. No workarounds. No shortcuts.
The Prime Directive
NO CODE LANDS WITHOUT ALL QUALITY CHECKS PASSING
If a check fails, fix the code. Never disable the check. Never bypass CI.
When to Use
Always before:
- Committing code
- Opening a pull request
- Merging to trunk
- Releasing to production
Especially when:
- "Just suppress the linter this once" (never)
- "CI is too slow, merge manually" (fix CI, do not skip it)
- "Type errors but it works at runtime" (fix the types)
- "Coverage dropped but the critical paths are tested" (restore coverage)
The Entry Protocol
BEFORE any PR or merge:
1. LINT: Zero errors, zero warnings
2. TYPES: Zero type errors (strict mode)
3. TESTS: All passing, coverage meets threshold
4. BUILD: Clean build, no warnings
5. SIZE: Bundle/binary within budget (if applicable)
6. DEPS: No known vulnerabilities (critical/high)
7. COMPLEXITY: No functions exceeding complexity threshold
Any check fails = code is not ready. Fix before advancing.
Quality Check Reference
Check 1: Linting
Standard: Zero errors AND zero warnings
| Setting | Value | Rationale |
|---|
| Errors | 0 | Non-negotiable |
| Warnings | 0 | Warnings become errors you learn to ignore |
| Config committed | Yes | Consistent across all contributors |
| CI enforced | Yes | Local overrides are irrelevant |
Warnings are tomorrow's errors. Either fix them or adjust the rule. Never tolerate warnings.
Disable a rule? Only if the team explicitly agrees the rule is inappropriate for this project. Document the rationale in the config file. Never disable inline for convenience.
Check 2: Type Safety
Standard: Zero type errors, strict mode enabled
TypeScript:
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"forceConsistentCasingInFileNames": true
}
}
Python: mypy or pyright with strict mode.
| Anti-Pattern | Problem | Fix |
|---|
any type | Disables type checking | Use specific types or generics |
// @ts-ignore | Conceals real errors | Fix the type error |
# type: ignore | Same problem | Fix the type error |
| Non-strict mode | False sense of safety | Enable strict from day one |
any is a type error you chose not to resolve. Every any weakens the type system for everything it touches.
Check 3: Test Coverage
Standard: Coverage threshold that never decreases
| Metric | Floor | Target |
|---|
| Line coverage | 80% | 90%+ |
| Branch coverage | 70% | 85%+ |
| New code coverage | 90% | 100% (aspire to) |
Coverage thresholds are a ratchet. They increase, never decrease. Configure CI to fail if coverage drops below the current level.
Coverage is necessary but not sufficient. 100% coverage with poor assertions is worse than 70% coverage with rigorous assertions. Coverage checks combine with TDD discipline (godmode:test-first).
Check 4: Build
Standard: Clean build, zero warnings
- Build must complete successfully
- Zero compiler/build warnings
- Output matches expected structure
- No missing dependencies at build time
Check 5: Bundle Size Budget (Frontend)
Standard: Total bundle size within defined budget
| Target | Budget | Tool |
|---|
| Initial JS (compressed) | <200KB | webpack-bundle-analyzer |
| CSS | <50KB | PurgeCSS check |
| Images | Optimized, WebP/AVIF | imagemin |
| Total page weight | <1MB | Lighthouse |
Set the budget. Enforce in CI. When budget is exceeded, analyze the bundle contents and eliminate or split.
Check 6: Dependency Audit
Standard: Zero critical or high vulnerabilities
| Language | Command | CI Integration |
|---|
| JavaScript | npm audit --audit-level=high | Fail on high+ |
| Python | pip-audit or safety check | Fail on high+ |
| Go | govulncheck ./... | Fail on any |
| Rust | cargo audit | Fail on any |
Also verify:
- No unnecessary dependencies (is every dep actually used?)
- No duplicate dependencies (different versions of same package)
- Dependencies are maintained (last update within 12 months)
Check 7: Complexity Metrics
Standard: No function exceeds complexity threshold
| Metric | Threshold | Tool |
|---|
| Cyclomatic complexity | <10 per function | ESLint (complexity rule), radon, gocyclo |
| Function length | <50 lines | Linter rules |
| File length | <400 lines | Linter rules |
| Parameters | <5 per function | Linter rules |
When complexity exceeds threshold: Refactor. Extract functions. Simplify conditionals. Never raise the threshold.
Check 8: Dead Code
Standard: No unused exports, variables, or dependencies
| What | Tool |
|---|
| Unused exports | ts-prune, knip |
| Unused dependencies | depcheck, knip |
| Unused variables | Linter (no-unused-vars) |
| Unreachable code | Linter, type checker |
Dead code is misleading code. It implies something depends on it. Remove it.
CI Pipeline Template
quality-checks:
steps:
- name: Lint
run: npm run lint
- name: Type Check
run: npm run typecheck
- name: Test
run: npm test -- --coverage
- name: Coverage Check
run: check-coverage --threshold 80
- name: Build
run: npm run build
- name: Bundle Size
run: bundlesize
- name: Audit
run: npm audit --audit-level=high
All checks run on every PR. All must pass before merge.
Cognitive Traps
| Rationalization | Truth |
|---|
| "Just a lint warning, not an error" | Warnings you ignore become errors you miss. |
| "Type error but it works at runtime" | Types prevent the runtime error you have not encountered yet. |
| "Coverage dropped 1%, not a big deal" | 1% per PR = 50% in a year. Ratchets do not go down. |
| "Skip CI, I tested locally" | Local environments differ from CI. That is why CI exists. |
| "Bundle grew because we added features" | Features should replace or split, not only add. |
| "Vulnerability is in a dev dependency" | Dev deps run in CI. CI has secrets. Still a risk. |
| "Function is complex but readable" | Complexity limits exist because readability is subjective. |
| "Dead code might be needed later" | Git remembers. Delete it. Restore from history if needed. |
Guardrails - HALT and Fix
- Disabling lint rules inline without documented rationale
@ts-ignore or # type: ignore without an accompanying issue
- Coverage threshold lowered in config
- CI skipped or overridden for merge
any types spreading through codebase
- Bundle size growing without investigation
- Warnings treated as acceptable
- Audit failures dismissed because "it's a dev dependency"
All of these mean: The check is broken. Fix the check before writing more code.
Integration
Complements:
- godmode:test-first — Tests are one check among many
- godmode:completion-gate — Quality checks are verification evidence
- godmode:project-bootstrap — Checks configured at project setup
- godmode:security-protocol — Dependency audit is a security check
- godmode:performance-tuning — Bundle size is a performance check
The Bottom Line
Every quality check automated in CI. Every check passing before merge. No exceptions.
If a check can be bypassed, it will be bypassed. Make it impossible to bypass.