@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
|
@@ -7,33 +7,16 @@ function parseReference(raw) {
|
|
|
7
7
|
return {
|
|
8
8
|
file: String(raw.file ?? ""),
|
|
9
9
|
symbol: typeof raw.symbol === "string" ? raw.symbol : null,
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
startLine: typeof raw.startLine === "number" ? raw.startLine : 0,
|
|
11
|
+
endLine: typeof raw.endLine === "number" ? raw.endLine : (typeof raw.startLine === "number" ? raw.startLine : 0),
|
|
12
|
+
contextLines: typeof raw.contextLines === "number" ? raw.contextLines : 3,
|
|
13
|
+
code: null, // Always null at parse time — populated by CodeSnippetService
|
|
12
14
|
suggestedCode: typeof raw.suggestedCode === "string" ? raw.suggestedCode : null,
|
|
13
15
|
note: typeof raw.note === "string" ? raw.note : null,
|
|
14
16
|
};
|
|
15
17
|
}
|
|
16
|
-
function legacyFindingToIssue(record) {
|
|
17
|
-
return {
|
|
18
|
-
severity: String(record.severity ?? "info"),
|
|
19
|
-
description: String(record.description ?? ""),
|
|
20
|
-
suggestion: typeof record.suggestion === "string" ? record.suggestion : null,
|
|
21
|
-
references: [{
|
|
22
|
-
file: String(record.file ?? ""),
|
|
23
|
-
symbol: null,
|
|
24
|
-
line: typeof record.line === "number" ? record.line : null,
|
|
25
|
-
code: null,
|
|
26
|
-
suggestedCode: null,
|
|
27
|
-
note: null,
|
|
28
|
-
}],
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
18
|
/**
|
|
32
19
|
* Parse executor output into a validated array of issues.
|
|
33
|
-
*
|
|
34
|
-
* Supports both the new Issue format (with `references` array) and the
|
|
35
|
-
* legacy Finding format (with `file` at top level). Legacy findings are
|
|
36
|
-
* automatically converted to Issues with a single Reference.
|
|
37
20
|
*/
|
|
38
21
|
export function parseIssues(output) {
|
|
39
22
|
// Try to extract JSON array from the output
|
|
@@ -76,42 +59,34 @@ export function parseIssues(output) {
|
|
|
76
59
|
console.error(`[deskcheck] Warning: skipping item with invalid severity "${severity}"`);
|
|
77
60
|
continue;
|
|
78
61
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
62
|
+
if (!Array.isArray(record.references) || record.references.length === 0)
|
|
63
|
+
continue;
|
|
64
|
+
const references = [];
|
|
65
|
+
for (const ref of record.references) {
|
|
66
|
+
if (typeof ref === "object" && ref !== null) {
|
|
67
|
+
references.push(parseReference(ref));
|
|
86
68
|
}
|
|
87
|
-
if (references.length === 0)
|
|
88
|
-
continue;
|
|
89
|
-
issues.push({
|
|
90
|
-
severity: severity,
|
|
91
|
-
description: String(record.description ?? ""),
|
|
92
|
-
suggestion: typeof record.suggestion === "string" ? record.suggestion : null,
|
|
93
|
-
references,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
else {
|
|
97
|
-
// Legacy Finding format: has `file` at top level
|
|
98
|
-
issues.push(legacyFindingToIssue(record));
|
|
99
69
|
}
|
|
70
|
+
if (references.length === 0)
|
|
71
|
+
continue;
|
|
72
|
+
issues.push({
|
|
73
|
+
severity: severity,
|
|
74
|
+
description: String(record.description ?? ""),
|
|
75
|
+
suggestion: typeof record.suggestion === "string" ? record.suggestion : null,
|
|
76
|
+
references,
|
|
77
|
+
});
|
|
100
78
|
}
|
|
101
79
|
return issues;
|
|
102
80
|
}
|
|
103
81
|
/**
|
|
104
|
-
* Parse executor output into
|
|
105
|
-
*
|
|
106
|
-
* @deprecated Use parseIssues instead. This is kept for backwards compatibility
|
|
107
|
-
* with the testing system which still uses the Finding type.
|
|
82
|
+
* Parse executor output into findings for the testing subsystem.
|
|
108
83
|
*/
|
|
109
84
|
export function parseFindings(output) {
|
|
110
85
|
const issues = parseIssues(output);
|
|
111
86
|
return issues.map((issue) => ({
|
|
112
87
|
severity: issue.severity,
|
|
113
88
|
file: issue.references[0]?.file ?? "",
|
|
114
|
-
line: issue.references[0]?.
|
|
89
|
+
line: issue.references[0]?.startLine ?? null,
|
|
115
90
|
description: issue.description,
|
|
116
91
|
suggestion: issue.suggestion,
|
|
117
92
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FindingsParserService.js","sourceRoot":"","sources":["../../src/services/FindingsParserService.ts"],"names":[],"mappings":"AAIA,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAkB;IACrE,UAAU;IACV,SAAS;IACT,MAAM;CACP,CAAC,CAAC;AAEH,SAAS,cAAc,CAAC,GAA4B;IAClD,OAAO;QACL,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QAC5B,MAAM,EAAE,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI;QAC1D,
|
|
1
|
+
{"version":3,"file":"FindingsParserService.js","sourceRoot":"","sources":["../../src/services/FindingsParserService.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ export declare function parseModule(filePath: string, basePath: string): ReviewM
|
|
|
16
16
|
* Discover all criteria by recursively scanning a directory for `.md` files.
|
|
17
17
|
*
|
|
18
18
|
* Each markdown file is parsed for YAML frontmatter containing criterion metadata
|
|
19
|
-
* (description,
|
|
19
|
+
* (description, globs, etc.) and the markdown body becomes the detective prompt.
|
|
20
20
|
*
|
|
21
21
|
* @param modulesDir - Path to the directory containing criterion markdown files.
|
|
22
22
|
* @returns Array of parsed ReviewModule objects, sorted by ID for deterministic ordering.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-parser.d.ts","sourceRoot":"","sources":["../../../src/services/criteria/module-parser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"module-parser.d.ts","sourceRoot":"","sources":["../../../src/services/criteria/module-parser.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAc,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAWxE;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CA8E5E;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE,CAqBlE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,YAAY,EAAE,CA+BzF"}
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import matter from "gray-matter";
|
|
4
|
-
const VALID_SEVERITIES = new Set([
|
|
5
|
-
"critical",
|
|
6
|
-
"high",
|
|
7
|
-
"medium",
|
|
8
|
-
"low",
|
|
9
|
-
]);
|
|
10
4
|
const VALID_MODELS = new Set([
|
|
11
5
|
"haiku",
|
|
12
6
|
"sonnet",
|
|
13
7
|
"opus",
|
|
14
8
|
]);
|
|
15
|
-
const
|
|
9
|
+
const DEFAULT_PARTITION = "one task per matched file";
|
|
16
10
|
const DEFAULT_MODEL = "haiku";
|
|
17
11
|
/**
|
|
18
12
|
* Parse a single criterion markdown file into a ReviewModule object.
|
|
@@ -37,9 +31,6 @@ export function parseModule(filePath, basePath) {
|
|
|
37
31
|
if (typeof frontmatter.description !== "string" || frontmatter.description.trim() === "") {
|
|
38
32
|
throw new Error(`Invalid criterion ${relativePath}: "description" is required and must be a non-empty string`);
|
|
39
33
|
}
|
|
40
|
-
if (!VALID_SEVERITIES.has(frontmatter.severity)) {
|
|
41
|
-
throw new Error(`Invalid criterion ${relativePath}: "severity" must be one of: ${[...VALID_SEVERITIES].join(", ")}. Got: ${JSON.stringify(frontmatter.severity)}`);
|
|
42
|
-
}
|
|
43
34
|
if (!Array.isArray(frontmatter.globs) || frontmatter.globs.length === 0) {
|
|
44
35
|
throw new Error(`Invalid criterion ${relativePath}: "globs" is required and must be a non-empty array of strings`);
|
|
45
36
|
}
|
|
@@ -49,23 +40,36 @@ export function parseModule(filePath, basePath) {
|
|
|
49
40
|
}
|
|
50
41
|
}
|
|
51
42
|
// --- Apply defaults for optional fields ---
|
|
52
|
-
const
|
|
53
|
-
? frontmatter.
|
|
54
|
-
:
|
|
43
|
+
const partition = typeof frontmatter.partition === "string" && frontmatter.partition.trim() !== ""
|
|
44
|
+
? frontmatter.partition
|
|
45
|
+
: DEFAULT_PARTITION;
|
|
55
46
|
const model = frontmatter.model ?? DEFAULT_MODEL;
|
|
56
47
|
if (!VALID_MODELS.has(model)) {
|
|
57
48
|
throw new Error(`Invalid criterion ${relativePath}: "model" must be one of: ${[...VALID_MODELS].join(", ")}. Got: ${JSON.stringify(model)}`);
|
|
58
49
|
}
|
|
50
|
+
// tools — optional array of strings, defaults to empty.
|
|
51
|
+
let tools = [];
|
|
52
|
+
if (frontmatter.tools !== undefined) {
|
|
53
|
+
if (!Array.isArray(frontmatter.tools)) {
|
|
54
|
+
throw new Error(`Invalid criterion ${relativePath}: "tools" must be an array of strings. Got: ${JSON.stringify(frontmatter.tools)}`);
|
|
55
|
+
}
|
|
56
|
+
for (const t of frontmatter.tools) {
|
|
57
|
+
if (typeof t !== "string" || t.trim() === "") {
|
|
58
|
+
throw new Error(`Invalid criterion ${relativePath}: each entry in "tools" must be a non-empty string. Got: ${JSON.stringify(t)}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
tools = frontmatter.tools;
|
|
62
|
+
}
|
|
59
63
|
// --- Build the criterion ID from relative path without extension ---
|
|
60
64
|
const id = relativePath.replace(/\.md$/, "").split(path.sep).join("/");
|
|
61
65
|
return {
|
|
62
66
|
id,
|
|
63
67
|
file: relativeFile.split(path.sep).join("/"),
|
|
64
68
|
description: frontmatter.description,
|
|
65
|
-
severity: frontmatter.severity,
|
|
66
69
|
globs: frontmatter.globs,
|
|
67
|
-
|
|
70
|
+
partition,
|
|
68
71
|
model: model,
|
|
72
|
+
tools,
|
|
69
73
|
prompt: content.trim(),
|
|
70
74
|
};
|
|
71
75
|
}
|
|
@@ -73,7 +77,7 @@ export function parseModule(filePath, basePath) {
|
|
|
73
77
|
* Discover all criteria by recursively scanning a directory for `.md` files.
|
|
74
78
|
*
|
|
75
79
|
* Each markdown file is parsed for YAML frontmatter containing criterion metadata
|
|
76
|
-
* (description,
|
|
80
|
+
* (description, globs, etc.) and the markdown body becomes the detective prompt.
|
|
77
81
|
*
|
|
78
82
|
* @param modulesDir - Path to the directory containing criterion markdown files.
|
|
79
83
|
* @returns Array of parsed ReviewModule objects, sorted by ID for deterministic ordering.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-parser.js","sourceRoot":"","sources":["../../../src/services/criteria/module-parser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,aAAa,CAAC;AAGjC,MAAM,
|
|
1
|
+
{"version":3,"file":"module-parser.js","sourceRoot":"","sources":["../../../src/services/criteria/module-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Issue } from "../../types/review.js";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves code snippets for issue references by reading the actual files
|
|
4
|
+
* from disk. Populates the `reference.code` field with the lines indicated
|
|
5
|
+
* by `startLine`/`endLine`, padded by `contextLines` on each side.
|
|
6
|
+
*
|
|
7
|
+
* This is a pure post-processing step — no LLM involved.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveCodeSnippets(issues: Issue[], projectRoot: string): Issue[];
|
|
10
|
+
//# sourceMappingURL=CodeSnippetService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeSnippetService.d.ts","sourceRoot":"","sources":["../../../src/services/review/CodeSnippetService.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAEnD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,MAAM,GAAG,KAAK,EAAE,CAiDjF"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
/**
|
|
4
|
+
* Resolves code snippets for issue references by reading the actual files
|
|
5
|
+
* from disk. Populates the `reference.code` field with the lines indicated
|
|
6
|
+
* by `startLine`/`endLine`, padded by `contextLines` on each side.
|
|
7
|
+
*
|
|
8
|
+
* This is a pure post-processing step — no LLM involved.
|
|
9
|
+
*/
|
|
10
|
+
export function resolveCodeSnippets(issues, projectRoot) {
|
|
11
|
+
// Cache file contents to avoid re-reading the same file for multiple references
|
|
12
|
+
const fileCache = new Map();
|
|
13
|
+
function getLines(filePath) {
|
|
14
|
+
if (fileCache.has(filePath))
|
|
15
|
+
return fileCache.get(filePath);
|
|
16
|
+
const absPath = path.resolve(projectRoot, filePath);
|
|
17
|
+
try {
|
|
18
|
+
const content = fs.readFileSync(absPath, "utf-8");
|
|
19
|
+
const lines = content.split("\n");
|
|
20
|
+
fileCache.set(filePath, lines);
|
|
21
|
+
return lines;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
console.error(`[deskcheck] Warning: could not read file for snippet resolution: ${filePath}`);
|
|
25
|
+
fileCache.set(filePath, null);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
for (const issue of issues) {
|
|
30
|
+
for (const ref of issue.references) {
|
|
31
|
+
if (ref.startLine <= 0 || ref.endLine <= 0) {
|
|
32
|
+
ref.code = null;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const lines = getLines(ref.file);
|
|
36
|
+
if (!lines) {
|
|
37
|
+
ref.code = null;
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
// Lines are 1-indexed, array is 0-indexed. Pad with contextLines.
|
|
41
|
+
const ctx = ref.contextLines;
|
|
42
|
+
const start = Math.max(ref.startLine - 1 - ctx, 0);
|
|
43
|
+
const end = Math.min(ref.endLine + ctx, lines.length); // slice end is exclusive
|
|
44
|
+
if (ref.startLine - 1 >= lines.length || ref.startLine - 1 < 0) {
|
|
45
|
+
console.error(`[deskcheck] Warning: line range ${ref.startLine}-${ref.endLine} out of bounds for ${ref.file} (${lines.length} lines)`);
|
|
46
|
+
ref.code = null;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
ref.code = lines.slice(start, end).join("\n");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return issues;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=CodeSnippetService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CodeSnippetService.js","sourceRoot":"","sources":["../../../src/services/review/CodeSnippetService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAG7B;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAe,EAAE,WAAmB;IACtE,gFAAgF;IAChF,MAAM,SAAS,GAAG,IAAI,GAAG,EAA2B,CAAC;IAErD,SAAS,QAAQ,CAAC,QAAgB;QAChC,IAAI,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;QAE7D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QACpD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAClD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAClC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YAC/B,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,oEAAoE,QAAQ,EAAE,CAAC,CAAC;YAC9F,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,KAAK,MAAM,GAAG,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACnC,IAAI,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,GAAG,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;gBAChB,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACjC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;gBAChB,SAAS;YACX,CAAC;YAED,kEAAkE;YAClE,MAAM,GAAG,GAAG,GAAG,CAAC,YAAY,CAAC;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,yBAAyB;YAEhF,IAAI,GAAG,CAAC,SAAS,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,SAAS,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/D,OAAO,CAAC,KAAK,CAAC,mCAAmC,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,OAAO,sBAAsB,GAAG,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;gBACvI,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;gBAChB,SAAS;YACX,CAAC;YAED,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReviewConfig } from "../../config/types.js";
|
|
2
|
+
import type { Scope } from "../../types/review.js";
|
|
3
|
+
/** Output of the resolver agent — what to review and how. */
|
|
4
|
+
export interface ResolvedInput {
|
|
5
|
+
scope: Scope;
|
|
6
|
+
files: string[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Translates a natural-language deskcheck request into `{ scope, files }` by
|
|
10
|
+
* running a fresh Claude agent that has filesystem/git tools and an
|
|
11
|
+
* in-process MCP `submit_resolution` tool. The resolver does NOT match
|
|
12
|
+
* criteria, partition, or review — those happen downstream identically to
|
|
13
|
+
* the deterministic `deskcheck diff` path.
|
|
14
|
+
*
|
|
15
|
+
* If the caller already supplied an explicit scope override (`--scope`),
|
|
16
|
+
* pass it via `scopeOverride`. The agent will then only resolve the file
|
|
17
|
+
* list; the override wins regardless of what the agent infers.
|
|
18
|
+
*/
|
|
19
|
+
export declare class ReviewInputResolverService {
|
|
20
|
+
private readonly config;
|
|
21
|
+
private readonly projectRoot;
|
|
22
|
+
constructor(config: ReviewConfig, projectRoot: string);
|
|
23
|
+
resolve(input: string, scopeOverride?: Scope): Promise<ResolvedInput>;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=ReviewInputResolverService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReviewInputResolverService.d.ts","sourceRoot":"","sources":["../../../src/services/review/ReviewInputResolverService.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAMnD,6DAA6D;AAC7D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAMD;;;;;;;;;;GAUG;AACH,qBAAa,0BAA0B;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAEzB,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM;IAK/C,OAAO,CACX,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,KAAK,GACpB,OAAO,CAAC,aAAa,CAAC;CAkG1B"}
|
|
@@ -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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"}
|
|
@@ -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,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;
|
|
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
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
|
// =============================================================================
|
|
@@ -65,27 +65,28 @@ export class ReviewOrchestratorService {
|
|
|
65
65
|
});
|
|
66
66
|
let taskUsage = null;
|
|
67
67
|
try {
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
88
|
-
|
|
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
91
|
storage.completeTask(planId, task.task_id, issues, taskUsage);
|
|
91
92
|
completedCount++;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReviewOrchestratorService.js","sourceRoot":"","sources":["../../../src/services/review/ReviewOrchestratorService.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,
|
|
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"}
|