Skip to content

Commit a66b9ad

Browse files
igerberclaude
andcommitted
twfe: scope coefficients-dict broadening to HC2/HC2-BM only
CI review (R7) flagged a P2 scope creep in the R1 coefficients-dict fix: I built `_twfe_var_names` on BOTH the full-dummy and within- transform branches, which silently broadened `result.coefficients` on HC1/classical/Conley paths from `{"ATT": att}` to `{"const": c, "ATT": att, ...covariates}`. That's a user-visible API change on unchanged TWFE paths that wasn't documented in CHANGELOG/REGISTRY or regression-tested. Per the reviewer's recommendation, restoring the historical `{"ATT": att}` contract on within-transform paths by setting `_twfe_var_names = None` on the else branch (the fallback at the DiDResults construction site handles None via the existing `{"ATT": float(att)}` literal). Only the HC2/HC2-BM full-dummy path now broadens the dict — which is what the REGISTRY/CHANGELOG surface-change disclosure documents, and what the alignment-invariant test and full-surface regression test pin. Verified end-to-end: hc1/classical → `{'ATT'}`; hc2/hc2_bm → `{'const', 'ATT', '_fe_unit_*', '_fe_time_*'}`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 25c364f commit a66b9ad

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

diff_diff/twfe.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,9 +359,13 @@ def fit( # type: ignore[override]
359359
X_list.append(data_demeaned[f"{cov}_demeaned"].values)
360360
X = np.column_stack([np.ones(len(y))] + X_list)
361361
df_adjustment = n_units + n_times - 2
362-
# Within-transform path: FE dummies are NOT in X (they're absorbed
363-
# by demeaning). var_names cover the visible columns only.
364-
_twfe_var_names = ["const", "ATT"] + list(covariates or [])
362+
# Within-transform path: preserve the historical
363+
# `{"ATT": att}` user-facing `result.coefficients` contract.
364+
# Broadening this dict here would silently change the
365+
# API surface on HC1 / classical / Conley fits — the
366+
# full-dummy `_twfe_var_names` exposure is scoped to the
367+
# HC2 / HC2-BM paths only (the documented surface change).
368+
_twfe_var_names = None
365369

366370
# ATT is the coefficient on treatment_post (index 1) on both branches.
367371
att_idx = 1

0 commit comments

Comments
 (0)