@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.
Files changed (45) hide show
  1. package/README.md +71 -180
  2. package/node_modules/@mrclrchtr/supi-core/package.json +2 -1
  3. package/node_modules/@mrclrchtr/supi-core/src/api.ts +2 -0
  4. package/node_modules/@mrclrchtr/supi-core/src/evidence-badge.ts +40 -0
  5. package/package.json +3 -3
  6. package/src/config.ts +30 -21
  7. package/src/git-command.ts +78 -0
  8. package/src/git.ts +311 -507
  9. package/src/history/collect.ts +43 -120
  10. package/src/model.ts +3 -1
  11. package/src/review-path.ts +85 -0
  12. package/src/review-result.ts +43 -92
  13. package/src/review.ts +187 -286
  14. package/src/session/review-plan-store.ts +20 -51
  15. package/src/target/packet.ts +46 -369
  16. package/src/tool/agent-review-schemas.ts +108 -104
  17. package/src/tool/agent-review-tools.ts +283 -307
  18. package/src/tool/child-failure-diagnostics.ts +59 -1
  19. package/src/tool/child-lifecycle-trace.ts +32 -3
  20. package/src/tool/child-resource-loader.ts +37 -0
  21. package/src/tool/child-session-runner.ts +83 -0
  22. package/src/tool/output-page.ts +47 -0
  23. package/src/tool/planner-runner.ts +69 -0
  24. package/src/tool/review-runner.ts +42 -257
  25. package/src/tool/review-system-prompt.ts +12 -110
  26. package/src/tool/review-tools.ts +119 -0
  27. package/src/tool/review-workflow.ts +325 -0
  28. package/src/tool/runner-helpers.ts +3 -8
  29. package/src/tool/schemas.ts +75 -62
  30. package/src/tui/common.ts +237 -0
  31. package/src/tui/prepare.ts +132 -0
  32. package/src/tui/run.ts +160 -0
  33. package/src/types.ts +157 -275
  34. package/src/history/synthesize.ts +0 -121
  35. package/src/tool/agent-review-workflow.ts +0 -398
  36. package/src/tool/brief-runner.ts +0 -180
  37. package/src/tool/guidance.ts +0 -21
  38. package/src/tool/review-handlers.ts +0 -314
  39. package/src/tool/snapshot-tools.ts +0 -117
  40. package/src/ui/flow.ts +0 -189
  41. package/src/ui/format-content.ts +0 -143
  42. package/src/ui/renderer.ts +0 -274
  43. package/src/ui/review-plan-inspector.ts +0 -391
  44. package/src/ui/review-tool-format.ts +0 -138
  45. package/src/ui/review-tool-renderer.ts +0 -234
@@ -1,234 +0,0 @@
1
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
- import { Container, Spacer, Text } from "@earendil-works/pi-tui";
3
- import type { PrepareAgentReviewInput, RunAgentReviewInput } from "../tool/agent-review-schemas.ts";
4
- import {
5
- formatChildFailureCopy,
6
- formatChildFailureDiagnostics,
7
- } from "../tool/child-failure-diagnostics.ts";
8
- import type {
9
- AgentReviewBatchDetails,
10
- PreparedAgentReviewDetails,
11
- ReviewProgress,
12
- } from "../types.ts";
13
- import { formatBrief, formatCritique } from "./review-tool-format.ts";
14
-
15
- type ReviewTheme = Parameters<Parameters<ExtensionAPI["registerMessageRenderer"]>[1]>[2];
16
-
17
- interface ToolResultLike {
18
- content: Array<{ type: string; text?: string }>;
19
- details?: unknown;
20
- }
21
-
22
- /** Partial tool-result details used while synthesis or reviewer sessions are active. */
23
- export interface AgentReviewProgressDetails {
24
- kind: "review-progress";
25
- phase: "prepare" | "review";
26
- completed: number;
27
- total: number;
28
- reviewers?: Record<string, ReviewProgress>;
29
- }
30
-
31
- export function renderPrepareReviewCall(args: PrepareAgentReviewInput, theme: ReviewTheme): Text {
32
- const target = args.target?.kind ?? "working-tree";
33
- const ref = args.target?.base ?? args.target?.sha;
34
- const suffix = ref ? ` (${ref})` : "";
35
- return new Text(
36
- `${theme.fg("toolTitle", theme.bold("supi_review_prepare "))}${theme.fg("accent", target)}${theme.fg("dim", suffix)}`,
37
- 0,
38
- 0,
39
- );
40
- }
41
-
42
- export function renderPrepareReviewResult(
43
- result: ToolResultLike,
44
- expanded: boolean,
45
- theme: ReviewTheme,
46
- ): Container | Text {
47
- const details = result.details as
48
- | PreparedAgentReviewDetails
49
- | AgentReviewProgressDetails
50
- | undefined;
51
- if (details?.kind === "review-progress") {
52
- return new Text(theme.fg("warning", "Synthesizing review brief…"), 0, 0);
53
- }
54
- if (details?.kind !== "review-prepared") return fallbackResult(result, theme);
55
-
56
- const container = new Container();
57
- container.addChild(
58
- new Text(
59
- `${theme.fg("success", "✓")} ${theme.fg("toolTitle", theme.bold("Review brief prepared"))}`,
60
- 0,
61
- 0,
62
- ),
63
- );
64
- container.addChild(new Text(theme.fg("dim", `Plan: ${details.planId}`), 0, 0));
65
- container.addChild(new Text(theme.fg("dim", `Snapshot: ${details.snapshot.title}`), 0, 0));
66
- container.addChild(
67
- new Text(theme.fg("muted", `Summary: ${details.generatedBrief.summary}`), 0, 0),
68
- );
69
- container.addChild(
70
- new Text(theme.fg("warning", "Main-agent critique required before run"), 0, 0),
71
- );
72
-
73
- if (expanded) {
74
- container.addChild(new Spacer(1));
75
- for (const line of formatBrief(details.generatedBrief)) {
76
- container.addChild(new Text(theme.fg("dim", line), 0, 0));
77
- }
78
- }
79
- return container;
80
- }
81
-
82
- export function renderRunReviewCall(
83
- args: RunAgentReviewInput,
84
- expanded: boolean,
85
- theme: ReviewTheme,
86
- ): Container | Text {
87
- const verdictColor = args.critique.verdict === "revise" ? "warning" : "success";
88
- const header = `${theme.fg("toolTitle", theme.bold("supi_review_run "))}${theme.fg(verdictColor, args.critique.verdict)}${theme.fg("dim", ` · ${args.critique.findings.length} critique finding(s) · ${args.reviewers.length} reviewer(s)`)}`;
89
- if (!expanded) return new Text(header, 0, 0);
90
-
91
- const container = new Container();
92
- container.addChild(new Text(header, 0, 0));
93
- for (const line of formatCritique(args.critique)) {
94
- container.addChild(new Text(theme.fg("dim", line), 0, 0));
95
- }
96
- if (args.revisedBrief) {
97
- container.addChild(new Spacer(1));
98
- container.addChild(new Text(theme.fg("accent", "Proposed revised brief"), 0, 0));
99
- for (const line of formatBrief(args.revisedBrief)) {
100
- container.addChild(new Text(theme.fg("dim", line), 0, 0));
101
- }
102
- }
103
- container.addChild(new Spacer(1));
104
- for (const reviewer of args.reviewers) {
105
- container.addChild(new Text(theme.fg("muted", `${reviewer.id}: ${reviewer.focus}`), 0, 0));
106
- }
107
- return container;
108
- }
109
-
110
- export function renderRunReviewResult(
111
- result: ToolResultLike,
112
- expanded: boolean,
113
- theme: ReviewTheme,
114
- ): Container | Text {
115
- const details = result.details as
116
- | AgentReviewBatchDetails
117
- | AgentReviewProgressDetails
118
- | undefined;
119
- if (details?.kind === "review-progress") {
120
- return renderProgress(details, theme);
121
- }
122
- if (details?.kind !== "review-batch") return fallbackResult(result, theme);
123
-
124
- const container = new Container();
125
- const successCount = details.results.filter((entry) => entry.result.kind === "success").length;
126
- const verdictColor = details.evaluation.critique.verdict === "revise" ? "warning" : "success";
127
- container.addChild(
128
- new Text(
129
- `${theme.fg("success", "✓")} ${theme.fg("toolTitle", theme.bold("Review batch complete"))}${theme.fg("dim", ` · ${successCount}/${details.results.length} succeeded`)}`,
130
- 0,
131
- 0,
132
- ),
133
- );
134
- container.addChild(
135
- new Text(
136
- theme.fg(
137
- verdictColor,
138
- `Brief ${details.evaluation.critique.verdict}: ${details.evaluation.critique.summary}`,
139
- ),
140
- 0,
141
- 0,
142
- ),
143
- );
144
-
145
- for (const entry of details.results) {
146
- const status = summarizeResult(entry.result);
147
- container.addChild(
148
- new Text(
149
- `${theme.fg(status.color, status.icon)} ${entry.assignment.id}: ${status.text}`,
150
- 0,
151
- 0,
152
- ),
153
- );
154
- }
155
-
156
- if (expanded) {
157
- renderReviewerDiagnostics(container, details, theme);
158
- container.addChild(new Spacer(1));
159
- for (const line of formatCritique(details.evaluation.critique)) {
160
- container.addChild(new Text(theme.fg("dim", line), 0, 0));
161
- }
162
- if (details.evaluation.critique.verdict === "revise") {
163
- container.addChild(new Spacer(1));
164
- container.addChild(new Text(theme.fg("accent", "Effective revised brief"), 0, 0));
165
- for (const line of formatBrief(details.evaluation.effectiveBrief)) {
166
- container.addChild(new Text(theme.fg("dim", line), 0, 0));
167
- }
168
- }
169
- }
170
- return container;
171
- }
172
-
173
- function renderReviewerDiagnostics(
174
- container: Container,
175
- details: AgentReviewBatchDetails,
176
- theme: ReviewTheme,
177
- ): void {
178
- if (
179
- !details.results.some((entry) => entry.result.kind !== "success" && entry.result.diagnostics)
180
- ) {
181
- return;
182
- }
183
-
184
- container.addChild(new Spacer(1));
185
- container.addChild(new Text(theme.fg("accent", "Reviewer diagnostics"), 0, 0));
186
- for (const { assignment, result } of details.results) {
187
- if (result.kind === "success" || !result.diagnostics) continue;
188
- container.addChild(new Text(theme.fg("muted", `${assignment.id}:`), 0, 0));
189
- for (const line of formatChildFailureDiagnostics(result.diagnostics)) {
190
- container.addChild(new Text(theme.fg("dim", line), 0, 0));
191
- }
192
- }
193
- }
194
-
195
- function renderProgress(details: AgentReviewProgressDetails, theme: ReviewTheme): Text {
196
- if (details.phase === "prepare") {
197
- return new Text(theme.fg("warning", "Synthesizing review brief…"), 0, 0);
198
- }
199
- return new Text(
200
- theme.fg("warning", `Running reviewers… ${details.completed}/${details.total} completed`),
201
- 0,
202
- 0,
203
- );
204
- }
205
-
206
- function summarizeResult(result: AgentReviewBatchDetails["results"][number]["result"]): {
207
- icon: string;
208
- color: "success" | "warning" | "error";
209
- text: string;
210
- } {
211
- switch (result.kind) {
212
- case "success":
213
- return {
214
- icon: "✓",
215
- color: result.output.items.length > 0 ? "warning" : "success",
216
- text: `${result.output.items.length} item(s), ${result.output.overall_correctness}`,
217
- };
218
- case "failed":
219
- return {
220
- icon: "✗",
221
- color: "error",
222
- text: formatChildFailureCopy("reviewer", result.failureCode),
223
- };
224
- case "canceled":
225
- return { icon: "○", color: "warning", text: "canceled" };
226
- case "timeout":
227
- return { icon: "◷", color: "warning", text: "timed out" };
228
- }
229
- }
230
-
231
- function fallbackResult(result: ToolResultLike, theme: ReviewTheme): Text {
232
- const content = result.content.find((part) => part.type === "text")?.text ?? "No review output";
233
- return new Text(theme.fg("dim", content), 0, 0);
234
- }