@rigour-labs/cli 6.9.0 → 6.10.0-rc.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.
@@ -8,3 +8,8 @@ export declare function groupFilesByRepo(cwd: string, files: string[]): Array<{
8
8
  export declare function hookFindings(result: HookCheckerResult): Failure[];
9
9
  /** Open what this edit introduced and resolve what it fixed; fixes become stories and lessons. */
10
10
  export declare function recordEditCatches(root: string, result: HookCheckerResult, files: string[]): Promise<void>;
11
+ /** Re-checks the per-edit findings another version of the checks opened (with `all`, every open one), with this version's checks (agent-fixes.ts). */
12
+ export declare function recheckEditFindings(root: string, all?: boolean): Promise<{
13
+ closed: number;
14
+ kept: number;
15
+ }>;
@@ -5,7 +5,7 @@
5
5
  import { spawnSync } from 'child_process';
6
6
  import fs from 'fs';
7
7
  import path from 'path';
8
- import { recordFixLessons, recordReviewOutcome } from '@rigour-labs/core';
8
+ import { recheckOpenFindings, recordFixLessons, recordReviewOutcome, runHookChecker } from '@rigour-labs/core';
9
9
  /** Findings about the write or the file's size, not a defect in the code: never stories. */
10
10
  const NOT_CODE = new Set(['file-guard', 'agent-scope', 'hook-timeout', 'file-size']);
11
11
  /** Files grouped by the git repository that holds them; a file outside any repository stays with `cwd`. */
@@ -34,9 +34,15 @@ export function hookFindings(result) {
34
34
  }
35
35
  /** Open what this edit introduced and resolve what it fixed; fixes become stories and lessons. */
36
36
  export async function recordEditCatches(root, result, files) {
37
+ // After an upgrade, what the old checks reported on earlier edits is checked again by these: never credited as a fix.
38
+ await recheckEditFindings(root).catch(() => undefined);
37
39
  const capture = recordReviewOutcome(root, hookFindings(result), files, 'edit');
38
40
  await recordFixLessons(root, capture.fixes).catch(() => undefined); // learning never blocks an edit
39
41
  }
42
+ /** Re-checks the per-edit findings another version of the checks opened (with `all`, every open one), with this version's checks (agent-fixes.ts). */
43
+ export function recheckEditFindings(root, all = false) {
44
+ return recheckOpenFindings(root, 'edit', async (files) => hookFindings(await runHookChecker({ cwd: root, files: files.map(f => path.join(root, f)) })), all);
45
+ }
40
46
  /** The directory's real, long-form path; the path as given when it cannot be resolved (deleted, for example). */
41
47
  function realDir(dir) {
42
48
  try {
@@ -60,6 +60,8 @@ function printQuietLines(result, notes) {
60
60
  const before = result.preexisting + result.excludedOutsideChangedLines;
61
61
  if (before)
62
62
  lines.push(`Not shown: ${before} issue${before === 1 ? '' : 's'} the code already had before this change (review.show_preexisting: true lists them).`);
63
+ if (result.baseUnknown)
64
+ lines.push('Compared with no base: HEAD already holds this diff, so findings on its lines were not checked against the code before it. Pass --base to compare.');
63
65
  if (result.hints.length)
64
66
  lines.push(`To confirm by hand: ${result.hints.length} hint${result.hints.length === 1 ? '' : 's'}${notes ? '' : ' (rigour review --notes)'}`);
65
67
  if (result.dismissed)
@@ -66,7 +66,9 @@ export function printReviewer(result, options = {}) {
66
66
  if (result.record && result.recordPath)
67
67
  console.log(chalk.dim(` record: ${result.recordPath} (integrity ${result.record.integrity.slice(0, 16)})`));
68
68
  const tokens = result.tokens ? `, ${(result.tokens.input + result.tokens.output).toLocaleString('en-US')} tokens` : '';
69
- const cost = `${result.costUsd !== undefined ? `, $${result.costUsd.toFixed(2)}` : ''}${tokens}`;
69
+ // What every run of this review cost, failed ones included (the verdict's judges alone would under-count it).
70
+ const spent = result.spentUsd ?? result.costUsd;
71
+ const cost = `${spent !== undefined ? `, $${spent.toFixed(2)}` : ''}${tokens}`;
70
72
  console.log(` ${result.items.length} open item(s)${result.cached ? chalk.dim(' (cached for this commit)') : cost}\n`);
71
73
  }
72
74
  /** Which mode ran, against which was asked, and why: a panel never shrinks to one judge silently. */
@@ -100,7 +102,9 @@ export function reviewerJson(result) {
100
102
  dismissed: result.dismissed,
101
103
  mode: result.mode ?? null,
102
104
  panel: result.panel ?? null,
105
+ // The verdict's judges, as reported; kept for compatibility. spent_usd is every run, and 0 for a cached verdict.
103
106
  cost_usd: result.costUsd ?? null,
107
+ spent_usd: result.spentUsd ?? 0,
104
108
  tokens: result.tokens ?? null,
105
109
  cached: result.cached,
106
110
  previous_review: result.previousReview ?? null,
@@ -241,6 +241,9 @@ async function handleApiRequest(req, res, url, ctx) {
241
241
  if (url.pathname === '/api/week') {
242
242
  try {
243
243
  const { loadWeek } = await import('./studio-week.js');
244
+ // What an older version of the checks opened is checked again before it is listed (a no-op once done).
245
+ const { recheckEditFindings } = await import('./hooks-check-repos.js');
246
+ await recheckEditFindings(cwd).catch(() => undefined);
244
247
  sendJson(res, 200, loadWeek(cwd));
245
248
  }
246
249
  catch (e) {
@@ -248,6 +251,16 @@ async function handleApiRequest(req, res, url, ctx) {
248
251
  }
249
252
  return true;
250
253
  }
254
+ if (url.pathname === '/api/recheck' && req.method === 'POST') {
255
+ try {
256
+ const { recheckEditFindings } = await import('./hooks-check-repos.js');
257
+ sendJson(res, 200, await recheckEditFindings(cwd, true));
258
+ }
259
+ catch (e) {
260
+ sendJson(res, 500, { error: e.message });
261
+ }
262
+ return true;
263
+ }
251
264
  if (url.pathname === '/api/dismiss' && req.method === 'POST') {
252
265
  let body = '';
253
266
  req.on('data', (chunk) => (body += chunk));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/cli",
3
- "version": "6.9.0",
3
+ "version": "6.10.0-rc.2",
4
4
  "description": "Code review that happens while your agent writes: deterministic checks on the lines it changed, quiet unless it can prove a defect, and learning from your team's fixes and dismissals. Works with Claude Code, Cursor, Codex, Cline and Windsurf.",
5
5
  "engines": {
6
6
  "node": ">=22.13"
@@ -59,13 +59,13 @@
59
59
  "inquirer": "9.2.16",
60
60
  "ora": "^8.0.1",
61
61
  "yaml": "^2.8.2",
62
- "@rigour-labs/core": "6.9.0"
62
+ "@rigour-labs/core": "6.10.0-rc.2"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@types/fs-extra": "^11.0.4",
66
66
  "@types/inquirer": "9.0.7",
67
67
  "@types/node": "^25.0.3",
68
- "@rigour-labs/studio": "6.9.0"
68
+ "@rigour-labs/studio": "6.10.0-rc.2"
69
69
  },
70
70
  "scripts": {
71
71
  "build": "tsc && pnpm bundle-studio",