sales-frontend-gemini-cli 0.4.3 → 0.4.4

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 (41) hide show
  1. package/dist/common/helper.cjs +119 -3
  2. package/dist/common/helper.cjs.map +1 -1
  3. package/dist/common/helper.d.cts +30 -1
  4. package/dist/common/helper.d.ts +30 -1
  5. package/dist/common/helper.js +118 -4
  6. package/dist/common/helper.js.map +1 -1
  7. package/dist/pr-review/claude/claude-commander.cjs +10 -3
  8. package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
  9. package/dist/pr-review/claude/claude-commander.js +10 -3
  10. package/dist/pr-review/claude/claude-commander.js.map +1 -1
  11. package/dist/pr-review/claude/installation-claude.cjs +1 -1
  12. package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
  13. package/dist/pr-review/claude/installation-claude.js +1 -1
  14. package/dist/pr-review/claude/installation-claude.js.map +1 -1
  15. package/dist/pr-review/codex/codex-commander.cjs +14 -4
  16. package/dist/pr-review/codex/codex-commander.cjs.map +1 -1
  17. package/dist/pr-review/codex/codex-commander.d.cts +1 -1
  18. package/dist/pr-review/codex/codex-commander.d.ts +1 -1
  19. package/dist/pr-review/codex/codex-commander.js +14 -4
  20. package/dist/pr-review/codex/codex-commander.js.map +1 -1
  21. package/dist/pr-review/codex/installation-codex.cjs +1 -1
  22. package/dist/pr-review/codex/installation-codex.cjs.map +1 -1
  23. package/dist/pr-review/codex/installation-codex.js +1 -1
  24. package/dist/pr-review/codex/installation-codex.js.map +1 -1
  25. package/dist/pr-review/gemini/gemini-commander.cjs +12 -12
  26. package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
  27. package/dist/pr-review/gemini/gemini-commander.js +12 -12
  28. package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
  29. package/dist/pr-review/gemini/installation-gemini.cjs +1 -1
  30. package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
  31. package/dist/pr-review/gemini/installation-gemini.js +1 -1
  32. package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
  33. package/dist/pr-review/review-one-by-one.cjs +223 -24
  34. package/dist/pr-review/review-one-by-one.cjs.map +1 -1
  35. package/dist/pr-review/review-one-by-one.js +223 -24
  36. package/dist/pr-review/review-one-by-one.js.map +1 -1
  37. package/dist/pr-review/review.cjs +220 -26
  38. package/dist/pr-review/review.cjs.map +1 -1
  39. package/dist/pr-review/review.js +220 -26
  40. package/dist/pr-review/review.js.map +1 -1
  41. package/package.json +1 -1
@@ -279,7 +279,7 @@ function serializeError(error) {
279
279
  }
280
280
  if (error && typeof error === "object") {
281
281
  const errorLike = error;
282
- const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs"];
282
+ const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs", "command"];
283
283
  extraKeys.forEach((key) => {
284
284
  if (errorLike[key] !== void 0) {
285
285
  serialized[key] = errorLike[key];
@@ -385,6 +385,87 @@ ${section.markdown}`).join("\n")}
385
385
  return "";
386
386
  }
387
387
  }
388
+ function getExecutionLogSummary(status, title) {
389
+ if (title) {
390
+ return title;
391
+ }
392
+ switch (status) {
393
+ case "success":
394
+ return "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uC131\uACF5\uC801\uC73C\uB85C \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
395
+ case "failed":
396
+ return "\uB9AC\uBDF0 \uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
397
+ case "partial_failure":
398
+ return "\uB9AC\uBDF0 \uC2E4\uD589\uC740 \uC644\uB8CC\uB418\uC5C8\uC9C0\uB9CC \uC77C\uBD80 \uB2E8\uACC4\uC5D0\uC11C \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
399
+ default:
400
+ return "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uCDE8\uC18C\uB418\uC5C8\uAC70\uB098 \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC5B4 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
401
+ }
402
+ }
403
+ function formatExecutionDuration(startedAt, finishedAt) {
404
+ const durationMs = Math.max(0, finishedAt.getTime() - startedAt.getTime());
405
+ if (durationMs < 1e3) {
406
+ return `${durationMs}ms`;
407
+ }
408
+ const durationSeconds = durationMs / 1e3;
409
+ if (durationSeconds < 60) {
410
+ return `${durationSeconds.toFixed(1)}s`;
411
+ }
412
+ const minutes = Math.floor(durationSeconds / 60);
413
+ const seconds = Math.round(durationSeconds % 60);
414
+ return `${minutes}m ${seconds}s`;
415
+ }
416
+ function writeExecutionLog(options = {}) {
417
+ try {
418
+ const startedAt = options.startedAt ?? /* @__PURE__ */ new Date();
419
+ const finishedAt = options.finishedAt ?? /* @__PURE__ */ new Date();
420
+ const status = options.status ?? "success";
421
+ helperTrace("execution-log:write:start", options.scope || "unknown");
422
+ createReportDirectory();
423
+ const reportPath = getAvailableFilePath(REPORT_DIR, `${getNowString(finishedAt)}-execution-log`, ".md");
424
+ const traceSnapshot = options.traceMessages ?? getTraceMessages();
425
+ const extraSections = options.extraSections || [];
426
+ const serializedError = options.error ? serializeError(options.error) : null;
427
+ const report = `# Execution Log
428
+
429
+ - \uC2DC\uC791 \uC2DC\uAC01: ${getHumanReadableNowString(startedAt)}
430
+ - \uC885\uB8CC \uC2DC\uAC01: ${getHumanReadableNowString(finishedAt)}
431
+ - \uC2E4\uD589 \uC2DC\uAC04: ${formatExecutionDuration(startedAt, finishedAt)}
432
+ - \uC0C1\uD0DC: \`${status}\`
433
+ - Scope: \`${options.scope || "unknown"}\`
434
+ - \uC791\uC5C5 \uACBD\uB85C: \`${process.cwd()}\`
435
+ - \uC2E4\uD589 \uC778\uC790: \`${JSON.stringify(options.args ?? process.argv.slice(2))}\`
436
+ - \uC2E4\uD589 \uD658\uACBD: \`${process.platform} ${process.arch} / Node ${process.version}\`
437
+
438
+ ## Summary
439
+
440
+ ${getExecutionLogSummary(status, options.title)}
441
+ ${serializedError ? `
442
+
443
+ ## Error
444
+
445
+ \`\`\`json
446
+ ${JSON.stringify(serializedError, null, 2)}
447
+ \`\`\`` : ""}
448
+
449
+ ## Trace
450
+
451
+ \`\`\`json
452
+ ${JSON.stringify(traceSnapshot, null, 2)}
453
+ \`\`\`${extraSections.length ? `
454
+ ${extraSections.map((section) => `
455
+ ## ${section.heading}
456
+
457
+ ${section.markdown}`).join("\n")}
458
+ ` : "\n"}
459
+ `;
460
+ fs__default.default.writeFileSync(reportPath, report);
461
+ helperTrace("execution-log:write:done", reportPath);
462
+ return reportPath;
463
+ } catch (writeError) {
464
+ console.error("\u26A0\uFE0F \uC2E4\uD589 \uB85C\uADF8 \uD30C\uC77C \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
465
+ console.error(writeError);
466
+ return "";
467
+ }
468
+ }
388
469
  function exitWithError(message, options = {}) {
389
470
  const reportPath = writeErrorReport(options.error || new Error(message), {
390
471
  ...options,
@@ -788,6 +869,13 @@ var ALLOWED_REASONING_EFFORTS = ["minimal", "low", "medium", "high"];
788
869
  function shellQuote(value) {
789
870
  return `'${value.replace(/'/g, `'\\''`)}'`;
790
871
  }
872
+ function toShellOptionToken(value) {
873
+ const SIMPLE_SHELL_TOKEN_PATTERN = /^[A-Za-z0-9._:/=-]+$/;
874
+ if (SIMPLE_SHELL_TOKEN_PATTERN.test(value)) {
875
+ return value;
876
+ }
877
+ return shellQuote(value);
878
+ }
791
879
  function getArgValue(flag) {
792
880
  const index = args.indexOf(flag);
793
881
  if (index === -1 || !args[index + 1]) {
@@ -867,9 +955,9 @@ function getAliasFallbacks(primaryAlias) {
867
955
  }
868
956
  function buildClaudeExecCommand(options) {
869
957
  const { tempDiffPath: tempDiffPath2, prompt, systemPromptFiles, effort, model, fallbackModel } = options;
870
- const modelOption = model ? `--model ${shellQuote(model)}` : "";
871
- const fallbackOption = model && fallbackModel ? `--fallback-model ${shellQuote(fallbackModel)}` : "";
872
- const effortOption = `--effort ${shellQuote(effort)}`;
958
+ const modelOption = model ? `--model ${toShellOptionToken(model)}` : "";
959
+ const fallbackOption = model && fallbackModel ? `--fallback-model ${toShellOptionToken(fallbackModel)}` : "";
960
+ const effortOption = `--effort ${toShellOptionToken(effort)}`;
873
961
  const appendedPromptFiles = systemPromptFiles.map((path3) => `--append-system-prompt-file ${shellQuote(path3)}`).join(" ");
874
962
  return `cat ${shellQuote(tempDiffPath2)} | claude ${[
875
963
  modelOption,
@@ -994,12 +1082,22 @@ function printNotice2(message) {
994
1082
  console.warn(message);
995
1083
  }
996
1084
  }
1085
+ function normalizeEffort2(level) {
1086
+ if (level === "minimal") {
1087
+ return "low";
1088
+ }
1089
+ return level;
1090
+ }
997
1091
  function resolveReasoningEffort2() {
998
1092
  const customReasoningEffort = getArgValue2("--reasoning-effort");
999
1093
  if (customReasoningEffort) {
1000
1094
  if (ALLOWED_REASONING_EFFORTS2.includes(customReasoningEffort)) {
1001
- trace3("reasoning:custom", customReasoningEffort);
1002
- return customReasoningEffort;
1095
+ const normalized = normalizeEffort2(customReasoningEffort);
1096
+ trace3("reasoning:custom", `${customReasoningEffort} -> ${normalized}`);
1097
+ if (customReasoningEffort === "minimal") {
1098
+ printNotice2("\u26A0\uFE0F Codex\uB294 minimal\uC774 web_search \uB3C4\uAD6C\uC640 \uCDA9\uB3CC\uD560 \uC218 \uC788\uC5B4 low\uB85C \uB9E4\uD551\uD569\uB2C8\uB2E4.");
1099
+ }
1100
+ return normalized;
1003
1101
  }
1004
1102
  printNotice2(
1005
1103
  `\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS2.join(
@@ -1008,8 +1106,8 @@ function resolveReasoningEffort2() {
1008
1106
  );
1009
1107
  }
1010
1108
  if (args2.includes("--flash")) {
1011
- trace3("reasoning:flash-default", "minimal");
1012
- return "minimal";
1109
+ trace3("reasoning:flash-default", "low");
1110
+ return "low";
1013
1111
  }
1014
1112
  if (args2.includes("--review")) {
1015
1113
  trace3("reasoning:review-default", "high");
@@ -1204,7 +1302,7 @@ function buildGeminiFileReferenceSection(files) {
1204
1302
  const existingFiles = files.filter((file) => fs__default.default.existsSync(file.path));
1205
1303
  return {
1206
1304
  count: existingFiles.length,
1207
- lines: existingFiles.map((file) => `- ${file.display}: ${toGeminiFileReference(file.path)}`)
1305
+ items: existingFiles.map((file) => `${file.display} ${toGeminiFileReference(file.path)}`)
1208
1306
  };
1209
1307
  }
1210
1308
  var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
@@ -1223,19 +1321,19 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
1223
1321
  const ruleSection = buildGeminiFileReferenceSection(rules);
1224
1322
  trace5("rules:loaded", `count=${ruleSection.count}`);
1225
1323
  const reviewFormExists = fs__default.default.existsSync(resolvedReviewFormPath);
1226
- const reviewFormLine = reviewFormExists ? `- \uB9AC\uBDF0 \uC591\uC2DD: ${toGeminiFileReference(resolvedReviewFormPath)}` : "- \uB9AC\uBDF0 \uC591\uC2DD: (\uC5C6\uC74C)";
1324
+ const reviewFormText = reviewFormExists ? `\uB9AC\uBDF0 \uC591\uC2DD ${toGeminiFileReference(resolvedReviewFormPath)}` : "\uB9AC\uBDF0 \uC591\uC2DD (\uC5C6\uC74C)";
1227
1325
  trace5("reviewForm:status", reviewFormExists ? "exists" : "missing");
1228
1326
  const reasoningInstruction = getReasoningInstruction(reasoningEffort);
1229
- const prompt = `\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uC21C\uC11C\uB300\uB85C \uC77D\uACE0 \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.
1230
- \uADDC\uCE59 \uD30C\uC77C:
1231
- ${ruleSection.lines.join("\n") || "- (\uC5C6\uC74C)"}
1232
- \uB9AC\uBDF0 \uC591\uC2DD \uD30C\uC77C:
1233
- ${reviewFormLine}
1234
- \uB9AC\uBDF0 \uB300\uC0C1 diff \uD30C\uC77C:
1235
- - \uB9AC\uBDF0 \uB300\uC0C1 diff: ${toGeminiFileReference(resolvedTempDiffPath)}
1236
-
1237
- \uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.
1238
- \uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`;
1327
+ const ruleText = ruleSection.items.join(" ") || "(\uC5C6\uC74C)";
1328
+ const diffText = `\uB9AC\uBDF0 \uB300\uC0C1 diff ${toGeminiFileReference(resolvedTempDiffPath)}`;
1329
+ const prompt = [
1330
+ "\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uC21C\uC11C\uB300\uB85C \uC77D\uACE0 \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.",
1331
+ `\uADDC\uCE59 \uD30C\uC77C: ${ruleText}`,
1332
+ `\uB9AC\uBDF0 \uC591\uC2DD \uD30C\uC77C: ${reviewFormText}`,
1333
+ `\uB9AC\uBDF0 \uB300\uC0C1 diff \uD30C\uC77C: ${diffText}`,
1334
+ "\uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.",
1335
+ `\uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`
1336
+ ].join(" ");
1239
1337
  trace5("prompt:prepared", `length=${prompt.length}`);
1240
1338
  const modelCandidates = toUnique2(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
1241
1339
  trace5("model:candidates", modelCandidates.join(", "));
@@ -1299,6 +1397,7 @@ function checkGeminiCliInstalled() {
1299
1397
  var execAsync = util__default.default.promisify(child_process.exec);
1300
1398
  async function main() {
1301
1399
  const args4 = process.argv.slice(2);
1400
+ const startedAt = /* @__PURE__ */ new Date();
1302
1401
  clearTraceMessages();
1303
1402
  const isTest = isTestMode(args4);
1304
1403
  const trace7 = createTraceLogger("review-one-by-one", args4);
@@ -1307,6 +1406,13 @@ async function main() {
1307
1406
  let savedDiffPath = "";
1308
1407
  let savedReportPath = "";
1309
1408
  let selectedCommitSummary = "";
1409
+ let fileList = [];
1410
+ let executionLogPath = "";
1411
+ let executionStatus = "cancelled";
1412
+ let executionTitle = "\uB9AC\uBDF0 \uC2E4\uD589\uC774 \uCDE8\uC18C\uB418\uC5C8\uAC70\uB098 \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC5B4 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
1413
+ let executionError = null;
1414
+ let exitCode = 0;
1415
+ const fileExecutionLogs = [];
1310
1416
  try {
1311
1417
  trace7("service-selection:start");
1312
1418
  service = await showSelectionAIService();
@@ -1335,22 +1441,24 @@ async function main() {
1335
1441
  trace7("commit-selection:done", `count=${selectedCommits.length}`);
1336
1442
  if (selectedCommits.length === 0) {
1337
1443
  trace7("commit-selection:empty");
1444
+ executionTitle = "\uC120\uD0DD\uB41C \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.";
1338
1445
  console.log("\u2139\uFE0F \uC120\uD0DD\uB41C \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
1339
1446
  deleteTempDiff();
1340
- process.exit(0);
1447
+ return;
1341
1448
  }
1342
1449
  selectedCommitSummary = buildSelectedCommitSummary(selectedCommits);
1343
1450
  trace7("commit-summary:prepared", selectedCommitSummary);
1344
1451
  console.log("\u23F3 \uC120\uD0DD\uD55C \uCEE4\uBC0B\uC758 \uD30C\uC77C \uBAA9\uB85D\uACFC diff\uB97C \uC815\uB9AC\uD558\uB294 \uC911\uC785\uB2C8\uB2E4...");
1345
1452
  trace7("files-command:run");
1346
- const fileList = getSelectedCommitFiles(selectedCommits);
1453
+ fileList = getSelectedCommitFiles(selectedCommits);
1347
1454
  trace7("files-command:done", `fileCount=${fileList.length}`);
1348
1455
  console.log(`\u{1F4C2} \uB9AC\uBDF0 \uB300\uC0C1 \uD30C\uC77C(${fileList.length}\uAC1C): ${formatReviewTargetFiles(fileList)}`);
1349
1456
  if (fileList.length === 0) {
1350
1457
  trace7("empty-file-list:exit");
1458
+ executionTitle = "\uC120\uD0DD\uD55C \uCEE4\uBC0B\uC5D0\uC11C \uB9AC\uBDF0 \uB300\uC0C1 \uD30C\uC77C \uBCC0\uACBD\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.";
1351
1459
  console.log("\u2139\uFE0F \uC120\uD0DD\uD55C \uCEE4\uBC0B\uC5D0\uC11C \uB9AC\uBDF0 \uB300\uC0C1 \uD30C\uC77C \uBCC0\uACBD\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.");
1352
1460
  deleteTempDiff();
1353
- process.exit(0);
1461
+ return;
1354
1462
  }
1355
1463
  trace7("report-dir:create:start");
1356
1464
  createReportDirectory();
@@ -1380,6 +1488,15 @@ async function main() {
1380
1488
  trace7("file-diff:build:done", `${file} | length=${fileDiff.length}`);
1381
1489
  if (!fileDiff.trim()) {
1382
1490
  trace7("file-diff:empty", file);
1491
+ fileExecutionLogs.push({
1492
+ command: null,
1493
+ errorSummary: null,
1494
+ file,
1495
+ index,
1496
+ resultLength: 0,
1497
+ status: "skipped",
1498
+ tempOneFileDiffPath
1499
+ });
1383
1500
  return;
1384
1501
  }
1385
1502
  trace7("file-temp-diff:write:start", tempOneFileDiffPath);
@@ -1422,9 +1539,27 @@ ${result}
1422
1539
  ${command}`);
1423
1540
  trace7("file-test-command:append:done", file);
1424
1541
  }
1542
+ fileExecutionLogs.push({
1543
+ command,
1544
+ errorSummary: null,
1545
+ file,
1546
+ index,
1547
+ resultLength: result.length,
1548
+ status: "success",
1549
+ tempOneFileDiffPath
1550
+ });
1425
1551
  trace7("file-review:end", file);
1426
1552
  } catch (err) {
1427
1553
  trace7("file-review:catch", `${file} | ${getErrorSummary(err)}`);
1554
+ fileExecutionLogs.push({
1555
+ command: command || null,
1556
+ errorSummary: getErrorSummary(err),
1557
+ file,
1558
+ index,
1559
+ resultLength: 0,
1560
+ status: "failed",
1561
+ tempOneFileDiffPath
1562
+ });
1428
1563
  const errorLogPath = writeErrorReport(err, {
1429
1564
  scope: "review-one-by-one:file",
1430
1565
  args: args4,
@@ -1476,6 +1611,15 @@ ${getErrorSummary(err)}
1476
1611
  trace7("parallel-review:await-start");
1477
1612
  await Promise.all(promises);
1478
1613
  trace7("parallel-review:await-done");
1614
+ const failedFileCount = fileExecutionLogs.filter((log) => log.status === "failed").length;
1615
+ const successfulFileCount = fileExecutionLogs.filter((log) => log.status === "success").length;
1616
+ if (failedFileCount > 0) {
1617
+ executionStatus = "partial_failure";
1618
+ executionTitle = `\uD30C\uC77C\uBCC4 \uB9AC\uBDF0 \uC911 \uC77C\uBD80\uAC00 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. (\uC131\uACF5 ${successfulFileCount}\uAC74 / \uC2E4\uD328 ${failedFileCount}\uAC74)`;
1619
+ } else {
1620
+ executionStatus = "success";
1621
+ executionTitle = "\uD30C\uC77C\uBCC4 \uB9AC\uBDF0\uAC00 \uC131\uACF5\uC801\uC73C\uB85C \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
1622
+ }
1479
1623
  console.log(`
1480
1624
  \u2705 \uB9AC\uBDF0\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`);
1481
1625
  console.log(`\u{1F4C4} \uB9AC\uD3EC\uD2B8 \uC800\uC7A5 \uC704\uCE58: ${savedReportPath}`);
@@ -1490,6 +1634,10 @@ ${getErrorSummary(err)}
1490
1634
  } catch (error) {
1491
1635
  trace7("review-flow:catch", getErrorSummary(error));
1492
1636
  let errorReportPath = "";
1637
+ executionStatus = "failed";
1638
+ executionTitle = "\uD30C\uC77C\uBCC4 \uB9AC\uBDF0 \uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
1639
+ executionError = error;
1640
+ exitCode = 1;
1493
1641
  trace7("cleanup-temp-diff:start(catch)");
1494
1642
  try {
1495
1643
  deleteTempDiff();
@@ -1527,7 +1675,58 @@ ${JSON.stringify(
1527
1675
  if (errorReportPath) {
1528
1676
  console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${errorReportPath}`);
1529
1677
  }
1530
- process.exit(1);
1678
+ } finally {
1679
+ executionLogPath = writeExecutionLog({
1680
+ scope: "review-one-by-one",
1681
+ status: executionStatus,
1682
+ title: executionTitle,
1683
+ args: args4,
1684
+ startedAt,
1685
+ error: executionError,
1686
+ extraSections: [
1687
+ {
1688
+ heading: "Execution Context",
1689
+ markdown: `\`\`\`json
1690
+ ${JSON.stringify(
1691
+ {
1692
+ service: service || null,
1693
+ selectedCommitSummary: selectedCommitSummary || null,
1694
+ fileList,
1695
+ tempDiffPath,
1696
+ savedDiffPath: savedDiffPath || null,
1697
+ savedReportPath: savedReportPath || null
1698
+ },
1699
+ null,
1700
+ 2
1701
+ )}
1702
+ \`\`\``
1703
+ },
1704
+ {
1705
+ heading: "Generated Commands",
1706
+ markdown: `\`\`\`json
1707
+ ${JSON.stringify(
1708
+ fileExecutionLogs.slice().sort((left, right) => left.index - right.index).map((log) => ({
1709
+ file: log.file,
1710
+ status: log.status,
1711
+ resultLength: log.resultLength,
1712
+ errorSummary: log.errorSummary,
1713
+ tempOneFileDiffPath: log.tempOneFileDiffPath,
1714
+ command: log.command
1715
+ })),
1716
+ null,
1717
+ 2
1718
+ )}
1719
+ \`\`\``
1720
+ }
1721
+ ]
1722
+ });
1723
+ if (executionLogPath) {
1724
+ const writeLog = executionStatus === "failed" ? console.error : console.log;
1725
+ writeLog(`\u{1F4DD} \uC2E4\uD589 \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${executionLogPath}`);
1726
+ }
1727
+ }
1728
+ if (exitCode !== 0) {
1729
+ process.exit(exitCode);
1531
1730
  }
1532
1731
  }
1533
1732
  main();