@nk070281sjv/cli 2.3.24 → 2.3.25
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/dist/index.js +103 -2
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -30775,7 +30775,7 @@ ${hint}
|
|
|
30775
30775
|
}
|
|
30776
30776
|
|
|
30777
30777
|
// src/lib/version.ts
|
|
30778
|
-
var CLI_VERSION = true ? "2.3.
|
|
30778
|
+
var CLI_VERSION = true ? "2.3.25" : createRequire(import.meta.url)("../../package.json").version;
|
|
30779
30779
|
|
|
30780
30780
|
// src/lib/deps.ts
|
|
30781
30781
|
init_src();
|
|
@@ -38482,10 +38482,62 @@ async function runReviewerPhase(input) {
|
|
|
38482
38482
|
`${reviewer.type}-${reviewer.instance}`,
|
|
38483
38483
|
reviewer
|
|
38484
38484
|
]));
|
|
38485
|
+
const reviewerArtifacts = /* @__PURE__ */ new Map();
|
|
38485
38486
|
for (const result of sortResults(results, requests)) {
|
|
38486
38487
|
const reviewer = byId.get(result.id);
|
|
38487
38488
|
if (!reviewer) continue;
|
|
38488
|
-
|
|
38489
|
+
const validated = normalizeReviewerArtifact(processOutput(result));
|
|
38490
|
+
if (!validated.ok) {
|
|
38491
|
+
const failedResult = { ...result, exitCode: 1 };
|
|
38492
|
+
await writeRoundArtifact(
|
|
38493
|
+
input.context.roundDir,
|
|
38494
|
+
"failure-summary.json",
|
|
38495
|
+
JSON.stringify(
|
|
38496
|
+
{
|
|
38497
|
+
schema_version: 1,
|
|
38498
|
+
phase: "reviews",
|
|
38499
|
+
failed_id: result.id,
|
|
38500
|
+
exit_code: 1,
|
|
38501
|
+
model: requests.find((request) => request.id === result.id)?.model,
|
|
38502
|
+
prompt_path: requests.find((request) => request.id === result.id)?.promptPath,
|
|
38503
|
+
cwd: requests.find((request) => request.id === result.id)?.cwd,
|
|
38504
|
+
diagnostic: {
|
|
38505
|
+
summary: "Reviewer output did not contain a valid compact ocr-json artifact. OCR refused to pass prose, plan-mode text, or malformed JSON into aggregation.",
|
|
38506
|
+
hint: "Inspect the saved reviewer prompt and process log. The reviewer must return exactly one fenced ```ocr-json block with structured findings.",
|
|
38507
|
+
stdout_excerpt: excerpt(processOutput(result))
|
|
38508
|
+
},
|
|
38509
|
+
stderr: result.stderr,
|
|
38510
|
+
stdout_excerpt: excerpt(result.stdout),
|
|
38511
|
+
validation_errors: validated.errors,
|
|
38512
|
+
results: sortResults(
|
|
38513
|
+
results.map((item) => item.id === result.id ? failedResult : item),
|
|
38514
|
+
requests
|
|
38515
|
+
).map((item) => ({
|
|
38516
|
+
id: item.id,
|
|
38517
|
+
exit_code: item.exitCode
|
|
38518
|
+
}))
|
|
38519
|
+
},
|
|
38520
|
+
null,
|
|
38521
|
+
2
|
|
38522
|
+
)
|
|
38523
|
+
);
|
|
38524
|
+
return {
|
|
38525
|
+
ok: false,
|
|
38526
|
+
failedId: result.id,
|
|
38527
|
+
errors: [
|
|
38528
|
+
`Reviewer ${result.id} produced invalid ocr-json output.`,
|
|
38529
|
+
...validated.errors
|
|
38530
|
+
],
|
|
38531
|
+
results: sortResults(
|
|
38532
|
+
results.map((item) => item.id === result.id ? failedResult : item),
|
|
38533
|
+
requests
|
|
38534
|
+
)
|
|
38535
|
+
};
|
|
38536
|
+
}
|
|
38537
|
+
reviewerArtifacts.set(reviewer.reviewPath, validated.artifact);
|
|
38538
|
+
}
|
|
38539
|
+
for (const [reviewPath, artifact] of reviewerArtifacts) {
|
|
38540
|
+
await writeRoundArtifact(input.context.roundDir, reviewPath, artifact);
|
|
38489
38541
|
}
|
|
38490
38542
|
return { ok: true, results: sortResults(results, requests) };
|
|
38491
38543
|
}
|
|
@@ -38956,6 +39008,55 @@ function readStartedAt(path2) {
|
|
|
38956
39008
|
function processOutput(result) {
|
|
38957
39009
|
return result.outputText ?? result.stdout;
|
|
38958
39010
|
}
|
|
39011
|
+
function normalizeReviewerArtifact(markdown) {
|
|
39012
|
+
const extracted = extractOcrJsonBlock(markdown);
|
|
39013
|
+
if (!extracted.ok) return extracted;
|
|
39014
|
+
const validationErrors = validateReviewerJson(extracted.value);
|
|
39015
|
+
if (validationErrors.length > 0) return { ok: false, errors: validationErrors };
|
|
39016
|
+
const fence = extractOcrJsonFence(markdown);
|
|
39017
|
+
if (!fence) return { ok: false, errors: ["Expected exactly one fenced ```ocr-json block."] };
|
|
39018
|
+
return { ok: true, artifact: `${fence}
|
|
39019
|
+
` };
|
|
39020
|
+
}
|
|
39021
|
+
function validateReviewerJson(value) {
|
|
39022
|
+
const errors = [];
|
|
39023
|
+
if (!isRecord2(value)) {
|
|
39024
|
+
return ["Reviewer ocr-json must be an object."];
|
|
39025
|
+
}
|
|
39026
|
+
if (!Array.isArray(value.findings)) {
|
|
39027
|
+
errors.push("Reviewer ocr-json findings must be an array.");
|
|
39028
|
+
return errors;
|
|
39029
|
+
}
|
|
39030
|
+
if (value.findings.length > 5) {
|
|
39031
|
+
errors.push("Reviewer ocr-json findings must contain at most 5 items.");
|
|
39032
|
+
}
|
|
39033
|
+
value.findings.forEach((finding, index) => {
|
|
39034
|
+
if (!isRecord2(finding)) {
|
|
39035
|
+
errors.push(`findings[${index}] must be an object.`);
|
|
39036
|
+
return;
|
|
39037
|
+
}
|
|
39038
|
+
for (const field of ["sev", "title", "claim", "evidence", "impact", "confidence"]) {
|
|
39039
|
+
if (typeof finding[field] !== "string" || !finding[field].trim()) {
|
|
39040
|
+
errors.push(`findings[${index}].${field} must be a non-empty string.`);
|
|
39041
|
+
}
|
|
39042
|
+
}
|
|
39043
|
+
if (!["critical", "high", "medium", "low"].includes(String(finding.sev))) {
|
|
39044
|
+
errors.push(`findings[${index}].sev must be one of critical, high, medium, low.`);
|
|
39045
|
+
}
|
|
39046
|
+
if (!["high", "medium", "low"].includes(String(finding.confidence))) {
|
|
39047
|
+
errors.push(`findings[${index}].confidence must be one of high, medium, low.`);
|
|
39048
|
+
}
|
|
39049
|
+
if (!Array.isArray(finding.files) || finding.files.length === 0) {
|
|
39050
|
+
errors.push(`findings[${index}].files must be a non-empty array.`);
|
|
39051
|
+
} else if (finding.files.some((file) => typeof file !== "string" || !file.trim())) {
|
|
39052
|
+
errors.push(`findings[${index}].files must contain only non-empty strings.`);
|
|
39053
|
+
}
|
|
39054
|
+
if ("fix" in finding) {
|
|
39055
|
+
errors.push(`findings[${index}].fix is not allowed in reviewer output.`);
|
|
39056
|
+
}
|
|
39057
|
+
});
|
|
39058
|
+
return errors;
|
|
39059
|
+
}
|
|
38959
39060
|
function normalizeProcessResult(result) {
|
|
38960
39061
|
if (!hasOpenCodeLengthFinish(result.ndjsonEvents)) return result;
|
|
38961
39062
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nk070281sjv/cli",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.25",
|
|
4
4
|
"description": "CLI for Open Code Review - Multi-environment setup and progress tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@inquirer/prompts": "^7.2.0",
|
|
40
|
-
"@nk070281sjv/agents": "2.3.
|
|
40
|
+
"@nk070281sjv/agents": "2.3.25",
|
|
41
41
|
"chalk": "^5.4.1",
|
|
42
42
|
"chokidar": "^4.0.3",
|
|
43
43
|
"commander": "^13.0.0",
|