feat(780): commit a ruff config and enforce it in CI #813
12
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7b28fc0e66 |
docs(780): one residual scope claim, and two wordings the measurement outgrew
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 15s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 12s
PR Gates / Docs update reminder (pull_request) Successful in 18s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 10s
PR Gates / decisions lifecycle (pull_request) Successful in 23s
Review verdict / Set review-verdict status (pull_request_target) Successful in 12s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 4m20s
review-verdict/h10 Review-verdict: MERGEABLE @ 7b28fc0 (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m22s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m12s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 5m54s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 9s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 7s
Round-4 verification came back MERGEABLE with no unexecuted claim introduced. Three leftovers from it: - The record still said an `exclude` 'defeats it in three different config scopes' with `it` bound to `ruff check .` — measured, `[format]` does not defeat `check`. It defeats DISCOVERY in three scopes, two per command, which is what the table three lines below already showed. - The force-exclude matrix row listed the non-shipped (flag-off) values first under a column headed 'what ships'. Swapped. - 'silences the check step entirely / green over any violation' — a syntax error still reds under `select = []` (measured). It silences every selected RULE. Refs: #780 Decisions-Edit: yes |
||
|
|
27603b215e |
docs(780): the residual-risk note was itself an unexecuted claim
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 9s
PR Gates / Docs update reminder (pull_request) Successful in 10s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 9s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 23s
PR Gates / decisions lifecycle (pull_request) Successful in 20s
review-verdict/h10 Awaiting review verdict for 27603b2
Review verdict / Set review-verdict status (pull_request_target) Successful in 15s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 4m29s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Canceled after 5m37s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 0s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
Round-4 verification re-ran everything the previous round wrote down. The gate survived a seventh and eighth attack (a nested `scripts/ruff.toml`, a tracked file under a gitignored directory), the §5.2 reproduction block produces exactly its stated output, and the 74/57/17 split, the CI job citations and the exclude matrix all reproduce cell for cell. Four claims did not. - "`select = []` leaves BOTH steps green" — measured, it silences `ruff check` only; `ruff format --check` is not rule-selected and still reddens. Half the gate, not all of it. Written while adding a note about unexecuted claims, which is the joke telling itself. - "dead in the tree for months" — the two pre-existing RUF100 sites predate this branch by 31 and 7 days. The number is not load-bearing; the fact that they predate it is. Also separated the two failure modes: one rule had stopped firing, the other is never enabled by this config, and only the first is what "stops matching" describes. - "~20 opaque assertion errors" without git — measured 208 failed + 45 errors. Deleted rather than restated: the ordering decision does not need a count. - `ruff.toml`'s header said an `exclude` in any of three scopes empties the run; only the top-level scope empties both commands. `docs/ci-cd.md` already had this right — the header, which is what an editor about to add an `exclude` reads, did not. Also: the `force-exclude` matrix row reported the flag-off result for one command and the flag-on result for the other, so the GREEN cell read as "the shipped command is defeatable". Both copies of the matrix are re-cut with the flag-off and flag-on rows separated. One stale `72` survived the 72→74 restatement. The `34` in the witnessed-red quotes now says why it is not 33. `ci.script-tests-job`'s catalog-visible `rule:` still described a pytest-only job. Refs: #780 Decisions-Edit: yes |
||
|
|
6e38ed839e |
docs(780): delete the mechanism claims that were never executed
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 11s
PR Gates / Docs update reminder (pull_request) Successful in 13s
PR Gates / decisions lifecycle (pull_request) Successful in 17s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 21s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 12s
review-verdict/h10 Awaiting review verdict for 6e38ed8
Review verdict / Set review-verdict status (pull_request_target) Successful in 13s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 4m41s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 9m6s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m13s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 6m2s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Successful in 7s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Successful in 6s
Round-3 cold review confirmed the gate itself: ten falsification attempts —
`exclude` in three scopes, `force-exclude`, `extend-exclude`, `include = []`, a
nested `scripts/ruff.toml`, git absent, a non-repo, filenames with spaces,
quotes, newlines and non-ASCII under `core.quotePath` — every one detected, none
green. No BLOCKER, no HIGH on the mechanism. What it did find was three rounds of
the same doc-layer defect: a causal "because" written next to a correct decision
and never run.
- The preflight-ordering rationale claimed a missing git "kills the step at the
population assignment, so its `::error::` never prints". Measured: process
substitution does not propagate exit status, `mapfile` returns 0 with an empty
array, and the `::error::` DOES print. The decision is unchanged; the reason it
now gives is the measured one — the empty-population message blames the glob for
a missing tool.
- `.pyi` was attributed to `ruff check .` skipping it. It does not; the default
`include` covers `*.pyi`. The gap was the previous COUNT guard's
`git ls-files '*.py'`. Claim removed; the tracked-but-gitignored half, which is
true, stays.
- The exclude matrix did not name its pattern, and the one the record itself used
to recommend (`["scripts"]`) reproduces none of it — `exclude` matches per file,
so a bare directory name matches nothing under `[lint]`/`[format]`. Captioned.
- `ci.script-tests-job` still told the reader the job runs `ruff check .`, which
the shipped rule explicitly forbids: two active records disagreeing about the
command, visible only on a whole-branch read.
- The `Lint runs FIRST` comment still described the pre-reorder design, after
ci-cd.md and the record had both been corrected.
- The 72/55/17 split was measured against the config as of
|
||
|
|
01f7a89e8f |
test(780): revert the lint probes; record the reds against the shipped body
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 16s
PR Gates / Docs update reminder (pull_request) Successful in 9s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 11s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 13s
PR Gates / decisions lifecycle (pull_request) Successful in 17s
review-verdict/h10 Awaiting review verdict for 01f7a89
Review verdict / Set review-verdict status (pull_request_target) Successful in 9s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 4m37s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m50s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 2m25s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
Witnessed on the runner, on the step bodies being merged: - run 2173 job 9176 — `❌ Failure - Main Lint scripts (ruff check)` on F401 - run 2170 job 9163 — `❌ Failure - Main Lint scripts (ruff format --check)` Both printed `Linting 34 tracked Python files` / `Format-checking 34`, so the git-derived population arm and `mapfile -d ''` both execute on the runner. The record cited runs 2158/2164 — reds against the previous discovery-based bodies. Those are superseded by the two above, not merely older. Refs: #780 Decisions-Edit: yes |
||
|
|
a8c0740b5f |
test(780): TEMPORARY lint probe against the REWRITTEN gate's check step
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
PR Gates / Docs update reminder (pull_request) Successful in 8s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 21s
PR Gates / decisions lifecycle (pull_request) Successful in 17s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Failing after 10s
review-verdict/h10 Awaiting review verdict for a8c0740
Review verdict / Set review-verdict status (pull_request_target) Successful in 19s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 10s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Canceled after 0s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 0s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
Run 2170 job 9163 recorded the format step red on the new body (and both steps executing: `Linting 34 tracked Python files` / `Format-checking 34`). This probe is check-dirty so `Lint scripts (ruff check)` is witnessed on the same body; the job stops there, which is why the two probes cannot be one. Refs: #780 |
||
|
|
b584f53c33 |
test(780): TEMPORARY format-only probe against the REWRITTEN gate
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 8s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 20s
PR Gates / Docs update reminder (pull_request) Successful in 16s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 14s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Failing after 6s
PR Gates / decisions lifecycle (pull_request) Successful in 21s
review-verdict/h10 Awaiting review verdict for b584f53
Review verdict / Set review-verdict status (pull_request_target) Successful in 11s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Canceled after 0s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 0s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
The reds recorded earlier (runs 2158/2164) were against the previous step bodies, which invoked `ruff check .`. The steps now enumerate from `git ls-files` with `--no-force-exclude`, so those reds prove nothing about what is shipping: a guard is proven by the code that runs, not by its predecessor. Re-witnessing both steps. Refs: #780 |
||
|
|
a706784881 |
fix(780): lint an explicit git population — discovery-based ruff was defeatable in three ways
Re-review of the previous fix commit found the population guard did not close the vacuity it was added for. `ruff check . --show-files` reports DISCOVERY, and an `exclude` defeats discovery in three config scopes — including `[format]`, which is where an appended line lands by TOML rules. Measured with 0.12.11 against a tracked file holding an unused import, a hardcoded credential and a formatting error (GREEN = gate silently off): exclude in check . explicit format --check . explicit top level GREEN red GREEN red [lint] GREEN red red red [format] red red GREEN red + force-exclude - GREEN - red with --no-force-exclude So both steps now pass an explicit population from `git ls-files -z '*.py' '*.pyi' '*.ipynb'` with `--no-force-exclude`, guarded by an empty-list arm. All five mutants above are detected; an empty population errors. This also fixes the count-comparison's three defects in one move: it covers `.pyi` (which the old `git ls-files '*.py'` miscounted into a false red), tracked-but-gitignored files (a permanent false red — `git add -f` under an ignored path is established practice here), and compensating drift that a count comparison nets to zero. RUF100 is now selected. The previous commit added a `# noqa: UP031` to a site the FIRST commit had already fixed in code — a suppression suppressing nothing, in a change whose whole premise is that suppressions must stay honest — and two more had been dead in the tree for months. All three removed. The split is 55 fixed in code / 17 suppressed, not 54/18. The `git` half of `Preflight external tools` moves back ahead of the lint steps, which now consume `git`: without it a missing git kills the step at the population assignment under `-e`, and the step's own `::error::` never prints. The orphaned pytest/PyYAML rationale comment goes back onto its own step. Docs: the record's mutation paragraph called the `[format]` exclude a mutation-construction pitfall when it was a live coverage hole — it now carries the measured matrix instead; `mechanics:` frontmatter rewritten; "all eight S105 hits" scoped (there are nine in the tree, one pre-existing); the defect-shapes reproduction block now actually runs (`mkdir -p`, `;` not `&&`, a sha not `main`, not /tmp). Refs: #780 Decisions-Edit: yes |
||
|
|
02f985edd7 |
test(780): revert the two temporary lint probes
Both are recorded red on the runner before removal: - run 2158 job 9111 — `❌ Failure - Main Lint scripts (ruff check)` on F401 - run 2164 job 9137 — `❌ Failure - Main Lint scripts (ruff format --check)` Both runs also printed `Population OK: 34 tracked Python files`, so the anti-vacuity check executed on the runner and agreed with git there. Refs: #780 |
||
|
|
6c470e769a |
test(780): TEMPORARY format-only violation, to witness the second lint step red
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 22s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 18s
PR Gates / Docs update reminder (pull_request) Successful in 31s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 25s
PR Gates / decisions lifecycle (pull_request) Successful in 20s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Failing after 10s
review-verdict/h10 Awaiting review verdict for 6c470e7
Review verdict / Set review-verdict status (pull_request_target) Successful in 31s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Canceled after 1m28s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 0s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
The previous probe reddened `Lint scripts (ruff check)` on F401 and the job stopped there, so `Lint scripts (ruff format --check)` had still never executed on the runner — merged is not ran, and a step nobody has seen run proves nothing. This probe is check-CLEAN and format-DIRTY, so the run reaches the second step. Both probes are reverted in the next commit. Refs: #780 |
||
|
|
b2e9942106 |
test(780): TEMPORARY deliberate lint violation to witness the gate red
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 10s
PR Gates / Docs update reminder (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 18s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Failing after 9s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 22s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 10s
review-verdict/h10 Awaiting review verdict for b2e9942
Review verdict / Set review-verdict status (pull_request_target) Successful in 10s
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m32s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Canceled after 32s
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Canceled after 0s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Canceled after 0s
Build ErsatzTV Image / API docs in sync (OpenAPI + endpoint index) (pull_request) Canceled after 0s
Build ErsatzTV Image / Formatting (changed .cs conform to .editorconfig) (pull_request) Canceled after 0s
The Done-when asks for a demonstrated red, not an assumed one. This commit introduces an unused import and a double-space assignment so `Lint scripts (ruff check)` and `Lint scripts (ruff format --check)` are seen failing on the runner — merged ≠ ran. Reverted in the next commit. Refs: #780 |
||
|
|
85ecd352f4 |
fix(780): address cold review — narrow S105, guard the population, fix the doc claims
Cold review (Opus, isolated worktree) cleared the mechanical reformat: 25 of 33 files AST-identical, the suite's collected node IDs identical to main, and the three percent-format -> f-string conversions byte-equivalent at both call sites. Everything below is config/CI/doc layer. M4: `S105` is no longer exempted directory-wide. A blanket over `scripts/tests/**` gives up hardcoded-credential coverage over the largest Python surface in the repo — permanently, and this is the only Python lint we run — to suppress 8 known lines. Those 8 now carry a per-site `# noqa: S105`; removing one is red (witnessed). Only `S101` stays directory-wide. M1: `ruff check .` on an empty population prints a stderr warning and exits 0, so a stray `exclude` would switch the gate off silently — the vacuity failure `testing.guard-derives-population-from-source` is about. The step now compares `--show-files` against `git ls-files '*.py'` and fails on drift. Mutation proof: a top-level `exclude = ["scripts"]` takes `ruff check` to green and the step to `::error::… 0 Python files but git tracks 33`. Note the same exclude under `[format]` does NOT reproduce it — it scopes to the formatter, and a mutation written that way passes while proving nothing. M3: lint moved ahead of the preflights. Behind `Preflight jq version` (a hard `--expect` tripwire) the lint would go dark for as long as the jq contract is broken, under a red that names jq. H3: ruff.toml named a `Script lint (ruff)` job that does not exist — wrong on the day it shipped. H1: the "72 errors" claim is now reproducible against the committed config (it was only true of the pre-M4 config), carries its reproduction command and base sha, and splits honestly: 54 fixed in code, 18 per-site `# noqa`s. H2: `docs/ci-cd.md` still said the suite is ~190 tests / ~10s next to a new "four-minute" figure. Measured: 773 tests, ~4.5 min. The no-path-filter rationale rested on the dead number; it now rests on the input set, which is the real reason. M2: the nine E501 `# noqa`s claimed splitting "would change the payload". Implicit string concatenation preserves the bytes exactly, so the stated reason was false nine times. They say what is actually true: kept one-line for greppability. Nits: the record no longer claims the config is identical to the operator's global one (per-file-ignores differ), and the unpinned pytest/pyyaml asymmetry is stated rather than left looking like an oversight. Refs: #780 Decisions-Edit: yes |
||
|
|
18b2a46beb |
feat(780): commit a ruff config and enforce it in CI
Python lint here was a property of the operator's laptop, not of the repo: the global instructions say to run `ruff check`/`ruff format --check`/`pyright`, no workflow or hook ran any of them, and with no committed config ruff fell back to whichever `~/.config/ruff/ruff.toml` the machine happened to have. A second machine lints this repo differently, or not at all — Family E in docs/defect-shapes-773.md, in our own toolchain. Option 1 from the issue: - `ruff.toml` at the root (the operator's global settings, pinned here — that is what the tree was de-facto written against, so adopting it cost a mechanical reformat rather than a rewrite). - The `script-tests` job installs a PINNED `ruff==0.12.11` and runs `ruff check .` + `ruff format --check .` before pytest, so a style red arrives in seconds instead of after the four-minute suite. The pin is the second half of the fix: an unpinned install re-introduces the same divergence one layer up. Renamed the job to `Script lint and tests (ruff + pytest)` so a lint red is not triaged under a name that says pytest. - Tree made clean: 72 errors and 20 files needing reformatting. Everything fixed except two config-level exemptions with reasons in the config (`S101`, `S105` under `scripts/tests/**` — the stub credentials that fire `S105` have no true positive anywhere in the tree) and two per-site `# noqa`s that carry their reason inline. `pyright` stays ungated: its only findings are `reportMissingImports` for `etv_client` in scripts/scripted-schedules/entrypoint.py, resolvable only in that script's deploy environment, and gating it would put a node toolchain on the git-only `small` lane to find nothing. Population is what `ruff check .` discovers from the root, so a new `.py` anywhere is covered without the job enumerating anything. Docs: new record `ci.python-lint-ruff-config-committed`, cross-ref from `ci.script-tests-job`, `docs/ci-cd.md` script-tests section, and `docs/defect-shapes-773.md` §5.2 marked resolved with the measured numbers. Refs: #780 Decisions-Edit: yes |