@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
package/dist/panel.js
ADDED
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
// Panel review orchestration: run N independent reviewer child sessions with
|
|
2
|
+
// bounded concurrency, aggregate their structured findings into one panel
|
|
3
|
+
// result, and emit a single aggregate footer + metadata record. Reviewers and
|
|
4
|
+
// the consensus adjudicator remain review-only (no write tools, --no-session).
|
|
5
|
+
import fs from "node:fs";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { Writable } from "node:stream";
|
|
8
|
+
import { spawnBufferedChild, spawnStreamingChild } from "./child-process.js";
|
|
9
|
+
import { childEnv, childRuntimeError, readReviewStdin } from "./review.js";
|
|
10
|
+
import { loadPanelPresets, loadPresets, loadSystemPrompt } from "./presets.js";
|
|
11
|
+
import { splitPayload, buildReviewerPrompt, buildAdjudicatorPrompt } from "./prompt.js";
|
|
12
|
+
import { parseVerdict } from "./verdict.js";
|
|
13
|
+
import { parseReviewResult, reviewExitCode } from "./review-result.js";
|
|
14
|
+
import { extractFinalText, JsonEventStream } from "./json-events.js";
|
|
15
|
+
import { fail, expandMaybeHome, normalizeTools } from "./utils.js";
|
|
16
|
+
import { resolveConfig } from "./config.js";
|
|
17
|
+
import { resolvePanelConfig } from "./panel-config.js";
|
|
18
|
+
import { aggregatePanel } from "./panel-aggregate.js";
|
|
19
|
+
import { SemanticMatcher } from "./matcher.js";
|
|
20
|
+
import { formatPanelMetaAscii, formatPanelFindingsMarkdown, formatReviewMetaJsonLine } from "./meta-footer.js";
|
|
21
|
+
/** Emit the aggregate panel footer (ASCII + JSON) like a single review. */
|
|
22
|
+
/** Sum token usage across reviewers (prompt-scoped fields as maxima, output as additive). */
|
|
23
|
+
function sumUsage(usages) {
|
|
24
|
+
const present = usages.filter((u) => Boolean(u));
|
|
25
|
+
if (present.length === 0)
|
|
26
|
+
return undefined;
|
|
27
|
+
const total = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, totalTokens: 0 };
|
|
28
|
+
for (const u of present) {
|
|
29
|
+
total.input = Math.max(total.input, u.input);
|
|
30
|
+
total.cacheRead = Math.max(total.cacheRead, u.cacheRead);
|
|
31
|
+
total.cacheWrite = Math.max(total.cacheWrite, u.cacheWrite);
|
|
32
|
+
total.output += u.output;
|
|
33
|
+
total.reasoning = Math.max(total.reasoning, u.reasoning);
|
|
34
|
+
total.totalTokens = Math.max(total.totalTokens, u.totalTokens);
|
|
35
|
+
if (typeof u.costTotal === "number")
|
|
36
|
+
total.costTotal = (total.costTotal ?? 0) + u.costTotal;
|
|
37
|
+
}
|
|
38
|
+
return total;
|
|
39
|
+
}
|
|
40
|
+
export function emitPanelFooter(meta) {
|
|
41
|
+
// Issue #2 Decision 39: confirmed findings are the primary Findings section;
|
|
42
|
+
// advisories are clearly separated and labelled non-blocking.
|
|
43
|
+
const body = formatPanelFindingsMarkdown(meta);
|
|
44
|
+
if (body)
|
|
45
|
+
process.stdout.write(`${body}\n\n`);
|
|
46
|
+
process.stdout.write(`${formatPanelMetaAscii(meta)}\n`);
|
|
47
|
+
const metaJsonDest = process.env.PI_REVIEW_META_STDOUT?.toLowerCase();
|
|
48
|
+
const jsonLine = formatReviewMetaJsonLine(meta);
|
|
49
|
+
if (metaJsonDest === "1" || metaJsonDest === "true" || metaJsonDest === "stdout") {
|
|
50
|
+
process.stdout.write(jsonLine);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
process.stderr.write(jsonLine);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function reviewerProgressLog(baseProgressLog, reviewerId) {
|
|
57
|
+
if (!baseProgressLog)
|
|
58
|
+
return undefined;
|
|
59
|
+
const base = baseProgressLog.replace(/\.jsonl$/i, "");
|
|
60
|
+
return `${base}.r${reviewerId}.jsonl`;
|
|
61
|
+
}
|
|
62
|
+
/** Tools that can mutate the working tree — forbidden for panel reviewers. */
|
|
63
|
+
const WRITE_TOOLS = new Set([
|
|
64
|
+
"edit", "write", "apply_patch", "create_file", "create", "patch",
|
|
65
|
+
"str_replace_editor", "file_editor", "delete", "move",
|
|
66
|
+
]);
|
|
67
|
+
/** Force a read-only tool allowlist for panel reviewers (issue #2 review-only security). */
|
|
68
|
+
function readOnlyTools(tools) {
|
|
69
|
+
if (!tools)
|
|
70
|
+
return undefined;
|
|
71
|
+
const kept = tools
|
|
72
|
+
.split(",")
|
|
73
|
+
.map((t) => t.trim())
|
|
74
|
+
.filter((t) => t.length > 0 && !WRITE_TOOLS.has(t));
|
|
75
|
+
if (kept.length === 0)
|
|
76
|
+
return "read,grep,find,ls";
|
|
77
|
+
return kept.join(",");
|
|
78
|
+
}
|
|
79
|
+
function buildReviewerArgs(config, parsed, preset, prompt, fileRefs, reviewer, progressLog, systemPrompt) {
|
|
80
|
+
const args = ["-p", "--mode", "json"];
|
|
81
|
+
if (systemPrompt)
|
|
82
|
+
args.push("--append-system-prompt", systemPrompt);
|
|
83
|
+
const provider = reviewer.provider || parsed.provider || preset.provider;
|
|
84
|
+
const model = reviewer.model || parsed.model || preset.model;
|
|
85
|
+
const thinking = reviewer.thinking || parsed.thinking || preset.thinking;
|
|
86
|
+
if (provider)
|
|
87
|
+
args.push("--provider", provider);
|
|
88
|
+
if (model)
|
|
89
|
+
args.push("--model", model);
|
|
90
|
+
if (thinking)
|
|
91
|
+
args.push("--thinking", thinking);
|
|
92
|
+
const tools = readOnlyTools(parsed.tools || normalizeTools(preset.tools));
|
|
93
|
+
if (tools)
|
|
94
|
+
args.push("--tools", tools);
|
|
95
|
+
const presetSkills = Array.isArray(preset.skillPaths) ? preset.skillPaths : [];
|
|
96
|
+
for (const skill of [...presetSkills, ...parsed.skills]) {
|
|
97
|
+
args.push("--skill", expandMaybeHome(skill));
|
|
98
|
+
}
|
|
99
|
+
args.push("--no-session");
|
|
100
|
+
args.push(...fileRefs, prompt);
|
|
101
|
+
return args;
|
|
102
|
+
}
|
|
103
|
+
async function runReviewerChild(input) {
|
|
104
|
+
const { config, parsed, preset, prompt, fileRefs, reviewer, progressLog, systemPrompt } = input;
|
|
105
|
+
const args = buildReviewerArgs(config, parsed, preset, prompt, fileRefs, reviewer, progressLog, systemPrompt);
|
|
106
|
+
let progressStream;
|
|
107
|
+
if (progressLog) {
|
|
108
|
+
fs.mkdirSync(path.dirname(progressLog), { recursive: true });
|
|
109
|
+
progressStream = fs.createWriteStream(progressLog, { flags: "a" });
|
|
110
|
+
}
|
|
111
|
+
// Reviewers always run in --mode json. A JsonEventStream accumulates token
|
|
112
|
+
// usage and emits reviewer-prefixed milestones to stderr; reviewer prose is
|
|
113
|
+
// NOT forwarded to stdout so concurrent reviewers never interleave (issue #2
|
|
114
|
+
// progress isolation). The raw json lines tee into the progress-log file.
|
|
115
|
+
const streamParser = new JsonEventStream({
|
|
116
|
+
onText: () => { },
|
|
117
|
+
onMilestone: (line) => process.stderr.write(` [${reviewer.id}] ${line}`),
|
|
118
|
+
});
|
|
119
|
+
const stdoutSink = new Writable({
|
|
120
|
+
write(chunk, _enc, cb) {
|
|
121
|
+
const text = String(chunk);
|
|
122
|
+
if (progressStream)
|
|
123
|
+
progressStream.write(text);
|
|
124
|
+
streamParser.feed(text);
|
|
125
|
+
cb();
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
const stderrChunks = [];
|
|
129
|
+
const stderrSink = new Writable({ write(chunk, _enc, cb) { stderrChunks.push(String(chunk)); cb(); } });
|
|
130
|
+
const child = await spawnStreamingChild(config.piBin, args, {
|
|
131
|
+
cwd: process.cwd(),
|
|
132
|
+
env: childEnv(config.piBin),
|
|
133
|
+
stdoutSink,
|
|
134
|
+
stderrSink,
|
|
135
|
+
});
|
|
136
|
+
streamParser.flush();
|
|
137
|
+
if (progressStream) {
|
|
138
|
+
await new Promise((resolve) => progressStream.end(() => resolve()));
|
|
139
|
+
}
|
|
140
|
+
let stdout = child.stdout || "";
|
|
141
|
+
const runtimeError = childRuntimeError(child);
|
|
142
|
+
// Surface a captured reviewer stderr tail only when the child failed, so
|
|
143
|
+
// concurrent reviewer diagnostics never interleave on the shared terminal.
|
|
144
|
+
const reviewerStderr = stderrChunks.join("");
|
|
145
|
+
let extractedError;
|
|
146
|
+
let extractedFatal = false;
|
|
147
|
+
const reviewerUsage = streamParser.usage().usage;
|
|
148
|
+
{
|
|
149
|
+
const extracted = extractFinalText(stdout);
|
|
150
|
+
stdout = extracted.text;
|
|
151
|
+
extractedError = extracted.error;
|
|
152
|
+
extractedFatal = Boolean(extracted.fatal);
|
|
153
|
+
}
|
|
154
|
+
let verdictInfo = parseVerdict(stdout);
|
|
155
|
+
if (runtimeError) {
|
|
156
|
+
const detail = [runtimeError, reviewerStderr.slice(-2000)].filter(Boolean).join("; ");
|
|
157
|
+
verdictInfo = { verdict: "blocked", verdictSource: "runtime_error", parseError: detail };
|
|
158
|
+
}
|
|
159
|
+
else if (extractedFatal) {
|
|
160
|
+
const detail = [extractedError, reviewerStderr.slice(-2000)].filter(Boolean).join("; ");
|
|
161
|
+
verdictInfo = { verdict: "blocked", verdictSource: "runtime_error", parseError: detail };
|
|
162
|
+
}
|
|
163
|
+
else if (extractedError) {
|
|
164
|
+
verdictInfo = { ...verdictInfo, parseError: [verdictInfo.parseError, extractedError].filter(Boolean).join("; ") };
|
|
165
|
+
}
|
|
166
|
+
const structured = parseReviewResult(stdout, verdictInfo);
|
|
167
|
+
const model = reviewer.model || parsed.model || preset.model || null;
|
|
168
|
+
const thinking = reviewer.thinking || parsed.thinking || preset.thinking;
|
|
169
|
+
return {
|
|
170
|
+
reviewerId: reviewer.id,
|
|
171
|
+
role: reviewer.role,
|
|
172
|
+
model,
|
|
173
|
+
...(thinking ? { thinking } : {}),
|
|
174
|
+
...(reviewerUsage ? { usage: reviewerUsage } : {}),
|
|
175
|
+
durationMs: 0, // set by caller wrapper
|
|
176
|
+
result: structured,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
async function mapWithConcurrency(items, concurrency, fn) {
|
|
180
|
+
const results = new Array(items.length);
|
|
181
|
+
let cursor = 0;
|
|
182
|
+
async function worker() {
|
|
183
|
+
while (cursor < items.length) {
|
|
184
|
+
const index = cursor;
|
|
185
|
+
cursor += 1;
|
|
186
|
+
results[index] = await fn(items[index], index);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
|
|
190
|
+
return results;
|
|
191
|
+
}
|
|
192
|
+
/** Real semantic adjudicator: spawns a review-only Pi session with the consensus model. */
|
|
193
|
+
function createAdjudicator(config, consensusModel) {
|
|
194
|
+
// Dedicated JSON-only system prompt. The adjudicator must NOT inherit the
|
|
195
|
+
// review Markdown output contract (system-prompt.md), which would conflict
|
|
196
|
+
// with the strict JSON clustering response and break parsing.
|
|
197
|
+
const adjudicatorSystemPrompt = [
|
|
198
|
+
"You are the consensus adjudicator for a panel code review.",
|
|
199
|
+
"Your only output is one JSON object matching the requested clustering schema.",
|
|
200
|
+
"Do not output Markdown, prose, or any other format. Do not review code quality.",
|
|
201
|
+
"You may not invent findings, drop findings, or act as a reviewer.",
|
|
202
|
+
].join("\n");
|
|
203
|
+
return {
|
|
204
|
+
async adjudicate(request) {
|
|
205
|
+
const prompt = buildAdjudicatorPrompt(request.candidates);
|
|
206
|
+
// The adjudicator is aggregation-only: it must not inspect the repository
|
|
207
|
+
// as an additional reviewer and has no write capability. Disable all tools
|
|
208
|
+
// and run with no session — it returns JSON purely from the structured
|
|
209
|
+
// findings embedded in the prompt.
|
|
210
|
+
const args = ["-p", "--no-session", "--no-tools", "--append-system-prompt", adjudicatorSystemPrompt];
|
|
211
|
+
if (consensusModel)
|
|
212
|
+
args.push("--model", consensusModel);
|
|
213
|
+
args.push(prompt);
|
|
214
|
+
const child = spawnBufferedChild(config.piBin, args, {
|
|
215
|
+
cwd: process.cwd(),
|
|
216
|
+
env: childEnv(config.piBin),
|
|
217
|
+
});
|
|
218
|
+
const runtimeError = childRuntimeError(child);
|
|
219
|
+
if (runtimeError) {
|
|
220
|
+
throw new Error(runtimeError);
|
|
221
|
+
}
|
|
222
|
+
const stdout = (child.stdout || "").trim();
|
|
223
|
+
const jsonStart = stdout.indexOf("{");
|
|
224
|
+
const jsonEnd = stdout.lastIndexOf("}");
|
|
225
|
+
if (jsonStart === -1 || jsonEnd === -1 || jsonEnd < jsonStart) {
|
|
226
|
+
return { merges: [], errors: ["adjudicator returned no parseable JSON object"] };
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
const parsed = JSON.parse(stdout.slice(jsonStart, jsonEnd + 1));
|
|
230
|
+
if (!parsed || !Array.isArray(parsed.merges)) {
|
|
231
|
+
return { merges: [], errors: ["adjudicator response missing a merges array"] };
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
merges: parsed.merges,
|
|
235
|
+
...(Array.isArray(parsed.errors) ? { errors: parsed.errors.map(String) } : {}),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
return { merges: [], errors: [`failed to parse adjudicator response: ${error.message}`] };
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** Resolve the panel config or fail with a usage error. */
|
|
245
|
+
function resolvePanel(parsed, config) {
|
|
246
|
+
const panelPresets = loadPanelPresets(config.panelPresetsFile);
|
|
247
|
+
try {
|
|
248
|
+
return resolvePanelConfig(parsed, panelPresets);
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
if (error instanceof Error)
|
|
252
|
+
fail(error.message);
|
|
253
|
+
throw error;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/** Run one complete panel evaluation and return the aggregate result (no exit). */
|
|
257
|
+
export async function runPanelReviewOnce(parsed, stdinText = readReviewStdin()) {
|
|
258
|
+
const config = resolveConfig();
|
|
259
|
+
const resolved = resolvePanel(parsed, config);
|
|
260
|
+
const presets = loadPresets(config.presetsFile);
|
|
261
|
+
const preset = presets[parsed.mode];
|
|
262
|
+
if (!preset) {
|
|
263
|
+
fail(`unknown review mode: ${parsed.mode}\nAvailable modes: ${Object.keys(presets).join(", ")}`);
|
|
264
|
+
}
|
|
265
|
+
const systemPrompt = loadSystemPrompt(config.systemPromptFile);
|
|
266
|
+
const payload = splitPayload(parsed.payload);
|
|
267
|
+
const startedAt = Date.now();
|
|
268
|
+
const submissions = await mapWithConcurrency(resolved.reviewers, resolved.concurrency, async (reviewer) => {
|
|
269
|
+
const reviewerStart = Date.now();
|
|
270
|
+
const prompt = buildReviewerPrompt(parsed.mode, preset, payload, stdinText, reviewer);
|
|
271
|
+
const progressLog = reviewerProgressLog(parsed.progressLog, reviewer.id);
|
|
272
|
+
const submission = await runReviewerChild({
|
|
273
|
+
config,
|
|
274
|
+
parsed,
|
|
275
|
+
preset,
|
|
276
|
+
prompt,
|
|
277
|
+
fileRefs: payload.fileRefs,
|
|
278
|
+
reviewer,
|
|
279
|
+
progressLog,
|
|
280
|
+
systemPrompt,
|
|
281
|
+
});
|
|
282
|
+
return { ...submission, durationMs: Date.now() - reviewerStart };
|
|
283
|
+
});
|
|
284
|
+
// Semantic adjudication is on by default (issue #2 Decision 27): when
|
|
285
|
+
// ambiguous same-path candidates exist, a constrained adjudicator clusters
|
|
286
|
+
// them. --consensus-model overrides the adjudicator model; otherwise fall
|
|
287
|
+
// back to the shared review model / Pi default. Exact matches never invoke
|
|
288
|
+
// the adjudicator, so this stays cheap when there is nothing ambiguous.
|
|
289
|
+
const adjudicatorModel = resolved.consensusModel ?? parsed.model ?? preset.model ?? undefined;
|
|
290
|
+
const matcher = new SemanticMatcher(createAdjudicator(config, adjudicatorModel));
|
|
291
|
+
const aggregate = await aggregatePanel({
|
|
292
|
+
reviewers: submissions,
|
|
293
|
+
policy: resolved.consensus,
|
|
294
|
+
...(resolved.minAgree !== undefined ? { minAgree: resolved.minAgree } : {}),
|
|
295
|
+
configuredReviewers: resolved.reviewerCount,
|
|
296
|
+
matcher,
|
|
297
|
+
});
|
|
298
|
+
const panelMeta = {
|
|
299
|
+
...aggregate,
|
|
300
|
+
reviewMode: parsed.mode,
|
|
301
|
+
durationMs: Date.now() - startedAt,
|
|
302
|
+
model: parsed.model || preset.model || null,
|
|
303
|
+
thinking: parsed.thinking || preset.thinking,
|
|
304
|
+
usage: sumUsage(submissions.map((s) => s.usage)),
|
|
305
|
+
...(resolved.presetName ? { panelPreset: resolved.presetName } : {}),
|
|
306
|
+
};
|
|
307
|
+
emitPanelFooter(panelMeta);
|
|
308
|
+
return { meta: panelMeta, exitCode: reviewExitCode(panelMeta.status) };
|
|
309
|
+
}
|
|
310
|
+
/** CLI-compatible panel review entrypoint. */
|
|
311
|
+
export async function runPanelReview(parsed) {
|
|
312
|
+
const result = await runPanelReviewOnce(parsed);
|
|
313
|
+
process.exit(result.exitCode);
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.js","sourceRoot":"","sources":["../src/panel.ts"],"names":[],"mappings":"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"}
|
package/dist/presets.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ReviewPreset } from "./types.js";
|
|
1
|
+
import type { PanelPreset, ReviewPreset } from "./types.js";
|
|
2
2
|
export declare function loadPresets(presetsFile: string): Record<string, ReviewPreset>;
|
|
3
|
+
export declare function loadPanelPresets(panelPresetsFile: string): Record<string, PanelPreset>;
|
|
3
4
|
export declare function loadSystemPrompt(systemPromptFile: string): string;
|
|
4
5
|
//# sourceMappingURL=presets.d.ts.map
|
package/dist/presets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG5D,wBAAgB,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAS7E;AAED,wBAAgB,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAOtF;AAED,wBAAgB,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAOjE"}
|
package/dist/presets.js
CHANGED
|
@@ -11,6 +11,16 @@ export function loadPresets(presetsFile) {
|
|
|
11
11
|
fail(`failed to read preset file ${presetsFile}: ${error.message}`);
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
+
export function loadPanelPresets(panelPresetsFile) {
|
|
15
|
+
if (!fs.existsSync(panelPresetsFile))
|
|
16
|
+
return {};
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(fs.readFileSync(panelPresetsFile, "utf8"));
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
fail(`failed to read panel preset file ${panelPresetsFile}: ${error.message}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
14
24
|
export function loadSystemPrompt(systemPromptFile) {
|
|
15
25
|
if (!fs.existsSync(systemPromptFile))
|
|
16
26
|
return "";
|
package/dist/presets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,8BAA8B,WAAW,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,gBAAwB;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,gCAAgC,gBAAgB,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../src/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,IAAI,CAAC,0BAA0B,WAAW,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,8BAA8B,WAAW,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,gBAAwB;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,oCAAoC,gBAAgB,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAC5F,CAAC;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,gBAAwB;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,gCAAgC,gBAAgB,KAAM,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IACxF,CAAC;AACH,CAAC"}
|
package/dist/prompt.d.ts
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
import type { ReviewPreset, SplitPayload } from "./types.js";
|
|
1
|
+
import type { PanelReviewerSpec, ReviewPreset, SplitPayload } from "./types.js";
|
|
2
|
+
import type { AdjudicationCandidate } from "./matcher.js";
|
|
2
3
|
export declare function splitPayload(payload: string[]): SplitPayload;
|
|
3
4
|
export declare function buildPrompt(mode: string, preset: ReviewPreset, payload: SplitPayload, stdinText: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Reviewer prompt for panel review: the shared review contract plus a stable
|
|
7
|
+
* reviewer identity/role. Reviewers never receive another reviewer's output.
|
|
8
|
+
*/
|
|
9
|
+
export declare function buildReviewerPrompt(mode: string, preset: ReviewPreset, payload: SplitPayload, stdinText: string, reviewer?: PanelReviewerSpec): string;
|
|
10
|
+
/**
|
|
11
|
+
* Strict clustering contract for the consensus adjudicator. It receives
|
|
12
|
+
* structured findings only, returns cluster assignments with confidence, and
|
|
13
|
+
* may not invent findings, drop findings, claim new evidence, or act as a
|
|
14
|
+
* reviewer. It has no write tools.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildAdjudicatorPrompt(candidates: AdjudicationCandidate[]): string;
|
|
4
17
|
//# sourceMappingURL=prompt.d.ts.map
|
package/dist/prompt.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEhF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AA4B1D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,YAAY,CAQ5D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEhH;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,MAAM,CAYR;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAoBlF"}
|
package/dist/prompt.js
CHANGED
|
@@ -1,22 +1,14 @@
|
|
|
1
1
|
import { VERDICTS } from "./types.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const textParts = [];
|
|
5
|
-
for (const item of payload) {
|
|
6
|
-
if (item.startsWith("@"))
|
|
7
|
-
fileRefs.push(item);
|
|
8
|
-
else
|
|
9
|
-
textParts.push(item);
|
|
10
|
-
}
|
|
11
|
-
return { fileRefs, userText: textParts.join(" ").trim() };
|
|
12
|
-
}
|
|
13
|
-
export function buildPrompt(mode, preset, payload, stdinText) {
|
|
14
|
-
const sections = [
|
|
2
|
+
function contractSections(mode, preset) {
|
|
3
|
+
return [
|
|
15
4
|
`You are running pi-review mode \`${mode}\`.`,
|
|
16
5
|
"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.",
|
|
17
6
|
preset.instructions || "Review the supplied material and return a concise conclusion.",
|
|
18
|
-
`Output Markdown with exactly these top-level sections:\n\n## Verdict\nOne of: ${VERDICTS.join(" | ")}\n\n## Summary\nShort conclusion in 2-5 bullets.\n\n## Findings\nPrioritized findings.
|
|
7
|
+
`Output Markdown with exactly these top-level sections:\n\n## Verdict\nOne of: ${VERDICTS.join(" | ")}\n\n## Summary\nShort conclusion in 2-5 bullets.\n\n## Findings\nPrioritized findings. For every material finding, use this exact shape (increment IDs as F1, F2, ...):\n\n### F1: <summary>\n- Severity: critical | high | medium | low\n- Path: <path or none>\n- Actionable: yes | no\n- Evidence: <concrete evidence>\n- Impact: <why it matters>\n- Recommendation: <specific next step>\n\nSet 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. If there are no material findings, write "No material findings."\n\n## Risks and Blind Spots\nWhat could still be wrong, missing, or unverified.\n\n## Open Questions\nQuestions the parent agent or user should answer before acting. If none, write "None."`,
|
|
19
8
|
];
|
|
9
|
+
}
|
|
10
|
+
function targetSections(payload, stdinText) {
|
|
11
|
+
const sections = [];
|
|
20
12
|
if (payload.userText) {
|
|
21
13
|
sections.push(`<user-request>\n${payload.userText}\n</user-request>`);
|
|
22
14
|
}
|
|
@@ -29,6 +21,60 @@ export function buildPrompt(mode, preset, payload, stdinText) {
|
|
|
29
21
|
if (!payload.userText && !stdinText && payload.fileRefs.length === 0) {
|
|
30
22
|
sections.push("No explicit target was provided. Return blocked and explain what input is required.");
|
|
31
23
|
}
|
|
32
|
-
return sections
|
|
24
|
+
return sections;
|
|
25
|
+
}
|
|
26
|
+
export function splitPayload(payload) {
|
|
27
|
+
const fileRefs = [];
|
|
28
|
+
const textParts = [];
|
|
29
|
+
for (const item of payload) {
|
|
30
|
+
if (item.startsWith("@"))
|
|
31
|
+
fileRefs.push(item);
|
|
32
|
+
else
|
|
33
|
+
textParts.push(item);
|
|
34
|
+
}
|
|
35
|
+
return { fileRefs, userText: textParts.join(" ").trim() };
|
|
36
|
+
}
|
|
37
|
+
export function buildPrompt(mode, preset, payload, stdinText) {
|
|
38
|
+
return [...contractSections(mode, preset), ...targetSections(payload, stdinText)].join("\n\n");
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Reviewer prompt for panel review: the shared review contract plus a stable
|
|
42
|
+
* reviewer identity/role. Reviewers never receive another reviewer's output.
|
|
43
|
+
*/
|
|
44
|
+
export function buildReviewerPrompt(mode, preset, payload, stdinText, reviewer) {
|
|
45
|
+
const preamble = reviewer
|
|
46
|
+
? [
|
|
47
|
+
"You are an independent panel reviewer.",
|
|
48
|
+
`- Reviewer ID: ${reviewer.id}`,
|
|
49
|
+
`- Role: ${reviewer.role}`,
|
|
50
|
+
"You cannot see other reviewers' findings. Submit your own independent conclusion only.",
|
|
51
|
+
].join("\n")
|
|
52
|
+
: "";
|
|
53
|
+
return [preamble, ...contractSections(mode, preset), ...targetSections(payload, stdinText)]
|
|
54
|
+
.filter(Boolean)
|
|
55
|
+
.join("\n\n");
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Strict clustering contract for the consensus adjudicator. It receives
|
|
59
|
+
* structured findings only, returns cluster assignments with confidence, and
|
|
60
|
+
* may not invent findings, drop findings, claim new evidence, or act as a
|
|
61
|
+
* reviewer. It has no write tools.
|
|
62
|
+
*/
|
|
63
|
+
export function buildAdjudicatorPrompt(candidates) {
|
|
64
|
+
const candidateBlocks = candidates.map((candidate, index) => {
|
|
65
|
+
const items = candidate.findings.map((sf) => `- id: ${sf.id}\n reviewer: ${sf.reviewerId}\n path: ${sf.finding.path ?? "(none)"}\n summary: ${sf.finding.summary}\n actionable: ${sf.finding.actionable ? "yes" : "no"}`);
|
|
66
|
+
return `Candidate group ${index + 1} (shared path anchor: ${candidate.anchorPath || "(none)"}):\n${items.join("\n")}`;
|
|
67
|
+
});
|
|
68
|
+
return [
|
|
69
|
+
"You are the consensus adjudicator for a panel code review. Your only job is to decide which findings describe the same underlying issue.",
|
|
70
|
+
"You are aggregation-only. You may not invent new findings, drop findings, add evidence, or act as an additional reviewer. You have no write tools.",
|
|
71
|
+
"Below are candidate groups of findings that share a file path but differ in wording. For each set of findings that you determine describe the same underlying issue, propose a merge.",
|
|
72
|
+
"Only merge findings that genuinely describe the same underlying issue. When unsure, do not merge.",
|
|
73
|
+
"Respond with one JSON object only, no prose, in this exact shape:",
|
|
74
|
+
'{"merges":[{"sourceFindingIds":["r1#F1","r2#F1"],"confidence":0.9}]}',
|
|
75
|
+
"`confidence` is a number between 0 and 1 expressing how sure you are that the listed findings are the same issue. Use 0 when unrelated. Every source id you reference must come from the candidates below.",
|
|
76
|
+
"Candidate findings:",
|
|
77
|
+
candidateBlocks.join("\n\n"),
|
|
78
|
+
].join("\n\n");
|
|
33
79
|
}
|
|
34
80
|
//# sourceMappingURL=prompt.js.map
|
package/dist/prompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.test.d.ts","sourceRoot":"","sources":["../src/prompt.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import { buildPrompt, buildReviewerPrompt, buildAdjudicatorPrompt } from "./prompt.js";
|
|
4
|
+
test("review prompt requests the parseable finding contract", () => {
|
|
5
|
+
const prompt = buildPrompt("code", { description: "code", instructions: "Review the code." }, { fileRefs: ["@src/cli.ts"], userText: "" }, "");
|
|
6
|
+
assert.match(prompt, /### F1: <summary>/);
|
|
7
|
+
assert.match(prompt, /Severity: critical \| high \| medium \| low/);
|
|
8
|
+
assert.match(prompt, /Path: <path or none>/);
|
|
9
|
+
assert.match(prompt, /Actionable: yes \| no/);
|
|
10
|
+
assert.match(prompt, /No material findings\./);
|
|
11
|
+
});
|
|
12
|
+
test("reviewer prompt injects stable reviewer identity and the shared contract", () => {
|
|
13
|
+
const reviewer = { id: "security", role: "Security reviewer" };
|
|
14
|
+
const prompt = buildReviewerPrompt("code", { description: "code", instructions: "Review the code." }, { fileRefs: ["@src/cli.ts"], userText: "" }, "", reviewer);
|
|
15
|
+
assert.match(prompt, /Reviewer ID: security/);
|
|
16
|
+
assert.match(prompt, /Role: Security reviewer/);
|
|
17
|
+
assert.match(prompt, /cannot see other reviewers' findings/);
|
|
18
|
+
assert.match(prompt, /### F1: <summary>/);
|
|
19
|
+
assert.match(prompt, /## Verdict/);
|
|
20
|
+
});
|
|
21
|
+
test("adjudicator prompt enforces aggregation-only constraints and the strict clustering contract", () => {
|
|
22
|
+
const findings = [
|
|
23
|
+
{ id: "r1#F1", reviewerId: "r1", finding: { summary: "loop bound is wrong", actionable: true, path: "src/cli.ts" } },
|
|
24
|
+
{ id: "r2#F1", reviewerId: "r2", finding: { summary: "off-by-one iteration", actionable: true, path: "src/cli.ts" } },
|
|
25
|
+
];
|
|
26
|
+
const prompt = buildAdjudicatorPrompt([{ anchorPath: "src/cli.ts", findings }]);
|
|
27
|
+
assert.match(prompt, /consensus adjudicator/i);
|
|
28
|
+
assert.match(prompt, /aggregation-only/);
|
|
29
|
+
assert.match(prompt, /may not invent new findings/);
|
|
30
|
+
assert.match(prompt, /no write tools/);
|
|
31
|
+
assert.match(prompt, /"sourceFindingIds":\["r1#F1","r2#F1"\],"confidence"/);
|
|
32
|
+
assert.match(prompt, /must come from the candidates below/);
|
|
33
|
+
// Adjudicator receives structured findings, not free repo access.
|
|
34
|
+
assert.match(prompt, /r1#F1/);
|
|
35
|
+
assert.match(prompt, /loop bound is wrong/);
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=prompt.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.test.js","sourceRoot":"","sources":["../src/prompt.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ReviewStatus, StructuredReviewResult, VerdictInfo } from "./types.js";
|
|
2
|
+
export declare function reviewExitCode(status: ReviewStatus): number;
|
|
3
|
+
/** Derives the machine review contract from the human-readable conclusion. */
|
|
4
|
+
export declare function parseReviewResult(markdown: string, verdictInfo?: VerdictInfo): StructuredReviewResult;
|
|
5
|
+
//# sourceMappingURL=review-result.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review-result.d.ts","sourceRoot":"","sources":["../src/review-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,YAAY,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAoFnG,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAE3D;AAED,8EAA8E;AAC9E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,WAAW,GAAE,WAAoC,GAChD,sBAAsB,CA4BxB"}
|