Skip to content

test(v4): naming-completeness guard - section-8 surface sweep, section-9 phase-table agreement, rule-11 consumer coverage - #740

Merged
igerber merged 2 commits into
mainfrom
feat/naming-guard
Aug 1, 2026
Merged

test(v4): naming-completeness guard - section-8 surface sweep, section-9 phase-table agreement, rule-11 consumer coverage#740
igerber merged 2 commits into
mainfrom
feat/naming-guard

Conversation

@igerber

@igerber igerber commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • New tests/test_naming_guard.py (~1,150 lines incl. self-tests): mechanical enforcement of the three v4-program naming invariants that were previously prose-only, per the amended TODO.md guard-row spec (now carried in the module docstring). Sequenced as item 2 of v4-design §9's "Remaining 3.9 sequence" - lands BEFORE the 2(c) rename sweep so that PR works from a mechanically-verified list.
  • Duty A - public-surface sweep: every diff_diff.__all__ export's signatures (all public methods, custom dataclass __init__ extras), dataclass fields and property names checked against the §8 rename vocabulary; each hit must be a ledger row, structurally exempt (wrapper functions / dying classes), or allowlisted with a stated reason. First run: 0 unrowed violations, 49 documented carve-outs (CS-cohort groups family, rule-1 canonical calendar time surfaces, rank_control_units[lambda_reg]). A binding self-test forces every param/field rename token - lifecycle-gated rows included - into the sweep predicate.
  • Duty B - phase-table agreement between the ledger and v4-design §9 in both directions: bracketed-only citation expansion (all three citation forms; bare prose ids like M-031's are not citations), the ship-version predicate with the decision_due channel for env-default rows (M-008 positive / M-031 negative named fixtures), terminal-row exemption, and a cross-check of the phase→version map against the table's Ships-in column.
  • Duty C - rule-11 consumer coverage over diff_diff/ source, the packaged guides/*.txt, and docs/methodology/, with lanes tiered by row kind and token ambiguity: regex lanes + qualified docs forms for distinctive tokens; callee-aware AST call-site matching (incl. super().__init__ delegation and exported subclasses sharing the effective constructor) plus getattr/hasattr/.get literal state reads for ambiguous tokens; bare-call text+AST lanes for function rows (docstring examples included, wrapper bodies exempt). Coverage = the token family's code_refs union or a reasoned allowlist entry; a reachability test kills dead entries on both allowlists. A version-aware lifecycle gate re-arms deferred rows at each release bump, and terminal rows stay enforced with their historical code_refs discounted.
  • docs/v4-deprecations.yaml: 30 rows' code_refs completed with guard-confirmed readers (diagnostics.py fit(time=...) sites on M-030, sun_abraham.py's robust=True legacy alias on M-115, synthetic_did.py's super().__init__(robust=True) on M-045, diagnostic_report.py's bare bacon_decompose(...) call + docstring/guidance readers on M-076, REGISTRY/guides readers across the cohort/controls/clean_control/aggregation/treatment_col/wrapper families, record-anyway entries on the gated M-016/M-050 families and the old==new-skipped M-020 family).
  • docs/v4-design.md: §8 rule 11 gains the token-family code_refs-union clause; the §8 carve-out paragraph adds plot_group_effects' cohort selector; §9 sequence item 2 and 3.9-cut checklist item 4 now point at the test file. TODO.md's completed guard row is removed.
  • .github/workflows/docs-tests.yml: trigger paths + a dedicated step so docs-only ledger/spec edits cannot bypass the guard (the file also runs in the label-gated main suite). CHANGELOG entry included.

Methodology references (required if estimator / math changes)

  • Method name(s): N/A - no methodology changes (naming-governance enforcement + ledger code_refs metadata only; docs/methodology/ paths are recorded as rename-consumer references, their content is untouched)
  • Paper / source link(s): N/A
  • Any intentional deviations from the source (and why): None

Validation

  • Tests added/updated: tests/test_naming_guard.py (20 tests: 9 guard tests + 11 parser/matcher/resolver/gate self-tests on synthetic fixtures). pytest tests/test_naming_guard.py tests/test_v4_matrix.py: 258 passed, 17 skipped - the ledger edits keep the whole matrix enforcement suite green.
  • Backtest / simulation / notebook evidence (if applicable): N/A

Security / privacy

  • Confirm no secrets/PII in this PR: Yes

…eement + consumer coverage (closes the TODO guard row)

tests/test_naming_guard.py enforces the three v4-program naming invariants
that were previously prose-only (spec in the module docstring, replacing the
TODO.md row):

(A) Public-surface sweep - every __all__ export's signatures, dataclass
fields (custom-__init__ extras included) and property names checked against
the section-8 rename vocabulary; every hit must be a ledger row,
structurally exempt (wrapper functions / dying classes), or allowlisted with
a stated reason. First run: 0 unrowed violations; 49 documented carve-outs
(the CS-cohort groups family, rule-1 canonical calendar time surfaces,
rank_control_units' own lambda_reg). A binding self-test forces every
param/field rename token - gated rows included - into the sweep predicate.

(B) Ledger<->section-9 phase-table agreement in both directions: bracketed
citation expansion (single tokens, compound brackets with ranges/comma
elements/trailing prose, endpoint-bracket ranges; bare prose ids are NOT
citations), the ship-version predicate with the decision_due channel for
env-default rows, M-008 positive / M-031 negative fixtures, terminal-row
exemption, and a cross-check of the hardcoded map against the table's
Ships-in column.

(C) Rule-11 consumer coverage over diff_diff/ source, the packaged
guides/*.txt, and docs/methodology/, tiered by row kind and token ambiguity:
regex lanes (quoted/kwarg/attr/backtick + qualified docs forms) for
distinctive tokens; AST call-site matching (callee-aware, including
super().__init__ delegation and exported subclasses sharing the effective
constructor) plus getattr/hasattr/.get literal state reads for ambiguous
tokens like time/group/robust; bare-call text+AST lanes for function rows
(docstring examples included, wrapper bodies exempt). Coverage = the token
family's code_refs UNION (rule 11's new token-family clause) or a reasoned
allowlist entry; both allowlists carry a reachability test that kills dead
entries. A version-aware lifecycle gate keyed on __version__ re-arms
deferred rows (M-050..M-058, M-016) at each release bump, and terminal rows
stay enforced with their own historical code_refs discounted. Accepted
limitations (dict/**kwargs indirection, ambiguous attr/dict-key reads) are
documented with their measured noise rationale. Parser/matcher/resolver/
gate self-tests run on synthetic fixtures.

The guard's first run completed 30 rows' code_refs with newly confirmed
readers: diagnostics.py's seven fit(time=...) call sites (M-030),
sun_abraham.py's robust=True legacy alias (M-115), synthetic_did.py's
super().__init__(robust=True) (M-045), diagnostic_report.py's bare
bacon_decompose(...) call and _diagnostic.py's docstring example plus
twfe.py's guidance string (M-076), REGISTRY's treatment_col / cohort /
controls / robust / clean_control / synthetic_control() / dCDH
results.groups references, the packaged-guide readers (cohort= ETWFE
examples, aggregation=, wrapper calls, clean_control, placebo_effects,
first_treat_col), and record-anyway entries on the lifecycle-gated
M-016/M-050 families and the old==new-skipped M-020 family.

docs/v4-design.md: rule 11 gains the token-family code_refs-union clause
(decided 2026-08-01 over per-row duplication); the section-8 carve-out
paragraph adds plot_group_effects' cohort selector; section-9 sequence item
2 and 3.9-cut checklist item 4 now point at the test file. TODO.md's
completed guard row is removed. Wired into docs-tests.yml (trigger paths +
step) so docs-only ledger/spec edits cannot bypass enforcement.
@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

Overall assessment

Looks good — no P0 or P1 findings.

Executive summary

  • No estimator, weighting, variance, inference, assumptions, or defaults changed.
  • Ledger and phase-table metadata currently agree.
  • Consumer guard and workflow coverage match the stated naming-governance scope.
  • One P3 documentation imprecision noted below.
  • Tests could not be executed locally because pytest/numpy are unavailable; static validation found no failures.

Methodology

No findings. The Methodology Registry content is unchanged; additions only reference existing methodology documents as rename consumers.

Code Quality

No findings.

Performance

No findings. The guard caches file contents and parsed ASTs.

Maintainability

No findings. Parser and matcher behavior has focused synthetic regression coverage.

Tech Debt

No findings. Removing the completed TODO.md row is justified by the new enforced guard.

Security

No findings. No secrets, unsafe execution, or permission changes were introduced.

Documentation/Tests

  • Severity: P3 — Informational
    • Impact: The accepted-limitation prose says only phases 2 and 3 share version 3.9, while _SHIP_VERSION also maps phase 4 to 3.9. Cross-phase miscitation among any of phases 2–4 is therefore indistinguishable by the lifecycle-version predicate. Current table data is consistent.
    • Location: tests/test_naming_guard.py:L33-L35, tests/test_naming_guard.py:L101-L106
    • Concrete fix: Optionally change the prose to “phases 2, 3, and 4 share ship version 3.9.”

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown

🔁 AI review rerun (requested by @igerber)

Head SHA: 4cedd01ab89a65eb1019154c1bd24a161cd35163


Overall assessment

Looks good — no unmitigated P0 or P1 findings.

Executive summary

  • The previous P3 wording issue is fixed: phases 2, 3, and 4 are correctly identified as shipping in 3.9.
  • No estimator, inference, assumptions, weighting, variance, or defaults changed.
  • Phase-table agreement and all 114 live ledger references pass static validation.
  • All added code_refs resolve to existing files.
  • Runtime tests could not run because the environment lacks pytest and scientific dependencies; Python syntax checks passed.

Methodology

No findings. Methodology files are referenced only as naming consumers; their contents and estimator behavior are unchanged.

Code Quality

No findings.

Performance

No findings.

Maintainability

No findings. The guard includes focused parser, matcher, lifecycle, and terminal-row self-tests.

Tech Debt

No findings. Removing the completed TODO entry is consistent with the implemented guard.

Security

No findings.

Documentation/Tests

No findings. The previous accepted-limitation wording is corrected at tests/test_naming_guard.py:L30-L31.

@igerber igerber added the ready-for-ci Triggers CI test workflows label Aug 1, 2026
@igerber
igerber merged commit ff05328 into main Aug 1, 2026
35 of 36 checks passed
@igerber
igerber deleted the feat/naming-guard branch August 1, 2026 17:11
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