Skip to content

gate: lsp — the override-suppression registry#1

Merged
Antawari merged 2 commits into
mainfrom
gate/lsp
Jun 11, 2026
Merged

gate: lsp — the override-suppression registry#1
Antawari merged 2 commits into
mainfrom
gate/lsp

Conversation

@Antawari

Copy link
Copy Markdown
Contributor

What this gate adds

Substitutability (Liskov) enforcement has two surfaces; only one is new:

  1. Credit-existing — substitutability itself stays the pinned mypy gauge: an override with an incompatible signature is an [override] error under configs/mypy-base.toml (mypy's own note names the Liskov substitution principle), surfacing as a NEW error through mypy | mypy-baseline filter per configs/BASELINE-CONVENTIONS.md. Nothing rebuilt.
  2. Build delta — the override-suppression registry in cf-exemptions: every # type: ignore[override] token in the measured tree must trace to a five-field exemptions.json entry ({file, symbol_or_line, rule override, reason, approver}) or the gate fails UNREGISTERED_SUPPRESSION naming the site. Same mechanism and entry shape as the noqa/nosec families.

Budget

  • 0 unregistered # type: ignore[override] suppressions — every site traces to a reasoned, approved registry entry, or the gate fails.
  • Anchored to measurement, not invented: 4 live sites measured fleet-wide 2026-06-11 (re-verified at review time), to be registered at mount time in their own repos' registries. The count rides the frozen_count ratchet, shrink-only.
  • The kit's own measured tree: 0 sites (self-compliance pinned by TestKitSelfCompliance).
  • Signal-honesty note: the measured fleet is composition-dominant (inheritance depth 3-4 max), so the substitutability signal is honest but weak by construction — the gate's value is keeping it that way.

Control rods

  • Scope rod: only the override code is registry-gated — the one token that silences the substitutability gauge entirely. Other type-ignore codes and bare # type: ignore stay the mypy gauge's jurisdiction (warn_unused_ignores), so the gate isolates exactly one factor and cannot creep.
  • Bypass closure: a multi-code ignore ([override, misc]) is still gated — hiding the token in a code list is the obvious bypass. Tokens inside string literals never trip the gate (comments are read via tokenize, COMMENT tokens only).
  • Loud pass: every covered suppression is printed with its site, entry, and approver — a visible exemption, never a silent one.
  • Ratchet: override entries ride the same shrink-only frozen_count discipline as every other gated family; 1:1 entry coverage (EXEMPTION_ENTRY_OVERLOADED) blocks the collision undercount.

Verification (oracle outputs)

  • Self-run against this repo: cf-exemptions --root . exits 0 (existing S603 entry covered, ratchet 1/1; no override tokens in the measured tree).
  • Full suite: 276 passed. ruff check . clean. mypy src clean (0 errors).
  • Wheel regression (the harsh oracle, per tests/test_packaging.py pattern): wheel built from this branch, installed into a clean venv with no source tree — the unregistered fixture fails exit 1 naming src/mod.py:7; the registered fixture passes exit 0 with the loud entry line.

Do not merge — pending maintainer review.

Antawari and others added 2 commits June 11, 2026 01:53
…ract tests)

Substitutability itself stays the live pinned mypy gauge (credit-existing,
anchored green: an incompatible override is a NEW [override] error through
'mypy | mypy-baseline filter', and the one token that silences it is pinned
as the hole the registry closes). The build delta under test: cf-exemptions
scans the measured tree for '# type: ignore[override]' tokens; every
occurrence must trace to a five-field exemptions.json entry (rule 'override')
or the gate fails UNREGISTERED_SUPPRESSION naming the site; registered sites
pass LOUDLY with the entry and the frozen count printed; the family rides the
same shrink-only frozen_count ratchet and 1:1 entry discipline as the noqa
families. Estate measurement 2026-06-11: 4 live sites, registered at mount.

Signal-honesty note for the design record: the estate is composition-dominant
(max inheritance depth 3-4 by convention), so the signal is honest but WEAK
by construction — the gate's value is keeping it that way.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Substitutability itself stays the live pinned mypy gauge (credit-existing,
nothing rebuilt). The build delta lands in cf-exemptions: coded
'type: ignore[override]' comments — the one token that silences the
gauge's [override] (Liskov) error entirely — are now a registry-gated
family (rule 'override'), scanned via the same tokenize COMMENT surface,
so string literals never trip it and a multi-code ignore hiding the token
in a list is gated too. Other type-ignore codes and the bare form stay
the mypy gauge's jurisdiction (warn_unused_ignores).

Registered sites now pass LOUDLY: every covered suppression prints its
site, rule, enclosing symbol, and covering entry beside the ratchet
banner — a visible exemption, never a silent one. The family rides the
same shrink-only frozen_count ratchet and 1:1 entry discipline as the
noqa families (EXEMPTION_ENTRY_OVERLOADED on collapse).

Oracle: .venv/bin/python -m pytest -q — 276 passed (was 7 failed / 269
passed at the RED commit). Budgets hold: file 492 lines, max function 23
statements, ruff C901<=10 clean, pinned mypy clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Antawari Antawari marked this pull request as ready for review June 11, 2026 14:59
@Antawari Antawari merged commit e0b28b9 into main Jun 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant