
## Trigger

About to run `git push` to a shared branch / fork OR about to run
`gh pr create`. The change is "done" in the sense that the work
intent is satisfied; the question is whether it's CI-safe.

## Symptoms

- Tempted to skip a check because "it always passes anyway".
- Pushed something with a TODO / debugging print left in.
- Pushed, then immediately had to push a follow-up "fix lint".
- CI broke on a check that exists locally but you didn't run.

## Fix

Run **the 5 gates in order**. Stop at the first failure; fix; re-run
from gate 1. Do NOT proceed to `git push` until all 5 are green.

1. **Change Hygiene** — what's actually in the diff?
   - `git diff --stat` (size sanity)
   - `git diff` (every change defensible? no debug prints, no commented
     code, no AI-generated junk left behind?)
   - No file outside the intended scope touched (no
     `content/post/**` changes on an AI-layer task, etc.)
2. **Format** — language-specific formatter (prettier / black /
   gofmt / cargo fmt / etc.) reports zero diff.
3. **Lint** — language-specific linter exits 0.
4. **Type** — type checker (mypy / tsc --noEmit / cargo check)
   exits 0.
5. **Tests + Coverage** — full test suite passes; if the project
   has a coverage gate, it's met.

For this blog repo specifically, the gate set is documented in
[`AGENTS.md`](AGENTS.md) `## Pre-completion checks` and runs as:

```bash
pip install -r requirements.txt
python -m unittest discover -s tests
python scripts/ai/redact.py --self-test
python scripts/ai/validate_assets.py
python scripts/ai/build_registry.py --check
python scripts/ai/guard_changed_paths.py --from-git
```

**Iron Law:** *If CI would catch it, you should have caught it
first.* A 30-second local check beats a 5-minute CI round-trip
every time.

## Reuse Rule

- **Load when**: about to push code, about to open a PR, finalizing
  a feature / bugfix / refactor for review, OR after a CI failure
  to confirm local == CI.
- **Do not load when**: still in exploratory work — pre-push gates
  are an end-of-task check, not a per-edit constraint.
