feat(v4): EventStudyResults full-vcov + per-row df round-trip (M-092 follow-up)#715
Conversation
…ed/TwoStage VCV persistence, event_study_df channels, PT joint-Wald guards (M-092 follow-up)
Overall assessment: ✅ Looks goodExecutive summary
Methodology
No undocumented estimator, weighting, identification, or variance mismatch found. The new fields copy the registered Gardner-GMM and pooled-regression covariance matrices ( Code QualityNo findings. Changed callers correctly handle the new PerformanceNo findings. Covariance persistence adds only small submatrix copies; the diagnostic eigendecomposition operates on the pre-period block. MaintainabilityNo findings. The producer-specific provenance channels are consistently adapted into the unified per-row representation. Tech Debt
SecurityNo findings. No secrets, unsafe input handling, or security-sensitive changes were identified. Documentation/Tests
Runtime tests could not be independently executed because the review environment lacks |
…t ES vcov/df tests
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall assessment: ✅ Looks goodExecutive summary
Methodology
No undocumented estimator, weighting, variance, SE, or identification mismatch found. See Code QualityNo findings. New inference continues through PerformanceNo findings. Added matrix slicing and diagnostic decomposition operate only on event-study blocks. MaintainabilityNo findings. Producer-specific df channels are normalized consistently into the per-row surface. Tech Debt
SecurityNo findings. No secrets or security-sensitive changes identified. Documentation/TestsNo findings. The prior power-scope inconsistency is corrected in |
Summary
event_study_vcov/event_study_vcov_indexcontainer fields persist it (mirroring the CallawaySantAnna/SunAbraham fields), and the unified surface picks it up with zero adapter change. StackedDiD persists in every inference mode (its reported ES SEs are always the matrix diagonal); TwoStageDiD persists on analytical paths and shipsNoneunder bootstrap (percentile inference, no covariance) and replicate-weight designs (mixed-layout replicate VCV - CS precedent). The reference period and Proposition-5 horizons are never regression columns and are excluded from the index; all-filtered horizons keep their NaN-filled rank-guard rows, consistent with their NaN marginal SEs.EventStudyResults.dfbecomes PER-ROW and joins the pinnedto_dataframe()schema (betweennandis_reference). This is an unreleased-schema change made deliberately beforeaggregate(type="event_study")exposes the surface publicly: three producers genuinely need per-row df (StackedDiDhc2_bmper-event Bell-McCaffrey Satterthwaite df; MultiPeriodDiDhc2_bmper-period BM df -inference_dfstores only the post-average contrast df; LPDiD per-horizon realized cluster df). Scalars broadcast; NaN means normal-theory, undefined, bootstrap-overridden, or unexposed; reference and NaN-p rows are always NaN.event_study_dfprovenance channels record the df each ES row'ssafe_inferenceactually received: CS (scalar; G-1 bare-cluster / conservative min-across-horizons effective df on explicit-survey fits -df_inferenceand its narrow HonestDiD contract untouched), MPD (per-period dict), StackedDiD (per-event dict), TwoStageDiD (scalar survey df), LPDiD (per-horizon dict). All channels clear under bootstrap; the adapter'sdf_inferencefallback is gated onbootstrap_results is Noneso a bootstrap fit can never surface a df its stored p-values never used.inconclusiverather than publishing a finite verdict through inference the estimator refused to produce; (2)hc2_bmfits skip the generic chi-square Wald (it would discard the CR2/BM small-sample correction; AHT/HTZ tracked in DEFERRED.md) and run Bonferroni over the BM-adjusted per-row p-values; (3) rank/PSD guard - a cluster-sandwich covariance is singular whenever tested leads approach the cluster count, and an unguarded solve produces a negative "Wald statistic" reported as p=1.0; the guard requires a finite full-rank PSD block and a non-negative statistic, else falls back to Bonferroni.Methodology references (required if estimator / math changes)
**Note:**entries under StackedDiD and TwoStageDiD document the exposure semantics.hc2_bmparallel-trends policy (Bonferroni over BM-adjusted per-row p-values instead of a chi-square joint Wald that would discard the CR2 small-sample correction) is documented in REPORTING.md "hc2_bm parallel-trends policy"; the proper multi-constraint AHT/HTZ CR2 test is tracked in DEFERRED.md (needs clubSandwich parity).Validation
tests/test_event_study_surface.py(per-row df container tests, Stacked/TwoStage vcov alignment incl. Prop-5 exclusion, per-producer df threading incl. the CS bootstrap leak pin, ALL_PRODUCERS df invariants),tests/test_two_stage.py(vcov persistence mode gating),tests/test_diagnostic_report.py(joint-Wald upgrade, hc2_bm fail-closed/routing, NaN-p provenance guard, organic singular-VCV downgrades for both estimators, non-negative-statistic contract).sqrt(diag(vcov))vs native SEs bit-exact at rtol 1e-14 on fixed-seed panels; 1,776 tests green across the 14 targeted suites; Sphinx -W clean; mypy zero errors.Security / privacy