Commit 086e597
Audit round 3: aggte() cryptic KeyError on non-CS input
Third-round audit focused on boundary conditions, data-flow edge
cases, and cross-module API consistency. Only one genuine new
issue surfaced; everything else (Mammen math, RCS IF normalisation,
breakdown_m formula, ggdid ordering, save_to path handling, BJS
Optional import) verified correct on close re-reading.
Issue: `aggte(sa_result)` crashed with `KeyError: 'group'` deep
inside `_weights_dynamic`, for the same reason as the round-2
`cs_report(sa_result)` bug — Sun-Abraham / BJS / dCDH event-study
frames carry `relative_time` but no `group` / `time` columns.
Round 2 fixed the cs_report entry point but aggte is also public
API, so the same error can be hit directly:
sa = sp.sun_abraham(...)
sp.aggte(sa, type='dynamic') # <-- cryptic KeyError
Fix: identical upfront guard in `aggte()` — require the CS detail
schema {group, time, att, se, relative_time} and raise a clear
ValueError pointing to honest_did() for non-CS event studies.
Test: `tests/test_aggte.py::test_aggte_rejects_non_cs_result`.
Full DiD suite: 170/170 (was 169).
Items verified clean on this pass (kept notes in case a future
refactor touches them):
* Mammen bootstrap: E[V]=0, Var(V)=1 confirmed algebraically;
IQR/iqr_norm equals σ for normal bootstrap draws.
* SE scaling: psi = inf @ W.T, boot = V @ centered / n, SE from
IQR gives the correct √(Var(ψ)/n).
* RCS IF: 4-cell ratio estimator IF is proportional to
1{i ∈ cell}(Y_i − Ȳ_cell)/p_cell — correct for sample means.
* breakdown_m: n_drift = max(e+1, 1) matches CS2021 smoothness
bias bound M · (e + 1) for post-treatment e ≥ 0.
* aggte-with-anticipation: `_get_gt_pairs` correctly skips cohorts
lacking a valid pre-period; downstream `_cohort_weight_series`
only uses cohorts actually present in detail, so the weights
renormalise rather than double-count.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent e5d68ec commit 086e597
3 files changed
Lines changed: 33 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | | - | |
| 19 | + | |
| 20 | + | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
141 | 152 | | |
142 | 153 | | |
143 | 154 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
206 | 206 | | |
207 | 207 | | |
208 | 208 | | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
0 commit comments