AoE2 · LLM Arena

ADR 0003 — Switch from pyright to basedpyright with reportAny enforcement

Status: Accepted (2026-05). Shipped over commits 4f884f0 / ec4880c / 7d33a29.

Decision

Use basedpyright instead of vanilla pyright. Enable reportAny repo-wide. Stub third-party libraries that don’t ship types (currently coremltools) under typings/. Use # pyright: ignore[reportX] per-line only at SDK boundaries where the upstream stubs are wrong.

What we considered

  1. Stay on pyright. No change.
  2. Move to mypy. Different ecosystem; mypy’s strict mode is incompatible with much of pyright’s inference style.
  3. basedpyright with reportAny. Stricter superset of pyright; better defaults for catching the long tail of Any leaks that vanilla pyright tolerates.

Why basedpyright

The vanilla pyright config tolerates Any flowing freely through SDK boundaries (anthropic, numpy, redis-py, duckdb). That’s manageable in a small codebase; in this one it had grown into a baseline of ~2200 violations that nobody checked because they weren’t surfaced as errors. Every new piece of code reaching for an SDK was rolling a die on whether its return type was actually typed.

basedpyright’s reportAny flips this: any expression whose static type is Any is an error unless explicitly suppressed. That gives three things:

What changed in code

Consequences

Positive

Negative