v3.33.0 — gates that could not measure
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 clippyas 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
dashfor 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_run → preview_only, total_fixes → total_previewed, fixes → previewed. 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 implementaborted in every debug build —-sbound to both--specand--summary, and clap only checks uniqueness in debug builds, which is exactly why it shippedpmat analyze graph-metricsreported 0 edges on every tree, so every centrality was trivially zeroserve --transport httpcould not start on Windows — token generation read/dev/urandomby hand- MCP reported success over populations it never measured, where the CLI has refused an empty denominator for two releases
- A missing
cargo clippywas filed as anError-severity finding about the code under review cargo clippyran unbounded on caller-supplied content — and the first bound killedcargo, not therustc/clippy-drivergrandchild 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 ondubious ownershiponce that stopped hiding itmake 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.