diff --git a/TODO.md b/TODO.md index 0dc21040..69c80cfa 100644 --- a/TODO.md +++ b/TODO.md @@ -33,7 +33,6 @@ The `Origin` column (Actionable tables) and the `PR` column (Deferred tables) bo | `ImputationDiD` LOO conservative-variance refinement (BJS 2024 Supp. Appendix A.9) — a finite-sample improvement to the auxiliary-model residuals reducing overfit of `tau_tilde_g` to `epsilon`. Asymptotic Theorem-3 variance is implemented and matches R `didimputation` (which also omits LOO by default). | `imputation.py` | imputation-validation | Mid | Low | | `TwoWayFixedEffects(vcov_type in {hc2, hc2_bm})` with replicate-weight designs raises `NotImplementedError` (`twfe.py:~233`). The replicate path re-demeans per replicate, which doesn't compose with the full-dummy HC2/HC2-BM build — a correct impl needs per-replicate full-dummy refit. Workaround: `hc1` for replicate-weight CR1. | `twfe.py::fit` | follow-up | Heavy | Low | | TWFE's HC2/HC2-BM inline full-dummy build (`twfe.py:280-315`) duplicates the dummy-construction logic in `DifferenceInDifferences(fixed_effects=...)` (`estimators.py:478-486`). Extract a shared helper, or delegate TWFE's HC2/HC2-BM path to DiD's `fixed_effects=` branch (with TWFE-specific cluster-default threading), to reduce drift risk on FE naming / survey behavior / result-surface conventions. Substantive refactor — touches both estimators. | `twfe.py::fit`, `estimators.py::DifferenceInDifferences.fit` | follow-up | Heavy | Low | -| Decide whether to formally deprecate `CallawaySantAnna.cluster=X` in favor of `survey_design=SurveyDesign(psu=X)` (the bare-cluster path already synthesizes a minimal SurveyDesign). Two equivalent paths = redundant surface. Mirrors the question for ImputationDiD / EfficientDiD / TwoStageDiD. | `staggered.py` | follow-up | Mid | Low | ### Performance diff --git a/docs/methodology/REGISTRY.md b/docs/methodology/REGISTRY.md index cf45ea42..a9d07b7a 100644 --- a/docs/methodology/REGISTRY.md +++ b/docs/methodology/REGISTRY.md @@ -474,6 +474,8 @@ Prior to the bare-`cluster=` wiring fix, `CallawaySantAnna(cluster="X")` was a s The `cluster_name` and `n_clusters` fields on `CallawaySantAnnaResults` report the effective clustering level: `survey_design.psu` (canonical column) when explicit PSU is provided, `self.cluster` when bare cluster synthesizes or injects. +- **Note (API decision — `cluster=` retained, NOT deprecated):** the `cluster=` → `SurveyDesign(psu=cluster)` synthesis above is an internal implementation detail, not a user-facing redundancy to be consolidated away. `cluster=` is the **canonical ergonomic single-level clustering kwarg** and is intentionally retained on `CallawaySantAnna` (and the sibling IF-based estimators `EfficientDiD` / `ImputationDiD` / `TwoStageDiD`): it matches the field's universal convention (R `fixest::feols(..., cluster = ~unit)`, Stata `vce(cluster id)`, statsmodels `cov_type="cluster"`), so users reach for `cluster=` first. `survey_design=SurveyDesign(psu=X, ...)` is the **advanced** entry point (adds strata / FPC / replicate weights / explicit weights); a bare `cluster=` is the shorthand for the common "just cluster at X" case and would be strictly less ergonomic if forced through `survey_design=`. This mirrors the HAD survey-API consolidation, which deprecated only the *redundant* `survey=` / `weights=` entry points in favor of `survey_design=` while deliberately keeping `cluster=`. Decision recorded 2026-07-04: do not deprecate `cluster=`; the former "decide whether to deprecate `CallawaySantAnna.cluster=X`" `TODO.md` row is closed as resolved (keep). + *Estimator equation (as implemented):* Group-time average treatment effect: