@nk070281sjv/cli 2.3.27 → 2.3.30
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 +143 -80
- 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.30" : createRequire(import.meta.url)("../../package.json").version;
|
|
30779
30779
|
|
|
30780
30780
|
// src/lib/deps.ts
|
|
30781
30781
|
init_src();
|
|
@@ -35280,6 +35280,7 @@ function validateReviewer(value, path2, errors) {
|
|
|
35280
35280
|
stringValue(obj.model, `${path2}.model`, errors);
|
|
35281
35281
|
stringValue(obj.promptPath, `${path2}.promptPath`, errors);
|
|
35282
35282
|
stringValue(obj.reviewPath, `${path2}.reviewPath`, errors);
|
|
35283
|
+
stringValue(obj.promptId, `${path2}.promptId`, errors);
|
|
35283
35284
|
}
|
|
35284
35285
|
function validatePipelineArtifactRef(value, path2, errors) {
|
|
35285
35286
|
const obj = object(value, path2, errors);
|
|
@@ -37417,6 +37418,7 @@ function extractVendorSessionId(events) {
|
|
|
37417
37418
|
|
|
37418
37419
|
// src/lib/agent-orchestrator/review-orchestrator.ts
|
|
37419
37420
|
import { existsSync as existsSync22, statSync as statSync5, readFileSync as readFileSync16 } from "node:fs";
|
|
37421
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
37420
37422
|
import { join as join27 } from "node:path";
|
|
37421
37423
|
|
|
37422
37424
|
// src/lib/agent-orchestrator/artifact-writer.ts
|
|
@@ -37957,6 +37959,7 @@ function isRecord(value) {
|
|
|
37957
37959
|
|
|
37958
37960
|
// src/lib/agent-orchestrator/prompt-writer.ts
|
|
37959
37961
|
import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
|
|
37962
|
+
import { createHash } from "node:crypto";
|
|
37960
37963
|
import { dirname as dirname11, join as join26, relative as relative3 } from "node:path";
|
|
37961
37964
|
async function writePromptSnapshots(input) {
|
|
37962
37965
|
const promptsDir = join26(input.context.roundDir, "prompts");
|
|
@@ -37973,9 +37976,10 @@ async function writePromptSnapshots(input) {
|
|
|
37973
37976
|
}
|
|
37974
37977
|
const promptPath = `prompts/${reviewer.persona}-${reviewer.instance_index}.md`;
|
|
37975
37978
|
const reviewPath = `reviews/${reviewer.persona}-${reviewer.instance_index}.md`;
|
|
37979
|
+
const promptId = reviewerPromptId(input.context, reviewer, promptPath);
|
|
37976
37980
|
await writeFile3(
|
|
37977
37981
|
join26(input.context.roundDir, promptPath),
|
|
37978
|
-
await reviewerPrompt(input.context, reviewer, promptPath, reviewPath, sharedReviewerPrefix),
|
|
37982
|
+
await reviewerPrompt(input.context, reviewer, promptPath, reviewPath, sharedReviewerPrefix, promptId),
|
|
37979
37983
|
"utf-8"
|
|
37980
37984
|
);
|
|
37981
37985
|
reviewers.push({
|
|
@@ -37983,7 +37987,8 @@ async function writePromptSnapshots(input) {
|
|
|
37983
37987
|
instance: reviewer.instance_index,
|
|
37984
37988
|
model: reviewer.model,
|
|
37985
37989
|
promptPath,
|
|
37986
|
-
reviewPath
|
|
37990
|
+
reviewPath,
|
|
37991
|
+
promptId
|
|
37987
37992
|
});
|
|
37988
37993
|
}
|
|
37989
37994
|
const pipeline = {
|
|
@@ -38017,7 +38022,7 @@ async function writePipelinePrompt(input, stage, artifactPath) {
|
|
|
38017
38022
|
artifactPath
|
|
38018
38023
|
};
|
|
38019
38024
|
}
|
|
38020
|
-
async function reviewerPrompt(context, reviewer, promptPath, reviewPath, sharedPrefix) {
|
|
38025
|
+
async function reviewerPrompt(context, reviewer, promptPath, reviewPath, sharedPrefix, promptId) {
|
|
38021
38026
|
const personaPath = reviewerPersonaPath(context, reviewer);
|
|
38022
38027
|
const personaContent = await readTextFile(personaPath);
|
|
38023
38028
|
return [
|
|
@@ -38027,6 +38032,7 @@ async function reviewerPrompt(context, reviewer, promptPath, reviewPath, sharedP
|
|
|
38027
38032
|
`Reviewer id: ${reviewer.persona}-${reviewer.instance_index}`,
|
|
38028
38033
|
`Agent identity: ${reviewer.name}`,
|
|
38029
38034
|
`Model alias and resolved model: ${reviewer.model}`,
|
|
38035
|
+
`OCR prompt id: ${promptId}`,
|
|
38030
38036
|
"",
|
|
38031
38037
|
"## Reviewer Persona",
|
|
38032
38038
|
"",
|
|
@@ -38041,8 +38047,9 @@ async function reviewerPrompt(context, reviewer, promptPath, reviewPath, sharedP
|
|
|
38041
38047
|
"- Persona focus areas are for detecting issues only; this output contract overrides any persona request to propose fixes or broad guidance.",
|
|
38042
38048
|
"",
|
|
38043
38049
|
"Output contract:",
|
|
38044
|
-
`- Return review
|
|
38045
|
-
"- Return
|
|
38050
|
+
`- Return the review artifact through stdout for ${reviewPath}.`,
|
|
38051
|
+
"- Return exactly one fenced ```ocr-json block and no prose outside it.",
|
|
38052
|
+
`- The ocr-json block must include top-level "prompt_id": "${promptId}".`,
|
|
38046
38053
|
"- Include maximum 5 findings, sorted by severity and production impact.",
|
|
38047
38054
|
"- No introductions, no progress narration, no endpoint tables, no code snippets, no broad summaries.",
|
|
38048
38055
|
"- Include critical, high, and medium findings. Include low only when it has concrete runtime/user impact. Exclude info/style/theoretical-only items.",
|
|
@@ -38052,10 +38059,11 @@ async function reviewerPrompt(context, reviewer, promptPath, reviewPath, sharedP
|
|
|
38052
38059
|
"- Do not claim skipped agents ran.",
|
|
38053
38060
|
"",
|
|
38054
38061
|
"Required ocr-json schema:",
|
|
38055
|
-
"- Output exactly this compact JSON shape inside
|
|
38062
|
+
"- Output exactly this compact JSON shape inside a fenced ```ocr-json block:",
|
|
38056
38063
|
"",
|
|
38057
|
-
"```json",
|
|
38064
|
+
"```ocr-json",
|
|
38058
38065
|
"{",
|
|
38066
|
+
` "prompt_id": "${promptId}",`,
|
|
38059
38067
|
' "findings": [',
|
|
38060
38068
|
" {",
|
|
38061
38069
|
' "sev": "high",',
|
|
@@ -38081,6 +38089,18 @@ async function reviewerPrompt(context, reviewer, promptPath, reviewPath, sharedP
|
|
|
38081
38089
|
""
|
|
38082
38090
|
].join("\n");
|
|
38083
38091
|
}
|
|
38092
|
+
function reviewerPromptId(context, reviewer, promptPath) {
|
|
38093
|
+
const input = [
|
|
38094
|
+
context.sessionId,
|
|
38095
|
+
String(context.round),
|
|
38096
|
+
reviewer.persona,
|
|
38097
|
+
String(reviewer.instance_index),
|
|
38098
|
+
reviewer.name,
|
|
38099
|
+
reviewer.model,
|
|
38100
|
+
promptPath
|
|
38101
|
+
].join("\n");
|
|
38102
|
+
return `ocr-prompt:${createHash("sha256").update(input).digest("hex").slice(0, 24)}`;
|
|
38103
|
+
}
|
|
38084
38104
|
async function reviewerSharedPrefix(context) {
|
|
38085
38105
|
const sections = [
|
|
38086
38106
|
"# OCR Reviewer Shared Context",
|
|
@@ -38184,7 +38204,7 @@ function pipelinePrompt(context, stage, agent, promptPath, artifactPath) {
|
|
|
38184
38204
|
"- Do not translate JSON field names, enum values, file paths, code identifiers, stack traces, commands, or model names.",
|
|
38185
38205
|
"- Do not add new findings, remove findings, change severity/category/verdict, or change counts."
|
|
38186
38206
|
] : stage === "aggregation" ? [
|
|
38187
|
-
"- Return
|
|
38207
|
+
"- Return exactly one fenced ```ocr-json block and no prose outside it.",
|
|
38188
38208
|
"- Keep the output compact: at most 8 findings and at most 12 dropped entries.",
|
|
38189
38209
|
"- Do not include code snippets, long quotes, markdown tables, or reviewer narrative.",
|
|
38190
38210
|
"- Read the original reviewer files, but aggregate only their structured findings and concrete evidence."
|
|
@@ -38219,7 +38239,7 @@ function schemaHint(stage) {
|
|
|
38219
38239
|
" - Keep low only when duplicated by 2+ reviewers or when it has concrete production/runtime impact.",
|
|
38220
38240
|
" - Drop info, style, theoretical-only, and future-extensibility-only items.",
|
|
38221
38241
|
"",
|
|
38222
|
-
"```json",
|
|
38242
|
+
"```ocr-json",
|
|
38223
38243
|
"{",
|
|
38224
38244
|
' "findings": [',
|
|
38225
38245
|
" {",
|
|
@@ -38261,7 +38281,7 @@ function schemaHint(stage) {
|
|
|
38261
38281
|
"- Verify claims against the actual code before confirming. Do not trust reviewer text without code evidence.",
|
|
38262
38282
|
"- Put every aggregation finding into exactly one of `confirmed`, `downgraded`, or `rejected`.",
|
|
38263
38283
|
"",
|
|
38264
|
-
"```json",
|
|
38284
|
+
"```ocr-json",
|
|
38265
38285
|
"{",
|
|
38266
38286
|
' "confirmed": [',
|
|
38267
38287
|
" {",
|
|
@@ -38303,7 +38323,7 @@ function schemaHint(stage) {
|
|
|
38303
38323
|
"- Write developer-facing findings from validation results, not from unvalidated reviewer claims.",
|
|
38304
38324
|
"- Include only confirmed and downgraded issues that a developer can act on.",
|
|
38305
38325
|
"",
|
|
38306
|
-
"```json",
|
|
38326
|
+
"```ocr-json",
|
|
38307
38327
|
"{",
|
|
38308
38328
|
' "verdict": "REQUEST CHANGES",',
|
|
38309
38329
|
' "synthesis_counts": {',
|
|
@@ -38432,7 +38452,48 @@ async function runReviewerPhase(input) {
|
|
|
38432
38452
|
} finally {
|
|
38433
38453
|
clearInterval(progressTimer);
|
|
38434
38454
|
}
|
|
38435
|
-
const
|
|
38455
|
+
const byId = new Map(input.resolvedTeam.reviewers.map((reviewer) => [
|
|
38456
|
+
`${reviewer.type}-${reviewer.instance}`,
|
|
38457
|
+
reviewer
|
|
38458
|
+
]));
|
|
38459
|
+
const sortedResults = sortResults(results, requests);
|
|
38460
|
+
const reviewerArtifacts = /* @__PURE__ */ new Map();
|
|
38461
|
+
const artifactStatuses = [];
|
|
38462
|
+
let failed = sortedResults.find((result) => result.exitCode !== 0);
|
|
38463
|
+
let validationFailure;
|
|
38464
|
+
for (const result of sortedResults) {
|
|
38465
|
+
const reviewer = byId.get(result.id);
|
|
38466
|
+
if (!reviewer) continue;
|
|
38467
|
+
if (result.exitCode !== 0) {
|
|
38468
|
+
artifactStatuses.push({
|
|
38469
|
+
id: result.id,
|
|
38470
|
+
exit_code: result.exitCode,
|
|
38471
|
+
artifact_written: false
|
|
38472
|
+
});
|
|
38473
|
+
continue;
|
|
38474
|
+
}
|
|
38475
|
+
const validated = normalizeReviewerArtifact(processOutput(result), reviewer.promptId);
|
|
38476
|
+
if (!validated.ok) {
|
|
38477
|
+
validationFailure ??= { result, errors: validated.errors };
|
|
38478
|
+
artifactStatuses.push({
|
|
38479
|
+
id: result.id,
|
|
38480
|
+
exit_code: 1,
|
|
38481
|
+
artifact_written: false,
|
|
38482
|
+
validation_errors: validated.errors
|
|
38483
|
+
});
|
|
38484
|
+
continue;
|
|
38485
|
+
}
|
|
38486
|
+
reviewerArtifacts.set(reviewer.reviewPath, validated.artifact);
|
|
38487
|
+
artifactStatuses.push({
|
|
38488
|
+
id: result.id,
|
|
38489
|
+
exit_code: result.exitCode,
|
|
38490
|
+
artifact_written: true,
|
|
38491
|
+
artifact_path: join27(input.context.roundDir, reviewer.reviewPath)
|
|
38492
|
+
});
|
|
38493
|
+
}
|
|
38494
|
+
for (const [reviewPath, artifact] of reviewerArtifacts) {
|
|
38495
|
+
await writeRoundArtifact(input.context.roundDir, reviewPath, artifact);
|
|
38496
|
+
}
|
|
38436
38497
|
if (failed) {
|
|
38437
38498
|
const failedRequest = requests.find((request) => request.id === failed.id);
|
|
38438
38499
|
const diagnostic = buildFailureDiagnostic(failed, failedRequest);
|
|
@@ -38451,9 +38512,11 @@ async function runReviewerPhase(input) {
|
|
|
38451
38512
|
diagnostic,
|
|
38452
38513
|
stderr: failed.stderr,
|
|
38453
38514
|
stdout_excerpt: excerpt(failed.stdout),
|
|
38454
|
-
|
|
38455
|
-
|
|
38456
|
-
|
|
38515
|
+
artifact_statuses: artifactStatuses,
|
|
38516
|
+
results: artifactStatuses.map((status) => ({
|
|
38517
|
+
id: status.id,
|
|
38518
|
+
exit_code: status.exit_code,
|
|
38519
|
+
artifact_written: status.artifact_written
|
|
38457
38520
|
}))
|
|
38458
38521
|
},
|
|
38459
38522
|
null,
|
|
@@ -38474,71 +38537,54 @@ async function runReviewerPhase(input) {
|
|
|
38474
38537
|
...diagnostic.stderr_excerpt ? [`stderr: ${diagnostic.stderr_excerpt}`] : [],
|
|
38475
38538
|
...diagnostic.stdout_excerpt ? [`stdout: ${diagnostic.stdout_excerpt}`] : []
|
|
38476
38539
|
],
|
|
38477
|
-
results:
|
|
38540
|
+
results: sortedResults
|
|
38478
38541
|
};
|
|
38479
38542
|
}
|
|
38480
|
-
|
|
38481
|
-
|
|
38482
|
-
|
|
38483
|
-
|
|
38484
|
-
|
|
38485
|
-
|
|
38486
|
-
|
|
38487
|
-
|
|
38488
|
-
|
|
38489
|
-
|
|
38490
|
-
|
|
38491
|
-
|
|
38492
|
-
|
|
38493
|
-
|
|
38494
|
-
|
|
38495
|
-
{
|
|
38496
|
-
|
|
38497
|
-
|
|
38498
|
-
|
|
38499
|
-
exit_code: 1,
|
|
38500
|
-
model: requests.find((request) => request.id === result.id)?.model,
|
|
38501
|
-
prompt_path: requests.find((request) => request.id === result.id)?.promptPath,
|
|
38502
|
-
cwd: requests.find((request) => request.id === result.id)?.cwd,
|
|
38503
|
-
diagnostic: {
|
|
38504
|
-
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.",
|
|
38505
|
-
hint: "Inspect the saved reviewer prompt and process log. The reviewer must return exactly one fenced ```ocr-json block with structured findings.",
|
|
38506
|
-
stdout_excerpt: excerpt(processOutput(result))
|
|
38507
|
-
},
|
|
38508
|
-
stderr: result.stderr,
|
|
38509
|
-
stdout_excerpt: excerpt(result.stdout),
|
|
38510
|
-
validation_errors: validated.errors,
|
|
38511
|
-
results: sortResults(
|
|
38512
|
-
results.map((item) => item.id === result.id ? failedResult : item),
|
|
38513
|
-
requests
|
|
38514
|
-
).map((item) => ({
|
|
38515
|
-
id: item.id,
|
|
38516
|
-
exit_code: item.exitCode
|
|
38517
|
-
}))
|
|
38543
|
+
if (validationFailure) {
|
|
38544
|
+
const failedResult = { ...validationFailure.result, exitCode: 1 };
|
|
38545
|
+
const failureResults = sortedResults.map((item) => item.id === failedResult.id ? failedResult : item);
|
|
38546
|
+
await writeRoundArtifact(
|
|
38547
|
+
input.context.roundDir,
|
|
38548
|
+
"failure-summary.json",
|
|
38549
|
+
JSON.stringify(
|
|
38550
|
+
{
|
|
38551
|
+
schema_version: 1,
|
|
38552
|
+
phase: "reviews",
|
|
38553
|
+
failed_id: validationFailure.result.id,
|
|
38554
|
+
exit_code: 1,
|
|
38555
|
+
model: requests.find((request) => request.id === validationFailure.result.id)?.model,
|
|
38556
|
+
prompt_path: requests.find((request) => request.id === validationFailure.result.id)?.promptPath,
|
|
38557
|
+
cwd: requests.find((request) => request.id === validationFailure.result.id)?.cwd,
|
|
38558
|
+
diagnostic: {
|
|
38559
|
+
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.",
|
|
38560
|
+
hint: "Inspect the saved reviewer prompt and process log. The reviewer must return exactly one fenced ```ocr-json block with structured findings.",
|
|
38561
|
+
stdout_excerpt: excerpt(processOutput(validationFailure.result))
|
|
38518
38562
|
},
|
|
38519
|
-
|
|
38520
|
-
|
|
38521
|
-
|
|
38522
|
-
|
|
38523
|
-
|
|
38524
|
-
|
|
38525
|
-
|
|
38526
|
-
|
|
38527
|
-
|
|
38528
|
-
|
|
38529
|
-
|
|
38530
|
-
|
|
38531
|
-
|
|
38532
|
-
|
|
38533
|
-
|
|
38534
|
-
|
|
38535
|
-
|
|
38536
|
-
|
|
38537
|
-
|
|
38538
|
-
|
|
38539
|
-
|
|
38563
|
+
stderr: validationFailure.result.stderr,
|
|
38564
|
+
stdout_excerpt: excerpt(validationFailure.result.stdout),
|
|
38565
|
+
validation_errors: validationFailure.errors,
|
|
38566
|
+
artifact_statuses: artifactStatuses,
|
|
38567
|
+
results: artifactStatuses.map((status) => ({
|
|
38568
|
+
id: status.id,
|
|
38569
|
+
exit_code: status.exit_code,
|
|
38570
|
+
artifact_written: status.artifact_written
|
|
38571
|
+
}))
|
|
38572
|
+
},
|
|
38573
|
+
null,
|
|
38574
|
+
2
|
|
38575
|
+
)
|
|
38576
|
+
);
|
|
38577
|
+
return {
|
|
38578
|
+
ok: false,
|
|
38579
|
+
failedId: validationFailure.result.id,
|
|
38580
|
+
errors: [
|
|
38581
|
+
`Reviewer ${validationFailure.result.id} produced invalid ocr-json output.`,
|
|
38582
|
+
...validationFailure.errors
|
|
38583
|
+
],
|
|
38584
|
+
results: failureResults
|
|
38585
|
+
};
|
|
38540
38586
|
}
|
|
38541
|
-
return { ok: true, results:
|
|
38587
|
+
return { ok: true, results: sortedResults };
|
|
38542
38588
|
}
|
|
38543
38589
|
async function runOpenCodeProcessAgentReview(input) {
|
|
38544
38590
|
const runner = input.runner ?? new OpenCodeProcessRunner();
|
|
@@ -38939,6 +38985,7 @@ function isNonEmptyFile(path2) {
|
|
|
38939
38985
|
}
|
|
38940
38986
|
async function writeProcessStartLog(roundDir, request) {
|
|
38941
38987
|
const metaPath = `process-logs/${request.id}.meta.json`;
|
|
38988
|
+
const promptMeta = readPromptMeta(request.promptPath);
|
|
38942
38989
|
await writeRoundArtifact(
|
|
38943
38990
|
roundDir,
|
|
38944
38991
|
metaPath,
|
|
@@ -38949,6 +38996,7 @@ async function writeProcessStartLog(roundDir, request) {
|
|
|
38949
38996
|
phase: request.phase,
|
|
38950
38997
|
model: request.model,
|
|
38951
38998
|
prompt_path: request.promptPath,
|
|
38999
|
+
...promptMeta,
|
|
38952
39000
|
status: "running",
|
|
38953
39001
|
started_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
38954
39002
|
},
|
|
@@ -38966,6 +39014,7 @@ async function writeProcessLogs(roundDir, request, result) {
|
|
|
38966
39014
|
const absoluteMetaPath = join27(roundDir, metaPath);
|
|
38967
39015
|
const startedAt = readStartedAt(absoluteMetaPath) ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
38968
39016
|
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
39017
|
+
const promptMeta = readPromptMeta(request.promptPath);
|
|
38969
39018
|
await writeRoundArtifact(roundDir, stdoutPath, result.stdout);
|
|
38970
39019
|
await writeRoundArtifact(roundDir, stderrPath, result.stderr);
|
|
38971
39020
|
await writeRoundArtifact(
|
|
@@ -38978,6 +39027,7 @@ async function writeProcessLogs(roundDir, request, result) {
|
|
|
38978
39027
|
phase: request.phase,
|
|
38979
39028
|
model: request.model,
|
|
38980
39029
|
prompt_path: request.promptPath,
|
|
39030
|
+
...promptMeta,
|
|
38981
39031
|
status: result.exitCode === 0 ? "completed" : "failed",
|
|
38982
39032
|
started_at: startedAt,
|
|
38983
39033
|
completed_at: completedAt,
|
|
@@ -38994,6 +39044,16 @@ async function writeProcessLogs(roundDir, request, result) {
|
|
|
38994
39044
|
);
|
|
38995
39045
|
return { stdout: stdoutPath, stderr: stderrPath, meta: metaPath };
|
|
38996
39046
|
}
|
|
39047
|
+
function readPromptMeta(promptPath) {
|
|
39048
|
+
if (!existsSync22(promptPath)) return {};
|
|
39049
|
+
const prompt = readFileSync16(promptPath, "utf-8");
|
|
39050
|
+
const bytes = Buffer.byteLength(prompt, "utf-8");
|
|
39051
|
+
return {
|
|
39052
|
+
prompt_sha256: createHash2("sha256").update(prompt).digest("hex"),
|
|
39053
|
+
prompt_bytes: bytes,
|
|
39054
|
+
prompt_delivery: prompt.length <= DEFAULT_PROMPT_ARGV_LIMIT ? "inline" : "file"
|
|
39055
|
+
};
|
|
39056
|
+
}
|
|
38997
39057
|
function readStartedAt(path2) {
|
|
38998
39058
|
if (!existsSync22(path2)) return void 0;
|
|
38999
39059
|
try {
|
|
@@ -39007,21 +39067,24 @@ function readStartedAt(path2) {
|
|
|
39007
39067
|
function processOutput(result) {
|
|
39008
39068
|
return result.outputText ?? result.stdout;
|
|
39009
39069
|
}
|
|
39010
|
-
function normalizeReviewerArtifact(markdown) {
|
|
39070
|
+
function normalizeReviewerArtifact(markdown, expectedPromptId) {
|
|
39011
39071
|
const extracted = extractOcrJsonBlock(markdown);
|
|
39012
39072
|
if (!extracted.ok) return extracted;
|
|
39013
|
-
const validationErrors = validateReviewerJson(extracted.value);
|
|
39073
|
+
const validationErrors = validateReviewerJson(extracted.value, expectedPromptId);
|
|
39014
39074
|
if (validationErrors.length > 0) return { ok: false, errors: validationErrors };
|
|
39015
39075
|
const fence = extractOcrJsonFence(markdown);
|
|
39016
39076
|
if (!fence) return { ok: false, errors: ["Expected exactly one fenced ```ocr-json block."] };
|
|
39017
39077
|
return { ok: true, artifact: `${fence}
|
|
39018
39078
|
` };
|
|
39019
39079
|
}
|
|
39020
|
-
function validateReviewerJson(value) {
|
|
39080
|
+
function validateReviewerJson(value, expectedPromptId) {
|
|
39021
39081
|
const errors = [];
|
|
39022
39082
|
if (!isRecord2(value)) {
|
|
39023
39083
|
return ["Reviewer ocr-json must be an object."];
|
|
39024
39084
|
}
|
|
39085
|
+
if (value.prompt_id !== expectedPromptId) {
|
|
39086
|
+
errors.push(`Reviewer ocr-json prompt_id must equal ${expectedPromptId}.`);
|
|
39087
|
+
}
|
|
39025
39088
|
if (!Array.isArray(value.findings)) {
|
|
39026
39089
|
errors.push("Reviewer ocr-json findings must be an array.");
|
|
39027
39090
|
return errors;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nk070281sjv/cli",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.30",
|
|
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.30",
|
|
41
41
|
"chalk": "^5.4.1",
|
|
42
42
|
"chokidar": "^4.0.3",
|
|
43
43
|
"commander": "^13.0.0",
|