agent-roast 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,6 +98,10 @@ re-labeled.
98
98
  It is a **review aid**: it cannot prove who wrote a change or that code is correct, and it
99
99
  reads text, not program semantics. A green result is not a quality certificate.
100
100
 
101
+ **Want to see what it says about your repository?** [docs/pilot.md](docs/pilot.md) has a
102
+ five-minute look back, an advisory workflow that never fails a pull request, and a feedback form.
103
+ Counts are enough; no code is needed.
104
+
101
105
  ### Quick start
102
106
 
103
107
  ```bash
@@ -114,8 +118,9 @@ npx agent-roast --all --verbose
114
118
  ```
115
119
 
116
120
  A finding includes its file and line, the evidence, and a concrete next step.
117
- `--format json|markdown|sarif|github` are available; terminal output shows the first
118
- 20 findings.
121
+ `--format json|markdown|sarif|github` are available; terminal output shows the 20 most
122
+ important findings (rules that block first, then the before/after rules, then the noisier
123
+ line patterns).
119
124
 
120
125
  ### Context review for pull requests
121
126
 
@@ -175,12 +180,12 @@ regressions) may appear in the report/summary rather than as an inline PR annota
175
180
  Use a separate SARIF category for introduced-findings review; it does not represent
176
181
  a full scan of all outstanding alerts.
177
182
 
178
- Install 0.10.0: `npx agent-roast@0.10.0 review --base origin/main`. For local development,
183
+ Install 0.10.1: `npx agent-roast@0.10.1 review --base origin/main`. For local development,
179
184
  run `npm run build` and use `node dist/cli.js`.
180
185
 
181
186
  ### Precise exceptions (since 0.8.0)
182
187
 
183
- Use `npx agent-roast@0.10.0 check --format json`, or build this checkout with
188
+ Use `npx agent-roast@0.10.1 check --format json`, or build this checkout with
184
189
  `npm run build` and run `node dist/cli.js`.
185
190
 
186
191
  Some skipped integrations or abstract stubs are intentional. In 0.8.0 you can accept
@@ -416,7 +421,7 @@ jobs:
416
421
 
417
422
  To pilot the Action without blocking on findings, set `advisory: true`. It passes
418
423
  an explicit empty fail-on list; invalid configuration, Git errors and incomplete
419
- scans still fail. The `v1` Action installs 0.10.0. The CLI equivalent is `--fail-on ''`.
424
+ scans still fail. The `v1` Action installs 0.10.1. The CLI equivalent is `--fail-on ''`.
420
425
 
421
426
  > **Security Note:** `agent-roast` runs in an isolated runner directory (`$RUNNER_TEMP`) with `--ignore-scripts` to neutralize malicious `.npmrc` files in untrusted pull requests. `pull_request_target` is not supported.
422
427
 
@@ -504,7 +509,7 @@ node scripts/verify-user-workflows.mjs dist/cli.js
504
509
  against current code. Regression tests use disposable Git repositories. The programmatic
505
510
  `auditPullRequest({ staged: true })` API retains the legacy added-lines contract;
506
511
  use `reviewStagedChanges()` for the new context comparison and `ReviewResult`.
507
- The composite Action installs exactly 0.10.0. For local development, use
512
+ The composite Action installs exactly 0.10.1. For local development, use
508
513
  `node dist/cli.js --staged` after building.
509
514
 
510
515
  ### Author & Support
@@ -1853,7 +1853,7 @@ function formatPrTerminalCard(result) {
1853
1853
  } else {
1854
1854
  lines.push(pc.bold(` INFRACTIONS DETECTED (${result.infractions.length})`));
1855
1855
  lines.push(pc.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1856
- for (const inf of result.infractions) {
1856
+ for (const inf of mostImportantFirst(result.infractions, result.failedRules)) {
1857
1857
  const isFailedRule = result.failedRules.includes(inf.type);
1858
1858
  const badge = isFailedRule ? pc.red("FAIL") : pc.yellow("WARN");
1859
1859
  const loc = `${inf.file || "unknown"}:${inf.lineNumber || 1}`;
@@ -1877,12 +1877,25 @@ function formatPrTerminalCard(result) {
1877
1877
  lines.push("");
1878
1878
  return lines.join("\n");
1879
1879
  }
1880
- function sortInfractionsDeterministic(infractions) {
1881
- const getLevelRank = (type) => {
1882
- return type === "test-skip" || type === "trivial-assert" || type === "swallowed-error" ? 0 : 1;
1883
- };
1880
+ var RULE_PRIORITY = {
1881
+ "assertion-weakened": 0,
1882
+ "guard-weakened": 0,
1883
+ "test-skip": 0,
1884
+ "test-focus": 0,
1885
+ "trivial-assert": 0,
1886
+ "assertion-removed": 1,
1887
+ "expectation-rewritten": 1,
1888
+ "test-removed": 1
1889
+ };
1890
+ function findingRank(type, failedRules) {
1891
+ return failedRules.includes(type) ? -1 : RULE_PRIORITY[type] ?? 2;
1892
+ }
1893
+ function mostImportantFirst(findings, failedRules) {
1894
+ return [...findings].sort((a, b) => findingRank(a.type, failedRules) - findingRank(b.type, failedRules));
1895
+ }
1896
+ function sortInfractionsDeterministic(infractions, failedRules) {
1884
1897
  return [...infractions].sort((a, b) => {
1885
- const rankDiff = getLevelRank(a.type) - getLevelRank(b.type);
1898
+ const rankDiff = findingRank(a.type, failedRules) - findingRank(b.type, failedRules);
1886
1899
  if (rankDiff !== 0) return rankDiff;
1887
1900
  const fileA = a.file || "";
1888
1901
  const fileB = b.file || "";
@@ -1896,7 +1909,7 @@ function escapeCommand(value, property = false) {
1896
1909
  }
1897
1910
  function formatGithubAnnotations(result) {
1898
1911
  const outputLines = [];
1899
- const sorted = sortInfractionsDeterministic(result.infractions);
1912
+ const sorted = sortInfractionsDeterministic(result.infractions, result.failedRules);
1900
1913
  const MAX_PER_LEVEL = 10;
1901
1914
  let errorCount = 0;
1902
1915
  let warnCount = 0;
@@ -1951,7 +1964,7 @@ function formatGithubStepSummary(result) {
1951
1964
  lines.push("");
1952
1965
  lines.push("| Type | File:Line | Description | Snippet |");
1953
1966
  lines.push("| --- | --- | --- | --- |");
1954
- const sorted = sortInfractionsDeterministic(result.infractions);
1967
+ const sorted = sortInfractionsDeterministic(result.infractions, result.failedRules);
1955
1968
  for (const inf of sorted) {
1956
1969
  const loc = inf.file ? markdownCell(`${inf.file}:${inf.lineNumber || 1}`) : "history";
1957
1970
  const snippet = inf.lineSnippet ? markdownCell(inf.lineSnippet) : "-";
@@ -1991,7 +2004,7 @@ function formatPrMarkdownComment(result) {
1991
2004
  lines.push("");
1992
2005
  lines.push("| Type | File:Line | Description | Snippet |");
1993
2006
  lines.push("| :--- | :--- | :--- | :--- |");
1994
- const sorted = sortInfractionsDeterministic(result.infractions);
2007
+ const sorted = sortInfractionsDeterministic(result.infractions, result.failedRules);
1995
2008
  for (const inf of sorted) {
1996
2009
  const loc = inf.file ? markdownCell(`${inf.file}:${inf.lineNumber || 1}`) : "history";
1997
2010
  const snippet = inf.lineSnippet ? markdownCell(inf.lineSnippet) : "-";
@@ -2051,7 +2064,7 @@ function formatCheckTerminal(result) {
2051
2064
  ];
2052
2065
  lines.push(...exceptionTerminal(result));
2053
2066
  if (result.staleBaselineCount) lines.push(` ${result.staleBaselineCount} baseline findings no longer present (or now disabled/ignored).`);
2054
- for (const inf of result.infractions.slice(0, 20)) {
2067
+ for (const inf of mostImportantFirst(result.infractions, result.failedRules).slice(0, 20)) {
2055
2068
  lines.push("", ` ${result.failedRules.includes(inf.type) ? pc.red("FAIL") : pc.yellow("WARN")} [${inf.type}] ${terminalText(inf.file || "unknown")}:${inf.lineNumber}`, ` ${terminalText(inf.lineSnippet || inf.reason)}`);
2056
2069
  if (inf.suggestion) lines.push(` Next: ${terminalText(inf.suggestion)}`);
2057
2070
  }
@@ -2076,7 +2089,7 @@ function formatCheckMarkdown(result) {
2076
2089
  "| Rule | Location | Finding | Next step |",
2077
2090
  "| --- | --- | --- | --- |"
2078
2091
  ];
2079
- for (const inf of result.infractions) lines.push(`| ${inf.type} | ${markdownCell(`${inf.file}:${inf.lineNumber}`)} | ${markdownCell(inf.lineSnippet || inf.reason)} | ${markdownCell(inf.suggestion || "Review this occurrence.")} |`);
2092
+ for (const inf of mostImportantFirst(result.infractions, result.failedRules)) lines.push(`| ${inf.type} | ${markdownCell(`${inf.file}:${inf.lineNumber}`)} | ${markdownCell(inf.lineSnippet || inf.reason)} | ${markdownCell(inf.suggestion || "Review this occurrence.")} |`);
2080
2093
  lines.push(...exceptionMarkdown(result));
2081
2094
  if (result.staleBaselineCount) lines.push("", `${result.staleBaselineCount} baseline findings no longer present (or now disabled/ignored).`);
2082
2095
  for (const skipped of result.skippedFiles) lines.push("", `Not scanned: ${markdownCell(skipped.file)} \u2014 ${markdownCell(skipped.reason)}`);
@@ -2094,7 +2107,7 @@ function formatReviewTerminal(result) {
2094
2107
  lines.push(...exceptionTerminal(result));
2095
2108
  if (result.policyChanges.length) lines.push(" Candidate policy changes were ignored; adopt them separately after review.");
2096
2109
  if (result.excludedFiles || result.unsupportedFiles) lines.push(` ${result.excludedFiles} excluded \xB7 ${result.unsupportedFiles} unsupported/non-source changes`);
2097
- for (const finding2 of result.infractions.slice(0, 20)) {
2110
+ for (const finding2 of mostImportantFirst(result.infractions, result.failedRules).slice(0, 20)) {
2098
2111
  lines.push(
2099
2112
  "",
2100
2113
  ` ${result.failedRules.includes(finding2.type) ? "FAIL" : "WARN"} [${finding2.type}] ${terminalText(finding2.file || "unknown")}:${finding2.lineNumber}`,
@@ -2120,7 +2133,7 @@ function formatReviewMarkdown(result) {
2120
2133
  ];
2121
2134
  if (result.policyChanges.length) lines.push("Candidate policy changes were ignored. This review uses the supplied base commit's policy.", "");
2122
2135
  lines.push("| New finding | Head location | Evidence | Next step |", "| --- | --- | --- | --- |");
2123
- for (const finding2 of result.infractions) lines.push(`| ${finding2.type} | ${markdownCell(`${finding2.file}:${finding2.lineNumber}`)} | ${markdownCell(finding2.lineSnippet || finding2.reason)} | ${markdownCell(finding2.suggestion || "Review this occurrence.")} |`);
2136
+ for (const finding2 of mostImportantFirst(result.infractions, result.failedRules)) lines.push(`| ${finding2.type} | ${markdownCell(`${finding2.file}:${finding2.lineNumber}`)} | ${markdownCell(finding2.lineSnippet || finding2.reason)} | ${markdownCell(finding2.suggestion || "Review this occurrence.")} |`);
2124
2137
  lines.push(...exceptionMarkdown(result));
2125
2138
  if (result.removedFindings.length) {
2126
2139
  lines.push(
package/dist/cli.js CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  roastRepository,
23
23
  terminalText,
24
24
  writeBaseline
25
- } from "./chunk-NSGANOZ5.js";
25
+ } from "./chunk-FFKEBW6D.js";
26
26
 
27
27
  // src/cli.ts
28
28
  import { Command } from "commander";
package/dist/index.js CHANGED
@@ -63,7 +63,7 @@ import {
63
63
  unquoteGitPath,
64
64
  validateExceptions,
65
65
  writeBaseline
66
- } from "./chunk-NSGANOZ5.js";
66
+ } from "./chunk-FFKEBW6D.js";
67
67
  export {
68
68
  CONFIG_FILENAMES,
69
69
  ConfigError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-roast",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Offline review for AI-assisted changes: catches weakened tests, lowered quality gates, skipped tests and swallowed errors",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",