fix(ci): judge a panic ratchet red by its per-lint rows, not the packages it names

TE
6d ago
+167-1

Summary

scripts/ci/base_red_excuse.py never excused a Rust panic ratchet red on clippy (changed cmux-tui packages) (step Rust panic ratchet on changed cmux-tui packages). It compared the ratchet's ::error line, which names the packages the run checked. A base run can be a whole-workspace dispatch ("the panic ratchet is red for the whole cmux-tui workspace"), but a PR run names only its changed packages. So the line never matched, even when every failure row was the same on both runs.

Concrete case: cmux#26849 at f81fd0a3e4386ddc13eea076dc9a5315abb4c798, run 41176610742, fails on exactly two rows:

  • acpmux: clippy::indexing_slicing 692 > baseline 686
  • cmux-tui: clippy::indexing_slicing 836 > baseline 831

Base run 41176544319 (at 734e99a7e6) fails on those same two rows plus cmux-rd-link: clippy::indexing_slicing 7 > new crate (must be 0). The classifier still said not excused: errors not on feat-cmux-next run 41176544319.

The ratchet red is now judged by the rows in its rust-panic-ratchet: RED block:

  • Each head row CRATE: clippy::LINT N > WHERE must be on the base with the same crate, the same lint and the same WHERE (baseline M or new crate (must be 0)), and the base's count must be at least the head's. The base may have extra rows.
  • Hit-location lines (crates/x/src/y.rs:L:C) are not compared. Any other RED line (for example an allow with no reason) must be on the base word for word.
  • A ratchet red with no row is never excused. The ratchet prints no row when its clippy run did not finish.
  • Other error lines in the same job (a clippy compile error, say) are still compared as before. So are failed steps. The crash and cut-short rules are unchanged.

This also closes a gap that loosened the check: when the head and base had the same scope line, the old code excused the head even when its count was higher than the base's (see the ..._with_the_same_scope_too test). That case now blocks.

No open PR fixes this classifier. #28958 lowers the base counts. It does not change the classifier.

Testing

Command: python3 -m unittest tests.test_base_red_excuse.PanicRatchet

  • At the test commit (fd5ad6bc3e6, fix not applied): FAILED (failures=7, errors=2) of 10 tests.
  • At the head: Ran 10 tests ... OK. The whole file python3 -m unittest tests.test_base_red_excuse passes: 106 tests, OK.

Observed / Not run

  • Observed: the new tests red and then green, as above. I read the real job logs of run 41176610742 (job 124465364731) and base run 41176544319 (job 124465669565) and ran the new parser on them. ratchet_red read 2 head rows and 3 base rows, and ratchet_unmatched returned no unmatched lines.
  • Not run: the end-to-end base_red_excuse.py --run 41176610742 against GitHub. The shared REST quota ran out (HTTP 403) when I tried it. I will re-check after the reset and report the result in a PR comment.

Changelog

none

risk:normal: CI tooling only. It loosens the base-red excuse for one kind of check and tightens it in the same-scope case.

Agent session: agent session

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes the base-red excuse for Rust panic ratchet failures so ratchet reds are judged by their per-lint rows instead of the scope line that names the checked packages.

A base run may cover the whole cmux-tui workspace while a PR run covers only its changed packages, so the scope line never matched and valid excuses were refused. Now each head row (CRATE: clippy::LINT N > WHERE) must appear on the base with the same crate, lint, and WHERE and a count at least the head's; other RED lines match word for word, and a red with no rows is never excused.

Behavior changes

  • Tightens the check: a head count above the base's now blocks even when both runs share the same scope.
  • Other error lines in the same job and failed steps are still compared as before.