@zephyrdeng/pi-review 0.6.1 → 0.7.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 +110 -13
- package/README.zh-CN.md +64 -3
- package/dist/args.d.ts +8 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +147 -28
- package/dist/args.js.map +1 -1
- package/dist/args.test.d.ts +2 -0
- package/dist/args.test.d.ts.map +1 -0
- package/dist/args.test.js +115 -0
- package/dist/args.test.js.map +1 -0
- package/dist/cli-exit.test.d.ts +2 -0
- package/dist/cli-exit.test.d.ts.map +1 -0
- package/dist/cli-exit.test.js +84 -0
- package/dist/cli-exit.test.js.map +1 -0
- package/dist/cli.js +16 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/extensions/review.d.ts +2 -0
- package/dist/extensions/review.js +22 -0
- package/dist/extensions/rv-prompts.d.ts +19 -0
- package/dist/extensions/rv-prompts.js +132 -0
- package/dist/index.d.ts +17 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -6
- package/dist/index.js.map +1 -1
- package/dist/json-events.d.ts +45 -0
- package/dist/json-events.d.ts.map +1 -1
- package/dist/json-events.js +185 -0
- package/dist/json-events.js.map +1 -1
- package/dist/json-events.test.js +64 -1
- package/dist/json-events.test.js.map +1 -1
- package/dist/loop.d.ts +36 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +73 -0
- package/dist/loop.js.map +1 -0
- package/dist/loop.test.d.ts +2 -0
- package/dist/loop.test.d.ts.map +1 -0
- package/dist/loop.test.js +83 -0
- package/dist/loop.test.js.map +1 -0
- package/dist/matcher.d.ts +74 -0
- package/dist/matcher.d.ts.map +1 -0
- package/dist/matcher.js +202 -0
- package/dist/matcher.js.map +1 -0
- package/dist/matcher.test.d.ts +2 -0
- package/dist/matcher.test.d.ts.map +1 -0
- package/dist/matcher.test.js +161 -0
- package/dist/matcher.test.js.map +1 -0
- package/dist/meta-footer.d.ts +15 -1
- package/dist/meta-footer.d.ts.map +1 -1
- package/dist/meta-footer.js +108 -0
- package/dist/meta-footer.js.map +1 -1
- package/dist/meta-footer.test.js +43 -1
- package/dist/meta-footer.test.js.map +1 -1
- package/dist/panel-aggregate.d.ts +18 -0
- package/dist/panel-aggregate.d.ts.map +1 -0
- package/dist/panel-aggregate.js +247 -0
- package/dist/panel-aggregate.js.map +1 -0
- package/dist/panel-aggregate.test.d.ts +2 -0
- package/dist/panel-aggregate.test.d.ts.map +1 -0
- package/dist/panel-aggregate.test.js +461 -0
- package/dist/panel-aggregate.test.js.map +1 -0
- package/dist/panel-cli.test.d.ts +2 -0
- package/dist/panel-cli.test.d.ts.map +1 -0
- package/dist/panel-cli.test.js +188 -0
- package/dist/panel-cli.test.js.map +1 -0
- package/dist/panel-config.d.ts +19 -0
- package/dist/panel-config.d.ts.map +1 -0
- package/dist/panel-config.js +115 -0
- package/dist/panel-config.js.map +1 -0
- package/dist/panel-config.test.d.ts +2 -0
- package/dist/panel-config.test.d.ts.map +1 -0
- package/dist/panel-config.test.js +91 -0
- package/dist/panel-config.test.js.map +1 -0
- package/dist/panel-loop.test.d.ts +2 -0
- package/dist/panel-loop.test.d.ts.map +1 -0
- package/dist/panel-loop.test.js +118 -0
- package/dist/panel-loop.test.js.map +1 -0
- package/dist/panel.d.ts +10 -0
- package/dist/panel.d.ts.map +1 -0
- package/dist/panel.js +315 -0
- package/dist/panel.js.map +1 -0
- package/dist/presets.d.ts +2 -1
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +10 -0
- package/dist/presets.js.map +1 -1
- package/dist/prompt.d.ts +14 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +61 -15
- package/dist/prompt.js.map +1 -1
- package/dist/prompt.test.d.ts +2 -0
- package/dist/prompt.test.d.ts.map +1 -0
- package/dist/prompt.test.js +37 -0
- package/dist/prompt.test.js.map +1 -0
- package/dist/review-result.d.ts +5 -0
- package/dist/review-result.d.ts.map +1 -0
- package/dist/review-result.js +98 -0
- package/dist/review-result.js.map +1 -0
- package/dist/review-result.test.d.ts +2 -0
- package/dist/review-result.test.d.ts.map +1 -0
- package/dist/review-result.test.js +196 -0
- package/dist/review-result.test.js.map +1 -0
- package/dist/review.d.ts +10 -4
- package/dist/review.d.ts.map +1 -1
- package/dist/review.js +82 -20
- package/dist/review.js.map +1 -1
- package/dist/review.meta.test.js +2 -2
- package/dist/review.meta.test.js.map +1 -1
- package/dist/skill-protocol.test.d.ts +2 -0
- package/dist/skill-protocol.test.d.ts.map +1 -0
- package/dist/skill-protocol.test.js +35 -0
- package/dist/skill-protocol.test.js.map +1 -0
- package/dist/types.d.ts +147 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -1
- package/extensions/rv-completions.test.ts +15 -0
- package/extensions/rv-completions.ts +7 -1
- package/package.json +3 -3
- package/resources/panel-presets.json +21 -0
- package/resources/system-prompt.md +11 -1
- package/skills/pi-review/SKILL.md +90 -12
- package/skills/pi-review/references/codex-tools.md +19 -6
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { test } from "node:test";
|
|
8
|
+
function tsxLoaderArgs() {
|
|
9
|
+
const args = [];
|
|
10
|
+
for (let index = 0; index < process.execArgv.length - 1; index += 1) {
|
|
11
|
+
const flag = process.execArgv[index];
|
|
12
|
+
const value = process.execArgv[index + 1];
|
|
13
|
+
if ((flag === "--require" || flag === "--import") && value?.includes("tsx")) {
|
|
14
|
+
args.push(flag, value);
|
|
15
|
+
index += 1;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return args;
|
|
19
|
+
}
|
|
20
|
+
function cliPath() {
|
|
21
|
+
return fileURLToPath(new URL("./cli.ts", import.meta.url));
|
|
22
|
+
}
|
|
23
|
+
function repoRoot() {
|
|
24
|
+
return path.dirname(fileURLToPath(new URL("../package.json", import.meta.url)));
|
|
25
|
+
}
|
|
26
|
+
function writeFakePi(tempDir) {
|
|
27
|
+
const fakePi = path.join(tempDir, "fake-pi");
|
|
28
|
+
fs.writeFileSync(fakePi, `#!/usr/bin/env node
|
|
29
|
+
const prompt = process.argv[process.argv.length - 1] || "";
|
|
30
|
+
const scenario = process.env.FAKE_PANEL_SCENARIO || "agree-bug";
|
|
31
|
+
const idMatch = prompt.match(/Reviewer ID:\\s*(\\S+)/);
|
|
32
|
+
const reviewerId = idMatch ? idMatch[1] : "r1";
|
|
33
|
+
const bug = "### F1: Off-by-one in loop\\n- Severity: high\\n- Path: src/cli.ts\\n- Actionable: yes\\n- Evidence: x\\n- Impact: y\\n- Recommendation: z";
|
|
34
|
+
function emit(text) {
|
|
35
|
+
function line(obj) { process.stdout.write(JSON.stringify(obj) + "\\n"); }
|
|
36
|
+
line({ type: "session", version: 3, id: "s1" });
|
|
37
|
+
line({ type: "agent_start" });
|
|
38
|
+
line({ type: "turn_start" });
|
|
39
|
+
line({ type: "message_start", message: { role: "user", content: [{ type: "text", text: "review" }] } });
|
|
40
|
+
line({ type: "message_end", message: { role: "user", content: [{ type: "text", text: "review" }] } });
|
|
41
|
+
line({ type: "message_start", message: { role: "assistant", content: [], model: "fake/model", usage: { input: 100, output: 50, cacheRead: 0, cacheWrite: 0, reasoning: 0, totalTokens: 150 } } });
|
|
42
|
+
line({ type: "message_update", assistantMessageEvent: { type: "text_delta", delta: text, partial: { role: "assistant" } } });
|
|
43
|
+
line({ type: "message_end", message: { role: "assistant", content: [{ type: "text", text }], model: "fake/model", usage: { input: 100, output: 50, cacheRead: 0, cacheWrite: 0, reasoning: 0, totalTokens: 150 }, stopReason: "stop" } });
|
|
44
|
+
line({ type: "turn_end", message: { role: "assistant", content: [{ type: "text", text }], usage: { input: 100, output: 50, totalTokens: 150 } } });
|
|
45
|
+
line({ type: "agent_end", messages: [{ role: "user", content: [{ type: "text", text: "review" }] }, { role: "assistant", content: [{ type: "text", text }], responseModel: "fake/model" }] });
|
|
46
|
+
}
|
|
47
|
+
function out(verdict, findings) {
|
|
48
|
+
emit("## Verdict\\n" + verdict + "\\n\\n## Summary\\n- Fixture.\\n\\n## Findings\\n" + findings + "\\n\\n## Risks and Blind Spots\\nNone.\\n\\n## Open Questions\\nNone.\\n");
|
|
49
|
+
}
|
|
50
|
+
const bugReporters = ["r1", "r2", "correctness", "security"];
|
|
51
|
+
if (scenario === "runtime-fail" && reviewerId === "r2") { process.stderr.write("child crashed\\n"); process.exit(9); }
|
|
52
|
+
if (scenario === "agree-bug") {
|
|
53
|
+
if (bugReporters.includes(reviewerId)) out("request_changes", bug);
|
|
54
|
+
else out("approve", "No material findings.");
|
|
55
|
+
} else if (scenario === "all-clean") {
|
|
56
|
+
out("approve", "No material findings.");
|
|
57
|
+
} else if (scenario === "singleton") {
|
|
58
|
+
if (reviewerId === "r1" || reviewerId === "correctness") out("request_changes", bug);
|
|
59
|
+
else out("approve", "No material findings.");
|
|
60
|
+
}
|
|
61
|
+
process.exit(0);
|
|
62
|
+
`);
|
|
63
|
+
fs.chmodSync(fakePi, 0o755);
|
|
64
|
+
return fakePi;
|
|
65
|
+
}
|
|
66
|
+
function runPanelCli(fakePi, scenario, extraArgs) {
|
|
67
|
+
return spawnSync(process.execPath, [...tsxLoaderArgs(), cliPath(), ...extraArgs, "--", "@src"], {
|
|
68
|
+
cwd: repoRoot(),
|
|
69
|
+
env: { ...process.env, PI_BIN: fakePi, FAKE_PANEL_SCENARIO: scenario },
|
|
70
|
+
encoding: "utf8",
|
|
71
|
+
timeout: 30_000,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function metaRecord(result) {
|
|
75
|
+
const lines = [...result.stderr.split("\n"), ...result.stdout.split("\n")];
|
|
76
|
+
const metaLine = lines.find((line) => line.startsWith("PI_REVIEW_META_JSON: "));
|
|
77
|
+
if (!metaLine)
|
|
78
|
+
return undefined;
|
|
79
|
+
return JSON.parse(metaLine.slice("PI_REVIEW_META_JSON: ".length));
|
|
80
|
+
}
|
|
81
|
+
test("panel review with two corroborating reviewers confirms one finding and exits 1", (t) => {
|
|
82
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
83
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
84
|
+
const fakePi = writeFakePi(tempDir);
|
|
85
|
+
const result = runPanelCli(fakePi, "agree-bug", ["--reviewers", "3", "--consensus", "quorum", "--min-agree", "2"]);
|
|
86
|
+
assert.equal(result.error, undefined);
|
|
87
|
+
assert.equal(result.status, 1, result.stderr);
|
|
88
|
+
const meta = metaRecord(result);
|
|
89
|
+
assert.ok(meta, result.stderr);
|
|
90
|
+
assert.equal(meta.status, "has_findings");
|
|
91
|
+
assert.equal(meta.strategy, "panel");
|
|
92
|
+
assert.equal(meta.configuredReviewers, 3);
|
|
93
|
+
assert.equal(meta.consensusPolicy, "quorum");
|
|
94
|
+
assert.equal(meta.consensusThreshold, 2);
|
|
95
|
+
assert.equal(meta.confirmedClusters.length, 1);
|
|
96
|
+
assert.equal(meta.advisories.length, 0);
|
|
97
|
+
assert.equal(meta.reviewers.length, 3);
|
|
98
|
+
assert.equal(meta.confirmedClusters[0].supportCount, 2);
|
|
99
|
+
});
|
|
100
|
+
test("panel review where all reviewers approve is clean and exits 0", (t) => {
|
|
101
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
102
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
103
|
+
const fakePi = writeFakePi(tempDir);
|
|
104
|
+
const result = runPanelCli(fakePi, "all-clean", ["--reviewers", "3"]);
|
|
105
|
+
assert.equal(result.status, 0, result.stderr);
|
|
106
|
+
const meta = metaRecord(result);
|
|
107
|
+
assert.ok(meta);
|
|
108
|
+
assert.equal(meta.status, "clean");
|
|
109
|
+
assert.equal(meta.confirmedClusters.length, 0);
|
|
110
|
+
assert.equal(meta.advisories.length, 0);
|
|
111
|
+
});
|
|
112
|
+
test("panel review with a singleton finding keeps it advisory and stays clean under quorum", (t) => {
|
|
113
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
114
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
115
|
+
const fakePi = writeFakePi(tempDir);
|
|
116
|
+
const result = runPanelCli(fakePi, "singleton", ["--reviewers", "3", "--consensus", "quorum", "--min-agree", "2"]);
|
|
117
|
+
assert.equal(result.status, 0, result.stderr);
|
|
118
|
+
const meta = metaRecord(result);
|
|
119
|
+
assert.ok(meta);
|
|
120
|
+
assert.equal(meta.status, "clean");
|
|
121
|
+
assert.equal(meta.confirmedClusters.length, 0);
|
|
122
|
+
assert.equal(meta.advisories.length, 1);
|
|
123
|
+
assert.equal(meta.advisories[0].supportCount, 1);
|
|
124
|
+
});
|
|
125
|
+
test("panel review with a reviewer runtime failure is blocked and exits 4", (t) => {
|
|
126
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
127
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
128
|
+
const fakePi = writeFakePi(tempDir);
|
|
129
|
+
const result = runPanelCli(fakePi, "runtime-fail", ["--reviewers", "3"]);
|
|
130
|
+
assert.equal(result.status, 4, result.stderr);
|
|
131
|
+
const meta = metaRecord(result);
|
|
132
|
+
assert.ok(meta);
|
|
133
|
+
assert.equal(meta.status, "blocked");
|
|
134
|
+
assert.equal(meta.panelHealth, "blocked");
|
|
135
|
+
assert.equal(meta.confirmedClusters.length, 0);
|
|
136
|
+
});
|
|
137
|
+
test("panel review emits exactly one aggregate metadata record", (t) => {
|
|
138
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
139
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
140
|
+
const fakePi = writeFakePi(tempDir);
|
|
141
|
+
const result = runPanelCli(fakePi, "agree-bug", ["--reviewers", "3"]);
|
|
142
|
+
const allLines = [...result.stderr.split("\n"), ...result.stdout.split("\n")];
|
|
143
|
+
const metaLines = allLines.filter((line) => line.startsWith("PI_REVIEW_META_JSON: "));
|
|
144
|
+
assert.equal(metaLines.length, 1, `expected one aggregate meta record, got ${metaLines.length}`);
|
|
145
|
+
});
|
|
146
|
+
test("panel rejects session reuse flags with usage exit 2", () => {
|
|
147
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
148
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
149
|
+
const result = runPanelCli("pi", "agree-bug", ["--reviewers", "3", "--keep-session"]);
|
|
150
|
+
assert.equal(result.status, 2);
|
|
151
|
+
assert.match(result.stderr, /panel cannot be used with/);
|
|
152
|
+
});
|
|
153
|
+
test("panel loop runs one full panel per round and reports a panel summary", (t) => {
|
|
154
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
155
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
156
|
+
const fakePi = writeFakePi(tempDir);
|
|
157
|
+
const result = spawnSync(process.execPath, [...tsxLoaderArgs(), cliPath(), "loop", "--reviewers", "3", "--max-rounds", "1", "--", "@src"], { cwd: repoRoot(), env: { ...process.env, PI_BIN: fakePi, FAKE_PANEL_SCENARIO: "agree-bug" }, encoding: "utf8", timeout: 30_000 });
|
|
158
|
+
assert.equal(result.status, 1, result.stderr);
|
|
159
|
+
assert.match(result.stdout, /pi-review loop/);
|
|
160
|
+
assert.match(result.stdout, /panel 3\/3/);
|
|
161
|
+
});
|
|
162
|
+
test("named panel preset propagates panelPreset to metadata and output", (t) => {
|
|
163
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
164
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
165
|
+
const fakePi = writeFakePi(tempDir);
|
|
166
|
+
const result = runPanelCli(fakePi, "agree-bug", ["--panel", "code-experts", "--consensus", "quorum", "--min-agree", "2"]);
|
|
167
|
+
assert.equal(result.status, 1, result.stderr);
|
|
168
|
+
const meta = metaRecord(result);
|
|
169
|
+
assert.ok(meta, result.stderr);
|
|
170
|
+
assert.equal(meta.status, "has_findings");
|
|
171
|
+
assert.equal(meta.strategy, "panel");
|
|
172
|
+
assert.equal(meta.panelPreset, "code-experts");
|
|
173
|
+
assert.equal(meta.configuredReviewers, 3);
|
|
174
|
+
assert.equal(meta.confirmedClusters.length, 1);
|
|
175
|
+
assert.equal(meta.confirmedClusters[0].supportCount, 2);
|
|
176
|
+
assert.match(result.stdout, /Panel\s+code-experts/);
|
|
177
|
+
});
|
|
178
|
+
test("named panel preset reviewer ids appear in supporting reviewer ids", (t) => {
|
|
179
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-review-panel-cli-"));
|
|
180
|
+
t.after(() => fs.rmSync(tempDir, { recursive: true, force: true }));
|
|
181
|
+
const fakePi = writeFakePi(tempDir);
|
|
182
|
+
const result = runPanelCli(fakePi, "agree-bug", ["--panel", "code-experts", "--consensus", "quorum", "--min-agree", "2"]);
|
|
183
|
+
const meta = metaRecord(result);
|
|
184
|
+
assert.ok(meta);
|
|
185
|
+
const cluster = meta.confirmedClusters[0];
|
|
186
|
+
assert.deepEqual(cluster.supportingReviewerIds.sort(), ["correctness", "security"]);
|
|
187
|
+
});
|
|
188
|
+
//# sourceMappingURL=panel-cli.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-cli.test.js","sourceRoot":"","sources":["../src/panel-cli.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ConsensusPolicy, type PanelPreset, type PanelReviewerSpec, type ParsedArgs } from "./types.js";
|
|
2
|
+
export interface ResolvedPanelConfig {
|
|
3
|
+
presetName?: string;
|
|
4
|
+
reviewers: PanelReviewerSpec[];
|
|
5
|
+
reviewerCount: number;
|
|
6
|
+
consensus: ConsensusPolicy;
|
|
7
|
+
minAgree?: number;
|
|
8
|
+
consensusModel?: string;
|
|
9
|
+
concurrency: number;
|
|
10
|
+
/** True when a consensus model enables semantic adjudication. */
|
|
11
|
+
semanticEnabled: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve a panel configuration. `panelPresets` is supplied by the caller (the
|
|
15
|
+
* orchestrator loads the file), so this function stays pure and testable with
|
|
16
|
+
* fixture presets.
|
|
17
|
+
*/
|
|
18
|
+
export declare function resolvePanelConfig(parsed: ParsedArgs, panelPresets: Record<string, PanelPreset>): ResolvedPanelConfig;
|
|
19
|
+
//# sourceMappingURL=panel-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-config.d.ts","sourceRoot":"","sources":["../src/panel-config.ts"],"names":[],"mappings":"AAOA,OAAO,EAIL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,mBAAmB;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,eAAe,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,eAAe,EAAE,OAAO,CAAC;CAC1B;AAUD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GACxC,mBAAmB,CAiHrB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Resolve and validate panel execution configuration from parsed CLI options
|
|
2
|
+
// and named panel presets. Called from the orchestration path after the pure
|
|
3
|
+
// argument parser has already rejected syntactically invalid input; this layer
|
|
4
|
+
// validates combinations that require the loaded preset (reviewer counts,
|
|
5
|
+
// impossible quorum, concurrency bounds).
|
|
6
|
+
import { ArgsParseError } from "./args.js";
|
|
7
|
+
import { CONSENSUS_POLICIES, DEFAULT_PANEL_MIN_AGREE, MAX_REVIEWERS, } from "./types.js";
|
|
8
|
+
function isPolicy(value) {
|
|
9
|
+
return CONSENSUS_POLICIES.includes(value);
|
|
10
|
+
}
|
|
11
|
+
function defaultMinAgree(policy) {
|
|
12
|
+
return policy === "quorum" ? DEFAULT_PANEL_MIN_AGREE : undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a panel configuration. `panelPresets` is supplied by the caller (the
|
|
16
|
+
* orchestrator loads the file), so this function stays pure and testable with
|
|
17
|
+
* fixture presets.
|
|
18
|
+
*/
|
|
19
|
+
export function resolvePanelConfig(parsed, panelPresets) {
|
|
20
|
+
const explicitConsensus = parsed.consensus;
|
|
21
|
+
if (explicitConsensus !== undefined && !isPolicy(explicitConsensus)) {
|
|
22
|
+
throw new ArgsParseError(`unknown consensus policy: ${explicitConsensus}. Available: ${CONSENSUS_POLICIES.join(", ")}`);
|
|
23
|
+
}
|
|
24
|
+
let presetName;
|
|
25
|
+
let reviewers;
|
|
26
|
+
let consensus;
|
|
27
|
+
let minAgree;
|
|
28
|
+
let consensusModel;
|
|
29
|
+
let concurrency;
|
|
30
|
+
if (parsed.panel) {
|
|
31
|
+
presetName = parsed.panel;
|
|
32
|
+
const preset = panelPresets[parsed.panel];
|
|
33
|
+
if (!preset) {
|
|
34
|
+
throw new ArgsParseError(`unknown panel preset: ${parsed.panel}. Available: ${Object.keys(panelPresets).join(", ") || "(none)"}`);
|
|
35
|
+
}
|
|
36
|
+
if (!Array.isArray(preset.reviewers) || preset.reviewers.length < 1) {
|
|
37
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} must define at least one reviewer`);
|
|
38
|
+
}
|
|
39
|
+
if (preset.reviewers.length > MAX_REVIEWERS) {
|
|
40
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} defines ${preset.reviewers.length} reviewers (max ${MAX_REVIEWERS})`);
|
|
41
|
+
}
|
|
42
|
+
const seenReviewerIds = new Set();
|
|
43
|
+
for (const reviewer of preset.reviewers) {
|
|
44
|
+
if (!reviewer?.id || !reviewer?.role) {
|
|
45
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} has a reviewer missing id or role`);
|
|
46
|
+
}
|
|
47
|
+
if (seenReviewerIds.has(reviewer.id)) {
|
|
48
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} has duplicate reviewer id: ${reviewer.id}`);
|
|
49
|
+
}
|
|
50
|
+
if (!/^[A-Za-z0-9_.-]+$/.test(reviewer.id)) {
|
|
51
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} reviewer id "${reviewer.id}" must be alphanumeric/dot/dash/underscore`);
|
|
52
|
+
}
|
|
53
|
+
seenReviewerIds.add(reviewer.id);
|
|
54
|
+
}
|
|
55
|
+
if (preset.consensus !== undefined && !isPolicy(preset.consensus)) {
|
|
56
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} has unknown consensus: ${preset.consensus}. Available: ${CONSENSUS_POLICIES.join(", ")}`);
|
|
57
|
+
}
|
|
58
|
+
if (preset.minAgree !== undefined && (!Number.isSafeInteger(preset.minAgree) || preset.minAgree < 1)) {
|
|
59
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} minAgree must be a positive integer`);
|
|
60
|
+
}
|
|
61
|
+
const presetConsensus = (explicitConsensus ?? preset.consensus ?? "quorum");
|
|
62
|
+
if (preset.minAgree !== undefined && presetConsensus !== "quorum") {
|
|
63
|
+
throw new ArgsParseError(`panel preset ${parsed.panel} sets minAgree but effective consensus is ${presetConsensus}; minAgree is only meaningful with quorum`);
|
|
64
|
+
}
|
|
65
|
+
reviewers = preset.reviewers;
|
|
66
|
+
consensus = (explicitConsensus ?? preset.consensus ?? "quorum");
|
|
67
|
+
// Only inherit a preset/default minAgree when the effective policy is quorum;
|
|
68
|
+
// a non-quorum override must not carry a stale quorum threshold.
|
|
69
|
+
const inheritMinAgree = consensus === "quorum" ? preset.minAgree : undefined;
|
|
70
|
+
minAgree = parsed.minAgree ?? inheritMinAgree ?? defaultMinAgree(consensus);
|
|
71
|
+
consensusModel = parsed.consensusModel ?? preset.consensusModel;
|
|
72
|
+
concurrency = parsed.concurrency ?? preset.concurrency;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Generic same-model panel: --reviewers N (parser guarantees N in 2..MAX).
|
|
76
|
+
const count = parsed.reviewers;
|
|
77
|
+
reviewers = Array.from({ length: count }, (_, index) => ({
|
|
78
|
+
id: `r${index + 1}`,
|
|
79
|
+
role: "Independent reviewer",
|
|
80
|
+
}));
|
|
81
|
+
consensus = (explicitConsensus ?? "quorum");
|
|
82
|
+
minAgree = parsed.minAgree ?? defaultMinAgree(consensus);
|
|
83
|
+
consensusModel = parsed.consensusModel;
|
|
84
|
+
concurrency = parsed.concurrency;
|
|
85
|
+
}
|
|
86
|
+
if (minAgree !== undefined) {
|
|
87
|
+
if (!Number.isSafeInteger(minAgree) || minAgree < 1) {
|
|
88
|
+
throw new ArgsParseError("--min-agree must be a positive integer");
|
|
89
|
+
}
|
|
90
|
+
if (minAgree > reviewers.length) {
|
|
91
|
+
throw new ArgsParseError(`--min-agree ${minAgree} cannot exceed reviewer count ${reviewers.length}`);
|
|
92
|
+
}
|
|
93
|
+
if (consensus !== "quorum") {
|
|
94
|
+
throw new ArgsParseError("--min-agree is only meaningful with --consensus quorum");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const reviewerCount = reviewers.length;
|
|
98
|
+
const effectiveConcurrency = concurrency ?? reviewerCount;
|
|
99
|
+
if (!Number.isSafeInteger(effectiveConcurrency) || effectiveConcurrency < 1) {
|
|
100
|
+
throw new ArgsParseError("--concurrency must be a positive integer");
|
|
101
|
+
}
|
|
102
|
+
if (effectiveConcurrency > reviewerCount) {
|
|
103
|
+
throw new ArgsParseError(`--concurrency ${effectiveConcurrency} cannot exceed reviewer count ${reviewerCount}`);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
...(presetName ? { presetName } : {}),
|
|
107
|
+
reviewers,
|
|
108
|
+
reviewerCount,
|
|
109
|
+
consensus,
|
|
110
|
+
...(minAgree !== undefined ? { minAgree } : {}),
|
|
111
|
+
...(consensusModel ? { consensusModel, semanticEnabled: true } : { semanticEnabled: false }),
|
|
112
|
+
concurrency: effectiveConcurrency,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=panel-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-config.js","sourceRoot":"","sources":["../src/panel-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-config.test.d.ts","sourceRoot":"","sources":["../src/panel-config.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { ArgsParseError } from "./args.js";
|
|
4
|
+
import { resolvePanelConfig } from "./panel-config.js";
|
|
5
|
+
function baseParsed(overrides = {}) {
|
|
6
|
+
return {
|
|
7
|
+
command: "review",
|
|
8
|
+
mode: "code",
|
|
9
|
+
skills: [],
|
|
10
|
+
payload: ["@src"],
|
|
11
|
+
keepSession: false,
|
|
12
|
+
stream: true,
|
|
13
|
+
...overrides,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
const codeExperts = {
|
|
17
|
+
description: "Code expert panel",
|
|
18
|
+
reviewers: [
|
|
19
|
+
{ id: "correctness", role: "Correctness reviewer" },
|
|
20
|
+
{ id: "security", role: "Security reviewer" },
|
|
21
|
+
{ id: "testing", role: "Testing reviewer" },
|
|
22
|
+
],
|
|
23
|
+
};
|
|
24
|
+
test("generic panel builds N anonymous reviewers with default quorum two", () => {
|
|
25
|
+
const resolved = resolvePanelConfig(baseParsed({ reviewers: 3 }), {});
|
|
26
|
+
assert.equal(resolved.presetName, undefined);
|
|
27
|
+
assert.equal(resolved.reviewerCount, 3);
|
|
28
|
+
assert.deepEqual(resolved.reviewers.map((r) => r.id), ["r1", "r2", "r3"]);
|
|
29
|
+
assert.equal(resolved.consensus, "quorum");
|
|
30
|
+
assert.equal(resolved.minAgree, 2);
|
|
31
|
+
assert.equal(resolved.concurrency, 3);
|
|
32
|
+
assert.equal(resolved.semanticEnabled, false);
|
|
33
|
+
});
|
|
34
|
+
test("generic panel respects explicit consensus and min-agree", () => {
|
|
35
|
+
const resolved = resolvePanelConfig(baseParsed({ reviewers: 5, consensus: "majority" }), {});
|
|
36
|
+
assert.equal(resolved.consensus, "majority");
|
|
37
|
+
assert.equal(resolved.minAgree, undefined);
|
|
38
|
+
});
|
|
39
|
+
test("named panel uses preset reviewers and defaults", () => {
|
|
40
|
+
const resolved = resolvePanelConfig(baseParsed({ panel: "code-experts" }), { "code-experts": codeExperts });
|
|
41
|
+
assert.equal(resolved.presetName, "code-experts");
|
|
42
|
+
assert.equal(resolved.reviewerCount, 3);
|
|
43
|
+
assert.deepEqual(resolved.reviewers.map((r) => r.id), ["correctness", "security", "testing"]);
|
|
44
|
+
assert.equal(resolved.consensus, "quorum");
|
|
45
|
+
assert.equal(resolved.minAgree, 2);
|
|
46
|
+
});
|
|
47
|
+
test("named panel allows CLI consensus to override preset defaults", () => {
|
|
48
|
+
const resolved = resolvePanelConfig(baseParsed({ panel: "code-experts", consensus: "majority" }), { "code-experts": codeExperts });
|
|
49
|
+
assert.equal(resolved.consensus, "majority");
|
|
50
|
+
assert.equal(resolved.minAgree, undefined);
|
|
51
|
+
});
|
|
52
|
+
test("named panel allows CLI min-agree to override preset default under quorum", () => {
|
|
53
|
+
const resolved = resolvePanelConfig(baseParsed({ panel: "code-experts", consensus: "quorum", minAgree: 3 }), { "code-experts": codeExperts });
|
|
54
|
+
assert.equal(resolved.consensus, "quorum");
|
|
55
|
+
assert.equal(resolved.minAgree, 3);
|
|
56
|
+
});
|
|
57
|
+
test("named panel can enable semantic adjudication via consensusModel", () => {
|
|
58
|
+
const resolved = resolvePanelConfig(baseParsed({ panel: "code-experts", consensusModel: "openai/gpt-5.5" }), { "code-experts": codeExperts });
|
|
59
|
+
assert.equal(resolved.semanticEnabled, true);
|
|
60
|
+
assert.equal(resolved.consensusModel, "openai/gpt-5.5");
|
|
61
|
+
});
|
|
62
|
+
function expectUsage(parsed, presets, pattern) {
|
|
63
|
+
assert.throws(() => resolvePanelConfig(baseParsed(parsed), presets), (error) => error instanceof ArgsParseError && error.exitCode === 2 && pattern.test(error.message));
|
|
64
|
+
}
|
|
65
|
+
test("unknown panel preset is a usage error", () => {
|
|
66
|
+
expectUsage({ panel: "missing" }, { "code-experts": codeExperts }, /unknown panel preset: missing/);
|
|
67
|
+
});
|
|
68
|
+
test("panel preset with no reviewers is a usage error", () => {
|
|
69
|
+
expectUsage({ panel: "empty" }, { empty: { description: "x", reviewers: [] } }, /at least one reviewer/);
|
|
70
|
+
});
|
|
71
|
+
test("panel preset exceeding the reviewer limit is a usage error", () => {
|
|
72
|
+
const tooMany = {
|
|
73
|
+
description: "x",
|
|
74
|
+
reviewers: Array.from({ length: 9 }, (_, i) => ({ id: `r${i + 1}`, role: "role" })),
|
|
75
|
+
};
|
|
76
|
+
expectUsage({ panel: "big" }, { big: tooMany }, /max 8/);
|
|
77
|
+
});
|
|
78
|
+
test("panel preset with a reviewer missing id or role is a usage error", () => {
|
|
79
|
+
expectUsage({ panel: "broken" }, { broken: { description: "x", reviewers: [{ id: "r1", role: "" }] } }, /missing id or role/);
|
|
80
|
+
});
|
|
81
|
+
test("impossible quorum (min-agree greater than reviewer count) is a usage error", () => {
|
|
82
|
+
expectUsage({ panel: "code-experts", consensus: "quorum", minAgree: 4 }, { "code-experts": codeExperts }, /cannot exceed reviewer count 3/);
|
|
83
|
+
});
|
|
84
|
+
test("min-agree with a non-quorum policy (from preset combination) is a usage error", () => {
|
|
85
|
+
const presetWithMin = { ...codeExperts, consensus: "any", minAgree: 2 };
|
|
86
|
+
expectUsage({ panel: "code-experts" }, { "code-experts": presetWithMin }, /only meaningful with quorum/);
|
|
87
|
+
});
|
|
88
|
+
test("concurrency greater than reviewer count is a usage error", () => {
|
|
89
|
+
expectUsage({ reviewers: 2, concurrency: 5 }, {}, /--concurrency 5 cannot exceed reviewer count 2/);
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=panel-config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-config.test.js","sourceRoot":"","sources":["../src/panel-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,SAAS,UAAU,CAAC,YAAiC,EAAE;IACrD,OAAO;QACL,OAAO,EAAE,QAAQ;QACjB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,EAAE;QACV,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,WAAW,EAAE,KAAK;QAClB,MAAM,EAAE,IAAI;QACZ,GAAG,SAAS;KACb,CAAC;AACJ,CAAC;AAED,MAAM,WAAW,GAAgB;IAC/B,WAAW,EAAE,mBAAmB;IAChC,SAAS,EAAE;QACT,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,sBAAsB,EAAE;QACnD,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,mBAAmB,EAAE;QAC7C,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE;KAC5C;CACF,CAAC;AAEF,IAAI,CAAC,oEAAoE,EAAE,GAAG,EAAE;IAC9E,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACxC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1E,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACnC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;AAChD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;IACnE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7F,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE;IAC1D,MAAM,QAAQ,GAAG,kBAAkB,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;IAC5G,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IACxC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;IAC9F,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8DAA8D,EAAE,GAAG,EAAE;IACxE,MAAM,QAAQ,GAAG,kBAAkB,CACjC,UAAU,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,EAC5D,EAAE,cAAc,EAAE,WAAW,EAAE,CAChC,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0EAA0E,EAAE,GAAG,EAAE;IACpF,MAAM,QAAQ,GAAG,kBAAkB,CACjC,UAAU,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EACvE,EAAE,cAAc,EAAE,WAAW,EAAE,CAChC,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;AACrC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;IAC3E,MAAM,QAAQ,GAAG,kBAAkB,CACjC,UAAU,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAC,EACvE,EAAE,cAAc,EAAE,WAAW,EAAE,CAChC,CAAC;IACF,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;AAC1D,CAAC,CAAC,CAAC;AAEH,SAAS,WAAW,CAAC,MAA2B,EAAE,OAAoC,EAAE,OAAe;IACrG,MAAM,CAAC,MAAM,CACX,GAAG,EAAE,CAAC,kBAAkB,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,EACrD,CAAC,KAAc,EAAE,EAAE,CAAC,KAAK,YAAY,cAAc,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAC3G,CAAC;AACJ,CAAC;AAED,IAAI,CAAC,uCAAuC,EAAE,GAAG,EAAE;IACjD,WAAW,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,EAAE,+BAA+B,CAAC,CAAC;AACtG,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;IAC3D,WAAW,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,EAAE,uBAAuB,CAAC,CAAC;AAC3G,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4DAA4D,EAAE,GAAG,EAAE;IACtE,MAAM,OAAO,GAAgB;QAC3B,WAAW,EAAE,GAAG;QAChB,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;KACpF,CAAC;IACF,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kEAAkE,EAAE,GAAG,EAAE;IAC5E,WAAW,CACT,EAAE,KAAK,EAAE,QAAQ,EAAE,EACnB,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EACrE,oBAAoB,CACrB,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4EAA4E,EAAE,GAAG,EAAE;IACtF,WAAW,CACT,EAAE,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,EAAE,EAC3D,EAAE,cAAc,EAAE,WAAW,EAAE,EAC/B,gCAAgC,CACjC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+EAA+E,EAAE,GAAG,EAAE;IACzF,MAAM,aAAa,GAAgB,EAAE,GAAG,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACrF,WAAW,CACT,EAAE,KAAK,EAAE,cAAc,EAAE,EACzB,EAAE,cAAc,EAAE,aAAa,EAAE,EACjC,6BAA6B,CAC9B,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;IACpE,WAAW,CACT,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,EAChC,EAAE,EACF,gDAAgD,CACjD,CAAC;AACJ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-loop.test.d.ts","sourceRoot":"","sources":["../src/panel-loop.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { formatLoopSummary, runReviewLoop } from "./loop.js";
|
|
4
|
+
function cluster(summary, opts = {}) {
|
|
5
|
+
const support = opts.support ?? 1;
|
|
6
|
+
return {
|
|
7
|
+
id: "C1",
|
|
8
|
+
summary,
|
|
9
|
+
confirmed: opts.confirmed ?? false,
|
|
10
|
+
supportCount: support,
|
|
11
|
+
actionableSupportCount: opts.actionableSupport ?? support,
|
|
12
|
+
supportingReviewerIds: opts.reviewers ?? ["r1"],
|
|
13
|
+
sourceFindingIds: ["r1#F1"],
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function panelMeta(status, opts = {}) {
|
|
17
|
+
const confirmed = opts.confirmed ?? [];
|
|
18
|
+
const advisories = opts.advisories ?? [];
|
|
19
|
+
const verdict = status === "clean" ? "approve" : status === "has_findings" ? "request_changes" : status === "needs_human" ? "needs_clarification" : "blocked";
|
|
20
|
+
return {
|
|
21
|
+
strategy: "panel",
|
|
22
|
+
reviewMode: "code",
|
|
23
|
+
verdict,
|
|
24
|
+
verdictSource: "parsed",
|
|
25
|
+
status,
|
|
26
|
+
findings: confirmed.map((c) => ({ id: c.id, summary: c.summary, actionable: true })),
|
|
27
|
+
actionableCount: confirmed.length,
|
|
28
|
+
durationMs: opts.durationMs ?? 100,
|
|
29
|
+
model: null,
|
|
30
|
+
configuredReviewers: opts.configured ?? 3,
|
|
31
|
+
successfulReviewers: opts.successful ?? opts.configured ?? 3,
|
|
32
|
+
consensusPolicy: (opts.policy ?? "quorum"),
|
|
33
|
+
consensusThreshold: opts.threshold ?? 2,
|
|
34
|
+
panelHealth: (opts.health ?? (status === "blocked" ? "blocked" : status === "needs_human" ? "needs_human" : "healthy")),
|
|
35
|
+
confirmedClusters: confirmed,
|
|
36
|
+
advisories,
|
|
37
|
+
reviewers: [],
|
|
38
|
+
adjudicationUsed: false,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const confirmedFinding = [cluster("Off-by-one", { confirmed: true, support: 2, actionableSupport: 2, reviewers: ["r1", "r2"] })];
|
|
42
|
+
test("panel loop stops after a clean first panel", async () => {
|
|
43
|
+
let calls = 0;
|
|
44
|
+
const result = await runReviewLoop(3, async () => {
|
|
45
|
+
calls += 1;
|
|
46
|
+
return { meta: panelMeta("clean"), exitCode: 0 };
|
|
47
|
+
});
|
|
48
|
+
assert.equal(calls, 1);
|
|
49
|
+
assert.equal(result.stopReason, "clean");
|
|
50
|
+
assert.equal(result.exitCode, 0);
|
|
51
|
+
assert.equal(result.rounds[0].panel?.confirmedCount, 0);
|
|
52
|
+
});
|
|
53
|
+
test("panel loop stops when a later panel becomes clean", async () => {
|
|
54
|
+
const sequence = [
|
|
55
|
+
{ meta: panelMeta("has_findings", { confirmed: confirmedFinding }), exitCode: 1 },
|
|
56
|
+
{ meta: panelMeta("clean"), exitCode: 0 },
|
|
57
|
+
];
|
|
58
|
+
const result = await runReviewLoop(3, async (i) => sequence[i - 1]);
|
|
59
|
+
assert.equal(result.stopReason, "clean");
|
|
60
|
+
assert.deepEqual(result.rounds.map((r) => r.status), ["has_findings", "clean"]);
|
|
61
|
+
assert.equal(result.rounds[0].panel?.confirmedCount, 1);
|
|
62
|
+
assert.equal(result.rounds[1].panel?.confirmedCount, 0);
|
|
63
|
+
});
|
|
64
|
+
test("panel loop exhausts the budget while confirmed findings remain", async () => {
|
|
65
|
+
let calls = 0;
|
|
66
|
+
const result = await runReviewLoop(2, async () => {
|
|
67
|
+
calls += 1;
|
|
68
|
+
return { meta: panelMeta("has_findings", { confirmed: confirmedFinding }), exitCode: 1 };
|
|
69
|
+
});
|
|
70
|
+
assert.equal(calls, 2);
|
|
71
|
+
assert.equal(result.stopReason, "budget_exhausted");
|
|
72
|
+
assert.equal(result.exitCode, 1);
|
|
73
|
+
});
|
|
74
|
+
test("panel loop escalates blocked and needs-human panels immediately", async () => {
|
|
75
|
+
for (const scenario of [
|
|
76
|
+
{ status: "blocked", exit: 4, health: "blocked" },
|
|
77
|
+
{ status: "needs_human", exit: 3, health: "needs_human" },
|
|
78
|
+
]) {
|
|
79
|
+
let calls = 0;
|
|
80
|
+
const result = await runReviewLoop(3, async () => {
|
|
81
|
+
calls += 1;
|
|
82
|
+
return { meta: panelMeta(scenario.status, { health: scenario.health }), exitCode: scenario.exit };
|
|
83
|
+
});
|
|
84
|
+
assert.equal(calls, 1);
|
|
85
|
+
assert.equal(result.stopReason, scenario.status);
|
|
86
|
+
assert.equal(result.exitCode, scenario.exit);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
test("panel loop execution count: reviewer runs scale with executed rounds and early stop reduces runs", async () => {
|
|
90
|
+
const reviewerCount = 3;
|
|
91
|
+
let calls = 0;
|
|
92
|
+
await runReviewLoop(5, async () => {
|
|
93
|
+
calls += 1;
|
|
94
|
+
return { meta: panelMeta("clean"), exitCode: 0 };
|
|
95
|
+
});
|
|
96
|
+
assert.equal(calls, 1);
|
|
97
|
+
assert.equal(calls * reviewerCount, reviewerCount);
|
|
98
|
+
let budgetCalls = 0;
|
|
99
|
+
await runReviewLoop(2, async () => {
|
|
100
|
+
budgetCalls += 1;
|
|
101
|
+
return { meta: panelMeta("has_findings", { confirmed: confirmedFinding, configured: reviewerCount }), exitCode: 1 };
|
|
102
|
+
});
|
|
103
|
+
assert.equal(budgetCalls, 2);
|
|
104
|
+
assert.equal(budgetCalls * reviewerCount, 6);
|
|
105
|
+
});
|
|
106
|
+
test("panel loop summary reports per-round support and consensus details", async () => {
|
|
107
|
+
const sequence = [
|
|
108
|
+
{ meta: panelMeta("has_findings", { confirmed: confirmedFinding, advisories: [cluster("Typo")], configured: 3, successful: 3, policy: "quorum", threshold: 2, health: "healthy", durationMs: 1200 }), exitCode: 1 },
|
|
109
|
+
{ meta: panelMeta("clean", { configured: 3, successful: 3, policy: "quorum", threshold: 2, durationMs: 800 }), exitCode: 0 },
|
|
110
|
+
];
|
|
111
|
+
const result = await runReviewLoop(3, async (i) => sequence[i - 1]);
|
|
112
|
+
const summary = formatLoopSummary(result);
|
|
113
|
+
assert.match(summary, /pi-review loop/);
|
|
114
|
+
assert.match(summary, /Round 1.*panel 3\/3.*1 confirmed \/ 1 advisory.*quorum≥2.*HEALTHY/);
|
|
115
|
+
assert.match(summary, /Round 2.*panel 3\/3.*0 confirmed \/ 0 advisory/);
|
|
116
|
+
assert.match(summary, /Stop.*clean/);
|
|
117
|
+
});
|
|
118
|
+
//# sourceMappingURL=panel-loop.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel-loop.test.js","sourceRoot":"","sources":["../src/panel-loop.test.ts"],"names":[],"mappings":"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"}
|
package/dist/panel.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ParsedArgs, PanelReviewMeta } from "./types.js";
|
|
2
|
+
export declare function emitPanelFooter(meta: PanelReviewMeta): void;
|
|
3
|
+
/** Run one complete panel evaluation and return the aggregate result (no exit). */
|
|
4
|
+
export declare function runPanelReviewOnce(parsed: ParsedArgs, stdinText?: string): Promise<{
|
|
5
|
+
meta: PanelReviewMeta;
|
|
6
|
+
exitCode: number;
|
|
7
|
+
}>;
|
|
8
|
+
/** CLI-compatible panel review entrypoint. */
|
|
9
|
+
export declare function runPanelReview(parsed: ParsedArgs): Promise<never>;
|
|
10
|
+
//# sourceMappingURL=panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EAIhB,MAAM,YAAY,CAAC;AAkCpB,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAa3D;AA6OD,mFAAmF;AACnF,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,SAAoB,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CA6DhJ;AAED,8CAA8C;AAC9C,wBAAsB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAGvE"}
|