@prowi/deskcheck 0.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/LICENSE +21 -0
- package/README.md +266 -0
- package/build/agents/executor-prompt.d.ts +10 -0
- package/build/agents/executor-prompt.d.ts.map +1 -0
- package/build/agents/executor-prompt.js +65 -0
- package/build/agents/executor-prompt.js.map +1 -0
- package/build/agents/orchestrator.d.ts +52 -0
- package/build/agents/orchestrator.d.ts.map +1 -0
- package/build/agents/orchestrator.js +343 -0
- package/build/agents/orchestrator.js.map +1 -0
- package/build/agents/planner.d.ts +28 -0
- package/build/agents/planner.d.ts.map +1 -0
- package/build/agents/planner.js +138 -0
- package/build/agents/planner.js.map +1 -0
- package/build/cli.d.ts +3 -0
- package/build/cli.d.ts.map +1 -0
- package/build/cli.js +467 -0
- package/build/cli.js.map +1 -0
- package/build/core/config.d.ts +16 -0
- package/build/core/config.d.ts.map +1 -0
- package/build/core/config.js +81 -0
- package/build/core/config.js.map +1 -0
- package/build/core/context-extractor.d.ts +17 -0
- package/build/core/context-extractor.d.ts.map +1 -0
- package/build/core/context-extractor.js +69 -0
- package/build/core/context-extractor.js.map +1 -0
- package/build/core/glob-matcher.d.ts +32 -0
- package/build/core/glob-matcher.d.ts.map +1 -0
- package/build/core/glob-matcher.js +51 -0
- package/build/core/glob-matcher.js.map +1 -0
- package/build/core/module-parser.d.ts +26 -0
- package/build/core/module-parser.d.ts.map +1 -0
- package/build/core/module-parser.js +98 -0
- package/build/core/module-parser.js.map +1 -0
- package/build/core/plan-builder.d.ts +12 -0
- package/build/core/plan-builder.d.ts.map +1 -0
- package/build/core/plan-builder.js +66 -0
- package/build/core/plan-builder.js.map +1 -0
- package/build/core/storage.d.ts +118 -0
- package/build/core/storage.d.ts.map +1 -0
- package/build/core/storage.js +590 -0
- package/build/core/storage.js.map +1 -0
- package/build/core/types.d.ts +268 -0
- package/build/core/types.d.ts.map +1 -0
- package/build/core/types.js +5 -0
- package/build/core/types.js.map +1 -0
- package/build/mcp/tools.d.ts +10 -0
- package/build/mcp/tools.d.ts.map +1 -0
- package/build/mcp/tools.js +354 -0
- package/build/mcp/tools.js.map +1 -0
- package/build/mcp-server.d.ts +3 -0
- package/build/mcp-server.d.ts.map +1 -0
- package/build/mcp-server.js +15 -0
- package/build/mcp-server.js.map +1 -0
- package/build/renderers/json.d.ts +4 -0
- package/build/renderers/json.d.ts.map +1 -0
- package/build/renderers/json.js +5 -0
- package/build/renderers/json.js.map +1 -0
- package/build/renderers/markdown.d.ts +4 -0
- package/build/renderers/markdown.d.ts.map +1 -0
- package/build/renderers/markdown.js +36 -0
- package/build/renderers/markdown.js.map +1 -0
- package/build/renderers/shared.d.ts +23 -0
- package/build/renderers/shared.d.ts.map +1 -0
- package/build/renderers/shared.js +30 -0
- package/build/renderers/shared.js.map +1 -0
- package/build/renderers/terminal.d.ts +4 -0
- package/build/renderers/terminal.d.ts.map +1 -0
- package/build/renderers/terminal.js +88 -0
- package/build/renderers/terminal.js.map +1 -0
- package/build/renderers/watch.d.ts +4 -0
- package/build/renderers/watch.d.ts.map +1 -0
- package/build/renderers/watch.js +119 -0
- package/build/renderers/watch.js.map +1 -0
- package/build/serve.d.ts +9 -0
- package/build/serve.d.ts.map +1 -0
- package/build/serve.js +249 -0
- package/build/serve.js.map +1 -0
- package/package.json +41 -0
- package/ui/dist/index.html +92 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/** Severity level assigned to a criterion (how important it is). */
|
|
2
|
+
export type ModuleSeverity = "critical" | "high" | "medium" | "low";
|
|
3
|
+
/** Severity level assigned to an individual finding. */
|
|
4
|
+
export type FindingSeverity = "critical" | "warning" | "info";
|
|
5
|
+
/** Claude model tier used for agent execution. */
|
|
6
|
+
export type AgentModel = "haiku" | "sonnet" | "opus";
|
|
7
|
+
/** How the source content is provided to executors. */
|
|
8
|
+
export type ContextType = "diff" | "file" | "symbol";
|
|
9
|
+
/** Lifecycle status of a deskcheck plan. */
|
|
10
|
+
export type PlanStatus = "planning" | "ready" | "executing" | "complete";
|
|
11
|
+
/** Lifecycle status of an individual deskcheck task. */
|
|
12
|
+
export type TaskStatus = "pending" | "in_progress" | "complete" | "error";
|
|
13
|
+
/** Whether results cover all tasks or only a subset. */
|
|
14
|
+
export type ResultsStatus = "partial" | "complete";
|
|
15
|
+
/** A criterion parsed from a markdown file in the criteria directory. */
|
|
16
|
+
export interface ReviewModule {
|
|
17
|
+
/** Unique identifier, e.g. "architecture/dto-enforcement". */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Relative file path, e.g. "deskcheck/criteria/architecture/dto-enforcement.md". */
|
|
20
|
+
file: string;
|
|
21
|
+
/** Human-readable description from frontmatter. */
|
|
22
|
+
description: string;
|
|
23
|
+
/** How important this criterion's findings are. */
|
|
24
|
+
severity: ModuleSeverity;
|
|
25
|
+
/** File glob patterns that determine which files this criterion checks. */
|
|
26
|
+
globs: string[];
|
|
27
|
+
/** Natural language instruction for how to split files into tasks. */
|
|
28
|
+
mode: string;
|
|
29
|
+
/** Claude model tier to use for executor agents. */
|
|
30
|
+
model: AgentModel;
|
|
31
|
+
/** The detective prompt (markdown body of the criterion) given to executor agents. */
|
|
32
|
+
prompt: string;
|
|
33
|
+
}
|
|
34
|
+
/** MCP server configuration for agent tool access. */
|
|
35
|
+
export interface McpServerConfig {
|
|
36
|
+
/** Command to start the MCP server. */
|
|
37
|
+
command: string;
|
|
38
|
+
/** Command-line arguments. */
|
|
39
|
+
args?: string[];
|
|
40
|
+
/** Environment variables passed to the server process. */
|
|
41
|
+
env?: Record<string, string>;
|
|
42
|
+
}
|
|
43
|
+
/** Per-role agent configuration (planner, executor, evaluator). */
|
|
44
|
+
export interface AgentRoleConfig {
|
|
45
|
+
/** Override the default model for this role. */
|
|
46
|
+
model?: AgentModel;
|
|
47
|
+
/** Additional tools beyond the shared set. */
|
|
48
|
+
additional_tools?: string[];
|
|
49
|
+
/** Additional MCP servers beyond the shared set. */
|
|
50
|
+
additional_mcp_servers?: Record<string, McpServerConfig>;
|
|
51
|
+
}
|
|
52
|
+
/** Top-level deskcheck tool configuration from .deskcheck/config.json. */
|
|
53
|
+
export interface ReviewConfig {
|
|
54
|
+
/** Directory containing criterion markdown files. */
|
|
55
|
+
modules_dir: string;
|
|
56
|
+
/** Directory for storing deskcheck run results. */
|
|
57
|
+
storage_dir: string;
|
|
58
|
+
/** Port for the web UI server. Default: 3000. */
|
|
59
|
+
serve_port: number;
|
|
60
|
+
/** Shared configuration applied to all agent roles. */
|
|
61
|
+
shared: {
|
|
62
|
+
/** Tools available to all agents. */
|
|
63
|
+
allowed_tools: string[];
|
|
64
|
+
/** MCP servers available to all agents. */
|
|
65
|
+
mcp_servers: Record<string, McpServerConfig>;
|
|
66
|
+
};
|
|
67
|
+
/** Per-role agent configuration. */
|
|
68
|
+
agents: {
|
|
69
|
+
planner: AgentRoleConfig;
|
|
70
|
+
executor: AgentRoleConfig;
|
|
71
|
+
evaluator: AgentRoleConfig;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** What is being reviewed — a diff, file, or symbol. */
|
|
75
|
+
export interface ReviewSource {
|
|
76
|
+
/** The kind of content being reviewed. */
|
|
77
|
+
type: ContextType;
|
|
78
|
+
/** Target identifier: branch name (diff), file path (file), or symbol name (symbol). */
|
|
79
|
+
target: string;
|
|
80
|
+
/** Only for symbol mode — the file containing the symbol. */
|
|
81
|
+
file?: string;
|
|
82
|
+
}
|
|
83
|
+
/** A single review task assigned to an executor agent. */
|
|
84
|
+
export interface ReviewTask {
|
|
85
|
+
/** Unique task identifier, e.g. "architecture--dto-enforcement-001". */
|
|
86
|
+
task_id: string;
|
|
87
|
+
/** Review module identifier, e.g. "architecture/dto-enforcement". */
|
|
88
|
+
review_id: string;
|
|
89
|
+
/** Relative path to the criterion file. */
|
|
90
|
+
review_file: string;
|
|
91
|
+
/** Files assigned to this task. */
|
|
92
|
+
files: string[];
|
|
93
|
+
/** Optional planner hint describing scope or focus area. */
|
|
94
|
+
hint: string | null;
|
|
95
|
+
/** Claude model tier for the executor agent. */
|
|
96
|
+
model: AgentModel;
|
|
97
|
+
/** Current lifecycle status. */
|
|
98
|
+
status: TaskStatus;
|
|
99
|
+
/** ISO 8601 timestamp when this task was created. */
|
|
100
|
+
created_at: string;
|
|
101
|
+
/** ISO 8601 timestamp when execution started. */
|
|
102
|
+
started_at: string | null;
|
|
103
|
+
/** ISO 8601 timestamp when execution completed. */
|
|
104
|
+
completed_at: string | null;
|
|
105
|
+
/** How context was provided to the executor (diff, file content, or symbol). */
|
|
106
|
+
context_type: ContextType;
|
|
107
|
+
/** The actual context content (pruneable after completion). */
|
|
108
|
+
context: string | null;
|
|
109
|
+
/** Only for symbol mode — the symbol being reviewed. */
|
|
110
|
+
symbol: string | null;
|
|
111
|
+
/** The detective prompt from the criterion (pruneable after completion). */
|
|
112
|
+
prompt: string | null;
|
|
113
|
+
}
|
|
114
|
+
/** Summary of a criterion's role in a plan. */
|
|
115
|
+
export interface ModuleSummary {
|
|
116
|
+
/** Review module identifier. */
|
|
117
|
+
review_id: string;
|
|
118
|
+
/** Human-readable description from frontmatter. */
|
|
119
|
+
description: string;
|
|
120
|
+
/** Criterion severity level. */
|
|
121
|
+
severity: ModuleSeverity;
|
|
122
|
+
/** Claude model tier from frontmatter. */
|
|
123
|
+
model: AgentModel;
|
|
124
|
+
/** Number of tasks created for this criterion. */
|
|
125
|
+
task_count: number;
|
|
126
|
+
/** Files that matched this module's globs. */
|
|
127
|
+
matched_files: string[];
|
|
128
|
+
}
|
|
129
|
+
/** The complete deskcheck plan written to plan.json. */
|
|
130
|
+
export interface ReviewPlan {
|
|
131
|
+
/** Unique plan identifier, e.g. "2026-03-19_143022". */
|
|
132
|
+
plan_id: string;
|
|
133
|
+
/** Human-readable name, e.g. "feature/order-rework vs develop". */
|
|
134
|
+
name: string;
|
|
135
|
+
/** What is being reviewed. */
|
|
136
|
+
source: ReviewSource;
|
|
137
|
+
/** Current lifecycle status. */
|
|
138
|
+
status: PlanStatus;
|
|
139
|
+
/** ISO 8601 timestamp when the plan was created. */
|
|
140
|
+
created_at: string;
|
|
141
|
+
/** ISO 8601 timestamp when planning was finalized. */
|
|
142
|
+
finalized_at: string | null;
|
|
143
|
+
/** ISO 8601 timestamp when execution started. */
|
|
144
|
+
started_at: string | null;
|
|
145
|
+
/** ISO 8601 timestamp when all tasks completed. */
|
|
146
|
+
completed_at: string | null;
|
|
147
|
+
/** Files that matched at least one criterion. */
|
|
148
|
+
matched_files: string[];
|
|
149
|
+
/** Files with no matching criterion (coverage gaps). */
|
|
150
|
+
unmatched_files: string[];
|
|
151
|
+
/** All tasks keyed by task_id. */
|
|
152
|
+
tasks: Record<string, ReviewTask>;
|
|
153
|
+
/** Per-module summaries keyed by review_id. */
|
|
154
|
+
modules: Record<string, ModuleSummary>;
|
|
155
|
+
}
|
|
156
|
+
/** Token usage and timing data from an executor agent run. */
|
|
157
|
+
export interface TaskUsage {
|
|
158
|
+
input_tokens: number;
|
|
159
|
+
output_tokens: number;
|
|
160
|
+
cache_read_tokens: number;
|
|
161
|
+
cache_creation_tokens: number;
|
|
162
|
+
cost_usd: number;
|
|
163
|
+
duration_ms: number;
|
|
164
|
+
duration_api_ms: number;
|
|
165
|
+
num_turns: number;
|
|
166
|
+
model: string;
|
|
167
|
+
}
|
|
168
|
+
/** Aggregated token usage across all tasks in a run. */
|
|
169
|
+
export interface TotalUsage {
|
|
170
|
+
input_tokens: number;
|
|
171
|
+
output_tokens: number;
|
|
172
|
+
cache_read_tokens: number;
|
|
173
|
+
cache_creation_tokens: number;
|
|
174
|
+
cost_usd: number;
|
|
175
|
+
duration_ms: number;
|
|
176
|
+
duration_api_ms: number;
|
|
177
|
+
num_turns: number;
|
|
178
|
+
}
|
|
179
|
+
/** A single finding produced by an executor agent. */
|
|
180
|
+
export interface Finding {
|
|
181
|
+
/** How severe this finding is. */
|
|
182
|
+
severity: FindingSeverity;
|
|
183
|
+
/** File path where the issue was found. */
|
|
184
|
+
file: string;
|
|
185
|
+
/** Line number where the issue occurs, if applicable. */
|
|
186
|
+
line: number | null;
|
|
187
|
+
/** Description of the issue. */
|
|
188
|
+
description: string;
|
|
189
|
+
/** Suggested fix or improvement, if applicable. */
|
|
190
|
+
suggestion: string | null;
|
|
191
|
+
}
|
|
192
|
+
/** A finding enriched with its source module and task for by-file grouping. */
|
|
193
|
+
export interface FileFinding extends Finding {
|
|
194
|
+
/** Which criterion produced this finding. */
|
|
195
|
+
review_id: string;
|
|
196
|
+
/** Which task produced this finding. */
|
|
197
|
+
task_id: string;
|
|
198
|
+
}
|
|
199
|
+
/** Results from a single completed task. */
|
|
200
|
+
export interface TaskResult {
|
|
201
|
+
/** The task that produced these results. */
|
|
202
|
+
task_id: string;
|
|
203
|
+
/** The criterion that was applied. */
|
|
204
|
+
review_id: string;
|
|
205
|
+
/** Files that were reviewed. */
|
|
206
|
+
files: string[];
|
|
207
|
+
/** ISO 8601 timestamp when the task completed. */
|
|
208
|
+
completed_at: string;
|
|
209
|
+
/** Findings produced by the executor agent. */
|
|
210
|
+
findings: Finding[];
|
|
211
|
+
/** Token usage and timing from the executor agent. Null for legacy results. */
|
|
212
|
+
usage: TaskUsage | null;
|
|
213
|
+
}
|
|
214
|
+
/** Aggregated findings for a single criterion. */
|
|
215
|
+
export interface ModuleFindings {
|
|
216
|
+
/** Review module identifier. */
|
|
217
|
+
review_id: string;
|
|
218
|
+
/** Human-readable description. */
|
|
219
|
+
description: string;
|
|
220
|
+
/** Criterion severity level. */
|
|
221
|
+
severity: ModuleSeverity;
|
|
222
|
+
/** Total number of tasks for this criterion. */
|
|
223
|
+
task_count: number;
|
|
224
|
+
/** Number of completed tasks. */
|
|
225
|
+
completed: number;
|
|
226
|
+
/** Aggregated finding counts by severity. */
|
|
227
|
+
counts: {
|
|
228
|
+
critical: number;
|
|
229
|
+
warning: number;
|
|
230
|
+
info: number;
|
|
231
|
+
total: number;
|
|
232
|
+
};
|
|
233
|
+
/** All findings from this module's tasks. */
|
|
234
|
+
findings: Finding[];
|
|
235
|
+
}
|
|
236
|
+
/** The complete deskcheck results written to results.json. */
|
|
237
|
+
export interface ReviewResults {
|
|
238
|
+
/** Matches the plan_id from plan.json. */
|
|
239
|
+
plan_id: string;
|
|
240
|
+
/** Whether all tasks have completed. */
|
|
241
|
+
status: ResultsStatus;
|
|
242
|
+
/** ISO 8601 timestamp of the last update. */
|
|
243
|
+
updated_at: string;
|
|
244
|
+
/** Task completion tracking. */
|
|
245
|
+
completion: {
|
|
246
|
+
total: number;
|
|
247
|
+
completed: number;
|
|
248
|
+
pending: number;
|
|
249
|
+
in_progress: number;
|
|
250
|
+
errored: number;
|
|
251
|
+
};
|
|
252
|
+
/** Aggregated finding counts across all tasks. */
|
|
253
|
+
summary: {
|
|
254
|
+
total: number;
|
|
255
|
+
critical: number;
|
|
256
|
+
warning: number;
|
|
257
|
+
info: number;
|
|
258
|
+
};
|
|
259
|
+
/** Per-task results keyed by task_id. */
|
|
260
|
+
task_results: Record<string, TaskResult>;
|
|
261
|
+
/** Findings grouped by file path. */
|
|
262
|
+
by_file: Record<string, FileFinding[]>;
|
|
263
|
+
/** Findings grouped by criterion. */
|
|
264
|
+
by_module: Record<string, ModuleFindings>;
|
|
265
|
+
/** Aggregated token usage across all completed tasks. */
|
|
266
|
+
total_usage: TotalUsage;
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,qBAAqB;AACrB,gFAAgF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { ReviewConfig } from "../core/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Register all review MCP tools on the given server.
|
|
5
|
+
*
|
|
6
|
+
* Each tool wraps core business logic (storage, module discovery, glob matching)
|
|
7
|
+
* and exposes it over the MCP protocol with Zod-validated input schemas.
|
|
8
|
+
*/
|
|
9
|
+
export declare function registerReviewTools(server: McpServer, config: ReviewConfig, projectRoot: string): void;
|
|
10
|
+
//# sourceMappingURL=tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/mcp/tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,YAAY,EAAuB,MAAM,kBAAkB,CAAC;AAM1E;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,YAAY,EACpB,WAAW,EAAE,MAAM,GAClB,IAAI,CAoYN"}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { ReviewStorage } from "../core/storage.js";
|
|
4
|
+
import { extractContext } from "../core/context-extractor.js";
|
|
5
|
+
import { discoverModules, parseModule } from "../core/module-parser.js";
|
|
6
|
+
import { findMatchingModules } from "../core/glob-matcher.js";
|
|
7
|
+
/**
|
|
8
|
+
* Register all review MCP tools on the given server.
|
|
9
|
+
*
|
|
10
|
+
* Each tool wraps core business logic (storage, module discovery, glob matching)
|
|
11
|
+
* and exposes it over the MCP protocol with Zod-validated input schemas.
|
|
12
|
+
*/
|
|
13
|
+
export function registerReviewTools(server, config, projectRoot) {
|
|
14
|
+
const storage = new ReviewStorage(path.resolve(projectRoot, config.storage_dir));
|
|
15
|
+
const modulesDir = path.resolve(projectRoot, config.modules_dir);
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// 1. review_status — health check
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
server.registerTool("review_status", {
|
|
20
|
+
description: "Returns the status of the deskcheck MCP server.",
|
|
21
|
+
}, () => {
|
|
22
|
+
return {
|
|
23
|
+
content: [{
|
|
24
|
+
type: "text",
|
|
25
|
+
text: JSON.stringify({ status: "ok", version: "0.1.0" }, null, 2),
|
|
26
|
+
}],
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// 2. start_review_plan — create a new review plan
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
server.registerTool("start_review_plan", {
|
|
33
|
+
description: "Create a new review plan. Returns the plan object with its generated plan_id.",
|
|
34
|
+
inputSchema: {
|
|
35
|
+
name: z.string().describe("Human-readable name for the review plan"),
|
|
36
|
+
source_type: z
|
|
37
|
+
.enum(["diff", "file", "symbol"])
|
|
38
|
+
.describe("How source content is provided: diff, file, or symbol"),
|
|
39
|
+
source_target: z
|
|
40
|
+
.string()
|
|
41
|
+
.describe("Target identifier: branch/ref for diff, file path for file, symbol name for symbol"),
|
|
42
|
+
source_file: z
|
|
43
|
+
.string()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe("File containing the symbol (only for symbol mode)"),
|
|
46
|
+
},
|
|
47
|
+
}, ({ name, source_type, source_target, source_file }) => {
|
|
48
|
+
try {
|
|
49
|
+
const plan = storage.createPlan(name, {
|
|
50
|
+
type: source_type,
|
|
51
|
+
target: source_target,
|
|
52
|
+
file: source_file,
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
content: [{ type: "text", text: JSON.stringify(plan, null, 2) }],
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
return {
|
|
60
|
+
content: [{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
63
|
+
}],
|
|
64
|
+
isError: true,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
// 3. get_review_files_matching_paths — discover modules matching files
|
|
70
|
+
// ---------------------------------------------------------------------------
|
|
71
|
+
server.registerTool("get_review_files_matching_paths", {
|
|
72
|
+
description: "Discover which criteria match a set of file paths. Returns matches without the full prompt body.",
|
|
73
|
+
inputSchema: {
|
|
74
|
+
files: z
|
|
75
|
+
.array(z.string())
|
|
76
|
+
.describe("Array of file paths to match against criterion globs"),
|
|
77
|
+
},
|
|
78
|
+
}, ({ files }) => {
|
|
79
|
+
try {
|
|
80
|
+
const modules = discoverModules(modulesDir);
|
|
81
|
+
const matches = findMatchingModules(files, modules);
|
|
82
|
+
const result = matches.map((match) => ({
|
|
83
|
+
review_id: match.module.id,
|
|
84
|
+
review_file: match.module.file,
|
|
85
|
+
description: match.module.description,
|
|
86
|
+
severity: match.module.severity,
|
|
87
|
+
globs: match.module.globs,
|
|
88
|
+
mode: match.module.mode,
|
|
89
|
+
model: match.module.model,
|
|
90
|
+
matched_files: match.matchedFiles,
|
|
91
|
+
}));
|
|
92
|
+
return {
|
|
93
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return {
|
|
98
|
+
content: [{
|
|
99
|
+
type: "text",
|
|
100
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
101
|
+
}],
|
|
102
|
+
isError: true,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// 4. create_review_task — add a task to a plan
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
server.registerTool("create_review_task", {
|
|
110
|
+
description: "Create a review task within a plan. The task_id is auto-generated from the review_id.",
|
|
111
|
+
inputSchema: {
|
|
112
|
+
plan_id: z.string().describe("The plan ID to add the task to"),
|
|
113
|
+
review_id: z
|
|
114
|
+
.string()
|
|
115
|
+
.describe('Review module identifier, e.g. "architecture/dto-enforcement"'),
|
|
116
|
+
review_file: z
|
|
117
|
+
.string()
|
|
118
|
+
.describe("Relative path to the criterion markdown file"),
|
|
119
|
+
files: z
|
|
120
|
+
.array(z.string())
|
|
121
|
+
.describe("Files assigned to this task"),
|
|
122
|
+
hint: z
|
|
123
|
+
.string()
|
|
124
|
+
.optional()
|
|
125
|
+
.describe("Optional planner hint describing scope or focus area"),
|
|
126
|
+
model: z
|
|
127
|
+
.enum(["haiku", "sonnet", "opus"])
|
|
128
|
+
.describe("Claude model tier for the executor agent"),
|
|
129
|
+
},
|
|
130
|
+
}, ({ plan_id, review_id, review_file, files, hint, model }) => {
|
|
131
|
+
try {
|
|
132
|
+
const task = storage.addTask(plan_id, {
|
|
133
|
+
review_id,
|
|
134
|
+
review_file,
|
|
135
|
+
files,
|
|
136
|
+
hint: hint ?? null,
|
|
137
|
+
model,
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
content: [{ type: "text", text: JSON.stringify(task, null, 2) }],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
return {
|
|
145
|
+
content: [{
|
|
146
|
+
type: "text",
|
|
147
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
148
|
+
}],
|
|
149
|
+
isError: true,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// 5. finish_planning — finalize the plan
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
server.registerTool("finish_planning", {
|
|
157
|
+
description: 'Finalize a review plan, setting its status to "ready" for execution.',
|
|
158
|
+
inputSchema: {
|
|
159
|
+
plan_id: z.string().describe("The plan ID to finalize"),
|
|
160
|
+
},
|
|
161
|
+
}, ({ plan_id }) => {
|
|
162
|
+
try {
|
|
163
|
+
const plan = storage.finalizePlan(plan_id);
|
|
164
|
+
return {
|
|
165
|
+
content: [{ type: "text", text: JSON.stringify(plan, null, 2) }],
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
return {
|
|
170
|
+
content: [{
|
|
171
|
+
type: "text",
|
|
172
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
173
|
+
}],
|
|
174
|
+
isError: true,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
// ---------------------------------------------------------------------------
|
|
179
|
+
// 6. get_pending_review_tasks — list tasks ready for execution
|
|
180
|
+
// ---------------------------------------------------------------------------
|
|
181
|
+
server.registerTool("get_pending_review_tasks", {
|
|
182
|
+
description: "Return tasks eligible for execution: pending tasks and stale in_progress tasks (older than 5 minutes).",
|
|
183
|
+
inputSchema: {
|
|
184
|
+
plan_id: z.string().describe("The plan ID to query"),
|
|
185
|
+
},
|
|
186
|
+
}, ({ plan_id }) => {
|
|
187
|
+
try {
|
|
188
|
+
const tasks = storage.getPendingTasks(plan_id);
|
|
189
|
+
return {
|
|
190
|
+
content: [{ type: "text", text: JSON.stringify(tasks, null, 2) }],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
catch (error) {
|
|
194
|
+
return {
|
|
195
|
+
content: [{
|
|
196
|
+
type: "text",
|
|
197
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
198
|
+
}],
|
|
199
|
+
isError: true,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
// ---------------------------------------------------------------------------
|
|
204
|
+
// 7. start_review — claim a task and return context for executor
|
|
205
|
+
// ---------------------------------------------------------------------------
|
|
206
|
+
server.registerTool("start_review", {
|
|
207
|
+
description: "Claim a review task and return everything the executor needs: context (diff/file/symbol content), the criterion prompt, and task metadata.",
|
|
208
|
+
inputSchema: {
|
|
209
|
+
plan_id: z.string().describe("The plan ID"),
|
|
210
|
+
task_id: z.string().describe("The task ID to claim"),
|
|
211
|
+
},
|
|
212
|
+
}, ({ plan_id, task_id }) => {
|
|
213
|
+
try {
|
|
214
|
+
const plan = storage.getPlan(plan_id);
|
|
215
|
+
const task = plan.tasks[task_id];
|
|
216
|
+
if (!task) {
|
|
217
|
+
return {
|
|
218
|
+
content: [{
|
|
219
|
+
type: "text",
|
|
220
|
+
text: `Error: Task "${task_id}" not found in plan "${plan_id}"`,
|
|
221
|
+
}],
|
|
222
|
+
isError: true,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
// Extract context based on source type
|
|
226
|
+
const symbol = plan.source.type === "symbol" ? plan.source.target : undefined;
|
|
227
|
+
const extracted = extractContext(plan.source.type, plan.source.target, task.files, projectRoot, symbol);
|
|
228
|
+
// Read the criterion prompt
|
|
229
|
+
const moduleFilePath = path.resolve(projectRoot, task.review_file);
|
|
230
|
+
const reviewModule = parseModule(moduleFilePath, path.resolve(projectRoot, config.modules_dir));
|
|
231
|
+
// Claim the task via storage
|
|
232
|
+
const claimedTask = storage.claimTask(plan_id, task_id, {
|
|
233
|
+
contextType: extracted.contextType,
|
|
234
|
+
content: extracted.content,
|
|
235
|
+
symbol: extracted.symbol ?? undefined,
|
|
236
|
+
prompt: reviewModule.prompt,
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
content: [{
|
|
240
|
+
type: "text",
|
|
241
|
+
text: JSON.stringify({
|
|
242
|
+
task_id: claimedTask.task_id,
|
|
243
|
+
review_id: claimedTask.review_id,
|
|
244
|
+
files: claimedTask.files,
|
|
245
|
+
hint: claimedTask.hint,
|
|
246
|
+
model: claimedTask.model,
|
|
247
|
+
context_type: claimedTask.context_type,
|
|
248
|
+
context: claimedTask.context,
|
|
249
|
+
symbol: claimedTask.symbol,
|
|
250
|
+
prompt: claimedTask.prompt,
|
|
251
|
+
}, null, 2),
|
|
252
|
+
}],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
return {
|
|
257
|
+
content: [{
|
|
258
|
+
type: "text",
|
|
259
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
260
|
+
}],
|
|
261
|
+
isError: true,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
// ---------------------------------------------------------------------------
|
|
266
|
+
// 8. finish_review — complete a task with findings
|
|
267
|
+
// ---------------------------------------------------------------------------
|
|
268
|
+
server.registerTool("finish_review", {
|
|
269
|
+
description: "Complete a review task by submitting findings. Updates both plan.json and results.json.",
|
|
270
|
+
inputSchema: {
|
|
271
|
+
plan_id: z.string().describe("The plan ID"),
|
|
272
|
+
task_id: z.string().describe("The task ID to complete"),
|
|
273
|
+
findings: z
|
|
274
|
+
.array(z.object({
|
|
275
|
+
severity: z
|
|
276
|
+
.enum(["critical", "warning", "info"])
|
|
277
|
+
.describe("Finding severity"),
|
|
278
|
+
file: z.string().describe("File path where the issue was found"),
|
|
279
|
+
line: z
|
|
280
|
+
.number()
|
|
281
|
+
.nullable()
|
|
282
|
+
.optional()
|
|
283
|
+
.describe("Line number, if applicable"),
|
|
284
|
+
description: z.string().describe("Description of the issue"),
|
|
285
|
+
suggestion: z
|
|
286
|
+
.string()
|
|
287
|
+
.nullable()
|
|
288
|
+
.optional()
|
|
289
|
+
.describe("Suggested fix, if applicable"),
|
|
290
|
+
}))
|
|
291
|
+
.describe("Array of findings from the review"),
|
|
292
|
+
},
|
|
293
|
+
}, ({ plan_id, task_id, findings }) => {
|
|
294
|
+
try {
|
|
295
|
+
const normalizedFindings = findings.map((f) => ({
|
|
296
|
+
severity: f.severity,
|
|
297
|
+
file: f.file,
|
|
298
|
+
line: f.line ?? null,
|
|
299
|
+
description: f.description,
|
|
300
|
+
suggestion: f.suggestion ?? null,
|
|
301
|
+
}));
|
|
302
|
+
storage.completeTask(plan_id, task_id, normalizedFindings);
|
|
303
|
+
const plan = storage.getPlan(plan_id);
|
|
304
|
+
const task = plan.tasks[task_id];
|
|
305
|
+
return {
|
|
306
|
+
content: [{
|
|
307
|
+
type: "text",
|
|
308
|
+
text: JSON.stringify({
|
|
309
|
+
task_id: task.task_id,
|
|
310
|
+
status: task.status,
|
|
311
|
+
completed_at: task.completed_at,
|
|
312
|
+
findings_count: normalizedFindings.length,
|
|
313
|
+
plan_status: plan.status,
|
|
314
|
+
}, null, 2),
|
|
315
|
+
}],
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
return {
|
|
320
|
+
content: [{
|
|
321
|
+
type: "text",
|
|
322
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
323
|
+
}],
|
|
324
|
+
isError: true,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
// ---------------------------------------------------------------------------
|
|
329
|
+
// 9. get_review_results — aggregated results
|
|
330
|
+
// ---------------------------------------------------------------------------
|
|
331
|
+
server.registerTool("get_review_results", {
|
|
332
|
+
description: "Return aggregated review results including findings grouped by file and module.",
|
|
333
|
+
inputSchema: {
|
|
334
|
+
plan_id: z.string().describe("The plan ID to get results for"),
|
|
335
|
+
},
|
|
336
|
+
}, ({ plan_id }) => {
|
|
337
|
+
try {
|
|
338
|
+
const results = storage.getResults(plan_id);
|
|
339
|
+
return {
|
|
340
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
return {
|
|
345
|
+
content: [{
|
|
346
|
+
type: "text",
|
|
347
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
348
|
+
}],
|
|
349
|
+
isError: true,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
//# sourceMappingURL=tools.js.map
|