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
Tighten SyntheticDiD set_params and TWFE Conley + wild_bootstrap guards
Closes two no-silent-failure gaps surfaced after the initial Phase 1 commit:
1. SyntheticDiD.set_params() now mirrors __init__'s Conley rejection contract.
The constructor correctly raises TypeError on vcov_type="conley" /
conley_*=... but set_params() previously only checked hasattr(self, key)
and silently accepted those kwargs because SyntheticDiD inherits the
conley_* attributes from DifferenceInDifferences. A user calling
est.set_params(vcov_type="conley", conley_cutoff_km=100.0) followed by
est.fit(...) would have gotten the bootstrap/jackknife/placebo variance
silently with no Conley computation -- forbidden by feedback_no_silent_failures.
The new set_params() rejects non-None vcov_type and any non-None conley_*
kwarg with TypeError before mutation; None values for these keys are
passthrough no-ops so get_params() -> set_params() round-trips cleanly.
SyntheticDiD.get_params() now surfaces the inherited conley_* keys with
None values for sklearn-style API consistency.
2. TwoWayFixedEffects(vcov_type="conley", inference="wild_bootstrap") now
raises NotImplementedError. Conley analytical spatial-HAC and wild cluster
bootstrap are different inference paths; combining them would route the
bootstrap branch with cluster_ids=None (TWFE auto-cluster is disabled
under Conley) and fail with a non-targeted error inside wild_bootstrap_se.
Use inference='analytical' for Conley spatial HAC, or vcov_type='hc1'
with inference='wild_bootstrap'.
3. DifferenceInDifferences and MultiPeriodDiD class docstrings now list
vcov_type="conley" in the enum and document the four conley_* params
(previously the Conley path was documented in REGISTRY/CHANGELOG/llms.txt
but the in-code class docs still listed only {classical, hc1, hc2, hc2_bm}).
4. New tests:
- SyntheticDiD().set_params(vcov_type="conley") raises TypeError + state
unchanged
- SyntheticDiD().set_params(conley_cutoff_km=100.0) raises + state unchanged
- SyntheticDiD().get_params() includes conley_* keys with None values;
round-trip set_params(**get_params()) is a no-op
- TwoWayFixedEffects(vcov_type="conley", inference="wild_bootstrap") raises
5. TODO.md entries added for deferred follow-ups: callable-conley_metric
shape/finiteness/symmetry validation, common Conley estimator-validator
helper extraction, and a stronger TWFE Conley FWL invariance test that
actually compares TWFE-within Conley to a full-dummy FE design (the
current test only asserts finite SEs).
74 Conley tests pass (70 prior + 4 new); 261 tests pass on the targeted
regression surface (test_conley_vcov, test_estimators_vcov_type, test_linalg,
test_linalg_hc2_bm).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: TODO.md
+3Lines changed: 3 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -117,6 +117,9 @@ Deferred items from PR reviews that were not addressed before merge.
117
117
| Conley + survey weights / `survey_design`. Score-reweighted meat `s_i = w_i · X_i · ε_i` is mechanical, but PSU clustering interaction with the spatial kernel and replicate-weights variance under spatial correlation are non-trivial (Bertanha-Imbens 2014 covers cluster-sample but not the explicit Conley case). Phase 5 of the spillover-conley initiative; paper review prerequisite. Currently raises `NotImplementedError`. |`linalg.py::_validate_vcov_args`, `twfe.py`, `estimators.py`| Phase 5 (spillover-conley) | Medium |
118
118
| Conley + `absorb=` (arbitrary FE projection beyond TWFE's two-FE within-transformation). FWL composability is proven analytically for TWFE's fixed two-FE design but not formally verified for arbitrary `absorb` dimensions; conservatively rejected at fit-time with a redirect to `fixed_effects=` dummies. Lift after empirical verification on multi-FE within-transformations. |`estimators.py::DifferenceInDifferences.fit`, `MultiPeriodDiD.fit`| follow-up (spillover-conley) | Low |
119
119
|`SyntheticDiD(vcov_type="conley")` support. Currently raises `TypeError` at `__init__` because SyntheticDiD uses `variance_method ∈ {bootstrap, jackknife, placebo}` rather than the analytical sandwich that Conley plugs into. Wiring would require either reimplementing an analytical sandwich path for SyntheticDiD or designing a spatial-block bootstrap (new methodology, Politis-Romano 1994 territory). |`synthetic_did.py::SyntheticDiD`| follow-up (spillover-conley) | Low |
120
+
| Validate user-supplied callable `conley_metric` for shape `(n, n)`, finiteness, non-negativity, and symmetry. Currently `np.asarray(metric(coords, coords))` is accepted unchecked; a malformed callable produces opaque matmul errors and a non-symmetric distance matrix produces a non-symmetric vcov. CI reviewer flagged as P2 M3 in PR #(spillover-conley). |`diff_diff/conley.py::_pairwise_distance_matrix`, `_compute_conley_vcov`| follow-up (spillover-conley) | Low |
121
+
| Extract common Conley estimator-level validation helper. Today `cluster=`, `survey_design=`, `conley_coords=`, and `conley_cutoff_km=` checks are duplicated across `DifferenceInDifferences.fit` (estimators.py:~370-400), `MultiPeriodDiD.fit` (estimators.py:~1395-1455), and `TwoWayFixedEffects.fit` (twfe.py:~165-205). A future Conley-feature change risks updating one estimator but not the others. CI reviewer flagged as P2 MT1. |`diff_diff/estimators.py`, `diff_diff/twfe.py`| follow-up (spillover-conley) | Low |
122
+
| Strengthen `tests/test_conley_vcov.py::TestConleyTWFE::test_twfe_conley_FWL_invariance` to actually verify FWL equivalence between TWFE-within Conley and a full-dummy-FE design (build the dummy regression explicitly and compare the ATT coefficient + Conley SE). The current test only asserts both fits produce finite SEs — the name overstates the assertion. CI reviewer flagged as P2 DT3. |`tests/test_conley_vcov.py`| follow-up (spillover-conley) | Low |
0 commit comments