@rigour-labs/core 6.6.6 → 6.7.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.
Files changed (133) hide show
  1. package/README.md +16 -92
  2. package/dist/environment.test.js +0 -4
  3. package/dist/gates/agent-team.d.ts +0 -2
  4. package/dist/gates/agent-team.js +0 -8
  5. package/dist/gates/checkpoint.d.ts +0 -1
  6. package/dist/gates/checkpoint.js +0 -1
  7. package/dist/gates/context.d.ts +0 -4
  8. package/dist/gates/context.js +7 -17
  9. package/dist/gates/deep-analysis.d.ts +0 -1
  10. package/dist/gates/deep-runner.js +0 -1
  11. package/dist/gates/frontend-secret-exposure.test.js +2 -2
  12. package/dist/gates/hallucinated-imports/index.d.ts +0 -2
  13. package/dist/gates/hallucinated-imports/index.js +2 -2
  14. package/dist/gates/hallucinated-imports/js-resolver.js +1 -0
  15. package/dist/gates/hallucinated-imports.test.js +10 -0
  16. package/dist/gates/runner.js +3 -4
  17. package/dist/gates/test-quality-matchers.d.ts +0 -4
  18. package/dist/gates/test-quality-matchers.js +0 -7
  19. package/dist/gates/test-quality.d.ts +0 -2
  20. package/dist/gates/test-quality.js +1 -10
  21. package/dist/hooks/checker.js +1 -1
  22. package/dist/hooks/index.d.ts +1 -2
  23. package/dist/hooks/index.js +0 -1
  24. package/dist/hooks/types.d.ts +0 -14
  25. package/dist/hooks/types.js +1 -15
  26. package/dist/index.d.ts +6 -1
  27. package/dist/index.js +6 -1
  28. package/dist/inference/cloud-provider.d.ts +2 -0
  29. package/dist/inference/cloud-provider.js +16 -6
  30. package/dist/inference/cloud-provider.test.js +21 -0
  31. package/dist/pattern-index/embeddings.d.ts +0 -5
  32. package/dist/pattern-index/embeddings.js +11 -4
  33. package/dist/pattern-index/semantic-runtime.d.ts +10 -0
  34. package/dist/pattern-index/semantic-runtime.js +46 -0
  35. package/dist/pattern-index/semantic-runtime.test.d.ts +1 -0
  36. package/dist/pattern-index/semantic-runtime.test.js +31 -0
  37. package/dist/review/backtest-judges.d.ts +38 -0
  38. package/dist/review/backtest-judges.js +63 -0
  39. package/dist/review/backtest-judges.test.d.ts +1 -0
  40. package/dist/review/backtest-judges.test.js +32 -0
  41. package/dist/review/backtest.d.ts +9 -4
  42. package/dist/review/backtest.js +19 -9
  43. package/dist/review/backtest.test.js +2 -2
  44. package/dist/review/baseline.js +2 -1
  45. package/dist/review/dead-code.test.js +7 -0
  46. package/dist/review/fix-scope.d.ts +21 -0
  47. package/dist/review/fix-scope.js +94 -0
  48. package/dist/review/fix-scope.test.d.ts +1 -0
  49. package/dist/review/fix-scope.test.js +104 -0
  50. package/dist/review/lint-overlay.js +1 -1
  51. package/dist/review/orphan-files.js +3 -2
  52. package/dist/review/partial-wiring.js +5 -3
  53. package/dist/review/query-patterns.js +3 -2
  54. package/dist/review/review.js +2 -1
  55. package/dist/review/reviewer/adapters.d.ts +23 -7
  56. package/dist/review/reviewer/adapters.js +32 -7
  57. package/dist/review/reviewer/adapters.test.d.ts +1 -0
  58. package/dist/review/reviewer/adapters.test.js +23 -0
  59. package/dist/review/reviewer/background.d.ts +8 -1
  60. package/dist/review/reviewer/background.js +34 -9
  61. package/dist/review/reviewer/background.test.js +16 -2
  62. package/dist/review/reviewer/consensus.d.ts +36 -0
  63. package/dist/review/reviewer/consensus.js +144 -0
  64. package/dist/review/reviewer/context.d.ts +75 -0
  65. package/dist/review/reviewer/context.js +140 -0
  66. package/dist/review/reviewer/context.test.d.ts +1 -0
  67. package/dist/review/reviewer/context.test.js +18 -0
  68. package/dist/review/reviewer/exec.js +6 -2
  69. package/dist/review/reviewer/exec.test.d.ts +1 -0
  70. package/dist/review/reviewer/exec.test.js +23 -0
  71. package/dist/review/reviewer/inputs.d.ts +2 -0
  72. package/dist/review/reviewer/inputs.js +5 -1
  73. package/dist/review/reviewer/panel.d.ts +67 -0
  74. package/dist/review/reviewer/panel.js +101 -0
  75. package/dist/review/reviewer/panel.test.d.ts +1 -0
  76. package/dist/review/reviewer/panel.test.js +110 -0
  77. package/dist/review/reviewer/prompt.d.ts +11 -0
  78. package/dist/review/reviewer/prompt.js +26 -4
  79. package/dist/review/reviewer/settings.d.ts +58 -0
  80. package/dist/review/reviewer/settings.js +152 -0
  81. package/dist/review/reviewer/settings.test.d.ts +1 -0
  82. package/dist/review/reviewer/settings.test.js +57 -0
  83. package/dist/review/reviewer/store.d.ts +25 -2
  84. package/dist/review/reviewer/store.js +43 -1
  85. package/dist/review/reviewer/usage.d.ts +2 -0
  86. package/dist/review/reviewer/usage.js +28 -0
  87. package/dist/review/reviewer/usage.test.d.ts +1 -0
  88. package/dist/review/reviewer/usage.test.js +14 -0
  89. package/dist/review/reviewer/verdict.d.ts +15 -1
  90. package/dist/review/reviewer/verdict.js +17 -7
  91. package/dist/review/reviewer.d.ts +45 -2
  92. package/dist/review/reviewer.js +186 -25
  93. package/dist/review/reviewer.test.js +127 -12
  94. package/dist/review/test-files.d.ts +5 -1
  95. package/dist/review/test-files.js +6 -2
  96. package/dist/review/toolchain.js +10 -3
  97. package/dist/review/toolchain.test.js +6 -3
  98. package/dist/review/typed/program.d.ts +0 -1
  99. package/dist/review/typed/program.js +3 -3
  100. package/dist/review/typed/redundancy.js +43 -4
  101. package/dist/review/typed/redundancy.test.js +58 -0
  102. package/dist/review/typed/schema-nullability.d.ts +6 -0
  103. package/dist/review/typed/schema-nullability.js +218 -0
  104. package/dist/review/typed/schema-nullability.test.d.ts +1 -0
  105. package/dist/review/typed/schema-nullability.test.js +63 -0
  106. package/dist/review/unused-exports.js +5 -6
  107. package/dist/semantic/learn/types.d.ts +2 -2
  108. package/dist/services/adaptive-thresholds.d.ts +2 -52
  109. package/dist/services/adaptive-thresholds.js +2 -147
  110. package/dist/services/adaptive-thresholds.test.js +1 -81
  111. package/dist/settings.d.ts +14 -6
  112. package/dist/settings.js +0 -12
  113. package/dist/storage/team-diagnostics.js +1 -1
  114. package/dist/storage/team-schema.d.ts +1 -1
  115. package/dist/storage/team-schema.js +2 -0
  116. package/dist/storage/team-store.js +26 -3
  117. package/dist/storage/team-sync-scope.test.js +35 -2
  118. package/dist/telemetry/telemetry.d.ts +5 -0
  119. package/dist/telemetry/telemetry.js +11 -1
  120. package/dist/templates/paradigms.js +0 -8
  121. package/dist/templates/presets.d.ts +0 -1
  122. package/dist/templates/presets.js +0 -23
  123. package/dist/templates/universal-config.js +8 -45
  124. package/dist/types/index.d.ts +108 -566
  125. package/dist/types/index.js +41 -66
  126. package/dist/types/index.test.d.ts +1 -0
  127. package/dist/types/index.test.js +33 -0
  128. package/dist/utils/command-line.d.ts +8 -0
  129. package/dist/utils/command-line.js +8 -0
  130. package/dist/utils/command-line.test.d.ts +1 -0
  131. package/dist/utils/command-line.test.js +8 -0
  132. package/dist/utils/profile.js +1 -1
  133. package/package.json +6 -7
@@ -8,6 +8,10 @@
8
8
  import fs from 'fs';
9
9
  import path from 'path';
10
10
  import { GH_TIMEOUT_MS } from './exec.js';
11
+ /** The local calendar day, as a team's "per day" means it. */
12
+ function localDay(at = new Date()) {
13
+ return `${at.getFullYear()}-${String(at.getMonth() + 1).padStart(2, '0')}-${String(at.getDate()).padStart(2, '0')}`;
14
+ }
11
15
  export class VerdictStore {
12
16
  dir;
13
17
  constructor(dir) {
@@ -46,7 +50,45 @@ export class VerdictStore {
46
50
  const previous = this.branchState(branch);
47
51
  this.writeJson(this.branchFile(branch), { ...state, chain: state.mode === 'delta' ? (previous?.chain ?? 0) + 1 : 0, at: new Date().toISOString() });
48
52
  }
49
- /** The branch's record (`json`), the background reviewer's `pid` and `log`. */
53
+ /** Today's spend, summed from the day's append-only log (one line per run or batch of runs). */
54
+ spend(day = localDay()) {
55
+ let text = '';
56
+ try {
57
+ text = fs.readFileSync(this.spendFile(day), 'utf8');
58
+ }
59
+ catch {
60
+ return { runs: 0, usd: 0 };
61
+ }
62
+ return text.split('\n').filter(Boolean).reduce((sum, line) => {
63
+ try {
64
+ const entry = JSON.parse(line);
65
+ return { runs: sum.runs + (Number(entry.runs) || 0), usd: sum.usd + (Number(entry.usd) || 0) };
66
+ }
67
+ catch {
68
+ return sum;
69
+ }
70
+ }, { runs: 0, usd: 0 });
71
+ }
72
+ /** Adds runs and reported dollars to today's log: an append, so the background reviewer and a person's run never lose each other's count. */
73
+ addSpend(runs, usd, day = localDay()) {
74
+ fs.mkdirSync(path.join(this.dir, 'spend'), { recursive: true });
75
+ fs.appendFileSync(this.spendFile(day), `${JSON.stringify({ runs, ...(usd ? { usd } : {}), at: new Date().toISOString() })}\n`);
76
+ }
77
+ spendFile(day) {
78
+ return path.join(this.dir, 'spend', `${day}.jsonl`);
79
+ }
80
+ /** The decision a verdict led to (what blocks, what is disputed or a note), kept so the same commit is not decided again. */
81
+ decidedPath(verdictPath) {
82
+ return verdictPath.replace(/\.json$/, '.decided.json');
83
+ }
84
+ /** A review on the branch that ended without a verdict, and why: what the status shows instead of "no verdict yet". */
85
+ recordAttempt(branch, attempt) {
86
+ this.writeJson(this.branchFile(branch, 'attempt'), attempt);
87
+ }
88
+ attempt(branch) {
89
+ return this.readJson(this.branchFile(branch, 'attempt'));
90
+ }
91
+ /** The branch's record (`json`), its last attempt without a verdict (`attempt`), the background reviewer's `pid` and `log`. */
50
92
  branchFile(branch, kind = 'json') {
51
93
  return path.join(this.dir, 'branches', `${branch.replace(/[^A-Za-z0-9._-]/g, '_')}.${kind}`);
52
94
  }
@@ -0,0 +1,2 @@
1
+ import type { ReviewerResult } from '../reviewer.js';
2
+ export declare function reviewerUsage(result: ReviewerResult, trigger: string): Record<string, unknown>;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * What the reviewer did, as anonymous opt-in telemetry (TELEMETRY.md): counts and buckets only, never code, file
3
+ * names, finding text or ids. It answers whether anyone turns the panel on, what actually runs, and what it costs.
4
+ */
5
+ import { costBucket } from '../../telemetry/telemetry.js';
6
+ export function reviewerUsage(result, trigger) {
7
+ const mode = result.mode;
8
+ return {
9
+ outcome: result.outcome,
10
+ trigger,
11
+ scope: result.scope,
12
+ asked: mode?.asked,
13
+ ran: mode?.ran,
14
+ source: mode?.source,
15
+ degraded: !!mode?.degraded,
16
+ escalation: mode?.escalation ? (mode.ran === 'single' ? 'one-judge' : 'all-judges') : undefined,
17
+ refused: mode?.refused?.length ?? 0,
18
+ judges: result.reviewers.length,
19
+ cached: result.cached,
20
+ confirmed: result.items.length,
21
+ disputed: result.disputed.length,
22
+ dropped: result.dropped.length,
23
+ notes: result.notes.length,
24
+ dismissed: result.dismissed.length,
25
+ runs: result.runs,
26
+ cost_bucket: costBucket(result.costUsd),
27
+ };
28
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,14 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { reviewerUsage } from './usage.js';
3
+ const item = { id: 'abcdef0123', kind: 'finding', class: 'correctness', file: 'src/secret-path.ts', line: 2, issue: 'private text' };
4
+ describe('reviewer usage telemetry', () => {
5
+ it('reports counts and buckets only: never file names, finding text or ids', () => {
6
+ const result = { outcome: 'findings', items: [item], unverified: [], resolved: [], answerInReply: [], notes: [], disputed: [item, item], dropped: [], dismissed: [], reviewers: ['claude', 'codex', 'cursor'], scope: 'delta', cached: false, costUsd: 0.7, runs: 5,
7
+ mode: { asked: 'panel', ran: 'panel', source: 'team', escalation: '2 risky changed function(s)' } };
8
+ const usage = reviewerUsage(result, 'push');
9
+ expect(usage).toEqual({ outcome: 'findings', trigger: 'push', scope: 'delta', asked: 'panel', ran: 'panel', source: 'team', degraded: false, escalation: 'all-judges', refused: 0, judges: 3, cached: false, confirmed: 1, disputed: 2, dropped: 0, notes: 0, dismissed: 0, runs: 5, cost_bucket: '$0.50-2' });
10
+ const text = JSON.stringify(usage);
11
+ for (const leak of ['secret-path', 'private text', 'abcdef0123'])
12
+ expect(text).not.toContain(leak);
13
+ });
14
+ });
@@ -1,3 +1,5 @@
1
+ import type { Spend, Tokens } from './adapters.js';
2
+ import type { PanelItem } from './panel.js';
1
3
  export interface PriorPoint {
2
4
  point: string;
3
5
  review?: string;
@@ -57,6 +59,7 @@ export interface Finding {
57
59
  line?: number;
58
60
  issue: string;
59
61
  why?: string;
62
+ consequence?: string;
60
63
  reviewer?: string;
61
64
  }
62
65
  export interface Verdict {
@@ -73,10 +76,17 @@ export interface Verdict {
73
76
  }>;
74
77
  reviewer?: string;
75
78
  cost_usd?: number;
79
+ tokens?: Tokens;
76
80
  reviewers?: Array<{
77
81
  reviewer: string;
78
82
  cost_usd?: number;
83
+ tokens?: Tokens;
79
84
  }>;
85
+ /** With a panel: every judge's own item ids, and the panel's decision on each finding (reviewer/panel.ts). */
86
+ panel?: {
87
+ judgeItemIds: string[];
88
+ items: PanelItem[];
89
+ };
80
90
  }
81
91
  export interface OpenItem {
82
92
  id: string;
@@ -86,6 +96,8 @@ export interface OpenItem {
86
96
  line?: number;
87
97
  issue: string;
88
98
  evidence?: string;
99
+ /** For a finding: the wrong outcome or the cost. A finding without one is a note, never a block. */
100
+ consequence?: string;
89
101
  reviewer?: string;
90
102
  /** In delta mode, how the item reached this verdict. */
91
103
  status?: 'carried' | 'not accounted for';
@@ -93,7 +105,7 @@ export interface OpenItem {
93
105
  /** Checks a file (and a line) against the checkout; an item that fails cannot block. */
94
106
  export type Verify = (file: string, line: number | undefined) => boolean;
95
107
  /** The verdict in a reviewer's answer, or why it is not one. `needsPriorPoints`: a human review exists and none of its points is carried. */
96
- export declare function parseVerdict(text: string, needsPriorPoints: boolean, reviewer: string, costUsd: number | undefined): {
108
+ export declare function parseVerdict(text: string, needsPriorPoints: boolean, reviewer: string, spend: Spend): {
97
109
  verdict: Verdict;
98
110
  } | {
99
111
  error: string;
@@ -120,6 +132,8 @@ export interface Accounting {
120
132
  }>;
121
133
  /** Prior points the human marked non-blocking and the code still leaves open: for the reply. */
122
134
  answerInReply: PriorPoint[];
135
+ /** Findings with no wrong outcome and no cost (an opinion): shown, never a block, however many judges agree. */
136
+ notes: OpenItem[];
123
137
  }
124
138
  /** Everything the reviewers reported blocks; in delta mode, previous open items carry unless resolved with evidence. */
125
139
  export declare function account(verdict: Verdict, previousOpen: OpenItem[] | undefined, verify: Verify): Accounting;
@@ -11,7 +11,7 @@ import { createHash } from 'crypto';
11
11
  const SHAPE = ['prior_points', 'reads', 'findings'];
12
12
  const LISTS = ['redundant', 'scans', 'merge_impact', 'carried', 'resolved_previous'];
13
13
  /** The verdict in a reviewer's answer, or why it is not one. `needsPriorPoints`: a human review exists and none of its points is carried. */
14
- export function parseVerdict(text, needsPriorPoints, reviewer, costUsd) {
14
+ export function parseVerdict(text, needsPriorPoints, reviewer, spend) {
15
15
  const parsed = verdictIn(text);
16
16
  if (!parsed || !SHAPE.every(key => Array.isArray(parsed[key])))
17
17
  return { error: `${reviewer}: no valid verdict (${text.slice(0, 200).replace(/\s+/g, ' ')})` };
@@ -20,7 +20,7 @@ export function parseVerdict(text, needsPriorPoints, reviewer, costUsd) {
20
20
  for (const key of LISTS)
21
21
  if (!Array.isArray(parsed[key]))
22
22
  parsed[key] = [];
23
- return { verdict: { ...parsed, reviewer, ...(costUsd !== undefined ? { cost_usd: costUsd } : {}) } };
23
+ return { verdict: { ...parsed, reviewer, ...(spend.costUsd !== undefined ? { cost_usd: spend.costUsd } : {}), ...(spend.tokens ? { tokens: spend.tokens } : {}) } };
24
24
  }
25
25
  /** The whole answer, a fenced block, or the last object that starts with "prior_points" (a model sometimes writes a summary around it). */
26
26
  function verdictIn(text) {
@@ -65,7 +65,7 @@ export function mergeVerdicts(parts) {
65
65
  findings: tagged(part => part.findings),
66
66
  carried: parts.flatMap(part => part.carried),
67
67
  resolved_previous: parts.length === 1 ? parts[0].resolved_previous : parts[0].resolved_previous.filter(x => parts.every(part => part.resolved_previous.some(y => y.id === x.id))),
68
- reviewers: parts.map(part => ({ reviewer: part.reviewer ?? '?', ...(part.cost_usd !== undefined ? { cost_usd: part.cost_usd } : {}) })),
68
+ reviewers: parts.map(part => ({ reviewer: part.reviewer ?? '?', ...(part.cost_usd !== undefined ? { cost_usd: part.cost_usd } : {}), ...(part.tokens ? { tokens: part.tokens } : {}) })),
69
69
  };
70
70
  }
71
71
  /**
@@ -132,8 +132,18 @@ export function account(verdict, previousOpen, verify) {
132
132
  if (m.holds === false)
133
133
  add({ id: id('correctness', m.call_site, m.symbol), kind: 'merge', class: 'correctness', file: m.call_site.split(':')[0], line: Number(m.call_site.split(':')[1]) || undefined, issue: `${m.symbol} from ${m.main_file} changed in main: ${m.why}`, reviewer: m.reviewer });
134
134
  }
135
- for (const f of verdict.findings)
136
- add({ id: id(f.class, f.file, f.issue), kind: 'finding', class: f.class, file: f.file, line: f.line, issue: f.issue, evidence: f.why, reviewer: f.reviewer });
135
+ const notes = [];
136
+ const stillOpen = new Set((previousOpen ?? []).map(item => item.id));
137
+ for (const f of verdict.findings) {
138
+ const item = { id: id(f.class, f.file, f.issue), kind: 'finding', class: f.class, file: f.file, line: f.line, issue: f.issue, evidence: f.why, ...(f.consequence?.trim() ? { consequence: f.consequence.trim() } : {}), reviewer: f.reviewer };
139
+ // An opinion is a finding the judge said has no consequence: an empty one. A missing field fails closed, and an
140
+ // item already open from the last round stays open until it is resolved with evidence.
141
+ const opinion = typeof f.consequence === 'string' && !f.consequence.trim() && !stillOpen.has(item.id);
142
+ if (!opinion)
143
+ add(item);
144
+ else if (!notes.some(n => n.id === item.id))
145
+ notes.push(item);
146
+ }
137
147
  const resolved = [];
138
148
  if (previousOpen) {
139
149
  const evidence = new Map(verdict.resolved_previous.filter(r => r?.id && r.evidence).map(r => [r.id, r.evidence]));
@@ -146,11 +156,11 @@ export function account(verdict, previousOpen, verify) {
146
156
  }
147
157
  }
148
158
  }
149
- return { open, unverified, resolved, answerInReply };
159
+ return { open, unverified, resolved, answerInReply, notes };
150
160
  }
151
161
  export function itemLine(item) {
152
162
  const where = item.file ? ` ${item.file}${item.line ? `:${item.line}` : ''}` : '';
153
163
  const by = item.reviewer ? ` (${item.reviewer})` : '';
154
164
  const status = item.status ? `, ${item.status}` : '';
155
- return `[${item.class}${status}]${by}${where} ${item.issue}${item.evidence ? `\n ${item.evidence}` : ''}`;
165
+ return `[${item.class}${status}]${by}${where} ${item.issue}${item.consequence ? `\n consequence: ${item.consequence}` : ''}${item.evidence ? `\n ${item.evidence}` : ''}`;
156
166
  }
@@ -1,6 +1,8 @@
1
1
  import type { Config } from '../types/index.js';
2
- import { type ReviewerName } from './reviewer/adapters.js';
2
+ import { type ReviewerName, type Tokens } from './reviewer/adapters.js';
3
3
  import { type Exec, type Progress } from './reviewer/exec.js';
4
+ import { type PanelItem } from './reviewer/panel.js';
5
+ import { type RunChoice, type Source } from './reviewer/settings.js';
4
6
  import { type Accounting, type OpenItem, type PriorPoint } from './reviewer/verdict.js';
5
7
  export { defaultExec, githubEnv, parseJsonArrays, type Exec, type Progress } from './reviewer/exec.js';
6
8
  export { itemLine, type OpenItem } from './reviewer/verdict.js';
@@ -12,12 +14,18 @@ export interface ReviewerOptions {
12
14
  reviewsBefore?: string;
13
15
  /** At push the ready-pull-request rule applies; a review command or a backtest always reviews. */
14
16
  trigger?: 'push' | 'review' | 'backtest';
15
- /** Two vendors, verdicts merged: the step before requesting a human review. */
17
+ /** Two vendors over the whole branch, never a delta: the step before requesting a human review. */
16
18
  full?: boolean;
19
+ /** This run's own choice of mode and panel, the nearest layer of the settings (reviewer/settings.ts). */
20
+ choice?: RunChoice;
17
21
  /** Review again even when a verdict for these inputs is cached. */
18
22
  force?: boolean;
19
23
  /** Deterministic hints (a nested scan, a property that only leaves through serialisation): candidates for the reviewer to confirm. */
20
24
  hints?: string;
25
+ /** What Rigour's checks already found on this change: settled, so no judge spends a turn finding it again. */
26
+ checks?: string[];
27
+ /** Where the team's state lives (.rigour: dismissals, reviewed functions) when cwd is a worktree that lacks it. */
28
+ stateRoot?: string;
21
29
  /** The branch the commit was pushed from, when reviewing it in a detached worktree (background.ts). */
22
30
  branch?: string;
23
31
  }
@@ -31,17 +39,52 @@ export interface ReviewerResult {
31
39
  resolved: Accounting['resolved'];
32
40
  /** Non-blocking human points still open: answered in the reply, not held against the push. */
33
41
  answerInReply: PriorPoint[];
42
+ /** Findings with no wrong outcome and no cost: shown, never a block. */
43
+ notes: OpenItem[];
44
+ /** Panel findings without a majority: shown, never a block, not carried to the next round. */
45
+ disputed: OpenItem[];
46
+ /** Panel findings refuted with evidence: logged, never a block. */
47
+ dropped: OpenItem[];
48
+ /** Findings the team dismissed as not a bug (`rigour dismiss <id>`), raised again: shown, never a block. */
49
+ dismissed: OpenItem[];
50
+ /** The panel's decision on every finding, with each judge's call: what a later re-scoring fits on. */
51
+ panel?: PanelItem[];
34
52
  /** Why there is no verdict (unavailable) or why none was sought (skipped). */
35
53
  reason?: string;
36
54
  reviewers: ReviewerName[];
37
55
  scope?: 'full' | 'delta';
38
56
  why?: string;
39
57
  costUsd?: number;
58
+ /** Tokens every run reported, summed: the only measure of a CLI that reports no dollars (Codex). */
59
+ tokens?: Tokens;
60
+ /** Whether the team lets people dismiss these findings (review.reviewer.dismissals). */
61
+ dismissable?: boolean;
62
+ /** Agent runs behind this verdict: one per judge, plus each cross-examination. */
63
+ runs?: number;
64
+ /** The mode asked for, the one that ran, where the choice came from, and why it ran with fewer judges. */
65
+ mode?: ModeRecord;
40
66
  cached: boolean;
41
67
  /** The latest human review it worked from (`<login>, <date> (<n> reviews)`). */
42
68
  previousReview?: string;
43
69
  pr?: number;
44
70
  }
71
+ export interface ModeRecord {
72
+ asked: 'single' | 'cross' | 'full' | 'panel';
73
+ ran: 'single' | 'cross' | 'full' | 'panel';
74
+ source: Source;
75
+ /** Why fewer judges ran than were asked for. */
76
+ degraded?: string;
77
+ /** Nearer choices that were not applied, such as a user turning off a panel the team requires. */
78
+ refused?: string[];
79
+ /** With escalate: risk, why this review got one judge or all of them. */
80
+ escalation?: string;
81
+ }
45
82
  /** Findings and no verdict stop a push; a skipped review does not, and is reported as owed. */
46
83
  export declare function reviewerBlocks(result: ReviewerResult): boolean;
84
+ /** The reviewer, and one anonymous usage event for what it did (only when the person opted in to telemetry). */
47
85
  export declare function runReviewer(cwd: string, base: string, config: Config, exec?: Exec, progress?: Progress, options?: ReviewerOptions): Promise<ReviewerResult>;
86
+ /**
87
+ * Before any checkout or typed review: whether this push gets a model review at all (an open, ready
88
+ * pull request, `on_push`). The background job asks first, so a push nobody will read costs one lookup.
89
+ */
90
+ export declare function pushReviewSkip(cwd: string, branch: string, head: string, config: Config, exec?: Exec): Promise<string | undefined>;