Skip to content

Commit ef6b53d

Browse files
igerberclaude
andcommitted
Address PR #356 CI review round 16 (1 P1 guide)
Rebased onto current main (17 commits clean — PR #355, #358, #359 all merged since last rebase). StaggeredTripleDifference corrected as panel-only + balance-enforced. The earlier §4.10 RCS wording paired TripleDifference / StaggeredTripleDifference together in the Explicit RCS support list, but REGISTRY.md §StaggeredTripleDifference requires a balanced panel and staggered_triple_diff.py:93-109 has no panel=False mode — fit() rejects unbalanced/duplicate (unit, time) structure at staggered_triple_diff.py:846-864. - §4.10 Explicit RCS support: TripleDifference (two-period) only; StaggeredTripleDifference removed from the supported set. - §4.10 Explicitly rejected for RCS: StaggeredTripleDifference added with a concrete "no panel=False mode" + "use TripleDifference for cross-sectional DDD" pointer. - §3 Balanced-panel eligibility: StaggeredTripleDifference added to the balance-sensitive gate. Regression tests extended: - Balanced-panel proximity check now covers StaggeredTripleDifference. - §4.10 section test asserts StaggeredTripleDifference appears in the Explicitly rejected block and NOT in the Explicit RCS support block. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 9d5f8f9 commit ef6b53d

2 files changed

Lines changed: 33 additions & 6 deletions

File tree

diff_diff/guides/llms-autonomous.txt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ supported / out of scope; `warn` supported but with documented caveats;
277277
**Balanced-panel eligibility.** The following estimators require
278278
exactly one observation per `(unit, time)` cell with every unit
279279
observed in every period: `ContinuousDiD`, `EfficientDiD`,
280-
`SyntheticDiD`, `HeterogeneousAdoptionDiD`. Gate these on BOTH
280+
`SyntheticDiD`, `HeterogeneousAdoptionDiD`,
281+
`StaggeredTripleDifference`. Gate these on BOTH
281282
`PanelProfile.is_balanced == True` AND the absence of the
282283
`duplicate_unit_time_rows` alert (`is_balanced` is computed from the
283284
unique-key support and stays `True` when duplicates exist; the
@@ -510,10 +511,11 @@ Explicit RCS support in this library:
510511

511512
- `CallawaySantAnna(panel=False)` - repeated-cross-section mode per
512513
REGISTRY.md §CallawaySantAnna; use this variant on RCS data.
513-
- `TripleDifference` / `StaggeredTripleDifference` - DDD cross-sectional
514-
use cases are documented in `docs/choosing_estimator.rst`; the DDD
515-
estimators do not require within-unit tracking when the third
516-
comparison axis carries the identification.
514+
- `TripleDifference` - DDD cross-sectional use cases are documented
515+
in `docs/choosing_estimator.rst`; the two-period DDD estimator does
516+
not require within-unit tracking when the third comparison axis
517+
carries the identification. The staggered DDD variant is panel-only
518+
and listed separately below.
517519

518520
Explicitly rejected for RCS (panel-only):
519521

@@ -524,6 +526,10 @@ Explicitly rejected for RCS (panel-only):
524526
- `SyntheticDiD` - requires balanced panel with per-unit donor matching.
525527
- `ContinuousDiD` - requires balanced panel with per-unit constant
526528
dose.
529+
- `StaggeredTripleDifference` - panel-only; `fit()` has no
530+
`panel=False` mode and rejects duplicate / unbalanced
531+
`(unit, time)` structure. For cross-sectional DDD data use
532+
`TripleDifference` instead.
527533

528534
Treat other estimators in this guide as panel-only unless their own
529535
docs explicitly say otherwise. When routing, also:

tests/test_profile_panel.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ def test_guide_api_strings_resolve_against_public_api():
676676
"EfficientDiD",
677677
"SyntheticDiD",
678678
"HeterogeneousAdoptionDiD",
679+
"StaggeredTripleDifference",
679680
):
680681
idx = 0
681682
found = False
@@ -763,12 +764,32 @@ def test_guide_api_strings_resolve_against_public_api():
763764
rcs_section_start = text.find("§4.10 Repeated cross-sections")
764765
assert rcs_section_start >= 0
765766
rcs_section = text[rcs_section_start : rcs_section_start + 2500]
766-
for panel_only in ("EfficientDiD", "HeterogeneousAdoptionDiD"):
767+
for panel_only in (
768+
"EfficientDiD",
769+
"HeterogeneousAdoptionDiD",
770+
"StaggeredTripleDifference",
771+
):
767772
assert panel_only in rcs_section, (
768773
f"§4.10 must explicitly name {panel_only!r} as panel-only "
769774
"so RCS data is not routed to it"
770775
)
771776

777+
# The explicit RCS-capable bullet list must NOT put
778+
# StaggeredTripleDifference next to the RCS-support language.
779+
# The estimator has no panel=False mode and fit() rejects
780+
# unbalanced input; only TripleDifference (non-staggered) is
781+
# cross-sectional-DDD-capable.
782+
explicit_support_block = text.find("Explicit RCS support", rcs_section_start)
783+
rejected_block = text.find("Explicitly rejected for RCS", rcs_section_start)
784+
assert 0 <= explicit_support_block < rejected_block, (
785+
"§4.10 must separate an Explicit RCS support list from the " "Explicitly rejected list"
786+
)
787+
explicit_segment = text[explicit_support_block:rejected_block]
788+
assert "StaggeredTripleDifference" not in explicit_segment, (
789+
"StaggeredTripleDifference must NOT appear in the Explicit RCS "
790+
"support list — it is panel-only and balance-enforced."
791+
)
792+
772793

773794
def test_min_pre_post_use_per_unit_observed_support():
774795
"""On an unbalanced panel where one treated unit is missing its

0 commit comments

Comments
 (0)