ci: gate on mypy, so #266's ungating cannot quietly come undone - #268
Merged
Conversation
`mypy` ran in NO workflow before this -- it appeared only in a passing comment in `code-quality.yml`. #266 brought `keel.*` under the checker, but nothing enforced that: a type error there was a clean CI run. Added as a STEP in the existing `test` job, not a job of its own. The `main` ruleset requires the status context `test`, which comes from that job's id, so a separate `typecheck:` job would report a context nothing requires and a red mypy would not block a merge -- the same failure shape `ci.yml`'s header already warns about for renamed jobs. `release.yml` gets it too, and re-runs it rather than trusting CI's: that workflow is dispatched against whatever `main` is at the time, which need not be a commit any CI run went green on. Neither workflow repeats the paths; they come from `[tool.mypy]`'s `files`. CI closes only half the hole, though. It catches a type ERROR in `keel/`. It cannot catch `keel.*` being re-added to an `ignore_errors` override, which silences the package wholesale -- mypy then exits 0 while checking nothing there, and the ungating is reverted with a green build to show for it. Verified both halves: with a type error injected, mypy exits 1; with the exemption restored, mypy exits 0 and only the new `test_keel_is_not_exempt_from_type_checking` fails. `tests.*` and `keel_core.*` stay legitimately exempt; the guard pins only the module that was deliberately brought under the checker. 2726 -> 2727 tests. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 16, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
mypyran in no workflow before this — it appeared only in a passing comment incode-quality.yml. #266 broughtkeel.*under the checker, but nothing enforced it: a type error inkeel/was a clean CI run.Why a step, not a job
Added to the existing
testjob rather than as atypecheck:job of its own. Themainruleset requires the status contexttest, which comes from that job's id — a separate job would report a context nothing requires, so a red mypy would not block a merge. That is the same failure shapeci.yml's own header already warns about for renamed jobs. As a step, it inherits the gate.release.ymlgets it too, and deliberately re-runs it rather than trusting CI's result: that workflow is dispatched against whatevermainis at the time, which need not be a commit any CI run went green on.Neither workflow repeats the paths — they come from
[tool.mypy]'sfilesinpyproject.toml, so a package moving in or out of the checked set stays a one-line edit there instead of one mirrored across two workflows.CI only closes half the hole
Running mypy catches a type error in
keel/. It cannot catchkeel.*being re-added to anignore_errorsoverride — that silences the package wholesale, mypy exits 0 while checking nothing there, and #266's ungating is reverted with a green build to show for it.test_keel_is_not_exempt_from_type_checkingcloses that. Both halves verified:mypyexitkeel/sim/report.pykeel.*restored toignore_errorsThe middle row is the point: the guard catches exactly what CI cannot see.
tests.*andkeel_core.*remain legitimately exempt, per the comments beside each inpyproject.toml. The guard pins only the module that was deliberately brought under the checker.Verification
mypy— clean, 224 source filesruff check keel tests packages— cleanpytest— 2727 passed, 1 skipped (2726 + the new guard)🤖 Generated with Claude Code