Skip to main content

Three-Layer Defense

In one line: Post-edit linting → stop-time verification → pre-push blocking → security scanning; a defect must slip past all of them to reach the remote.

Layer 1: Post-Edit Linting. Runs automatically after edits — syntax, style, and type errors surface within seconds, while the code is still in context. Catches the cheapest defects: typos, missing imports, bad annotations, unused variables.

Layer 2: Stop Verification. Runs when the AI signals completion. A verification prompt asks whether tests ran, coverage held, and linting passed — catching the "it should work now" failure mode. It fires every time, whether or not anyone invoked /verification-before-completion. It is the safety net beneath the process layer.

Layer 3: Pre-Push Blocking. A hard gate before the remote — failing tests, sub-threshold coverage, or lint regressions block the push. Last line of defense, catching what slipped past Layers 1-2 (integration failures, coverage drops, merge-conflict lint regressions).

Defense-in-depth rationale: Each layer catches a different defect category at a different cost; the layers are redundant by design, so no single gate failure lets a defect reach the remote unchecked.

Layer 4: Security Scanning. For regulated systems, a compliance requirement, not an optional improvement: a dev-time SAST/secrets/IaC scanner with an auto-remediation loop, plus a PR-time security-review GitHub Action posting inline findings with severity.

Evidence: Each layer is a configured mechanism: the post-edit layer is an LSP plugin catching type errors in real time; the Stop hook (verification prompt in .claude/settings.json) fires on every task completion; the pre-push gate is templates/hooks/pre-push-gate.sh. Reproducible: introduce a type error, an unverified claim, and a failing test, and watch each get caught at its own layer. See appendix-e-hooks.md.