@zephyrdeng/pi-review 0.19.0 → 0.20.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 +1 -0
- package/README.zh-CN.md +1 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +18 -0
- package/dist/args.js.map +1 -1
- package/dist/claude-plugin-sync.test.d.ts +2 -0
- package/dist/claude-plugin-sync.test.d.ts.map +1 -0
- package/dist/claude-plugin-sync.test.js +33 -0
- package/dist/claude-plugin-sync.test.js.map +1 -0
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/meta-footer.d.ts +3 -1
- package/dist/meta-footer.d.ts.map +1 -1
- package/dist/meta-footer.js +10 -0
- package/dist/meta-footer.js.map +1 -1
- package/dist/panel.d.ts.map +1 -1
- package/dist/panel.js +6 -1
- package/dist/panel.js.map +1 -1
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +5 -1
- package/dist/review.js.map +1 -1
- package/dist/types.d.ts +60 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/verify-cli.d.ts +14 -0
- package/dist/verify-cli.d.ts.map +1 -0
- package/dist/verify-cli.js +223 -0
- package/dist/verify-cli.js.map +1 -0
- package/dist/verify-cli.test.d.ts +2 -0
- package/dist/verify-cli.test.d.ts.map +1 -0
- package/dist/verify-cli.test.js +208 -0
- package/dist/verify-cli.test.js.map +1 -0
- package/dist/verify-regression.test.d.ts +2 -0
- package/dist/verify-regression.test.d.ts.map +1 -0
- package/dist/verify-regression.test.js +307 -0
- package/dist/verify-regression.test.js.map +1 -0
- package/dist/verify.d.ts +151 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +737 -0
- package/dist/verify.js.map +1 -0
- package/dist/verify.test.d.ts +2 -0
- package/dist/verify.test.d.ts.map +1 -0
- package/dist/verify.test.js +442 -0
- package/dist/verify.test.js.map +1 -0
- package/package.json +1 -1
- package/resources/review-presets.json +3 -3
- package/skills/pi-review/SKILL.md +25 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
// CLI-level verify tests: the show/approve/run handshake and end-to-end
|
|
2
|
+
// injection into single, panel, and loop reviews. Pi is a fake script; no
|
|
3
|
+
// network, no real model.
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
|
+
import { afterEach, test } from "vitest";
|
|
11
|
+
import { buildProposerPrompt, extractJsonObject } from "./verify-cli.js";
|
|
12
|
+
const NODE = process.execPath;
|
|
13
|
+
const repoRoot = path.dirname(fileURLToPath(new URL("../package.json", import.meta.url)));
|
|
14
|
+
const tsxLoader = pathToFileURL(path.join(repoRoot, "node_modules/tsx/dist/loader.mjs")).href;
|
|
15
|
+
const temps = [];
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
for (const dir of temps.splice(0))
|
|
18
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
19
|
+
});
|
|
20
|
+
function tmp(prefix) {
|
|
21
|
+
const dir = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), prefix)));
|
|
22
|
+
temps.push(dir);
|
|
23
|
+
return dir;
|
|
24
|
+
}
|
|
25
|
+
function git(cwd, ...args) {
|
|
26
|
+
const result = spawnSync("git", args, { cwd, encoding: "utf8" });
|
|
27
|
+
if (result.status !== 0)
|
|
28
|
+
throw new Error(result.stderr);
|
|
29
|
+
return result.stdout;
|
|
30
|
+
}
|
|
31
|
+
function makeRepo(whitelist) {
|
|
32
|
+
const dir = tmp("pi-review-verify-cli-repo-");
|
|
33
|
+
git(dir, "init", "-q");
|
|
34
|
+
git(dir, "config", "user.email", "t@example.com");
|
|
35
|
+
git(dir, "config", "user.name", "t");
|
|
36
|
+
git(dir, "config", "commit.gpgsign", "false");
|
|
37
|
+
fs.writeFileSync(path.join(dir, "a.txt"), "hello\n");
|
|
38
|
+
if (whitelist)
|
|
39
|
+
fs.writeFileSync(path.join(dir, ".pi-review.json"), JSON.stringify(whitelist));
|
|
40
|
+
git(dir, "add", "-A");
|
|
41
|
+
git(dir, "commit", "-qm", "init");
|
|
42
|
+
fs.writeFileSync(path.join(dir, "a.txt"), "hello, uncommitted\n");
|
|
43
|
+
return dir;
|
|
44
|
+
}
|
|
45
|
+
function writeFakePi(dir, reply) {
|
|
46
|
+
const argvDir = path.join(dir, "argv");
|
|
47
|
+
fs.mkdirSync(argvDir);
|
|
48
|
+
const bin = path.join(dir, "fake-pi");
|
|
49
|
+
fs.writeFileSync(bin, `#!/usr/bin/env node
|
|
50
|
+
const fs = require("node:fs");
|
|
51
|
+
const path = require("node:path");
|
|
52
|
+
fs.writeFileSync(path.join(${JSON.stringify(argvDir)}, process.pid + "-" + Date.now() + ".json"), JSON.stringify(process.argv.slice(2)));
|
|
53
|
+
const text = ${JSON.stringify(reply)};
|
|
54
|
+
const line = (o) => process.stdout.write(JSON.stringify(o) + "\\n");
|
|
55
|
+
line({ type: "message_end", message: { role: "assistant", content: [{ type: "text", text }], stopReason: "stop" } });
|
|
56
|
+
line({ type: "agent_end", messages: [{ role: "assistant", content: [{ type: "text", text }] }] });
|
|
57
|
+
`);
|
|
58
|
+
fs.chmodSync(bin, 0o755);
|
|
59
|
+
return { bin, argvDir };
|
|
60
|
+
}
|
|
61
|
+
const APPROVE = "## Verdict\napprove\n\n## Summary\n- ok\n\n## Findings\nNo material findings.\n";
|
|
62
|
+
const FINDINGS = "## Verdict\nrequest_changes\n\n## Summary\n- x\n\n## Findings\n### F1: Gate\n- Severity: high\n- Path: a.txt\n- Actionable: yes\n- Evidence: test-output count\n- Impact: x\n- Recommendation: y\n";
|
|
63
|
+
function cli(cwd, args, env = {}) {
|
|
64
|
+
const fullEnv = { ...process.env, ...env };
|
|
65
|
+
delete fullEnv.TYPESAFE_API_KEY;
|
|
66
|
+
delete fullEnv.PI_REVIEW_META_STDOUT;
|
|
67
|
+
return spawnSync(NODE, ["--import", tsxLoader, path.join(repoRoot, "src/cli.ts"), ...args], { cwd, env: fullEnv, encoding: "utf8", timeout: 60_000, input: "" });
|
|
68
|
+
}
|
|
69
|
+
function meta(stderr) {
|
|
70
|
+
const line = stderr.split("\n").find((l) => l.startsWith("PI_REVIEW_META_JSON: "));
|
|
71
|
+
assert.ok(line, stderr);
|
|
72
|
+
return JSON.parse(line.slice("PI_REVIEW_META_JSON: ".length));
|
|
73
|
+
}
|
|
74
|
+
function prompts(argvDir) {
|
|
75
|
+
return fs.readdirSync(argvDir).map((name) => JSON.parse(fs.readFileSync(path.join(argvDir, name), "utf8")).at(-1));
|
|
76
|
+
}
|
|
77
|
+
/** A step that appends one line per execution to a counter file outside the repo. */
|
|
78
|
+
function counterStep(counter) {
|
|
79
|
+
return { id: "count", argv: [NODE, "-e", `const fs=require('fs');fs.appendFileSync(${JSON.stringify(counter)},'x');console.log('VERIFY_OK '+fs.readFileSync('a.txt','utf8').trim())`], purpose: "Claim: a.txt carries the uncommitted edit" };
|
|
80
|
+
}
|
|
81
|
+
test("verify show exits 5 when approval is needed and 0 when everything is pre-approved", () => {
|
|
82
|
+
const repo = makeRepo({ verify: { commands: [{ id: "check", argv: ["npm", "run", "check"] }] } });
|
|
83
|
+
const io = tmp("pi-review-verify-cli-io-");
|
|
84
|
+
const plan = path.join(io, "plan.json");
|
|
85
|
+
fs.writeFileSync(plan, JSON.stringify({ version: 1, steps: [{ id: "check", argv: ["npm", "run", "check"], purpose: "types" }, { id: "unit", argv: ["npm", "test"], purpose: "tests", sideEffects: "none", idempotent: true }] }));
|
|
86
|
+
const needs = cli(repo, ["verify", "show", plan]);
|
|
87
|
+
assert.equal(needs.status, 5, needs.stderr);
|
|
88
|
+
assert.match(needs.stdout, /\[check\] round 1 · pre-approved/);
|
|
89
|
+
assert.match(needs.stdout, /\[unit\] round 1 · NEEDS APPROVAL/);
|
|
90
|
+
assert.match(needs.stdout, /self-assessed \(not a gate\)/);
|
|
91
|
+
fs.writeFileSync(plan, JSON.stringify({ version: 1, steps: [{ id: "check", argv: ["npm", "run", "check"], purpose: "types" }] }));
|
|
92
|
+
assert.equal(cli(repo, ["verify", "show", plan]).status, 0);
|
|
93
|
+
fs.writeFileSync(plan, JSON.stringify({ version: 1, steps: [{ id: "x", argv: ["a"], purpose: "p", isolated: false }] }));
|
|
94
|
+
const invalid = cli(repo, ["verify", "show", plan]);
|
|
95
|
+
assert.equal(invalid.status, 2);
|
|
96
|
+
assert.match(invalid.stderr, /isolated=false/);
|
|
97
|
+
});
|
|
98
|
+
test("plan -> approve -> single review: reviewer prompt carries approved results, meta records approval hashes", () => {
|
|
99
|
+
const repo = makeRepo();
|
|
100
|
+
const io = tmp("pi-review-verify-cli-io-");
|
|
101
|
+
const counter = path.join(io, "count");
|
|
102
|
+
const plan = path.join(io, "plan.json");
|
|
103
|
+
fs.writeFileSync(plan, JSON.stringify({ version: 1, steps: [counterStep(counter)] }));
|
|
104
|
+
const approve = cli(repo, ["verify", "approve", plan, "--all", "--by", "user via test"]);
|
|
105
|
+
assert.equal(approve.status, 0, approve.stderr);
|
|
106
|
+
const approval = path.join(io, "approval.json");
|
|
107
|
+
fs.writeFileSync(approval, approve.stdout);
|
|
108
|
+
const fake = writeFakePi(io, APPROVE);
|
|
109
|
+
const status = git(repo, "status", "--porcelain");
|
|
110
|
+
const run = cli(repo, ["--no-stream", "--verify-plan", plan, "--verify-approval", approval, "--", "@a.txt"], { PI_BIN: fake.bin });
|
|
111
|
+
assert.equal(run.status, 0, run.stderr);
|
|
112
|
+
const [prompt] = prompts(fake.argvDir);
|
|
113
|
+
assert.match(prompt, /## Verification evidence \(source type: test-output\)/);
|
|
114
|
+
assert.match(prompt, /approved by a human before it ran/);
|
|
115
|
+
assert.match(prompt, /VERIFY_OK hello, uncommitted/);
|
|
116
|
+
const m = meta(run.stderr);
|
|
117
|
+
assert.equal(m.verification.status, "passed");
|
|
118
|
+
assert.equal(m.verification.source, "test-output");
|
|
119
|
+
assert.equal(m.verification.approvals[0].approvedBy, "user via test");
|
|
120
|
+
assert.equal(m.verification.steps[0].approval, "approved");
|
|
121
|
+
assert.equal(m.verification.steps[0].stepSha256, JSON.parse(approve.stdout).decisions[0].stepSha256);
|
|
122
|
+
assert.match(run.stdout, /Verify\s+passed · 1 run \/ 0 not run/);
|
|
123
|
+
assert.equal(git(repo, "status", "--porcelain"), status);
|
|
124
|
+
});
|
|
125
|
+
test("--verify-plan without approval runs nothing and says so in prompt and meta", () => {
|
|
126
|
+
const repo = makeRepo();
|
|
127
|
+
const io = tmp("pi-review-verify-cli-io-");
|
|
128
|
+
const counter = path.join(io, "count");
|
|
129
|
+
const plan = path.join(io, "plan.json");
|
|
130
|
+
fs.writeFileSync(plan, JSON.stringify({ version: 1, steps: [counterStep(counter)] }));
|
|
131
|
+
const fake = writeFakePi(io, APPROVE);
|
|
132
|
+
const run = cli(repo, ["--no-stream", "--verify-plan", plan, "--", "@a.txt"], { PI_BIN: fake.bin });
|
|
133
|
+
assert.equal(run.status, 0, run.stderr);
|
|
134
|
+
assert.equal(fs.existsSync(counter), false);
|
|
135
|
+
assert.match(prompts(fake.argvDir)[0], /Treat build, type-check, lint, and test status as UNVERIFIED/);
|
|
136
|
+
const m = meta(run.stderr);
|
|
137
|
+
assert.equal(m.verification.status, "unverified");
|
|
138
|
+
assert.equal(m.verification.steps[0].status, "skipped_unapproved");
|
|
139
|
+
});
|
|
140
|
+
test("panel: verification runs once and every reviewer receives the identical section", () => {
|
|
141
|
+
const repo = makeRepo();
|
|
142
|
+
const io = tmp("pi-review-verify-cli-io-");
|
|
143
|
+
const counter = path.join(io, "count");
|
|
144
|
+
const plan = path.join(io, "plan.json");
|
|
145
|
+
fs.writeFileSync(plan, JSON.stringify({ version: 1, steps: [counterStep(counter)] }));
|
|
146
|
+
const approval = path.join(io, "approval.json");
|
|
147
|
+
fs.writeFileSync(approval, cli(repo, ["verify", "approve", plan, "--all"]).stdout);
|
|
148
|
+
const fake = writeFakePi(io, APPROVE);
|
|
149
|
+
const run = cli(repo, ["--reviewers", "3", "--verify-plan", plan, "--verify-approval", approval, "--", "@a.txt"], { PI_BIN: fake.bin });
|
|
150
|
+
assert.equal(run.status, 0, run.stderr);
|
|
151
|
+
assert.equal(fs.readFileSync(counter, "utf8"), "x", "verification must run exactly once per panel");
|
|
152
|
+
const sections = prompts(fake.argvDir).map((p) => p.slice(p.indexOf("## Verification evidence")));
|
|
153
|
+
assert.equal(sections.length, 3);
|
|
154
|
+
assert.equal(new Set(sections).size, 1);
|
|
155
|
+
assert.match(sections[0], /VERIFY_OK/);
|
|
156
|
+
const m = meta(run.stderr);
|
|
157
|
+
assert.equal(m.strategy, "panel");
|
|
158
|
+
assert.equal(m.verification.status, "passed");
|
|
159
|
+
for (const argv of fs.readdirSync(fake.argvDir).map((n) => JSON.parse(fs.readFileSync(path.join(fake.argvDir, n), "utf8")))) {
|
|
160
|
+
assert.equal(argv[argv.indexOf("--tools") + 1], "read,grep,find,ls", "reviewer tools must stay read-only");
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
test("loop re-verifies every round (no cached results)", () => {
|
|
164
|
+
const repo = makeRepo();
|
|
165
|
+
const io = tmp("pi-review-verify-cli-io-");
|
|
166
|
+
const counter = path.join(io, "count");
|
|
167
|
+
const plan = path.join(io, "plan.json");
|
|
168
|
+
fs.writeFileSync(plan, JSON.stringify({ version: 1, steps: [counterStep(counter)] }));
|
|
169
|
+
const approval = path.join(io, "approval.json");
|
|
170
|
+
fs.writeFileSync(approval, cli(repo, ["verify", "approve", plan, "--all"]).stdout);
|
|
171
|
+
const fake = writeFakePi(io, FINDINGS);
|
|
172
|
+
const run = cli(repo, ["loop", "--no-stream", "--max-rounds", "2", "--verify-plan", plan, "--verify-approval", approval, "--", "@a.txt"], { PI_BIN: fake.bin });
|
|
173
|
+
assert.equal(run.status, 1, run.stderr);
|
|
174
|
+
assert.equal(fs.readFileSync(counter, "utf8"), "xx", "one verification per loop round");
|
|
175
|
+
});
|
|
176
|
+
test("verify run prints a summary without starting any reviewer", () => {
|
|
177
|
+
const repo = makeRepo({ verify: { commands: [{ id: "ok", argv: [NODE, "-e", "console.log('fine')"] }] } });
|
|
178
|
+
const run = cli(repo, ["verify", "run"], { PI_BIN: "/nonexistent/pi" });
|
|
179
|
+
assert.equal(run.status, 0, run.stderr);
|
|
180
|
+
const summary = JSON.parse(run.stdout);
|
|
181
|
+
assert.equal(summary.status, "passed");
|
|
182
|
+
assert.equal(summary.proposer, "whitelist");
|
|
183
|
+
});
|
|
184
|
+
test("verify propose: read-only Pi child drafts a plan in the shared format", () => {
|
|
185
|
+
const repo = makeRepo();
|
|
186
|
+
const io = tmp("pi-review-verify-cli-io-");
|
|
187
|
+
const proposed = { version: 1, steps: [{ id: "unit", argv: ["npm", "test"], purpose: "claim" }] };
|
|
188
|
+
const fake = writeFakePi(io, "```json\n" + JSON.stringify(proposed) + "\n```");
|
|
189
|
+
const run = cli(repo, ["verify", "propose", "--", "@a.txt", "check the edit"], { PI_BIN: fake.bin });
|
|
190
|
+
assert.equal(run.status, 0, run.stderr);
|
|
191
|
+
const plan = JSON.parse(run.stdout);
|
|
192
|
+
assert.equal(plan.proposer, "pi");
|
|
193
|
+
assert.equal(plan.steps[0].id, "unit");
|
|
194
|
+
const argv = JSON.parse(fs.readFileSync(path.join(fake.argvDir, fs.readdirSync(fake.argvDir)[0]), "utf8"));
|
|
195
|
+
assert.equal(argv[argv.indexOf("--tools") + 1], "read,grep,find,ls");
|
|
196
|
+
assert.ok(argv.includes("--no-session"));
|
|
197
|
+
const garbage = writeFakePi(tmp("pi-review-verify-cli-io-"), "I think you should run the tests.");
|
|
198
|
+
const bad = cli(repo, ["verify", "propose", "--", "@a.txt"], { PI_BIN: garbage.bin });
|
|
199
|
+
assert.equal(bad.status, 4);
|
|
200
|
+
assert.match(bad.stderr, /no JSON object/);
|
|
201
|
+
});
|
|
202
|
+
test("proposer prompt lists the standing whitelist; JSON extraction tolerates fences", () => {
|
|
203
|
+
const prompt = buildProposerPrompt("file: @a.ts", { commands: [{ id: "c", argv: ["npm", "run", "check"] }], link: [], maxFollowUpRounds: 1 });
|
|
204
|
+
assert.match(prompt, /\["npm","run","check"\]/);
|
|
205
|
+
assert.match(prompt, /Do not run, edit, or write anything/);
|
|
206
|
+
assert.deepEqual(extractJsonObject("```json\n{\"a\":1}\n```"), { a: 1 });
|
|
207
|
+
});
|
|
208
|
+
//# sourceMappingURL=verify-cli.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-cli.test.js","sourceRoot":"","sources":["../src/verify-cli.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-regression.test.d.ts","sourceRoot":"","sources":["../src/verify-regression.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
// Regression guard for --verify being strictly opt-in: with the flag absent,
|
|
2
|
+
// the reviewer argv (which carries the full prompt) and PI_REVIEW_META_JSON
|
|
3
|
+
// must stay byte-identical to the pre-verify base (16855bc). The inline
|
|
4
|
+
// snapshots below were recorded on that base before any verify code existed.
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import os from "node:os";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { afterEach, expect, test } from "vitest";
|
|
11
|
+
const repoRoot = path.dirname(fileURLToPath(new URL("../package.json", import.meta.url)));
|
|
12
|
+
let tempDir = "";
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
if (tempDir)
|
|
15
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
16
|
+
tempDir = "";
|
|
17
|
+
});
|
|
18
|
+
function writeFixtures(dir) {
|
|
19
|
+
const presets = path.join(dir, "presets.json");
|
|
20
|
+
fs.writeFileSync(presets, JSON.stringify({ code: { description: "fixture", tools: "read,grep,find,ls", instructions: "Fixture instructions." } }));
|
|
21
|
+
const systemPrompt = path.join(dir, "system.md");
|
|
22
|
+
fs.writeFileSync(systemPrompt, "Fixture system prompt.");
|
|
23
|
+
const argvDir = path.join(dir, "argv");
|
|
24
|
+
fs.mkdirSync(argvDir);
|
|
25
|
+
const fakePi = path.join(dir, "fake-pi");
|
|
26
|
+
fs.writeFileSync(fakePi, `#!/usr/bin/env node
|
|
27
|
+
const fs = require("node:fs");
|
|
28
|
+
const path = require("node:path");
|
|
29
|
+
fs.writeFileSync(path.join(process.env.FAKE_PI_ARGV_DIR, process.pid + ".json"), JSON.stringify(process.argv.slice(2)));
|
|
30
|
+
const text = "## Verdict\\napprove\\n\\n## Summary\\n- Fixture.\\n\\n## Findings\\nNo material findings.\\n";
|
|
31
|
+
const line = (o) => process.stdout.write(JSON.stringify(o) + "\\n");
|
|
32
|
+
line({ type: "message_end", message: { role: "assistant", content: [{ type: "text", text }], model: "fake/model", stopReason: "stop" } });
|
|
33
|
+
line({ type: "agent_end", messages: [{ role: "assistant", content: [{ type: "text", text }] }] });
|
|
34
|
+
`);
|
|
35
|
+
fs.chmodSync(fakePi, 0o755);
|
|
36
|
+
return { presets, systemPrompt, argvDir, fakePi };
|
|
37
|
+
}
|
|
38
|
+
function runCli(args) {
|
|
39
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-verify-regression-"));
|
|
40
|
+
const fx = writeFixtures(tempDir);
|
|
41
|
+
const env = {
|
|
42
|
+
...process.env,
|
|
43
|
+
PI_BIN: fx.fakePi,
|
|
44
|
+
PI_REVIEW_PRESETS: fx.presets,
|
|
45
|
+
PI_REVIEW_SYSTEM_PROMPT: fx.systemPrompt,
|
|
46
|
+
FAKE_PI_ARGV_DIR: fx.argvDir,
|
|
47
|
+
};
|
|
48
|
+
delete env.TYPESAFE_API_KEY;
|
|
49
|
+
delete env.PI_REVIEW_META_STDOUT;
|
|
50
|
+
const result = spawnSync(process.execPath, ["--import", "tsx", path.join(repoRoot, "src/cli.ts"), ...args, "--", "@src/types.ts", "check the gate"], { cwd: repoRoot, env, encoding: "utf8", timeout: 60_000, input: "" });
|
|
51
|
+
// Generic panel roles are shuffled per run; pin them so the snapshot is stable.
|
|
52
|
+
const normalize = (value) => value.split(repoRoot).join("<ROOT>").split(tempDir).join("<TMP>").replace(/- Role: [^\\\n]+/g, "- Role: <ROLE>");
|
|
53
|
+
const argvs = fs.readdirSync(fx.argvDir).map((name) => normalize(fs.readFileSync(path.join(fx.argvDir, name), "utf8"))).sort();
|
|
54
|
+
const metaLine = result.stderr.split("\n").find((line) => line.startsWith("PI_REVIEW_META_JSON: "));
|
|
55
|
+
const meta = JSON.parse(metaLine.slice("PI_REVIEW_META_JSON: ".length));
|
|
56
|
+
meta.durationMs = 0;
|
|
57
|
+
for (const reviewer of meta.reviewers ?? [])
|
|
58
|
+
Object.assign(reviewer, { durationMs: 0, role: "<ROLE>" });
|
|
59
|
+
return { status: result.status, argvs: argvs.map((a) => JSON.parse(a)), meta };
|
|
60
|
+
}
|
|
61
|
+
test("single review without --verify: argv, prompt, and meta match the base", () => {
|
|
62
|
+
const run = runCli(["--no-stream"]);
|
|
63
|
+
expect(run.status).toBe(0);
|
|
64
|
+
expect(run.argvs).toMatchInlineSnapshot(`
|
|
65
|
+
[
|
|
66
|
+
[
|
|
67
|
+
"-p",
|
|
68
|
+
"--mode",
|
|
69
|
+
"json",
|
|
70
|
+
"--append-system-prompt",
|
|
71
|
+
"Fixture system prompt.",
|
|
72
|
+
"--tools",
|
|
73
|
+
"read,grep,find,ls",
|
|
74
|
+
"--no-session",
|
|
75
|
+
"--no-extensions",
|
|
76
|
+
"--extension",
|
|
77
|
+
"<ROOT>/src/rules-extension.ts",
|
|
78
|
+
"@src/types.ts",
|
|
79
|
+
"You are running pi-review mode \`code\`.
|
|
80
|
+
|
|
81
|
+
Your job is to produce a review conclusion only. Do not edit files, do not write files, do not produce patches, and do not claim implementation work was done.
|
|
82
|
+
|
|
83
|
+
Fixture instructions.
|
|
84
|
+
|
|
85
|
+
Output Markdown with exactly these top-level sections:
|
|
86
|
+
|
|
87
|
+
## Verdict
|
|
88
|
+
One of: approve | request_changes | needs_clarification | blocked
|
|
89
|
+
|
|
90
|
+
## Summary
|
|
91
|
+
Short conclusion in 2-5 bullets.
|
|
92
|
+
|
|
93
|
+
## Findings
|
|
94
|
+
Prioritized findings. For every material finding, use this exact shape (increment IDs as F1, F2, ...):
|
|
95
|
+
|
|
96
|
+
### F1: <summary>
|
|
97
|
+
- Severity: critical | high | medium | low
|
|
98
|
+
- Path: <path or none>
|
|
99
|
+
- Lines: <line or line-range in Path, or none>
|
|
100
|
+
- Side: base | working (optional; defaults to working)
|
|
101
|
+
- Actionable: yes | no
|
|
102
|
+
- Evidence: <concrete evidence>
|
|
103
|
+
- Impact: <why it matters>
|
|
104
|
+
- Recommendation: <specific next step>
|
|
105
|
+
|
|
106
|
+
Set Actionable to yes when the host must fix or consciously reject the finding before clean closeout. Use no for informational or explicitly out-of-scope follow-up findings. Include Lines only when you have reliable line numbers for Path: a single line (\`42\`) or an inclusive range (\`42-58\`). Omit Lines or write "none" for file-level or non-line-specific findings — never guess a line number. Side marks which half of a diff Lines refers to (\`base\` = before the change, \`working\` = after); omit it to default to \`working\`. If there are no material findings, write "No material findings."
|
|
107
|
+
|
|
108
|
+
## Risks and Blind Spots
|
|
109
|
+
What could still be wrong, missing, or unverified.
|
|
110
|
+
|
|
111
|
+
## Open Questions
|
|
112
|
+
Questions the parent agent or user should answer before acting. If none, write "None."
|
|
113
|
+
|
|
114
|
+
<user-request>
|
|
115
|
+
check the gate
|
|
116
|
+
</user-request>
|
|
117
|
+
|
|
118
|
+
Review the attached file reference(s): @src/types.ts",
|
|
119
|
+
],
|
|
120
|
+
]
|
|
121
|
+
`);
|
|
122
|
+
expect(run.meta).toMatchInlineSnapshot(`
|
|
123
|
+
{
|
|
124
|
+
"actionableCount": 0,
|
|
125
|
+
"durationMs": 0,
|
|
126
|
+
"findings": [],
|
|
127
|
+
"metaVersion": 1,
|
|
128
|
+
"model": null,
|
|
129
|
+
"reviewMode": "code",
|
|
130
|
+
"status": "clean",
|
|
131
|
+
"verdict": "approve",
|
|
132
|
+
"verdictSource": "parsed",
|
|
133
|
+
}
|
|
134
|
+
`);
|
|
135
|
+
});
|
|
136
|
+
test("panel review without --verify: reviewer argv, prompts, and meta match the base", () => {
|
|
137
|
+
const run = runCli(["--reviewers", "2"]);
|
|
138
|
+
expect(run.status).toBe(0);
|
|
139
|
+
expect(run.argvs).toMatchInlineSnapshot(`
|
|
140
|
+
[
|
|
141
|
+
[
|
|
142
|
+
"-p",
|
|
143
|
+
"--mode",
|
|
144
|
+
"json",
|
|
145
|
+
"--append-system-prompt",
|
|
146
|
+
"Fixture system prompt.",
|
|
147
|
+
"--tools",
|
|
148
|
+
"read,grep,find,ls",
|
|
149
|
+
"--no-extensions",
|
|
150
|
+
"--extension",
|
|
151
|
+
"<ROOT>/src/rules-extension.ts",
|
|
152
|
+
"--no-session",
|
|
153
|
+
"@src/types.ts",
|
|
154
|
+
"You are an independent panel reviewer.
|
|
155
|
+
- Reviewer ID: r1
|
|
156
|
+
- Role: <ROLE>
|
|
157
|
+
You cannot see other reviewers' findings. Submit your own independent conclusion only.
|
|
158
|
+
|
|
159
|
+
You are running pi-review mode \`code\`.
|
|
160
|
+
|
|
161
|
+
Your job is to produce a review conclusion only. Do not edit files, do not write files, do not produce patches, and do not claim implementation work was done.
|
|
162
|
+
|
|
163
|
+
Fixture instructions.
|
|
164
|
+
|
|
165
|
+
Output Markdown with exactly these top-level sections:
|
|
166
|
+
|
|
167
|
+
## Verdict
|
|
168
|
+
One of: approve | request_changes | needs_clarification | blocked
|
|
169
|
+
|
|
170
|
+
## Summary
|
|
171
|
+
Short conclusion in 2-5 bullets.
|
|
172
|
+
|
|
173
|
+
## Findings
|
|
174
|
+
Prioritized findings. For every material finding, use this exact shape (increment IDs as F1, F2, ...):
|
|
175
|
+
|
|
176
|
+
### F1: <summary>
|
|
177
|
+
- Severity: critical | high | medium | low
|
|
178
|
+
- Path: <path or none>
|
|
179
|
+
- Lines: <line or line-range in Path, or none>
|
|
180
|
+
- Side: base | working (optional; defaults to working)
|
|
181
|
+
- Actionable: yes | no
|
|
182
|
+
- Evidence: <concrete evidence>
|
|
183
|
+
- Impact: <why it matters>
|
|
184
|
+
- Recommendation: <specific next step>
|
|
185
|
+
|
|
186
|
+
Set Actionable to yes when the host must fix or consciously reject the finding before clean closeout. Use no for informational or explicitly out-of-scope follow-up findings. Include Lines only when you have reliable line numbers for Path: a single line (\`42\`) or an inclusive range (\`42-58\`). Omit Lines or write "none" for file-level or non-line-specific findings — never guess a line number. Side marks which half of a diff Lines refers to (\`base\` = before the change, \`working\` = after); omit it to default to \`working\`. If there are no material findings, write "No material findings."
|
|
187
|
+
|
|
188
|
+
## Risks and Blind Spots
|
|
189
|
+
What could still be wrong, missing, or unverified.
|
|
190
|
+
|
|
191
|
+
## Open Questions
|
|
192
|
+
Questions the parent agent or user should answer before acting. If none, write "None."
|
|
193
|
+
|
|
194
|
+
<user-request>
|
|
195
|
+
check the gate
|
|
196
|
+
</user-request>
|
|
197
|
+
|
|
198
|
+
Review the attached file reference(s): @src/types.ts",
|
|
199
|
+
],
|
|
200
|
+
[
|
|
201
|
+
"-p",
|
|
202
|
+
"--mode",
|
|
203
|
+
"json",
|
|
204
|
+
"--append-system-prompt",
|
|
205
|
+
"Fixture system prompt.",
|
|
206
|
+
"--tools",
|
|
207
|
+
"read,grep,find,ls",
|
|
208
|
+
"--no-extensions",
|
|
209
|
+
"--extension",
|
|
210
|
+
"<ROOT>/src/rules-extension.ts",
|
|
211
|
+
"--no-session",
|
|
212
|
+
"@src/types.ts",
|
|
213
|
+
"You are an independent panel reviewer.
|
|
214
|
+
- Reviewer ID: r2
|
|
215
|
+
- Role: <ROLE>
|
|
216
|
+
You cannot see other reviewers' findings. Submit your own independent conclusion only.
|
|
217
|
+
|
|
218
|
+
You are running pi-review mode \`code\`.
|
|
219
|
+
|
|
220
|
+
Your job is to produce a review conclusion only. Do not edit files, do not write files, do not produce patches, and do not claim implementation work was done.
|
|
221
|
+
|
|
222
|
+
Fixture instructions.
|
|
223
|
+
|
|
224
|
+
Output Markdown with exactly these top-level sections:
|
|
225
|
+
|
|
226
|
+
## Verdict
|
|
227
|
+
One of: approve | request_changes | needs_clarification | blocked
|
|
228
|
+
|
|
229
|
+
## Summary
|
|
230
|
+
Short conclusion in 2-5 bullets.
|
|
231
|
+
|
|
232
|
+
## Findings
|
|
233
|
+
Prioritized findings. For every material finding, use this exact shape (increment IDs as F1, F2, ...):
|
|
234
|
+
|
|
235
|
+
### F1: <summary>
|
|
236
|
+
- Severity: critical | high | medium | low
|
|
237
|
+
- Path: <path or none>
|
|
238
|
+
- Lines: <line or line-range in Path, or none>
|
|
239
|
+
- Side: base | working (optional; defaults to working)
|
|
240
|
+
- Actionable: yes | no
|
|
241
|
+
- Evidence: <concrete evidence>
|
|
242
|
+
- Impact: <why it matters>
|
|
243
|
+
- Recommendation: <specific next step>
|
|
244
|
+
|
|
245
|
+
Set Actionable to yes when the host must fix or consciously reject the finding before clean closeout. Use no for informational or explicitly out-of-scope follow-up findings. Include Lines only when you have reliable line numbers for Path: a single line (\`42\`) or an inclusive range (\`42-58\`). Omit Lines or write "none" for file-level or non-line-specific findings — never guess a line number. Side marks which half of a diff Lines refers to (\`base\` = before the change, \`working\` = after); omit it to default to \`working\`. If there are no material findings, write "No material findings."
|
|
246
|
+
|
|
247
|
+
## Risks and Blind Spots
|
|
248
|
+
What could still be wrong, missing, or unverified.
|
|
249
|
+
|
|
250
|
+
## Open Questions
|
|
251
|
+
Questions the parent agent or user should answer before acting. If none, write "None."
|
|
252
|
+
|
|
253
|
+
<user-request>
|
|
254
|
+
check the gate
|
|
255
|
+
</user-request>
|
|
256
|
+
|
|
257
|
+
Review the attached file reference(s): @src/types.ts",
|
|
258
|
+
],
|
|
259
|
+
]
|
|
260
|
+
`);
|
|
261
|
+
expect(run.meta).toMatchInlineSnapshot(`
|
|
262
|
+
{
|
|
263
|
+
"actionableCount": 0,
|
|
264
|
+
"adjudicationUsed": false,
|
|
265
|
+
"advisories": [],
|
|
266
|
+
"configuredReviewers": 2,
|
|
267
|
+
"confirmedClusters": [],
|
|
268
|
+
"consensusPolicy": "quorum",
|
|
269
|
+
"consensusThreshold": 2,
|
|
270
|
+
"durationMs": 0,
|
|
271
|
+
"findings": [],
|
|
272
|
+
"metaVersion": 1,
|
|
273
|
+
"model": null,
|
|
274
|
+
"panelHealth": "healthy",
|
|
275
|
+
"reviewMode": "code",
|
|
276
|
+
"reviewers": [
|
|
277
|
+
{
|
|
278
|
+
"contributed": true,
|
|
279
|
+
"durationMs": 0,
|
|
280
|
+
"model": null,
|
|
281
|
+
"reviewerId": "r1",
|
|
282
|
+
"role": "<ROLE>",
|
|
283
|
+
"status": "clean",
|
|
284
|
+
"verdict": "approve",
|
|
285
|
+
"verdictSource": "parsed",
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
"contributed": true,
|
|
289
|
+
"durationMs": 0,
|
|
290
|
+
"model": null,
|
|
291
|
+
"reviewerId": "r2",
|
|
292
|
+
"role": "<ROLE>",
|
|
293
|
+
"status": "clean",
|
|
294
|
+
"verdict": "approve",
|
|
295
|
+
"verdictSource": "parsed",
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
"sourceFindings": [],
|
|
299
|
+
"status": "clean",
|
|
300
|
+
"strategy": "panel",
|
|
301
|
+
"successfulReviewers": 2,
|
|
302
|
+
"verdict": "approve",
|
|
303
|
+
"verdictSource": "parsed",
|
|
304
|
+
}
|
|
305
|
+
`);
|
|
306
|
+
});
|
|
307
|
+
//# sourceMappingURL=verify-regression.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-regression.test.js","sourceRoot":"","sources":["../src/verify-regression.test.ts"],"names":[],"mappings":"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"}
|