Skip to content

v3.33.0 — gates that could not measure

Choose a tag to compare

@noahgift noahgift released this 28 Aug 20:40
· 459 commits to master since this release
3d79b49

Minor rather than patch, for the same reason 3.32.0 was: most of this release changes what pmat reports on unchanged code. Read the notes before upgrading a gate — pmat analyze clippy loses six response keys, quality_proxy gains two and stops accepting non-Rust files by default, and three CI lanes start failing on trees they used to pass.

One shape, sixteen times

Something that could not measure was reporting that there was nothing to find:

  • a skipped language as a pass
  • a parse failure as complexity zero
  • a missing cargo clippy as a verdict about your code
  • a fix that was never written as "applied"
  • a config nobody parses as a config that was satisfied
  • a CI lane dead in dash for seven nights as a lane with nothing to report

Each of those reads, to a caller, exactly like clean code. Several were found only by dogfooding the published 3.32.0 artifact, after the release — the binary-size gate had never compiled, and the binary was 2.8 MB past the limit it was supposedly enforcing.

Breaking

pmat analyze clippy is preview-only. It reported "action": "applied" with a non-zero successful_fixes while the file on disk was byte-identical. This is not fixed by adding the missing write: the transform is a blind whole-file source.replace("return ", "") that ignores the diagnostic's span, so writing its output would corrupt source — it strikes the substring inside string literals and identifiers too.

apply_fixes is deleted, and with it successful_fixes, failed_fixes, success_rate, fixed_files, detailed_results. dry_runpreview_only, total_fixestotal_previewed, fixespreviewed. A key that does not exist cannot lie.

quality_proxy no longer accepts every non-Rust file. It returned passed: true with all-zero metrics for every extension but lowercase "rs" — and strict is the default mode. SATD now runs for every language, complexity for every language pmat has an analyzer for. QualityReport gains language and gates_run: a gate absent from gates_run did not run, and its zero is unknown rather than zero.

Also fixed

  • pmat prompt implement aborted in every debug build-s bound to both --spec and --summary, and clap only checks uniqueness in debug builds, which is exactly why it shipped
  • pmat analyze graph-metrics reported 0 edges on every tree, so every centrality was trivially zero
  • serve --transport http could not start on Windows — token generation read /dev/urandom by hand
  • MCP reported success over populations it never measured, where the CLI has refused an empty denominator for two releases
  • A missing cargo clippy was filed as an Error-severity finding about the code under review
  • cargo clippy ran unbounded on caller-supplied content — and the first bound killed cargo, not the rustc/clippy-driver grandchild that holds the memory
  • The scaffolder generated a [gates] config section nothing in pmat parses

Gates that could not fail

  • The binary-size gate had never run; it is now a band (±5% quiet, ±20% hard) that fails on shrinkage too, because a binary that sheds 20% has lost a feature. And the band itself was never asked to assert — nothing set PMAT_REQUIRE_BINARY_SIZE, so every leg printed "THIS RUN VERIFIED NOTHING" and passed. A CI job now sets it.
  • Mutation (diff) died in dash on every one of its seven nights, then died again on dubious ownership once that stopped hiding it
  • make validate-book: 6 of 7 chapter scripts could not fail. Running the new control for this release found three of four CRITICAL chapters vacuous — one inverted conditional meant a working pmat selected the mock branch, so the suites had never invoked pmat at all
  • Two shell blocks in a doc comment were compiled as Rust, behind a gate that had been red since clippy went missing from the clean-room image

Not done, deliberately

No pmat_write_file / pmat_edit_file. MCP has no primitive by which a server can gate a client's own tools, so such a tool is a menu item an uncooperative agent never calls.

The HTTP transport still answers {"jsonrpc":"1.0"} with 200 and the full tool list. A guard was written and withdrawn: its parked-frame queue was bounded in entries but not bytes, it keyed correlation on a client-supplied header, and its only end-to-end test lives in a target no CI job runs.


Full detail, with the measurements behind each claim, in CHANGELOG.md.