fix(dml): fail closed when cross-fit learners cannot be isolated (mirror of #816) - #817
fix(dml): fail closed when cross-fit learners cannot be isolated (mirror of #816)#817igerber wants to merge 3 commits into
Conversation
Context: - Cross-fit reuse after a failed or identity-returning deepcopy can carry fitted state and prior-fold training data into a later fold. - DMLDiD must reject an invalid learner template before any group-time cell is fitted. Changes: - Require a distinct top-level deepcopy for cross-fit learner templates and raise a sanitised TypeError otherwise. - Probe custom DML learner specifications during configuration validation while retaining the direct cross_fit_predict backstop. - Document the top-level clone boundary and cover copy failures, identity copies, sklearn templates, exact OOF isolation, and pre-cell error propagation. Verification: - pytest -q tests/test_crossfit.py tests/test_dml_did.py tests/test_changelog_fragments.py tests/test_docs_ia.py tests/test_doc_deps_integrity.py - Python 3.9 targeted regression tests, including sklearn preflight - ruff, black, scoped mypy, changelog compiler, and native cross-fit output comparison against upstream/main - Not run: full default suite was stopped after an interrupted long-running attempt.
Context: - Cross-fit learner templates must fail closed when cloning cannot provide an independent, usable learner, without exposing stale DML results after a failed re-fit. Changes: - Validate clone protocol and weighted-fit capability during DML preflight and for each direct cross-fit fold; delayed errors name the public nuisance parameter. - Clear DMLDiD fitted state before every fit attempt, and cover panel, repeated-cross-section, survey, and direct helper failure paths. - Correct the DML tutorial and documentation registry, and record the warning-to-TypeError behavioural change. Verification: - /tmp/diff-diff-814-python39/bin/python -m pytest -q tests/test_crossfit.py tests/test_dml_did.py tests/test_survey_dml.py tests/test_changelog_fragments.py tests/test_docs_ia.py tests/test_doc_deps_integrity.py (665 passed, 6 skipped) - black --check, ruff check, and mypy --follow-imports=skip on touched source/test modules - python -m json.tool docs/tutorials/32_dml_did.ipynb and python .claude/scripts/changelog_compile.py check - Not run: full repository test suite.
…light The preflight guarantees a failing or self-returning __deepcopy__ raises before any cell is fitted; a per-fold clone failure later in the fit propagates as the same sanitized TypeError. State that on every surface that previously promised the stronger before-any-cell guarantee.
Overall assessment✅ Looks good — no unmitigated P0 or P1 findings. Executive summary
Methodology
Code QualityNo findings. Clone, protocol, and sample-weight validation are centralized and errors remain targeted. PerformanceNo findings. The additional configuration-time copies are bounded and appropriate for validating learner isolation. MaintainabilityNo findings. The same helpers cover DMLDiD and direct Tech DebtNo new untracked correctness debt identified. SecurityNo findings. Foreign copy-exception messages and traceback context are suppressed at Documentation/Tests
Test coverage is strong across panel/RCS, survey weighting, protocol loss, sanitized errors, and failed-refit cleanup. Runtime tests could not be executed because pytest/NumPy are unavailable; changed Python files passed AST parsing, the notebook passed JSON parsing, and the changelog-fragment checker passed. |
Mirror of third-party PR #816 (fixes #814) so the label-gated CI and the CI AI reviewer can run on the contributor's change. The contributor's two commits are carried verbatim; one maintainer commit on top narrows a documentation claim. Do not merge this PR on its own - findings feed back to #816.
Summary
deepcopyfails or returns the original object at configuration time, before any group-time cell is fitted (contributor commit 9cd5649).cross_fit_predictcallers; a per-fold clone failure propagates as a sanitizedTypeError, never a NaN-cell skip; a failed re-fit clears prior fitted state; fold clones are re-validated for the learner protocol and, on declared survey fits,sample_weightsupport (contributor commit bb187a3).Methodology references (required if estimator / math changes)
_crossfit.py,_learners.py,dml_did.py)Validation
tests/test_crossfit.py,tests/test_dml_did.py(copy failure, self-returning__deepcopy__, clone protocol loss, weighted clone loss, panel/RCS hard-error propagation, re-fit state clearing, survey preflight, sanitized traceback, sklearn preflight viaimportorskip)Security / privacy
token=SECRET-...strings in the new tests are fake sentinels asserting that foreign exception text is withheld)Changelog
changelog.d/20260903-dml-crossfit-learner-isolation.md)