Skip to content

feat: add covariate support to ChangesInChanges/QDiD (qte xformla parity)#688

Merged
igerber merged 6 commits into
mainfrom
cic-covariates
Jul 14, 2026
Merged

feat: add covariate support to ChangesInChanges/QDiD (qte xformla parity)#688
igerber merged 6 commits into
mainfrom
cic-covariates

Conversation

@igerber

@igerber igerber commented Jul 13, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add covariate support to ChangesInChanges and QDiD by porting qte 1.3.1's xformla branch exactly - the Melly-Santangelo (2015) quantile-regression conditional CiC in qte's simplified form: covariates=[...] fit kwarg (library convention) plus DiD-style trailing formula terms; numeric covariates only (dummy-encode categoricals); formula combined with any explicit column argument now raises (uniform strictness, documented as deliberately stricter than DifferenceInDifferences).
  • Numeric core: per-cell Koenker-Bassett quantile regressions (LP via scipy.optimize.linprog/HiGHS) on qte's fixed internal seq(0.01, 0.99, 0.01) tau grid (hardcoded R doubles, pinned against the fixture); quantreg predict.rqs Fhat/Qhat step-function conventions ported verbatim; per-observation conditional-rank imputation (CiC: control-cell QRs; QDiD: three cells, own-cell ranks, additive form with qte's asymmetric type-7/type-1 quantile pair). Covariates travel through both bootstrap schemes with QR refits per replicate (qte bootiter parity); LP failures NaN-row through the existing gate.
  • Diagnostics: conditional-envelope support warning (Melly-Santangelo Assumption 4) replaces the unconditional support check on covariate fits; the eq. 17 interior-range guard is scoped to unconditional fits (q_lower/q_upper NaN under covariates - the NaN-mask interaction is explicitly gated and lock-tested); QDiD's monotonicity warning is skipped under covariates (moot by construction); paired cell sort keeps (y, X) aligned while preserving every sorted-y invariant.
  • Fixtures: covariate scenarios + qr_cases convention micro-fixtures (R coefficient matrices, prediction matrices, Fhat/Qhat outputs) added to benchmarks/data/qte_golden.json; quantreg 6.1 pinned alongside qte 1.3.1; seeded SE blocks now generated with cores=1 after discovering qte's default forked bootstrap is not reproducible even under set.seed - the generator is now byte-reproducible run-to-run.
  • Docs sweep: REGISTRY covariates block with labeled Notes/Deviation, API example (file added to the doc-snippets allowlist; the pre-existing panel example is now self-contained and actually executes), llms/llms-full updates, references.rst gains Melly-Santangelo (2015) and Koenker-Bassett (1978) entries, review-doc factual correction (the earlier "no R parity target exists for covariate CiC" claim was wrong - qte's xformla branch is one), TODO row rescoped to the full MS estimator, stale ROADMAP row removed, CHANGELOG Unreleased bullet amended.

Methodology references (required if estimator / math changes)

  • Method name(s): Changes-in-Changes with covariates / conditional quantile-DiD (qte xformla parity route)
  • Paper / source link(s): Athey & Imbens (2006), Econometrica 74(2) (reviewed: docs/methodology/papers/athey-imbens-2006-review.md); Melly & Santangelo (2015) working paper (reviewed: docs/methodology/papers/melly-santangelo-2015-review.md); Koenker & Bassett (1978), Econometrica 46(1); reference implementation qte 1.3.1 (CiC()/QDiD() xformla branches) with quantreg 6.1.
  • Any intentional deviations from the source (and why): all documented with labeled Notes in docs/methodology/REGISTRY.md (ChangesInChanges section, covariates block): qte's simplified MS pipeline (fixed 99-tau grid, treated-PRE covariate integration, raw un-rearranged step functions) is canonical; NA handling is fit-level dropna-with-warning rather than qte's silent na.omit; scipy-HiGHS-vs-quantreg-br solver deviation with exact-tie selection semantics; QDiD's asymmetric Q7/Q1 quantile types ported verbatim. The full Melly-Santangelo estimator, discrete bounds, analytical SEs, and staggered designs remain documented-deferred (TODO rows).

Validation

  • Tests added/updated: tests/test_changes_in_changes.py (covariate validation, formula grammar, diagnostics scoping, bootstrap gates, NaN-guard lock test, x11-invariance), tests/test_methodology_changes_in_changes.py (irrelevant-covariate consistency, compositional-confounding correction, constant-covariate order-statistic hand-check), tests/test_changes_in_changes_parity.py (layered parity: qr_cases conventions at atol=0 conditioned on R inputs, per-tau LP optimality via coefficient-or-loss equality, end-to-end covariate gates at tie-selection bounds with sharpness floors, covariate SE statistical parity, quantreg version pin), tests/test_doc_snippets.py (allowlist).
  • Backtest / simulation / notebook evidence (if applicable): cross-language parity is layered because end-to-end bit-parity is unattainable for the QR pipeline (two exact-tie artifacts: optimal-face vertex selection and Fhat knot-tie ordering; see the REGISTRY Deviation note). A 30-dataset randomized decomposition audit (5 DGP families incl. binary-covariate and ties-heavy cells) verified: composition-on-R-coefficients exact 30/30 (worst 1.3e-15); 8,910 LP solves all coefficient-matching or two-sided loss-equal (worst gap 3.2e-16, zero descent-probe failures); all 1,586 rank flips attributed to the documented tie mechanisms; no directional bias (sign tests p=0.69/0.59). A 1,999-replicate seeded SE comparison agrees with R's to 2.3% on the ATT SE - statistically indistinguishable from pure Monte Carlo noise at that replicate count. Existing no-covariate goldens pass unchanged at the original 1e-10 gate.

Security / privacy

  • Confirm no secrets/PII in this PR: Yes

Generated with Claude Code

🤖 Generated with Claude Code

https://claude.ai/code/session_011hismLBFcUbUzvDRq8ruWb

igerber and others added 2 commits July 13, 2026 18:57
…ity)

Port qte 1.3.1's xformla covariate branch exactly - the Melly-Santangelo
(2015) quantile-regression conditional CiC in qte's simplified form:

- covariates= fit kwarg (library convention) + DiD-style trailing formula
  terms; numeric covariates only (dummy-encode categoricals); formula plus
  any explicit column argument now raises (uniform strictness)
- per-cell Koenker-Bassett quantile regressions via scipy linprog/HiGHS on
  qte's fixed internal seq(0.01, 0.99, 0.01) tau grid (hardcoded R doubles,
  pinned against the fixture); quantreg predict.rqs Fhat/Qhat step-function
  conventions ported verbatim; per-observation conditional-rank imputation
  (CiC: control-cell QRs; QDiD: three cells, own-cell ranks, additive form
  with qte's asymmetric type-7/type-1 quantile pair)
- covariates travel through both bootstrap schemes with QR refits per
  replicate (qte bootiter parity); LP failure NaN-rows through the gate
- conditional-envelope support diagnostic (MS Assumption 4) replaces the
  unconditional support warning; the eq. 17 interior-range guard is scoped
  to unconditional fits (q_lower/q_upper NaN under covariates); QDiD
  monotonicity check skipped (moot by construction); paired cell sort keeps
  (y, X) aligned while preserving all sorted-y invariants
- fixtures: covariate scenarios + atol=0 qr_cases convention micro-fixtures
  (R coefficients, prediction matrices, Fhat/Qhat outputs), quantreg 6.1
  pinned alongside qte 1.3.1; seeded SE blocks now generated with cores=1
  (qte's default forked bootstrap is not reproducible even under set.seed)
- parity is layered: conventions bit-exact conditioned on R inputs, the LP
  solver proven exactly optimal per tau (equal coefficients or equal check
  loss), end-to-end covariate results gated at documented exact-tie
  selection bounds (REGISTRY Deviation note; measured worst 9.3e-3 ATT /
  8.1e-2 QTE, gates 2e-2 / 0.15)
- docs sweep: REGISTRY covariates block with labeled Notes, api rst example
  (file added to doc-snippets allowlist), llms/llms-full, references.rst
  (Melly-Santangelo 2015 + Koenker-Bassett 1978 entries), choosing/r_
  comparison, review-doc corrections (the earlier "no R parity target for
  covariate CiC" claim was wrong - qte's xformla branch is one), TODO row
  rescoped to the full MS estimator, stale ROADMAP row removed, CHANGELOG
  Unreleased bullet amended

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hismLBFcUbUzvDRq8ruWb
The regenerated benchmarks/data/qte_golden.json is ~700KB of single-line
generated JSON; with both diff sides it pushed the review prompt past the
model's input limit and the review job died in 23s on PR #688. Extend the
existing large-asset exclusion list (the file stays visible in
--name-status; the reviewable artifact is benchmarks/R/generate_qte_golden.R).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hismLBFcUbUzvDRq8ruWb
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 023886fb8a2db5f85734e70b5cad0af4f5ba9544


Overall Assessment

Looks good — no unmitigated P0/P1 findings.

Executive Summary

  • Affected methods: ChangesInChanges and QDiD, specifically the new covariate / qte xformla paths.
  • I found no undocumented estimator-math, bootstrap, SE, or inference mismatch against docs/methodology/REGISTRY.md.
  • The new inference path uses safe_inference / safe_inference_batch; I did not find new inline t-stat / p-value / CI anti-patterns.
  • Minor issues remain in documentation/validation consistency, but they do not block approval.
  • I could not run tests in this environment: pytest and numpy are not installed.

Methodology

Finding 1

Severity: P3
Location: docs/methodology/REGISTRY.md:L3800, benchmarks/R/generate_qte_golden.R:L426-L434, tests/test_changes_in_changes_parity.py:L66-L68
Impact: The registry says covariate end-to-end parity is gated at ATT 2e-2 and QTE 0.15, while the generator/test constants use ATT 0.04 and QTE 0.25. This is not an estimator defect, but it weakens the registry as the methodology source of truth.
Concrete fix: Align the registry text with the actual committed gates, or tighten COV_ATT_ATOL / COV_QTE_ATOL and fixture metadata to match the registry.

Code Quality

No findings.

Performance

Finding 1

Severity: P3 informational, tracked in TODO.md
Location: TODO.md:L44, diff_diff/changes_in_changes.py:_rq_fit
Impact: Dense LP assembly can be memory/time heavy for large covariate bootstrap workloads. This is already tracked as deferred performance work and is not a blocker.
Concrete fix: No PR action required. Future sparse LP assembly should re-run and recalibrate the parity suite as noted in TODO.md.

Maintainability

No findings.

Tech Debt

Finding 1

Severity: P3 informational, tracked in TODO.md
Location: TODO.md:L116
Impact: The full Melly-Santangelo estimator remains deferred, while this PR ships the documented qte simplified route. This is explicitly tracked and documented.
Concrete fix: No PR action required.

Security

No findings.

Documentation/Tests

Finding 1

Severity: P2
Location: docs/choosing_estimator.rst:L42, diff_diff/guides/llms.txt:L74
Impact: These compact docs can be read as saying CiC remains invariant to monotone outcome transformations even when covariates are used. The registry correctly says monotone-transform equivariance does not extend to the covariate QR branch.
Concrete fix: Qualify both entries with “unconditional fits only” or split the covariate sentence so the invariant property is not attached to covariate fits.

Finding 2

Severity: P3
Location: benchmarks/R/generate_qte_golden.R:L367-L393, tests/test_changes_in_changes_parity.py:L246-L356
Impact: The generator stores cic_ate, cic_qte, qdid_ate, and qdid_qte for QR micro-cases and comments that they guard against qte internals diverging, but the tests do not assert those fields.
Concrete fix: Add assertions comparing the helper-composed micro results to the stored qte end-to-end micro outputs, or remove the unused fields/comment.

…iers, micro consistency test

- REGISTRY covariate Deviation note now states the audited committed gates
  (ATT 0.04 / QTE 0.25) with the randomized-audit evidence and sharpness
  floors, replacing the stale pre-audit numbers (P3)
- choosing_estimator.rst + llms.txt qualify the monotone-transform
  invariance claim as unconditional-fits-only (the covariate QR branch is
  not equivariant) (P2)
- new qr_cases test asserts the stored micro end-to-end qte outputs are
  consistent with composing R's stored imputations (R-vs-R, atol 1e-12) -
  the guard the generator comment promised (P3)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hismLBFcUbUzvDRq8ruWb
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 4cce8c8fbd2e40e1e05696b8774a765a74efb378


Overall Assessment

Looks good — no unmitigated P0/P1 findings.

Executive Summary

  • Affected methods: ChangesInChanges and QDiD, specifically the new covariate / qte xformla paths.
  • The methodology deviations I found are documented in REGISTRY.md with labeled Notes/Deviation blocks, so they are not defects under the review rules.
  • Prior review items appear addressed: covariate parity gates now align, monotone-transform docs are qualified, and QR micro end-to-end outputs are asserted.
  • New inference code uses safe_inference / safe_inference_batch; I found no new inline inference or partial-NaN anti-patterns.
  • I could not run tests here: pytest, numpy, pandas, and scipy are not installed.

Methodology

Finding 1

Severity: P3 informational, documented deviation
Impact: The covariate implementation intentionally follows qte’s simplified Melly-Santangelo-style xformla route, not the full Melly-Santangelo estimator. The treated-pre covariate integration, raw QR step functions, HiGHS-vs-quantreg tie selection, and QDiD asymmetric Q7/Q1 quantile types are all documented with labeled Notes/Deviation entries.
Concrete fix: No PR action required. Relevant code/docs: diff_diff/changes_in_changes.py:L432-L499, docs/methodology/REGISTRY.md:L3794-L3801, TODO.md:L116.

Code Quality

No findings.

Performance

Finding 1

Severity: P3 informational, tracked in TODO.md
Impact: _rq_fit builds dense LP matrices per cell/tau/bootstrap replicate, which may be memory/time heavy for large covariate workloads. This is explicitly tracked as deferred performance work.
Concrete fix: No PR action required. Future sparse LP assembly should preserve the parity/tie-selection contract. Location: TODO.md:L44.

Maintainability

No findings.

Tech Debt

Finding 1

Severity: P3 informational, tracked in TODO.md
Impact: The full Melly-Santangelo estimator remains deferred while the PR ships the documented qte simplified route. This is explicitly tracked.
Concrete fix: No PR action required. Location: TODO.md:L116.

Security

No findings.

Documentation/Tests

Finding 1

Severity: P2
Impact: The compact QDiD guide still says “a non-monotonicity warning fires when violated” without qualifying that this is for unconditional fits only. The registry, API docs, and full LLM guide correctly say the covariate-path check is skipped because the imputed counterfactual quantile curve is monotone by construction.
Concrete fix: Update diff_diff/guides/llms.txt:L75 to mention covariates= support and qualify the non-monotonicity warning as “unconditional fits only.”

…ms.txt

The compact QDiD one-liner still attached the footnote-21 warning to all
fits; qualified as unconditional-only (covariate-path counterfactual
quantile curve is monotone by construction) and mention covariates= support,
matching the registry / API docs / llms-full.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hismLBFcUbUzvDRq8ruWb
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 571f842597318a1f01dbe4f0e4cd0dc8f9700a52


Overall Assessment

Looks good — no unmitigated P0/P1 findings.

Executive Summary

  • Affected methods: ChangesInChanges / CiC and QDiD, specifically the new covariate / qte xformla paths.
  • Prior P2 compact-guide issue is addressed: diff_diff/guides/llms.txt:L74-L75 now documents covariate support and scopes QDiD’s non-monotonicity warning to unconditional fits.
  • Methodology deviations I checked are documented with Note / Deviation from R labels in REGISTRY.md, so they are not defects under the review rules.
  • New inference assembly uses safe_inference / safe_inference_batch; I found no new inline inference or partial-NaN anti-pattern.
  • I could not run tests in this environment because numpy, pandas, and scipy are not installed.

Methodology

Finding 1

Severity: P3 informational, documented deviation
Impact: The PR implements qte’s simplified Melly-Santangelo-style covariate route, not the full Melly-Santangelo estimator. The treated-pre covariate integration, raw/unrearranged QR step functions, HiGHS-vs-quantreg solver selection, conditional-envelope diagnostic scope, skipped covariate QDiD monotonicity warning, and QDiD asymmetric Q7/Q1 quantile types are all documented in labeled registry notes/deviations.
Concrete fix: No action required. Relevant locations: diff_diff/changes_in_changes.py:L432-L499, diff_diff/changes_in_changes.py:L979-L1058, docs/methodology/REGISTRY.md:L3794-L3801.

Code Quality

No findings.

Performance

Finding 1

Severity: P3 informational, tracked in TODO.md
Impact: _rq_fit uses dense LP assembly per tau/cell/bootstrap replicate, which may be expensive for large covariate workloads. This is already tracked as deferred performance work.
Concrete fix: No PR action required. Future sparse assembly should preserve the documented solver/tie-selection parity contract. Location: TODO.md:L44.

Maintainability

No findings.

Tech Debt

Finding 1

Severity: P3 informational, tracked in TODO.md
Impact: The full Melly-Santangelo estimator remains deferred while the PR ships the documented qte simplified route. This is tracked explicitly.
Concrete fix: No PR action required. Location: TODO.md:L116.

Security

No findings.

Documentation/Tests

Finding 1

Severity: P3 informational
Impact: Most docs now correctly qualify monotone-transform invariance as unconditional-only, but a few first mentions can still be read too broadly now that covariates ship. The registry and compact guide are correct, so this is not a methodology defect.
Concrete fix: Optionally qualify the first invariance mention in docs/api/changes_in_changes.rst:L10-L15, diff_diff/guides/llms-full.txt:L1033, and CHANGELOG.md:L82-L97 with “unconditional fits only; the covariate QR branch is not invariant to nonlinear monotone transforms.”

…claims

api rst intro, llms-full narrative, and the CHANGELOG bullet now carry the
unconditional-fits-only qualifier on monotone-transform invariance,
completing the claim-set sweep.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hismLBFcUbUzvDRq8ruWb
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 332f3989635725546ca2b1ef70892be0da936f0b


Overall Assessment

Looks good — no unmitigated P0/P1 findings.

Executive Summary

  • Affected methods: ChangesInChanges / CiC and QDiD, specifically the new covariate / qte xformla paths.
  • Prior documentation issue is addressed: invariance is now scoped to unconditional fits in the changelog, API docs, compact guide, and full guide.
  • Methodology deviations I checked are documented with Note / Deviation from R labels in REGISTRY.md, so they are P3 informational, not defects.
  • Inference assembly uses safe_inference / safe_inference_batch; I found no new inline inference or partial-NaN anti-pattern.
  • I could not run tests because this environment lacks numpy and pytest.

Methodology

Finding 1
Severity: P3 informational, documented deviation
Impact: The PR implements qte’s simplified Melly-Santangelo-style covariate route rather than the full Melly-Santangelo estimator. Treated-pre covariate integration, raw/unrearranged QR step functions, HiGHS-vs-quantreg solver differences, conditional-envelope diagnostic scope, skipped covariate QDiD monotonicity warning, and QDiD asymmetric Q7/Q1 quantile types are all documented.
Concrete fix: No action required. Relevant locations: diff_diff/changes_in_changes.py:L432-L499, docs/methodology/REGISTRY.md:L3794-L3801.

Code Quality

No findings.

Performance

Finding 1
Severity: P3 informational, tracked in TODO.md
Impact: _rq_fit builds dense LP matrices per tau/cell/bootstrap replicate, which may be expensive for large covariate workloads. This is already tracked as deferred performance work.
Concrete fix: No PR action required. Future sparse assembly should preserve the documented solver/tie-selection parity contract. Location: TODO.md:L44.

Maintainability

No findings.

Tech Debt

Finding 1
Severity: P3 informational, tracked in TODO.md
Impact: The full Melly-Santangelo estimator remains deferred while the PR ships the documented qte simplified route. This is tracked explicitly.
Concrete fix: No PR action required. Location: TODO.md:L116.

Security

No findings.

Documentation/Tests

Finding 1
Severity: P3 informational
Impact: A later section of melly-santangelo-2015-review.md still uses pre-PR language saying covariates are a future PR and that no R implementation is known. The registry and the top/reference sections are correct, so this is not a methodology defect, but it is stale documentation.
Concrete fix: Update docs/methodology/papers/melly-santangelo-2015-review.md:L460-L464 and docs/methodology/papers/melly-santangelo-2015-review.md:L516-L519 to distinguish “qte simplified branch shipped” from “full Melly-Santangelo estimator still has no R reference.”

…MS review doc

The Implementation Notes relevance block, the version-gaps bullet, and the
requirements-checklist header still described covariates as a future PR /
claimed no R implementation exists; all now distinguish the shipped qte
simplified branch from the full Melly-Santangelo estimator (which indeed
still has no R reference).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hismLBFcUbUzvDRq8ruWb
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 9cfb7de930d6ee994bb5f7a2c1a40f6ca8dd2834


Overall Assessment

Looks good — no unmitigated P0/P1 findings.

Executive Summary

  • Affected methods: ChangesInChanges / CiC and QDiD, specifically the new covariate / qte xformla paths.
  • Prior stale Melly-Santangelo documentation issue is addressed.
  • The major methodology deviations are explicitly documented in REGISTRY.md with Note / Deviation from R labels, so they are P3 informational, not defects.
  • Inference still flows through safe_inference() / safe_inference_batch(); I found no new inline t-stat/p-value/CI anti-pattern or partial NaN guard.
  • I could not run tests locally because this environment lacks numpy.

Methodology

Finding 1
Severity: P3 informational, documented deviation
Impact: The PR implements qte’s simplified Melly-Santangelo-style covariate route rather than the full Melly-Santangelo estimator. Treated-pre covariate integration, raw/unrearranged QR step functions, HiGHS-vs-quantreg solver differences, conditional-envelope diagnostic scope, skipped covariate QDiD monotonicity warning, and QDiD’s asymmetric Q7/Q1 quantile types are all documented.
Concrete fix: No action required. Relevant locations: diff_diff/changes_in_changes.py:L432-L499, diff_diff/changes_in_changes.py:L684-L761, docs/methodology/REGISTRY.md:L3794-L3801.

Code Quality

No findings.

Performance

Finding 1
Severity: P3 informational, tracked in TODO.md
Impact: _rq_fit builds dense LP matrices per tau/cell/bootstrap replicate, which can be expensive for large covariate workloads. This is already tracked as deferred performance work.
Concrete fix: No PR action required. Future sparse assembly should preserve the documented solver/tie-selection parity contract. Locations: diff_diff/changes_in_changes.py:L316-L342, TODO.md:L44.

Maintainability

No findings.

Tech Debt

Finding 1
Severity: P3 informational, tracked in TODO.md / REGISTRY.md
Impact: The full Melly-Santangelo estimator remains deferred while the PR ships the documented qte simplified route. This is explicitly tracked.
Concrete fix: No action required. Locations: TODO.md:L116, docs/methodology/REGISTRY.md:L3817-L3825.

Security

No findings. A secret-pattern scan only hit the expected GitHub Actions secret reference, not a committed secret.

Documentation/Tests

Finding 1
Severity: P3 informational, prior issue resolved
Impact: The prior review’s stale “no R implementation / future covariates” concern has been corrected and now distinguishes qte’s shipped simplified branch from the full Melly-Santangelo estimator.
Concrete fix: No action required. Locations: docs/methodology/papers/melly-santangelo-2015-review.md:L16, docs/methodology/papers/melly-santangelo-2015-review.md:L440, docs/methodology/papers/melly-santangelo-2015-review.md:L460-L464, docs/methodology/papers/melly-santangelo-2015-review.md:L519.

Finding 2
Severity: P3 informational
Impact: Local execution could not validate the added tests because importing the package fails with ModuleNotFoundError: No module named 'numpy'. Static review found targeted coverage for covariate validation, bootstrap gating, NaN inference behavior, registry parity fixtures, and the prior interior-range/covariate interaction.
Concrete fix: No PR action required; rely on CI for the full pytest/parity suite.

@igerber igerber added the ready-for-ci Triggers CI test workflows label Jul 14, 2026
@igerber igerber merged commit 01c80e5 into main Jul 14, 2026
38 of 39 checks passed
@igerber igerber deleted the cic-covariates branch July 14, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-ci Triggers CI test workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant