CS positional base period + absorbed-FE full-K SE parity vs R#621
Conversation
PR Review ReportOverall Assessment:
|
29f1538 to
51bde09
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review ReportOverall Assessment:
|
51bde09 to
9c952f7
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review ReportOverall Assessment:
|
9c952f7 to
47593fa
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review ReportOverall Assessment: ⛔ BlockerExecutive Summary
MethodologyFinding: Bootstrap event-study inference omits universal zero reference cells
Finding:
|
47593fa to
54be4fd
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review ReportOverall Assessment: ⛔ BlockerExecutive Summary
MethodologyFinding: Universal reference cells can receive the wrong cohort weight after skipped cells
Informational: Absorbed-FE full-K scaling is documented and scoped
Code QualityNo additional P0/P1 code-quality findings beyond the reference-weight bug. PerformanceNo findings. The new reference materialization is cohort-linear. MaintainabilityFinding: Event-study weighting semantics remain split across analytical/bootstrap paths
Tech DebtNo blocker. The clustered absorbed-FE non-nested CR1 limitation is tracked in SecurityNo findings. I did not see credential handling, network I/O, subprocess execution, or secrets introduced. Documentation/TestsFinding: Missing regression for unbalanced universal reference weights
Path to Approval
|
54be4fd to
73a9c53
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review ReportOverall Assessment: ⛔ BlockerExecutive Summary
MethodologyFinding: Universal reference rows still use cell-derived weight metadata
Informational: Positional base-period selection matches the documented contract
Informational: Absorbed-FE full-K scaling is documented and scoped
Code QualityNo P0/P1 code-quality findings beyond the reference-weight correctness bug. PerformanceNo findings. The new reference materialization remains cohort-linear. MaintainabilityFinding: Event-study bucket construction remains duplicated, but tracked
Tech DebtNo untracked blocker. The clustered absorbed-FE non-nested CR1 limitation is tracked in SecurityNo findings. The diff does not introduce credential handling, network I/O, subprocess execution, or secrets. Documentation/TestsFinding: Missing partial-mass unbalanced reference regression
Path to Approval
|
73a9c53 to
3b0d8de
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review ReportOverall Assessment:
|
3b0d8de to
8ca08e2
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment: ✅ Looks goodExecutive Summary
MethodologyFinding: Universal reference-only cohort handling is resolved
Finding: Documented deviations are properly mitigated
Code QualityNo P0/P1 findings. The new PerformanceNo findings. Reference materialization is cohort-linear; absorbed-FE SE parity is a scalar vcov rescale. MaintainabilityFinding: Event-study bucket logic remains duplicated but tracked
Tech DebtNo untracked blocking tech debt found. The new deferred items in SecurityNo findings in the changed files. No secrets or credential-like material observed. Documentation/TestsFinding: Exact reference-only bootstrap regression is still worth adding
Validation note: I attempted targeted pytest execution, but the environment lacks |
8ca08e2 to
5d00187
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment: ✅ Looks goodExecutive Summary
MethodologyNo P0/P1 findings. Finding: Documented deviations are not blockers
Code QualityNo findings. The new PerformanceNo findings requiring action. The bootstrap path remains draw-block chunked and memory-bounded, but the removed fused tiled-GEMM code is a performance rollback, not a methodology defect. MaintainabilityNo blocking findings. Event-study bucket construction remains duplicated between analytic and bootstrap paths, but this is tracked in Tech DebtNo untracked blocking tech debt found. SecurityNo findings. No credential-like material observed in the changed files. Documentation/TestsFinding: Direct bootstrap regression for all-skipped reference cohort remains useful
Validation note: attempted targeted pytest execution, but |
5d00187 to
40ddd8e
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment: ✅ Looks goodExecutive Summary
MethodologyFinding: Documented CS unbalanced event-study weighting deviation
Finding: Documented absorbed-FE clustered non-nested CR1 deviation
Code QualityNo findings. I did not find new inline inference anti-patterns or partial NaN guards in the affected paths. PerformanceNo blocking findings. The draw-block bootstrap path remains memory-bounded; removal of the fused tiled-GEMM machinery is a performance tradeoff, not a methodology defect. MaintainabilityFinding: Event-study bucket construction duplication is tracked
Tech DebtNo untracked blocking tech debt found. SecurityNo findings. I did not observe credential-like material in the changed files. Documentation/TestsFinding:
|
…l-K SE parity vs R
Two standard-error parity fixes vs canonical R (SE-audit D3, D4).
D3 - CallawaySantAnna base period is now selected positionally (nearest observed
period) via shared `_select_base_period` / `_valid_periods_for_group` helpers used
across every estimation path (panel fast/vectorized/covariate-reg, repeated
cross-sections, and the universal filters), matching R `did::att_gt` on gapped
(non-consecutive) grids. The pre/post split is corrected to `t < g` (independent of
anticipation; only the post/universal base uses anticipation), verified against a
deparse of `did` 2.5.1 `compute.att_gt`. Consecutive grids are byte-identical to the
old rule; gapped panels now reproduce every R cell (fewer_periods {1,3,4,6},
non_consecutive {1,2,5,7}). For `base_period="universal"`, each cohort's positional
base is materialized as a zero reference cell (att=0, se=NaN, zero influence
function) in group_time_effects / to_dataframe("group_time") at its positional base
event time (`e = base - g`, which can be -2, -3, ... on gapped grids), matching R's
att_gt table AND aggte(type="dynamic") uniformly across the analytical, multiplier-
bootstrap, and balance_e paths -- including the overlapping-reference case where a
cohort's zero base dilutes another cohort's estimated pre-trend at the same event
time (analytical and bootstrap verified vs did 2.5.1 to ~1e-5). The group/simple
aggregations use post-treatment cells only and exclude the reference.
D4 - absorbed-FE (`absorb=`) non-clustered classical/hc1 standard errors now use the
full-K finite-sample scale (`linalg._absorbed_fe_vcov_scale`, a single scalar rescale
of the k_visible vcov; fail-closed to NaN inference when the full-K residual dof is
non-positive), matching `fixest::feols(vcov="iid"/"hetero")` and the explicit
full-dummy oracle. Applies to TwoWayFixedEffects(classical),
DifferenceInDifferences(absorb=), and MultiPeriodDiD(absorb=). Clustered SEs are
unchanged (gated on cluster_ids is None): the k_visible CR1 scale matches fixest for
FE nested in the cluster; non-nested absorbed FE (e.g. time FE with unit clustering)
are a small documented deviation tracked in TODO.md. hc2/hc2_bm (Satterthwaite DOF),
survey vcov, full-dummy fits, and SunAbraham hc1 (auto-clusters) are unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0178r8ZK6VRiXbaBiknrWjQB
40ddd8e to
9b110d3
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment: ✅ Looks goodExecutive Summary
MethodologyFinding: Documented CS unbalanced event-study weighting deviation
Finding: Documented absorbed-FE clustered non-nested CR1 deviation
Code QualityNo findings. I did not find new inline inference computation or partial NaN-guard anti-patterns in the modified paths. PerformanceNo findings. The added base-period helper and scalar absorbed-FE vcov rescale are not performance concerns. MaintainabilityFinding: Event-study bucket construction duplication is tracked
Tech DebtNo untracked blocking tech debt found. SecurityNo findings. Secret-pattern scan only hit existing test fixtures ( Documentation/TestsNo PR findings. The new tests cover positional base selection, gapped panel/RCS paths, universal reference materialization, bootstrap all-skipped cohort handling, and absorbed-FE full-dummy parity. Validation note: targeted tests could not be run here because |
Summary
CallawaySantAnnapositional base period (Rdid::att_gtparity on gapped grids). Base periods are selected positionally (nearest observed period) via shared_select_base_period/_valid_periods_for_grouphelpers used across every estimation path (panel fast/vectorized/covariate-reg, repeated cross-sections, universal filters). The pre/post split is corrected tot < g(independent of anticipation; only the post/universal base uses anticipation), verified against a deparse ofdid2.5.1compute.att_gt. Consecutive grids are byte-identical to the old rule; gapped panels (fewer_periods{1,3,4,6},non_consecutive{1,2,5,7}) now reproduce every R cell instead of NaN-ing cells whose calendar base was unobserved, andbase_period="universal"no longer materializes the positional base as a fake zero cell. Aggregated event-study / group SEs on gapped panels are corrected accordingly.absorb=) non-clustered classical/hc1 SE full-K scale (fixestparity). A single scalar vcov rescale (linalg._absorbed_fe_vcov_scale, fail-closed to NaN inference when the full-K residual dof is non-positive) aligns the SE'skwithK_full = k_visible + df_adjustment, matchingfixest::feols(vcov="iid"/"hetero")and the explicit full-dummy (fixed_effects=) oracle. Previously these SEs sat ~6.5% below fixest even though the reported t-dfalready usedK_full(an internal inconsistency). Applies toTwoWayFixedEffects(vcov_type="classical"),DifferenceInDifferences(absorb=...),MultiPeriodDiD(absorb=...).Methodology references (required if estimator / math changes)
absorb=) finite-sample SE forDifferenceInDifferences/TwoWayFixedEffects/MultiPeriodDiD.did::att_gt(deparse ofdid2.5.1compute.att_gt);fixest::feolssscdegrees-of-freedom convention. Seedocs/methodology/REGISTRY.mdbase-period and within-transform sections.absorb=["unit","time"], cluster="unit", where the time FE are non-nested) still usesk_visible— fixest counts the non-nested FE in the CR1 denominator. This is a small, documented deviation left out of this D4 (non-clustered) scope and tracked inTODO.md; the nested case (unit FE with unit clustering) already matches fixest. The SunAbraham / Wooldridgehc1deviations documented in REGISTRY are unaffected.Validation
tests/test_csdid_ported.py(newTestCSDIDPositionalBasePeriod— helper unit cases incl. ananticipation=2gapped casebase(6)==5, universal, covariate-reg, and repeated-cross-section coverage; tightened thefewer_periods/non_consecutivegapped goldens fromabs<0.05/0.5to1e-3…1e-7with SE assertions),tests/test_estimators_vcov_type.py(newTestAbsorbedFEFullKParity— DiD/MPD/TWFE absorb==full-dummy oracle for classical+hc1, cluster/hc2_bm/SunAbraham-hc1 guards, and a saturated full-K NaN fail-closed case),tests/test_staggered.py,tests/test_methodology_callaway.py.did2.5.1 (per-cell att+se on the gapped goldens) andfixest(iid0.202158/ hetero0.432290— the absorb path matches the full-dummy oracle and fixest exactly).Security / privacy
🤖 Generated with Claude Code
https://claude.ai/code/session_0178r8ZK6VRiXbaBiknrWjQB