sales-frontend-gemini-cli 0.4.1 → 0.4.2

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 (39) hide show
  1. package/dist/common/helper.cjs +226 -32
  2. package/dist/common/helper.cjs.map +1 -1
  3. package/dist/common/helper.d.cts +22 -2
  4. package/dist/common/helper.d.ts +22 -2
  5. package/dist/common/helper.js +220 -33
  6. package/dist/common/helper.js.map +1 -1
  7. package/dist/pr-review/claude/claude-commander.cjs +8 -1
  8. package/dist/pr-review/claude/claude-commander.cjs.map +1 -1
  9. package/dist/pr-review/claude/claude-commander.js +8 -1
  10. package/dist/pr-review/claude/claude-commander.js.map +1 -1
  11. package/dist/pr-review/claude/installation-claude.cjs +178 -8
  12. package/dist/pr-review/claude/installation-claude.cjs.map +1 -1
  13. package/dist/pr-review/claude/installation-claude.js +177 -8
  14. package/dist/pr-review/claude/installation-claude.js.map +1 -1
  15. package/dist/pr-review/codex/codex-commander.cjs +6 -1
  16. package/dist/pr-review/codex/codex-commander.cjs.map +1 -1
  17. package/dist/pr-review/codex/codex-commander.js +6 -1
  18. package/dist/pr-review/codex/codex-commander.js.map +1 -1
  19. package/dist/pr-review/codex/installation-codex.cjs +178 -8
  20. package/dist/pr-review/codex/installation-codex.cjs.map +1 -1
  21. package/dist/pr-review/codex/installation-codex.js +177 -8
  22. package/dist/pr-review/codex/installation-codex.js.map +1 -1
  23. package/dist/pr-review/gemini/gemini-commander.cjs +7 -1
  24. package/dist/pr-review/gemini/gemini-commander.cjs.map +1 -1
  25. package/dist/pr-review/gemini/gemini-commander.js +7 -1
  26. package/dist/pr-review/gemini/gemini-commander.js.map +1 -1
  27. package/dist/pr-review/gemini/installation-gemini.cjs +178 -8
  28. package/dist/pr-review/gemini/installation-gemini.cjs.map +1 -1
  29. package/dist/pr-review/gemini/installation-gemini.js +177 -8
  30. package/dist/pr-review/gemini/installation-gemini.js.map +1 -1
  31. package/dist/pr-review/review-one-by-one.cjs +368 -108
  32. package/dist/pr-review/review-one-by-one.cjs.map +1 -1
  33. package/dist/pr-review/review-one-by-one.js +368 -108
  34. package/dist/pr-review/review-one-by-one.js.map +1 -1
  35. package/dist/pr-review/review.cjs +316 -80
  36. package/dist/pr-review/review.cjs.map +1 -1
  37. package/dist/pr-review/review.js +316 -80
  38. package/dist/pr-review/review.js.map +1 -1
  39. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
  'use strict';
3
3
 
4
4
  var child_process = require('child_process');
5
- var fs5 = require('fs');
5
+ var fs = require('fs');
6
6
  var util = require('util');
7
7
  var path = require('path');
8
8
  var readline = require('readline');
@@ -11,12 +11,13 @@ var url = require('url');
11
11
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
12
12
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
13
13
 
14
- var fs5__default = /*#__PURE__*/_interopDefault(fs5);
14
+ var fs__default = /*#__PURE__*/_interopDefault(fs);
15
15
  var util__default = /*#__PURE__*/_interopDefault(util);
16
16
  var path__default = /*#__PURE__*/_interopDefault(path);
17
17
  var readline__default = /*#__PURE__*/_interopDefault(readline);
18
18
 
19
19
  var __dirname$1 = path__default.default.dirname(url.fileURLToPath((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('review-one-by-one.cjs', document.baseURI).href))));
20
+ var traceMessages = [];
20
21
  var rulesPath = path__default.default.resolve(__dirname$1, "../../src/common/rules/review-rules.md");
21
22
  var namingRulesPath = path__default.default.resolve(__dirname$1, "../../src/common/rules/naming-rule.md");
22
23
  var codingConventionRulesPath = path__default.default.resolve(__dirname$1, "../../src/common/rules/coding-convention.md");
@@ -39,66 +40,226 @@ var ignoreList = [
39
40
  ".review-report/"
40
41
  // 생성되는 리포트 폴더도 제외
41
42
  ];
42
- function parseServiceFromArgs(args4 = process.argv.slice(2)) {
43
- const serviceIndex = args4.indexOf("--service");
44
- const rawService = serviceIndex !== -1 ? args4[serviceIndex + 1] : "";
45
- if (!rawService) {
46
- return "";
47
- }
48
- const normalizedService = rawService.toLowerCase();
49
- if (AIServices.includes(normalizedService)) {
50
- return normalizedService;
51
- }
52
- console.error(
53
- `\u274C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC11C\uBE44\uC2A4\uC785\uB2C8\uB2E4: ${rawService}. \uC0AC\uC6A9 \uAC00\uB2A5 \uAC12: ${AIServices.join(", ")} (\uC608: --service codex)`
54
- );
55
- process.exit(1);
56
- }
57
43
  function isTestMode(args4 = process.argv.slice(2)) {
58
44
  return args4.includes("--test");
59
45
  }
46
+ function clearTraceMessages() {
47
+ traceMessages.length = 0;
48
+ }
49
+ function getTraceMessages() {
50
+ return [...traceMessages];
51
+ }
60
52
  function createTraceLogger(scope, args4 = process.argv.slice(2)) {
61
53
  const enabled = isTestMode(args4);
62
54
  return (step, detail) => {
55
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
56
+ const message = `[${timestamp}][TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ""}`;
57
+ traceMessages.push(message);
63
58
  if (!enabled) {
64
59
  return;
65
60
  }
66
- console.log(`[TRACE][${scope}] ${step}${detail ? ` | ${detail}` : ""}`);
61
+ console.log(message);
62
+ };
63
+ }
64
+ var helperTrace = createTraceLogger("helper");
65
+ function getTimestampParts(now = /* @__PURE__ */ new Date()) {
66
+ return {
67
+ YYYY: now.getFullYear(),
68
+ MM: String(now.getMonth() + 1).padStart(2, "0"),
69
+ DD: String(now.getDate()).padStart(2, "0"),
70
+ HH: String(now.getHours()).padStart(2, "0"),
71
+ mm: String(now.getMinutes()).padStart(2, "0"),
72
+ ss: String(now.getSeconds()).padStart(2, "0")
67
73
  };
68
74
  }
75
+ function getHumanReadableNowString(now = /* @__PURE__ */ new Date()) {
76
+ const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);
77
+ return `${YYYY}-${MM}-${DD} ${HH}:${mm}:${ss}`;
78
+ }
79
+ function stringifyUnknown(value) {
80
+ if (value === void 0 || value === null) {
81
+ return "";
82
+ }
83
+ if (typeof value === "string") {
84
+ return value;
85
+ }
86
+ if (Buffer.isBuffer(value)) {
87
+ return value.toString();
88
+ }
89
+ if (value instanceof Error) {
90
+ return value.stack || value.message;
91
+ }
92
+ return util.inspect(value, { depth: 5, breakLength: 120 });
93
+ }
94
+ function getErrorSummary(error) {
95
+ if (error instanceof Error) {
96
+ return `${error.name}: ${error.message}`;
97
+ }
98
+ return stringifyUnknown(error) || "Unknown error";
99
+ }
100
+ function serializeError(error) {
101
+ const serialized = {
102
+ summary: getErrorSummary(error)
103
+ };
104
+ if (error instanceof Error) {
105
+ serialized.name = error.name;
106
+ serialized.message = error.message;
107
+ serialized.stack = error.stack;
108
+ } else {
109
+ serialized.value = stringifyUnknown(error);
110
+ }
111
+ if (error && typeof error === "object") {
112
+ const errorLike = error;
113
+ const extraKeys = ["code", "errno", "syscall", "path", "cmd", "status", "signal", "spawnargs"];
114
+ extraKeys.forEach((key) => {
115
+ if (errorLike[key] !== void 0) {
116
+ serialized[key] = errorLike[key];
117
+ }
118
+ });
119
+ const stdout = stringifyUnknown(errorLike.stdout);
120
+ if (stdout) {
121
+ serialized.stdout = stdout;
122
+ }
123
+ const stderr = stringifyUnknown(errorLike.stderr);
124
+ if (stderr) {
125
+ serialized.stderr = stderr;
126
+ }
127
+ const cause = stringifyUnknown(errorLike.cause);
128
+ if (cause) {
129
+ serialized.cause = cause;
130
+ }
131
+ }
132
+ return serialized;
133
+ }
69
134
  function getNextFilePath(dir, baseName, extension) {
70
135
  let counter = 1;
71
136
  while (true) {
72
137
  const filePath = path__default.default.join(dir, `${baseName}-${counter}${extension}`);
73
- if (!fs5__default.default.existsSync(filePath)) {
138
+ if (!fs__default.default.existsSync(filePath)) {
74
139
  return filePath;
75
140
  }
76
141
  counter++;
77
142
  }
78
143
  }
144
+ function getAvailableFilePath(dir, baseName, extension) {
145
+ const firstFilePath = path__default.default.join(dir, `${baseName}${extension}`);
146
+ if (!fs__default.default.existsSync(firstFilePath)) {
147
+ return firstFilePath;
148
+ }
149
+ return getNextFilePath(dir, baseName, extension);
150
+ }
79
151
  function deleteFile(filePath) {
80
- if (fs5__default.default.existsSync(filePath)) {
81
- fs5__default.default.unlinkSync(filePath);
152
+ if (fs__default.default.existsSync(filePath)) {
153
+ fs__default.default.unlinkSync(filePath);
82
154
  }
83
155
  }
84
156
  function deleteTempDiff() {
85
157
  deleteFile(tempDiffPath);
86
158
  }
87
159
  function createReportDirectory() {
88
- if (!fs5__default.default.existsSync(REPORT_DIR)) {
89
- fs5__default.default.mkdirSync(REPORT_DIR, { recursive: true });
90
- }
91
- }
92
- function getNowString() {
93
- const now = /* @__PURE__ */ new Date();
94
- const YYYY = now.getFullYear();
95
- const MM = String(now.getMonth() + 1).padStart(2, "0");
96
- const DD = String(now.getDate()).padStart(2, "0");
97
- const HH = String(now.getHours()).padStart(2, "0");
98
- const mm = String(now.getMinutes()).padStart(2, "0");
99
- const ss = String(now.getSeconds()).padStart(2, "0");
160
+ if (!fs__default.default.existsSync(REPORT_DIR)) {
161
+ fs__default.default.mkdirSync(REPORT_DIR, { recursive: true });
162
+ }
163
+ }
164
+ function getNowString(now = /* @__PURE__ */ new Date()) {
165
+ const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);
100
166
  return `${YYYY}-${MM}-${DD}_${HH}-${mm}-${ss}`;
101
167
  }
168
+ function getErrorLogTimestamp(now = /* @__PURE__ */ new Date()) {
169
+ const { YYYY, MM, DD, HH, mm, ss } = getTimestampParts(now);
170
+ return `${YYYY}-${MM}-${DD}-${HH}\uC2DC-${mm}\uBD84-${ss}\uCD08`;
171
+ }
172
+ function writeErrorReport(error, options = {}) {
173
+ try {
174
+ const now = /* @__PURE__ */ new Date();
175
+ helperTrace("error-report:write:start", options.scope || "unknown");
176
+ createReportDirectory();
177
+ const reportPath = getAvailableFilePath(REPORT_DIR, `error-log-${getErrorLogTimestamp(now)}`, ".md");
178
+ const serializedError = serializeError(error);
179
+ const traceSnapshot = options.traceMessages ?? getTraceMessages();
180
+ const extraSections = options.extraSections || [];
181
+ const report = `# Error Log
182
+
183
+ - \uBC1C\uC0DD \uC2DC\uAC01: ${getHumanReadableNowString(now)}
184
+ - Scope: \`${options.scope || "unknown"}\`
185
+ - \uC791\uC5C5 \uACBD\uB85C: \`${process.cwd()}\`
186
+ - \uC2E4\uD589 \uC778\uC790: \`${JSON.stringify(options.args ?? process.argv.slice(2))}\`
187
+ - \uC2E4\uD589 \uD658\uACBD: \`${process.platform} ${process.arch} / Node ${process.version}\`
188
+
189
+ ## Summary
190
+
191
+ ${options.title || serializedError.summary || "Unknown error"}
192
+
193
+ ## Error
194
+
195
+ \`\`\`json
196
+ ${JSON.stringify(serializedError, null, 2)}
197
+ \`\`\`
198
+
199
+ ## Trace
200
+
201
+ \`\`\`json
202
+ ${JSON.stringify(traceSnapshot, null, 2)}
203
+ \`\`\`${extraSections.length ? `
204
+ ${extraSections.map((section) => `
205
+ ## ${section.heading}
206
+
207
+ ${section.markdown}`).join("\n")}
208
+ ` : "\n"}
209
+ `;
210
+ fs__default.default.writeFileSync(reportPath, report);
211
+ helperTrace("error-report:write:done", reportPath);
212
+ return reportPath;
213
+ } catch (writeError) {
214
+ console.error("\u26A0\uFE0F \uC5D0\uB7EC \uB85C\uADF8 \uD30C\uC77C \uC0DD\uC131\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4.");
215
+ console.error(writeError);
216
+ return "";
217
+ }
218
+ }
219
+ function exitWithError(message, options = {}) {
220
+ const reportPath = writeErrorReport(options.error || new Error(message), {
221
+ ...options,
222
+ title: message
223
+ });
224
+ console.error(message);
225
+ if (options.error) {
226
+ console.error(options.error);
227
+ }
228
+ if (reportPath) {
229
+ console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${reportPath}`);
230
+ }
231
+ process.exit(1);
232
+ }
233
+ function parseServiceFromArgs(args4 = process.argv.slice(2)) {
234
+ helperTrace("parse-service:start", `args=${JSON.stringify(args4)}`);
235
+ const serviceIndex = args4.indexOf("--service");
236
+ const rawService = serviceIndex !== -1 ? args4[serviceIndex + 1] : "";
237
+ if (!rawService) {
238
+ helperTrace("parse-service:empty");
239
+ return "";
240
+ }
241
+ const normalizedService = rawService.toLowerCase();
242
+ if (AIServices.includes(normalizedService)) {
243
+ helperTrace("parse-service:resolved", normalizedService);
244
+ return normalizedService;
245
+ }
246
+ helperTrace("parse-service:invalid", rawService);
247
+ exitWithError(
248
+ `\u274C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uC11C\uBE44\uC2A4\uC785\uB2C8\uB2E4: ${rawService}. \uC0AC\uC6A9 \uAC00\uB2A5 \uAC12: ${AIServices.join(", ")} (\uC608: --service codex)`,
249
+ {
250
+ scope: "helper:parseServiceFromArgs",
251
+ args: args4,
252
+ extraSections: [
253
+ {
254
+ heading: "Allowed Services",
255
+ markdown: `\`\`\`json
256
+ ${JSON.stringify(AIServices, null, 2)}
257
+ \`\`\``
258
+ }
259
+ ]
260
+ }
261
+ );
262
+ }
102
263
  function getGitDiffFilter() {
103
264
  const includeExtensions = ["*.ts", "*.tsx", "*.js", "*.jsx"];
104
265
  const excludePatterns = ignoreList.map((item) => `:(exclude)${item}`);
@@ -110,6 +271,7 @@ function getGitDiffFilter() {
110
271
  function openReport(reportPath) {
111
272
  const resolvedPath = path__default.default.resolve(reportPath);
112
273
  const { platform } = process;
274
+ helperTrace("open-report:start", resolvedPath);
113
275
  const openWithChrome = () => {
114
276
  if (platform === "darwin") {
115
277
  child_process.execSync(`open -a "Google Chrome" "${resolvedPath}"`, { stdio: "ignore" });
@@ -134,32 +296,41 @@ function openReport(reportPath) {
134
296
  };
135
297
  try {
136
298
  if (openWithChrome()) {
299
+ helperTrace("open-report:chrome:success", platform);
137
300
  console.log("\u{1F680} Google Chrome\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
138
301
  return;
139
302
  }
140
- } catch {
303
+ } catch (error) {
304
+ helperTrace("open-report:chrome:failed", getErrorSummary(error));
141
305
  }
142
306
  try {
143
307
  if (openWithDefaultBrowser()) {
308
+ helperTrace("open-report:default-browser:success", platform);
144
309
  console.log("\u{1F680} \uAE30\uBCF8 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB9AC\uD3EC\uD2B8\uB97C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4.");
145
310
  return;
146
311
  }
147
- } catch (e) {
148
- console.error("\u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800 \uC5F4\uAE30 \uC2E4\uD328:", e);
312
+ } catch (error) {
313
+ helperTrace("open-report:default-browser:failed", getErrorSummary(error));
314
+ console.error("\u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800 \uC5F4\uAE30 \uC2E4\uD328:", error);
149
315
  return;
150
316
  }
317
+ helperTrace("open-report:unsupported-platform", platform);
151
318
  console.error(`\u26A0\uFE0F \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD50C\uB7AB\uD3FC\uC785\uB2C8\uB2E4: ${platform}`);
152
319
  }
153
320
  function getDiffArgs() {
154
321
  const args4 = process.argv.slice(2);
155
322
  const commitIndex = args4.indexOf("--commit");
156
323
  const { includeParams, excludeParams } = getGitDiffFilter();
324
+ helperTrace("diff-args:resolve:start", `args=${JSON.stringify(args4)}`);
157
325
  let diffArgs = "";
158
326
  if (commitIndex !== -1) {
159
327
  const commitHash = args4[commitIndex + 1];
160
328
  if (!commitHash) {
161
- console.error("\u274C \uCEE4\uBC0B \uD574\uC2DC\uAC00 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.");
162
- process.exit(1);
329
+ helperTrace("diff-args:commit-hash-missing");
330
+ exitWithError("\u274C \uCEE4\uBC0B \uD574\uC2DC\uAC00 \uC81C\uACF5\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4.", {
331
+ scope: "helper:getDiffArgs",
332
+ args: args4
333
+ });
163
334
  }
164
335
  const nextArg = args4[commitIndex + 2];
165
336
  let n = 0;
@@ -169,28 +340,37 @@ function getDiffArgs() {
169
340
  n = 0;
170
341
  }
171
342
  }
343
+ helperTrace("diff-args:commit-mode", `${commitHash}~${n + 1} ${commitHash}`);
172
344
  console.log(`\u2139\uFE0F \uCEE4\uBC0B '${commitHash}' ${n > 0 ? ` \uD3EC\uD568 \uCD1D ${n + 1}\uAC1C\uC758 \uCEE4\uBC0B` : ""}\uC744 \uB9AC\uBDF0\uD569\uB2C8\uB2E4...`);
173
345
  diffArgs = `${commitHash}~${n + 1} ${commitHash}`;
174
346
  } else {
175
347
  try {
348
+ helperTrace("diff-args:unstaged-check:start");
176
349
  const check = child_process.execSync(`git diff --name-only -- ${includeParams} ${excludeParams}`).toString();
177
350
  if (!check.trim()) {
351
+ helperTrace("diff-args:unstaged-check:empty", "use HEAD~1 HEAD");
178
352
  console.log("\u2139\uFE0F Unstaged \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uB9C8\uC9C0\uB9C9 \uCEE4\uBC0B(HEAD)\uC744 \uB9AC\uBDF0\uD569\uB2C8\uB2E4...");
179
353
  diffArgs = "HEAD~1 HEAD";
354
+ } else {
355
+ helperTrace("diff-args:unstaged-check:has-changes", `length=${check.length}`);
180
356
  }
181
- } catch {
357
+ } catch (error) {
358
+ helperTrace("diff-args:unstaged-check:failed", getErrorSummary(error));
182
359
  }
183
360
  }
361
+ helperTrace("diff-args:resolve:done", diffArgs || "(default)");
184
362
  return diffArgs;
185
363
  }
186
364
  async function showSelectionAIService() {
187
365
  const selectedServiceFromArgs = parseServiceFromArgs();
188
366
  if (selectedServiceFromArgs) {
367
+ helperTrace("show-selection:from-args", selectedServiceFromArgs);
189
368
  console.log(`
190
369
  \u2705 \x1B[32m${selectedServiceFromArgs}\x1B[0m \uC11C\uBE44\uC2A4\uAC00 \uC120\uD0DD\uB418\uC5C8\uC2B5\uB2C8\uB2E4. (--service)
191
370
  `);
192
371
  return selectedServiceFromArgs;
193
372
  }
373
+ helperTrace("show-selection:interactive:start");
194
374
  let selectedIndex = 0;
195
375
  const rl = readline__default.default.createInterface({
196
376
  input: process.stdin,
@@ -204,6 +384,7 @@ async function showSelectionAIService() {
204
384
  readline__default.default.moveCursor(process.stdout, 0, -(AIServices.length + 1));
205
385
  }
206
386
  firstRender = false;
387
+ helperTrace("show-selection:interactive:render", AIServices[selectedIndex] || "unknown");
207
388
  readline__default.default.clearScreenDown(process.stdout);
208
389
  process.stdout.write(
209
390
  "\u{1F916} AI \uC11C\uBE44\uC2A4\uB97C \uC120\uD0DD\uD574\uC8FC\uC138\uC694 (\x1B[33m\u2191\u2193 \uBC29\uD5A5\uD0A4\x1B[0m \uC774\uB3D9, \x1B[33mEnter\x1B[0m \uC120\uD0DD):\n"
@@ -223,6 +404,7 @@ async function showSelectionAIService() {
223
404
  const onData = (data) => {
224
405
  const key = data.toString();
225
406
  if (key === "") {
407
+ helperTrace("show-selection:interactive:ctrl-c");
226
408
  process.stdout.write("\x1B[?25h");
227
409
  process.exit(0);
228
410
  }
@@ -243,6 +425,7 @@ async function showSelectionAIService() {
243
425
  `);
244
426
  const result = AIServices[selectedIndex];
245
427
  if (result) {
428
+ helperTrace("show-selection:interactive:confirmed", result);
246
429
  resolve(result);
247
430
  }
248
431
  }
@@ -356,14 +539,17 @@ var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
356
539
  { path: namingRulesPath, display: "\uB124\uC774\uBC0D \uADDC\uCE59" },
357
540
  { path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
358
541
  ];
359
- const existingRuleFiles = rules.filter((rule) => fs5__default.default.existsSync(rule.path)).map((rule) => rule.path);
542
+ const existingRuleFiles = rules.filter((rule) => fs__default.default.existsSync(rule.path)).map((rule) => rule.path);
360
543
  trace("rules:loaded", `count=${existingRuleFiles.length}`);
361
- const reviewFormExists = fs5__default.default.existsSync(reviewFormPath2);
544
+ const reviewFormExists = fs__default.default.existsSync(reviewFormPath2);
362
545
  trace("reviewForm:status", reviewFormExists ? "exists" : "missing");
363
546
  const systemPromptFiles = reviewFormExists ? [...existingRuleFiles, reviewFormPath2] : existingRuleFiles;
364
547
  const prompt = "\uC704 \uADDC\uCE59\uB4E4\uC744 \uCC38\uACE0\uD558\uC5EC \uC774 diff\uB97C \uCF54\uB4DC\uB9AC\uBDF0\uD574\uC918. \uB9AC\uBDF0\uC591\uC2DD\uC5D0 \uB9DE\uCDB0\uC11C \uC791\uC131\uD574\uC918.";
548
+ trace("prompt:prepared", `length=${prompt.length}`);
549
+ trace("system-prompt-files", `count=${systemPromptFiles.length}`);
365
550
  const modelCandidates = toUnique(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
366
551
  trace("model:candidates", modelCandidates.join(", "));
552
+ trace("command:candidates:count", String(modelCandidates.length + 1));
367
553
  if (customModel) {
368
554
  console.warn(
369
555
  `\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
@@ -404,6 +590,7 @@ var createClaudeCommand = (tempDiffPath2, reviewFormPath2) => {
404
590
  \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
405
591
  ${safeCommand}"`;
406
592
  }
593
+ trace("command:mode", "execute");
407
594
  trace("createClaudeCommand:end");
408
595
  return command;
409
596
  };
@@ -414,23 +601,25 @@ function checkClaudeCliInstalled() {
414
601
  trace2("version-check:run", "claude --version");
415
602
  child_process.execSync("claude --version", { stdio: "ignore" });
416
603
  trace2("version-check:ok");
417
- } catch {
418
- trace2("version-check:failed", "install-start");
604
+ } catch (error) {
605
+ trace2("version-check:failed", getErrorSummary(error));
606
+ trace2("install:start", "@anthropic-ai/claude-code");
419
607
  console.log(
420
608
  "\u2139\uFE0F claude-cli\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4... npm install -g @anthropic-ai/claude-code"
421
609
  );
422
610
  try {
423
611
  child_process.execSync("npm install -g @anthropic-ai/claude-code", { stdio: "inherit" });
424
- trace2("install:ok", "exit(1) for login");
612
+ trace2("install:ok", "login-required");
425
613
  console.log("\u2705 claude-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
426
614
  console.log("\u26A0\uFE0F claude-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
427
615
  console.log(' \uD130\uBBF8\uB110\uC5D0\uC11C "claude" \uB97C \uC785\uB825\uD558\uC5EC \uBE0C\uB77C\uC6B0\uC800 \uB85C\uADF8\uC778\uC744 \uC644\uB8CC\uD55C \uD6C4, \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.');
428
616
  process.exit(1);
429
617
  } catch (installError) {
430
- trace2("install:failed");
431
- console.error("\u274C claude-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).");
432
- console.error(installError);
433
- process.exit(1);
618
+ trace2("install:failed", getErrorSummary(installError));
619
+ exitWithError("\u274C claude-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).", {
620
+ scope: "installation-claude",
621
+ error: installError
622
+ });
434
623
  }
435
624
  }
436
625
  trace2("checkClaudeCliInstalled:end");
@@ -481,10 +670,10 @@ var createCodexCommand = (tempDiffPath2, reviewFormPath2) => {
481
670
  trace3("createCodexCommand:start", `tempDiffPath=${tempDiffPath2}, reviewFormPath=${reviewFormPath2}`);
482
671
  const customModel = getArgValue2("--model");
483
672
  const reasoningEffort = resolveReasoningEffort2();
484
- const rules = [rulesPath, namingRulesPath, codingConventionRulesPath].filter((filePath) => fs5__default.default.existsSync(filePath)).map((filePath) => `- ${filePath}`).join("\n");
673
+ const rules = [rulesPath, namingRulesPath, codingConventionRulesPath].filter((filePath) => fs__default.default.existsSync(filePath)).map((filePath) => `- ${filePath}`).join("\n");
485
674
  const rulesCount = rules ? rules.split("\n").length : 0;
486
675
  trace3("rules:loaded", `count=${rulesCount}`);
487
- const hasReviewForm = fs5__default.default.existsSync(reviewFormPath2);
676
+ const hasReviewForm = fs__default.default.existsSync(reviewFormPath2);
488
677
  const reviewFormLine = hasReviewForm ? `- ${reviewFormPath2}` : "";
489
678
  trace3("reviewForm:status", reviewFormLine ? "exists" : "missing");
490
679
  const prompt = `\uC544\uB798 \uD30C\uC77C\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C \uCF54\uB4DC \uB9AC\uBDF0\uB97C \uC9C4\uD589\uD574\uC918.
@@ -496,6 +685,7 @@ ${reviewFormLine || "- (\uC5C6\uC74C)"}
496
685
  - ${tempDiffPath2}
497
686
 
498
687
  \uBC18\uB4DC\uC2DC \uB9AC\uBDF0 \uC591\uC2DD\uC5D0 \uB9DE\uCDB0 \uC791\uC131\uD574\uC918.`;
688
+ trace3("prompt:prepared", `length=${prompt.length}`);
499
689
  let command = "";
500
690
  if (customModel) {
501
691
  console.warn("\u26A0\uFE0F \uC9C0\uC815\uD55C \uBAA8\uB378\uC774 \uC5C6\uB294 \uACBD\uC6B0, \uC5D0\uB7EC\uAC00 \uBC1C\uC0DD\uD558\uB2C8 \uC8FC\uC758\uD558\uC138\uC694.");
@@ -521,6 +711,7 @@ ${reviewFormLine || "- (\uC5C6\uC74C)"}
521
711
  \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
522
712
  ${safeCommand}"`;
523
713
  }
714
+ trace3("command:mode", "execute");
524
715
  trace3("createCodexCommand:end");
525
716
  return command;
526
717
  };
@@ -531,21 +722,23 @@ function checkCodexCliInstalled() {
531
722
  trace4("version-check:run", "codex --version");
532
723
  child_process.execSync("codex --version", { stdio: "ignore" });
533
724
  trace4("version-check:ok");
534
- } catch {
535
- trace4("version-check:failed", "install-start");
725
+ } catch (error) {
726
+ trace4("version-check:failed", getErrorSummary(error));
727
+ trace4("install:start", "@openai/codex");
536
728
  console.log("\u2139\uFE0F codex-cli\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4... npm install -g @openai/codex");
537
729
  try {
538
730
  child_process.execSync("npm install -g @openai/codex", { stdio: "inherit" });
539
- trace4("install:ok", "exit(1) for login");
731
+ trace4("install:ok", "login-required");
540
732
  console.log("\u2705 codex-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
541
733
  console.log("\u26A0\uFE0F codex-cli \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
542
734
  console.log(' \uD130\uBBF8\uB110\uC5D0\uC11C "codex login" \uC744 \uC785\uB825\uD558\uC5EC \uB85C\uADF8\uC778\uC744 \uC644\uB8CC\uD55C \uD6C4, \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.');
543
735
  process.exit(1);
544
736
  } catch (installError) {
545
- trace4("install:failed");
546
- console.error("\u274C codex-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).");
547
- console.error(installError);
548
- process.exit(1);
737
+ trace4("install:failed", getErrorSummary(installError));
738
+ exitWithError("\u274C codex-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).", {
739
+ scope: "installation-codex",
740
+ error: installError
741
+ });
549
742
  }
550
743
  }
551
744
  trace4("checkCodexCliInstalled:end");
@@ -653,17 +846,19 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
653
846
  { path: namingRulesPath, display: "\uB124\uC774\uBC0D \uADDC\uCE59" },
654
847
  { path: codingConventionRulesPath, display: "\uCF54\uB529 \uCEE8\uBCA4\uC158" }
655
848
  ];
656
- const validRules = rules.filter((rule) => fs5__default.default.existsSync(rule.path)).map((rule) => `@${rule.path}`).join(", ");
849
+ const validRules = rules.filter((rule) => fs__default.default.existsSync(rule.path)).map((rule) => `@${rule.path}`).join(", ");
657
850
  const rulesCount = validRules ? validRules.split(",").length : 0;
658
851
  trace5("rules:loaded", `count=${rulesCount}`);
659
- const reviewFormRef = fs5__default.default.existsSync(reviewFormPath2) ? `@${reviewFormPath2}` : "(\uC5C6\uC74C)";
852
+ const reviewFormRef = fs__default.default.existsSync(reviewFormPath2) ? `@${reviewFormPath2}` : "(\uC5C6\uC74C)";
660
853
  trace5("reviewForm:status", reviewFormRef === "(\uC5C6\uC74C)" ? "missing" : "exists");
661
854
  const reasoningInstruction = getReasoningInstruction(reasoningEffort);
662
855
  const prompt = `\uB2E4\uC74C \uADDC\uCE59\uB4E4\uC744 \uCC38\uACE0\uD574\uC11C(${validRules || "(\uC5C6\uC74C)"}) \uC774 diff(@${tempDiffPath2})\uB97C \uB9AC\uBDF0\uD574\uC918.
663
856
  \uB9AC\uBDF0 \uC591\uC2DD\uC740 ${reviewFormRef} \uC5D0 \uB9DE\uCDB0\uC11C \uC791\uC131\uD574\uC918.
664
857
  \uCD94\uB860 \uAC15\uB3C4 \uC9C0\uCE68: ${reasoningInstruction}`;
858
+ trace5("prompt:prepared", `length=${prompt.length}`);
665
859
  const modelCandidates = toUnique2(customModel ? [customModel, ...aliasFallbacks] : aliasFallbacks);
666
860
  trace5("model:candidates", modelCandidates.join(", "));
861
+ trace5("command:candidates:count", String(modelCandidates.length + 1));
667
862
  if (customModel) {
668
863
  console.warn(
669
864
  `\u26A0\uFE0F \uCEE4\uC2A4\uD140 \uBAA8\uB378(${customModel})\uC744 \uC6B0\uC120 \uC2DC\uB3C4\uD558\uACE0 \uC2E4\uD328\uD558\uBA74 alias(${aliasFallbacks.join(
@@ -686,6 +881,7 @@ var createGeminiCommand = (tempDiffPath2, reviewFormPath2) => {
686
881
  \uC0DD\uC131\uB420 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30:
687
882
  ${safeCommand}"`;
688
883
  }
884
+ trace5("command:mode", "execute");
689
885
  trace5("createGeminiCommand:end");
690
886
  return command;
691
887
  };
@@ -696,21 +892,23 @@ function checkGeminiCliInstalled() {
696
892
  trace6("version-check:run", "gemini --version");
697
893
  child_process.execSync("gemini --version", { stdio: "ignore" });
698
894
  trace6("version-check:ok");
699
- } catch {
700
- trace6("version-check:failed", "install-start");
895
+ } catch (error) {
896
+ trace6("version-check:failed", getErrorSummary(error));
897
+ trace6("install:start", "@google/gemini-cli");
701
898
  console.log("\u2139\uFE0F gemini-cli\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uB97C \uC9C4\uD589\uD569\uB2C8\uB2E4... npm install -g @google/gemini-cli");
702
899
  try {
703
900
  child_process.execSync("npm install -g @google/gemini-cli", { stdio: "inherit" });
704
- trace6("install:ok", "exit(1) for login");
901
+ trace6("install:ok", "login-required");
705
902
  console.log("\u2705 gemini-cli \uC124\uCE58\uAC00 \uC644\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
706
903
  console.log("\u26A0\uFE0F Gemini API \uC0AC\uC6A9\uC744 \uC704\uD574 \uC778\uC99D\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.");
707
904
  console.log(' \uD130\uBBF8\uB110\uC5D0\uC11C "gemini" \uB97C \uC785\uB825\uD558\uC5EC \uBE0C\uB77C\uC6B0\uC800 \uB85C\uADF8\uC778\uC744 \uC644\uB8CC\uD55C \uD6C4, \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694.');
708
905
  process.exit(1);
709
906
  } catch (installError) {
710
- trace6("install:failed");
711
- console.error("\u274C gemini-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).");
712
- console.error(installError);
713
- process.exit(1);
907
+ trace6("install:failed", getErrorSummary(installError));
908
+ exitWithError("\u274C gemini-cli \uC124\uCE58 \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4. \uAD8C\uD55C \uBB38\uC81C\uC77C \uC218 \uC788\uC2B5\uB2C8\uB2E4 (sudo \uD544\uC694).", {
909
+ scope: "installation-gemini",
910
+ error: installError
911
+ });
714
912
  }
715
913
  }
716
914
  trace6("checkGeminiCliInstalled:end");
@@ -720,30 +918,34 @@ function checkGeminiCliInstalled() {
720
918
  var execAsync = util__default.default.promisify(child_process.exec);
721
919
  async function main() {
722
920
  const args4 = process.argv.slice(2);
921
+ clearTraceMessages();
723
922
  const isTest = isTestMode(args4);
724
923
  const trace7 = createTraceLogger("review-one-by-one", args4);
725
924
  trace7("main:start", `args=${JSON.stringify(args4)}`);
726
- trace7("service-selection:start");
727
- const service = await showSelectionAIService();
728
- trace7("service-selection:done", `service=${service}`);
729
- switch (service) {
730
- case "gemini":
731
- trace7("install-check:start", "service=gemini");
732
- checkGeminiCliInstalled();
733
- trace7("install-check:done", "service=gemini");
734
- break;
735
- case "claude":
736
- trace7("install-check:start", "service=claude");
737
- checkClaudeCliInstalled();
738
- trace7("install-check:done", "service=claude");
739
- break;
740
- case "codex":
741
- trace7("install-check:start", "service=codex");
742
- checkCodexCliInstalled();
743
- trace7("install-check:done", "service=codex");
744
- break;
745
- }
925
+ let service = "";
926
+ let savedDiffPath = "";
927
+ let savedReportPath = "";
746
928
  try {
929
+ trace7("service-selection:start");
930
+ service = await showSelectionAIService();
931
+ trace7("service-selection:done", `service=${service}`);
932
+ switch (service) {
933
+ case "gemini":
934
+ trace7("install-check:start", "service=gemini");
935
+ checkGeminiCliInstalled();
936
+ trace7("install-check:done", "service=gemini");
937
+ break;
938
+ case "claude":
939
+ trace7("install-check:start", "service=claude");
940
+ checkClaudeCliInstalled();
941
+ trace7("install-check:done", "service=claude");
942
+ break;
943
+ case "codex":
944
+ trace7("install-check:start", "service=codex");
945
+ checkCodexCliInstalled();
946
+ trace7("install-check:done", "service=codex");
947
+ break;
948
+ }
747
949
  trace7("review-flow:start");
748
950
  console.log("\u{1F680} AI Code Review\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4...");
749
951
  trace7("report-dir:create:start");
@@ -751,6 +953,7 @@ async function main() {
751
953
  trace7("report-dir:create:done");
752
954
  const { includeParams, excludeParams } = getGitDiffFilter();
753
955
  trace7("diff-filter:loaded", `include=${includeParams} | exclude=${excludeParams}`);
956
+ trace7("diff-args:build:start");
754
957
  const diffArgs = getDiffArgs();
755
958
  trace7("diff-args:build:done", `diffArgs=${diffArgs || "(default)"}`);
756
959
  const filesCommand = `git diff --name-only ${diffArgs} -- ${includeParams} ${excludeParams}`;
@@ -770,26 +973,26 @@ async function main() {
770
973
  trace7("full-diff:done", `length=${fullDiff.length}`);
771
974
  trace7("timestamp:created", nowStr);
772
975
  trace7("temp-diff:write:start", tempDiffPath);
773
- fs5__default.default.writeFileSync(tempDiffPath, fullDiff);
976
+ fs__default.default.writeFileSync(tempDiffPath, fullDiff);
774
977
  trace7("temp-diff:write:done");
775
978
  trace7("saved-diff:copy:start");
776
- const savedDiffPath = getNextFilePath(REPORT_DIR, `${nowStr}-diff`, ".txt");
777
- fs5__default.default.copyFileSync(tempDiffPath, savedDiffPath);
979
+ savedDiffPath = getNextFilePath(REPORT_DIR, `${nowStr}-diff`, ".txt");
980
+ fs__default.default.copyFileSync(tempDiffPath, savedDiffPath);
778
981
  trace7("saved-diff:copy:done", savedDiffPath);
779
- const savedReportPath = getNextFilePath(REPORT_DIR, nowStr, ".md");
982
+ savedReportPath = getNextFilePath(REPORT_DIR, nowStr, ".md");
780
983
  trace7("saved-report:path", savedReportPath);
781
984
  const promises = fileList.map(async (file) => {
985
+ const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
986
+ let command = "";
782
987
  try {
783
988
  trace7("file-review:start", file);
784
989
  console.log(`\u{1F50D} Reviewing: ${file}...`);
785
990
  trace7("file-diff:run", file);
786
991
  const fileDiff = child_process.execSync(`git diff ${diffArgs} -- "${file}"`).toString();
787
992
  trace7("file-diff:done", `${file} | length=${fileDiff.length}`);
788
- const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
789
993
  trace7("file-temp-diff:write:start", tempOneFileDiffPath);
790
- fs5__default.default.writeFileSync(tempOneFileDiffPath, fileDiff);
994
+ fs__default.default.writeFileSync(tempOneFileDiffPath, fileDiff);
791
995
  trace7("file-temp-diff:write:done", tempOneFileDiffPath);
792
- let command = "";
793
996
  trace7("file-command:create:start", file);
794
997
  switch (service) {
795
998
  case "gemini":
@@ -802,7 +1005,7 @@ async function main() {
802
1005
  command = createCodexCommand(tempOneFileDiffPath, reviewFormOneByOnePath);
803
1006
  break;
804
1007
  }
805
- trace7("file-command:create:done", file);
1008
+ trace7("file-command:create:done", `${file} | commandLength=${command.length}`);
806
1009
  trace7("file-command:exec:start", file);
807
1010
  const { stdout } = await execAsync(command, { maxBuffer: 1024 * 1024 * 20 });
808
1011
  const result = stdout.toString();
@@ -816,11 +1019,11 @@ ${result}
816
1019
  `;
817
1020
  console.log(tempReport);
818
1021
  trace7("file-report:append:start", file);
819
- fs5__default.default.appendFileSync(savedReportPath, tempReport);
1022
+ fs__default.default.appendFileSync(savedReportPath, tempReport);
820
1023
  trace7("file-report:append:done", file);
821
1024
  if (isTest) {
822
1025
  trace7("file-test-command:append:start", file);
823
- fs5__default.default.appendFileSync(savedReportPath, `
1026
+ fs__default.default.appendFileSync(savedReportPath, `
824
1027
 
825
1028
  ## \uC0AC\uC6A9\uB41C \uBA85\uB839\uC5B4
826
1029
 
@@ -829,26 +1032,51 @@ ${command}`);
829
1032
  }
830
1033
  trace7("file-review:end", file);
831
1034
  } catch (err) {
832
- trace7("file-review:catch", file);
1035
+ trace7("file-review:catch", `${file} | ${getErrorSummary(err)}`);
1036
+ const errorLogPath = writeErrorReport(err, {
1037
+ scope: "review-one-by-one:file",
1038
+ args: args4,
1039
+ extraSections: [
1040
+ {
1041
+ heading: "Execution Context",
1042
+ markdown: `\`\`\`json
1043
+ ${JSON.stringify(
1044
+ {
1045
+ service,
1046
+ file,
1047
+ command: command || null,
1048
+ tempOneFileDiffPath,
1049
+ savedDiffPath: savedDiffPath || null,
1050
+ savedReportPath: savedReportPath || null
1051
+ },
1052
+ null,
1053
+ 2
1054
+ )}
1055
+ \`\`\``
1056
+ }
1057
+ ]
1058
+ });
833
1059
  console.error(`\u274C Error reviewing file ${file}:`, err);
1060
+ if (errorLogPath) {
1061
+ console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${errorLogPath}`);
1062
+ }
834
1063
  const errorReport = `### File: ${file}
835
1064
  \u274C Review Failed
836
1065
  \`\`\`
837
- ${err}
1066
+ ${getErrorSummary(err)}
838
1067
  \`\`\`
839
1068
 
840
1069
  `;
841
- fs5__default.default.appendFileSync(savedReportPath, errorReport);
1070
+ fs__default.default.appendFileSync(savedReportPath, errorReport);
842
1071
  try {
843
- const tempOneFileDiffPath = `temp_diff_${file.replace(/\//g, "_")}.txt`;
844
- if (fs5__default.default.existsSync(tempOneFileDiffPath)) {
1072
+ if (fs__default.default.existsSync(tempOneFileDiffPath)) {
845
1073
  trace7("file-temp-diff:delete:start(catch)", tempOneFileDiffPath);
846
1074
  deleteFile(tempOneFileDiffPath);
847
1075
  trace7("file-temp-diff:delete:done(catch)", tempOneFileDiffPath);
848
1076
  }
849
- } catch (e) {
850
- trace7("file-temp-diff:delete:failed(catch)", file);
851
- console.error(`\u274C Error deleting temp file for ${file}:`, e);
1077
+ } catch (cleanupError) {
1078
+ trace7("file-temp-diff:delete:failed(catch)", `${file} | ${getErrorSummary(cleanupError)}`);
1079
+ console.error(`\u274C Error deleting temp file for ${file}:`, cleanupError);
852
1080
  }
853
1081
  }
854
1082
  });
@@ -867,12 +1095,44 @@ ${err}
867
1095
  trace7("cleanup-temp-diff:done");
868
1096
  trace7("review-flow:end");
869
1097
  } catch (error) {
870
- trace7("review-flow:catch");
1098
+ trace7("review-flow:catch", getErrorSummary(error));
1099
+ let errorReportPath = "";
1100
+ trace7("cleanup-temp-diff:start(catch)");
1101
+ try {
1102
+ deleteTempDiff();
1103
+ trace7("cleanup-temp-diff:done(catch)");
1104
+ } catch (cleanupError) {
1105
+ trace7("cleanup-temp-diff:failed(catch)", getErrorSummary(cleanupError));
1106
+ console.error("\u26A0\uFE0F \uC784\uC2DC diff \uC815\uB9AC \uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
1107
+ console.error(cleanupError);
1108
+ }
1109
+ trace7("error-report:prepare", `service=${service || "unknown"}`);
1110
+ errorReportPath = writeErrorReport(error, {
1111
+ scope: "review-one-by-one",
1112
+ args: args4,
1113
+ extraSections: [
1114
+ {
1115
+ heading: "Execution Context",
1116
+ markdown: `\`\`\`json
1117
+ ${JSON.stringify(
1118
+ {
1119
+ service: service || null,
1120
+ tempDiffPath,
1121
+ savedDiffPath: savedDiffPath || null,
1122
+ savedReportPath: savedReportPath || null
1123
+ },
1124
+ null,
1125
+ 2
1126
+ )}
1127
+ \`\`\``
1128
+ }
1129
+ ]
1130
+ });
871
1131
  console.error("\u274C \uB9AC\uBDF0 \uB3C4\uC911 \uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.");
872
1132
  console.error(error);
873
- trace7("cleanup-temp-diff:start(catch)");
874
- deleteTempDiff();
875
- trace7("cleanup-temp-diff:done(catch)");
1133
+ if (errorReportPath) {
1134
+ console.error(`\u{1F4C4} \uC5D0\uB7EC \uB85C\uADF8 \uC800\uC7A5 \uC704\uCE58: ${errorReportPath}`);
1135
+ }
876
1136
  process.exit(1);
877
1137
  }
878
1138
  }