Context
During the PR #2 review fix loop, two CI round-trips were spent on failures that were fully reproducible locally: an isort ordering error (ruff) and a ty invalid-assignment error in a test. Local checks ran bare ruff instead of the same gates CI runs, so both escaped to the remote.
Proposal
Add a thin script (e.g. scripts/ci-local.sh or a make target) that mirrors the two gating CI jobs:
- pre-commit run --all-files (same hooks CI's 'Lint and Format Check' runs)
- ty check
- the fast unit-test suites
Constraint: uv is currently broken on the dev machine (Rust panic in system-configuration), so the script must run through the venv/python-exec path rather than 'uv run --frozen' as CI does — a small fidelity loss on dependency pinning, acceptable for a pre-push filter.
Non-goal: reproducing the platform build matrix (macos/arm/windows C++ builds) locally; clean-room CI remains authoritative for that layer.
Acceptance
- One command runs all three gates locally and exits nonzero on any failure.
- Documented in the contributor docs as the expected pre-push step.
Context
During the PR #2 review fix loop, two CI round-trips were spent on failures that were fully reproducible locally: an isort ordering error (ruff) and a ty invalid-assignment error in a test. Local checks ran bare ruff instead of the same gates CI runs, so both escaped to the remote.
Proposal
Add a thin script (e.g. scripts/ci-local.sh or a make target) that mirrors the two gating CI jobs:
Constraint: uv is currently broken on the dev machine (Rust panic in system-configuration), so the script must run through the venv/python-exec path rather than 'uv run --frozen' as CI does — a small fidelity loss on dependency pinning, acceptable for a pre-push filter.
Non-goal: reproducing the platform build matrix (macos/arm/windows C++ builds) locally; clean-room CI remains authoritative for that layer.
Acceptance