Add Conley (1999) spatial HAC SE on DiD/TWFE/MultiPeriodDiD (Phase 1 of spillover-conley)#411
Add Conley (1999) spatial HAC SE on DiD/TWFE/MultiPeriodDiD (Phase 1 of spillover-conley)#411
Conversation
PR Review: Conley Spatial HACOverall Assessment: Executive Summary
MethodologyP1 — Panel estimators silently use cross-sectional Conley over all unit-time rowsLocations: Impact: The registry and paper review define Phase 1 as cross-sectional spatial HAC, with the time dimension deferred to Phase 2. The implementation nevertheless passes every long-panel row into Concrete fix: Either reject Code QualityP1 —
|
…ring Address CI Codex review of PR #411 (P1#1 + P1#2): P1#1 — Panel estimators with vcov_type="conley" silently produced wrong SE because cross-sectional Conley over (unit, time) rows treated same- unit cross-time pairs as d_ij=0 -> K=1, mishandling the space-time HAC. Phase 1 supports cross-sectional Conley only; reject panel fits at fit-time on DifferenceInDifferences, TwoWayFixedEffects, and MultiPeriodDiD with NotImplementedError. Practitioners pre-collapse to per-unit first-differences and call compute_robust_vcov directly. Phase 2 will add the space-time product kernel (Driscoll-Kraay) and lift the rejection. Granular Conley-arg validation collapsed into the single unconditional reject (cluster/absorb/coords/cutoff combinations all hit the same path). P1#2 — conley_metric was dropped at the result boundary and _format_vcov_label hard-coded "km" for the cutoff label even when metric was "euclidean". With panels rejected, the conley_cutoff_km / conley_kernel fields on DiDResults / MultiPeriodDiDResults are now unreachable; remove the dead fields, the dead arg passes from estimators.py / twfe.py, and the dead "conley" branch in _format_vcov_label. Tests added: TWFE / DiD / MPD panel-rejection regressions, including a repeated-coords-across-periods regression per the CI reviewer's recommendation. 70 Conley tests + 401 targeted regression tests pass. REGISTRY / CHANGELOG / llms.txt / README / TODO updated to reflect that the only supported Phase 1 Conley path is direct LinearRegression / compute_robust_vcov on a single-period design. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HACOverall Assessment: Executive Summary
MethodologyP1 — Panel estimators still silently use cross-sectional Conley over long-panel rowsLocations: Impact: Concrete fix: Either reject Code QualityP1 —
|
…ring Address CI Codex review of PR #411 (P1#1 + P1#2): P1#1 — Panel estimators with vcov_type="conley" silently produced wrong SE because cross-sectional Conley over (unit, time) rows treated same- unit cross-time pairs as d_ij=0 -> K=1, mishandling the space-time HAC. Phase 1 supports cross-sectional Conley only; reject panel fits at fit-time on DifferenceInDifferences, TwoWayFixedEffects, and MultiPeriodDiD with NotImplementedError. Practitioners pre-collapse to per-unit first-differences and call compute_robust_vcov directly. Phase 2 will add the space-time product kernel (Driscoll-Kraay) and lift the rejection. Granular Conley-arg validation collapsed into the single unconditional reject (cluster/absorb/coords/cutoff combinations all hit the same path). P1#2 — conley_metric was dropped at the result boundary and _format_vcov_label hard-coded "km" for the cutoff label even when metric was "euclidean". With panels rejected, the conley_cutoff_km / conley_kernel fields on DiDResults / MultiPeriodDiDResults are now unreachable; remove the dead fields, the dead arg passes from estimators.py / twfe.py, and the dead "conley" branch in _format_vcov_label. Tests added: TWFE / DiD / MPD panel-rejection regressions, including a repeated-coords-across-periods regression per the CI reviewer's recommendation. 70 Conley tests + 401 targeted regression tests pass. REGISTRY / CHANGELOG / llms.txt / README / TODO updated to reflect that the only supported Phase 1 Conley path is direct LinearRegression / compute_robust_vcov on a single-period design. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HACOverall Assessment: Executive Summary
MethodologyP1 —
|
Address CI Codex review of PR #411 (P1 + P2): P1 — LinearRegression(vcov_type="conley", survey_design=...) silently bypassed the documented Conley+survey rejection. The downstream _validate_vcov_args (inside compute_robust_vcov) rejects this combination, but LinearRegression.fit() sets return_vcov=False on the solve_ols call when survey vcov is needed (so the linalg validator never runs), and the survey vcov path then overwrites vcov_ with a non-Conley variance under a Conley request. Front-door the rejection at LinearRegression entry so the contract is enforced uniformly. New regression test test_linear_regression_conley_with_survey_design_raises locks the new guard with a make_pweight_design fixture. P2 — DifferenceInDifferences and MultiPeriodDiD docstrings still listed "conley" as a vcov_type option and described the conley_* kwargs as if the path were reachable. Updated both to spell out the Phase 1 panel rejection and point users at compute_robust_vcov / LinearRegression for cross-sectional Conley. Rewrote the llms-full.txt Conley section around the LinearRegression / compute_robust_vcov surface, replaced the panel- estimator example with a cross-sectional one, and listed the panel rejection in the restrictions table. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HAC Re-reviewOverall Assessment: Executive Summary
MethodologyP1 — [Newly identified] Radial Bartlett is presented as Conley’s PSD-guaranteed Bartlett kernelLocations: Impact: The code implements Concrete fix: Either implement/document a true separable Conley Eq. 3.14 product kernel for the PSD-guaranteed path, or keep the current R- Code QualityNo additional unmitigated code-quality findings. The prior survey bypass is fixed at PerformanceNo unmitigated findings. Dense MaintainabilityP3 — Callable
|
…h kernels Address CI Codex review of PR #411 (P1 + P3): P1 — The implementation called the radial 1-D Bartlett kernel "PSD-guaranteed" by citing Conley 1999 Eq 3.14 + Andrews 1991. Conley's explicit PSD Bartlett formula (Eq 3.14, page 12) is the 2-D separable product window `(1 - |j|/L_M)(1 - |k|/L_N)` indexed on a lattice; the 1-D radial form on pairwise distance that diff-diff and R `conleyreg` implement is a practitioner specialization (Hsiang 2010, Colella et al. 2019) that is not explicitly written in the paper and is therefore not formally PSD-guaranteed. Reframe the kernel docstring around the practitioner-specialization framing, drop the PSD-guaranteed claim, and lift the meat-eigenvalue PSD guard out of the uniform-only branch so it fires for both supported kernels. The warning message now names the active kernel and explicitly states neither radial form is formally PSD. New regression test test_indefinite_meat_warning_fires_for_bartlett locks the lifted guard by patching `_bartlett_kernel` to return an aggressively indefinite matrix and asserting the warning surfaces with the kernel name. P3 — Stale wording cleanup: - conley.py:128-132 missing-coords error message pointed at TwoWayFixedEffects(conley_coords=...) even though TWFE rejects Conley in Phase 1; redirect to LinearRegression / compute_robust_vcov. - TestConleyEstimatorIntegration class docstring claimed panel estimators accept Conley and print a label; rewrote to describe fit-time panel rejection. Doc surfaces (REGISTRY ConleySpatialHAC kernel section, llms-full.txt kernels block, CHANGELOG `conley_kernel` description, conley-1999- review.md PSD-failure note) updated to reflect the both-kernels guard and the radial-specialization framing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HAC Re-reviewOverall assessment: ✅ Looks good Executive Summary
MethodologyP3 — Informational: radial Bartlett is a documented source specializationImpact: The implementation uses the radial Concrete fix: No action required. The registry note and runtime warning contract are present at Code QualityNo unmitigated findings. Conley dispatch is centralized through PerformanceNo unmitigated findings. Dense MaintainabilityNo unmitigated findings. The sibling surfaces are mirrored: Tech DebtP3 — Callable
|
Address P3 doc-drift finding from CI Codex review of PR #411 R-final. The function-level docstring already lists Conley in the dispatch description, but the Parameters section's `vcov_type` enum line and the four `conley_*` keyword-only kwargs were not separately documented. Added `"conley"` to the enum and four new parameter entries (``conley_coords``, ``conley_cutoff_km``, ``conley_metric``, ``conley_kernel``) describing the cross-sectional-only Phase 1 contract and the both-kernel indefiniteness warning. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HAC Re-reviewOverall assessment: ✅ Looks good Executive Summary
MethodologyP3 — Informational: radial Bartlett is a documented source specializationImpact: The implementation uses radial Concrete fix: No action required. See Code QualityNo unmitigated findings. Conley dispatch is centralized through PerformanceNo unmitigated findings. Dense MaintainabilityP3 — Dead Conley TWFE forwarding remains behind an unconditional rejectionImpact: Concrete fix: Either remove the unreachable block now or mark it explicitly as Phase 2 scaffolding. Tech DebtP3 — Callable
|
Address two P3 findings from CI Codex review of PR #411: P3 (Maintainability) — DiD/MultiPeriodDiD/TWFE all reject vcov_type="conley" unconditionally at fit-time, but each fit() still materialized `_conley_coords_array` from data and forwarded `conley_coords`, `conley_cutoff_km`, `conley_metric`, `conley_kernel` to LinearRegression / solve_ols. Those code paths were unreachable behind the unconditional NotImplementedError raise. Removed the dead extraction + arg-passes from all three estimators. The constructor still accepts the conley_* kwargs for sklearn-style API symmetry (set_params/get_params round-trip works); they have no effect on the panel paths. P3 (Documentation) — `docs/methodology/papers/conley-1999-review.md` Requirements checklist and Tuning Parameters table still said the Bartlett kernel is "PSD by construction" and only flagged uniform as needing the negative-eigenvalue warning. Updated both surfaces to spell out the radial 1-D pairwise specialization vs Conley's explicit 2-D separable PSD lattice formula (Eq 3.14) and to apply the warning to both kernels — matching the registry and the runtime contract. 271 targeted regression tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HAC Re-reviewOverall Assessment✅ Looks good — No unmitigated P0/P1 findings found in this re-review. Executive Summary
MethodologyP3 — Informational: radial Bartlett is a documented source specializationImpact: The implementation uses Concrete fix: No action required. See Code QualityNo unmitigated findings. The Conley dispatch and guards are centralized through PerformanceP3 — Informational: dense O(n²) Conley path is warned and trackedImpact: Phase 1 builds a dense pairwise distance matrix, which is expected but can be expensive for large Concrete fix: No blocking action required. The implementation emits a warning for MaintainabilityP3 — Unreachable TWFE Conley auto-cluster branch remainsImpact: Concrete fix: Remove the unreachable block or mark it explicitly as Phase 2 scaffolding. Tech DebtP3 — Callable
|
…esolve_vcov_type docstring Address two P3 documentation/maintenance findings from CI Codex review of PR #411 R-final: - twfe.py:234-240: an `elif self.vcov_type == "conley"` branch in the cluster-resolution chain disabled the auto-cluster default for Conley. Unreachable behind the unconditional Conley reject at twfe.py:146-163. Removed. - linalg.py::resolve_vcov_type docstring: the "Rules" section and Returns docstring listed only `{"classical", "hc1", "hc2", "hc2_bm"}`, omitting `"conley"` even though `_VALID_VCOV_TYPES` includes it and the runtime path already accepts it. Updated both surfaces; the source of truth pointer (`_VALID_VCOV_TYPES`) is now named explicitly so future enum additions don't need a docstring sweep. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HAC Re-reviewOverall Assessment✅ Looks good — No unmitigated P0/P1 findings found. Executive Summary
MethodologyP3 — Informational: radial Bartlett is documented as a source specializationImpact: The implementation uses radial Concrete fix: No action required. Locations: Code QualityNo unmitigated findings. The Conley dispatch and validation are centralized through Locations: PerformanceP3 — Informational: dense O(n²) Conley path is warned and trackedImpact: Phase 1 materializes a dense pairwise distance matrix, which can be expensive for large cross sections. Concrete fix: No blocking action required. The implementation warns at large Locations: MaintainabilityP3 — Minor: MultiPeriodDiD has a redundant Conley + absorb pre-guardImpact: Concrete fix: Remove the absorb-specific Conley block or change its message to point to the unconditional Phase 2 panel rejection. Location: Tech DebtP3 — Tracked: callable
|
Wires Conley spatial-HAC standard errors into DifferenceInDifferences,
TwoWayFixedEffects, and MultiPeriodDiD via four new keyword-only kwargs:
conley_coords (lat/lon column tuple), conley_cutoff_km (required, no
default per no-silent-failures), conley_metric ("haversine" default,
"euclidean", or callable), conley_kernel ("bartlett" default, "uniform").
Variance estimator (Conley 1999 Eq 4.2): Var̂(β) = (X'X)^{-1} ·
(Σ_{i,j} K(d_ij/h) X_i ε_i ε_j X_j') · (X'X)^{-1}. FWL composes cleanly
because the meat depends only on scores X·ε which within-transformation
preserves -- TwoWayFixedEffects with conley is supported, unlike hc2/hc2_bm
which need the full hat matrix. TWFE auto-cluster-at-unit is disabled when
vcov_type="conley"; explicit cluster= raises NotImplementedError (combined
product kernel deferred to Phase 2).
Helpers live in new module diff_diff/conley.py (separated from linalg.py
to keep the linear-algebra backend focused; revisited from the original
plan when Phase 2's k-d-tree fast path was scoped).
Cross-language parity vs R conleyreg (Düsterhöft 2021, CRAN v0.1.9) at
≤1e-6 on three benchmark fixtures; observed max abs diff 5.7e-16.
Earth radius 6371.01 km matches conleyreg::haversine_dist exactly.
Generation: cd benchmarks/R && Rscript generate_conley_golden.R.
SyntheticDiD(vcov_type="conley") raises TypeError (uses bootstrap variance,
not analytical sandwich; tracked in TODO.md). conley + cluster_ids /
weights / survey_design / absorb each raise NotImplementedError with
references to the deferral phase.
Other changes: .gitignore /papers/ rule anchored to repo root so
docs/methodology/papers/ is no longer silently swallowed; 5 paper-review
markdowns committed (Conley 1999, Colella 2019, Clarke 2017, Butts 2023,
Butts 2021) as the methodology basis for REGISTRY ConleySpatialHAC and
the Phase 3 ring-indicator rescope flagged in BRIEFING.md.
70 new Conley tests pass (67 internal + 3 R parity); 442 tests pass on
the targeted regression surface (test_linalg, test_linalg_hc2_bm,
test_estimators_vcov_type, test_estimators, test_methodology_twfe).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes two no-silent-failure gaps surfaced after the initial Phase 1 commit:
1. SyntheticDiD.set_params() now mirrors __init__'s Conley rejection contract.
The constructor correctly raises TypeError on vcov_type="conley" /
conley_*=... but set_params() previously only checked hasattr(self, key)
and silently accepted those kwargs because SyntheticDiD inherits the
conley_* attributes from DifferenceInDifferences. A user calling
est.set_params(vcov_type="conley", conley_cutoff_km=100.0) followed by
est.fit(...) would have gotten the bootstrap/jackknife/placebo variance
silently with no Conley computation -- forbidden by feedback_no_silent_failures.
The new set_params() rejects non-None vcov_type and any non-None conley_*
kwarg with TypeError before mutation; None values for these keys are
passthrough no-ops so get_params() -> set_params() round-trips cleanly.
SyntheticDiD.get_params() now surfaces the inherited conley_* keys with
None values for sklearn-style API consistency.
2. TwoWayFixedEffects(vcov_type="conley", inference="wild_bootstrap") now
raises NotImplementedError. Conley analytical spatial-HAC and wild cluster
bootstrap are different inference paths; combining them would route the
bootstrap branch with cluster_ids=None (TWFE auto-cluster is disabled
under Conley) and fail with a non-targeted error inside wild_bootstrap_se.
Use inference='analytical' for Conley spatial HAC, or vcov_type='hc1'
with inference='wild_bootstrap'.
3. DifferenceInDifferences and MultiPeriodDiD class docstrings now list
vcov_type="conley" in the enum and document the four conley_* params
(previously the Conley path was documented in REGISTRY/CHANGELOG/llms.txt
but the in-code class docs still listed only {classical, hc1, hc2, hc2_bm}).
4. New tests:
- SyntheticDiD().set_params(vcov_type="conley") raises TypeError + state
unchanged
- SyntheticDiD().set_params(conley_cutoff_km=100.0) raises + state unchanged
- SyntheticDiD().get_params() includes conley_* keys with None values;
round-trip set_params(**get_params()) is a no-op
- TwoWayFixedEffects(vcov_type="conley", inference="wild_bootstrap") raises
5. TODO.md entries added for deferred follow-ups: callable-conley_metric
shape/finiteness/symmetry validation, common Conley estimator-validator
helper extraction, and a stronger TWFE Conley FWL invariance test that
actually compares TWFE-within Conley to a full-dummy FE design (the
current test only asserts finite SEs).
74 Conley tests pass (70 prior + 4 new); 261 tests pass on the targeted
regression surface (test_conley_vcov, test_estimators_vcov_type, test_linalg,
test_linalg_hc2_bm).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ring Address CI Codex review of PR #411 (P1#1 + P1#2): P1#1 — Panel estimators with vcov_type="conley" silently produced wrong SE because cross-sectional Conley over (unit, time) rows treated same- unit cross-time pairs as d_ij=0 -> K=1, mishandling the space-time HAC. Phase 1 supports cross-sectional Conley only; reject panel fits at fit-time on DifferenceInDifferences, TwoWayFixedEffects, and MultiPeriodDiD with NotImplementedError. Practitioners pre-collapse to per-unit first-differences and call compute_robust_vcov directly. Phase 2 will add the space-time product kernel (Driscoll-Kraay) and lift the rejection. Granular Conley-arg validation collapsed into the single unconditional reject (cluster/absorb/coords/cutoff combinations all hit the same path). P1#2 — conley_metric was dropped at the result boundary and _format_vcov_label hard-coded "km" for the cutoff label even when metric was "euclidean". With panels rejected, the conley_cutoff_km / conley_kernel fields on DiDResults / MultiPeriodDiDResults are now unreachable; remove the dead fields, the dead arg passes from estimators.py / twfe.py, and the dead "conley" branch in _format_vcov_label. Tests added: TWFE / DiD / MPD panel-rejection regressions, including a repeated-coords-across-periods regression per the CI reviewer's recommendation. 70 Conley tests + 401 targeted regression tests pass. REGISTRY / CHANGELOG / llms.txt / README / TODO updated to reflect that the only supported Phase 1 Conley path is direct LinearRegression / compute_robust_vcov on a single-period design. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address CI Codex review of PR #411 (P1 + P2): P1 — LinearRegression(vcov_type="conley", survey_design=...) silently bypassed the documented Conley+survey rejection. The downstream _validate_vcov_args (inside compute_robust_vcov) rejects this combination, but LinearRegression.fit() sets return_vcov=False on the solve_ols call when survey vcov is needed (so the linalg validator never runs), and the survey vcov path then overwrites vcov_ with a non-Conley variance under a Conley request. Front-door the rejection at LinearRegression entry so the contract is enforced uniformly. New regression test test_linear_regression_conley_with_survey_design_raises locks the new guard with a make_pweight_design fixture. P2 — DifferenceInDifferences and MultiPeriodDiD docstrings still listed "conley" as a vcov_type option and described the conley_* kwargs as if the path were reachable. Updated both to spell out the Phase 1 panel rejection and point users at compute_robust_vcov / LinearRegression for cross-sectional Conley. Rewrote the llms-full.txt Conley section around the LinearRegression / compute_robust_vcov surface, replaced the panel- estimator example with a cross-sectional one, and listed the panel rejection in the restrictions table. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…h kernels Address CI Codex review of PR #411 (P1 + P3): P1 — The implementation called the radial 1-D Bartlett kernel "PSD-guaranteed" by citing Conley 1999 Eq 3.14 + Andrews 1991. Conley's explicit PSD Bartlett formula (Eq 3.14, page 12) is the 2-D separable product window `(1 - |j|/L_M)(1 - |k|/L_N)` indexed on a lattice; the 1-D radial form on pairwise distance that diff-diff and R `conleyreg` implement is a practitioner specialization (Hsiang 2010, Colella et al. 2019) that is not explicitly written in the paper and is therefore not formally PSD-guaranteed. Reframe the kernel docstring around the practitioner-specialization framing, drop the PSD-guaranteed claim, and lift the meat-eigenvalue PSD guard out of the uniform-only branch so it fires for both supported kernels. The warning message now names the active kernel and explicitly states neither radial form is formally PSD. New regression test test_indefinite_meat_warning_fires_for_bartlett locks the lifted guard by patching `_bartlett_kernel` to return an aggressively indefinite matrix and asserting the warning surfaces with the kernel name. P3 — Stale wording cleanup: - conley.py:128-132 missing-coords error message pointed at TwoWayFixedEffects(conley_coords=...) even though TWFE rejects Conley in Phase 1; redirect to LinearRegression / compute_robust_vcov. - TestConleyEstimatorIntegration class docstring claimed panel estimators accept Conley and print a label; rewrote to describe fit-time panel rejection. Doc surfaces (REGISTRY ConleySpatialHAC kernel section, llms-full.txt kernels block, CHANGELOG `conley_kernel` description, conley-1999- review.md PSD-failure note) updated to reflect the both-kernels guard and the radial-specialization framing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address P3 doc-drift finding from CI Codex review of PR #411 R-final. The function-level docstring already lists Conley in the dispatch description, but the Parameters section's `vcov_type` enum line and the four `conley_*` keyword-only kwargs were not separately documented. Added `"conley"` to the enum and four new parameter entries (``conley_coords``, ``conley_cutoff_km``, ``conley_metric``, ``conley_kernel``) describing the cross-sectional-only Phase 1 contract and the both-kernel indefiniteness warning. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address two P3 findings from CI Codex review of PR #411: P3 (Maintainability) — DiD/MultiPeriodDiD/TWFE all reject vcov_type="conley" unconditionally at fit-time, but each fit() still materialized `_conley_coords_array` from data and forwarded `conley_coords`, `conley_cutoff_km`, `conley_metric`, `conley_kernel` to LinearRegression / solve_ols. Those code paths were unreachable behind the unconditional NotImplementedError raise. Removed the dead extraction + arg-passes from all three estimators. The constructor still accepts the conley_* kwargs for sklearn-style API symmetry (set_params/get_params round-trip works); they have no effect on the panel paths. P3 (Documentation) — `docs/methodology/papers/conley-1999-review.md` Requirements checklist and Tuning Parameters table still said the Bartlett kernel is "PSD by construction" and only flagged uniform as needing the negative-eigenvalue warning. Updated both surfaces to spell out the radial 1-D pairwise specialization vs Conley's explicit 2-D separable PSD lattice formula (Eq 3.14) and to apply the warning to both kernels — matching the registry and the runtime contract. 271 targeted regression tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…esolve_vcov_type docstring Address two P3 documentation/maintenance findings from CI Codex review of PR #411 R-final: - twfe.py:234-240: an `elif self.vcov_type == "conley"` branch in the cluster-resolution chain disabled the auto-cluster default for Conley. Unreachable behind the unconditional Conley reject at twfe.py:146-163. Removed. - linalg.py::resolve_vcov_type docstring: the "Rules" section and Returns docstring listed only `{"classical", "hc1", "hc2", "hc2_bm"}`, omitting `"conley"` even though `_VALID_VCOV_TYPES` includes it and the runtime path already accepts it. Updated both surfaces; the source of truth pointer (`_VALID_VCOV_TYPES`) is now named explicitly so future enum additions don't need a docstring sweep. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
/ai-review |
|
🔁 AI review rerun (requested by @igerber) Head SHA: PR Review: Conley Spatial HAC SE Re-reviewOverall AssessmentExecutive Summary
MethodologyP3 — Informational: radial Bartlett specialization is documented as a deviation/source specializationImpact: The implementation uses radial 1-D Bartlett on pairwise distance, matching R Concrete fix: No action required. Locations:
P3 — Informational: panel Conley is correctly rejected per current registry scopeImpact: The changed registry and changelog state Phase 1 supports cross-sectional Conley only and rejects
This resolves the main methodology risk of silently applying cross-sectional Conley over panel Concrete fix: No action required. Locations:
Code QualityP3 — Minor: MultiPeriodDiD has a redundant and misleading Conley +
|
Summary
vcov_type="conley"onDifferenceInDifferences,TwoWayFixedEffects, andMultiPeriodDiDwith four new__init__kwargs:conley_coords,conley_cutoff_km,conley_metric,conley_kernel. Variance estimator is Conley (1999) Eq 4.2 in pairwise form:Var̂(β) = (X'X)^{-1} · (Σ_{i,j} K(d_ij/h) · X_i ε_i ε_j X_j') · (X'X)^{-1}. Helpers live in newdiff_diff/conley.pymodule (kept separate fromlinalg.pyso the linear-algebra backend stays focused on OLS/sandwich primitives).X·ε, both of which within-transformation preserves.TwoWayFixedEffects(vcov_type="conley", ...)is therefore supported (unlikehc2/hc2_bmwhich need the full hat matrix). TWFE auto-cluster-at-unit is disabled whenvcov_type="conley"; explicitcluster=,survey_design=,absorb=, orinference="wild_bootstrap"each raiseNotImplementedError(deferred to Phase 2+ follow-ups).SyntheticDiD(vcov_type="conley")raisesTypeErrorat both__init__andset_params(uses bootstrap variance, not the analytical sandwich).conleyregparity (Düsterhöft 2021, CRAN v0.1.9) on three benchmark fixtures atbenchmarks/data/r_conleyreg_conley_golden.json; observed max abs diff 5.7e-16. Earth radius 6371.01 km matchesconleyreg::haversine_dist. Regenerate viacd benchmarks/R && Rscript generate_conley_golden.R. Test filetests/test_conley_vcov.pyskips parity cleanly when the JSON is absent (per thefeedback_golden_file_pytest_skipconvention; CI's isolated-install job ships onlytests/).Methodology references (required if estimator / math changes)
## ConleySpatialHAC.conleyreg: Estimations using Conley Standard Errors. CRAN R package, https://github.com/cdueben/conleyreg. Parity benchmark target.acregreference; cited but not parity-tested here (Stata is paid-only).docs/methodology/papers/(Conley 1999, Colella 2019, Clarke 2017, Butts 2023, Butts 2021) committed as the methodology basis forConleySpatialHACand the rescoped Phase 3 ring-indicator design tracked in BRIEFING.md.conleyregexactly; the methodologically-equivalent 6371.0 km was the original draft value but produces ~1.5e-6 relative drift vsconleyregand would break the 1e-6 parity bound. All deferrals (cluster,weights,absorb,wild_bootstrap,SyntheticDiD) are documented asNotImplementedError/TypeErrorraises with explicit pointers to the deferral phase, perfeedback_no_silent_failures.Validation
tests/test_conley_vcov.py(new; 74 tests across 12 test classes covering kernels, distance metrics, validator helpers, dispatch parity, estimator integration on DiD/MultiPeriodDiD/TWFE, set_params atomicity, defensive SyntheticDiD rejection, TWFE Conley+cluster/wild_bootstrap rejection, and Rconleyregparity at atol=1e-6 on three haversine fixtures).benchmarks/data/r_conleyreg_conley_golden.json, observed max abs diff 5.7e-16. No tutorial added in Phase 1; the practitioner-facing T22 tutorial demonstrating Phase 3 ring-indicator spillover-aware DiD with Conley SE on top is queued for Phase 3 of the initiative.Security / privacy
/pre-merge-checkSection 2.6 secret-pattern scan; only synthetic test data and generated fixtures).🤖 Generated with Claude Code