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
Audit round 2: 3 deeper semantic / UX bugs found and fixed
Second-pass audit of today's work — focused on algorithmic semantics
rather than mechanics. Three genuine issues, all now fixed with
regression tests.
1. **aggte(type='dynamic').estimate averaged pre + post event times.**
R `did::aggte(type='dynamic')` reports the overall ATT as a simple
average of *post-treatment* event-study estimates (e ≥ 0). Pre-
treatment cells are placebos — averaging them into the headline
number pollutes the causal summary with pre-trend signal.
On the canonical demo DGP the bug produced overall = 0.7590
(diluted by 6 pre-treatment rows with mean-zero placebos); the
correct value is 1.4052 — off by nearly a factor of 2.
Fixed in `_aggregate` computation of `w_overall`: for dynamic,
restrict the averaging weights to cells where the label (event
time) is ≥ 0. Group and calendar aggregations are unchanged:
by construction their weight matrices already pick only post-
treatment (g, t) cells.
Also switched the bootstrap-off fallback SE formula from
`sqrt(mean(se²))` to `sqrt(sum(w² · se²))` so it respects the
same weight vector and remains comparable with the bootstrap
path.
Docstring updated to explicitly state the four overall conventions.
2. **cs_report() crashed with KeyError: 'group' on non-CS results.**
Before: passing a Sun-Abraham / BJS / dCDH result (which carry
`relative_time` but not `group` / `time`) raised a cryptic
pandas KeyError deep inside aggte's weight builder.
Now: detects the missing CS schema up-front and raises a
ValueError pointing the user to honest_did() for those result
types.
3. **cs_report(pre_fitted_cs, estimator='reg', …) silently ignored
the estimator override.** A user reading the call site would
reasonably believe the estimator was applied; in fact the pre-
fit's settings were used verbatim. Now emits a UserWarning that
lists every shadowed argument and tells the caller to pass raw
data instead if they want to re-estimate.
Regression tests (+4 new cases):
- `test_dynamic_overall_averages_post_event_only`
- `test_cs_report_rejects_non_cs_result`
- `test_cs_report_warns_on_shadowed_args`
- `test_cs_report_pre_fitted_without_shadowed_args_is_silent`
Full DiD suite: 169/169 (was 165).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
0 commit comments