@prowi/deskcheck 0.3.0 → 0.4.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 +78 -84
- package/build/cli.js +129 -23
- package/build/cli.js.map +1 -1
- package/build/config/loader.d.ts.map +1 -1
- package/build/config/loader.js +2 -1
- package/build/config/loader.js.map +1 -1
- package/build/config/types.d.ts +2 -1
- package/build/config/types.d.ts.map +1 -1
- package/build/mcp/tools.d.ts.map +1 -1
- package/build/mcp/tools.js +25 -49
- package/build/mcp/tools.js.map +1 -1
- package/build/prompts/ExecutorPrompt.d.ts +4 -2
- package/build/prompts/ExecutorPrompt.d.ts.map +1 -1
- package/build/prompts/ExecutorPrompt.js +40 -33
- package/build/prompts/ExecutorPrompt.js.map +1 -1
- package/build/prompts/PartitionerPrompt.d.ts +12 -0
- package/build/prompts/PartitionerPrompt.d.ts.map +1 -0
- package/build/prompts/PartitionerPrompt.js +54 -0
- package/build/prompts/PartitionerPrompt.js.map +1 -0
- package/build/prompts/ResolverPrompt.d.ts +11 -0
- package/build/prompts/ResolverPrompt.d.ts.map +1 -0
- package/build/prompts/ResolverPrompt.js +45 -0
- package/build/prompts/ResolverPrompt.js.map +1 -0
- package/build/renderers/review/MarkdownRenderer.js +5 -2
- package/build/renderers/review/MarkdownRenderer.js.map +1 -1
- package/build/renderers/review/TerminalRenderer.js +5 -2
- package/build/renderers/review/TerminalRenderer.js.map +1 -1
- package/build/renderers/review/WatchRenderer.d.ts.map +1 -1
- package/build/renderers/review/WatchRenderer.js +10 -1
- package/build/renderers/review/WatchRenderer.js.map +1 -1
- package/build/server/controllers/ReviewController.d.ts +12 -3
- package/build/server/controllers/ReviewController.d.ts.map +1 -1
- package/build/server/controllers/ReviewController.js +50 -6
- package/build/server/controllers/ReviewController.js.map +1 -1
- package/build/server/server.d.ts.map +1 -1
- package/build/server/server.js +22 -1
- package/build/server/server.js.map +1 -1
- package/build/services/ExecutorService.d.ts +17 -2
- package/build/services/ExecutorService.d.ts.map +1 -1
- package/build/services/ExecutorService.js +37 -5
- package/build/services/ExecutorService.js.map +1 -1
- package/build/services/FindingsParserService.d.ts +1 -8
- package/build/services/FindingsParserService.d.ts.map +1 -1
- package/build/services/FindingsParserService.js +20 -45
- package/build/services/FindingsParserService.js.map +1 -1
- package/build/services/criteria/module-parser.d.ts +1 -1
- package/build/services/criteria/module-parser.d.ts.map +1 -1
- package/build/services/criteria/module-parser.js +20 -16
- package/build/services/criteria/module-parser.js.map +1 -1
- package/build/services/review/CodeSnippetService.d.ts +10 -0
- package/build/services/review/CodeSnippetService.d.ts.map +1 -0
- package/build/services/review/CodeSnippetService.js +54 -0
- package/build/services/review/CodeSnippetService.js.map +1 -0
- package/build/services/review/ReviewInputResolverService.d.ts +25 -0
- package/build/services/review/ReviewInputResolverService.d.ts.map +1 -0
- package/build/services/review/ReviewInputResolverService.js +106 -0
- package/build/services/review/ReviewInputResolverService.js.map +1 -0
- package/build/services/review/ReviewOrchestratorService.d.ts.map +1 -1
- package/build/services/review/ReviewOrchestratorService.js +21 -20
- package/build/services/review/ReviewOrchestratorService.js.map +1 -1
- package/build/services/review/ReviewPartitionerService.d.ts +46 -0
- package/build/services/review/ReviewPartitionerService.d.ts.map +1 -0
- package/build/services/review/ReviewPartitionerService.js +208 -0
- package/build/services/review/ReviewPartitionerService.js.map +1 -0
- package/build/services/review/ReviewPlanBuilderService.d.ts +25 -7
- package/build/services/review/ReviewPlanBuilderService.d.ts.map +1 -1
- package/build/services/review/ReviewPlanBuilderService.js +88 -30
- package/build/services/review/ReviewPlanBuilderService.js.map +1 -1
- package/build/services/review/ReviewStorageService.d.ts +34 -10
- package/build/services/review/ReviewStorageService.d.ts.map +1 -1
- package/build/services/review/ReviewStorageService.js +100 -14
- package/build/services/review/ReviewStorageService.js.map +1 -1
- package/build/services/testing/TestRunnerService.d.ts.map +1 -1
- package/build/services/testing/TestRunnerService.js +10 -8
- package/build/services/testing/TestRunnerService.js.map +1 -1
- package/build/types/criteria.d.ts +8 -6
- package/build/types/criteria.d.ts.map +1 -1
- package/build/types/review.d.ts +123 -28
- package/build/types/review.d.ts.map +1 -1
- package/package.json +3 -1
- package/ui/dist/index.html +12 -63
- package/build/prompts/PlannerPrompt.d.ts +0 -12
- package/build/prompts/PlannerPrompt.d.ts.map +0 -1
- package/build/prompts/PlannerPrompt.js +0 -34
- package/build/prompts/PlannerPrompt.js.map +0 -1
- package/build/services/review/ReviewContextExtractorService.d.ts +0 -17
- package/build/services/review/ReviewContextExtractorService.d.ts.map +0 -1
- package/build/services/review/ReviewContextExtractorService.js +0 -69
- package/build/services/review/ReviewContextExtractorService.js.map +0 -1
- package/build/services/review/ReviewPlannerService.d.ts +0 -29
- package/build/services/review/ReviewPlannerService.d.ts.map +0 -1
- package/build/services/review/ReviewPlannerService.js +0 -122
- package/build/services/review/ReviewPlannerService.js.map +0 -1
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { query, createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { buildPartitionerPrompt } from "../../prompts/PartitionerPrompt.js";
|
|
4
|
+
// =============================================================================
|
|
5
|
+
// Errors
|
|
6
|
+
// =============================================================================
|
|
7
|
+
/** Thrown when the partitioner agent fails or produces invalid output. */
|
|
8
|
+
export class PartitionerError extends Error {
|
|
9
|
+
/** The criterion id this failure was scoped to. */
|
|
10
|
+
reviewId;
|
|
11
|
+
constructor(reviewId, message) {
|
|
12
|
+
super(`Partitioner failed for criterion "${reviewId}": ${message}`);
|
|
13
|
+
this.name = "PartitionerError";
|
|
14
|
+
this.reviewId = reviewId;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
// =============================================================================
|
|
18
|
+
// ReviewPartitionerService
|
|
19
|
+
// =============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Spawns one fresh Claude agent per criterion to decide how to split the
|
|
22
|
+
* matched files into reviewer subtasks. The agent reads the criterion's
|
|
23
|
+
* `partition` instruction (natural language) and uses built-in tools
|
|
24
|
+
* (Read, Grep, Glob, Bash) to inspect files when grouping requires it.
|
|
25
|
+
*
|
|
26
|
+
* Output is delivered via an in-process MCP tool `submit_partition`. If the
|
|
27
|
+
* agent never calls the tool, or calls it with invalid output (e.g. drops a
|
|
28
|
+
* file), this service throws — partitioner failures fail the whole run.
|
|
29
|
+
*/
|
|
30
|
+
export class ReviewPartitionerService {
|
|
31
|
+
config;
|
|
32
|
+
projectRoot;
|
|
33
|
+
constructor(config, projectRoot) {
|
|
34
|
+
this.config = config;
|
|
35
|
+
this.projectRoot = projectRoot;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Run the partitioner for one criterion. Returns the validated partition
|
|
39
|
+
* result, or throws on failure.
|
|
40
|
+
*/
|
|
41
|
+
async partition(criterion, matchedFiles, scope) {
|
|
42
|
+
if (matchedFiles.length === 0) {
|
|
43
|
+
throw new PartitionerError(criterion.id, "matchedFiles is empty");
|
|
44
|
+
}
|
|
45
|
+
let captured = null;
|
|
46
|
+
let captureError = null;
|
|
47
|
+
const inputFileSet = new Set(matchedFiles);
|
|
48
|
+
// In-process MCP tool the partitioner agent calls to deliver its output.
|
|
49
|
+
const partitionerServer = createSdkMcpServer({
|
|
50
|
+
name: "deskcheck-partitioner",
|
|
51
|
+
version: "0.1.0",
|
|
52
|
+
tools: [
|
|
53
|
+
tool("submit_partition", "Submit the final partition for this criterion. Call exactly once.", {
|
|
54
|
+
reasoning: z
|
|
55
|
+
.string()
|
|
56
|
+
.describe("Short overall explanation of how you split the files."),
|
|
57
|
+
subtasks: z
|
|
58
|
+
.array(z.object({
|
|
59
|
+
files: z
|
|
60
|
+
.array(z.string())
|
|
61
|
+
.describe("Files assigned to this subtask. At least one."),
|
|
62
|
+
focus: z
|
|
63
|
+
.string()
|
|
64
|
+
.nullable()
|
|
65
|
+
.optional()
|
|
66
|
+
.describe("Optional sub-file narrowing (method name, class name, region). Null if the whole file is the unit."),
|
|
67
|
+
hint: z
|
|
68
|
+
.string()
|
|
69
|
+
.nullable()
|
|
70
|
+
.optional()
|
|
71
|
+
.describe("One short sentence explaining why these files belong together."),
|
|
72
|
+
}))
|
|
73
|
+
.min(1)
|
|
74
|
+
.describe("Non-empty list of subtasks."),
|
|
75
|
+
}, async (args) => {
|
|
76
|
+
// Validate locally so we can return a useful error to the agent
|
|
77
|
+
// (and abort with a clear message if it never recovers).
|
|
78
|
+
const normalized = args.subtasks.map((s) => ({
|
|
79
|
+
files: s.files,
|
|
80
|
+
focus: s.focus ?? null,
|
|
81
|
+
hint: s.hint ?? null,
|
|
82
|
+
}));
|
|
83
|
+
const validationError = validatePartition(normalized, inputFileSet);
|
|
84
|
+
if (validationError) {
|
|
85
|
+
captureError = validationError;
|
|
86
|
+
return {
|
|
87
|
+
content: [{
|
|
88
|
+
type: "text",
|
|
89
|
+
text: `Error: ${validationError}. Please call submit_partition again with a corrected partition.`,
|
|
90
|
+
}],
|
|
91
|
+
isError: true,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
captured = { reasoning: args.reasoning, subtasks: normalized };
|
|
95
|
+
captureError = null;
|
|
96
|
+
return {
|
|
97
|
+
content: [{
|
|
98
|
+
type: "text",
|
|
99
|
+
text: `Accepted: ${normalized.length} subtask(s).`,
|
|
100
|
+
}],
|
|
101
|
+
};
|
|
102
|
+
}),
|
|
103
|
+
],
|
|
104
|
+
});
|
|
105
|
+
const partitionerModel = this.config.agents.partitioner.model ?? "haiku";
|
|
106
|
+
const systemPrompt = buildPartitionerPrompt(criterion, matchedFiles, scope);
|
|
107
|
+
const abortController = new AbortController();
|
|
108
|
+
const timeout = setTimeout(() => abortController.abort(), 5 * 60 * 1000);
|
|
109
|
+
let usage = null;
|
|
110
|
+
const messages = [];
|
|
111
|
+
try {
|
|
112
|
+
for await (const message of query({
|
|
113
|
+
prompt: `Partition the files for criterion ${criterion.id}.`,
|
|
114
|
+
options: {
|
|
115
|
+
model: partitionerModel,
|
|
116
|
+
systemPrompt,
|
|
117
|
+
tools: [
|
|
118
|
+
"Read",
|
|
119
|
+
"Grep",
|
|
120
|
+
"Glob",
|
|
121
|
+
"Bash",
|
|
122
|
+
"mcp__deskcheck-partitioner__*",
|
|
123
|
+
],
|
|
124
|
+
permissionMode: "bypassPermissions",
|
|
125
|
+
maxTurns: 15,
|
|
126
|
+
cwd: this.projectRoot,
|
|
127
|
+
persistSession: false,
|
|
128
|
+
abortController,
|
|
129
|
+
mcpServers: {
|
|
130
|
+
"deskcheck-partitioner": partitionerServer,
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
})) {
|
|
134
|
+
messages.push(message);
|
|
135
|
+
if (message.type === "result") {
|
|
136
|
+
const msg = message;
|
|
137
|
+
const u = msg.usage;
|
|
138
|
+
usage = {
|
|
139
|
+
input_tokens: u?.input_tokens ?? 0,
|
|
140
|
+
output_tokens: u?.output_tokens ?? 0,
|
|
141
|
+
cache_read_tokens: u?.cache_read_input_tokens ?? 0,
|
|
142
|
+
cache_creation_tokens: u?.cache_creation_input_tokens ?? 0,
|
|
143
|
+
cost_usd: msg.total_cost_usd ?? 0,
|
|
144
|
+
duration_ms: msg.duration_ms ?? 0,
|
|
145
|
+
duration_api_ms: msg.duration_api_ms ?? 0,
|
|
146
|
+
num_turns: msg.num_turns ?? 0,
|
|
147
|
+
model: partitionerModel,
|
|
148
|
+
};
|
|
149
|
+
if (message.subtype !== "success") {
|
|
150
|
+
throw new PartitionerError(criterion.id, `agent ended with subtype "${message.subtype}"`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
clearTimeout(timeout);
|
|
157
|
+
}
|
|
158
|
+
// TS narrows `captured` to `never` because all assignments happen inside
|
|
159
|
+
// the MCP tool handler closure — control-flow analysis doesn't follow
|
|
160
|
+
// those. Cast through unknown to read the runtime value.
|
|
161
|
+
const finalCaptured = captured;
|
|
162
|
+
if (!finalCaptured) {
|
|
163
|
+
const detail = captureError
|
|
164
|
+
? `agent never produced a valid partition. Last validation error: ${captureError}`
|
|
165
|
+
: "agent did not call submit_partition";
|
|
166
|
+
throw new PartitionerError(criterion.id, detail);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
reasoning: finalCaptured.reasoning,
|
|
170
|
+
subtasks: finalCaptured.subtasks,
|
|
171
|
+
model: partitionerModel,
|
|
172
|
+
usage,
|
|
173
|
+
messages,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// =============================================================================
|
|
178
|
+
// Validation
|
|
179
|
+
// =============================================================================
|
|
180
|
+
/**
|
|
181
|
+
* Verify a candidate partition covers every input file at least once and
|
|
182
|
+
* has well-formed subtasks. Returns a human-readable error string or null
|
|
183
|
+
* if the partition is valid.
|
|
184
|
+
*/
|
|
185
|
+
export function validatePartition(subtasks, inputFiles) {
|
|
186
|
+
if (subtasks.length === 0) {
|
|
187
|
+
return "subtasks must be non-empty";
|
|
188
|
+
}
|
|
189
|
+
const seen = new Set();
|
|
190
|
+
for (let i = 0; i < subtasks.length; i++) {
|
|
191
|
+
const sub = subtasks[i];
|
|
192
|
+
if (!Array.isArray(sub.files) || sub.files.length === 0) {
|
|
193
|
+
return `subtask ${i} has no files`;
|
|
194
|
+
}
|
|
195
|
+
for (const file of sub.files) {
|
|
196
|
+
if (!inputFiles.has(file)) {
|
|
197
|
+
return `subtask ${i} references file "${file}" which is not in the input list`;
|
|
198
|
+
}
|
|
199
|
+
seen.add(file);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const missing = [...inputFiles].filter((f) => !seen.has(f));
|
|
203
|
+
if (missing.length > 0) {
|
|
204
|
+
return `${missing.length} input file(s) missing from partition: ${missing.slice(0, 5).join(", ")}${missing.length > 5 ? "…" : ""}`;
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
//# sourceMappingURL=ReviewPartitionerService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReviewPartitionerService.js","sourceRoot":"","sources":["../../../src/services/review/ReviewPartitionerService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,31 @@
|
|
|
1
1
|
import { ReviewStorageService } from "./ReviewStorageService.js";
|
|
2
|
+
import { ReviewPartitionerService } from "./ReviewPartitionerService.js";
|
|
2
3
|
import type { ReviewModule } from "../../types/criteria.js";
|
|
3
|
-
import type { ReviewPlan,
|
|
4
|
+
import type { PartitionDecision, PlanInvocation, ReviewPlan, Scope } from "../../types/review.js";
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* Hooks called as the plan builder progresses through its steps. Used by
|
|
7
|
+
* the CLI to print live status. Optional.
|
|
8
|
+
*/
|
|
9
|
+
export interface PartitionProgressEvents {
|
|
10
|
+
/** Fires once after glob matching, before partitioning starts. */
|
|
11
|
+
onMatchingComplete?: (matchedCriteria: number, matchedFiles: number) => void;
|
|
12
|
+
/** Fires when each per-criterion partitioner starts. */
|
|
13
|
+
onPartitionStarted?: (reviewId: string, fileCount: number) => void;
|
|
14
|
+
/** Fires when each per-criterion partitioner finishes successfully. */
|
|
15
|
+
onPartitionCompleted?: (decision: PartitionDecision) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build a complete review plan: create the plan, glob-match files to
|
|
19
|
+
* criteria, run one partitioner agent per matched criterion to produce
|
|
20
|
+
* subtasks, write everything to storage, and finalize.
|
|
21
|
+
*
|
|
22
|
+
* Partitioners run concurrently with `Promise.all`. ALL partitioners must
|
|
23
|
+
* complete before any tasks are added — this is a deliberate barrier so
|
|
24
|
+
* that downstream reviewers see a fully-partitioned plan and so that the
|
|
25
|
+
* partitioning step can be inspected as a unit (e.g. via `--dry-run`).
|
|
7
26
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* entry point that needs to create a plan from a file list.
|
|
27
|
+
* If any partitioner throws, the error propagates and the plan is left in
|
|
28
|
+
* its pre-finalized state. Per design, partitioner failures fail the run.
|
|
11
29
|
*/
|
|
12
|
-
export declare function buildPlanWithTasks(storage: ReviewStorageService, name: string,
|
|
30
|
+
export declare function buildPlanWithTasks(storage: ReviewStorageService, partitioner: ReviewPartitionerService, name: string, scope: Scope, invocation: PlanInvocation, files: string[], modules: ReviewModule[], events?: PartitionProgressEvents): Promise<ReviewPlan>;
|
|
13
31
|
//# sourceMappingURL=ReviewPlanBuilderService.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReviewPlanBuilderService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewPlanBuilderService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAEV,UAAU,EACV,
|
|
1
|
+
{"version":3,"file":"ReviewPlanBuilderService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewPlanBuilderService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,wBAAwB,EAAoB,MAAM,+BAA+B,CAAC;AAC3F,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAEV,iBAAiB,EACjB,cAAc,EACd,UAAU,EACV,KAAK,EACN,MAAM,uBAAuB,CAAC;AAE/B;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACtC,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7E,wDAAwD;IACxD,kBAAkB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACnE,uEAAuE;IACvE,oBAAoB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAC9D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,oBAAoB,EAC7B,WAAW,EAAE,wBAAwB,EACrC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,KAAK,EACZ,UAAU,EAAE,cAAc,EAC1B,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,YAAY,EAAE,EACvB,MAAM,CAAC,EAAE,uBAAuB,GAC/B,OAAO,CAAC,UAAU,CAAC,CA8HrB"}
|
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
import { findMatchingModules } from "../criteria/glob-matcher.js";
|
|
2
|
+
import { PartitionerError } from "./ReviewPartitionerService.js";
|
|
2
3
|
/**
|
|
3
|
-
* Build a complete review plan: create the plan, match files to
|
|
4
|
-
*
|
|
4
|
+
* Build a complete review plan: create the plan, glob-match files to
|
|
5
|
+
* criteria, run one partitioner agent per matched criterion to produce
|
|
6
|
+
* subtasks, write everything to storage, and finalize.
|
|
5
7
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
8
|
+
* Partitioners run concurrently with `Promise.all`. ALL partitioners must
|
|
9
|
+
* complete before any tasks are added — this is a deliberate barrier so
|
|
10
|
+
* that downstream reviewers see a fully-partitioned plan and so that the
|
|
11
|
+
* partitioning step can be inspected as a unit (e.g. via `--dry-run`).
|
|
12
|
+
*
|
|
13
|
+
* If any partitioner throws, the error propagates and the plan is left in
|
|
14
|
+
* its pre-finalized state. Per design, partitioner failures fail the run.
|
|
9
15
|
*/
|
|
10
|
-
export function buildPlanWithTasks(storage, name,
|
|
11
|
-
// Create the plan shell
|
|
12
|
-
const plan = storage.createPlan(name,
|
|
13
|
-
// Match files against criteria
|
|
16
|
+
export async function buildPlanWithTasks(storage, partitioner, name, scope, invocation, files, modules, events) {
|
|
17
|
+
// Create the plan shell — already at step "matching" by default.
|
|
18
|
+
const plan = storage.createPlan(name, scope, invocation);
|
|
19
|
+
// Match files against criteria (programmatic, no LLM)
|
|
14
20
|
const matches = findMatchingModules(files, modules);
|
|
21
|
+
events?.onMatchingComplete?.(matches.length, new Set(matches.flatMap((m) => m.matchedFiles)).size);
|
|
15
22
|
// Track coverage
|
|
16
23
|
const matchedFileSet = new Set();
|
|
17
24
|
for (const match of matches) {
|
|
@@ -28,39 +35,90 @@ export function buildPlanWithTasks(storage, name, source, files, modules) {
|
|
|
28
35
|
moduleSummaries[match.module.id] = {
|
|
29
36
|
review_id: match.module.id,
|
|
30
37
|
description: match.module.description,
|
|
31
|
-
severity: match.module.severity,
|
|
32
38
|
model: match.module.model,
|
|
39
|
+
partition: match.module.partition,
|
|
33
40
|
task_count: 0,
|
|
34
41
|
matched_files: match.matchedFiles,
|
|
35
42
|
};
|
|
36
43
|
}
|
|
37
44
|
storage.setModules(plan.plan_id, moduleSummaries);
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Partition step — one fresh agent per matched criterion, all in parallel.
|
|
47
|
+
// Must complete entirely before any tasks are added. If anything throws,
|
|
48
|
+
// we stamp the failure on the plan so the UI can render it before
|
|
49
|
+
// re-raising for the CLI to surface.
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
storage.setStep(plan.plan_id, "partitioning");
|
|
52
|
+
let decisions;
|
|
53
|
+
try {
|
|
54
|
+
decisions = await Promise.all(matches.map(async (match) => {
|
|
55
|
+
events?.onPartitionStarted?.(match.module.id, match.matchedFiles.length);
|
|
56
|
+
const result = await partitioner.partition(match.module, match.matchedFiles, scope);
|
|
57
|
+
// Persist the partitioner's full SDK transcript as a side-file.
|
|
58
|
+
try {
|
|
59
|
+
storage.writePartitionerLog(plan.plan_id, match.module.id, result.messages);
|
|
60
|
+
}
|
|
61
|
+
catch (logErr) {
|
|
62
|
+
console.error(`[deskcheck] Warning: failed to write partitioner log for ${match.module.id}: ${logErr instanceof Error ? logErr.message : String(logErr)}`);
|
|
63
|
+
}
|
|
64
|
+
const decision = {
|
|
65
|
+
review_id: match.module.id,
|
|
66
|
+
matched_files: match.matchedFiles,
|
|
67
|
+
reasoning: result.reasoning,
|
|
68
|
+
subtasks: result.subtasks,
|
|
69
|
+
completed_at: new Date().toISOString(),
|
|
70
|
+
model: result.model,
|
|
71
|
+
usage: result.usage,
|
|
72
|
+
};
|
|
73
|
+
storage.setPartitionDecision(plan.plan_id, decision);
|
|
74
|
+
events?.onPartitionCompleted?.(decision);
|
|
75
|
+
return decision;
|
|
76
|
+
}));
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
80
|
+
const reviewId = err instanceof PartitionerError ? err.reviewId : null;
|
|
81
|
+
storage.setFailure(plan.plan_id, {
|
|
82
|
+
step: "partitioning",
|
|
83
|
+
review_id: reviewId,
|
|
84
|
+
message,
|
|
85
|
+
});
|
|
86
|
+
throw err;
|
|
87
|
+
}
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
// Materialize partitioner output as ReviewTasks. We do this after all
|
|
90
|
+
// partitioners finish so storage writes are batched and the plan is never
|
|
91
|
+
// half-partitioned on disk.
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
for (let i = 0; i < matches.length; i++) {
|
|
94
|
+
const match = matches[i];
|
|
95
|
+
const decision = decisions[i];
|
|
96
|
+
for (const subtask of decision.subtasks) {
|
|
43
97
|
storage.addTask(plan.plan_id, {
|
|
44
98
|
review_id: match.module.id,
|
|
45
99
|
review_file: match.module.file,
|
|
46
|
-
files:
|
|
47
|
-
|
|
100
|
+
files: subtask.files,
|
|
101
|
+
focus: subtask.focus,
|
|
102
|
+
hint: subtask.hint,
|
|
48
103
|
model: match.module.model,
|
|
104
|
+
tools: match.module.tools,
|
|
105
|
+
prompt: match.module.prompt,
|
|
49
106
|
});
|
|
50
107
|
}
|
|
51
|
-
else {
|
|
52
|
-
for (const file of match.matchedFiles) {
|
|
53
|
-
storage.addTask(plan.plan_id, {
|
|
54
|
-
review_id: match.module.id,
|
|
55
|
-
review_file: match.module.file,
|
|
56
|
-
files: [file],
|
|
57
|
-
hint: null,
|
|
58
|
-
model: match.module.model,
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
108
|
}
|
|
63
|
-
// Finalize the plan (sets status to "ready", recounts tasks per module)
|
|
64
|
-
|
|
109
|
+
// Finalize the plan (sets status to "ready", recounts tasks per module).
|
|
110
|
+
// After finalize, the orchestrator takes over — it flips step to "complete"
|
|
111
|
+
// when all tasks reach a terminal state. We set "reviewing" here as the
|
|
112
|
+
// intermediate so the UI sees the transition immediately on plan load.
|
|
113
|
+
const finalized = storage.finalizePlan(plan.plan_id);
|
|
114
|
+
if (Object.keys(finalized.tasks).length > 0) {
|
|
115
|
+
storage.setStep(plan.plan_id, "reviewing");
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
// No tasks (no criteria matched, or all partitioners produced empty
|
|
119
|
+
// sets — though the validator forbids the latter). Mark complete.
|
|
120
|
+
storage.setStep(plan.plan_id, "complete");
|
|
121
|
+
}
|
|
122
|
+
return storage.getPlan(plan.plan_id);
|
|
65
123
|
}
|
|
66
124
|
//# sourceMappingURL=ReviewPlanBuilderService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReviewPlanBuilderService.js","sourceRoot":"","sources":["../../../src/services/review/ReviewPlanBuilderService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"ReviewPlanBuilderService.js","sourceRoot":"","sources":["../../../src/services/review/ReviewPlanBuilderService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Issue, ModuleSummary, PartitionDecision, PipelineStep, PlanFailure, PlanInvocation, ReviewPlan, ReviewResults, ReviewTask, Scope, TaskUsage } from "../../types/review.js";
|
|
2
2
|
/**
|
|
3
3
|
* Manages the two-file storage format (plan.json + results.json) for deskcheck runs.
|
|
4
4
|
*
|
|
@@ -29,7 +29,7 @@ export declare class ReviewStorageService {
|
|
|
29
29
|
* Creates the timestamped directory and writes an initial plan.json with
|
|
30
30
|
* status "planning" and empty collections.
|
|
31
31
|
*/
|
|
32
|
-
createPlan(name: string,
|
|
32
|
+
createPlan(name: string, scope: Scope, invocation: PlanInvocation): ReviewPlan;
|
|
33
33
|
/** Read the plan.json for a given plan ID. */
|
|
34
34
|
getPlan(planId: string): ReviewPlan;
|
|
35
35
|
/**
|
|
@@ -56,18 +56,42 @@ export declare class ReviewStorageService {
|
|
|
56
56
|
* appending a zero-padded incrementing suffix (e.g., "-001", "-002").
|
|
57
57
|
* The task is created with status "pending" and null context fields.
|
|
58
58
|
*/
|
|
59
|
-
addTask(planId: string, task: Omit<ReviewTask, "task_id" | "status" | "created_at" | "started_at" | "completed_at" | "
|
|
59
|
+
addTask(planId: string, task: Omit<ReviewTask, "task_id" | "status" | "created_at" | "started_at" | "completed_at" | "scope" | "focus" | "tools" | "error" | "prompt"> & {
|
|
60
|
+
focus?: string | null;
|
|
61
|
+
tools?: string[];
|
|
62
|
+
prompt?: string | null;
|
|
63
|
+
}): ReviewTask;
|
|
64
|
+
/** Record a partitioner decision for one criterion. */
|
|
65
|
+
setPartitionDecision(planId: string, decision: PartitionDecision): void;
|
|
66
|
+
/**
|
|
67
|
+
* Update the pipeline step the plan is currently in. When transitioning
|
|
68
|
+
* to a terminal step (`complete`/`failed`), also promotes `status` to the
|
|
69
|
+
* matching terminal value and stamps `completed_at` if not already set —
|
|
70
|
+
* this keeps the invariant `step terminal ⟺ status terminal`.
|
|
71
|
+
*/
|
|
72
|
+
setStep(planId: string, step: PipelineStep): void;
|
|
73
|
+
/**
|
|
74
|
+
* Mark the plan as failed at a specific step. Sets `status = "failed"`,
|
|
75
|
+
* `step = "failed"`, and stamps the failure details. Idempotent — if the
|
|
76
|
+
* plan is already failed, the new failure overwrites the old.
|
|
77
|
+
*/
|
|
78
|
+
setFailure(planId: string, failure: PlanFailure): void;
|
|
79
|
+
/** Persist the full SDK message stream from one reviewer's run. */
|
|
80
|
+
writeTaskLog(planId: string, taskId: string, messages: unknown[]): void;
|
|
81
|
+
/** Read a previously persisted reviewer transcript. */
|
|
82
|
+
getTaskLog(planId: string, taskId: string): unknown[];
|
|
83
|
+
/** Persist the full SDK message stream from one partitioner's run. */
|
|
84
|
+
writePartitionerLog(planId: string, reviewId: string, messages: unknown[]): void;
|
|
85
|
+
/** Read a previously persisted partitioner transcript. */
|
|
86
|
+
getPartitionerLog(planId: string, reviewId: string): unknown[];
|
|
60
87
|
/**
|
|
61
88
|
* Claim a pending task for execution.
|
|
62
89
|
*
|
|
63
|
-
* Sets the task status to "in_progress",
|
|
64
|
-
*
|
|
90
|
+
* Sets the task status to "in_progress", records the start time, and
|
|
91
|
+
* optionally stores the criterion prompt for later inspection.
|
|
65
92
|
*/
|
|
66
|
-
claimTask(planId: string, taskId: string,
|
|
67
|
-
|
|
68
|
-
content: string;
|
|
69
|
-
symbol?: string;
|
|
70
|
-
prompt: string;
|
|
93
|
+
claimTask(planId: string, taskId: string, options?: {
|
|
94
|
+
prompt?: string;
|
|
71
95
|
}): ReviewTask;
|
|
72
96
|
/**
|
|
73
97
|
* Return tasks eligible for execution: those with status "pending" or
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReviewStorageService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewStorageService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,
|
|
1
|
+
{"version":3,"file":"ReviewStorageService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewStorageService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,KAAK,EAGL,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,cAAc,EACd,UAAU,EACV,aAAa,EACb,UAAU,EACV,KAAK,EAEL,SAAS,EAEV,MAAM,uBAAuB,CAAC;AAsC/B;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,+EAA+E;IAC/E,OAAO,CAAC,MAAM,CAAC,WAAW,CAAqB;gBAanC,UAAU,EAAE,MAAM;IAI9B;;;;;;;;OAQG;IACH,OAAO,CAAC,QAAQ;IAoDhB,yCAAyC;IACzC,OAAO,CAAC,OAAO;IAQf;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,cAAc,GAAG,UAAU;IA8B9E,8CAA8C;IAC9C,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;IAMnC;;;OAGG;IACH,eAAe,IAAI,MAAM,GAAG,IAAI;IAsBhC,0CAA0C;IAC1C,SAAS,IAAI,KAAK,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;IAqCF;;;OAGG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU;IAsBxC;;;;;;OAMG;IACH,OAAO,CACL,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,IAAI,CACR,UAAU,EACR,SAAS,GACT,QAAQ,GACR,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,OAAO,GACP,OAAO,GACP,OAAO,GACP,OAAO,GACP,QAAQ,CACX,GAAG;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GACtE,UAAU;IAmCb,uDAAuD;IACvD,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,iBAAiB,GAAG,IAAI;IAQvE;;;;;OAKG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI;IAejD;;;;OAIG;IACH,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,IAAI;IAoBtD,mEAAmE;IACnE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI;IAOvE,uDAAuD;IACvD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,EAAE;IAMrD,sEAAsE;IACtE,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI;IAUhF,0DAA0D;IAC1D,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE;IAS9D;;;;;OAKG;IACH,SAAS,CACP,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5B,UAAU;IA4Bb;;;OAGG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE;IAkB7C;;;;;;OAMG;IACH,YAAY,CACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,KAAK,EAAE,EACf,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GACvB,IAAI;IAkDP;;;;;;OAMG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAgD/F,iDAAiD;IACjD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa;IAgBzC,4DAA4D;IAC5D,eAAe,CACb,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EAAE,EACjB,SAAS,EAAE,MAAM,EAAE,GAClB,IAAI;IASP,gDAAgD;IAChD,UAAU,CACR,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,GACrC,IAAI;IAYP,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,kBAAkB;IAkC1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B;;;;;;;OAOG;IACH,OAAO,CAAC,qBAAqB;CAiI9B"}
|