fix(ci): the Gate was failing on a missing pin file, not on 915 lint findings - #60
Conversation
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 55 minutes Limit details: You’ve used the included review currently available. Your 75 included PR review attempts over the past 7 days set your current allowance at 1 review per hour. Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?Wait for the limit to reset, then comment An organization admin can change what happens after included review limits in Billing. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (33)
Comment |
5da5ef6 to
6387624
Compare
… lint debt
Every Python PR failed six checks — lint-ruff, lint-format, typecheck-mypy,
python 3.12, python 3.13, summary — and `ruff check .` on main reported 915
findings with 181 files needing reformatting. That reads as debt no single PR can
clear. It was not. All five upstream jobs died at the SAME shared install step,
before any tool ran:
Error: .../.github/workflows/autofix-versions.env is required;
refusing to install unpinned tooling.
identical in jobs 97151941071 / 97151941074 / 97151941041 / 97151952706 /
97151952767. Ruff, Black and mypy had never executed on this repository, not
once, so every prior statement about its lint debt was inferred.
The cause is a contradiction between two lines of one upstream file.
`Workflows/.github/sync-manifest.yml:33` syncs `pr-00-gate.yml` to consumers;
line 967 of the same file lists `autofix-versions.env` under EXCLUDED —
"consumers copy or override per docs/ci/WORKFLOWS.md. Intentionally not synced".
So the sync delivered a Gate that hard-requires a file the sync deliberately
never delivers, and this repo never did the documented copy
(`Workflows/docs/ci/WORKFLOWS.md:83`). This commit does it.
Neither option in the brief would have worked alone. Setting lint/format_check/
typecheck/run-mypy to false leaves python 3.12, python 3.13 and summary red,
because `require_exact_pin` demands pytest and pytest-xdist pins
unconditionally. And a second latch sat behind the first: with coverage on, the
reusable appends `--cov-config=pyproject.toml` unconditionally, so pytest dies
at startup here (`ConfigError: Couldn't read 'pyproject.toml'`) — while adding a
pyproject.toml makes the same workflow append `-e '.[app,dev]'`, which 129 flat
root modules with no build backend cannot satisfy. That is why the Ruff and mypy
config land as ruff.toml + mypy.ini, and why coverage is off.
THE REAL LATCH: two windows that could never agree. With no config present the
two CI surfaces resolved "no config" differently — the Gate pinned the pre-0.16
family (`--select E4,E7,E9,F`) while Autofix took Ruff 0.16's own much wider
default plus `--select I`. On today's main that is 37 findings versus 733; before
#42's Autofix commits landed it was 79 versus 915, which is where the "915, no PR
can drain it" reading came from. The gap is the defect, not its size on any given
day. Autofix rewrote the tree to satisfy rules the Gate never checked, on every
Gate failure, and the Gate stayed red anyway: four `chore(autofix)` commits on
#42 and one on #51, ~143 files and +20,562/-11,089 each. Reverting one got it
re-pushed.
ruff.toml collapses them into one window — Ruff reads it from either surface, so
what Autofix fixes is exactly what the Gate checks — and this commit brings the
tree TO that canon, which makes the loop structurally dead rather than dormant.
Verified by replaying Autofix's three commands verbatim: `ruff check --select I
--fix`, `ruff check --fix`, `black -l 100 .` → zero changes, 196 files
unchanged. Deferring format instead would have left the loop armed;
`.autofix-exclude`, the only repo-owned lever, cannot express "do not format
this repo", and `autofix.yml` carries no `sync_mode`, so an edit there would be
overwritten by the next template sync.
Measured 2026-08-23 at the pinned versions, blocking / drainable:
lint-ruff 39 -> 0 findings drainable 39 ON, green
lint-format 2 -> 0 files drainable 2 ON, green
python 3.12/3.13 0 failures ON, green
typecheck-mypy 601 errors in 89/189 drainable 0 OFF, annotated
coverage 1 startup error drainable 0 OFF, annotated
Because #42's Autofix commits reached main first, the drain here is 39 findings
and 2 files rather than the 141 and 126 it would have been a day earlier.
Both OFF toggles state blocking AND drainable AND "drains by" at the single
place the toggles are computed, and a test fails if any of the three fields goes
missing — the runtime rule enforced rather than written down. One literal per
toggle: the `with:` block and the `summary` job's coverage branch both read
`needs.detect.outputs.*`, and a test rejects a second hardcoded value. mypy.ini
is committed although the check is off, because without it `mypy .` aborts on a
duplicate-module setup error and the 601 would be unverifiable prose; it
silences no error code, by test — fifteen `disable_error_code` entries would
cover 597 of the 601 and make the job green while checking nothing.
docs/CI_LINT_BASELINE.md records the baseline and
`scripts/ci_lint_baseline.py` regenerates it, refusing to print numbers measured
with unpinned tools. A `measured-with` line is asserted against the pin file, so
bumping a tool version without re-measuring goes red — the drain and the
measurement are wired to move together.
E501 is deliberately not selected: 1068 lines still exceed 100 columns after
`black -l 100`, all long strings, URLs and comment prose. Selecting it would be
selecting a rule with no drain. Three E402 findings are exempted per site with a
reason, because each import follows the `sys.path.insert` that makes it
resolvable; the rule stays on everywhere else. RUF100 is not selected, because
72 `# noqa` comments name rules the narrow set does not check and deleting them
would have to be undone the moment the selection widens.
Verified: `python3 verify.py` on the owner's machine — 402 passed, 0 failed, 0
skipped, 84/84 selftests, 43/43 CAN FIRE, 5/5 gates. Fresh-machine simulation
with empty ORCH_STATE_DIR and ORCH_LOCAL_RUNTIME: 394 passed, 8 skipped, 402
collected. CI-equivalent parallel run (`pytest -n auto --dist=loadgroup`): 393
passed, 9 skipped. Floor 391 -> 402 for the 11 new tests; no ceiling moved.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
6387624 to
4298f92
Compare
Workflow source neededPR #60 needs either a linked GitHub issue or one valid non-issue Workflow Source before PR metadata automation can manage it safely. Please do one of:
Once a valid source is present, this warning will not be reposted. |
|
Workflow state fingerprint for Agents Gate Followups. Do not edit. |
Automated Status SummaryHead SHA: a41aa3d
Updated automatically; will refresh on subsequent CI/Docker completions. Keepalive checklistScopeNo scope information available Tasks
Acceptance criteria
|
…in's floor at 391 #61 merged while this branch was in review. Merged it in and re-ran the count rather than assuming: 393 passed + 9 skipped = 402 collected, identical to the pre-#61 measurement, so #61 added no collected tests and this floor is not sitting below reality. main's own floor is still 391, which is exactly main-without-these-11 — no inherited drift to correct. The merge is clean and #61's new code needs nothing: `ruff check` under this branch's ruff.toml reports 0 findings and `black --check -l 100` leaves all 196 files unchanged, so the Gate stays green across the merge rather than only on the branch. verify.py on the merge result: 402 passed, 0 failed, 0 skipped, 84/84 selftests, 43/43 CAN FIRE, 5/5 gates. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Independent verification of this PR from a separate session — I re-derived the root cause before finding this PR, and it matches. Two findings, one of them actionable here. 1. Dangling citation in the pin file (actionable)
The file this PR actually adds is 2.
|
CodeRabbit thread 3838730241 on #63, verified: the break keyed on an exact substring including the trailing space, so a reformatted query would make `str.replace` a silent no-op. The filter would keep protecting the row, the corruption assertion would fail, and its message would blame the fix rather than the stale fixture. It fails RED either way -- no false green -- but it misdiagnoses, and in this repo a check has to name its own cause. Two guards, because there are two ways to go stale, and only one was proposed: 1. The clause MOVES within a still-recognisable query -- asserted per statement, naming the clause it expected and printing the actual SQL. 2. The query itself becomes UNRECOGNISABLE, so nothing is ever stripped -- caught after the run by `stripped`. The review's guarded snippet asserts only WHEN the FROM/JOIN + ORDER BY signature matches, so a rewrite that changes the signature leaves the break silently inert and its assert never runs. That is the same hole one level up. Not the review's first proposal, which is tautological: `broken != sql or clause not in sql` cannot fail, since `clause in sql` makes `broken != sql` necessarily true and the other branch covers the rest. Its second snippet is the right shape and is what guard 1 implements. The candidate query is identified by its FROM/JOIN plus ORDER BY fragments; the not-terminal count query shares the FROM/JOIN but ends in GROUP BY, so it is not mistaken for the candidate and other SQL passes through untouched. Both guards demonstrated then reverted: clause "unresolved" -> " = 'unresolved' " => "deliberate break is STALE: the candidate query no longer contains ... Update this fixture" + the real SQL ORDER BY r.ts DESC -> ASC (valid rewrite) => "deliberate break never fired: nothing matched the candidate query's ... the assertions below prove nothing" No new test, so the floor stays 392 (re-measured: 392 collected). verify.py: 392 passed, 0 failed, 0 skipped, 84/84 selftests, 5/5 gates. Clean under #60's incoming ruff config and black -l 100. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings in #60 (`autofix-versions.env`, `ruff.toml`, `mypy.ini`, the tree drain), which is what every red check on this PR was actually waiting for — all five python-ci jobs were dying at the shared install step before any tool ran. `capability_admission.py` auto-merged: #60 deletes the bare `cited` binding, this branch deletes it and adds `_probe_live_root` in its place, so the two agree on the deletion and differ only in what replaces it. Verified afterwards that the only remaining `cited = {d["record"]...}` in the file is the docstring quoting it as the thing that was dropped. ONE conflict, `langsmith-fleet-worker-attempt.json` (add/add): a generated worker-attempt telemetry snapshot that each CI run rewrites. Resolved to main's copy verbatim, so this PR's diff against main stays exactly one file. It is a single-object "last attempt" snapshot rather than a log, so taking either side discards the other by design — not something to repair in a merge. Net change vs main after the merge: capability_admission.py only, +84/-4. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…e-measured #60 landed the `.github/workflows/autofix-versions.env` pin file that every Python check on this PR was dying on, at the shared `Install dependencies` step before any tool ran. It also brings this repo's first `ruff.toml` and `mypy.ini`, so this change is linted for real for the first time rather than under Ruff's 88-column defaults. Checked against the config that actually landed, not the branch preview: ruff check ledger_reconcile.py test_feedback_model_provenance.py -> passed ruff check . (the Gate's own command) -> passed black --line-length 100 --check on both files -> unchanged `.verify-floor.json` conflicted, as it has every round. Resolved as the UNION: main's note is kept whole (it carries #60's +11 tests and the #64/#65 rationale) with this branch's entry appended, and the count RE-MEASURED on the merge result rather than either side's number -- `pytest --collect-only` reports 403, which is main's 402 plus this branch's one test. No ceiling moved; nothing new is skipped. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two follow-ups to #60, found while independently verifying it. 1. The pin file #60 added cited docs/ci/LINT_BASELINE.md; the file it added is docs/CI_LINT_BASELINE.md. docs/ci/ is the Workflows repo layout and does not exist here. That paragraph is the only pointer telling a reader to re-measure the baseline before bumping a pin, so it pointed nowhere. 2. test_ci_gate_config.py read the pin file CONTENTS thoroughly and its PROSE not at all, which is where (1) lived. test_every_cited_repo_path_resolves requires every repo-relative docs/, scripts/ or tools/ path cited in the two config files this repo OWNS to resolve. Scoped to those two: pr-00-gate.yml adds six findings that are all correct as written (check_issue_consistency.py behind hashFiles(...) != %s with a named skip, ledger_validate.py behind a .agents check, docs/ci/WORKFLOWS.md upstream), and a test that cries wolf gets waived. The upstream marker is scoped per PARAGRAPH, not per line, because the prose wraps and docs/ci/WORKFLOWS.md is quoted three lines below the sentence naming whose doc it is. A third fix was DROPPED as redundant: this branch also carried the backplane-conformance.yml editable-install guard, and #73 landed byte-identical text from the same upstream template while this was open. Deliberate break -> revert: restoring the original citation failed with "autofix-versions.env paragraph at line 23 cites docs/ci/LINT_BASELINE.md"; reverting gave a cmp-clean file and 12 passed. Floor re-measured five times as the base moved under this one-line change (bd6da2e 402 -> ddb0928 402 -> fc1fd42 407 -> 0d661e3 407 -> 0593eeb 411, each +1), never carried forward. verify.py green on the 0d661e3 rebase: 408 passed, 0 failed, 0 skipped, 84/84 selftests, 5/5 gates; re-based onto 0593eeb with the fast checks re-run (12 passed, 412 collected, ruff and black clean) and the full suite left to CI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…70) * test(diagnostics): salvage PR #43's pytest coverage and fetch-first pointer Rebuilt on current main (PR #43's branch was CONFLICTING and #46/#60 have since reshaped both files). #43 and #46 built the entrypoint-absence diagnostic independently and in parallel; #46 merged first, so this lifts the three things #43 had that #46 lacked rather than losing them with the closed PR. 1. `test_an_absent_entrypoint_diagnoses_itself_differently_from_a_real_defect` — #46 put the equivalent checks in `capability_activation_audit --selftest`, and a selftest is NOT guarded by `.verify-floor.json`. Only a COLLECTED test is, so this is the half that makes the behaviour hold. 2. `test_the_capability_gates_all_consult_the_entrypoint_diagnosis` — the sharper idea, with no equivalent in #46 at all: nothing else notices if one of the three gates quietly stops calling the helper and reverts to a bare capability id. It matches the CALL, not the bare name, because all three files also MENTION the helper in a comment — a name-only grep would keep passing after someone deleted the call and left the comment behind. 3. The `git fetch --all && git log --all --oneline -- <module>` pointer, WITH its caveat. `git log --all` is the natural next probe and on 2026-08-22 it came back empty for a module that existed, because the branch holding it had never been fetched into that checkout. An empty result there means "not fetched", never "does not exist", so the command and its precondition travel together or the pointer reproduces the misreading it exists to prevent. Also adds `absent_entrypoint_report(..., ledger=)` / `absent_entrypoint_note(..., ledger=)` so both tests inject their rows instead of reading the running instance's ledger. That is why neither test skips anywhere: the interesting case is one row present and one absent, and no real ledger is reliably both. A machine-independent test is the preferred way to grow this suite — see the 24 -> 26 -> 24 ceiling episode in `.verify-floor.json`. FLOOR 402 -> 404, measured on the merge result, and it must be exact now that #56 made `collected` an EQUALITY. No ceiling moved and nothing new is skipped. Deliberate break -> revert, each caught then reverted byte-identically: * stripped one gate's call to the helper while leaving the comment behind — the drift guard fired and named the file; * dropped the fetch-first caveat from the pointer — the pointer assertion fired. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix(diagnostics): two CodeRabbit findings — a short-circuit and a vacuous guard Both from the review on PR #51, both real, and the second is embarrassing in a useful way. 1. THE FETCH COMMAND OMITTED THE MODULES THAT MATTERED MOST. The module list behind `git log --all` was `{sibling hits} or {missing candidates}`. `or` short-circuits, so as soon as ONE absent row was found in a sibling checkout, the candidates of every row found NOWHERE were dropped — and those are precisely the rows the pointer exists for, because a module in no sibling checkout is the one most likely to sit on an unfetched remote branch. The command said "to check every branch" while silently omitting the hardest cases. Now a union, with the truncation counted rather than silent (`+N more module(s) not shown`), because a cap that hides modules would put the same lie back in a smaller place. 2. THE DRIFT GUARD WAS VACUOUS FOR ITS OWN FILE. It searched each whole FILE for the substring `audit.absent_entrypoint_note(` — which appears SIX times in `test_capability_set_coverage.py` alone: in the docstring, in sibling tests, and inside the assertion itself. So deleting the real call from the recurrence-fixture gate left the guard passing. A guard written specifically to catch a check that cannot fail, that itself could not fail. That is this repo's founding defect wearing the uniform of its own countermeasure. It now walks the AST of ONE NAMED FUNCTION per file, from an explicit `GATE_CALL_SITES` mapping. A string literal or a comment cannot satisfy an AST call match at all, and a RENAMED gate asserts rather than passing quietly — "some call somewhere in the file" was the whole weakness. Deliberate break -> revert, each caught then reverted byte-identically: * union -> `or`: the new regression test failed naming the exact omission (`b_lane.py` absent from the command while `a_lane.py` was present); * deleted the real call from this file's gate, leaving all six literals in place: the AST guard failed where the substring version had passed — the specific hole CodeRabbit found; * renamed a gate function: caught, with a message saying to update `GATE_CALL_SITES` deliberately. FLOOR 404 -> 405: one new test, `test_the_fetch_command_names_every_absent_module_not_just_the_found_ones`. It needs BOTH kinds of absent row present at once, which is why it is its own test rather than more assertions on an existing one — with only one kind, `or` and `|` are indistinguishable. It injects its ledger rows, so it skips nowhere. No ceiling moved. Verified with `python3 verify.py`: 405 passed, 0 failed, 0 skipped, 84/84 selftests, 43/43 can-fire, 5/5 gates. `ruff check .` and `black --check --line-length 100` both clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test(diagnostics): address PR #70 CodeRabbit threads Add truncation regression for seven-plus absent modules and tighten the AST gate predicate to require audit.absent_entrypoint_note in the named function body only, ignoring nested defs and non-audit receivers. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(autofix): formatting/lint * chore(verify): raise floor to 415 on PR #70 merge result CI measured 415 collected (389 passed + 26 skipped) after merging main into the diagnostics salvage branch. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Tim Stranske <tim@stranskemo.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
The pin file #60 added cited docs/ci/LINT_BASELINE.md; the file it added is docs/CI_LINT_BASELINE.md. docs/ci/ is the Workflows repo layout and does not exist here, so the only pointer telling a reader to re-measure the baseline before bumping a pin led nowhere. test_ci_gate_config.py read that file CONTENTS thoroughly and its PROSE not at all, which is where the defect lived. test_every_cited_repo_path_resolves requires every repo-relative docs/, scripts/ or tools/ path cited in the two config files this repo OWNS to resolve. Scoped to those two: pr-00-gate.yml yields six findings that are all correct as written, and a test that cries wolf gets waived. The upstream marker is per PARAGRAPH, not per line, because the prose wraps. Deliberate break -> revert: restoring the original citation failed with "autofix-versions.env paragraph at line 23 cites docs/ci/LINT_BASELINE.md"; reverting gave a cmp-clean file and 12 passed. A third fix was dropped as redundant: #73 landed byte-identical backplane-conformance.yml text from the same upstream template while this was open. Floor re-measured six times as the base moved under this one-line change (402 -> 402 -> 407 -> 407 -> 411 -> 415, each +1). verify.py green on the 0d661e3 rebase: 408 passed, 0 failed, 0 skipped, 84/84 selftests, 5/5 gates; fast checks re-run on each later base (12 passed, 416 collected, ruff and black clean) with the full suite left to CI. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The pin file #60 added cited docs/ci/LINT_BASELINE.md; the file it added is docs/CI_LINT_BASELINE.md. docs/ci/ is the Workflows repo layout and does not exist here, so the only pointer telling a reader to re-measure the baseline before bumping a pin led nowhere. test_ci_gate_config.py read that file CONTENTS thoroughly and its PROSE not at all, which is where the defect lived. test_every_cited_repo_path_resolves requires every repo-relative docs/, scripts/ or tools/ path cited in the two config files this repo OWNS to resolve. Scoped to those two: pr-00-gate.yml yields six findings that are all correct as written, and a test that cries wolf gets waived. The upstream marker is per PARAGRAPH, not per line, because the prose wraps. Deliberate break -> revert: restoring the original citation failed with "autofix-versions.env paragraph at line 23 cites docs/ci/LINT_BASELINE.md"; reverting gave a cmp-clean file and 12 passed. A third fix was dropped as redundant: #73 landed byte-identical backplane-conformance.yml text from the same upstream template while this was open. Floor re-measured six times as the base moved under this one-line change (402 -> 402 -> 407 -> 407 -> 411 -> 415, each +1). verify.py green on the 0d661e3 rebase: 408 passed, 0 failed, 0 skipped, 84/84 selftests, 5/5 gates; fast checks re-run on each later base (12 passed, 416 collected, ruff and black clean) with the full suite left to CI. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The thing that was actually broken
Every Python PR failed six checks —
lint-ruff,lint-format,typecheck-mypy,python 3.12,python 3.13,summary— andruff check .reported 915 findings, 181 files needing reformatting. That reads as undrained lint debt no single PR can clear, which is the latched-gate shape.It was not that. All five upstream jobs died at the same shared install step, before any tool ran:
Identical in jobs
97151941071/97151941074/97151941041/97151952706/97151952767. Ruff, Black and mypy had never executed on this repository, not once — so every prior statement about its lint debt was inferred, not measured.The cause is a contradiction between two lines of one upstream file:
Workflows/.github/sync-manifest.yml:33pr-00-gate.ymlis synced to consumers (create_only)Workflows/.github/sync-manifest.yml:967autofix-versions.envis excluded — "consumers copy or override per docs/ci/WORKFLOWS.md. Intentionally not synced"Workflows/docs/ci/WORKFLOWS.md:83The sync delivered a Gate that hard-requires a file the sync deliberately never delivers, and this repo never performed the copy. This PR performs it.
Neither option in the brief would have worked on its own
lint/format_check/typecheck/run-mypyfalse — leavespython 3.12,python 3.13andsummaryred, becauserequire_exact_pindemandspytestandpytest-xdistpins unconditionally.--cov-config=pyproject.tomlunconditionally (reusable-10-ci-python.yml:1975), so pytest dies at startup here:coverage.exceptions.ConfigError: Couldn't read 'pyproject.toml' as a config file. Adding apyproject.tomlto fix that makes the same workflow append-e '.[app,dev]'(:1683), which 129 flat root modules with no build backend cannot satisfy. Mutually exclusive upstream assumptions — which is why the config lands asruff.toml+mypy.ini, and whycoverageis off.The real latch: two windows that could never agree
With no config file present, the two CI surfaces resolved "no config" differently:
mainreusable-10-ci-python.yml:1155)ruff check --select E4,E7,E9,F— pre-0.16 default, pinned on purposereusable-18-autofix.yml:523-527)--select I --fix, then bareruff check --fix(Ruff 0.16's own, wider default), thenblack -l 100Before #42's Autofix commits landed those read 79 and 915 — which is where the "915, undrainable" reading came from. The gap is the defect, not its size on any given day. Autofix rewrote the tree to satisfy rules the Gate never checked, on every Gate failure, and the Gate stayed red regardless because it was dying at the install step: four
chore(autofix)commits on #42, one on #51, ~143 files and +20,562/−11,089 each. Reverting one got it re-pushed.ruff.tomlcollapses them into one window — Ruff reads it from either surface, so what Autofix fixes is exactly what the Gate checks — and this PR brings the tree to that canon, which is what kills the loop structurally rather than leaving it dormant. Verified by replaying Autofix's three commands verbatim:Deferring the format check instead would have left the loop armed for the next Gate failure of any kind.
.autofix-exclude, the only repo-owned lever, cannot express "do not format this repo" (its patterns filter directories, and the repo root is always a target), andautofix.ymlcarries nosync_mode, so an edit there would be overwritten by the next template sync.Measured, blocking / drainable
2026-08-23, at the pinned versions, on the rebuilt base:
lint-rufflint-formatpython 3.12/3.13typecheck-mypymypy --fixexists)coverageBoth OFF toggles state blocking and drainable and
drains by:at the single place the toggles are computed, andtest_ci_gate_config.pyfails if any of those three fields goes missing — the repo's runtime rule enforced rather than written down. One literal per toggle: thewith:block and thesummaryjob's coverage branch both readneeds.detect.outputs.*, and a test rejects a second hardcoded value.mypy.iniis committed although the check is off, for one reason: without itmypy .aborts onSource file found twice under different module namesand the 601 would be unverifiable prose. It silences no error code, by test — fifteendisable_error_codeentries would cover 597 of the 601 and make the job green while checking essentially nothing.Deliberately not selected, each with its count and its drain:
E501— 1068 lines still exceed 100 columns afterblack -l 100, all long strings, URLs and comment prose, so selecting it would be selecting a rule with no drain. The rest of Ruff 0.16's default set — 742 findings, each a real code change.RUF100— 72# noqacomments name rules the narrow set does not check; deleting them would have to be undone the moment the selection widens. ThreeE402findings are exempted per site with a reason (each import follows thesys.path.insertthat makes it resolvable), not by anignoreinruff.toml.Line length is 100, not Black's default 88 — the value both the Gate's format job and Autofix hardcode. At 88 Black rewrites 184 of 196 files here; at 100 it rewrites 2. A test asserts
ruff.toml, the baseline script and that 100 still agree.Files
.github/workflows/autofix-versions.env— the actual unblock. The documented copy of the fleet pins.ruff.toml,mypy.ini— one rule set for both surfaces; module resolution so mypy's count is reproducible..github/workflows/pr-00-gate.yml—typecheck/coverageoff at the single toggle source, each annotated with both quantities and its drain.docs/CI_LINT_BASELINE.md,scripts/ci_lint_baseline.py— the recorded baseline and the tool that regenerates it. The script refuses to print numbers measured with unpinned tools; ameasured-withline in the doc is asserted against the pin file, so bumping a version without re-measuring goes red.test_ci_gate_config.py(11 tests) +env_prereq.repo_files_absent— the enforcement. The skip gate is the presence of the repository directories, never of the pin file itself: gating on the file would have made the test that checks for it unable to fail, which is this very defect reproduced inside its own test."route_weights"appeared twice in a test fixture, so one value was silently discarded), one stray mid-fileimport mathhoisted.Verification
python3 verify.pyon the owner's machine: 402 passed, 0 failed, 0 skipped, 84/84 selftests, 43/43 CAN FIRE, 5/5 gates. Fresh-machine simulation with emptyORCH_STATE_DIRandORCH_LOCAL_RUNTIME: 394 passed, 8 skipped, 402 collected. CI-equivalent parallel run (pytest -n auto --dist=loadgroup): 393 passed, 9 skipped. Also re-run from a mirror-shaped copy (root-level*.pyonly, asorch-sync-mirror.shproduces) to confirm the new tests skip there with a named reason rather than failing. The live exec mirror was deliberately not synced: it currently carries another session's branch, and syncing it is the manual circuit breaker between a change and the dispatcher — a post-merge step, not part of this PR. Floor 391 → 402 for the 11 new tests; no ceiling moved.One click is needed to see the Gate itself run
Gateon this PR isaction_requiredwith zero jobs — run 32644152974. That is GitHub's suspicious-workflow protection, armed because this PR edits.github/workflows/pr-00-gate.yml; the scan attaches to the file version, so any change to that file re-arms it. The signature is exact:status=completed,conclusion=action_required,created_at == updated_at, 0 jobs, andPOST /actions/runs/{id}/approvereturns403 "This run is not from a fork pull request or queued by the Actions bot". Aworkflow_dispatchrun on the same ref (32644278296) is held identically, so no event can route around it.It needs one click of "Approve and run" on that run page. There is no API path. Until then the Gate's own python-ci legs cannot be observed on this branch — which is why every number in this PR was measured by running the Gate's exact commands locally, at the exact pinned tool versions, and why
scripts/ci_lint_baseline.pyexists to re-run them rather than being taken on trust.What did run on a clean GitHub runner is this repo's own
CIworkflow —python3 verify.py, green: 376 passed, 0 failed, 402 collected against floor 402, at exactly the agreed 26/7/2 skip ceilings with every skip naming its missing prerequisite.Out of scope, filed separately
A seventh red check on these PRs, same class, different workflow:
backplane-conformance.yml:35runspip install -e .unconditionally, so it fails on any non-package consumer despite its own header promising it "skips harmlessly". Both that and the--cov-configfix belong upstream inWorkflows(both files are overwrite-synced, so a local fix would be reverted). When the--cov-configfix lands,coveragecan come back on here — the annotation inpr-00-gate.ymlalready names it as the drain.🤖 Generated with Claude Code