ci(python-sdk): enforce mypy with module-by-module allowlist ratchet (#971) - #1052
Conversation
Adopts the mypy half of Agent-Field#620 (the ruff half shipped in Agent-Field#812). mypy.ini existed but nothing ran it. This wires a required mypy step into the Python SDK CI without changing any behavior. Phase 1 of Agent-Field#971: - Pin mypy==1.18.2 in the dev extras (and uv.lock). - Add a per-module ignore_errors allowlist to mypy.ini for the 34 modules that currently have type errors, so the gate can be enforced now and the allowlist shrunk module by module. - Add a 'Type check (mypy)' step to .github/workflows/sdk-python.yml running 'mypy --config-file mypy.ini agentfield/'. The gate is green today (Success: no issues found). It fails if a non-allowlisted module gains a new error, or if a module is removed from the allowlist while it still has errors. No '# type: ignore' sprinkles were added.
Performance
✓ No regressions detected |
📊 Coverage gateThresholds from
✅ Gate passedNo surface regressed past the allowed threshold and the aggregate stayed above the floor. |
📐 Patch coverage gateThreshold: 80% on lines this PR touches vs
✅ Patch gate passedEvery surface whose lines were touched by this PR has patch coverage at or above the threshold. |
santoshkumarradha
left a comment
There was a problem hiding this comment.
The ratchet structure makes sense, but the checked-in environment cannot currently run the new gate.
Addresses review on Agent-Field#1052. The locked dev environment pins requests 2.33.1, which ships no type stubs, so 'uv sync --extra dev' followed by mypy failed with [import-untyped] in multimodal.py and agent_field_handler.py. CI was green only because 'pip install .[dev]' resolved a newer requests that bundles stubs, so it wasn't validating the reproducible environment. Pin types-requests==2.33.0.20260906 in the dev extras (and uv.lock) so mypy passes in both the locked (uv sync) and pip-resolved environments. Verified mypy clean against the locked requests 2.33.1 and a newer requests; ruff still clean; uv lock --check clean.
|
Fixed in e57eaf7. You're right - the gate wasn't reproducible. Reproduced exactly: after Went with your first suggestion: pinned Verified mypy |
session_turn_detection.py landed on main (via Agent-Field#1056) after this PR opened and carries 3 mypy errors (loosely-typed dict value used in numeric comparisons at line 58). The mypy gate correctly failed on it because it was not allowlisted - the ratchet working as designed. Add it to the allowlist to keep this PR a pure CI-wiring change; the module's type errors can be cleaned in a follow-up (phase 2).
santoshkumarradha
left a comment
There was a problem hiding this comment.
Thanks for fixing the reproducible typing environment. I rechecked the updated head with Python 3.13: the locked dev sync, full mypy gate, Ruff, and diff check all pass. The new allowlist entry matches the module added on current main, so this is ready from review.
AbirAbbas
left a comment
There was a problem hiding this comment.
Ran the workflow's exact steps on the merge with main in three environments: fresh pip 3.10, fresh pip 3.13, and the locked uv sync --python 3.13 --extra dev env Santosh used. ruff 0.15.22, mypy --config-file mypy.ini agentfield/ (80 files, clean) and run_pytest.sh pass in all of them, uv lock --check is clean, and the types-requests pin installs on 3.10/3.11/3.12/3.13. The gate is real: a type error injected into an unlisted module fails CI, one in a listed dirty module is suppressed, which is the ratchet contract. All 35 listed modules exist on main. Good to merge.
Summary
Adopts the mypy half of #620 as phase 1 of #971. The ruff half shipped in #812, but the mypy half was never wired up:
sdk/python/mypy.iniexisted and nothing ran it. This adds a requiredmypystep to the Python SDK CI with a module-by-module allowlist, so the gate can be turned on immediately (zero behavior change) and the allowlist shrunk module by module.Closes #971 (phase 1). Refs #620.
Type of change
What changed
mypy==1.18.2in thedevextras (pyproject.toml) and regenerateuv.lock.ignore_errors = Trueallowlist tomypy.inifor the 34 modules that currently have type errors (217 errors total), with a header comment describing the ratchet and how to shrink it.Type check (mypy)step to.github/workflows/sdk-python.ymlrunningmypy --config-file mypy.ini agentfield/.No
# type: ignoresprinkles were added, and noagentfield/source was modified.Validation contract (from #971)
agent_cli.py) makes mypy exit 1.agentfield.typesre-surfaces its errors (exit 1).pip install .[dev]provides the pinned mypy version used in CI.Test plan
cd sdk/python && mypy --config-file mypy.ini agentfield/->Success: no issues found in 79 source files(exit 0)cd sdk/python && ruff check .->All checks passed!cd sdk/python && uv lock --check-> clean after regeneratinguv.lockpython -c "import agentfield"-> imports OKTest coverage
Checklist
Related issues / PRs
Closes #971 (phase 1). Refs #620, #812.
Notes for reviewers
lint-and-testmatrix (Python 3.10-3.13).mypy.inipinspython_version = 3.10, so results are identical across matrix rows; running it in every row is redundant but harmless. Happy to move it to a single dedicated job if you prefer.