Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [3.11.0] - 2026-08-29

### Added
- **DMLDiD tutorial notebook** (`docs/tutorials/32_dml_did.ipynb`): authored via the
numbers-locked workflow (companion drift test `tests/test_t32_dml_did_drift.py`).
A staggered panel with engineered nonlinear confounding motivates the estimator:
the misspecified linear outcome learner misses by ~5 SE while the sieve and a
hand-rolled duck-typed `PolynomialRidge` learner recover the truth via double
robustness; also covers cross-fitting diagnostics, event-study/group aggregation,
HonestDiD, bootstrap sup-t bands, the `panel=False` repeated-cross-section lane
with a `SurveyDesign`, and seed semantics.
- **`DMLDiD` survey-design and cluster support (both lanes)**: `fit()` gains
`survey_design=` (pweight-only full-design TSL — weights/strata/PSU/FPC)
and the constructor gains `cluster=` (coarser-than-unit clustering). A
Expand Down
1 change: 0 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ generic sparse-FE, QR+SVD rank-detection redundancy, `check_finite` bypass — m

| Issue | Location | Origin | Effort | Priority |
|-------|----------|--------|--------|----------|
| DMLDiD tutorial notebook (CONTRIBUTING's new-estimator checklist requires a tutorial; deferred to its own PR per the numbers-locked notebook protocol — prototype in scripts, lock numbers, assemble + execute once, register in `docs/tutorials/index.rst` with a toctree short label + group card): staggered DGP with nonlinear covariate confounding, learner comparison (linear/ridge/sieve/sklearn object), post-fit aggregation + HonestDiD via the event-study container, seed/reproducibility note, and a `panel=False` repeated-cross-section example | `docs/tutorials/`, `docs/tutorials/index.rst` | DML PR-B1 | Mid | Medium |
| Replicate Chang (2020) §4's own RCS simulation DGPs (pp. 17-21, "fully specified" per the paper review) as recovery/coverage fixtures for the `DMLDiD(panel=False)` lane — the shipped tests use a library-authored RCS design (documented in the REGISTRY checklist caveat); needs the paper PDF to extract the parameterization | `tests/test_methodology_dml_did.py`, `docs/methodology/papers/chang-2020-review.md` | DML PR-B2 | Mid | Low |
| Optional scheduled end-to-end execution gate for the MMM tutorials (29/30): a cron-only workflow (or extension of `mmm-interop.yml`) that executes both notebooks in isolated exact-pin environments, so a stale/invalid committed posterior cannot stay green indefinitely - today the hybrid posture (deliberate: notebooks execute locally with committed outputs; CI smoke-tests the exporters without sampling; drift tests pin source + committed-output needles) leaves the MCMC claims un-re-executed in CI | `.github/workflows/mmm-interop.yml`, `docs/tutorials/29_mmm_calibration_pymc.ipynb`, `docs/tutorials/30_mmm_calibration_meridian.ipynb` | mmm-interop | Mid | Low |
| Committed `fixest::feols` event-study golden for TWFE `event_study=True` (within + pooled specs, unbalanced + covariate panels, matched CR1 cluster convention, per-period effects + vcov block) - the in-suite gates are shared-core cross-checks (TWFE-within == MPD-absorb, pooled == MPD bit-exact), so a defect common to the shared core would pass; the live-R harness (`benchmarks/R/benchmark_multiperiod.R`, `feols(y ~ treated * time_f \| unit)`) validated the within design in `docs/benchmarks.rst` but is not a committed regression test - follow the `fixest_did_twfe_golden.json` committed-golden pattern (pytest.skip when absent) | `tests/test_fixest_did_twfe_parity.py`, `benchmarks/R/` | 3(a) R2 | Mid | Medium |
Expand Down
4 changes: 3 additions & 1 deletion docs/dev-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ Jupyter kernel (TensorFlow does not support the 3.14 dev environment):

Both use the CI jobs' `diff_diff_dev.pth` shim (the repo root written into
site-packages) instead of `pip install -e .` (the maturin build backend would
demand a Rust build). Committed notebooks stay kernelspec-free; every local
demand a Rust build). Committed notebooks carry either no kernelspec or the
plain `python3` one (10 of 33 carry it; the t31/t32 drift tests pin `python3`
where present) - never a machine-local venv kernel name; every local
execution names the kernel explicitly (`--nbmake-kernel=...` /
`nbconvert --ExecutePreprocessor.kernel_name=...`) - never the default
`python3` kernel. Fragile edge: google-meridian pins an exact `tfp-nightly`
Expand Down
6 changes: 6 additions & 0 deletions docs/doc-deps.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,8 @@ sources:
- path: docs/index.rst
section: "Supported Estimators (one-line catalog row)"
type: user_guide
- path: docs/tutorials/32_dml_did.ipynb
type: tutorial

diff_diff/dml_did_results.py:
drift_risk: low
Expand All @@ -998,6 +1000,8 @@ sources:
section: "DMLDiD"
type: methodology
note: "DMLDiDResults subclasses CallawaySantAnnaResults (kit-based post-fit aggregate(), bootstrap replay); adds learner/fold/cross-fit provenance and the seed/n_bootstrap/bootstrap_weights/cband inference-provenance fields."
- path: docs/tutorials/32_dml_did.ipynb
type: tutorial

# ── TROP (trop group) ──────────────────────────────────────────────

Expand Down Expand Up @@ -1454,6 +1458,8 @@ sources:
section: "Cross-fitting, DR-score, and ridge infrastructure (DML)"
type: methodology
note: "Duck-typed learner protocol (RegressorLearner/ClassifierLearner Protocols, validate_learner, _validate_predictions) + native learners (LinearLearner/RidgeLearner/LogitLearner/SieveLearner) wrapping linalg solvers. Contracts documented in REGISTRY: raw-X-no-intercept input, fit-reset semantics (documented limitation for stateful user learners), identified-columns prediction under rank deficiency."
- path: docs/tutorials/32_dml_did.ipynb
type: tutorial

diff_diff/_dr_scores.py:
drift_risk: low
Expand Down
Loading
Loading