@rigour-labs/core 6.12.2-rc.5 → 6.12.2
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/dist/gates/runner.d.ts +2 -0
- package/dist/gates/runner.js +8 -0
- package/dist/review/review.d.ts +2 -0
- package/dist/review/review.js +20 -4
- package/package.json +6 -6
package/dist/gates/runner.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Gate } from './base.js';
|
|
2
2
|
import { Failure, Config, Report, DeepOptions } from '../types/index.js';
|
|
3
|
+
/** The gate a finding came from, for a finding this runner produced; else undefined. */
|
|
4
|
+
export declare function gateOf(failure: Failure): string | undefined;
|
|
3
5
|
export declare class GateRunner {
|
|
4
6
|
private config;
|
|
5
7
|
private gates;
|
package/dist/gates/runner.js
CHANGED
|
@@ -36,6 +36,12 @@ import { execa } from 'execa';
|
|
|
36
36
|
import { Logger } from '../utils/logger.js';
|
|
37
37
|
import { FileSystemCache } from '../services/filesystem-cache.js';
|
|
38
38
|
import { onChangedLines, settledChecks } from '../review/settled-checks.js';
|
|
39
|
+
/** The gate each finding of a run came from (a gate may give its findings other ids, such as `AST_COMPLEXITY`). */
|
|
40
|
+
const GATE_OF = new WeakMap();
|
|
41
|
+
/** The gate a finding came from, for a finding this runner produced; else undefined. */
|
|
42
|
+
export function gateOf(failure) {
|
|
43
|
+
return GATE_OF.get(failure);
|
|
44
|
+
}
|
|
39
45
|
export class GateRunner {
|
|
40
46
|
config;
|
|
41
47
|
gates = [];
|
|
@@ -166,6 +172,8 @@ export class GateRunner {
|
|
|
166
172
|
let skipped;
|
|
167
173
|
const gateFailures = await gate.run({ cwd, record, ignore, patterns, fileCache, skip: reason => { skipped = reason; } });
|
|
168
174
|
if (gateFailures.length > 0) {
|
|
175
|
+
for (const f of gateFailures)
|
|
176
|
+
GATE_OF.set(f, gate.id);
|
|
169
177
|
failures.push(...gateFailures);
|
|
170
178
|
summary[gate.id] = 'FAIL';
|
|
171
179
|
}
|
package/dist/review/review.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export interface ReviewResult {
|
|
|
38
38
|
excludedOutsideChangedLines: number;
|
|
39
39
|
/** Findings the base already had: counted, not reported (baseline.ts). */
|
|
40
40
|
preexisting: number;
|
|
41
|
+
/** The same, by check. A check whose findings were all the base's reads PASS in the report's summary. */
|
|
42
|
+
preexistingByCheck: Record<string, number>;
|
|
41
43
|
/** A diff given with no base whose change HEAD already holds (committed work): nothing was compared, so nothing was dropped as the base's. */
|
|
42
44
|
baseUnknown?: boolean;
|
|
43
45
|
changedLines: Record<string, Set<number>>;
|
package/dist/review/review.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* and so does a proven gate that crashed (a heuristic one is only listed).
|
|
9
9
|
*/
|
|
10
10
|
import { spawnSync } from 'child_process';
|
|
11
|
-
import { GateRunner } from '../gates/runner.js';
|
|
11
|
+
import { GateRunner, gateOf } from '../gates/runner.js';
|
|
12
12
|
import { changedLinesByFile, parseDiff, removedByFile } from '../utils/diff.js';
|
|
13
13
|
import { normalizeScopePatterns } from '../utils/scope.js';
|
|
14
14
|
import { deepAnalysisError } from '../utils/deep-status.js';
|
|
@@ -39,14 +39,14 @@ export async function reviewChange(input) {
|
|
|
39
39
|
const changedLines = withoutGenerated(input.cwd, parseDiff(diff));
|
|
40
40
|
const targets = input.files?.length ? input.files : Object.keys(changedLines);
|
|
41
41
|
if (targets.length === 0) {
|
|
42
|
-
return { status: 'PASS', findings: [], fileFindings: [], contextFindings: [], advisory: [], muted: 0, dismissed: 0, dismissedByGate: {}, unlocated: 0, excludedOutsideChangedLines: 0, preexisting: 0, changedLines, report: null, gateErrors: [], controlFilesChanged: controlFiles(diff), hints: [], covered: [] };
|
|
42
|
+
return { status: 'PASS', findings: [], fileFindings: [], contextFindings: [], advisory: [], muted: 0, dismissed: 0, dismissedByGate: {}, unlocated: 0, excludedOutsideChangedLines: 0, preexisting: 0, preexistingByCheck: {}, changedLines, report: null, gateErrors: [], controlFilesChanged: controlFiles(diff), hints: [], covered: [] };
|
|
43
43
|
}
|
|
44
44
|
// The team's compiled checks run before the deep review, so it is told what they found and which lessons they covered.
|
|
45
45
|
const compiled = compiledChecksOn(input.cwd, changedLines, input.config);
|
|
46
46
|
const deep = input.deep ? { ...input.deep, focusLines: changedLinesByFile(changedLines), removedLines: removedByFile(diff), diff, settled: settledChecks(compiled.failures), covered: compiled.covered } : undefined;
|
|
47
47
|
// The team's `commands:` run at push (toolchain.ts), where a failure blocks; here they would only cost time.
|
|
48
48
|
const report = await new GateRunner({ ...input.config, commands: {} }).run(input.cwd, await normalizeScopePatterns(input.cwd, targets), deep);
|
|
49
|
-
const { preexisting, baseUnknown } = await dropPreexisting(input, report, targets);
|
|
49
|
+
const { preexisting, byCheck: preexistingByCheck = {}, baseUnknown } = await dropPreexisting(input, report, targets);
|
|
50
50
|
if (input.diffTests && deep)
|
|
51
51
|
report.failures.push(...await diffTestFailures(input.cwd, input.source, deep));
|
|
52
52
|
// The review's own checks, each recorded in the summary beside the gates, so a report says everything that ran.
|
|
@@ -96,6 +96,7 @@ export async function reviewChange(input) {
|
|
|
96
96
|
unlocated: split.unlocated,
|
|
97
97
|
excludedOutsideChangedLines: split.outside,
|
|
98
98
|
preexisting,
|
|
99
|
+
preexistingByCheck,
|
|
99
100
|
...(baseUnknown ? { baseUnknown } : {}),
|
|
100
101
|
changedLines,
|
|
101
102
|
report,
|
|
@@ -108,6 +109,21 @@ export async function reviewChange(input) {
|
|
|
108
109
|
...(checkedGoal ? { goal: checkedGoal } : {}),
|
|
109
110
|
};
|
|
110
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* A check that failed only on what the base already had passes for this change: its summary reads PASS, and the
|
|
114
|
+
* count, by check, says what it left out. A check with a finding the change introduced keeps FAIL.
|
|
115
|
+
*/
|
|
116
|
+
function passOnlyPreexisting(report, preexisting) {
|
|
117
|
+
const byCheck = {};
|
|
118
|
+
const check = (f) => gateOf(f) ?? f.id;
|
|
119
|
+
for (const f of preexisting)
|
|
120
|
+
byCheck[check(f)] = (byCheck[check(f)] ?? 0) + 1;
|
|
121
|
+
const remaining = new Set(report.failures.map(check));
|
|
122
|
+
for (const id of Object.keys(byCheck))
|
|
123
|
+
if (report.summary[id] === 'FAIL' && !remaining.has(id))
|
|
124
|
+
report.summary[id] = 'PASS';
|
|
125
|
+
return byCheck;
|
|
126
|
+
}
|
|
111
127
|
/**
|
|
112
128
|
* Drop the rules' findings the base already had; returns how many. Model findings stay: the model reviews only the change.
|
|
113
129
|
* A diff given with no `--base` is compared with HEAD, which is right for uncommitted work. When HEAD already holds the
|
|
@@ -127,7 +143,7 @@ async function dropPreexisting(input, report, targets) {
|
|
|
127
143
|
const { preexisting } = splitIntroduced(rules, await baseFindings(input.cwd, input.config, commit, targets));
|
|
128
144
|
const old = new Set(preexisting);
|
|
129
145
|
report.failures = report.failures.filter(f => !old.has(f));
|
|
130
|
-
return { preexisting: old.size };
|
|
146
|
+
return { preexisting: old.size, byCheck: passOnlyPreexisting(report, preexisting) };
|
|
131
147
|
}
|
|
132
148
|
catch {
|
|
133
149
|
return { preexisting: 0 }; // the comparison is a courtesy; it never fails a review
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigour-labs/core",
|
|
3
|
-
"version": "6.12.2
|
|
3
|
+
"version": "6.12.2",
|
|
4
4
|
"description": "Rigour's review engine: deterministic gates on changed lines, rules and lessons learned from your team's fixes, and per-check precision from what you fix versus dismiss, across TypeScript, JavaScript, Python, Go, Ruby and C#.",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22.13"
|
|
@@ -75,11 +75,11 @@
|
|
|
75
75
|
"@anthropic-ai/sdk": "^0.132.1",
|
|
76
76
|
"pg": "^8.16.3",
|
|
77
77
|
"openai": "^5.23.2",
|
|
78
|
-
"@rigour-labs/brain-darwin-
|
|
79
|
-
"@rigour-labs/brain-linux-arm64": "6.12.2
|
|
80
|
-
"@rigour-labs/brain-
|
|
81
|
-
"@rigour-labs/brain-
|
|
82
|
-
"@rigour-labs/brain-
|
|
78
|
+
"@rigour-labs/brain-darwin-arm64": "6.12.2",
|
|
79
|
+
"@rigour-labs/brain-linux-arm64": "6.12.2",
|
|
80
|
+
"@rigour-labs/brain-darwin-x64": "6.12.2",
|
|
81
|
+
"@rigour-labs/brain-win-x64": "6.12.2",
|
|
82
|
+
"@rigour-labs/brain-linux-x64": "6.12.2"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
85
|
"@types/fs-extra": "^11.0.4",
|