chore(types): mypy triage to enforceable zero + blocking CI job (3/3)#683
Merged
Conversation
Tier 1 (real fixes): - 19 survey params typed `object` across 13 estimator files -> proper Optional[SurveyDesign]/Optional[ResolvedSurveyDesign] via TYPE_CHECKING imports; linalg's param typed as the SurveyDesign|ResolvedSurveyDesign union its isinstance branches actually handle - solve_ols overload chain unbroken (_validate_weights moved out from between the @overload block and the implementation) - stale return-arity annotations fixed: _aggregate_simple (2->3-tuple), _compute_cluster_psi_sums (2->3-tuple), plus Literal overloads for the flag-dependent returns of _compute_aggregated_se_with_wif and SunAbraham._compute_overall_att - cdh: float-keyed diagnostics dict annotated str-keyed; duplicate inner annotations dropped; a variable reused for two types in the bootstrap renamed; sentinel "_a11_warnings" str key in int-keyed dicts documented with scoped ignores - missing mixin attribute stub (TwoStageDiDBootstrapMixin.pretrends); efficient_did._unit_resolved_survey no longer inferred as type None - ~50 assert-based narrowings at flag-guarded blocks, each documenting a real invariant (all verified: 3,434 targeted tests pass, no assert fires) Tier 2/3 (documented suppressions): - prep_dgp per-module [index] override (seeded-DGP Optional covariate arrays; None-vs-array shape is RNG-stream-load-bearing) - matplotlib/plotly follow_imports=skip for local/CI stub parity - warn_unused_ignores=true; 23 already-stale ignores removed - reasoned inline ignores for mypy's union-explosion limitation CI: lint.yml gains a blocking Mypy job (pinned mypy + numpy/pandas/scipy, no package build); Lint Gate needs extended; TestLintWorkflowPinSync now covers the mypy pin. TODO.md Type Annotations note rewritten to the honest enforced-zero state; Large Module Files table regenerated (2026-07-13); override-tightening tracked as an Actionable row. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Lbd6nqWmg4snvvBmegwqiw
Overall Assessment✅ Looks good — no unmitigated P0 or P1 findings. Executive Summary
Methodology
Code Quality
Performance
Maintainability
Tech Debt
Security
Documentation/Tests
I did not run the full test suite in this review environment; this was a static diff and methodology review. |
igerber
added a commit
that referenced
this pull request
Jul 13, 2026
…job) The type: ignore[assignment] comments on the beta_p_* dataclass fields are unused under the pinned CI mypy config, which now fails on unused ignores (warn_unused_ignores = true). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGca52n6H8oDDXALjjrsp4
igerber
added a commit
that referenced
this pull request
Jul 13, 2026
…0 parity (RDD PR-2) (#684) * feat: RegressionDiscontinuity - sharp RD estimator with rdrobust parity Estimation-path port + public estimator + docs sweep (PR-2 of 2). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGca52n6H8oDDXALjjrsp4 * fix: run mass-point detection before the bandwidth branch + reject bools on integer knobs rdrobust.R:365-380 runs the mass-point check in rdrobust() itself, ahead of the manual-vs-data-driven bandwidth split, so the warning must fire on manual-h fits too (verified on installed 4.0.0). fit() now performs the detection and the port's rdbwselect-level warning is suppressed on the estimator path to mirror R's single warning per fit. Integer knobs (p/q/nnmatch/bwcheck) now reject bool (int subclass) inputs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGca52n6H8oDDXALjjrsp4 * chore: drop stale mypy ignores after rebase onto #683 (blocking mypy job) The type: ignore[assignment] comments on the beta_p_* dataclass fields are unused under the pinned CI mypy config, which now fails on unused ignores (warn_unused_ignores = true). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGca52n6H8oDDXALjjrsp4 --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.
Summary
Final part of the lint/type-hygiene program (#677/#679 normalization, #681 Lint workflow).
mypy diff_diffgoes from 184 errors to an enforced zero, and the Lint workflow gains a blocking Mypy job.Error-class disposition (184 baseline, mid-triage peak 193 from annotation exposure):
[index]79assignmentcode)prep_dgpper-module override (seeded-RNG-stream-load-bearing Optional arrays); rest fixed[attr-defined]51survey_design/resolved_survey: objectparams across 13 files -> properly typed viaTYPE_CHECKINGimports; one attribute inferred as typeNonefrom unannotated= Noneinit; one missing mixin stub[union-attr]21 (+conversions)assert ... is not Nonenarrowings at flag-guarded blocks, each documenting a real invariant (incl. a 5-estimator copy-pasted twin block)[misc]11Literaloverloads (_compute_aggregated_se_with_wif,_compute_overall_att); a variable reused for two types renamed; mypy's union-explosion give-up -> 2 reasoned inline ignores[call-overload]6-8solve_olsoverload chain unbroken (helper moved out from between@overloadblock and implementation); sentinel str key in int-keyed dCDH dicts -> scoped documented ignores[no-redef]4,[operator]8, restNet: ~170 of 184 resolved by real fixes; suppressions are one module override +
matplotlib/plotlystub-parity skips + a handful of reasoned inline ignores.warn_unused_ignores = trueadded — it immediately surfaced 23 stale pre-existing ignores, now removed.CI:
lint.ymlgains theMypyjob (pinnedmypy==2.1.0+ pinnednumpy/pandas/scipyso stubs cannot drift CI-vs-local; the package is NOT installed — no maturin/Rust).Lint Gateneedsextended — no branch-protection change needed (the gate name is unchanged by design).TestLintWorkflowPinSyncnow covers the mypy pin, and a newtest_mypy_job_stub_deps_exact_pinnedlocks the stub pins.Docs: TODO.md "Type Annotations" note rewritten to the honest enforced-zero-with-listed-suppressions state; "Large Module Files" table regenerated from live counts (dated 2026-07-13); suppression-tightening filed as an Actionable Backlog row. CONTRIBUTING/CLAUDE.md updated to the all-three-tools-mirrored state.
Local review: 3 codex rounds (force-fresh), converged to zero actionable findings; round findings (stub-pin guard test, workflow header comment) folded in.
Methodology references (required if estimator / math changes)
Validation
tests/test_openai_review.py -m ''green (254). Targeted estimator batteries across every touched file: 3,434 tests passed, zero narrowing-assert fires (survey, linalg, estimators, staggered, sun_abraham, imputation, two_stage, cdh, efficient_did, spillover, diagnostics, prep, bootstrap_chunking, survey_phase6, had_pretests, wooldridge, triple_diff, staggered_triple_diff, continuous_did, pretrends, bootstrap_utils, methodology_synthetic_control).mypy diff_diffnow reports zero.Security / privacy
Generated with Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_01Lbd6nqWmg4snvvBmegwqiw