Repository navigation
docs(v4): 4.0-cut framing - cut-window gate, ledger/spec refresh, M-080 re-scope - #854
Merged
Merged
Conversation
…80 re-scope First PR of the 4.0 cut (at v3.13.0). Re-syncs docs/v4-design.md and the deprecation ledger with the library as shipped since 3.9, and makes the enforcement gate admit an incremental removal program. - Ledger header declares the cut window (cut_window "4.0", cut_base "3.13.0"); tests/test_v4_matrix.py parses it, relaxes only the early-removal guard for 4.0-scheduled rows, refuses any other version bump while early-terminal rows exist, and keeps due enforcement unchanged (new parametrized cut-window and header-parser tests). - M-008 (DIFF_DIFF_SOLVE_OLS_FASTPATH default) decided: evaluated, kept off. - M-080 (auto-cluster policy) re-scoped to the measured roster: static TWFE already auto-clusters; SpilloverDiD is the one default that moves; cluster=False becomes the explicit off-switch where clustering is a choice (no-op on by-construction estimators, rejected by StackedDiD); by-construction estimators keep no auto-cluster metadata (variance-conventions roster + REGISTRY Notes on SpilloverDiD/StackedDiD/ ImputationDiD/TwoStageDiD/DMLDiD/DurationDiD). - New row M-150 (WooldridgeDiDResults.to_dataframe level "event", twin of M-136); M-091/M-050/M-045/M-115 code_refs and notes amended; id snapshot and ROW_COUNT_FLOOR repaired to include M-148/M-149 (132 rows). - Spec: roster 27 -> 24 (LWDiD/DMLDiD/DurationDiD), diagnostic-family additions, section 9 "4.0 cut sequence" (storage flip before the DDD container unification), section 11 cut-window rule. - Migration guide: M-150 appendix row, M-080 row/orientation/inference bullet rewritten, "Estimators added after 3.9" paragraph, M-008 decided. - Naming-guard M-008 fixture becomes the terminal-exempt fixture.
Overall assessment: ✅ Looks goodNo unmitigated P0/P1 findings. Executive summary
Methodology
Code QualityNo findings. The parser reports malformed headers, and the gate retains enforcement outside the declared cut window. PerformanceNo findings. No estimator execution paths change. MaintainabilityNo findings. The M-150 locator, immutable ID snapshot, migration appendix, and phase-table references agree. Tech Debt
SecurityNo findings in the changed code or documentation. Documentation/TestsNo findings requiring changes. The changelog fragment follows the repository convention. Validation confirmed 132 schema-valid ledger rows, exact coverage of 111 migration appendix rows, reference existence, and the reported release-gate counts. All changed Python files compiled successfully in memory. Full pytest integration remains unverified in this environment. |
This was referenced Oct 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
docs/v4-design.mdand the deprecation ledger with the library as shipped since 3.9 and makes the enforcement gate admit an incremental removal program. No estimator behaviour changes; the twodiff_diff/edits are docstrings.cut_window: "4.0"/cut_base: "3.13.0".tests/test_v4_matrix.pyparses the header (half-declared or malformed headers fail a dedicated test), relaxes ONLY the early-removal guard for rows scheduled at 4.0, refuses any other version bump while early-terminal rows exist (minor and patch cases pinned), and keeps due enforcement unchanged (the "window does not hide overdue" case).__version__stays 3.13.0 until the release PR; 3.13.x patches come from amaint/3.13branch cut atv3.13.0before this merges (spec section 2).DIFF_DIFF_SOLVE_OLS_FASTPATHdefault) flipped todone,decided_default: off: evaluated, kept off (no soak telemetry ever existed). Naming-guard fixture becomes the terminal-exempt fixture.TwoWayFixedEffectsalready auto-clusters at unit, so the row's premise was stale.SpilloverDiDis the one estimator whose default SE moves at 4.0;cluster=Falsebecomes the explicit off-switch where clustering is a choice (accepted no-op on by-construction estimators and ImputationDiD/TwoStageDiD, rejected by StackedDiD); by-construction estimators keep no auto-cluster metadata by decision. New "Default clustering roster" section indocs/methodology/variance-conventions.md; REGISTRY**Note:**lines on SpilloverDiD, StackedDiD, ImputationDiD, TwoStageDiD, DMLDiD (edited in place), DurationDiD.WooldridgeDiDResults.to_dataframe(level="event")gets its own locator (twin of M-136; it previously rode M-086's notes). M-091 roster records the four later-bornDiagnosticcontainers; M-050code_refsrecord thatdiff_diff/_deprecation.pysurvives 4.0 as 5.0-window infrastructure; M-045/M-115 name the legacy-CR1 remap branches their removal deletes. The id snapshot andROW_COUNT_FLOORnow include M-148/M-149 (shipped by [Bug]: SyntheticControl's Frank-Wolfe stops on its budget at the default inner_max_iter; in_space_placebo() then fails closed or drops placebos on 33-40 of 40 panels #838 without extending them) and M-150: 132 rows.Methodology references (required if estimator / math changes)
diff_diff/;docs/methodology/edits record clustering-policy decisions, no equations change)cluster=Falsesemantics per estimator are recorded as REGISTRY**Note:**decisions (SpilloverDiD, StackedDiD, ImputationDiD, TwoStageDiD, DMLDiD, DurationDiD).Validation
tests/test_v4_matrix.py(header parser,test_cut_window_semanticsx9,test_parse_header_casesx6, header well-formedness and cut-window declaration tests, snapshot 132),tests/test_naming_guard.py(M-008 terminal-exempt fixture). Verified:collect_due_problemsat 3.13.0 / 3.14.0 / 4.0.0 reports 0 / 1 / 118 problems (109 distinct ids) with the window declared.cluster="unit"SEs per estimator) and is tabulated indocs/methodology/variance-conventions.md.Security / privacy
Changelog
changelog.d/20261018-v4-cut-framing.md