@prowi/deskcheck 0.2.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.
Files changed (100) hide show
  1. package/README.md +78 -84
  2. package/build/cli.js +131 -25
  3. package/build/cli.js.map +1 -1
  4. package/build/config/loader.d.ts.map +1 -1
  5. package/build/config/loader.js +2 -1
  6. package/build/config/loader.js.map +1 -1
  7. package/build/config/types.d.ts +2 -1
  8. package/build/config/types.d.ts.map +1 -1
  9. package/build/mcp/tools.d.ts.map +1 -1
  10. package/build/mcp/tools.js +51 -65
  11. package/build/mcp/tools.js.map +1 -1
  12. package/build/prompts/ExecutorPrompt.d.ts +4 -2
  13. package/build/prompts/ExecutorPrompt.d.ts.map +1 -1
  14. package/build/prompts/ExecutorPrompt.js +72 -34
  15. package/build/prompts/ExecutorPrompt.js.map +1 -1
  16. package/build/prompts/PartitionerPrompt.d.ts +12 -0
  17. package/build/prompts/PartitionerPrompt.d.ts.map +1 -0
  18. package/build/prompts/PartitionerPrompt.js +54 -0
  19. package/build/prompts/PartitionerPrompt.js.map +1 -0
  20. package/build/prompts/ResolverPrompt.d.ts +11 -0
  21. package/build/prompts/ResolverPrompt.d.ts.map +1 -0
  22. package/build/prompts/ResolverPrompt.js +45 -0
  23. package/build/prompts/ResolverPrompt.js.map +1 -0
  24. package/build/renderers/review/MarkdownRenderer.d.ts.map +1 -1
  25. package/build/renderers/review/MarkdownRenderer.js +30 -11
  26. package/build/renderers/review/MarkdownRenderer.js.map +1 -1
  27. package/build/renderers/review/TerminalRenderer.d.ts.map +1 -1
  28. package/build/renderers/review/TerminalRenderer.js +38 -13
  29. package/build/renderers/review/TerminalRenderer.js.map +1 -1
  30. package/build/renderers/review/WatchRenderer.d.ts.map +1 -1
  31. package/build/renderers/review/WatchRenderer.js +12 -3
  32. package/build/renderers/review/WatchRenderer.js.map +1 -1
  33. package/build/renderers/shared.d.ts +11 -11
  34. package/build/renderers/shared.d.ts.map +1 -1
  35. package/build/renderers/shared.js +15 -15
  36. package/build/renderers/shared.js.map +1 -1
  37. package/build/server/controllers/ReviewController.d.ts +12 -3
  38. package/build/server/controllers/ReviewController.d.ts.map +1 -1
  39. package/build/server/controllers/ReviewController.js +50 -6
  40. package/build/server/controllers/ReviewController.js.map +1 -1
  41. package/build/server/server.d.ts.map +1 -1
  42. package/build/server/server.js +22 -1
  43. package/build/server/server.js.map +1 -1
  44. package/build/services/ExecutorService.d.ts +17 -2
  45. package/build/services/ExecutorService.d.ts.map +1 -1
  46. package/build/services/ExecutorService.js +37 -5
  47. package/build/services/ExecutorService.js.map +1 -1
  48. package/build/services/FindingsParserService.d.ts +7 -6
  49. package/build/services/FindingsParserService.d.ts.map +1 -1
  50. package/build/services/FindingsParserService.js +44 -14
  51. package/build/services/FindingsParserService.js.map +1 -1
  52. package/build/services/criteria/module-parser.d.ts +1 -1
  53. package/build/services/criteria/module-parser.d.ts.map +1 -1
  54. package/build/services/criteria/module-parser.js +20 -16
  55. package/build/services/criteria/module-parser.js.map +1 -1
  56. package/build/services/review/CodeSnippetService.d.ts +10 -0
  57. package/build/services/review/CodeSnippetService.d.ts.map +1 -0
  58. package/build/services/review/CodeSnippetService.js +54 -0
  59. package/build/services/review/CodeSnippetService.js.map +1 -0
  60. package/build/services/review/ReviewInputResolverService.d.ts +25 -0
  61. package/build/services/review/ReviewInputResolverService.d.ts.map +1 -0
  62. package/build/services/review/ReviewInputResolverService.js +106 -0
  63. package/build/services/review/ReviewInputResolverService.js.map +1 -0
  64. package/build/services/review/ReviewOrchestratorService.d.ts +2 -2
  65. package/build/services/review/ReviewOrchestratorService.d.ts.map +1 -1
  66. package/build/services/review/ReviewOrchestratorService.js +28 -27
  67. package/build/services/review/ReviewOrchestratorService.js.map +1 -1
  68. package/build/services/review/ReviewPartitionerService.d.ts +46 -0
  69. package/build/services/review/ReviewPartitionerService.d.ts.map +1 -0
  70. package/build/services/review/ReviewPartitionerService.js +208 -0
  71. package/build/services/review/ReviewPartitionerService.js.map +1 -0
  72. package/build/services/review/ReviewPlanBuilderService.d.ts +25 -7
  73. package/build/services/review/ReviewPlanBuilderService.d.ts.map +1 -1
  74. package/build/services/review/ReviewPlanBuilderService.js +88 -30
  75. package/build/services/review/ReviewPlanBuilderService.js.map +1 -1
  76. package/build/services/review/ReviewStorageService.d.ts +35 -11
  77. package/build/services/review/ReviewStorageService.d.ts.map +1 -1
  78. package/build/services/review/ReviewStorageService.js +136 -35
  79. package/build/services/review/ReviewStorageService.js.map +1 -1
  80. package/build/services/testing/TestRunnerService.d.ts.map +1 -1
  81. package/build/services/testing/TestRunnerService.js +10 -8
  82. package/build/services/testing/TestRunnerService.js.map +1 -1
  83. package/build/types/criteria.d.ts +8 -6
  84. package/build/types/criteria.d.ts.map +1 -1
  85. package/build/types/review.d.ts +173 -50
  86. package/build/types/review.d.ts.map +1 -1
  87. package/package.json +3 -1
  88. package/ui/dist/index.html +12 -63
  89. package/build/prompts/PlannerPrompt.d.ts +0 -12
  90. package/build/prompts/PlannerPrompt.d.ts.map +0 -1
  91. package/build/prompts/PlannerPrompt.js +0 -34
  92. package/build/prompts/PlannerPrompt.js.map +0 -1
  93. package/build/services/review/ReviewContextExtractorService.d.ts +0 -17
  94. package/build/services/review/ReviewContextExtractorService.d.ts.map +0 -1
  95. package/build/services/review/ReviewContextExtractorService.js +0 -69
  96. package/build/services/review/ReviewContextExtractorService.js.map +0 -1
  97. package/build/services/review/ReviewPlannerService.d.ts +0 -29
  98. package/build/services/review/ReviewPlannerService.d.ts.map +0 -1
  99. package/build/services/review/ReviewPlannerService.js +0 -122
  100. package/build/services/review/ReviewPlannerService.js.map +0 -1
@@ -0,0 +1,106 @@
1
+ import { query, createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
2
+ import { z } from "zod";
3
+ import { buildResolverPrompt } from "../../prompts/ResolverPrompt.js";
4
+ // =============================================================================
5
+ // ReviewInputResolverService
6
+ // =============================================================================
7
+ /**
8
+ * Translates a natural-language deskcheck request into `{ scope, files }` by
9
+ * running a fresh Claude agent that has filesystem/git tools and an
10
+ * in-process MCP `submit_resolution` tool. The resolver does NOT match
11
+ * criteria, partition, or review — those happen downstream identically to
12
+ * the deterministic `deskcheck diff` path.
13
+ *
14
+ * If the caller already supplied an explicit scope override (`--scope`),
15
+ * pass it via `scopeOverride`. The agent will then only resolve the file
16
+ * list; the override wins regardless of what the agent infers.
17
+ */
18
+ export class ReviewInputResolverService {
19
+ config;
20
+ projectRoot;
21
+ constructor(config, projectRoot) {
22
+ this.config = config;
23
+ this.projectRoot = projectRoot;
24
+ }
25
+ async resolve(input, scopeOverride) {
26
+ let captured = null;
27
+ const resolverServer = createSdkMcpServer({
28
+ name: "deskcheck-resolver",
29
+ version: "0.1.0",
30
+ tools: [
31
+ tool("submit_resolution", "Submit the resolved scope and file list. Call exactly once.", {
32
+ scope_type: z
33
+ .enum(["all", "changes"])
34
+ .describe("'all' to review full files, 'changes' to review only the diff against a git ref."),
35
+ scope_ref: z
36
+ .string()
37
+ .optional()
38
+ .describe("For scope_type='changes': the git ref to compare against (branch, commit, or HEAD). Ignored for 'all'."),
39
+ files: z
40
+ .array(z.string())
41
+ .describe("File paths to review. May be empty if no files match the request."),
42
+ }, async (args) => {
43
+ const inferredScope = args.scope_type === "changes"
44
+ ? { type: "changes", ref: args.scope_ref ?? "HEAD" }
45
+ : { type: "all" };
46
+ captured = {
47
+ scope: scopeOverride ?? inferredScope,
48
+ files: args.files,
49
+ };
50
+ return {
51
+ content: [{
52
+ type: "text",
53
+ text: `Accepted: ${args.files.length} file(s), scope=${JSON.stringify(captured.scope)}`,
54
+ }],
55
+ };
56
+ }),
57
+ ],
58
+ });
59
+ const resolverModel = this.config.agents.resolver.model ?? "haiku";
60
+ const systemPrompt = buildResolverPrompt() +
61
+ (scopeOverride
62
+ ? `\n\n## Scope override\n\nThe user has explicitly specified \`scope = ${JSON.stringify(scopeOverride)}\`. Do not override it. You only need to resolve the file list.`
63
+ : "");
64
+ const abortController = new AbortController();
65
+ const timeout = setTimeout(() => abortController.abort(), 5 * 60 * 1000);
66
+ try {
67
+ for await (const message of query({
68
+ prompt: input,
69
+ options: {
70
+ model: resolverModel,
71
+ systemPrompt,
72
+ tools: [
73
+ "Bash",
74
+ "Read",
75
+ "Glob",
76
+ "Grep",
77
+ "mcp__deskcheck-resolver__*",
78
+ ],
79
+ permissionMode: "bypassPermissions",
80
+ maxTurns: 15,
81
+ cwd: this.projectRoot,
82
+ persistSession: false,
83
+ abortController,
84
+ mcpServers: {
85
+ "deskcheck-resolver": resolverServer,
86
+ },
87
+ },
88
+ })) {
89
+ if (message.type === "result" && message.subtype !== "success") {
90
+ throw new Error(`Resolver agent failed: ${JSON.stringify(message)}`);
91
+ }
92
+ }
93
+ }
94
+ finally {
95
+ clearTimeout(timeout);
96
+ }
97
+ // Cast through unknown — see ReviewPartitionerService for why TS narrows
98
+ // closure-assigned vars to never.
99
+ const finalCaptured = captured;
100
+ if (!finalCaptured) {
101
+ throw new Error("Resolver agent did not call submit_resolution. The request may not have been understood.");
102
+ }
103
+ return finalCaptured;
104
+ }
105
+ }
106
+ //# sourceMappingURL=ReviewInputResolverService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReviewInputResolverService.js","sourceRoot":"","sources":["../../../src/services/review/ReviewInputResolverService.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,7 @@ export type OrchestratorEvent = {
12
12
  taskId: string;
13
13
  reviewId: string;
14
14
  files: string[];
15
- findingCount: number;
15
+ issueCount: number;
16
16
  usage: TaskUsage | null;
17
17
  } | {
18
18
  type: "task_error";
@@ -26,7 +26,7 @@ export type OrchestratorEvent = {
26
26
  total: number;
27
27
  } | {
28
28
  type: "complete";
29
- totalFindings: number;
29
+ totalIssues: number;
30
30
  };
31
31
  /**
32
32
  * Executes a review plan by dispatching tasks to executor agents via the
@@ -1 +1 @@
1
- {"version":3,"file":"ReviewOrchestratorService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewOrchestratorService.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAEV,SAAS,EACV,MAAM,uBAAuB,CAAC;AAM/B,sEAAsE;AACtE,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1F;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;CAAE,GAC5H;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxF;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC;AAMhD;;;;;;GAMG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;gBAEtC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM;IAMrD;;;;;;OAMG;IACI,OAAO,CACZ,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GACnC,cAAc,CAAC,iBAAiB,CAAC;CAwLrC"}
1
+ {"version":3,"file":"ReviewOrchestratorService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewOrchestratorService.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAEV,SAAS,EACV,MAAM,uBAAuB,CAAC;AAM/B,sEAAsE;AACtE,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,GAC1F;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;CAAE,GAC1H;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxF;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAM9C;;;;;;GAMG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAkB;gBAEtC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM;IAMrD;;;;;;OAMG;IACI,OAAO,CACZ,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GACnC,cAAc,CAAC,iBAAiB,CAAC;CAkLrC"}
@@ -1,9 +1,9 @@
1
1
  import path from "node:path";
2
2
  import { ReviewStorageService } from "./ReviewStorageService.js";
3
- import { extractContext } from "./ReviewContextExtractorService.js";
4
3
  import { buildExecutorPrompt } from "../../prompts/ExecutorPrompt.js";
5
- import { parseFindings } from "../FindingsParserService.js";
4
+ import { parseIssues } from "../FindingsParserService.js";
6
5
  import { ExecutorService } from "../ExecutorService.js";
6
+ import { resolveCodeSnippets } from "./CodeSnippetService.js";
7
7
  // =============================================================================
8
8
  // ReviewOrchestratorService
9
9
  // =============================================================================
@@ -37,11 +37,11 @@ export class ReviewOrchestratorService {
37
37
  const plan = storage.getPlan(planId);
38
38
  const pendingTasks = storage.getPendingTasks(planId);
39
39
  if (pendingTasks.length === 0) {
40
- yield { type: "complete", totalFindings: 0 };
40
+ yield { type: "complete", totalIssues: 0 };
41
41
  return;
42
42
  }
43
43
  let completedCount = 0;
44
- let totalFindings = 0;
44
+ let totalIssues = 0;
45
45
  const total = pendingTasks.length;
46
46
  // Event queue: executor promises push events here, generator yields them
47
47
  const eventQueue = [];
@@ -65,37 +65,38 @@ export class ReviewOrchestratorService {
65
65
  });
66
66
  let taskUsage = null;
67
67
  try {
68
- // Extract context and claim the task
69
- const extracted = extractContext(plan.source.type, plan.source.target, task.files, this.projectRoot, task.symbol ?? undefined);
70
- // Read the criterion prompt from the module file
71
- const modulePrompt = task.prompt ?? plan.modules[task.review_id]?.description ?? "";
72
- // Claim the task in storage (sets status to in_progress, fills context)
73
- storage.claimTask(planId, task.task_id, {
74
- contextType: extracted.contextType,
75
- content: extracted.content,
76
- symbol: extracted.symbol ?? undefined,
77
- prompt: modulePrompt,
78
- });
79
- // Re-read the task with filled context for prompt building
80
- const claimedPlan = storage.getPlan(planId);
81
- const claimedTask = claimedPlan.tasks[task.task_id];
82
- // Build the executor prompt
68
+ // The criterion prompt was stamped onto the task at addTask time;
69
+ // claimTask only flips status to in_progress and records started_at.
70
+ const claimedTask = storage.claimTask(planId, task.task_id);
71
+ // Build the executor prompt reviewer fetches its own context via tools.
83
72
  const executorPrompt = buildExecutorPrompt(claimedTask);
84
- // Spawn executor agent via ExecutorService
85
- const result = await this.executorService.execute(executorPrompt, modelId);
73
+ // Spawn executor agent via ExecutorService. Per-criterion tools
74
+ // (from the criterion's frontmatter) are layered on top of built-ins
75
+ // and config tools via `extraTools`.
76
+ const result = await this.executorService.execute(executorPrompt, modelId, {
77
+ extraTools: claimedTask.tools,
78
+ });
86
79
  taskUsage = result.usage;
87
- // Parse findings from executor output
88
- const findings = parseFindings(result.resultText);
80
+ // Persist the full SDK message stream as a side-file for inspection.
81
+ try {
82
+ storage.writeTaskLog(planId, task.task_id, result.messages);
83
+ }
84
+ catch (logErr) {
85
+ // Don't fail the task if transcript persistence fails — log and move on.
86
+ console.error(`[deskcheck] Warning: failed to write task log for ${task.task_id}: ${logErr instanceof Error ? logErr.message : String(logErr)}`);
87
+ }
88
+ // Parse issues from executor output and resolve code snippets from disk
89
+ const issues = resolveCodeSnippets(parseIssues(result.resultText), this.projectRoot);
89
90
  // Complete the task in storage
90
- storage.completeTask(planId, task.task_id, findings, taskUsage);
91
+ storage.completeTask(planId, task.task_id, issues, taskUsage);
91
92
  completedCount++;
92
- totalFindings += findings.length;
93
+ totalIssues += issues.length;
93
94
  pushEvent({
94
95
  type: "task_completed",
95
96
  taskId: task.task_id,
96
97
  reviewId: task.review_id,
97
98
  files: task.files,
98
- findingCount: findings.length,
99
+ issueCount: issues.length,
99
100
  usage: taskUsage,
100
101
  });
101
102
  pushEvent({
@@ -181,7 +182,7 @@ export class ReviewOrchestratorService {
181
182
  yield eventQueue.shift();
182
183
  }
183
184
  // Final completion event
184
- yield { type: "complete", totalFindings };
185
+ yield { type: "complete", totalIssues };
185
186
  }
186
187
  }
187
188
  //# sourceMappingURL=ReviewOrchestratorService.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ReviewOrchestratorService.js","sourceRoot":"","sources":["../../../src/services/review/ReviewOrchestratorService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ReviewOrchestratorService.js","sourceRoot":"","sources":["../../../src/services/review/ReviewOrchestratorService.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ import type { ReviewConfig } from "../../config/types.js";
2
+ import type { AgentModel, ReviewModule } from "../../types/criteria.js";
3
+ import type { PartitionedSubtask, Scope, TaskUsage } from "../../types/review.js";
4
+ /** What the partitioner agent produces for one criterion. */
5
+ export interface PartitionResult {
6
+ reasoning: string;
7
+ subtasks: PartitionedSubtask[];
8
+ /** Claude model tier used for this partitioner run. */
9
+ model: AgentModel;
10
+ usage: TaskUsage | null;
11
+ /** Full SDK message stream from this run, for transcript persistence. */
12
+ messages: unknown[];
13
+ }
14
+ /** Thrown when the partitioner agent fails or produces invalid output. */
15
+ export declare class PartitionerError extends Error {
16
+ /** The criterion id this failure was scoped to. */
17
+ readonly reviewId: string;
18
+ constructor(reviewId: string, message: string);
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 declare class ReviewPartitionerService {
31
+ private readonly config;
32
+ private readonly projectRoot;
33
+ constructor(config: ReviewConfig, projectRoot: string);
34
+ /**
35
+ * Run the partitioner for one criterion. Returns the validated partition
36
+ * result, or throws on failure.
37
+ */
38
+ partition(criterion: ReviewModule, matchedFiles: string[], scope: Scope): Promise<PartitionResult>;
39
+ }
40
+ /**
41
+ * Verify a candidate partition covers every input file at least once and
42
+ * has well-formed subtasks. Returns a human-readable error string or null
43
+ * if the partition is valid.
44
+ */
45
+ export declare function validatePartition(subtasks: PartitionedSubtask[], inputFiles: Set<string>): string | null;
46
+ //# sourceMappingURL=ReviewPartitionerService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReviewPartitionerService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewPartitionerService.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,KAAK,EACV,kBAAkB,EAClB,KAAK,EACL,SAAS,EACV,MAAM,uBAAuB,CAAC;AAM/B,6DAA6D;AAC7D,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,uDAAuD;IACvD,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,yEAAyE;IACzE,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB;AAMD,0EAA0E;AAC1E,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAEd,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK9C;AAMD;;;;;;;;;GASG;AACH,qBAAa,wBAAwB;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM;IAKrD;;;OAGG;IACG,SAAS,CACb,SAAS,EAAE,YAAY,EACvB,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,KAAK,GACX,OAAO,CAAC,eAAe,CAAC;CAkK5B;AAMD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,kBAAkB,EAAE,EAC9B,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,MAAM,GAAG,IAAI,CAyBf"}
@@ -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, ReviewSource } from "../../types/review.js";
4
+ import type { PartitionDecision, PlanInvocation, ReviewPlan, Scope } from "../../types/review.js";
4
5
  /**
5
- * Build a complete review plan: create the plan, match files to modules,
6
- * generate tasks, and finalize.
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
- * This is the single authoritative implementation of plan+task creation,
9
- * shared by both the planner agent's in-process MCP tool and any other
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, source: ReviewSource, files: string[], modules: ReviewModule[]): ReviewPlan;
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,YAAY,EACb,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,oBAAoB,EAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,YAAY,EAAE,GACtB,UAAU,CA6DZ"}
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"}