v2.21.0
Added
- Each finding shows where its evidence came from (#1026). A short label and the confidence score follow the finding text, for example
(corroborated by analyzer, confidence 88). The label is one ofcorroborated by analyzer,analyzer finding,judge kept,single agent, unverified, orsingle agent, not judged. It shows on GitHub, GitLab, and Bitbucket. It is display text only and does not change the approval decision. It is on by default. Setfinding-badges: 'false'(AI_FINDING_BADGES=falseon Bitbucket) to hide it. A finding that the judge did not rule on showssingle agent, not judged. - Behavior change: new analyzer
dep-existsflags a new dependency that its registry does not know (#1024). A model can invent a package name, and an attacker can register that name. The analyzer checks each dependency that a diff adds topackage.json,requirements*.txt,Cargo.toml,composer.json, orGemfile. An unknown name is a High finding. A version bump of an existing dependency is not looked up. An npm, PyPI, or crates.io package first published under 30 days ago is a Medium finding. It sends only the package name to the public registry. It does not check Go modules, and it skips an ecosystem when the repository sets a private registry. It is on by default. Turn it off withexclude-analyzers: dep-exists. A High finding makes the review request changes, so a repository can see a pull request blocked by a dependency that is real but private. The analyzer reads only files in the repository, so it cannot see a private registry that is set in CI settings or a user-level config. It also asks the public registry about a private scoped npm package, or about a monorepo package that another package lists by plain version (workspace:,file:andlink:specs are skipped). If that affects you, turn the analyzer off withexclude-analyzers: dep-exists, or set the registry in a file in the repository. When registry lookups fail, the run logs a warning, and the dependencies that were not checked add no finding. - The review comment says what the review did not look at (#1023). A short
Not reviewed:note lists theexclude-patternsyou set, the agents that did not run, and whether the review is incremental. The note is empty when nothing was left out. - The finding judge can read the code a finding cites, and the repository has a measured comparison (#1025). The production review does not use this yet, because the first measurement did not meet the bar. The shipped judge is unchanged.
- Claude Haiku 5.5 has a pricing row, with a second set of rates for long prompts (#1012). Haiku 5.5 is not a default model.
- The consistency harness has a hard spend cap (#1014). It also refuses to start without
--yes. This changes the test tools only, not the action.
Changed
- Behavior change: the pre-flight cost estimate is about 2.2 times higher for the same diff (#1013). The estimate now counts input tokens from a measured ratio of 1.8 characters per token. The old estimate counted only 48% to 81% of the real tokens. This affects
AI_MAX_COST_USD(off by default), theCOST_ESTIMATElog line, and the cost-ceiling skip. A repository that sets a ceiling can see a review skipped that passed before. Raise the ceiling, or compare it with the logged estimate. - The published docs are rewritten to ASD-STE100 and checked against the code (#1021, #1028). Em dashes are removed. Statements that did not match the code are fixed.
- Dependency updates. The
trufflehogimage is 3.99.2, theruffimage is 0.17.0, anddocker/dockerfileis 1.28. The artifact andsetup-rubyactions are newer. Theruffanalyzer can report findings that the old 0.16.10 did not. - The engine pins the git diff format (#1032). A non-ASCII directory name or
diff.mnemonicPrefix=truein a user’s git config no longer makesdep-existsskip a manifest. A path with a control character is never decoded, anddep-existswarns when it cannot read a path. - The policy
pathsglobs now match a non-ASCII path. Git used to write such a path in quotes, so a route likedocs/**did not match it.
Fixed
- The Sonnet 5.5 cache-read price was twice the published price (#1012). The token table and the compact usage line counted Sonnet 5.5 cache hits at $0.20 per million tokens. The correct price is $0.10.
- A model id with a digit glued to
opus-5is no longer priced or handled as Opus 5 (#1012). A futureclaude-opus-59would have used the Opus 5 rates and settings. - Claude Haiku 5.5 no longer fails with HTTP 400, and its thinking is capped (#1015). The action omits
temperaturefor Haiku 5.5 and caps effort atlow. - The
rescanandreview-fullcommands read their ownfail-on-findingsvariable. The shipped workflows readAI_REVIEW_SLASH_FAIL_ON_FINDINGS(defaultfalse) on that path. They readAI_REVIEW_FAIL_ON_FINDINGSbefore, so a repository that set it totruefor the review job also made a rescan that found something fail the run. If you want the gate on rescans, set the new variable totrue. The example pipelines also state the correctAI_CONTEXT_ENRICHMENTdefault and learning-loop scope.
Not verified
- Haiku 5.5 is not a default model. A model-change verification run is still needed before it can become one.
- The code-aware judge is not part of the production review.
See CHANGELOG.md for full technical detail.