@nk070281sjv/cli 2.3.30 → 2.3.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +98 -42
  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.30" : createRequire(import.meta.url)("../../package.json").version;
30778
+ var CLI_VERSION = true ? "2.3.31" : createRequire(import.meta.url)("../../package.json").version;
30779
30779
 
30780
30780
  // src/lib/deps.ts
30781
30781
  init_src();
@@ -37994,7 +37994,7 @@ async function writePromptSnapshots(input) {
37994
37994
  const pipeline = {
37995
37995
  aggregation: await writePipelinePrompt(input, "aggregation", "aggregation.md"),
37996
37996
  validation: await writePipelinePrompt(input, "validation", "validation.md"),
37997
- synthesis: await writePipelinePrompt(input, "synthesis", "final.md"),
37997
+ synthesis: await writePipelinePrompt(input, "synthesis", "synthesis.md"),
37998
37998
  translation_uk: await writePipelinePrompt(input, "translation_uk", "final.uk.md")
37999
37999
  };
38000
38000
  const resolvedTeam = {
@@ -38199,22 +38199,25 @@ function pipelinePrompt(context, stage, agent, promptPath, artifactPath) {
38199
38199
  "Output contract:",
38200
38200
  `- Return markdown through stdout for ${artifactPath}.`,
38201
38201
  ...stage === "translation_uk" ? [
38202
- "- Translate the complete final review to Ukrainian.",
38203
- "- Preserve markdown structure, headings, bullets, code spans, file paths, line numbers, and the fenced ```ocr-json block exactly as data.",
38204
- "- Do not translate JSON field names, enum values, file paths, code identifiers, stack traces, commands, or model names.",
38202
+ "- Translate the complete human final review to Ukrainian.",
38203
+ "- Return only readable Ukrainian Markdown for a developer.",
38204
+ "- Do not include ```ocr-json, JSON, analysis notes, verification notes, or progress narration.",
38205
+ "- Preserve markdown structure, headings, bullets, code spans, file paths, line numbers, commands, and model names.",
38205
38206
  "- Do not add new findings, remove findings, change severity/category/verdict, or change counts."
38206
38207
  ] : stage === "aggregation" ? [
38207
38208
  "- Return exactly one fenced ```ocr-json block and no prose outside it.",
38208
38209
  "- Keep the output compact: at most 8 findings and at most 12 dropped entries.",
38209
38210
  "- Do not include code snippets, long quotes, markdown tables, or reviewer narrative.",
38210
38211
  "- Read the original reviewer files, but aggregate only their structured findings and concrete evidence."
38211
- ] : ["- Include exactly one fenced ```ocr-json block."],
38212
+ ] : ["- Return exactly one fenced ```ocr-json block and no prose outside it."],
38212
38213
  "- Do not write files directly.",
38213
38214
  "",
38214
38215
  ...stage === "translation_uk" ? [
38215
38216
  "Translation contract:",
38216
- "- The output must be a Ukrainian-language version of final.md.",
38217
- "- Keep the original ocr-json block valid JSON and semantically identical.",
38217
+ "- The output must be a Ukrainian-language version of final.md for humans.",
38218
+ "- Start with the translated top-level heading.",
38219
+ "- Do not wrap the answer in a markdown code fence.",
38220
+ "- Do not include JSON or machine-readable metadata.",
38218
38221
  ""
38219
38222
  ] : ["Required ocr-json schema:", schemaHint(stage), ""],
38220
38223
  "Forbidden behavior:",
@@ -38225,7 +38228,7 @@ function pipelinePrompt(context, stage, agent, promptPath, artifactPath) {
38225
38228
  }
38226
38229
  function schemaHint(stage) {
38227
38230
  if (stage === "translation_uk") {
38228
- return "No new schema. Preserve the existing final.md ocr-json block exactly.";
38231
+ return "No machine schema. Produce human-readable Ukrainian Markdown only.";
38229
38232
  }
38230
38233
  if (stage === "aggregation") {
38231
38234
  return [
@@ -38771,21 +38774,38 @@ async function runPipelineStages(input) {
38771
38774
  results
38772
38775
  };
38773
38776
  }
38774
- await writeRoundArtifact(input.context.roundDir, ref.artifactPath, processOutput(result));
38775
- const validationErrors = validateStageArtifact(input.context.roundDir, stage, ref.artifactPath);
38776
- if (validationErrors.length > 0) {
38777
+ const normalizedArtifact = normalizeStageArtifact(processOutput(result));
38778
+ if (!normalizedArtifact.ok) {
38777
38779
  await journal.endInstance(agentSessionId, {
38778
38780
  exitCode: 1,
38779
- note: validationErrors.join("\n")
38781
+ note: normalizedArtifact.errors.join("\n")
38780
38782
  });
38781
- await writePipelineFailure(input.context.roundDir, stage, result, results, validationErrors);
38783
+ await writePipelineFailure(input.context.roundDir, stage, result, results, normalizedArtifact.errors);
38782
38784
  return {
38783
38785
  ok: false,
38784
38786
  failedStage: stage,
38785
- errors: validationErrors,
38787
+ errors: normalizedArtifact.errors,
38786
38788
  results
38787
38789
  };
38788
38790
  }
38791
+ await writeRoundArtifact(input.context.roundDir, ref.artifactPath, normalizedArtifact.artifact);
38792
+ const validation = validateStageArtifact(input.context.roundDir, stage, ref.artifactPath);
38793
+ if (!validation.ok) {
38794
+ await journal.endInstance(agentSessionId, {
38795
+ exitCode: 1,
38796
+ note: validation.errors.join("\n")
38797
+ });
38798
+ await writePipelineFailure(input.context.roundDir, stage, result, results, validation.errors);
38799
+ return {
38800
+ ok: false,
38801
+ failedStage: stage,
38802
+ errors: validation.errors,
38803
+ results
38804
+ };
38805
+ }
38806
+ if (stage === "synthesis") {
38807
+ await writeRoundArtifact(input.context.roundDir, "final.md", renderHumanFinalReview(validation.value));
38808
+ }
38789
38809
  await journal.endInstance(agentSessionId, { exitCode: 0 });
38790
38810
  }
38791
38811
  return { ok: true, results };
@@ -38880,15 +38900,8 @@ async function runUkrainianTranslation(input) {
38880
38900
  });
38881
38901
  return result;
38882
38902
  }
38883
- const sourceFinalMarkdown = readFileSync16(finalPath, "utf-8");
38884
- const translatedMarkdown = normalizeUkrainianTranslationOutput(
38885
- sourceFinalMarkdown,
38886
- processOutput(result)
38887
- );
38888
- const translationErrors = validateUkrainianTranslationOutput(
38889
- sourceFinalMarkdown,
38890
- translatedMarkdown
38891
- );
38903
+ const translatedMarkdown = normalizeHumanMarkdownOutput(processOutput(result));
38904
+ const translationErrors = validateUkrainianTranslationOutput(translatedMarkdown);
38892
38905
  if (translationErrors.length > 0) {
38893
38906
  await patchProcessMeta(input.context.roundDir, logPaths.meta, {
38894
38907
  status: "failed",
@@ -38908,7 +38921,7 @@ async function runUkrainianTranslation(input) {
38908
38921
  failed_id: request.id,
38909
38922
  exit_code: 1,
38910
38923
  diagnostic: {
38911
- summary: "Ukrainian translation output did not preserve the final review ocr-json block."
38924
+ summary: "Ukrainian translation output was not a readable human Markdown final review."
38912
38925
  },
38913
38926
  validation_errors: translationErrors,
38914
38927
  stdout_excerpt: excerpt(result.stdout)
@@ -38946,23 +38959,21 @@ async function patchProcessMeta(roundDir, metaPath, patch) {
38946
38959
  }
38947
38960
  await writeRoundArtifact(roundDir, metaPath, JSON.stringify({ ...current, ...patch }, null, 2));
38948
38961
  }
38949
- function validateUkrainianTranslationOutput(sourceMarkdown, translatedMarkdown) {
38950
- const sourceJson = extractOcrJsonBlock(sourceMarkdown);
38951
- if (!sourceJson.ok) return sourceJson.errors.map((error) => `source final.md: ${error}`);
38952
- const translatedJson = extractOcrJsonBlock(translatedMarkdown);
38953
- if (!translatedJson.ok) return translatedJson.errors.map((error) => `final.uk.md: ${error}`);
38954
- if (JSON.stringify(sourceJson.value) !== JSON.stringify(translatedJson.value)) {
38955
- return ["final.uk.md ocr-json block must be identical to final.md ocr-json block."];
38962
+ function validateUkrainianTranslationOutput(translatedMarkdown) {
38963
+ const errors = [];
38964
+ if (!translatedMarkdown.trim()) errors.push("final.uk.md must not be empty.");
38965
+ if (/```ocr-json/i.test(translatedMarkdown) || /^\s*[{[]/.test(translatedMarkdown)) {
38966
+ errors.push("final.uk.md must be human Markdown without JSON or ocr-json blocks.");
38967
+ }
38968
+ if (!translatedMarkdown.trimStart().startsWith("#")) {
38969
+ errors.push("final.uk.md must start with a Markdown heading.");
38956
38970
  }
38957
- return [];
38971
+ return errors;
38958
38972
  }
38959
- function normalizeUkrainianTranslationOutput(sourceMarkdown, translatedMarkdown) {
38960
- const sourceBlock = extractOcrJsonFence(sourceMarkdown);
38961
- if (!sourceBlock) return translatedMarkdown;
38962
- const translatedWithoutJson = translatedMarkdown.replace(/```ocr-json[\s\S]*?```/g, "").trimEnd();
38963
- return `${translatedWithoutJson}
38964
-
38965
- ${sourceBlock}
38973
+ function normalizeHumanMarkdownOutput(markdown) {
38974
+ const trimmed = markdown.trim();
38975
+ const fenced3 = trimmed.match(/^```(?:markdown|md)?\s*([\s\S]*?)```$/i);
38976
+ return `${(fenced3?.[1] ?? trimmed).trimEnd()}
38966
38977
  `;
38967
38978
  }
38968
38979
  function extractOcrJsonFence(markdown) {
@@ -38976,9 +38987,54 @@ function sortResults(results, requests) {
38976
38987
  function validateStageArtifact(roundDir, stage, artifactPath) {
38977
38988
  const markdown = readFileSync16(join27(roundDir, artifactPath), "utf-8");
38978
38989
  const extracted = extractOcrJsonBlock(markdown);
38979
- if (!extracted.ok) return extracted.errors;
38990
+ if (!extracted.ok) return extracted;
38980
38991
  const validated = stage === "aggregation" ? validateAggregationJson(extracted.value) : stage === "validation" ? validateValidationJson(extracted.value) : validateSynthesisJson(extracted.value);
38981
- return validated.ok ? [] : validated.errors;
38992
+ return validated;
38993
+ }
38994
+ function normalizeStageArtifact(markdown) {
38995
+ const extracted = extractOcrJsonBlock(markdown);
38996
+ if (!extracted.ok) return extracted;
38997
+ const fence = extractOcrJsonFence(markdown);
38998
+ if (!fence) return { ok: false, errors: ["Expected exactly one fenced ```ocr-json block."] };
38999
+ return { ok: true, artifact: `${fence}
39000
+ ` };
39001
+ }
39002
+ function renderHumanFinalReview(synthesis) {
39003
+ const grouped = {
39004
+ blocker: synthesis.findings.filter((finding) => finding.category === "blocker"),
39005
+ should_fix: synthesis.findings.filter((finding) => finding.category === "should_fix"),
39006
+ suggestion: synthesis.findings.filter((finding) => finding.category === "suggestion"),
39007
+ style: synthesis.findings.filter((finding) => finding.category === "style")
39008
+ };
39009
+ return [
39010
+ "# OCR Final Review",
39011
+ "",
39012
+ `**Verdict:** ${synthesis.verdict}`,
39013
+ "",
39014
+ `**Counts:** ${synthesis.synthesis_counts.blockers} blocker(s), ${synthesis.synthesis_counts.should_fix} should-fix item(s), ${synthesis.synthesis_counts.suggestions} suggestion(s).`,
39015
+ "",
39016
+ ...renderFindingSection("Blockers", grouped.blocker),
39017
+ ...renderFindingSection("Should Fix", grouped.should_fix),
39018
+ ...renderFindingSection("Suggestions", grouped.suggestion),
39019
+ ...renderFindingSection("Style", grouped.style)
39020
+ ].join("\n").trimEnd() + "\n";
39021
+ }
39022
+ function renderFindingSection(title, findings) {
39023
+ if (findings.length === 0) return [`## ${title}`, "", "None.", ""];
39024
+ return [
39025
+ `## ${title}`,
39026
+ "",
39027
+ ...findings.flatMap((finding, index) => [
39028
+ `### ${index + 1}. ${finding.title}`,
39029
+ "",
39030
+ `- **Severity:** ${finding.severity}`,
39031
+ `- **Location:** ${finding.file_path ?? "n/a"}${finding.line_start ? `:${finding.line_start}` : ""}${finding.line_end && finding.line_end !== finding.line_start ? `-${finding.line_end}` : ""}`,
39032
+ `- **Issue:** ${finding.summary}`,
39033
+ ...finding.flagged_by?.length ? [`- **Flagged by:** ${finding.flagged_by.join(", ")}`] : [],
39034
+ ...finding.validation_source ? [`- **Validation:** ${finding.validation_source}`] : [],
39035
+ ""
39036
+ ])
39037
+ ];
38982
39038
  }
38983
39039
  function isNonEmptyFile(path2) {
38984
39040
  return existsSync22(path2) && statSync5(path2).isFile() && statSync5(path2).size > 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nk070281sjv/cli",
3
- "version": "2.3.30",
3
+ "version": "2.3.31",
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.30",
40
+ "@nk070281sjv/agents": "2.3.31",
41
41
  "chalk": "^5.4.1",
42
42
  "chokidar": "^4.0.3",
43
43
  "commander": "^13.0.0",