Skip to content

feat(v4): mechanical rename wave - canonical names with 3.9 FutureWarning shims (2(c)-ii PR-A, 32 rows) - #742

Merged
igerber merged 5 commits into
mainfrom
feat/v4-rename-mechanical
Aug 2, 2026
Merged

feat(v4): mechanical rename wave - canonical names with 3.9 FutureWarning shims (2(c)-ii PR-A, 32 rows)#742
igerber merged 5 commits into
mainfrom
feat/v4-rename-mechanical

Conversation

@igerber

@igerber igerber commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Summary

  • First of the two 2(c)-ii rename-sweep PRs (v4-design §9 item 4, the mechanical wave): flips 32 ledger rows plannedshimmed — [M-032], [M-033]/[M-034], [M-035]..[M-042], [M-088]/[M-089], [M-094], [M-097]..[M-113], [M-114] — introducing the canonical names with 3.9 FutureWarning shims (removal in 4.0).
  • New underscore-leaf module diff_diff/_deprecation.py: _NotSupplied sentinel, resolve_renamed_kwarg (single warning with the uniform migration message; both-spellings ValueError), require_arg (restored missing-argument TypeError naming the NEW param), deprecated_field_property (renamed-results-field alias).
  • Renames: WooldridgeDiD.fit(cohort→first_treat); ChaisemartinDHaultfoeuille.fit(group→unit, controls→covariates) + twowayfeweights(group→unit) + results field groups→units (alias property, __setstate__ pickle migration, n_units=/"Units (post-filter):" labels); HAD fit + the three pretest functions (*_col → bare names, 20 rows); RegressionDiscontinuity.fit(outcome_col/running_col/treatment_col → outcome/running/takeup) + results field treatment_col→takeup (alias property, __setstate__, dual-key to_dict window through 3.9); RDPlot.fit (2 rows); trim_weights(weight_col→weights).
  • The NEW name takes the OLD name's signature position (positional callers bind identically); the deprecated path routes to bit-identical results; default constructions and canonical calls are warning-free.
  • Enforcement in the same diff: ledger rows flipped with test_ref: tests/test_v4_rename_mechanical.py (41 behavioral pins), naming-guard rule-1 allowlist entries for the four new time params, ~900 test call sites migrated to canonical names (AST-guided), tutorials 16/19/20/21/22 re-validated via nbmake, guides/rst/README/REGISTRY/paper-review kwarg references updated (llms-full keeps the deprecated tail inside the CI-pinned HAD signature block), CHANGELOG names the full row inventory.

Methodology references (required if estimator / math changes)

  • Method name(s): N/A - pure API renames; no estimand, weighting, comparison-group, variance, or inference change. Every shim resolves the alias into the pre-existing body-local variable before any estimation code runs, and per-surface routing-parity tests pin old-path == new-path numbers.
  • Paper / source link(s): naming rules per docs/v4-design.md §8 (rule 5 no _col suffixes, rule 3 unit vs reserved group, rule 7's non-binary corollary selecting takeup, rule 9 results-field mirrors, rule 10 public-function completeness).
  • Any intentional deviations from the source (and why): None. The n_groups_dropped_* counters, CS-family cohort groups vocabulary, TripleDifference's rule-3 group=, and the removal-bound chaisemartin_dhaultfoeuille() wrapper's own group param are deliberately unchanged per the ledger row notes.

Validation

  • Tests added/updated: new tests/test_v4_rename_mechanical.py (41 pins: warning message/count, canonical + positional silence, both-supplied rejection, sentinel-restored missing-arg errors, bit-exact routing parity, field-alias trio, pickle migration, M-094 dual-key to_dict, dCDH to_dict non-serialization pin); ~30 test files migrated to canonical names and all their suites re-run green, including under -W error::FutureWarning; tests/test_v4_matrix.py + tests/test_naming_guard.py green with the flipped rows.
  • Backtest / simulation / notebook evidence (if applicable): tutorials 16_wooldridge_etwfe, 19_dcdh_marketing_pulse, 20/21/22 HAD executed end-to-end via nbmake (5/5 pass); numbers unchanged (rename-only routing).

Security / privacy

  • Confirm no secrets/PII in this PR: Yes

…th 3.9 FutureWarning shims (2(c)-ii PR-A, 32 ledger rows)

First of the two 2(c)-ii rename-sweep PRs (v4-design section 9 item 4;
mechanical wave). Flips 32 ledger rows planned -> shimmed - M-032,
M-033/M-034, M-035..M-042, M-088/M-089, M-094, M-097..M-113, M-114 - via
the shared sentinel machinery in the new leaf module
diff_diff/_deprecation.py (_NotSupplied sentinel + resolve_renamed_kwarg
+ require_arg + deprecated_field_property; single FutureWarning with the
uniform migration message, both-spellings ValueError, missing-argument
TypeError naming the NEW param).

Renames (old spelling stays through 3.9 as a warning alias; removal in
4.0; the NEW name takes the OLD name's signature position so positional
calls bind identically, and the deprecated path routes to bit-identical
results):

- WooldridgeDiD.fit: cohort= -> first_treat= [M-032].
- ChaisemartinDHaultfoeuille.fit: group= -> unit= [M-033], controls= ->
  covariates= [M-034]; twowayfeweights(): group= -> unit= [M-097]; the
  removal-bound chaisemartin_dhaultfoeuille() wrapper keeps its own
  group param (dies with M-077) but forwards to the canonical name.
- ChaisemartinDHaultfoeuilleResults.groups -> units [M-114]: dataclass
  field renamed, read-only FutureWarning alias property under the old
  name, __setstate__ migration for 3.8-era pickles, repr n_units= and
  summary "Units (post-filter):". to_dict() never serialized the list
  (pinned by test); n_groups_dropped_* counters and CS-family cohort
  "groups" vocabulary are deliberately untouched.
- HeterogeneousAdoptionDiD.fit + joint_pretrends_test +
  joint_homogeneity_test + did_had_pretest_workflow:
  outcome_col/dose_col/time_col/unit_col/first_treat_col -> bare
  outcome/dose/time/unit/first_treat [M-035..M-039, M-098..M-112];
  followers of renamed required params (pre_periods/base_period/
  post_periods; dCDH time/treatment) carry required-sentinels with the
  restored missing-argument errors pinned.
- RegressionDiscontinuity.fit: outcome_col/running_col/treatment_col ->
  outcome/running/takeup [M-040..M-042] (takeup per section 8 rule 7's
  non-binary corollary); RegressionDiscontinuityResults.treatment_col ->
  takeup [M-094] with alias property, __setstate__, and a dual-key
  to_dict window ("takeup" + deprecated "treatment_col" through 3.9).
  RDPlot.fit: outcome_col/running_col -> outcome/running [M-088/M-089].
- trim_weights(): weight_col= -> weights= [M-113].

Sentinel-carrying params are transitionally annotated Any (mypy zero-
error gate; the 4.0 removal restores narrow annotations). User-facing
validation/guidance strings across had.py, chaisemartin_dhaultfoeuille.py
and the results modules now name the canonical spellings.

Enforcement kept green in the same diff: docs/v4-deprecations.yaml rows
flipped to shimmed/phase 5 with test_ref
tests/test_v4_rename_mechanical.py (41 behavioral pins: per-surface
old-name warning + canonical-silence + routing parity + both-supplied
rejection + field-trio/pickle/dual-key contracts);
tests/test_naming_guard.py gains the four new rule-1 time-surface
allowlist entries (HAD.fit and the three pretest functions).

Bulk migration to canonical names: ~900 call sites across 30 test files
(AST-guided kwarg rewrite; fit-kwargs dict builders and results-attribute
reads swept by hand; TripleDifference's rule-3 group= and the unmerged
third-party LWDiD surface deliberately untouched), tutorials 16/19/20/
21/22 (re-executed via nbmake), guides llms*.txt (llms-full keeps the
deprecated tail listed inside the CI-pinned HAD signature block),
docs rst (incl. both renamed-field autosummary pages), README's one
catalog line, REGISTRY.md kwarg references, and the two paper reviews
with kwarg mentions. CHANGELOG names the full row inventory.
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Overall assessment

Looks good — no unmitigated P0 or P1 findings.

Executive summary

  • The affected ETWFE, dCDH, HAD, RDD, RDPlot, and preprocessing surfaces preserve their existing estimator bodies.
  • No estimand, weighting, comparison-group, variance, SE, inference, or assumption-check changes were found.
  • Positional compatibility, deprecated-keyword routing, result aliases, serialization, and pickle migration are correctly implemented.
  • Existing methodology deviations remain documented in the Methodology Registry and are unaffected.
  • One non-blocking P2 documentation consistency issue remains.

Methodology

Severity: P3 — Informational

Impact: None. Cross-checking the affected Registry entries—dCDH at docs/methodology/REGISTRY.md:L962, ETWFE at L2091, HAD at L3488, RDD at L3835, and RDPlot at L4197—shows terminology-only changes. Canonical arguments are mapped back to the pre-existing body-local variables before estimation, for example:

  • diff_diff/chaisemartin_dhaultfoeuille.py:L1052-L1074
  • diff_diff/had.py:L3088-L3123
  • diff_diff/rdd.py:L784-L814
  • diff_diff/wooldridge.py:L1135-L1145

No new inline inference, NaN guard, variance, or control-group logic was introduced.

Concrete fix: None required.

Code Quality

No findings. The shared sentinel resolver consistently handles explicit None, missing required arguments, conflicting spellings, and warning emission.

Performance

No findings. The shims add only constant-time argument resolution before existing computations.

Maintainability

No findings. Deprecation behavior is centralized in diff_diff/_deprecation.py, while removal versions and test references are recorded in the deprecation ledger.

Tech Debt

No findings. The aliases have an explicit 4.0 removal lifecycle; no new silent correctness limitation is introduced.

Security

No findings. No secrets, unsafe deserialization behavior, or security-sensitive changes were identified.

Documentation/Tests

Canonical-name cleanup is incomplete

Severity: P2

Impact: A public dCDH example still uses deprecated group=, causing a FutureWarning, while several HAD validation messages and helper docstrings direct canonical callers toward deprecated first_treat_col terminology.

Locations:

  • diff_diff/chaisemartin_dhaultfoeuille.py:L718-L727
  • diff_diff/had.py:L1344-L1390
  • diff_diff/had_pretests.py:L2457-L2473

Concrete fix: Change the dCDH example to unit="group" and replace remaining user-facing first_treat_col wording with first_treat while retaining internal variable names as needed. Add a regression assertion that staggered-panel validation messages recommend first_treat=.

The new rename suite otherwise covers warning counts, positional compatibility, conflicting spellings, routing parity, result aliases, dual-key serialization, and pickle migration. Static parsing and a standard-library shim smoke test passed; the full suite could not be executed because this environment lacks pytest and numerical dependencies.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: d31b30c3547bcf12a740d2553eb80fbc7163a8f5


Overall assessment

Looks good — no unmitigated P0 or P1 findings.

Executive summary

  • The previous P2 documentation finding is resolved, including canonical first_treat= validation wording and its regression test.
  • ETWFE, dCDH, HAD/pretests, RDD, RDPlot, and weight trimming retain their existing numerical behavior.
  • Deprecated aliases resolve before estimation; no inference, weighting, variance, identification, or control-group logic changed.
  • Positional compatibility, conflict rejection, serialization, and pickle migration are correctly implemented.
  • One minor canonical-name documentation inconsistency remains.

Methodology

Severity: P3 — Informational

Impact: None. Registry and estimator-body review confirms this is an API-only rename. Existing documented methodological deviations are unchanged, and no new inline inference or NaN inconsistency was introduced.

Concrete fix: None required.

Code Quality

Severity: None

Impact: Alias resolution is consistently centralized, including explicit-None handling, missing required arguments, and conflicting spellings.

Concrete fix: None.

Performance

Severity: None

Impact: Each shim adds only constant-time argument resolution.

Concrete fix: None.

Maintainability

Severity: None

Impact: Deprecation behavior and warning text are centralized in diff_diff/_deprecation.py.

Concrete fix: None.

Tech Debt

Severity: None

Impact: Every alias has a recorded 4.0 removal lifecycle in the deprecation ledger.

Concrete fix: None.

Security

Severity: None

Impact: No secrets, unsafe deserialization, or security-sensitive behavior was introduced.

Concrete fix: None.

Documentation/Tests

Remaining deprecated terminology

Severity: P2

Impact: Two references still steer readers toward deprecated names:

  • docs/methodology/REGISTRY.md:L1118 refers to dCDH results.groups instead of canonical results.units.
  • diff_diff/had_pretests.py:L3835-L3836 documents first_treat_col instead of first_treat.

Both aliases work during 3.9 but emit FutureWarning.

Concrete fix: Replace those references with results.units and first_treat.

The focused pytest suites could not run because pytest and numerical dependencies are unavailable. Static parsing and the standalone deprecation-helper smoke checks passed.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 0ab60b3d3970422e255f87767d2f43fb12d7939a


Overall assessment

Looks good — no unmitigated P0 or P1 findings.

Executive summary

  • Both prior documentation findings are resolved.
  • ETWFE, dCDH, HAD/pretests, RDD/RDPlot, and weight trimming retain their existing numerical methodology.
  • Alias routing, conflict detection, positional compatibility, and result-field migration are consistently implemented.
  • One minor validation-message inconsistency remains.
  • Pytest was unavailable; static compilation and helper smoke checks passed.

Methodology

Severity: P3 — Informational

Impact: None. Canonical parameters are resolved into the existing body-local variables before estimation (diff_diff/chaisemartin_dhaultfoeuille.py:L1052, diff_diff/had.py:L3088, diff_diff/rdd.py:L784, diff_diff/wooldridge.py:L1135). No estimand, weighting, comparison-group, variance, inference, or identification logic changed. Registry deviations remain documented.

Concrete fix: None required.

Code Quality

Severity: P3 — Informational

Impact: The shared helper correctly distinguishes omitted arguments from explicit None, rejects both spellings, and emits one FutureWarning.

Concrete fix: None.

Performance

Severity: P3 — Informational

Impact: Shims add only constant-time argument resolution.

Concrete fix: None.

Maintainability

Severity: P3 — Informational

Impact: Warning behavior and renamed-field aliases are centralized in diff_diff/_deprecation.py.

Concrete fix: None.

Tech Debt

Severity: P3 — Informational

Impact: Every alias has a recorded 4.0 removal lifecycle in docs/v4-deprecations.yaml.

Concrete fix: None.

Security

Severity: P3 — Informational

Impact: No secrets, unsafe deserialization, or security-sensitive changes were found.

Concrete fix: None.

Documentation/Tests

Canonical validation terminology

Severity: P2 — Newly identified

Impact: Invalid-period errors from the renamed HAD pretest APIs still describe the canonical time parameter as time_col (diff_diff/had_pretests.py:L2568, L3523-L3531, L3920-L3928). This is misleading but does not affect computation.

Concrete fix: Replace those user-facing labels with time and add a regression assertion that canonical validation messages exclude time_col.

The prior results.groups and first_treat_col documentation findings are fixed at docs/methodology/REGISTRY.md:L1118 and diff_diff/had_pretests.py:L3835. The focused suite could not execute because pytest is unavailable; all changed Python files compiled, helper smoke checks passed, and the five changed notebooks parse as valid JSON.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: b35b77442366bde00f96012569b2a2e788ba4716


Overall assessment

Looks good — no unmitigated P0 or P1 findings.

Executive summary

  • The previous HAD time_col validation-message finding is resolved with regression coverage.
  • All changes remain API-only renames; estimator formulas, weighting, controls, variance, and inference are unchanged.
  • Alias conflict detection, positional compatibility, optional-None handling, and pickle migration are consistent.
  • Static parsing and deprecation-helper smoke checks passed. Full pytest execution was unavailable because the environment lacks pytest/numpy.

Methodology

Severity: P3 — Informational
Impact: None. The affected ETWFE, dCDH, HAD/pretest, RDD, and RDPlot surfaces match their Registry contracts (docs/methodology/REGISTRY.md:L962, L2091, L3488, L3835, L4197). Renamed arguments are converted back to existing body-local variables before estimation (diff_diff/chaisemartin_dhaultfoeuille.py:L1052, diff_diff/had.py:L3088, diff_diff/rdd.py:L784, diff_diff/wooldridge.py:L1135). No paper-defined operation changed.
Concrete fix: None.

Code Quality

Severity: P3 — Informational
Impact: The shared helper correctly distinguishes omission from explicit None, rejects both spellings, restores required-argument errors, and emits one FutureWarning (diff_diff/_deprecation.py:L80-L141).
Concrete fix: None.

Performance

Severity: P3 — Informational
Impact: Each shim adds only constant-time argument resolution.
Concrete fix: None.

Maintainability

Severity: P3 — Informational
Impact: Warning and renamed-field behavior is centralized; result migrations preserve old pickle state (diff_diff/rdd.py:L292-L306, diff_diff/chaisemartin_dhaultfoeuille_results.py:L686-L701).
Concrete fix: None.

Tech Debt

Severity: P3 — Informational
Impact: Deprecated aliases have an explicit 4.0 removal lifecycle in docs/v4-deprecations.yaml.
Concrete fix: None.

Security

Severity: P3 — Informational
Impact: No secrets, unsafe deserialization behavior, or security-sensitive changes were found.
Concrete fix: None.

Documentation/Tests

Severity: P3 — Informational
Impact: The previous finding is fixed: validation errors now say “the time column” (diff_diff/had_pretests.py:L2568-L2570, L3523-L3532, L3920-L3929), with regression assertions excluding time_col (tests/test_v4_rename_mechanical.py:L677-L692).
Concrete fix: None.

@igerber igerber added the ready-for-ci Triggers CI test workflows label Aug 2, 2026
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: f44a0f90231e84948dd2ef6f8b4bc1d8adbe5d0a


Overall assessment

Looks good — no unmitigated P0 or P1 findings.

Executive summary

  • The previous HAD validation-message finding is resolved with regression coverage.
  • ETWFE, dCDH, HAD/pretests, RDD, and RDPlot changes are API-only; no estimator math, weighting, variance, inference, assumptions, controls, or defaults changed.
  • Positional compatibility, optional None, alias conflicts, serialization, and pickle migration are handled consistently.
  • Static parsing, notebook validation, and deprecation-helper smoke checks passed. Full pytest execution was unavailable because pytest and numerical dependencies are absent.

Methodology

Severity: P3 — Informational
Impact: None. The changes conform to the registered ETWFE, dCDH, HAD, RDD, and RDPlot methods (docs/methodology/REGISTRY.md:L962, L2091, L3488, L3835, L4197). Aliases resolve into the original body-local variables before estimation, leaving estimands and inference unchanged.
Concrete fix: None.

Code Quality

Severity: P3 — Informational
Impact: The shared helper distinguishes omission from explicit None, rejects both spellings, restores canonical missing-argument errors, and emits one warning (diff_diff/_deprecation.py:L80-L141). No new inline inference or partial NaN guards were found.
Concrete fix: None.

Performance

Severity: P3 — Informational
Impact: Each shim adds only constant-time sentinel checks and argument assignment.
Concrete fix: None.

Maintainability

Severity: P3 — Informational
Impact: Warning behavior is centralized, internal delegations use canonical names, and result-field migrations support legacy pickle state (diff_diff/rdd.py:L295-L305, diff_diff/chaisemartin_dhaultfoeuille_results.py:L689-L701).
Concrete fix: None.

Tech Debt

Severity: P3 — Informational
Impact: Every alias has an explicit 4.0 removal lifecycle and behavioral test reference in docs/v4-deprecations.yaml.
Concrete fix: None.

Security

Severity: P3 — Informational
Impact: No secrets, unsafe input handling, or new security-sensitive behavior was found.
Concrete fix: None.

Documentation/Tests

Severity: P3 — Informational
Impact: The prior issue is fixed: HAD errors now describe the canonical time column (diff_diff/had_pretests.py:L3520-L3532), with regression assertions preventing time_col leakage (tests/test_v4_rename_mechanical.py:L677-L692). The final guide pin also checks canonical first_treat (tests/test_profile_panel.py:L741-L754).
Concrete fix: None.

@igerber
igerber merged commit 663065e into main Aug 2, 2026
31 checks passed
@igerber
igerber deleted the feat/v4-rename-mechanical branch August 2, 2026 12:26
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