Orchestrata Ultimate › Gates › mypy

Gate: mypy

At a glance

Purpose Refuse a mypy type error in src/ locally, so the first sight of one is never a failed pipeline.
Where it runs The PostToolUse hook typecheck-on-write.sh (on every write); the scripts/gates.py battery (registered as mypy); CI's lint job; per file inside the commit review (code-review.py's MyPyChecker, run by scripts/gate.py review-staged).
Trigger A file write in a session; a battery run; a CI pipeline; every git commit that stages .py files under src/.
Exact command Battery argv: uv run mypy --cache-dir .cache/mypy src/. CI: uv run mypy src/. Commit review: <interpreter> -m mypy --no-error-summary <file>, 30 s timeout.
Blocks mypy's own exit code: non-zero on errors, 0 clean. In the commit review, mypy findings and MYPY_TIMEOUT / MYPY_NOT_FOUND are ERROR and block the commit.
Ruling / ADR None names this gate directly; the commit-review layer is RUL-008.
Last recorded verdict ok: true in the primary checkout's .cache/gates.json (file last written 2026-09-22 10:01 local). wt-MAP-PRECOMMIT has no .cache/gates.json.

What it refuses

A mypy type error in src/ — caught locally, with the exact command CI runs, so the first sight of a type error is never a failed pipeline.

Why it exists

The gates.py registry comment records the incident:

"THE SAME COMMAND CI's lint job runs. Until 2026-08-07 mypy was a CI-ONLY gate: this battery could report 10/10 while uv run mypy src/ was red, so the first sight of a type error was a failed pipeline — which is exactly what happened (16 errors, two files, after a local run reported 0 from a stale incremental cache)."

And the cache-location decision:

"--cache-dir is pinned INSIDE the repo on purpose. The default .mypy_cache resolves per working directory, and sibling worktrees sharing this checkout's caches have already produced results attributed to the wrong tree. Pinning it makes a gate PASS mean this tree."

How it runs

Typical failures and how to fix them

Wiring