Skip to content

marketing: DMLDiD launch carousel (Circuit palette) + claims-sync guard - #802

Merged
igerber merged 5 commits into
mainfrom
dml-carousel
Aug 29, 2026
Merged

marketing: DMLDiD launch carousel (Circuit palette) + claims-sync guard#802
igerber merged 5 commits into
mainfrom
dml-carousel

Conversation

@igerber

@igerber igerber commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Summary

  • LinkedIn launch carousel for the v3.11 DMLDiD estimator: carousel/generate_dml_carousel.py + committed carousel/diff-diff-dml-carousel.pdf (11 slides, poster mode, "Circuit" palette — graphite structure with a single signal-green ML/truth accent).
  • ML-forward narrative spine: cover ("Plug any ML model into your DiD", curve-vs-line motif), the confidently-wrong receipt (linear 2.5909, reported SE 0.0743, vs true 2.2388 — nominal-inference caveats slide-local), dark ridge twist, Chang (2020) paper slide, annotated Case-1 score slide (the uncentered summand s labeled as such with psi = s - ATT in the caption; orthogonality scoped to the learned nuisances g and ℓ; annotation arrows pixel-anchored via manual fraction composition), four-learner payoff chart with the double-robustness beat, honest DMLDiD-vs-CS decision split plus the learner-flexibility band (four built-ins, no extra installs; scikit-learn estimators fit the duck-typed contract), dark code slide with a real sklearn swap line, production grid with the DoubleML Case-1 parity strip and the A2.3 same-target-population qualifier on the RCS card, CTA.
  • tests/test_dml_carousel_claims.py (17 checks): every deck estimate located on the committed tutorial-32 notebook surface (row-associated learner-table pins), arithmetic backing for the five-SE and recovery claims, constants-reach-their-slides + qualifier slide-locality enforcement, a banned-absolutes/overclaims list, REGISTRY sync for the DoubleML figure, a dependency-free proof for the built-in-learner claim, and the documented-sklearn-contract check.
  • No verbatim pull quote: the Chang paper review is pinned to the arXiv layout and the published PDF was not cross-checked word-for-word, so the paper slide carries an attributed paraphrase (recorded in the generator docstring; a no-typographic-quotes test enforces it).

Methodology references (required if estimator / math changes)

  • Method name(s): N/A — no estimator/math changes (marketing collateral + claim tests only). Slide copy follows the REGISTRY DMLDiD section (Chang 2020) and the DR-score families note.
  • Paper / source link(s): Chang (2020), The Econometrics Journal 23(2), https://doi.org/10.1093/ectj/utaa001.
  • Any intentional deviations from the source (and why): None — the deck flags its own demo's deliberate deviation on-slide (misspecified propensity ⇒ reported SEs labeled nominal/illustrative) and labels staggered cells + survey lanes as documented library extensions.

Validation

  • Tests added/updated: tests/test_dml_carousel_claims.py (new, 17 checks, green).
  • Backtest / simulation / notebook evidence (if applicable): every number on the deck is a seed-locked tutorial-32 value (simulated example, truth known by construction, said on-slide); all 11 pages visually verified at pixel zoom; PDF regenerated from the committed generator in the same commit.

Security / privacy

  • Confirm no secrets/PII in this PR: Yes

11-slide poster-mode deck for the v3.11 DMLDiD launch (ML-forward hook;
user decisions 2026-08-29): cover curve-vs-line motif, the
confidently-wrong receipt (linear 2.5909, reported SE 0.0743, vs true
2.2388 - nominal-inference caveats slide-local), dark ridge twist,
Chang (2020) paper slide (attributed paraphrase, no verbatim pull quote
- the published PDF was not cross-checked word-for-word), annotated
Case-1 score slide (the UNCENTERED summand s labeled as such, centered
score psi = s - ATT in the caption, orthogonality scoped to the learned
nuisances g and l, arrows pixel-anchored via manual fraction
composition - mathtext bboxes carry asymmetric slop), four-learner
payoff chart with the double-robustness beat, honest DMLDiD-vs-CS
decision split plus the learner-flexibility band (four built-ins with
no extra installs; scikit-learn estimators fit the duck-typed
fit()/predict() contract), dark code slide with a real sklearn swap
line, production grid (aggregation/HonestDiD/sup-t, survey + clustering
with the A2.3 same-target-population qualifier on the RCS card,
diagnostics) with the DoubleML Case-1 parity strip (ATT diff 4.4e-16,
committed spike), CTA with the single tutorial-32 mention.

Every estimate is a seed-locked tutorial-32 value from the simulated
truth-known example (labeled on-slide).

tests/test_dml_carousel_claims.py (17 checks): notebook-surface sync
with row-associated learner-table pins, arithmetic backing for the
five-SE and recovery claims, constants-reach-their-slides + qualifier
slide-locality enforcement, banned-absolutes list (including the
retired overclaims: "in each nuisance", "confident CI"), REGISTRY sync
for the DoubleML figure, dependency-free proof for the
built-in-learner claim, and the documented-sklearn-contract check.
@github-actions

Copy link
Copy Markdown

Overall Assessment: ✅ Looks good

Executive Summary

  • No unmitigated P0/P1 findings.
  • Chang Equation 3.1, Theorem 2, and Assumption 2.3 are represented correctly.
  • Prior inference-qualification and extension-scoping concerns are resolved.
  • Two minor claim-test/documentation issues remain.
  • All 17 claim assertions passed manual execution; pytest itself was unavailable.

Methodology

P3 — Documented extensions correctly scoped

  • Impact: None. Staggered cells, survey support, and DoubleML Case-1 parity are accurately limited and labeled (carousel/generate_dml_carousel.py:L1192-L1236). The score and treated-share correction also match the Registry.
  • Concrete fix: None required.

Code Quality

No findings.

Performance

No findings.

Maintainability

No findings.

Tech Debt

P3 — PDF/source drift guard remains deferred

  • Impact: Tests validate generator text but cannot prove the committed PDF matches it.
  • Concrete fix: Already tracked in TODO.md:L97; no PR action required.

Security

No findings.

Documentation/Tests

P2 — Learner contract copy omits predict_proba

  • Impact: Slide 8 says any learner needs fit()/predict(), but propensity learners require fit()/predict_proba(). Some sklearn classifiers would therefore fail immediately (carousel/generate_dml_carousel.py:L1054-L1057, L1110-L1115).
  • Concrete fix: Scope the copy to outcome regressors or state both contracts. Strengthen tests/test_dml_carousel_claims.py:L397-L403 to verify that distinction.

P2 — Cohort synchronization assertion is effectively vacuous

  • Impact: or str(g) in code succeeds because 4 and 5 occur throughout the notebook, so incorrect cohort labels could pass (tests/test_dml_carousel_claims.py:L200-L211).
  • Concrete fix: Assert the exact cohort-construction expression or parse its AST and compare both cohort values.

…onstruction pin

PR #802 review P2s: (1) slide 8 said any learner needs fit()/predict(),
but propensity learners require predict_proba() - the card and the
flexibility band now state both contracts (regressors fit()/predict(),
classifiers predict_proba()), with slide-local pins; (2) the cohort
sync assertion's str(g)-in-code fallback was vacuous (single digits
occur everywhere) - it now requires the exact
np.where(early, 4, 5) construction rendered from the deck constants.
PDF regenerated; claims guard 17/17 green.
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 7880232969cf322d2a305fca7085af74fd580283


Overall Assessment: ⚠️ Needs changes

Executive Summary

  • One P1 remains: the learner-contract correction missed the generator’s module docstring.
  • Slide 8 and the committed 11-page PDF correctly distinguish predict() from predict_proba().
  • The exact cohort-construction guard now resolves the previous vacuous assertion.
  • The score, inference caveats, assumptions, and extension labels agree with Chang (2020) and the Registry.
  • All 17 claim checks were reproduced manually; pytest was unavailable.

Methodology

P3 — Documented extensions are correctly scoped

  • Impact: None. The Case-1 score, treated-share variance correction, RCS population assumption, and staggered/survey extension labels match the Registry (carousel/generate_dml_carousel.py:L485-L533, L949-L979, L1191-L1241).
  • Concrete fix: None required.

Code Quality

No findings.

Performance

No findings.

Maintainability

No additional findings.

Tech Debt

P3 — PDF/source drift guard remains tracked

  • Impact: Claims tests cannot generally prove that a committed PDF matches its generator.
  • Concrete fix: None required for this PR; tracked in TODO.md:L97.

Security

No findings.

Documentation/Tests

P1 [Newly identified] — Learner-contract fix is incomplete

  • Impact: The module docstring still claims generic scikit-learn estimators satisfy a fit()/predict() contract, although propensity classifiers require predict_proba(). Classifiers such as LinearSVC would be rejected. The new guard only examines slide strings and explicitly excludes docstrings (carousel/generate_dml_carousel.py:L59-L62, tests/test_dml_carousel_claims.py:L66-L94, L405-L415).
  • Concrete fix: Update the module docstring to state both regressor and classifier protocols, and add an ast.get_docstring() assertion requiring predict_proba().

Path to Approval

  1. Correct carousel/generate_dml_carousel.py:L59-L62 and extend the claim test to cover that module-docstring contract.

…t docstring guard

PR #802 review round 2 P1: the slide fix missed the module docstring,
which still described a bare fit()/predict() scikit-learn contract -
propensity classifiers need predict_proba() (a LinearSVC would be
rejected). The spine bullet and claim-discipline bullet now state both
contracts, and a new ast.get_docstring test requires predict_proba()
there (the slide-string guard deliberately excludes docstrings, so the
docstring needs its own pin). PDF regenerated (byte-freshness only;
slide content unchanged); claims guard 18/18 green.
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 6521075c1e8415aebe4f6d2886ffc6186aa11df2


Overall Assessment: ✅ Looks good

Executive Summary

  • The prior P1 is resolved: both learner protocols are now documented and AST-tested.
  • Mathematical, variance, assumption, and extension claims match Chang (2020) and the Methodology Registry.
  • One P2 remains: slide 9 presents a syntactically invalid Python call.
  • All 18 claim assertions passed manual execution; pytest and carousel-generation dependencies were unavailable.
  • PDF/source drift remains tracked in TODO.md.

Methodology

P3 — Documented extensions are correctly scoped

  • Impact: None. The Case-1 score, treated-share variance correction, nominal-inference caveats, Case-2 population assumption, DoubleML scope, and staggered/survey extensions agree with docs/methodology/REGISTRY.md:L2789-L3160.
  • Concrete fix: None required.

Code Quality

No findings.

Performance

No findings.

Maintainability

No findings.

Tech Debt

P3 — PDF/source drift guard is tracked

  • Impact: Automated tests cannot prove that a committed PDF matches its generator.
  • Concrete fix: No PR action required; tracked in TODO.md:L97.

Security

No findings.

Documentation/Tests

P2 — Slide 9’s displayed fit call is invalid Python

  • Impact: res = est.fit(df, outcome="y", ..., covariates=...) raises SyntaxError: positional argument follows keyword argument, contradicting the claim that the shown call reproduces the numbers (carousel/generate_dml_carousel.py:L1150-L1176).
  • Concrete fix: Render the actual required unit, time, and first_treat keywords—plus the tutorial’s base_period="universal"—and add an ast.parse() assertion for the reconstructed slide snippet in tests/test_dml_carousel_claims.py:L364-L380.

The previous learner-contract P1 is resolved at carousel/generate_dml_carousel.py:L59-L64 and guarded at tests/test_dml_carousel_claims.py:L405-L423.

…e slide

PR #802 review round 3 P2: the displayed call used a positional
ellipsis after keyword arguments (a SyntaxError) under a caption
claiming the shown call reproduces the shown numbers. The slide now
renders the tutorial's full invocation (unit/time/first_treat keywords
+ base_period=universal) in a slightly wider panel, and a new claims
check reconstructs the snippet from the slide's token lines via AST and
requires it to ast.parse, pinning base_period and the fit keywords.
PDF regenerated; claims guard 19/19 green.
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: e5f0914c22aea61deb6d0b39b77ac3836bbcc8f6


Overall Assessment: ✅ Looks good

Executive Summary

  • The prior slide-9 defect is resolved: the displayed call is valid, complete Python.
  • DMLDiD claims match Chang (2020) and the Methodology Registry.
  • All 19 claim assertions passed manual execution; the PDF contains 11 pages and the corrected snippet.
  • No estimator, weighting, variance, or default behavior changed.

Methodology

P3 — Documented extensions are correctly scoped

  • Impact: None. Staggered and survey support are identified as library extensions, while the Case-1 score, treated-share correction, cross-fitting, rate-condition caveats, and RCS population assumption match docs/methodology/REGISTRY.md:L2789-L2865 and L3028-L3048.
  • Concrete fix: None required.

Code Quality

No findings.

Performance

No findings.

Maintainability

No findings.

Tech Debt

P3 — PDF/source drift guard remains tracked

  • Impact: Tests cannot automatically prove byte-level generator/PDF synchronization.
  • Concrete fix: No PR action required; tracked in TODO.md:L97.

Security

No findings.

Documentation/Tests

P3 — Prior slide-9 finding resolved

  • Impact: The code now includes base_period, unit, time, and first_treat, and parses successfully (carousel/generate_dml_carousel.py:L1139-L1169).
  • Concrete fix: None. The regression test reconstructs and parses the snippet at tests/test_dml_carousel_claims.py:L431-L477.

The environment lacked pytest and carousel-generation dependencies; all 19 test bodies were executed manually without failures.

@igerber igerber added the ready-for-ci Triggers CI test workflows label Aug 29, 2026
…outs

CI failure on every Python leg: test_module_docstring_states_both_contracts
read the generator without the GENERATOR.exists() guard the rest of the
file carries, and the isolated-install CI jobs copy only tests/ (no
carousel/). Verified both layouts: full checkout 19 passed; a simulated
tests-only layout 19 skipped.
@github-actions

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 4c65419453c9328b05c4445b053a0f4dd16f9899


Overall Assessment: ✅ Looks good

Executive Summary

  • No P0/P1 findings; estimator behavior is unchanged.
  • DMLDiD equations and assumptions match Chang (2020) and the Methodology Registry.
  • Prior slide-9 syntax issue is resolved.
  • All 19 claim checks passed manual execution; PDF contains 11 pages.
  • One minor CTA provenance overstatement remains.

Methodology

P3 — Documented extensions correctly scoped

  • Impact: None. The Case-1 score matches Chang Eq. 3.1, while staggered and survey support are labeled as documented library extensions (carousel/generate_dml_carousel.py:L936-L984, L1239-L1254).
  • Concrete fix: None required.

Code Quality

No findings.

Performance

No findings.

Maintainability

No findings.

Tech Debt

P3 — PDF/source drift guard remains tracked

  • Impact: Automated tests do not prove that the committed PDF was regenerated from the current source.
  • Concrete fix: No PR action required; tracked in TODO.md:L97.

Security

No findings. No apparent secrets or unsafe file handling were introduced.

Documentation/Tests

P2 — CTA overstates Tutorial 32’s provenance

  • Impact: The CTA claims Tutorial 32 reproduces “every number,” but the 4.4e-16 DoubleML figure comes from the separate Registry parity spike, not the notebook (carousel/generate_dml_carousel.py:L1239-L1254, L1280-L1289).
  • Concrete fix: Replace “every number” with “the tutorial examples” and add a regression assertion for the narrowed wording.

P3 — Prior slide-9 finding resolved

  • Impact: None. The displayed fit call is valid Python and includes all required arguments.
  • Concrete fix: None; covered by tests/test_dml_carousel_claims.py:L431-L477.

@igerber
igerber merged commit aaec858 into main Aug 29, 2026
26 checks passed
@igerber
igerber deleted the dml-carousel branch August 29, 2026 20:18
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