From 3963ce5627499b9ec6eb5f3c451f2fc8c82754da Mon Sep 17 00:00:00 2001 From: Antawari de la Torre Cobos Date: Thu, 11 Jun 2026 09:44:23 -0600 Subject: [PATCH] feat: cf-import-contract joins the reusable quality gate (rollout, merge LAST) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Executes the rollout deliberately deferred in the gate's build PR ("Open fork for the maintainer") and since ratified by the maintainer via ADR 0030: the reusable quality-gate.yml now runs cf-import-contract --root . against the consumer tree, in the same battery position as self-ci (after cf-exemptions, before the mypy ratchet) and with the same typed semantics — exit 1 is a violation verdict (CONTRACT_MISSING for a repo with no committed contract), exit 2 is the gate itself failing to run (typed GateError; environment trouble is never a violation verdict). test_gate_runs_full_battery_in_order re-anchors honestly: the pinned battery now names cf-import-contract in its position. Blast radius: a consumer repo running this workflow without a committed import contract fails CONTRACT_MISSING from the moment its pin reaches this commit — this change merges LAST, after every mounted repo's contract PR. Full self-ci battery green locally in a fresh venv (ruff check + format, sticky, file-budget, recursion, exemptions, import-contract exit 0, mypy 0 issues, 310 passed). Co-Authored-By: Claude Fable 5 --- .github/workflows/quality-gate.yml | 9 +++++++++ tests/test_workflows.py | 1 + 2 files changed, 10 insertions(+) diff --git a/.github/workflows/quality-gate.yml b/.github/workflows/quality-gate.yml index 24e8311..a15a696 100644 --- a/.github/workflows/quality-gate.yml +++ b/.github/workflows/quality-gate.yml @@ -159,6 +159,15 @@ jobs: - name: cf-exemptions — every suppression traces to a reasoned entry run: cf-exemptions + - name: cf-import-contract — the committed layering contract holds + # Same command shape as self-ci. The consumer's ONE committed import + # contract ([tool.importlinter] in pyproject.toml) is held in three + # passes; a repo with no committed contract fails CONTRACT_MISSING — + # the contract must be merged BEFORE the consumer's pin reaches this + # commit. Exit 2 is the gate itself failing to run (typed GateError + # on stderr — environment trouble is never a violation verdict). + run: cf-import-contract --root . + - name: mypy through the baseline ratchet (a Python repo MUST carry a baseline) # The pipe is the design: mypy exits nonzero whenever baselined debt # exists; mypy-baseline filter is the gate (0 new errors), so the step diff --git a/tests/test_workflows.py b/tests/test_workflows.py index 2891ef1..b03877e 100644 --- a/tests/test_workflows.py +++ b/tests/test_workflows.py @@ -151,6 +151,7 @@ def test_gate_runs_full_battery_in_order() -> None: "cf-mirror-check", "cf-recursion-check", "cf-exemptions", + "cf-import-contract", "mypy-baseline filter", "pytest", ]