@verevoir/review 0.2.0 → 0.3.0
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 +132 -2
- package/dist/cli/bin.d.ts +2 -0
- package/dist/cli/bin.js +46 -0
- package/dist/cli/footer.d.ts +9 -0
- package/dist/cli/footer.js +59 -0
- package/dist/cli/review.d.ts +45 -0
- package/dist/cli/review.js +507 -0
- package/dist/context-assembler.d.ts +9 -0
- package/dist/context-assembler.js +118 -0
- package/dist/context-files.d.ts +33 -0
- package/dist/context-files.js +174 -0
- package/dist/context-types.d.ts +28 -0
- package/dist/context-types.js +5 -0
- package/dist/dedup.d.ts +40 -0
- package/dist/dedup.js +151 -0
- package/dist/diff-hunks.d.ts +17 -0
- package/dist/diff-hunks.js +73 -0
- package/dist/fs-source-access.d.ts +7 -0
- package/dist/fs-source-access.js +39 -0
- package/dist/parseReply.js +58 -7
- package/dist/practice-lenses.d.ts +69 -0
- package/dist/practice-lenses.js +218 -0
- package/dist/prompt.d.ts +23 -0
- package/dist/prompt.js +18 -0
- package/dist/references.d.ts +44 -0
- package/dist/references.js +312 -0
- package/dist/report.d.ts +17 -1
- package/dist/report.js +56 -3
- package/dist/run-review.d.ts +16 -0
- package/dist/run-review.js +37 -2
- package/dist/source-access.d.ts +8 -0
- package/dist/source-access.js +1 -0
- package/dist/subject-context-render.d.ts +8 -0
- package/dist/subject-context-render.js +29 -0
- package/dist/tier.d.ts +20 -0
- package/dist/tier.js +88 -0
- package/dist/warm-first.d.ts +2 -0
- package/dist/warm-first.js +21 -0
- package/lenses.default.json +30 -0
- package/package.json +5 -1
- package/src/cli/bin.ts +61 -0
- package/src/cli/footer.ts +78 -0
- package/src/cli/review.ts +647 -0
- package/src/context-files.ts +194 -0
- package/src/dedup.ts +187 -0
- package/src/parseReply.ts +58 -7
- package/src/practice-lenses.ts +265 -0
- package/src/prompt.ts +44 -0
- package/src/references.ts +381 -0
- package/src/report.ts +71 -3
- package/src/run-review.ts +55 -7
- package/src/tier.ts +103 -0
- package/src/warm-first.ts +27 -0
package/README.md
CHANGED
|
@@ -19,8 +19,8 @@ own header, and the seed commit message, for exactly what moved and why.
|
|
|
19
19
|
|
|
20
20
|
**Known gaps in this PR**, named rather than silently absorbed:
|
|
21
21
|
|
|
22
|
-
-
|
|
23
|
-
|
|
22
|
+
- The CLI (`aigency-review`, below) is a port of governance's; see "Command
|
|
23
|
+
line" for what was deliberately not ported.
|
|
24
24
|
|
|
25
25
|
All nine of v5's review test suites are ported (see "Tests" below, not
|
|
26
26
|
two), and the ported-file doc debt (stale README/ownership references) is
|
|
@@ -298,6 +298,136 @@ aigency-runtime-v2, from round 2 of an implement↔review loop onward) is
|
|
|
298
298
|
responsible for assembling the array from its own prior verdict's
|
|
299
299
|
blocking findings before calling `runPanel`/`runReviewNode` again.
|
|
300
300
|
|
|
301
|
+
## Command line
|
|
302
|
+
|
|
303
|
+
`aigency-review` runs the panel over a diff from any repository, including a
|
|
304
|
+
public one that cannot call governance's private reusable workflow:
|
|
305
|
+
|
|
306
|
+
```sh
|
|
307
|
+
npx -y @verevoir/review aigency-review --base origin/main --title "My change"
|
|
308
|
+
git diff origin/main...HEAD | npx -y @verevoir/review aigency-review
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
**Flags**
|
|
312
|
+
|
|
313
|
+
- `--base <ref>` -- review `git diff --merge-base <ref> HEAD` (run via
|
|
314
|
+
`execFile`, no shell). Needs full history. Without it, the diff is read from
|
|
315
|
+
stdin.
|
|
316
|
+
- `--title <text>` -- shown at the top of the report (default `this change`).
|
|
317
|
+
- `--lenses <path>` -- a lens set JSON file. Else `AIGENCY_REVIEW_LENSES`, else
|
|
318
|
+
the bundled default.
|
|
319
|
+
- `--description-file <path>` -- the PR description, shown under `## The change`.
|
|
320
|
+
Unreadable or blank is `could_not_run`. Without it the prompt says, in one
|
|
321
|
+
line, that no description was supplied and not to judge it.
|
|
322
|
+
- `--checks-file <path>` -- CI check results, rendered verbatim in the shared prompt under
|
|
323
|
+
`## Checks on this change` (after `## The change`, before `## The diff`). Unreadable or
|
|
324
|
+
blank is `could_not_run`. Without it the prompt says, in one line, that no check results
|
|
325
|
+
were supplied and not to assume the tests pass.
|
|
326
|
+
- References in added lines (automatic with a context root) -- ADR citations (`ADR 009`,
|
|
327
|
+
`ADR-009`, `ADR 9`) and repo-relative file paths in the diff's ADDED lines are resolved
|
|
328
|
+
deterministically (no model call) and rendered under `## References in added lines`, after
|
|
329
|
+
`## Changed files in full`. An ADR is looked up in directories named `adrs` or `adr` (depth
|
|
330
|
+
4, skipping `node_modules`, `.git`, `dist`) and shown with its path and first heading, or
|
|
331
|
+
"not found in this repository"; a path is reported as existing or not. At most 40 are
|
|
332
|
+
resolved. `..`, absolute paths and root-escaping symlinks are refused.
|
|
333
|
+
- With `--practices`, every lens also gets a tier anchor (tag `[blocking]` only when quoting
|
|
334
|
+
the signal failed) and is asked for a `REASON:` line; the report shows every lens as
|
|
335
|
+
`#### <lens>: <verdict>: <reason>`, approving lenses included.
|
|
336
|
+
- With `--practices`, the tier is enforced in code. After each lens's reply is parsed, every
|
|
337
|
+
`[blocking]` finding must contain a verbatim quote of one of THAT lens's practices'
|
|
338
|
+
`_Reject:_` / `_Expect:_` lines: after lower-casing and removing markdown emphasis, quote
|
|
339
|
+
marks and extra whitespace on both sides, a contiguous run of at least 24 characters of the
|
|
340
|
+
signal line (or all of a shorter line). Otherwise it becomes `[smell]` with
|
|
341
|
+
" (downgraded: no signal quoted)", and a lens left with no blocking finding counts as
|
|
342
|
+
approved. Bundled lenses are unchanged.
|
|
343
|
+
- De-duplication: after the panel, ONE extra call through the same reviewer asks which findings
|
|
344
|
+
(ids `lens:index`) describe the same defect. The reply must put every id in exactly one
|
|
345
|
+
group; otherwise (or if the call fails) the un-merged report is kept with a line saying
|
|
346
|
+
de-duplication was skipped and why. Each group is shown once, at its highest tier, with its
|
|
347
|
+
first member's text and `raised by: <lens> (<practices>), ...`. Per-lens verdict lines are
|
|
348
|
+
unchanged, and the call's usage appears in the footer as `dedup`. `--no-dedup` skips it. It is
|
|
349
|
+
also skipped when fewer than two findings were raised.
|
|
350
|
+
- With `--checks-file`, the checks section ends with: "If a check fails, report it once, then
|
|
351
|
+
review the rest of the change on its own merits, as if that failure were fixed."
|
|
352
|
+
- `--warm-first` / `--no-warm-first` -- run the first lens alone, then fan out
|
|
353
|
+
the rest, so they read the prompt cache the first wrote instead of every lens
|
|
354
|
+
writing the same prefix. On by default with 2 or more lenses; costs roughly one
|
|
355
|
+
extra lens-latency of wall time. A first lens that fails does not stop the rest.
|
|
356
|
+
- `--context-root <dir>` -- a tree at the change's head. Each file the diff
|
|
357
|
+
touches (paths from the `+++` headers) that still exists there is shown in
|
|
358
|
+
full, post-change, if it is 16 KB or smaller, in a shared
|
|
359
|
+
`## Changed files in full` section after `## The diff`; skipped files are listed with the reason
|
|
360
|
+
(too large, deleted, not present, binary). Paths with `..` or absolute paths
|
|
361
|
+
are refused, and so is any file whose resolved real path (symlinks followed)
|
|
362
|
+
leaves the root. With `--base` it defaults to the current directory (run from
|
|
363
|
+
the repo root); with stdin and no `--context-root` the prompt says in one line
|
|
364
|
+
that there is no file context.
|
|
365
|
+
- `-h`, `--help`.
|
|
366
|
+
|
|
367
|
+
**Environment**
|
|
368
|
+
|
|
369
|
+
- `ANTHROPIC_API_KEY` -- billed route. Else `ANTHROPIC_API_KEY_FILE`, else
|
|
370
|
+
`$XDG_CONFIG_HOME/verevoir/anthropic.key` (or `~/.config/verevoir/anthropic.key`).
|
|
371
|
+
With no key anywhere the logged-in `claude` CLI is used. A key file that is
|
|
372
|
+
unreadable or blank, or a named `ANTHROPIC_API_KEY_FILE` that does not exist,
|
|
373
|
+
blocks the run rather than silently falling back.
|
|
374
|
+
- `AIGENCY_REVIEW_LENSES` -- lens set path (see above).
|
|
375
|
+
- `AIGENCY_REVIEW_MODEL` -- default `claude-opus-5-5`.
|
|
376
|
+
- `AIGENCY_REVIEW_MAX_TOKENS` -- positive integer, default `65536`.
|
|
377
|
+
- `GITHUB_STEP_SUMMARY` -- when set, the report is appended to that file.
|
|
378
|
+
|
|
379
|
+
**Report footer.** The report ends with what judged it: the model (the id the
|
|
380
|
+
transport reported, else the requested one, said as such), the reviewer route by
|
|
381
|
+
name only (`env`, `key-file` or `claude-cli` -- never a key or a path), and one
|
|
382
|
+
per-lens line with input/output tokens (and cache tokens when non-zero) and wall
|
|
383
|
+
time. The same per-lens lines go to stderr. A route that reports no usage says
|
|
384
|
+
`usage not reported`.
|
|
385
|
+
|
|
386
|
+
**Output.** The markdown report goes to stdout; `RESULT: approved|out_of_scope|rejected|could_not_run`
|
|
387
|
+
goes to stderr.
|
|
388
|
+
|
|
389
|
+
**Exit codes** (from `exitCodeFor`, as in governance): `approved` and
|
|
390
|
+
`out_of_scope` exit `0`; `rejected` and `could_not_run` exit `1`. Anything
|
|
391
|
+
that stops a verdict (bad config, no diff, empty diff, unreadable lens set, a
|
|
392
|
+
bad flag) is `could_not_run`: red, never a pass.
|
|
393
|
+
|
|
394
|
+
**Bundled lenses.** `lenses.default.json` is a copy of
|
|
395
|
+
`verevoir/aigency-governance` `review/lenses.json` at commit `de238aa`. It is a
|
|
396
|
+
snapshot, refreshed deliberately.
|
|
397
|
+
|
|
398
|
+
**Not ported from governance's CLI**: fetching the lens set over HTTP
|
|
399
|
+
(`AIGENCY_REVIEW_LENSES_TOKEN`/`GITHUB_TOKEN`; paths only here), the
|
|
400
|
+
cited-file context built from the checkout (`citations`/`readers`), and
|
|
401
|
+
governance's `practices` fetch. The title is `--title`, not `argv[2]`.
|
|
402
|
+
|
|
403
|
+
**Derived lenses (trial, BL-424).** `--practices <dir>` reads the `*.md`
|
|
404
|
+
files directly under `<dir>` (a guardrails checkout's `corpus/practices`),
|
|
405
|
+
groups them by their front-matter `lens:` value, and makes one lens per value
|
|
406
|
+
(id and title are the value; focus is a fixed adversarial sentence plus the
|
|
407
|
+
group's `**Sensor**` / `**Look for**` text). Practices with no `lens:` are
|
|
408
|
+
warned about on stderr, reviewed by nothing, and counted in the report. A
|
|
409
|
+
tagged practice with no sensor text is `could_not_run`. It cannot be combined
|
|
410
|
+
with `--lenses`. `--print-lenses` (needs `--practices`) prints each lens's id,
|
|
411
|
+
practice ids and focus length as JSON and exits 0 with no diff and no model
|
|
412
|
+
call. `<dir>/README.md` must exist: its "Signals: reject / accept / expect" section and
|
|
413
|
+
the "keyed to different tiers" provenance paragraph are sent to every lens as the
|
|
414
|
+
bar (missing or without those headings is `could_not_run`). Each practice's sensor
|
|
415
|
+
is headed `### <id>: <title>`. `--print-prompt <lens-id>` prints the exact prompt
|
|
416
|
+
that lens would be sent for the diff and exits 0 with no model call.
|
|
417
|
+
Front-matter is parsed by a minimal reader (only the `lens:` line, as in
|
|
418
|
+
v2); no YAML library.
|
|
419
|
+
|
|
420
|
+
**GitHub Actions**
|
|
421
|
+
|
|
422
|
+
```yaml
|
|
423
|
+
- uses: actions/checkout@v4
|
|
424
|
+
with:
|
|
425
|
+
fetch-depth: 0
|
|
426
|
+
- run: npx -y @verevoir/review@<next> aigency-review --base origin/${{ github.base_ref }} --title "${{ github.event.pull_request.title }}"
|
|
427
|
+
env:
|
|
428
|
+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
429
|
+
```
|
|
430
|
+
|
|
301
431
|
## Merge policy
|
|
302
432
|
|
|
303
433
|
Merges on green, same as this organisation's other rebuild repos. "Green"
|
package/dist/cli/bin.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
// The process boundary for `aigency-review`: construct the real adapters and
|
|
4
|
+
// hand them to `main` (review.ts). No decision lives here.
|
|
5
|
+
import { execFile } from 'node:child_process';
|
|
6
|
+
import { appendFile, readFile, readdir, realpath, stat } from 'node:fs/promises';
|
|
7
|
+
import process from 'node:process';
|
|
8
|
+
import { promisify } from 'node:util';
|
|
9
|
+
import { main } from './review.js';
|
|
10
|
+
const execFileAsync = promisify(execFile);
|
|
11
|
+
async function readAll(stream) {
|
|
12
|
+
const chunks = [];
|
|
13
|
+
stream.setEncoding('utf8');
|
|
14
|
+
for await (const chunk of stream)
|
|
15
|
+
chunks.push(chunk);
|
|
16
|
+
return chunks.join('');
|
|
17
|
+
}
|
|
18
|
+
main(process.argv.slice(2), process.env, {
|
|
19
|
+
readStdin: () => readAll(process.stdin),
|
|
20
|
+
stdout: (text) => void process.stdout.write(text),
|
|
21
|
+
stderr: (text) => void process.stderr.write(text),
|
|
22
|
+
readFile: (path) => readFile(path, 'utf8'),
|
|
23
|
+
appendFile: (path, text) => appendFile(path, text, 'utf8'),
|
|
24
|
+
readDir: async (path) => (await readdir(path, { withFileTypes: true })).filter((e) => e.isFile()).map((e) => e.name),
|
|
25
|
+
listDir: async (path) => (await readdir(path, { withFileTypes: true })).map((e) => ({
|
|
26
|
+
name: e.name,
|
|
27
|
+
isDir: e.isDirectory(),
|
|
28
|
+
})),
|
|
29
|
+
realpath: (path) => realpath(path),
|
|
30
|
+
statFile: async (path) => {
|
|
31
|
+
const s = await stat(path);
|
|
32
|
+
return { size: s.size, isFile: s.isFile() };
|
|
33
|
+
},
|
|
34
|
+
}, {
|
|
35
|
+
// execFile, no shell: a ref is an argument, never parsed as a command.
|
|
36
|
+
git: async (args) => (await execFileAsync('git', [...args], { maxBuffer: 512 * 1024 * 1024 })).stdout,
|
|
37
|
+
// dist/cli/bin.js and src/cli/bin.ts both sit two levels under the package root.
|
|
38
|
+
defaultLenses: () => readFile(new URL('../../lenses.default.json', import.meta.url), 'utf8'),
|
|
39
|
+
}).then((code) => {
|
|
40
|
+
process.exitCode = code;
|
|
41
|
+
}, (cause) => {
|
|
42
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
43
|
+
process.stderr.write('RESULT: could_not_run\n');
|
|
44
|
+
process.stderr.write(`Unexpected failure: ${message}\n`);
|
|
45
|
+
process.exitCode = 1;
|
|
46
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RawCall } from '../raw-call.js';
|
|
2
|
+
export type RouteName = 'env' | 'key-file' | 'claude-cli';
|
|
3
|
+
/** The model(s) the transport reported, else the requested one, said as such. */
|
|
4
|
+
export declare function modelText(requested: string, calls: readonly RawCall[]): string;
|
|
5
|
+
/** The one line saying how many [blocking] findings tier enforcement downgraded; none for 0. */
|
|
6
|
+
export declare function tierLine(downgraded: number): string | undefined;
|
|
7
|
+
export declare function renderFooter(requested: string, route: RouteName, calls: readonly RawCall[], downgraded?: number): string;
|
|
8
|
+
/** One stderr line per lens. */
|
|
9
|
+
export declare function usageLines(calls: readonly RawCall[]): string[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// What judged a review: the model, the route (by NAME only -- never a key or a
|
|
2
|
+
// path), and per-lens token usage and wall time, from runReviewNode's `onCall`
|
|
3
|
+
// records. Pure formatting.
|
|
4
|
+
function seconds(ms) {
|
|
5
|
+
return `${(ms / 1000).toFixed(1)}s`;
|
|
6
|
+
}
|
|
7
|
+
function byLens(calls) {
|
|
8
|
+
return calls.slice().sort((a, b) => (a.lens < b.lens ? -1 : a.lens > b.lens ? 1 : 0));
|
|
9
|
+
}
|
|
10
|
+
function tokens(call) {
|
|
11
|
+
const u = call.usage;
|
|
12
|
+
if (u === undefined)
|
|
13
|
+
return 'usage not reported';
|
|
14
|
+
const cache = u.cacheReadInputTokens > 0 || u.cacheCreationInputTokens > 0
|
|
15
|
+
? ` (cache read ${String(u.cacheReadInputTokens)}, cache write ` +
|
|
16
|
+
`${String(u.cacheCreationInputTokens)})`
|
|
17
|
+
: '';
|
|
18
|
+
return `${String(u.inputTokens)} input / ${String(u.outputTokens)} output tokens${cache}`;
|
|
19
|
+
}
|
|
20
|
+
/** The model(s) the transport reported, else the requested one, said as such. */
|
|
21
|
+
export function modelText(requested, calls) {
|
|
22
|
+
const resolved = [
|
|
23
|
+
...new Set(calls.map((c) => c.resolved).filter((m) => m !== null)),
|
|
24
|
+
].sort();
|
|
25
|
+
if (resolved.length === 0) {
|
|
26
|
+
return `model \`${requested}\` (as requested; the transport reported none)`;
|
|
27
|
+
}
|
|
28
|
+
const names = resolved.map((m) => `\`${m}\``).join(', ');
|
|
29
|
+
return resolved.length === 1 && resolved[0] === requested
|
|
30
|
+
? `model ${names}`
|
|
31
|
+
: `model ${names} (requested \`${requested}\`)`;
|
|
32
|
+
}
|
|
33
|
+
/** The one line saying how many [blocking] findings tier enforcement downgraded; none for 0. */
|
|
34
|
+
export function tierLine(downgraded) {
|
|
35
|
+
return downgraded > 0
|
|
36
|
+
? `Tier: ${String(downgraded)} blocking finding(s) downgraded: no Reject/Expect signal quoted`
|
|
37
|
+
: undefined;
|
|
38
|
+
}
|
|
39
|
+
export function renderFooter(requested, route, calls, downgraded = 0) {
|
|
40
|
+
const lines = ['---', '', `Judged with ${modelText(requested, calls)}, route: ${route}.`];
|
|
41
|
+
const tier = tierLine(downgraded);
|
|
42
|
+
if (tier !== undefined)
|
|
43
|
+
lines.push('', tier);
|
|
44
|
+
if (calls.length > 0) {
|
|
45
|
+
lines.push('', 'Per-lens usage and wall time:', '');
|
|
46
|
+
for (const call of byLens(calls)) {
|
|
47
|
+
lines.push(call.failure === undefined
|
|
48
|
+
? `- \`${call.lens}\`: ${tokens(call)}, ${seconds(call.durationMs)}`
|
|
49
|
+
: `- \`${call.lens}\`: failed after ${seconds(call.durationMs)}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return lines.join('\n');
|
|
53
|
+
}
|
|
54
|
+
/** One stderr line per lens. */
|
|
55
|
+
export function usageLines(calls) {
|
|
56
|
+
return byLens(calls).map((call) => call.failure === undefined
|
|
57
|
+
? `lens ${call.lens}: ${tokens(call)}, ${seconds(call.durationMs)}\n`
|
|
58
|
+
: `lens ${call.lens}: failed after ${seconds(call.durationMs)}\n`);
|
|
59
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Reviewer } from '../panel.js';
|
|
2
|
+
import type { Outcome } from '../verdict.js';
|
|
3
|
+
import type { DirEntry } from '../references.js';
|
|
4
|
+
/** Governance's pinned default, sent to both routes. */
|
|
5
|
+
export declare const DEFAULT_MODEL = "claude-opus-5-5";
|
|
6
|
+
/** Governance's default output-token budget (billed route only). */
|
|
7
|
+
export declare const DEFAULT_MAX_TOKENS = 65536;
|
|
8
|
+
/** What the prompt's "## The change" shows when no --description-file was given. */
|
|
9
|
+
export declare const NO_DESCRIPTION_NOTE = "No PR description was supplied; do not judge the description.";
|
|
10
|
+
/** What the prompt's "## Checks on this change" shows when no --checks-file was given. */
|
|
11
|
+
export declare const NO_CHECKS_NOTE = "No check results were supplied; do not assume the tests pass.";
|
|
12
|
+
/** Ends the checks section when --checks-file is given, so a red check is reported once. */
|
|
13
|
+
export declare const RED_CI_NOTE: string;
|
|
14
|
+
export type ResultWord = Outcome;
|
|
15
|
+
export interface ReviewIo {
|
|
16
|
+
readonly readStdin: () => Promise<string>;
|
|
17
|
+
readonly stdout: (text: string) => void;
|
|
18
|
+
readonly stderr: (text: string) => void;
|
|
19
|
+
/** Read a UTF-8 file. Must reject with an error carrying a `code` like fs does. */
|
|
20
|
+
readonly readFile: (path: string) => Promise<string>;
|
|
21
|
+
readonly appendFile: (path: string, text: string) => Promise<void>;
|
|
22
|
+
/** File names directly under a directory (no recursion, files only). */
|
|
23
|
+
readonly readDir: (path: string) => Promise<string[]>;
|
|
24
|
+
/** Resolve symlinks (fs.realpath). Rejects with an fs-style `code` if absent. */
|
|
25
|
+
readonly realpath: (path: string) => Promise<string>;
|
|
26
|
+
readonly statFile: (path: string) => Promise<{
|
|
27
|
+
readonly size: number;
|
|
28
|
+
readonly isFile: boolean;
|
|
29
|
+
}>;
|
|
30
|
+
/** List a directory's entries (for the ADR search). Optional: absent, ADRs are not searched. */
|
|
31
|
+
readonly listDir?: (path: string) => Promise<DirEntry[]>;
|
|
32
|
+
}
|
|
33
|
+
export interface ReviewCliDeps {
|
|
34
|
+
/** Run git with these args (no shell) and return stdout. Rejects on failure. */
|
|
35
|
+
readonly git: (args: readonly string[]) => Promise<string>;
|
|
36
|
+
/** Overrides the reviewer; omitted, the route is selected from the account. */
|
|
37
|
+
readonly reviewer?: Reviewer;
|
|
38
|
+
/** The bundled default lens set's JSON text. */
|
|
39
|
+
readonly defaultLenses: () => Promise<string>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Run the review. Returns the process exit code; never throws (anything
|
|
43
|
+
* unexpected is reported as could_not_run).
|
|
44
|
+
*/
|
|
45
|
+
export declare function main(argv: readonly string[], env: Record<string, string | undefined>, io: ReviewIo, deps: ReviewCliDeps): Promise<number>;
|