fix(780): reconcile the ruff gate with #784, merged in parallel
PR Gates / Docs update reminder (pull_request) Successful in 22s
Build ErsatzTV Image / Delimiter ban (release path) (pull_request) Successful in 38s
PR Gates / CI image pin matches docker/ci (pull_request) Successful in 12s
PR Gates / Fix proofs (Proves trailers) (pull_request) Successful in 12s
PR Gates / decisions lifecycle (pull_request) Successful in 30s
Review verdict / Set review-verdict status (pull_request_target) Successful in 36s
PR Gates / Script lint and tests (ruff + pytest) (pull_request) Successful in 4m28s
review-verdict/h10 Review-verdict: MERGEABLE @ eda2fac (base: main)
Build ErsatzTV Image / Build & test (.NET) (pull_request) Successful in 8m33s
Build ErsatzTV Image / EF migration integrity (SQLite + MySql) (pull_request) Successful in 6m7s
Build ErsatzTV Image / Build & push image (amd64) (pull_request) Skipped
Build ErsatzTV Image / Functional E2E (curl + UI contracts) (pull_request) Successful in 5m46s
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 6s

#780 and #784 were green separately and red together: the gate landed with a base
that predated `scripts/check-doc-narrative.py`, so nothing ever ran ruff over it.
On merged main the shipped invocation is RED, which would have surfaced as a
mystery lint failure on whichever PR opened next.

Two findings, both in #784's files:

- `RUF100` on `# noqa: BLE001` twice — `BLE` is not in this repo's `select`, so
  those directives suppress nothing. Enabling `BLE` instead was measured and
  rejected: it fires 6 more times in `decisions_validate.py`, whose broad catches
  are deliberate, and that is a ruleset decision for its own PR rather than a
  side effect of unbreaking main. The non-enabled code is dropped; the `S110` on
  the first site stays (S IS selected), and both explanatory comments stay.
- `scripts/tests/test_check_doc_narrative.py` was not ruff-formatted. Formatted;
  suite still 807 passed, 2 skipped.

The general shape, for the next time two PRs touch disjoint files: a gate whose
population is "everything tracked" is only as green as its base. #813's CI could
not have caught this and neither could #811's.

Refs: #780, #784
This commit is contained in:
2026-08-22 02:39:06 +02:00
parent d4c72697f2
commit eda2fac35f
2 changed files with 22 additions and 24 deletions
+3 -2
View File
@@ -38,7 +38,7 @@ import sys
try:
sys.stdout.reconfigure(errors="replace") # type: ignore[union-attr]
sys.stderr.reconfigure(errors="replace") # type: ignore[union-attr]
except Exception: # noqa: BLE001, S110 — a stdout that cannot be reconfigured is not a reason to fail
except Exception: # noqa: S110 — a stdout that cannot be reconfigured is not a reason to fail
pass # deliberate: this is the never-fails invariant's own setup, so it cannot itself raise
# `docs/decisions/**` is exempt WHOLESALE — a decision record narrating how a rule was got wrong is
@@ -254,6 +254,7 @@ def main(argv: list[str]) -> int:
if __name__ == "__main__":
try:
sys.exit(main(sys.argv))
except Exception as exc: # noqa: BLE001 — the never-fails constraint outranks a clean traceback
# The never-fails constraint outranks a clean traceback, so this catch is deliberately blind.
except Exception as exc:
print(f"doc-narrative: internal error ({exc!r}) — SCANNED NOTHING. Advisory; not a failure.")
sys.exit(0)
+19 -22
View File
@@ -27,9 +27,7 @@ HIT = re.compile(r"^::warning file=(?P<path>[^:]+)::(?P=path):(?P<line>\d+) ", r
def run(cwd: Path, *args: str) -> subprocess.CompletedProcess:
return subprocess.run(
[sys.executable, str(SCRIPT), *args], cwd=cwd, capture_output=True, text=True
)
return subprocess.run([sys.executable, str(SCRIPT), *args], cwd=cwd, capture_output=True, text=True)
def hits(out: str) -> set[tuple[str, int]]:
@@ -76,9 +74,9 @@ def commit(r: Path, msg: str = "c") -> None:
[
((), "scanned "),
(("--all",), "scanned "),
(("--diff",), "--diff needs a base ref"), # no base ref at all
(("--diff", ""), "--diff needs a base ref"), # `origin/` with base_ref unset
(("--diff", "no-such-ref-xyz"), "SCANNED NOTHING"), # an unresolvable ref
(("--diff",), "--diff needs a base ref"), # no base ref at all
(("--diff", ""), "--diff needs a base ref"), # `origin/` with base_ref unset
(("--diff", "no-such-ref-xyz"), "SCANNED NOTHING"), # an unresolvable ref
(("--diff", "origin/"), "SCANNED NOTHING"),
(("--nonsense",), "unknown mode"),
],
@@ -133,14 +131,14 @@ def test_a_DELETED_doc_is_not_reported_as_added_content(repo: Path) -> None:
# stopped pinning variants and removed the surface. The table is here so the next knob someone finds
# gets a row instead of a round.
FORMAT_KNOBS = [
("core.quotePath", "true"), # quotes non-ASCII paths out of the population
("diff.dstPrefix", "dst/"), # rewrites the header the path is read from
("core.quotePath", "true"), # quotes non-ASCII paths out of the population
("diff.dstPrefix", "dst/"), # rewrites the header the path is read from
("diff.srcPrefix", "src/"),
("diff.noprefix", "true"),
("color.diff", "always"), # injects ANSI escapes into every line
("color.diff", "always"), # injects ANSI escapes into every line
("color.ui", "always"),
("diff.renames", "false"), # turns a `git mv` into a whole-file add
("diff.context", "9"), # a configured context must not beat the -U0 on the CLI
("diff.renames", "false"), # turns a `git mv` into a whole-file add
("diff.context", "9"), # a configured context must not beat the -U0 on the CLI
("diff.external", "/bin/echo"), # replaces the output wholesale
]
@@ -167,9 +165,7 @@ def test_a_NON_UTF8_stdio_does_not_break_the_never_fails_invariant(repo: Path, e
env = dict(os.environ, **{env_name: env_value})
env.pop("PYTHONUTF8", None)
p = subprocess.run(
[sys.executable, str(SCRIPT), "--all"], cwd=repo, capture_output=True, text=True, env=env
)
p = subprocess.run([sys.executable, str(SCRIPT), "--all"], cwd=repo, capture_output=True, text=True, env=env)
assert p.returncode == 0, f"{env_name}={env_value} exited {p.returncode}: {p.stderr}"
@@ -224,9 +220,9 @@ def test_a_multi_hunk_file_numbers_every_hunk_from_its_own_header(repo: Path) ->
body = [f"l{i}" for i in range(1, 31)]
(repo / "docs" / "m.md").write_text("\n".join(body) + "\n", encoding="utf-8")
commit(repo)
body[4] = NARRATIVE # replace, early hunk
body.insert(15, NARRATIVE) # pure insert, middle hunk
body[-1] = NARRATIVE # replace, last hunk
body[4] = NARRATIVE # replace, early hunk
body.insert(15, NARRATIVE) # pure insert, middle hunk
body[-1] = NARRATIVE # replace, last hunk
(repo / "docs" / "m.md").write_text("\n".join(body) + "\n", encoding="utf-8")
commit(repo)
assert hits(run(repo, "--diff", "HEAD~1").stdout) == truth(repo, "docs/m.md")
@@ -326,7 +322,10 @@ def test_a_NON_UTF8_LOCALE_does_not_silently_empty_the_scan(repo: Path) -> None:
env = dict(os.environ, LC_ALL="C", PYTHONUTF8="0", PYTHONIOENCODING="utf-8")
p = subprocess.run(
[sys.executable, str(SCRIPT), "--diff", "HEAD~1"],
cwd=repo, capture_output=True, text=True, env=env,
cwd=repo,
capture_output=True,
text=True,
env=env,
)
assert p.returncode == 0, p.stderr
assert "internal error" not in p.stdout, p.stdout
@@ -348,13 +347,11 @@ def test_MUTATION_neutering_the_pattern_makes_a_known_hit_go_quiet(repo: Path, t
disarmed = tmp_path / "disarmed.py"
src = SCRIPT.read_text(encoding="utf-8")
marker = 'PATTERNS = re.compile('
marker = "PATTERNS = re.compile("
assert src.count(marker) == 1
disarmed.write_text(
src.replace(marker, 'PATTERNS = re.compile(r"(?!x)x" # disarmed\n or ', 1), encoding="utf-8"
)
p = subprocess.run(
[sys.executable, str(disarmed), "--all"], cwd=repo, capture_output=True, text=True
)
p = subprocess.run([sys.executable, str(disarmed), "--all"], cwd=repo, capture_output=True, text=True)
assert p.returncode == 0, p.stderr
assert hits(p.stdout) == set(), "the disarmed detector still flagged something — the mutation did not take"