fix(imputation): FE-span snap guard on the pretrends lead model#650
fix(imputation): FE-span snap guard on the pretrends lead model#650igerber wants to merge 3 commits into
Conversation
Overall Assessment✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology
Code QualityNo findings. PerformanceNo findings. The added LSMR confirmation is behind the existing two-stage snap screen, so it is scoped to near-absorbed candidate regressors rather than every column unconditionally; see MaintainabilityNo findings. Tech DebtNo findings. The relevant deferred TODO row has been removed after implementation; remaining TODO entries do not track this specific gap. See SecurityNo findings. Documentation/Tests
|
9664389 to
22a2b43
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
Methodology
Code QualityNo findings. The changed code uses the shared utility rather than adding inline collinearity or inference logic. PerformanceNo findings. The added LSMR confirmation is gated behind the existing snap screen in MaintainabilityNo findings. The change reuses the common FE-span utility and passes display labels for lead warnings. Tech DebtNo findings. The deferred TODO row for adopting SecurityNo findings. Documentation/Tests
Validation not run: |
The Test-1 lead indicators + covariates now route through snap_absorbed_regressors after the within-transform (the same two-stage snap + LSMR confirmation the absorb= estimators use). A lead whose calendar period contains only its cohort's rows on Omega_0 collapses to a calendar-time dummy in the span of the absorbed time FE; it now snaps to exact zero — deterministic NaN coefficient + cause-specific warning naming lead[h] — instead of relying on the raw rank check alone, which the documented truncated-MAP-iterate exposure can defeat in slow-convergence regimes. Identified leads unchanged (full suites pass unmodified); behavioral tests lock the spanned-NaN contract and the no-op case. REGISTRY ImputationDiD note added. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…pecific) CI surfaced that WHICH redundant lead the rank handler drops after the snap (the leads-sum dummy trap column) is pivoted-QR/BLAS-order dependent: -4 on macOS/Accelerate, -3 on linux-arm py3.11, -6 on the pure-python CI backend. The snap contract itself (lead[-2] NaN + cause warning) is deterministic and unchanged; the sibling-finiteness assert now checks the count (exactly one trap drop) and survivor health instead of hardcoded horizons. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…lead (review P3) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
22a2b43 to
7763f71
Compare
|
🔁 AI review rerun (requested by @igerber) Head SHA: Overall Assessment✅ Looks good. No unmitigated P0/P1 findings. Executive Summary
MethodologyNo P0/P1 findings. Severity: P3 informational Code QualityNo findings. The PR reuses PerformanceNo findings. The added LSMR confirmation is behind the shared MaintainabilityNo findings. The guard is applied at both call sites of Tech DebtNo findings. The TODO item for adopting SecurityNo findings. Documentation/TestsSeverity: P3 Prior P3 resolved: Validation not run: |
Summary
snap_absorbed_regressors(the two-stage FE-span snap + LSMR confirmation theabsorb=estimators use) onImputationDiD._compute_lead_coefficients— the change the demean-modernization PR deliberately deferred (TODO row). Lead indicators are the most plausible FE-spanned regressors: when a lead's calendar period contains only its cohort's rows on the untreated sample (e.g., never-treated units unobserved there), the lead collapses to a calendar-time dummy in the span of the absorbed time FE.lead[h], instead of relying on the raw rank check alone — which the documented truncated-MAP-iterate exposure can defeat in slow-convergence regimes (the junk direction then perturbs the identified lead coefficients; see the REGISTRY "Absorbed Fixed Effects" contract). Identified leads are untouched: the snap is a no-op there and the full imputation suites (incl. the R-parity anchors and the replicate/bit-equality grids) pass unmodified — 198 tests.TestLeadSnapAbsorbed: (a) a spanned-lead design (never-treated span ends before a cohort pre-period) locks NaN + the cause-specific warning + finite untouched siblings; (b) a balanced design locks the no-op (no warning, leads finite). REGISTRY ImputationDiD note documents the guard.Methodology references (required if estimator / math changes)
Validation
tests/test_imputation.py::TestLeadSnapAbsorbed(2 behavioral tests);tests/test_imputation.py+tests/test_methodology_imputation.py+tests/test_replicate_weight_expansion.pyall pass (198).Security / privacy
Generated with Claude Code