You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Clean up completed items from TODO.md and ROADMAP.md
Remove strikethrough/done sections from TODO.md (NaN handling, safe_inference
migration, 10 fixed tech debt rows, Fix Plan subsection, 5 completed module
splits). Update ROADMAP.md version to v2.4.1, remove shipped Two-Stage DiD
section, bump Near-Term milestone to v2.5. Fix factual error in CHANGELOG.md
line 16 (was backwards: actual change was @ -> np.dot, not np.dot -> @).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@@ -38,16 +33,6 @@ Target: < 1000 lines per module for maintainability.
38
33
|`estimators.py`| 1161 | Acceptable |
39
34
|`pretrends.py`| 1104 | Acceptable |
40
35
41
-
### ~~NaN Handling for Undefined t-statistics~~ -- DONE
42
-
43
-
All 7 t_stat locations fixed (diagnostics.py, sun_abraham.py, triple_diff.py) -- all now use `np.nan` or `np.isfinite()` guards. Fixed in PR #118 and follow-up PRs.
44
-
45
-
~~**Remaining nuance**: `diagnostics.py:785` SE = 0.0~~ — ✅ Fixed: SE now returns `np.nan` when undefined, and all downstream inference uses `safe_inference()`.
46
-
47
-
### ~~Migrate Existing Inference Call Sites to `safe_inference()`~~ -- DONE
48
-
49
-
✅ All ~32 inline inference call sites migrated to `safe_inference()` across 11 source files: `estimators.py`, `sun_abraham.py`, `staggered.py`, `staggered_aggregation.py`, `triple_diff.py`, `imputation.py`, `two_stage.py`, `diagnostics.py`, `synthetic_did.py`, `trop.py`, `utils.py`. Two sites left as-is with comments: `diagnostics.py:665` (permutation-based p_value) and `linalg.py:1310` (deliberately uses ±inf for zero-SE).
50
-
51
36
---
52
37
53
38
### Tech Debt from Code Reviews
@@ -58,31 +43,21 @@ Deferred items from PR reviews that were not addressed before merge.
58
43
59
44
| Issue | Location | PR | Priority |
60
45
|-------|----------|----|----------|
61
-
|~~TwoStageDiD & ImputationDiD bootstrap hardcodes Rademacher only; no `bootstrap_weights` parameter unlike CallawaySantAnna~~|~~`two_stage_bootstrap.py`, `imputation_bootstrap.py`~~|~~#156, #141~~| ✅ Fixed: Added `bootstrap_weights` parameter to both estimators |
62
-
|~~TwoStageDiD GMM score logic duplicated between analytic/bootstrap with inconsistent NaN/overflow handling~~|~~`two_stage.py`, `two_stage_bootstrap.py`~~|~~#156~~| ✅ Fixed: Unified via `_compute_gmm_scores()` static method |
63
-
|~~ImputationDiD weight construction duplicated between aggregation and bootstrap (drift risk)~~|~~`imputation.py`, `imputation_bootstrap.py`~~|~~#141~~| ✅ Fixed: Extracted `_compute_target_weights()` helper in `imputation_bootstrap.py`|
64
46
| ImputationDiD dense `(A0'A0).toarray()` scales O((U+T+K)^2), OOM risk on large panels |`imputation.py`|#141| Medium (deferred — only triggers when sparse solver fails; fixing requires sparse least-squares alternatives) |
65
47
66
48
#### Performance
67
49
68
50
| Issue | Location | PR | Priority |
69
51
|-------|----------|----|----------|
70
-
|~~TwoStageDiD per-column `.toarray()` in loop for cluster scores~~|~~`two_stage_bootstrap.py`~~|~~#156~~| ✅ Fixed: Single `.toarray()` call replaces per-column loop |
71
52
| ImputationDiD event-study SEs recompute full conservative variance per horizon (should cache A0/A1 factorization) |`imputation.py`|#141| Low |
|~~TROP `n_bootstrap >= 2` validation missing (can yield 0/NaN SE silently)~~|~~`trop.py:462`~~|~~#124~~| ✅ Fixed: Added `ValueError` for `n_bootstrap < 2`|
83
-
|~~SunAbraham deprecated `min_pre_periods`/`min_post_periods` still in `fit()` docstring~~|~~`sun_abraham.py:458-487`~~|~~#153~~| ✅ Fixed: Removed deprecated params from `fit()`|
84
60
| R comparison tests spawn separate `Rscript` per test (slow CI) |`tests/test_methodology_twfe.py:294`|#139| Low |
85
-
|~~Rust TROP bootstrap SE returns 0.0 instead of NaN for <2 samples~~|~~`rust/src/trop.rs:1038-1054`~~|~~#115~~| ✅ Already fixed: Returns `f64::NAN` at `rust/src/trop.rs:1034`|
86
61
87
62
---
88
63
@@ -171,11 +146,7 @@ Spurious RuntimeWarnings ("divide by zero", "overflow", "invalid value") are emi
171
146
- Occurs in IPW and DR estimation methods with covariates
172
147
- Related to logistic regression overflow in edge cases (separate from BLAS bug)
173
148
174
-
### ~~Fix Plan (follow-up PR)~~ -- DONE
175
-
176
-
✅ Replaced `@` operator with `np.dot()` at all 19 affected call sites across 6 files: `linalg.py` (5), `staggered.py` (5), `triple_diff.py` (3), `utils.py` (1), `imputation.py` (4), `trop.py` (1). Regression test added in `test_linalg.py::TestNoDotRuntimeWarnings`.
177
-
178
-
**Long-term:** Revert to `@` operator when numpy ≥ 2.3 becomes the minimum supported version.
149
+
-**Long-term:** Revert to `@` operator when numpy ≥ 2.3 becomes the minimum supported version.
0 commit comments