Gate hardening: honor the consumer's kit pin, gate complexipy, derive known-first-party, honor source_root, Node-24 action pins#6
Merged
Conversation
…t-party, honor source_root, Node-24 action pins Four measured gate defects from the overnight burn's adversarial verifies, plus the Node-20 deadline, each with a control rod that MUST fail: 1. Kit-pin honor — github.job_workflow_sha was OBSERVED empty at run time: the kit checkout received no ref and floated to kit MAIN (git checkout -B main refs/remotes/origin/main), so SHA-pinned consumers were gauged by an unpinned gauge (counts irreproducible, twice in one night). The gate now re-anchors the kit checkout to the pin the consumer COMMITTED in its caller stub, refuses two distinct pins, and refuses to run when no pin is determinable — fail-safe, never a silent float. Rod: the step's script runs against a real git fixture whose floating checkout must be moved to the declared pin (tests/test_gate_hardening.py). 2. complexipy joins the gate — the watermark was runbook-only; now a workflow step in both quality-gate.yml and self-ci.yml with the mypy-style presence rule (a Python repo without its committed snapshot FAILS; Python-free repos skip visibly; never piped). The kit ratchets FIRST: its own snapshot is booted and gated. 3. known-first-party derived per consumer — a shared gauge file cannot name every consumer's packages, and ruff's on-disk detection mis-files first-party imports that do not resolve (measured: fixing the kit's two I001 created two NEW legacy-isort I001 in the same repo). cf-repo-config grows a first-party field (derived from the resolved source root) and the gate feeds it inline to the pinned ruff gauge. 4. cf-exemptions honors the declared source_root — the scanner discovered the repo-root src/ (JS in the measured case) and never visited the declared tree, making every registered exemption documentation-grade. The scan surface now resolves through cf-repo-config exactly like the gauges. Rod: an unregistered suppression under a declared server/src must fail (it silently passed before). 5. Node-24 action pins — GitHub forces Node 24 on 2026-06-16; both pinned actions bumped to their Node-24 releases (checkout v6.0.3, setup-python v6.2.0, full-SHA pinned, releases verified). The deprecated Node-20 SHAs are denylisted ratchet-style. Tests 310 -> 337; full self-ci battery green locally. Two test files split at the file budget's own refusal — the gate caught its maker, the split is the fix, not a baseline. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.
What merging this blesses
Five gate-hardening changes, each anchored to a measured defect and carrying a control rod that MUST fail:
1 · Kit-pin honor — the gate floated to kit MAIN (the reproducibility defect)
Observed:
github.job_workflow_shais documented as the reusable workflow's commit but evaluated EMPTY at run time. The kit checkout received noref:and actions/checkout silently fell back to the default branch.Run-log proof (notioncrm, run 27370755155, job 80882071363):
with:block carries noref:at all (the expression evaluated empty).git checkout --progress --force -B main refs/remotes/origin/main— kit MAIN, while notioncrm's committed stub pinseb4f88c3a863bebf08b9d4f3d5e4044a6133b13f.STICKY_INTRO_ABSENTat main — the sole red step in an otherwise green run. The same float produced the divergent class/residue counts observed on two other consumers the same night.Fix: a new step between the kit checkout and the kit install re-anchors the checkout to the pin the consumer committed in its caller stub (
grepof the consumer's own.github/workflowsfor the full-SHAuses:ref — committed state, never a caller knob; zero-inputs doctrine intact). Two distinct pins refuse. No determinable pin refuses (exit 1) unlessgithub.job_workflow_shais populated AND already matches HEAD — fail-safe, never a silent float to main.Control rod (functional, not just structural):
tests/test_gate_hardening.pyextracts the step's actual script from the YAML and runs it against a real git fixture — a kit clone sitting at main with a consumer stub pinning an older SHA. The script MUST move HEAD to the pin; the no-pin and two-pin cases MUST exit 1.Migration for the 7 mounted repos: none. No caller-side change. Every mounted repo already commits exactly one full-SHA pin, which is precisely what the step reads. The fix takes effect for a consumer when it bumps its pin to a kit SHA containing this change. A repo calling the gate by branch ref (doctrine-banned) will now fail loudly instead of floating — by design.
2 · complexipy joins the gate (was runbook-only)
Per-repo
complexipy-snapshot.jsonbaselines are committed fleet-wide and the conventions define the watermark as a gate, but no workflow step enforced it (one consumer shrank its snapshot 36→13 with nothing in CI gating it). Now: a plaincomplexipy "$CF_SOURCE_ROOT"run (auto-compares against the CWD snapshot — tool-spike semantics; never piped, piping masks the exit code) with the mypy-style presence rule — a Python repo without its committed snapshot FAILS; a Python-free repo skips visibly. The kit ratchets FIRST: its own snapshot is booted ([], clean) and gated inself-ci.yml.Fleet note: consumers meet this step only when they bump their pin; a consumer missing its snapshot at that point boots one per
configs/BASELINE-CONVENTIONS.md(green by construction).3 · known-first-party derived per consumer (the I001 cross-config conflict)
Measured: the kit's gauge flagged 2 I001 in a consumer's tests; fixing them per the kit's sort created 2 NEW I001 under the repo's legacy isort config. Root cause: the legacy config forces all of the repo's packages first-party via
known-first-party, while the kit's gauge classifies by on-disk detection — imports that don't resolve on disk (<pkg>.tests.*with tests outside the package tree, modules authored RED) get mis-filed third-party. A shared gauge file cannot statically name every consumer's packages, socf-repo-configgrows afirst-partyfield (derived from the consumer's resolved source root: top-level packages incl. PEP 420 + top-level modules; non-shipping dirs excluded at root layouts) and the gate feeds it inline:--config "lint.isort.known-first-party=$CF_FIRST_PARTY". Verified on the real conflict: kit gauge alone = 2 errors; kit gauge + derived["<pkg>"]= All checks passed, matching the legacy verdict. Derived from committed state — not a caller knob; CI's value cannot be weakened by a vendored copy.4 · cf-exemptions honors the declared
source_rootMeasured (mexxa main-green pass): cf-exemptions discovered the repo-root
src/(JS) and ignored the declaredserver/src— both registered exemptions were documentation-grade; the scanner never visited the files they cover. The scan surface now resolves throughcf-repo-configexactly like the gauges (typedGATE_CONFIG_INVALIDon an invalid declaration, never a silent fallback). Control rod: a fixture withsource_root = "server/src"and an unregistered suppression inserver/src/MUST fail — it silently passed before (tests/test_exemptions_source_root.py).5 · Node-24 action pins (deadline 2026-06-16)
The deprecation annotation on the notioncrm run names both pinned actions: "Actions will be forced to run with Node.js 24 by default starting June 16th, 2026." Both bumped, SHA-pinned (never floated to a tag), releases verified against the actions' own repos (
runs.using: node24confirmed at each commit):actions/checkoutv4.2.2 → v6.0.3 (df4cb1c069e1874edd31b4311f1884172cec0e10)actions/setup-pythonv5.3.0 → v6.2.0 (a309ff8b426b58ec0e2a45f0f869d46889d02405)The old Node-20 SHAs are denylisted ratchet-style (Dependabot may bump forward freely; a rollback to the deprecated runtime fails the test battery).
Verification
test_gate_hardening.py,test_exemptions_source_root.py), not baselined. The gate caught its maker; the kit submits before it preaches.job_workflow_shawas reliable; the record now carries the observed defect and the re-anchor mechanism).Files
.github/workflows/quality-gate.yml— pin-honor step · complexipy step · first-party wiring · Node-24 pins.github/workflows/self-ci.yml— complexipy step · Node-24 pinssrc/cf_quality/repo_config.py—first_party_packages()+first-partyCLI field + shared non-shipping setsrc/cf_quality/exemptions.py— declared-source_root resolution (shares the set; no second list to drift)configs/ruff-base.toml— documents why known-first-party is gate-derived, never staticcomplexipy-snapshot.json— the kit's own watermark, booted clean ([])tests/test_gate_hardening.py·tests/test_exemptions_source_root.py·tests/test_repo_config.py·tests/test_workflows.py— the rodsDESIGN.md·docs/sha-pin-doctrine.md— record matches shipped behaviorCI state
Will be reported on this PR's checks (self-ci runs the full battery on this branch). The reusable gate's consumer-facing behavior is covered by the functional script rod above; the live consumer proof lands when a consumer bumps its pin to this commit (Anta-gated, per the pin doctrine).
DO NOT MERGE without Anta's review — this PR records and fixes the defects; only Anta merges.
🤖 Generated with Claude Code