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 +11 -6
- package/dist/{chunk-NSGANOZ5.js → chunk-FFKEBW6D.js} +26 -13
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
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
|
|
118
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
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 =
|
|
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
package/dist/index.js
CHANGED
package/package.json
CHANGED