sales-frontend-gemini-cli 0.4.3 → 0.5.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.
Files changed (43) hide show
  1. package/dist/common/helper.cjs +227 -20
  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 +226 -21
  6. package/dist/common/helper.js.map +1 -1
  7. package/dist/common/types.d.cts +3 -1
  8. package/dist/common/types.d.ts +3 -1
  9. package/dist/pr-review/claude/claude-commander.cjs +10 -3
  10. package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
  11. package/dist/pr-review/claude/claude-commander.js +10 -3
  12. package/dist/pr-review/claude/claude-commander.js.map +1 -1
  13. package/dist/pr-review/claude/installation-claude.cjs +1 -1
  14. package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
  15. package/dist/pr-review/claude/installation-claude.js +1 -1
  16. package/dist/pr-review/claude/installation-claude.js.map +1 -1
  17. package/dist/pr-review/codex/codex-commander.cjs +14 -4
  18. package/dist/pr-review/codex/codex-commander.cjs.map +1 -1
  19. package/dist/pr-review/codex/codex-commander.d.cts +1 -1
  20. package/dist/pr-review/codex/codex-commander.d.ts +1 -1
  21. package/dist/pr-review/codex/codex-commander.js +14 -4
  22. package/dist/pr-review/codex/codex-commander.js.map +1 -1
  23. package/dist/pr-review/codex/installation-codex.cjs +1 -1
  24. package/dist/pr-review/codex/installation-codex.cjs.map +1 -1
  25. package/dist/pr-review/codex/installation-codex.js +1 -1
  26. package/dist/pr-review/codex/installation-codex.js.map +1 -1
  27. package/dist/pr-review/gemini/gemini-commander.cjs +12 -12
  28. package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
  29. package/dist/pr-review/gemini/gemini-commander.js +12 -12
  30. package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
  31. package/dist/pr-review/gemini/installation-gemini.cjs +1 -1
  32. package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
  33. package/dist/pr-review/gemini/installation-gemini.js +1 -1
  34. package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
  35. package/dist/pr-review/review-one-by-one.cjs +296 -42
  36. package/dist/pr-review/review-one-by-one.cjs.map +1 -1
  37. package/dist/pr-review/review-one-by-one.js +296 -42
  38. package/dist/pr-review/review-one-by-one.js.map +1 -1
  39. package/dist/pr-review/review.cjs +327 -42
  40. package/dist/pr-review/review.cjs.map +1 -1
  41. package/dist/pr-review/review.js +327 -42
  42. package/dist/pr-review/review.js.map +1 -1
  43. 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,
@@ -435,6 +516,62 @@ function truncateCommitSubject(subject) {
435
516
  }
436
517
  return `${subject.slice(0, 69)}...`;
437
518
  }
519
+ function formatReviewTargetFileCount(fileCount) {
520
+ return fileCount === 0 ? "\uBCC0\uACBD \uC5C6\uC74C" : `${fileCount}\uAC1C \uD30C\uC77C`;
521
+ }
522
+ function buildReviewTargetSectionTitle(target) {
523
+ return target.kind === "commit" ? `${target.hash} ${target.subject}` : `${target.hash} | ${target.subject}`;
524
+ }
525
+ function buildReviewTargetSummaryLine(target) {
526
+ if (target.kind === "commit") {
527
+ return `- ${target.hash} | ${target.subject} | ${target.author} | ${target.relativeDate}`;
528
+ }
529
+ return `- ${target.hash} | ${target.subject}`;
530
+ }
531
+ function buildReviewTargetDiffArgs(target, filePath) {
532
+ const reviewPathspecArgs = getReviewPathspecArgs();
533
+ if (target.kind === "commit") {
534
+ return filePath ? ["show", "--stat", "--patch", "--format=", target.hash, "--", filePath] : ["show", "--stat", "--patch", "--format=", target.hash, "--", ...reviewPathspecArgs];
535
+ }
536
+ const diffArgs = ["diff"];
537
+ if (target.kind === "staged") {
538
+ diffArgs.push("--cached");
539
+ }
540
+ diffArgs.push("--stat", "--patch", "--");
541
+ return filePath ? [...diffArgs, filePath] : [...diffArgs, ...reviewPathspecArgs];
542
+ }
543
+ function buildReviewTargetFileArgs(target) {
544
+ const reviewPathspecArgs = getReviewPathspecArgs();
545
+ if (target.kind === "commit") {
546
+ return ["show", "--pretty=format:", "--name-only", target.hash, "--", ...reviewPathspecArgs];
547
+ }
548
+ const diffArgs = ["diff"];
549
+ if (target.kind === "staged") {
550
+ diffArgs.push("--cached");
551
+ }
552
+ return [...diffArgs, "--name-only", "--", ...reviewPathspecArgs];
553
+ }
554
+ function getReviewTargetFiles(target) {
555
+ const output = runGitCommand(buildReviewTargetFileArgs(target), {
556
+ allowFailure: true
557
+ });
558
+ return output.split("\n").map((line) => line.trim()).filter(Boolean);
559
+ }
560
+ function createWorkingTreeReviewOption(kind) {
561
+ const files = getReviewTargetFiles({
562
+ hash: kind,
563
+ kind});
564
+ const subject = kind === "unstaged" ? "\uC544\uC9C1 git add \uD558\uC9C0 \uC54A\uC740 \uBCC0\uACBD\uC0AC\uD56D" : "git add \uB41C \uBCC0\uACBD\uC0AC\uD56D";
565
+ return {
566
+ author: "",
567
+ description: `${subject} | ${formatReviewTargetFileCount(files.length)}`,
568
+ hash: kind,
569
+ kind,
570
+ label: kind,
571
+ relativeDate: "",
572
+ subject
573
+ };
574
+ }
438
575
  function getRecentCommitOptions() {
439
576
  const output = runGitCommand(
440
577
  ["log", `-${COMMIT_FETCH_LIMIT}`, "--date=relative", "--pretty=format:%h%x09%an%x09%ar%x09%s"],
@@ -450,62 +587,61 @@ function getRecentCommitOptions() {
450
587
  author,
451
588
  description: `${author} | ${relativeDate}`,
452
589
  hash,
590
+ kind: "commit",
453
591
  label: `${hash} | ${truncateCommitSubject(subject)}`,
454
592
  relativeDate,
455
593
  subject
456
594
  };
457
595
  });
458
596
  }
597
+ function getReviewTargetOptions() {
598
+ return [createWorkingTreeReviewOption("unstaged"), createWorkingTreeReviewOption("staged"), ...getRecentCommitOptions()];
599
+ }
459
600
  function buildSelectedCommitSummary(commits) {
460
- return commits.map((commit) => `- ${commit.hash} | ${commit.subject} | ${commit.author} | ${commit.relativeDate}`).join("\n");
601
+ return commits.map((commit) => buildReviewTargetSummaryLine(commit)).join("\n");
461
602
  }
462
603
  function getReviewPathspecArgs() {
463
604
  const { includePatterns, excludePatterns } = getGitDiffPathspecs();
464
605
  return [...includePatterns, ...excludePatterns];
465
606
  }
466
607
  function buildSelectedCommitDiff(commits) {
467
- const reviewPathspecArgs = getReviewPathspecArgs();
468
608
  const sections = commits.map((commit) => {
469
- const diff = runGitCommand(["show", "--stat", "--patch", "--format=", commit.hash, "--", ...reviewPathspecArgs], {
609
+ const diff = runGitCommand(buildReviewTargetDiffArgs(commit), {
470
610
  allowFailure: true,
471
611
  trimOutput: false
472
612
  }).trim();
473
613
  if (!diff) {
474
614
  return "";
475
615
  }
476
- return [`## ${commit.hash} ${commit.subject}`, diff].join("\n\n");
616
+ return [`## ${buildReviewTargetSectionTitle(commit)}`, diff].join("\n\n");
477
617
  }).filter(Boolean).join("\n\n");
478
618
  if (!sections) {
479
619
  return "";
480
620
  }
481
- return ["# \uC120\uD0DD\uD55C \uCEE4\uBC0B", buildSelectedCommitSummary(commits), "", "# \uB9AC\uBDF0 \uB300\uC0C1 diff", sections].join("\n");
621
+ return ["# \uC120\uD0DD\uD55C \uB9AC\uBDF0 \uB300\uC0C1", buildSelectedCommitSummary(commits), "", "# \uB9AC\uBDF0 \uB300\uC0C1 diff", sections].join("\n");
482
622
  }
483
623
  function getSelectedCommitFiles(commits) {
484
- const reviewPathspecArgs = getReviewPathspecArgs();
485
624
  const files = /* @__PURE__ */ new Set();
486
625
  commits.forEach((commit) => {
487
- const output = runGitCommand(["show", "--pretty=format:", "--name-only", commit.hash, "--", ...reviewPathspecArgs], {
488
- allowFailure: true
489
- });
490
- output.split("\n").map((line) => line.trim()).filter(Boolean).forEach((filePath) => files.add(filePath));
626
+ getReviewTargetFiles(commit).forEach((filePath) => files.add(filePath));
491
627
  });
492
628
  return [...files];
493
629
  }
494
630
  function buildSelectedFileDiff(commits, filePath) {
495
631
  const sections = commits.map((commit) => {
496
- const diff = runGitCommand(["show", "--stat", "--patch", "--format=", commit.hash, "--", filePath], {
632
+ const diff = runGitCommand(buildReviewTargetDiffArgs(commit, filePath), {
497
633
  allowFailure: true,
498
634
  trimOutput: false
499
635
  }).trim();
500
636
  if (!diff) {
501
637
  return "";
502
638
  }
503
- return [`## ${commit.hash} ${commit.subject}`, diff].join("\n\n");
639
+ return [`## ${buildReviewTargetSectionTitle(commit)}`, diff].join("\n\n");
504
640
  }).filter(Boolean).join("\n\n");
505
641
  if (!sections) {
506
642
  return "";
507
643
  }
508
- return ["# \uC120\uD0DD\uD55C \uCEE4\uBC0B", buildSelectedCommitSummary(commits), "", `# \uD30C\uC77C: ${filePath}`, sections].join("\n\n");
644
+ return ["# \uC120\uD0DD\uD55C \uB9AC\uBDF0 \uB300\uC0C1", buildSelectedCommitSummary(commits), "", `# \uD30C\uC77C: ${filePath}`, sections].join("\n\n");
509
645
  }
510
646
  function openReport(reportPath) {
511
647
  const resolvedPath = path__default.default.resolve(reportPath);
@@ -691,13 +827,13 @@ async function showMultiSelect(question, options, windowSize = COMMIT_SELECTION_
691
827
  });
692
828
  }
693
829
  async function selectReviewCommits() {
694
- const commits = getRecentCommitOptions();
830
+ const commits = getReviewTargetOptions();
695
831
  if (commits.length === 0) {
696
- console.log("\u2139\uFE0F \uB9AC\uBDF0\uD560 \uCD5C\uADFC \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
832
+ console.log("\u2139\uFE0F \uB9AC\uBDF0\uD560 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
697
833
  return [];
698
834
  }
699
835
  return showMultiSelect(
700
- "\uB9AC\uBDF0\uD560 \uCEE4\uBC0B\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.",
836
+ "\uB9AC\uBDF0\uD560 \uB300\uC0C1\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694.",
701
837
  commits.map((commit) => ({
702
838
  description: commit.description,
703
839
  label: commit.label,
@@ -788,6 +924,13 @@ var ALLOWED_REASONING_EFFORTS = ["minimal", "low", "medium", "high"];
788
924
  function shellQuote(value) {
789
925
  return `'${value.replace(/'/g, `'\\''`)}'`;
790
926
  }
927
+ function toShellOptionToken(value) {
928
+ const SIMPLE_SHELL_TOKEN_PATTERN = /^[A-Za-z0-9._:/=-]+$/;
929
+ if (SIMPLE_SHELL_TOKEN_PATTERN.test(value)) {
930
+ return value;
931
+ }
932
+ return shellQuote(value);
933
+ }
791
934
  function getArgValue(flag) {
792
935
  const index = args.indexOf(flag);
793
936
  if (index === -1 || !args[index + 1]) {
@@ -867,9 +1010,9 @@ function getAliasFallbacks(primaryAlias) {
867
1010
  }
868
1011
  function buildClaudeExecCommand(options) {
869
1012
  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)}`;
1013
+ const modelOption = model ? `--model ${toShellOptionToken(model)}` : "";
1014
+ const fallbackOption = model && fallbackModel ? `--fallback-model ${toShellOptionToken(fallbackModel)}` : "";
1015
+ const effortOption = `--effort ${toShellOptionToken(effort)}`;
873
1016
  const appendedPromptFiles = systemPromptFiles.map((path3) => `--append-system-prompt-file ${shellQuote(path3)}`).join(" ");
874
1017
  return `cat ${shellQuote(tempDiffPath2)} | claude ${[
875
1018
  modelOption,
@@ -994,12 +1137,22 @@ function printNotice2(message) {
994
1137
  console.warn(message);
995
1138
  }
996
1139
  }
1140
+ function normalizeEffort2(level) {
1141
+ if (level === "minimal") {
1142
+ return "low";
1143
+ }
1144
+ return level;
1145
+ }
997
1146
  function resolveReasoningEffort2() {
998
1147
  const customReasoningEffort = getArgValue2("--reasoning-effort");
999
1148
  if (customReasoningEffort) {
1000
1149
  if (ALLOWED_REASONING_EFFORTS2.includes(customReasoningEffort)) {
1001
- trace3("reasoning:custom", customReasoningEffort);
1002
- return customReasoningEffort;
1150
+ const normalized = normalizeEffort2(customReasoningEffort);
1151
+ trace3("reasoning:custom", `${customReasoningEffort} -> ${normalized}`);
1152
+ if (customReasoningEffort === "minimal") {
1153
+ 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.");
1154
+ }
1155
+ return normalized;
1003
1156
  }
1004
1157
  printNotice2(
1005
1158
  `\u26A0\uFE0F \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 reasoning effort(${customReasoningEffort})\uC785\uB2C8\uB2E4. allowed: ${ALLOWED_REASONING_EFFORTS2.join(
@@ -1008,8 +1161,8 @@ function resolveReasoningEffort2() {
1008
1161
  );
1009
1162
  }
1010
1163
  if (args2.includes("--flash")) {
1011
- trace3("reasoning:flash-default", "minimal");
1012
- return "minimal";
1164
+ trace3("reasoning:flash-default", "low");
1165
+ return "low";
1013
1166
  }
1014
1167
  if (args2.includes("--review")) {
1015
1168
  trace3("reasoning:review-default", "high");
@@ -1204,7 +1357,7 @@ function buildGeminiFileReferenceSection(files) {
1204
1357
  const existingFiles = files.filter((file) => fs__default.default.existsSync(file.path));
1205
1358
  return {
1206
1359
  count: existingFiles.length,
1207
- lines: existingFiles.map((file) => `- ${file.display}: ${toGeminiFileReference(file.path)}`)
1360
+ items: existingFiles.map((file) => `${file.display} ${toGeminiFileReference(file.path)}`)
1208
1361
  };
1209
1362
  }
1210
1363
  var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
@@ -1223,19 +1376,19 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
1223
1376
  const ruleSection = buildGeminiFileReferenceSection(rules);
1224
1377
  trace5("rules:loaded", `count=${ruleSection.count}`);
1225
1378
  const reviewFormExists = fs__default.default.existsSync(resolvedReviewFormPath);
1226
- const reviewFormLine = reviewFormExists ? `- \uB9AC\uBDF0 \uC591\uC2DD: ${toGeminiFileReference(resolvedReviewFormPath)}` : "- \uB9AC\uBDF0 \uC591\uC2DD: (\uC5C6\uC74C)";
1379
+ const reviewFormText = reviewFormExists ? `\uB9AC\uBDF0 \uC591\uC2DD ${toGeminiFileReference(resolvedReviewFormPath)}` : "\uB9AC\uBDF0 \uC591\uC2DD (\uC5C6\uC74C)";
1227
1380
  trace5("reviewForm:status", reviewFormExists ? "exists" : "missing");
1228
1381
  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}`;
1382
+ const ruleText = ruleSection.items.join(" ") || "(\uC5C6\uC74C)";
1383
+ const diffText = `\uB9AC\uBDF0 \uB300\uC0C1 diff ${toGeminiFileReference(resolvedTempDiffPath)}`;
1384
+ const prompt = [
1385
+ "\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uC21C\uC11C\uB300\uB85C \uC77D\uACE0 \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.",
1386
+ `\uADDC\uCE59 \uD30C\uC77C: ${ruleText}`,
1387
+ `\uB9AC\uBDF0 \uC591\uC2DD \uD30C\uC77C: ${reviewFormText}`,
1388
+ `\uB9AC\uBDF0 \uB300\uC0C1 diff \uD30C\uC77C: ${diffText}`,
1389
+ "\uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.",
1390
+ `\uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`
1391
+ ].join(" ");
1239
1392
  trace5("prompt:prepared", `length=${prompt.length}`);
1240
1393
  const modelCandidates = toUnique2(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
1241
1394
  trace5("model:candidates", modelCandidates.join(", "));
@@ -1299,6 +1452,7 @@ function checkGeminiCliInstalled() {
1299
1452
  var execAsync = util__default.default.promisify(child_process.exec);
1300
1453
  async function main() {
1301
1454
  const args4 = process.argv.slice(2);
1455
+ const startedAt = /* @__PURE__ */ new Date();
1302
1456
  clearTraceMessages();
1303
1457
  const isTest = isTestMode(args4);
1304
1458
  const trace7 = createTraceLogger("review-one-by-one", args4);
@@ -1307,6 +1461,13 @@ async function main() {
1307
1461
  let savedDiffPath = "";
1308
1462
  let savedReportPath = "";
1309
1463
  let selectedCommitSummary = "";
1464
+ let fileList = [];
1465
+ let executionLogPath = "";
1466
+ let executionStatus = "cancelled";
1467
+ 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.";
1468
+ let executionError = null;
1469
+ let exitCode = 0;
1470
+ const fileExecutionLogs = [];
1310
1471
  try {
1311
1472
  trace7("service-selection:start");
1312
1473
  service = await showSelectionAIService();
@@ -1335,22 +1496,24 @@ async function main() {
1335
1496
  trace7("commit-selection:done", `count=${selectedCommits.length}`);
1336
1497
  if (selectedCommits.length === 0) {
1337
1498
  trace7("commit-selection:empty");
1338
- console.log("\u2139\uFE0F \uC120\uD0DD\uB41C \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
1499
+ executionTitle = "\uC120\uD0DD\uB41C \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.";
1500
+ console.log("\u2139\uFE0F \uC120\uD0DD\uB41C \uB9AC\uBDF0 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
1339
1501
  deleteTempDiff();
1340
- process.exit(0);
1502
+ return;
1341
1503
  }
1342
1504
  selectedCommitSummary = buildSelectedCommitSummary(selectedCommits);
1343
1505
  trace7("commit-summary:prepared", selectedCommitSummary);
1344
1506
  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
1507
  trace7("files-command:run");
1346
- const fileList = getSelectedCommitFiles(selectedCommits);
1508
+ fileList = getSelectedCommitFiles(selectedCommits);
1347
1509
  trace7("files-command:done", `fileCount=${fileList.length}`);
1348
1510
  console.log(`\u{1F4C2} \uB9AC\uBDF0 \uB300\uC0C1 \uD30C\uC77C(${fileList.length}\uAC1C): ${formatReviewTargetFiles(fileList)}`);
1349
1511
  if (fileList.length === 0) {
1350
1512
  trace7("empty-file-list:exit");
1351
- 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.");
1513
+ executionTitle = "\uC120\uD0DD\uD55C \uB9AC\uBDF0 \uB300\uC0C1\uC5D0\uC11C \uB9AC\uBDF0\uD560 \uBCC0\uACBD\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.";
1514
+ console.log("\u2139\uFE0F \uC120\uD0DD\uD55C \uB9AC\uBDF0 \uB300\uC0C1\uC5D0\uC11C \uB9AC\uBDF0\uD560 \uBCC0\uACBD\uC744 \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.");
1352
1515
  deleteTempDiff();
1353
- process.exit(0);
1516
+ return;
1354
1517
  }
1355
1518
  trace7("report-dir:create:start");
1356
1519
  createReportDirectory();
@@ -1380,6 +1543,15 @@ async function main() {
1380
1543
  trace7("file-diff:build:done", `${file} | length=${fileDiff.length}`);
1381
1544
  if (!fileDiff.trim()) {
1382
1545
  trace7("file-diff:empty", file);
1546
+ fileExecutionLogs.push({
1547
+ command: null,
1548
+ errorSummary: null,
1549
+ file,
1550
+ index,
1551
+ resultLength: 0,
1552
+ status: "skipped",
1553
+ tempOneFileDiffPath
1554
+ });
1383
1555
  return;
1384
1556
  }
1385
1557
  trace7("file-temp-diff:write:start", tempOneFileDiffPath);
@@ -1422,9 +1594,27 @@ ${result}
1422
1594
  ${command}`);
1423
1595
  trace7("file-test-command:append:done", file);
1424
1596
  }
1597
+ fileExecutionLogs.push({
1598
+ command,
1599
+ errorSummary: null,
1600
+ file,
1601
+ index,
1602
+ resultLength: result.length,
1603
+ status: "success",
1604
+ tempOneFileDiffPath
1605
+ });
1425
1606
  trace7("file-review:end", file);
1426
1607
  } catch (err) {
1427
1608
  trace7("file-review:catch", `${file} | ${getErrorSummary(err)}`);
1609
+ fileExecutionLogs.push({
1610
+ command: command || null,
1611
+ errorSummary: getErrorSummary(err),
1612
+ file,
1613
+ index,
1614
+ resultLength: 0,
1615
+ status: "failed",
1616
+ tempOneFileDiffPath
1617
+ });
1428
1618
  const errorLogPath = writeErrorReport(err, {
1429
1619
  scope: "review-one-by-one:file",
1430
1620
  args: args4,
@@ -1476,6 +1666,15 @@ ${getErrorSummary(err)}
1476
1666
  trace7("parallel-review:await-start");
1477
1667
  await Promise.all(promises);
1478
1668
  trace7("parallel-review:await-done");
1669
+ const failedFileCount = fileExecutionLogs.filter((log) => log.status === "failed").length;
1670
+ const successfulFileCount = fileExecutionLogs.filter((log) => log.status === "success").length;
1671
+ if (failedFileCount > 0) {
1672
+ executionStatus = "partial_failure";
1673
+ executionTitle = `\uD30C\uC77C\uBCC4 \uB9AC\uBDF0 \uC911 \uC77C\uBD80\uAC00 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. (\uC131\uACF5 ${successfulFileCount}\uAC74 / \uC2E4\uD328 ${failedFileCount}\uAC74)`;
1674
+ } else {
1675
+ executionStatus = "success";
1676
+ executionTitle = "\uD30C\uC77C\uBCC4 \uB9AC\uBDF0\uAC00 \uC131\uACF5\uC801\uC73C\uB85C \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.";
1677
+ }
1479
1678
  console.log(`
1480
1679
  \u2705 \uB9AC\uBDF0\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`);
1481
1680
  console.log(`\u{1F4C4} \uB9AC\uD3EC\uD2B8 \uC800\uC7A5 \uC704\uCE58: ${savedReportPath}`);
@@ -1490,6 +1689,10 @@ ${getErrorSummary(err)}
1490
1689
  } catch (error) {
1491
1690
  trace7("review-flow:catch", getErrorSummary(error));
1492
1691
  let errorReportPath = "";
1692
+ executionStatus = "failed";
1693
+ executionTitle = "\uD30C\uC77C\uBCC4 \uB9AC\uBDF0 \uC2E4\uD589 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.";
1694
+ executionError = error;
1695
+ exitCode = 1;
1493
1696
  trace7("cleanup-temp-diff:start(catch)");
1494
1697
  try {
1495
1698
  deleteTempDiff();
@@ -1527,7 +1730,58 @@ ${JSON.stringify(
1527
1730
  if (errorReportPath) {
1528
1731
  console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${errorReportPath}`);
1529
1732
  }
1530
- process.exit(1);
1733
+ } finally {
1734
+ executionLogPath = writeExecutionLog({
1735
+ scope: "review-one-by-one",
1736
+ status: executionStatus,
1737
+ title: executionTitle,
1738
+ args: args4,
1739
+ startedAt,
1740
+ error: executionError,
1741
+ extraSections: [
1742
+ {
1743
+ heading: "Execution Context",
1744
+ markdown: `\`\`\`json
1745
+ ${JSON.stringify(
1746
+ {
1747
+ service: service || null,
1748
+ selectedCommitSummary: selectedCommitSummary || null,
1749
+ fileList,
1750
+ tempDiffPath,
1751
+ savedDiffPath: savedDiffPath || null,
1752
+ savedReportPath: savedReportPath || null
1753
+ },
1754
+ null,
1755
+ 2
1756
+ )}
1757
+ \`\`\``
1758
+ },
1759
+ {
1760
+ heading: "Generated Commands",
1761
+ markdown: `\`\`\`json
1762
+ ${JSON.stringify(
1763
+ fileExecutionLogs.slice().sort((left, right) => left.index - right.index).map((log) => ({
1764
+ file: log.file,
1765
+ status: log.status,
1766
+ resultLength: log.resultLength,
1767
+ errorSummary: log.errorSummary,
1768
+ tempOneFileDiffPath: log.tempOneFileDiffPath,
1769
+ command: log.command
1770
+ })),
1771
+ null,
1772
+ 2
1773
+ )}
1774
+ \`\`\``
1775
+ }
1776
+ ]
1777
+ });
1778
+ if (executionLogPath) {
1779
+ const writeLog = executionStatus === "failed" ? console.error : console.log;
1780
+ writeLog(`\u{1F4DD} \uC2E4\uD589 \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${executionLogPath}`);
1781
+ }
1782
+ }
1783
+ if (exitCode !== 0) {
1784
+ process.exit(exitCode);
1531
1785
  }
1532
1786
  }
1533
1787
  main();