vibe-coding-master 0.3.21 → 0.3.23

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.
@@ -7,7 +7,6 @@ const TRANSLATIONS_ROOT = ".ai/vcm/translations";
7
7
  const TRANSLATIONS_RUNTIME_DIR = `${TRANSLATIONS_ROOT}/runtime`;
8
8
  const MEMORY_DIR = `${TRANSLATIONS_ROOT}/memory`;
9
9
  const QUEUE_PATH = `${TRANSLATIONS_RUNTIME_DIR}/queue.json`;
10
- const LEGACY_QUEUE_PATH = `${TRANSLATIONS_ROOT}/queue.json`;
11
10
  const FILE_INDEX_PATH = `${TRANSLATIONS_ROOT}/files/index.json`;
12
11
  const FILE_COMPLETED_DIR = `${TRANSLATIONS_ROOT}/files/completed`;
13
12
  const FILE_RUNTIME_JOBS_DIR = `${TRANSLATIONS_RUNTIME_DIR}/files/jobs`;
@@ -15,10 +14,6 @@ const BOOTSTRAP_INDEX_PATH = `${TRANSLATIONS_ROOT}/bootstrap/index.json`;
15
14
  const BOOTSTRAP_RUNTIME_RUNS_DIR = `${TRANSLATIONS_RUNTIME_DIR}/bootstrap/runs`;
16
15
  const CONVERSATION_RUNTIME_DIR = `${TRANSLATIONS_RUNTIME_DIR}/conversations`;
17
16
  const MEMORY_UPDATE_RUNTIME_DIR = `${TRANSLATIONS_RUNTIME_DIR}/memory-updates`;
18
- const TRANSLATOR_LOG_PATHS = [
19
- `${TRANSLATIONS_RUNTIME_DIR}/codex-translator.log`,
20
- `${TRANSLATIONS_ROOT}/codex-translator.log`
21
- ];
22
17
  const DEFAULT_PROFILE = "default";
23
18
  const DEFAULT_CHUNK_SOURCE_TOKEN_TARGET = 80000;
24
19
  const BOOTSTRAP_DEFAULT_LIMIT = 12;
@@ -115,7 +110,6 @@ export function createCodexTranslationService(deps) {
115
110
  await ensureMemoryFile(repoRoot, "style-guide.md", "# Style Guide\n");
116
111
  await ensureMemoryFile(repoRoot, "project-context.md", "# Project Context\n");
117
112
  await ensureMemoryFile(repoRoot, "decisions.md", "# Decisions\n");
118
- await cleanupTranslatorLogs(repoRoot);
119
113
  }
120
114
  async function ensureMemoryFile(repoRoot, fileName, content) {
121
115
  await deps.fs.ensureFile(resolveRepoPath(repoRoot, `${MEMORY_DIR}/${fileName}`), content);
@@ -129,19 +123,9 @@ export function createCodexTranslationService(deps) {
129
123
  force: true
130
124
  });
131
125
  }
132
- async function cleanupTranslatorLogs(repoRoot) {
133
- await Promise.all(TRANSLATOR_LOG_PATHS.map((relativePath) => removeRepoPath(repoRoot, relativePath)));
134
- }
135
126
  async function loadQueue(repoRoot) {
136
127
  const queuePath = resolveRepoPath(repoRoot, QUEUE_PATH);
137
128
  if (!(await deps.fs.pathExists(queuePath))) {
138
- const legacyQueuePath = resolveRepoPath(repoRoot, LEGACY_QUEUE_PATH);
139
- if (await deps.fs.pathExists(legacyQueuePath)) {
140
- const migrated = normalizeQueue(await deps.fs.readJson(legacyQueuePath));
141
- await deps.fs.writeJsonAtomic(queuePath, migrated);
142
- await removeRepoPath(repoRoot, LEGACY_QUEUE_PATH);
143
- return migrated;
144
- }
145
129
  return {
146
130
  version: 1,
147
131
  updatedAt: now(),
@@ -152,7 +136,6 @@ export function createCodexTranslationService(deps) {
152
136
  }
153
137
  async function saveQueue(repoRoot, queue) {
154
138
  await deps.fs.writeJsonAtomic(resolveRepoPath(repoRoot, QUEUE_PATH), queue);
155
- await removeRepoPath(repoRoot, LEGACY_QUEUE_PATH);
156
139
  }
157
140
  async function loadFileIndex(repoRoot) {
158
141
  const indexPath = resolveRepoPath(repoRoot, FILE_INDEX_PATH);
@@ -195,7 +178,7 @@ export function createCodexTranslationService(deps) {
195
178
  await saveQueue(repoRoot, queue);
196
179
  return queued;
197
180
  }
198
- async function dispatchNext(repoRoot, taskSlug) {
181
+ async function dispatchNext(repoRoot) {
199
182
  if (!deps.runtime || !deps.sessionService) {
200
183
  return;
201
184
  }
@@ -224,7 +207,7 @@ export function createCodexTranslationService(deps) {
224
207
  queue.updatedAt = next.updatedAt;
225
208
  await saveQueue(repoRoot, queue);
226
209
  }
227
- const session = await ensureTranslatorSession(repoRoot, taskSlug, next.targetLanguage);
210
+ const session = await ensureTranslatorSession(repoRoot, next.targetLanguage);
228
211
  await submitTerminalInput(deps.runtime, session.id, batch?.prompt ?? await buildQueuePrompt(repoRoot, next));
229
212
  const dispatchedAt = now();
230
213
  for (const item of batch?.items ?? [next]) {
@@ -272,7 +255,7 @@ export function createCodexTranslationService(deps) {
272
255
  await saveQueue(repoRoot, queue);
273
256
  return { items: candidates, prompt };
274
257
  }
275
- async function ensureTranslatorSession(repoRoot, taskSlug, targetLanguage) {
258
+ async function ensureTranslatorSession(repoRoot, targetLanguage) {
276
259
  void targetLanguage;
277
260
  if (!deps.sessionService) {
278
261
  throw new VcmError({
@@ -281,17 +264,7 @@ export function createCodexTranslationService(deps) {
281
264
  statusCode: 500
282
265
  });
283
266
  }
284
- const existing = await deps.sessionService.getRoleSession(repoRoot, taskSlug, CODEX_TRANSLATOR_ROLE);
285
- if (existing?.status === "running") {
286
- return existing;
287
- }
288
- if (existing?.claudeSessionId) {
289
- return deps.sessionService.resumeRoleSession(repoRoot, taskSlug, CODEX_TRANSLATOR_ROLE, {
290
- model: existing.model,
291
- effort: existing.effort
292
- });
293
- }
294
- return deps.sessionService.startRoleSession(repoRoot, taskSlug, CODEX_TRANSLATOR_ROLE, {
267
+ return deps.sessionService.ensureProjectTranslatorSession(repoRoot, {
295
268
  model: "gpt-5.5",
296
269
  effort: "medium"
297
270
  });
@@ -577,6 +550,7 @@ export function createCodexTranslationService(deps) {
577
550
  try {
578
551
  const request = await deps.fs.readJson(resolveRepoPath(repoRoot, requestPath));
579
552
  return {
553
+ job: isFileJob(request.job) ? request.job : undefined,
580
554
  chunks: Array.isArray(request.chunks) ? request.chunks.filter(isFileTranslationChunk) : []
581
555
  };
582
556
  }
@@ -584,6 +558,37 @@ export function createCodexTranslationService(deps) {
584
558
  return {};
585
559
  }
586
560
  }
561
+ async function loadRuntimeFileJob(repoRoot, item) {
562
+ if (!isFileTranslationQueueItem(item)) {
563
+ return undefined;
564
+ }
565
+ const request = await loadFileTranslationRequest(repoRoot, item.requestPath);
566
+ if (!request.job) {
567
+ return undefined;
568
+ }
569
+ return {
570
+ ...request.job,
571
+ status: toFileJobStatus(item.status),
572
+ queueItemId: item.id,
573
+ updatedAt: item.updatedAt
574
+ };
575
+ }
576
+ async function loadRuntimeFileJobs(repoRoot, queue) {
577
+ const sourceQueue = queue ?? await loadQueue(repoRoot);
578
+ const jobs = await Promise.all(sourceQueue.items
579
+ .filter(isFileTranslationQueueItem)
580
+ .filter((item) => item.status !== "completed")
581
+ .map((item) => loadRuntimeFileJob(repoRoot, item)));
582
+ return jobs
583
+ .filter((job) => Boolean(job))
584
+ .sort(compareFileJobUpdatedAtDesc);
585
+ }
586
+ async function findRuntimeFileJobById(repoRoot, jobId) {
587
+ const queue = await loadQueue(repoRoot);
588
+ const item = queue.items.find((candidate) => isFileTranslationQueueItem(candidate) &&
589
+ candidate.jobId === jobId);
590
+ return item ? loadRuntimeFileJob(repoRoot, item) : undefined;
591
+ }
587
592
  async function validateMemoryBudget(repoRoot) {
588
593
  const [usage, unexpectedEntries] = await Promise.all([
589
594
  getMemoryUsage(repoRoot, deps.fs),
@@ -630,19 +635,29 @@ export function createCodexTranslationService(deps) {
630
635
  if (item.type === "conversation") {
631
636
  return;
632
637
  }
633
- const index = await loadFileIndex(repoRoot);
634
- const job = index.jobs.find((candidate) => candidate.id === item.jobId);
635
- if (job) {
636
- job.status = item.status === "needs_review" ? "needs_review" : item.status;
637
- job.updatedAt = now();
638
- if (item.status === "completed") {
639
- await finalizeCompletedFileJob(repoRoot, job);
640
- job.completedAt = job.updatedAt;
641
- await cleanupSupersededCompletedFileJobs(repoRoot, index);
642
- }
643
- index.updatedAt = job.updatedAt;
644
- await saveFileIndex(repoRoot, index);
638
+ if (!isFileTranslationQueueItem(item) || item.status !== "completed") {
639
+ return;
640
+ }
641
+ const runtimeJob = await loadRuntimeFileJob(repoRoot, item);
642
+ if (!runtimeJob) {
643
+ return;
645
644
  }
645
+ const completedAt = now();
646
+ const completedJob = {
647
+ ...runtimeJob,
648
+ status: "completed",
649
+ updatedAt: completedAt,
650
+ completedAt
651
+ };
652
+ await finalizeCompletedFileJob(repoRoot, completedJob);
653
+ const index = await loadFileIndex(repoRoot);
654
+ index.jobs = [
655
+ completedJob,
656
+ ...index.jobs.filter((job) => job.id !== completedJob.id)
657
+ ];
658
+ await cleanupSupersededCompletedFileJobs(repoRoot, index);
659
+ index.updatedAt = completedAt;
660
+ await saveFileIndex(repoRoot, index);
646
661
  }
647
662
  async function cleanupCompletedRuntime(repoRoot) {
648
663
  const fileIndex = await loadFileIndex(repoRoot);
@@ -674,6 +689,48 @@ export function createCodexTranslationService(deps) {
674
689
  .map((item) => cleanupRuntimeDirectoryForPath(repoRoot, item.requestPath)));
675
690
  await pruneQueueItems(repoRoot, isPrunableCompletedQueueItem);
676
691
  }
692
+ async function cleanupStartupFileIndex(repoRoot) {
693
+ const indexPath = resolveRepoPath(repoRoot, FILE_INDEX_PATH);
694
+ if (!(await deps.fs.pathExists(indexPath))) {
695
+ return;
696
+ }
697
+ const index = await loadFileIndex(repoRoot);
698
+ const seenKeys = new Set();
699
+ const jobs = [];
700
+ for (const job of index.jobs) {
701
+ if (job.status !== "completed" || !isCompletedFileResultPath(job.resultPath)) {
702
+ continue;
703
+ }
704
+ const key = fileTranslationReplacementKey(job);
705
+ if (seenKeys.has(key)) {
706
+ continue;
707
+ }
708
+ if (await deps.fs.pathExists(resolveRepoPath(repoRoot, job.resultPath))) {
709
+ seenKeys.add(key);
710
+ jobs.push(job);
711
+ }
712
+ }
713
+ if (jobs.length === index.jobs.length) {
714
+ return;
715
+ }
716
+ index.jobs = jobs;
717
+ index.updatedAt = now();
718
+ await saveFileIndex(repoRoot, index);
719
+ }
720
+ async function cleanupStartupBootstrapIndex(repoRoot) {
721
+ const indexPath = resolveRepoPath(repoRoot, BOOTSTRAP_INDEX_PATH);
722
+ if (!(await deps.fs.pathExists(indexPath))) {
723
+ return;
724
+ }
725
+ const index = await loadBootstrapIndex(repoRoot);
726
+ const runs = index.runs.filter((run) => run.status === "completed");
727
+ if (runs.length === index.runs.length) {
728
+ return;
729
+ }
730
+ index.runs = runs;
731
+ index.updatedAt = now();
732
+ await saveBootstrapIndex(repoRoot, index);
733
+ }
677
734
  async function finalizeCompletedFileJob(repoRoot, job) {
678
735
  const finalResultPath = completedFileResultPath(job.sourcePath, job.targetLanguage, job.translationProfile);
679
736
  const absoluteCurrentResultPath = resolveRepoPath(repoRoot, job.resultPath);
@@ -750,6 +807,11 @@ export function createCodexTranslationService(deps) {
750
807
  await saveQueue(repoRoot, queue);
751
808
  }
752
809
  return {
810
+ async cleanupStartupRuntime(repoRoot) {
811
+ await removeRepoPath(repoRoot, TRANSLATIONS_RUNTIME_DIR, true);
812
+ await cleanupStartupFileIndex(repoRoot);
813
+ await cleanupStartupBootstrapIndex(repoRoot);
814
+ },
753
815
  async getState(repoRoot) {
754
816
  await ensureLayout(repoRoot);
755
817
  await cleanupCompletedRuntime(repoRoot);
@@ -759,9 +821,13 @@ export function createCodexTranslationService(deps) {
759
821
  loadBootstrapIndex(repoRoot),
760
822
  isMemoryInitialized(repoRoot, deps.fs)
761
823
  ]);
824
+ const runtimeFileJobs = await loadRuntimeFileJobs(repoRoot, queue);
762
825
  return {
763
826
  queue,
764
- fileIndex,
827
+ fileIndex: visibleFileTranslationIndex({
828
+ ...fileIndex,
829
+ jobs: [...runtimeFileJobs, ...fileIndex.jobs]
830
+ }),
765
831
  bootstrapIndex,
766
832
  memoryInitialized
767
833
  };
@@ -822,7 +888,13 @@ export function createCodexTranslationService(deps) {
822
888
  const targetLanguage = input.targetLanguage.trim() || "zh-CN";
823
889
  const profile = input.translationProfile?.trim() || DEFAULT_PROFILE;
824
890
  const dedupeKey = sha256(`${sourceHash}|${targetLanguage}|${profile}`);
825
- const index = await loadFileIndex(repoRoot);
891
+ const replacementKey = fileTranslationReplacementKeyFromParts(sourcePath, targetLanguage, profile);
892
+ const activeExisting = (await loadRuntimeFileJobs(repoRoot)).find((job) => fileTranslationReplacementKey(job) === replacementKey &&
893
+ isActiveFileTranslationJobStatus(job.status));
894
+ if (activeExisting) {
895
+ void dispatchNext(repoRoot);
896
+ return activeExisting;
897
+ }
826
898
  const timestamp = now();
827
899
  const jobId = `file-${safeId(path.basename(sourcePath, path.extname(sourcePath)))}-${Date.now()}-${createId().slice(0, 8)}`;
828
900
  const jobRoot = `${FILE_RUNTIME_JOBS_DIR}/${jobId}`;
@@ -919,12 +991,7 @@ export function createCodexTranslationService(deps) {
919
991
  lastUpdatedAt: timestamp
920
992
  });
921
993
  await deps.fs.writeText(resolveRepoPath(repoRoot, job.reportPath), `# Translation Report\n\nStatus: queued\nJob: ${jobId}\n`);
922
- index.jobs = [job, ...index.jobs];
923
- index.updatedAt = timestamp;
924
- await saveFileIndex(repoRoot, index);
925
- if (input.taskSlug) {
926
- void dispatchNext(repoRoot, input.taskSlug);
927
- }
994
+ void dispatchNext(repoRoot);
928
995
  return job;
929
996
  },
930
997
  async createBootstrapRun(repoRoot, input) {
@@ -981,9 +1048,7 @@ export function createCodexTranslationService(deps) {
981
1048
  index.runs = [run, ...index.runs];
982
1049
  index.updatedAt = timestamp;
983
1050
  await saveBootstrapIndex(repoRoot, index);
984
- if (input.taskSlug) {
985
- void dispatchNext(repoRoot, input.taskSlug);
986
- }
1051
+ void dispatchNext(repoRoot);
987
1052
  return run;
988
1053
  },
989
1054
  async createMemoryUpdate(repoRoot, input) {
@@ -1039,15 +1104,14 @@ export function createCodexTranslationService(deps) {
1039
1104
  "Delete or merge stale, duplicate, temporary, and task-local content."
1040
1105
  ]
1041
1106
  });
1042
- if (input.taskSlug) {
1043
- void dispatchNext(repoRoot, input.taskSlug);
1044
- }
1107
+ void dispatchNext(repoRoot);
1045
1108
  return queueItem;
1046
1109
  },
1047
1110
  async readFileJobOutput(repoRoot, jobId) {
1048
1111
  await ensureLayout(repoRoot);
1049
1112
  const index = await loadFileIndex(repoRoot);
1050
- const job = index.jobs.find((candidate) => candidate.id === jobId);
1113
+ const job = index.jobs.find((candidate) => candidate.id === jobId)
1114
+ ?? await findRuntimeFileJobById(repoRoot, jobId);
1051
1115
  if (!job) {
1052
1116
  throw new VcmError({
1053
1117
  code: "TRANSLATION_JOB_MISSING",
@@ -1074,14 +1138,12 @@ export function createCodexTranslationService(deps) {
1074
1138
  });
1075
1139
  }
1076
1140
  const timestamp = now();
1077
- const jobId = `conversation-${safeId(input.role)}-${Date.now()}-${createId().slice(0, 8)}`;
1078
- const jobRoot = `${CONVERSATION_RUNTIME_DIR}/${safeId(input.taskSlug)}/${safeId(input.role)}/jobs/${jobId}`;
1141
+ const jobId = `conversation-${Date.now()}-${createId().slice(0, 8)}`;
1142
+ const jobRoot = `${CONVERSATION_RUNTIME_DIR}/jobs/${jobId}`;
1079
1143
  const sourceHash = `sha256:${sha256(sourceText)}`;
1080
1144
  const targetLanguage = input.targetLanguage.trim() || "zh-CN";
1081
1145
  const job = {
1082
1146
  id: jobId,
1083
- taskSlug: input.taskSlug,
1084
- role: input.role,
1085
1147
  direction: input.direction,
1086
1148
  sourceHash,
1087
1149
  sourceLanguage: input.sourceLanguage.trim() || "auto",
@@ -1105,15 +1167,10 @@ export function createCodexTranslationService(deps) {
1105
1167
  version: 1,
1106
1168
  baseRepoRoot: repoRoot,
1107
1169
  pathBase: "baseRepoRoot",
1108
- job,
1109
- taskSlug: input.taskSlug,
1110
- role: input.role,
1111
1170
  direction: input.direction,
1112
- sourceHash,
1113
1171
  sourceLanguage: job.sourceLanguage,
1114
1172
  targetLanguage,
1115
1173
  translationProfile: input.translationProfile?.trim() || DEFAULT_PROFILE,
1116
- contextText: input.contextText,
1117
1174
  sourceContentBoundary: "VCM_TEXT",
1118
1175
  sourceText,
1119
1176
  absolutePaths: {
@@ -1126,8 +1183,8 @@ export function createCodexTranslationService(deps) {
1126
1183
  format: "plain-text"
1127
1184
  }
1128
1185
  });
1129
- if (input.taskSlug && !input.deferDispatch) {
1130
- void dispatchNext(repoRoot, input.taskSlug);
1186
+ if (!input.deferDispatch) {
1187
+ void dispatchNext(repoRoot);
1131
1188
  }
1132
1189
  return job;
1133
1190
  },
@@ -1208,6 +1265,7 @@ export function createCodexTranslationService(deps) {
1208
1265
  return job;
1209
1266
  },
1210
1267
  async handleCodexHook(repoRoot, eventName, taskSlug) {
1268
+ void taskSlug;
1211
1269
  if (eventName === "UserPromptSubmit") {
1212
1270
  const queue = await loadQueue(repoRoot);
1213
1271
  const active = queue.activeItemId
@@ -1224,10 +1282,11 @@ export function createCodexTranslationService(deps) {
1224
1282
  }
1225
1283
  if (eventName === "Stop") {
1226
1284
  await validateActiveQueueItem(repoRoot);
1227
- if (taskSlug) {
1228
- await dispatchNext(repoRoot, taskSlug);
1229
- }
1285
+ await dispatchNext(repoRoot);
1230
1286
  }
1287
+ },
1288
+ ensureTranslatorSession(repoRoot) {
1289
+ return ensureTranslatorSession(repoRoot, "zh-CN");
1231
1290
  }
1232
1291
  };
1233
1292
  }
@@ -1607,12 +1666,60 @@ function completedFileResultPath(sourcePath, targetLanguage, translationProfile)
1607
1666
  return `${FILE_COMPLETED_DIR}/${sourceBaseName}-${languagePart}-${profilePart}-${sourcePathHash}.md`;
1608
1667
  }
1609
1668
  function fileTranslationReplacementKey(job) {
1669
+ return fileTranslationReplacementKeyFromParts(job.sourcePath, job.targetLanguage, job.translationProfile);
1670
+ }
1671
+ function fileTranslationReplacementKeyFromParts(sourcePath, targetLanguage, translationProfile) {
1610
1672
  return [
1611
- normalizeRepoRelative(job.sourcePath),
1612
- job.targetLanguage.trim(),
1613
- (job.translationProfile || DEFAULT_PROFILE).trim()
1673
+ normalizeRepoRelative(sourcePath),
1674
+ targetLanguage.trim(),
1675
+ (translationProfile || DEFAULT_PROFILE).trim()
1614
1676
  ].join("\0");
1615
1677
  }
1678
+ function isActiveFileTranslationJobStatus(status) {
1679
+ return status === "queued" || status === "running" || status === "validating";
1680
+ }
1681
+ function isFileTranslationQueueItem(item) {
1682
+ return item.type === "file" || item.type === "force-retranslate";
1683
+ }
1684
+ function toFileJobStatus(status) {
1685
+ if (status === "dispatching") {
1686
+ return "running";
1687
+ }
1688
+ return status === "completed" ||
1689
+ status === "queued" ||
1690
+ status === "running" ||
1691
+ status === "validating" ||
1692
+ status === "needs_review" ||
1693
+ status === "failed" ||
1694
+ status === "interrupted" ||
1695
+ status === "skipped" ||
1696
+ status === "cancelled"
1697
+ ? status
1698
+ : "failed";
1699
+ }
1700
+ function compareFileJobUpdatedAtDesc(left, right) {
1701
+ return (right.updatedAt ?? "").localeCompare(left.updatedAt ?? "");
1702
+ }
1703
+ function isCompletedFileResultPath(relativePath) {
1704
+ const normalized = normalizeRepoRelative(relativePath);
1705
+ return normalized.startsWith(`${FILE_COMPLETED_DIR}/`);
1706
+ }
1707
+ function visibleFileTranslationIndex(index) {
1708
+ const seenKeys = new Set();
1709
+ const jobs = [];
1710
+ for (const job of index.jobs) {
1711
+ const key = fileTranslationReplacementKey(job);
1712
+ if (seenKeys.has(key)) {
1713
+ continue;
1714
+ }
1715
+ seenKeys.add(key);
1716
+ jobs.push(job);
1717
+ }
1718
+ return {
1719
+ ...index,
1720
+ jobs
1721
+ };
1722
+ }
1616
1723
  function retainedCompletedFileJobIds(index) {
1617
1724
  const seenKeys = new Set();
1618
1725
  const retainedIds = new Set();
@@ -1637,10 +1744,7 @@ function isPrunableCompletedQueueItem(item) {
1637
1744
  }
1638
1745
  function isTranslationRuntimeDirectory(relativePath) {
1639
1746
  const normalized = normalizeRepoRelative(relativePath);
1640
- return normalized.startsWith(`${TRANSLATIONS_RUNTIME_DIR}/`) ||
1641
- normalized.startsWith(`${TRANSLATIONS_ROOT}/files/jobs/`) ||
1642
- normalized.startsWith(`${TRANSLATIONS_ROOT}/bootstrap/runs/`) ||
1643
- normalized.startsWith(`${TRANSLATIONS_ROOT}/conversations/`);
1747
+ return normalized.startsWith(`${TRANSLATIONS_RUNTIME_DIR}/`);
1644
1748
  }
1645
1749
  async function readStandaloneConversationResult(repoRoot, resultRelativePath, fs) {
1646
1750
  const resultPath = resolveRepoPath(repoRoot, resultRelativePath);