@mrclrchtr/supi-review 2.8.0 → 3.1.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 +71 -180
- package/node_modules/@mrclrchtr/supi-core/package.json +2 -1
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/evidence-badge.ts +40 -0
- package/package.json +3 -3
- package/src/config.ts +30 -21
- package/src/git-command.ts +78 -0
- package/src/git.ts +311 -507
- package/src/history/collect.ts +43 -120
- package/src/model.ts +3 -1
- package/src/review-path.ts +85 -0
- package/src/review-result.ts +43 -92
- package/src/review.ts +187 -286
- package/src/session/review-plan-store.ts +20 -51
- package/src/target/packet.ts +46 -369
- package/src/tool/agent-review-schemas.ts +108 -104
- package/src/tool/agent-review-tools.ts +283 -307
- package/src/tool/child-failure-diagnostics.ts +59 -1
- package/src/tool/child-lifecycle-trace.ts +32 -3
- package/src/tool/child-resource-loader.ts +37 -0
- package/src/tool/child-session-runner.ts +83 -0
- package/src/tool/output-page.ts +47 -0
- package/src/tool/planner-runner.ts +69 -0
- package/src/tool/review-runner.ts +42 -257
- package/src/tool/review-system-prompt.ts +12 -110
- package/src/tool/review-tools.ts +119 -0
- package/src/tool/review-workflow.ts +325 -0
- package/src/tool/runner-helpers.ts +3 -8
- package/src/tool/schemas.ts +75 -62
- package/src/tui/common.ts +237 -0
- package/src/tui/prepare.ts +132 -0
- package/src/tui/run.ts +160 -0
- package/src/types.ts +157 -275
- package/src/history/synthesize.ts +0 -121
- package/src/tool/agent-review-workflow.ts +0 -398
- package/src/tool/brief-runner.ts +0 -180
- package/src/tool/guidance.ts +0 -21
- package/src/tool/review-handlers.ts +0 -314
- package/src/tool/snapshot-tools.ts +0 -117
- package/src/ui/flow.ts +0 -189
- package/src/ui/format-content.ts +0 -143
- package/src/ui/renderer.ts +0 -274
- package/src/ui/review-plan-inspector.ts +0 -391
- package/src/ui/review-tool-format.ts +0 -138
- package/src/ui/review-tool-renderer.ts +0 -234
package/src/types.ts
CHANGED
|
@@ -1,292 +1,100 @@
|
|
|
1
1
|
import type { Model } from "@earendil-works/pi-ai";
|
|
2
2
|
import type { ChildLifecycleTrace } from "./tool/child-lifecycle-trace.ts";
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
export type
|
|
6
|
-
| "session-creation-failed"
|
|
7
|
-
| "prompt-rejected"
|
|
8
|
-
| "missing-structured-output"
|
|
9
|
-
| "unexpected-runner-failure";
|
|
10
|
-
|
|
11
|
-
/** Managed child role used for host-owned failure copy. */
|
|
12
|
-
export type ChildStage = "brief-synthesis" | "reviewer";
|
|
13
|
-
|
|
14
|
-
/** Failed child result fields with diagnostics required exactly when a child was observed. */
|
|
15
|
-
export type ChildFailedResult =
|
|
16
|
-
| { failureCode: "session-creation-failed"; diagnostics?: never }
|
|
17
|
-
| {
|
|
18
|
-
failureCode: Exclude<ChildFailureCode, "session-creation-failed">;
|
|
19
|
-
diagnostics: ChildFailureDiagnostics;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
/** Inclusive 1-based line range reported by the reviewer. */
|
|
23
|
-
export interface ReviewLineRange {
|
|
24
|
-
start: number;
|
|
25
|
-
end: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** File location reported by the reviewer. */
|
|
29
|
-
export interface ReviewCodeLocation {
|
|
30
|
-
absolute_file_path: string;
|
|
31
|
-
line_range: ReviewLineRange;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type ReviewItemCategory =
|
|
35
|
-
| "correctness"
|
|
36
|
-
| "security"
|
|
37
|
-
| "performance"
|
|
38
|
-
| "api"
|
|
39
|
-
| "test-gap"
|
|
40
|
-
| "docs"
|
|
41
|
-
| "cleanup"
|
|
42
|
-
| "maintainer";
|
|
4
|
+
/** A full hexadecimal Git commit object id supplied by an agent caller. */
|
|
5
|
+
export type CommitId = string;
|
|
43
6
|
|
|
44
|
-
|
|
45
|
-
export type ReviewItemEffort = "low" | "medium" | "high";
|
|
46
|
-
export type ReviewItemRecommendedAction = "must-fix" | "should-fix" | "consider";
|
|
47
|
-
export type ReviewOverallCorrectness = "PATCH IS CORRECT" | "PATCH HAS ISSUES";
|
|
48
|
-
|
|
49
|
-
/** Structured review item returned by the reviewer session. */
|
|
50
|
-
export interface ReviewItem {
|
|
51
|
-
title: string;
|
|
52
|
-
body: string;
|
|
53
|
-
category: ReviewItemCategory;
|
|
54
|
-
impact: ReviewItemImpact;
|
|
55
|
-
effort: ReviewItemEffort;
|
|
56
|
-
recommended_action: ReviewItemRecommendedAction;
|
|
57
|
-
confidence_score: number;
|
|
58
|
-
suggested_fix: string;
|
|
59
|
-
verification_hint: string;
|
|
60
|
-
code_location?: ReviewCodeLocation;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/** Raw review payload submitted by the reviewer child session. */
|
|
64
|
-
export interface ReviewOutputEvent {
|
|
65
|
-
items: ReviewItem[];
|
|
66
|
-
overall_explanation: string;
|
|
67
|
-
overall_confidence_score: number;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export interface ReviewSummary {
|
|
71
|
-
actions: {
|
|
72
|
-
mustFix: number;
|
|
73
|
-
shouldFix: number;
|
|
74
|
-
consider: number;
|
|
75
|
-
};
|
|
76
|
-
categories: Partial<Record<ReviewItemCategory, number>>;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** Host-normalized review payload used for rendering and follow-up flow. */
|
|
80
|
-
export interface NormalizedReviewOutput extends ReviewOutputEvent {
|
|
81
|
-
overall_correctness: ReviewOverallCorrectness;
|
|
82
|
-
summary: ReviewSummary;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** User-selected review target. */
|
|
7
|
+
/** The Git change selected for review. */
|
|
86
8
|
export type ReviewTargetSpec =
|
|
87
9
|
| { kind: "working-tree" }
|
|
88
|
-
| { kind: "
|
|
89
|
-
| { kind: "commit";
|
|
10
|
+
| { kind: "comparison"; baseCommit: CommitId }
|
|
11
|
+
| { kind: "commit"; commit: CommitId };
|
|
12
|
+
|
|
13
|
+
/** Resolved identity of a selected review target. */
|
|
14
|
+
export type ResolvedReviewTarget =
|
|
15
|
+
| { kind: "working-tree"; headCommit: CommitId }
|
|
16
|
+
| {
|
|
17
|
+
kind: "comparison";
|
|
18
|
+
requestedBaseCommit: CommitId;
|
|
19
|
+
mergeBaseCommit: CommitId;
|
|
20
|
+
headCommit: CommitId;
|
|
21
|
+
}
|
|
22
|
+
| { kind: "commit"; commit: CommitId; parentCommit?: CommitId };
|
|
90
23
|
|
|
91
|
-
/** Diff statistics for a resolved snapshot. */
|
|
92
24
|
export interface DiffStats {
|
|
93
25
|
files: number;
|
|
94
26
|
additions: number;
|
|
95
27
|
deletions: number;
|
|
96
28
|
}
|
|
97
29
|
|
|
98
|
-
/** Concrete
|
|
30
|
+
/** Concrete target metadata and diff resolved before reviewer execution. */
|
|
99
31
|
export interface ReviewSnapshot {
|
|
100
|
-
|
|
32
|
+
requestedTarget: ReviewTargetSpec;
|
|
33
|
+
target: ResolvedReviewTarget;
|
|
101
34
|
title: string;
|
|
102
35
|
changedFiles: string[];
|
|
103
36
|
diffText: string;
|
|
104
37
|
stats: DiffStats;
|
|
105
38
|
}
|
|
106
39
|
|
|
107
|
-
/** Snapshot metadata safe to retain without duplicating bulk diff text. */
|
|
108
40
|
export type ReviewSnapshotSummary = Omit<ReviewSnapshot, "diffText">;
|
|
109
41
|
|
|
110
|
-
/**
|
|
111
|
-
export
|
|
112
|
-
|
|
113
|
-
/** Structured brief synthesized from the current session history. */
|
|
114
|
-
export type ReviewInstructionBlockId =
|
|
115
|
-
| "public-surface"
|
|
116
|
-
| "cross-layer"
|
|
117
|
-
| "schema-widening"
|
|
118
|
-
| "cleanup";
|
|
119
|
-
|
|
120
|
-
export interface SynthesizedReviewBrief {
|
|
121
|
-
summary: string;
|
|
122
|
-
intendedOutcome: string;
|
|
123
|
-
constraints: string[];
|
|
124
|
-
focusAreas: string[];
|
|
125
|
-
riskyFiles: string[];
|
|
126
|
-
unresolvedQuestions: string[];
|
|
127
|
-
reviewInstructionBlockIds: ReviewInstructionBlockId[];
|
|
128
|
-
note?: string;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** Brief field evaluated by the main agent before reviewer sessions run. */
|
|
132
|
-
export type ReviewBriefField =
|
|
133
|
-
| "summary"
|
|
134
|
-
| "intendedOutcome"
|
|
135
|
-
| "constraints"
|
|
136
|
-
| "focusAreas"
|
|
137
|
-
| "riskyFiles"
|
|
138
|
-
| "unresolvedQuestions"
|
|
139
|
-
| "reviewInstructionBlockIds";
|
|
140
|
-
|
|
141
|
-
/** Class of defect identified in a generated review brief. */
|
|
142
|
-
export type BriefCritiqueFindingKind =
|
|
143
|
-
| "omission"
|
|
144
|
-
| "unsupported-inference"
|
|
145
|
-
| "misprioritized"
|
|
146
|
-
| "unclear";
|
|
147
|
-
|
|
148
|
-
/** One evidence-backed main-agent criticism of a generated review brief. */
|
|
149
|
-
export interface BriefCritiqueFinding {
|
|
150
|
-
kind: BriefCritiqueFindingKind;
|
|
151
|
-
field: ReviewBriefField;
|
|
152
|
-
explanation: string;
|
|
153
|
-
evidence: string;
|
|
154
|
-
proposedChange: string;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/** Structured quality gate completed by the main agent before review execution. */
|
|
158
|
-
export interface BriefCritique {
|
|
159
|
-
verdict: "accept" | "revise";
|
|
160
|
-
summary: string;
|
|
161
|
-
findings: BriefCritiqueFinding[];
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/** One independent reviewer child-session assignment. */
|
|
165
|
-
export interface ReviewerAssignment {
|
|
42
|
+
/** One independent caller-defined review objective. */
|
|
43
|
+
export interface ReviewTask {
|
|
166
44
|
id: string;
|
|
167
|
-
|
|
45
|
+
instructions: string;
|
|
168
46
|
}
|
|
169
47
|
|
|
170
|
-
/**
|
|
171
|
-
export interface
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
generatedBrief: SynthesizedReviewBrief;
|
|
175
|
-
critique: BriefCritique;
|
|
176
|
-
effectiveBrief: SynthesizedReviewBrief;
|
|
177
|
-
synthesizerModelId: string;
|
|
178
|
-
snapshotFingerprint: string;
|
|
48
|
+
/** Semantic input shared with the reviewer tasks in one run. */
|
|
49
|
+
export interface ReviewInput {
|
|
50
|
+
sharedContext?: string;
|
|
51
|
+
tasks: ReviewTask[];
|
|
179
52
|
}
|
|
180
53
|
|
|
181
|
-
/**
|
|
182
|
-
export type
|
|
183
|
-
| {
|
|
184
|
-
kind: "success";
|
|
185
|
-
output: NormalizedReviewOutput;
|
|
186
|
-
modelId: string;
|
|
187
|
-
}
|
|
188
|
-
| ({ kind: "failed"; modelId: string } & ChildFailedResult)
|
|
189
|
-
| {
|
|
190
|
-
kind: "canceled";
|
|
191
|
-
modelId: string;
|
|
192
|
-
diagnostics: ChildFailureDiagnostics;
|
|
193
|
-
}
|
|
194
|
-
| {
|
|
195
|
-
kind: "timeout";
|
|
196
|
-
timeoutMs: number;
|
|
197
|
-
modelId: string;
|
|
198
|
-
diagnostics: ChildFailureDiagnostics;
|
|
199
|
-
};
|
|
54
|
+
/** Advisory review input generated by the optional lightweight Planner. */
|
|
55
|
+
export type PlannerDraft = ReviewInput;
|
|
200
56
|
|
|
201
|
-
|
|
202
|
-
export
|
|
203
|
-
|
|
204
|
-
result: AgentReviewerResult;
|
|
205
|
-
}
|
|
57
|
+
export type FindingImpact = "low" | "medium" | "high";
|
|
58
|
+
export type FindingEffort = "small" | "medium" | "large";
|
|
59
|
+
export type TaskVerdict = "pass" | "issues";
|
|
206
60
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
snapshot: ReviewSnapshotSummary;
|
|
212
|
-
results: ReviewerAssignmentResult[];
|
|
61
|
+
export interface ReviewLocation {
|
|
62
|
+
path: string;
|
|
63
|
+
startLine: number;
|
|
64
|
+
endLine: number;
|
|
213
65
|
}
|
|
214
66
|
|
|
215
|
-
/**
|
|
216
|
-
export interface
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
67
|
+
/** One structured issue submitted by a reviewer task. */
|
|
68
|
+
export interface ReviewFinding {
|
|
69
|
+
title: string;
|
|
70
|
+
description: string;
|
|
71
|
+
blocksAcceptance: boolean;
|
|
72
|
+
impact: FindingImpact;
|
|
73
|
+
effort: FindingEffort;
|
|
74
|
+
confidence: number;
|
|
75
|
+
location?: ReviewLocation;
|
|
224
76
|
}
|
|
225
77
|
|
|
226
|
-
/**
|
|
227
|
-
export interface
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
omittedFiles: string[];
|
|
231
|
-
charBudget: number;
|
|
78
|
+
/** Fixed Review Engine-owned submission grammar. */
|
|
79
|
+
export interface ReviewSubmission {
|
|
80
|
+
summary: string;
|
|
81
|
+
findings: ReviewFinding[];
|
|
232
82
|
}
|
|
233
83
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
model: ReviewModelSelection;
|
|
237
|
-
snapshot: ReviewSnapshot;
|
|
238
|
-
brief: SynthesizedReviewBrief;
|
|
239
|
-
packet: ReviewPacket;
|
|
84
|
+
export interface NormalizedReviewSubmission extends ReviewSubmission {
|
|
85
|
+
verdict: TaskVerdict;
|
|
240
86
|
}
|
|
241
87
|
|
|
242
|
-
|
|
243
|
-
export type RawReviewResult =
|
|
244
|
-
| {
|
|
245
|
-
kind: "success";
|
|
246
|
-
output: ReviewOutputEvent;
|
|
247
|
-
snapshot: ReviewSnapshot;
|
|
248
|
-
brief?: SynthesizedReviewBrief;
|
|
249
|
-
modelId: string;
|
|
250
|
-
}
|
|
251
|
-
| ({
|
|
252
|
-
kind: "failed";
|
|
253
|
-
snapshot: ReviewSnapshot;
|
|
254
|
-
brief?: SynthesizedReviewBrief;
|
|
255
|
-
modelId: string;
|
|
256
|
-
} & ChildFailedResult)
|
|
257
|
-
| {
|
|
258
|
-
kind: "canceled";
|
|
259
|
-
snapshot: ReviewSnapshot;
|
|
260
|
-
brief?: SynthesizedReviewBrief;
|
|
261
|
-
modelId: string;
|
|
262
|
-
diagnostics: ChildFailureDiagnostics;
|
|
263
|
-
}
|
|
264
|
-
| {
|
|
265
|
-
kind: "timeout";
|
|
266
|
-
snapshot: ReviewSnapshot;
|
|
267
|
-
timeoutMs: number;
|
|
268
|
-
brief?: SynthesizedReviewBrief;
|
|
269
|
-
modelId: string;
|
|
270
|
-
diagnostics: ChildFailureDiagnostics;
|
|
271
|
-
};
|
|
88
|
+
export type ReviewModelSelection = import("@mrclrchtr/supi-core/model-selection").ModelSelection;
|
|
272
89
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
modelId: string;
|
|
281
|
-
}
|
|
282
|
-
| Extract<RawReviewResult, { kind: "failed" | "canceled" | "timeout" }>;
|
|
90
|
+
export type ChildStage = "planner" | "reviewer";
|
|
91
|
+
|
|
92
|
+
export type ChildFailureCode =
|
|
93
|
+
| "session-creation-failed"
|
|
94
|
+
| "prompt-rejected"
|
|
95
|
+
| "missing-structured-output"
|
|
96
|
+
| "unexpected-runner-failure";
|
|
283
97
|
|
|
284
|
-
/**
|
|
285
|
-
* Safe bounded diagnostics attached only to a non-success managed child run.
|
|
286
|
-
*
|
|
287
|
-
* The trace and Recent Activity lane contain only allowlisted control metadata;
|
|
288
|
-
* no child-generated text, caught error, or raw SDK event is retained.
|
|
289
|
-
*/
|
|
290
98
|
export interface ChildFailureDiagnostics {
|
|
291
99
|
lifecycleTrace: ChildLifecycleTrace;
|
|
292
100
|
turns: number;
|
|
@@ -301,15 +109,22 @@ export interface ChildFailureDiagnostics {
|
|
|
301
109
|
recentActivity?: string[];
|
|
302
110
|
lastAssistantStopReason?: string;
|
|
303
111
|
lastAssistantToolCalls?: string[];
|
|
112
|
+
/** Error text extracted from the last assistant message when stopReason is "error". */
|
|
113
|
+
lastAssistantErrorText?: string;
|
|
114
|
+
/** Error text extracted from the most recent lifecycle event (compaction_end, auto_retry_end). */
|
|
115
|
+
lastLifecycleErrorText?: string;
|
|
304
116
|
}
|
|
305
117
|
|
|
306
|
-
|
|
118
|
+
export type ChildFailedResult =
|
|
119
|
+
| { failureCode: "session-creation-failed"; diagnostics?: never }
|
|
120
|
+
| {
|
|
121
|
+
failureCode: Exclude<ChildFailureCode, "session-creation-failed">;
|
|
122
|
+
diagnostics: ChildFailureDiagnostics;
|
|
123
|
+
};
|
|
124
|
+
|
|
307
125
|
export interface ReviewProgress {
|
|
308
|
-
/** Number of agent turns completed. */
|
|
309
126
|
turns: number;
|
|
310
|
-
/** Number of tool executions started. */
|
|
311
127
|
toolUses: number;
|
|
312
|
-
/** Token usage stats, if available. */
|
|
313
128
|
tokens?: {
|
|
314
129
|
input: number;
|
|
315
130
|
output: number;
|
|
@@ -317,42 +132,109 @@ export interface ReviewProgress {
|
|
|
317
132
|
cacheRead?: number;
|
|
318
133
|
cacheWrite?: number;
|
|
319
134
|
};
|
|
320
|
-
/** Per-tool execution counts keyed by short display label (e.g. "diffs", "reads", "greps"). */
|
|
321
135
|
toolCounts?: Record<string, number>;
|
|
322
|
-
/** Number of distinct files inspected so far (via read_snapshot_diff / read_snapshot_file). */
|
|
323
|
-
filesInspected?: number;
|
|
324
|
-
/** Total files in the review snapshot. */
|
|
325
|
-
filesTotal?: number;
|
|
326
|
-
/** Current tool + context for the progress narrative line. */
|
|
327
136
|
currentFocus?: { label: string; detail: string };
|
|
328
|
-
/** Elapsed time in milliseconds since the operation started. */
|
|
329
137
|
elapsedMs?: number;
|
|
330
138
|
}
|
|
331
139
|
|
|
332
|
-
export
|
|
333
|
-
| { kind: "success"; brief: SynthesizedReviewBrief }
|
|
334
|
-
| ({ kind: "failed" } & ChildFailedResult)
|
|
335
|
-
| { kind: "canceled"; diagnostics: ChildFailureDiagnostics }
|
|
336
|
-
| { kind: "timeout"; timeoutMs: number; diagnostics: ChildFailureDiagnostics };
|
|
337
|
-
|
|
338
|
-
export interface BriefSynthesisInvocation {
|
|
140
|
+
export interface PlannerInvocation {
|
|
339
141
|
prompt: string;
|
|
340
|
-
// biome-ignore lint/suspicious/noExplicitAny: Model<any> is
|
|
142
|
+
// biome-ignore lint/suspicious/noExplicitAny: Model<any> is Pi's canonical type
|
|
341
143
|
model: Model<any>;
|
|
342
144
|
cwd: string;
|
|
343
145
|
signal?: AbortSignal;
|
|
344
|
-
timeoutMs?: number;
|
|
345
146
|
onProgress?: (progress: ReviewProgress) => void;
|
|
346
147
|
}
|
|
347
148
|
|
|
348
|
-
export
|
|
149
|
+
export type PlannerRunResult =
|
|
150
|
+
| { kind: "success"; draft: PlannerDraft }
|
|
151
|
+
| ({ kind: "failed" } & ChildFailedResult)
|
|
152
|
+
| { kind: "canceled"; diagnostics: ChildFailureDiagnostics }
|
|
153
|
+
| { kind: "timeout"; timeoutMs: number; diagnostics: ChildFailureDiagnostics };
|
|
154
|
+
|
|
155
|
+
export interface ReviewerInvocation {
|
|
349
156
|
prompt: string;
|
|
157
|
+
task: ReviewTask;
|
|
350
158
|
model: ReviewModelSelection;
|
|
351
159
|
cwd: string;
|
|
352
|
-
signal?: AbortSignal;
|
|
353
160
|
snapshot: ReviewSnapshot;
|
|
354
|
-
|
|
355
|
-
timeoutMs?: number;
|
|
356
|
-
onToolActivity?: (event: { toolName: string; phase: "start" | "end" }) => void;
|
|
161
|
+
signal?: AbortSignal;
|
|
357
162
|
onProgress?: (progress: ReviewProgress) => void;
|
|
358
163
|
}
|
|
164
|
+
|
|
165
|
+
export type ReviewerRunResult =
|
|
166
|
+
| { kind: "success"; submission: ReviewSubmission; modelId: string }
|
|
167
|
+
| ({ kind: "failed"; modelId: string } & ChildFailedResult)
|
|
168
|
+
| { kind: "canceled"; modelId: string; diagnostics: ChildFailureDiagnostics }
|
|
169
|
+
| {
|
|
170
|
+
kind: "timeout";
|
|
171
|
+
timeoutMs: number;
|
|
172
|
+
modelId: string;
|
|
173
|
+
diagnostics: ChildFailureDiagnostics;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
interface ReviewTaskResultIdentity {
|
|
177
|
+
taskId: string;
|
|
178
|
+
modelId: string;
|
|
179
|
+
/** SHA-256 of the exact reviewer packet bytes. */
|
|
180
|
+
packetHash: string;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export type ReviewTaskResult = ReviewTaskResultIdentity &
|
|
184
|
+
(
|
|
185
|
+
| {
|
|
186
|
+
status: "completed";
|
|
187
|
+
verdict: TaskVerdict;
|
|
188
|
+
summary: string;
|
|
189
|
+
findings: ReviewFinding[];
|
|
190
|
+
}
|
|
191
|
+
| {
|
|
192
|
+
status: "failed";
|
|
193
|
+
failureCode: ChildFailureCode;
|
|
194
|
+
diagnostics?: ChildFailureDiagnostics;
|
|
195
|
+
}
|
|
196
|
+
| {
|
|
197
|
+
status: "canceled";
|
|
198
|
+
diagnostics: ChildFailureDiagnostics;
|
|
199
|
+
}
|
|
200
|
+
| {
|
|
201
|
+
status: "timeout";
|
|
202
|
+
timeoutMs: number;
|
|
203
|
+
diagnostics: ChildFailureDiagnostics;
|
|
204
|
+
}
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
export interface PlanningRecord {
|
|
208
|
+
promptVersion: string;
|
|
209
|
+
modelId: string;
|
|
210
|
+
draft: PlannerDraft;
|
|
211
|
+
effectiveReview: ReviewInput;
|
|
212
|
+
decision: "accept-draft" | "use-review";
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export interface ReviewBatchDetails {
|
|
216
|
+
kind: "review-batch";
|
|
217
|
+
mode: "direct" | "prepared";
|
|
218
|
+
provenance: "caller-supplied" | "planner-assisted";
|
|
219
|
+
snapshot: ReviewSnapshotSummary;
|
|
220
|
+
review: ReviewInput;
|
|
221
|
+
planning?: PlanningRecord;
|
|
222
|
+
results: ReviewTaskResult[];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export interface PreparedReviewDetails {
|
|
226
|
+
kind: "review-prepared";
|
|
227
|
+
planId: string;
|
|
228
|
+
snapshot: ReviewSnapshotSummary;
|
|
229
|
+
reviewerModelId: string;
|
|
230
|
+
plannerDraft?: PlannerDraft;
|
|
231
|
+
plannerModelId?: string;
|
|
232
|
+
plannerPromptVersion?: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface ReviewPacket {
|
|
236
|
+
prompt: string;
|
|
237
|
+
/** SHA-256 of prompt encoded as UTF-8, used to verify adapter parity. */
|
|
238
|
+
packetHash: string;
|
|
239
|
+
taskId: string;
|
|
240
|
+
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { listReviewInstructionBlocks } from "../target/packet.ts";
|
|
2
|
-
import { runBriefSynthesis } from "../tool/brief-runner.ts";
|
|
3
|
-
import type {
|
|
4
|
-
BriefSynthesisRunResult,
|
|
5
|
-
ReviewModelSelection,
|
|
6
|
-
ReviewProgress,
|
|
7
|
-
ReviewSnapshot,
|
|
8
|
-
} from "../types.ts";
|
|
9
|
-
|
|
10
|
-
const DIFF_EXCERPT_CHAR_BUDGET = 12_000;
|
|
11
|
-
|
|
12
|
-
/** Version of the brief-synthesis prompt contract retained in evaluation artifacts. */
|
|
13
|
-
export const BRIEF_SYNTHESIS_PROMPT_VERSION = "1";
|
|
14
|
-
|
|
15
|
-
export interface SynthesizeReviewBriefOptions {
|
|
16
|
-
model: ReviewModelSelection;
|
|
17
|
-
cwd: string;
|
|
18
|
-
snapshot: ReviewSnapshot;
|
|
19
|
-
serializedContext: string;
|
|
20
|
-
note?: string;
|
|
21
|
-
signal?: AbortSignal;
|
|
22
|
-
onProgress?: (progress: ReviewProgress) => void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** Synthesize a structured review brief from the current snapshot and session context. */
|
|
26
|
-
export function synthesizeReviewBrief(
|
|
27
|
-
options: SynthesizeReviewBriefOptions,
|
|
28
|
-
): Promise<BriefSynthesisRunResult> {
|
|
29
|
-
const { model, cwd, snapshot, serializedContext, note, signal, onProgress } = options;
|
|
30
|
-
|
|
31
|
-
return runBriefSynthesis({
|
|
32
|
-
prompt: buildBriefSynthesisPrompt(snapshot, serializedContext, note),
|
|
33
|
-
model: model.model,
|
|
34
|
-
cwd,
|
|
35
|
-
signal,
|
|
36
|
-
onProgress,
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function buildBriefSynthesisPrompt(
|
|
41
|
-
snapshot: ReviewSnapshot,
|
|
42
|
-
serializedContext: string,
|
|
43
|
-
note?: string,
|
|
44
|
-
): string {
|
|
45
|
-
const diffExcerpt = buildDiffExcerpt(snapshot.diffText);
|
|
46
|
-
const instructionBlocks = listReviewInstructionBlocks();
|
|
47
|
-
const parts: string[] = [
|
|
48
|
-
"# Review Brief Synthesis Input",
|
|
49
|
-
"",
|
|
50
|
-
"You are preparing a review brief for a second code-reviewing agent.",
|
|
51
|
-
"Infer the likely goal, constraints, and focus areas from the active session history.",
|
|
52
|
-
"Be concise, evidence-based, and avoid inventing requirements that are not supported by the input.",
|
|
53
|
-
"",
|
|
54
|
-
"## Snapshot",
|
|
55
|
-
`Target: ${snapshot.title}`,
|
|
56
|
-
`Files changed: ${snapshot.changedFiles.length}`,
|
|
57
|
-
`Diff stats: +${snapshot.stats.additions} / -${snapshot.stats.deletions}`,
|
|
58
|
-
"",
|
|
59
|
-
"### Changed files",
|
|
60
|
-
...snapshot.changedFiles.map((file) => `- ${file}`),
|
|
61
|
-
];
|
|
62
|
-
|
|
63
|
-
if (diffExcerpt.text) {
|
|
64
|
-
parts.push("", "### Diff excerpt", "```diff", diffExcerpt.text, "```");
|
|
65
|
-
if (diffExcerpt.truncated) {
|
|
66
|
-
parts.push(`> Note: diff excerpt truncated to ${diffExcerpt.text.length} characters.`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (instructionBlocks.length > 0) {
|
|
71
|
-
parts.push(
|
|
72
|
-
"",
|
|
73
|
-
"## Available review instruction blocks",
|
|
74
|
-
...instructionBlocks.map((block) => `- ${block.id}: ${block.title} — ${block.instruction}`),
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (note?.trim()) {
|
|
79
|
-
parts.push("", "## User note", note.trim());
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
parts.push("", "## Serialized session context");
|
|
83
|
-
if (serializedContext.trim()) {
|
|
84
|
-
parts.push(serializedContext.trim());
|
|
85
|
-
} else {
|
|
86
|
-
parts.push("No session context was available. Derive the brief from the snapshot only.");
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
parts.push(
|
|
90
|
-
"",
|
|
91
|
-
"## Output requirements",
|
|
92
|
-
"Call submit_review_brief with:",
|
|
93
|
-
"- summary: one-sentence summary of the likely change",
|
|
94
|
-
"- intendedOutcome: what the session seems to be trying to achieve",
|
|
95
|
-
"- constraints: invariants or requirements to preserve",
|
|
96
|
-
"- focusAreas: what the reviewer should inspect carefully",
|
|
97
|
-
"- riskyFiles: changed files that seem especially important or risky.",
|
|
98
|
-
" Prioritize files touching auth, data handling, core logic, error handling, or public APIs.",
|
|
99
|
-
" Include only files from the changed-files list above.",
|
|
100
|
-
"- unresolvedQuestions: ambiguities or concerns that remain unclear",
|
|
101
|
-
"- reviewInstructionBlockIds: zero or more IDs from the available review instruction block catalog",
|
|
102
|
-
" Select only blocks that are clearly supported by the supplied session/snapshot evidence.",
|
|
103
|
-
" Prefer omission over guessing. Do not invent new IDs.",
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
return parts.join("\n");
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function buildDiffExcerpt(diffText: string): { text: string; truncated: boolean } {
|
|
110
|
-
const trimmed = diffText.trim();
|
|
111
|
-
if (!trimmed) {
|
|
112
|
-
return { text: "", truncated: false };
|
|
113
|
-
}
|
|
114
|
-
if (trimmed.length <= DIFF_EXCERPT_CHAR_BUDGET) {
|
|
115
|
-
return { text: trimmed, truncated: false };
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
text: `${trimmed.slice(0, DIFF_EXCERPT_CHAR_BUDGET)}\n[... diff excerpt truncated ...]`,
|
|
119
|
-
truncated: true,
|
|
120
|
-
};
|
|
121
|
-
}
|