feat(provenance): per-row event-study df threading (M-092 completion) + ContinuousDiD unit-level metadata - #803
Merged
Merged
Conversation
…uousDiD unit-level metadata + df_survey contract - Thread event_study_df into the unified container's per-row df column for EfficientDiD, ImputationDiD, ContinuousDiD, HAD (finite on analytical survey fits; None on non-survey/bootstrapped/no-surface fits and for the replicate-undefined 0 sentinel; ImputationDiD replay carriers use the level-matched replay df). - ContinuousDiD survey_metadata recomputed unit-level on every arm (bootstrap + degenerate no-post-cells arms included). - Document the df_survey scalar two-channel contract (persists beside percentile inference; HonestDiD consumer channel) with a cross-estimator pin; REGISTRY + v4 ledger note prose updated; TODO rows for granularity/scalar/per-row-df closed.
Overall assessment: ✅ Looks goodExecutive summary
Methodology
Code QualityNo findings. Performance
MaintainabilityNo findings. Tech DebtNo untracked correctness debt introduced. SecurityNo findings or apparent secrets. Documentation/Tests
|
…it; docs: event_study_df in llms-full tables CI review round 1: the fit-level metadata hoist, _compute_analytical_se, and _run_bootstrap each collapsed the panel design to unit level (replicate designs copied the unit-by-replicate matrix twice) - build once and thread as pre_unit_resolved (byte-identical outputs, verified against the captured baseline). Add event_study_df rows to the shared staggered and ContinuousDiD llms-full.txt field tables.
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall assessment: ✅ Looks goodExecutive summary
Methodology
Code QualityNo findings. PerformanceNo findings. The prior duplicate-collapse issue is resolved by reusing MaintainabilityNo findings. Tech Debt
SecurityNo findings or apparent secrets. Documentation/TestsNo findings. All four new public fields are now covered in the LLM guide and autosummary stubs. The added tests cover analytical, bootstrap, replicate, undefined-df, absent-surface, and empty-post-cell paths. |
This was referenced Aug 30, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
EfficientDiD,ImputationDiD,ContinuousDiD,HeterogeneousAdoptionDiD) gain a results-levelevent_study_dfscalar (appended after each class's final field; positional__init__indexes unchanged) threaded into the unified container's per-rowdfcolumn, previously all-NaN even on survey fits whose p-values used a finite survey df. Finite on analytical survey fits (ImputationDiD threads the FINAL replicate-override df, with the level-matched replay value on replicate replays and lead rows included; EfficientDiD the post-overall snapshot; HAD the unit-level design df via_from_had, plusto_dict());None— never the replicate-undefined0sentinel — on non-survey fits, under bootstrap (percentile inference used no df, per the shippedstaggered.py/two_stage.pyproducer convention), and when no event-study surface was built. Inference values byte-identical everywhere.survey_metadataunified at unit level on every inference arm — the bootstrap and degenerate no-post-cells arms previously kept the obs-level resolve, sosum_weights/effective_n/n_psu(anddf_surveyon implicit-PSU designs) diverged from the analytic arm by panel length; the unit-level recompute is now hoisted above the branch split (metadata provenance only; estimates/inference unchanged).df_surveyscalar contract recorded as design — the container-level scalar (the fit's resolved scalar inference df) deliberately persists on bootstrapped fit-time and replayed surfaces (CS, DMLDiD, EfficientDiD identically): it is the consumer channel HonestDiD's container branches read asdf=for their critical values, while the per-rowdfcolumn is the inference-provenance channel percentile bootstrap clears (M-027). No behavior change; REGISTRY Note + cross-estimator parity pins.docs/v4-deprecations.yamlM-092/M-093 note PROSE amended (qualifiers resolved; no status/target/lifecycle change); committed autosummary stubs regenerated for the four classes;llms-full.txtHAD field table extended (CI-enforced); TODO rows 40/41/45 removed and the#variance-PR-Crow's ImputationDiD clause narrowed to the non-survey per-lead remainder.Methodology references (required if estimator / math changes)
Validation
TestPerRowDfProvenanceCompletionintests/test_aggregate_contract.py(15 pins: per-row df ==survey_metadata.df_surveywith per-row p-value reproduction oracles; replicate arms incl. the healthy/dropped df contrast and the level-matchedcohort_zeroreplay; the replicate-undefined 0-sentinel-is-None attribute pins; bootstrap fit-time clearing + replay NaN + persisting scalar for CS/EfficientDiD; ImputationDiD bootstrapped replay still fails closed; absent-ES-surface gates; HAD survey/non-survey +to_dict); a DMLDiD replay two-channel pin intests/test_survey_dml.py; Row A flips + analytic-vs-bootstrap full-field metadata parity (incl. implicit-PSU df) + a survey empty-post-cells arm intests/test_survey_metadata_raw_scale.py.Security / privacy