vibe-coding-master 0.3.21 → 0.3.22

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.
@@ -64,11 +64,18 @@ export function registerArtifactRoutes(app, deps) {
64
64
  const task = await deps.taskService.loadTask(project.repoRoot, request.params.taskSlug);
65
65
  const taskRepoRoot = getTaskRuntimeRepoRoot(task);
66
66
  const paths = deps.artifactService.getHandoffPaths(taskRepoRoot, task.handoffDir);
67
+ const artifactPath = paths.roleLogPaths[request.params.role];
68
+ if (!artifactPath) {
69
+ return {
70
+ role: request.params.role,
71
+ content: ""
72
+ };
73
+ }
67
74
  return {
68
75
  role: request.params.role,
69
76
  content: await deps.artifactService.readArtifact({
70
77
  repoRoot: taskRepoRoot,
71
- artifactPath: paths.roleLogPaths[request.params.role]
78
+ artifactPath
72
79
  })
73
80
  };
74
81
  });
@@ -4,7 +4,9 @@ export function registerProjectRoutes(app, deps) {
4
4
  return deps.projectService.getRecentRepositoryPaths();
5
5
  });
6
6
  app.post("/api/projects/connect", async (request) => {
7
- return deps.projectService.connectProject(request.body);
7
+ const project = await deps.projectService.connectProject(request.body);
8
+ await deps.codexTranslationService?.cleanupStartupRuntime(project.repoRoot);
9
+ return project;
8
10
  });
9
11
  app.get("/api/projects/current", async () => {
10
12
  return deps.projectService.getCurrentProject();
@@ -88,7 +88,9 @@ function degradedArtifactSummary(handoffDir) {
88
88
  logsDir,
89
89
  messagesDir,
90
90
  roleCommandPaths: Object.fromEntries(DISPATCHABLE_ROLES.map((role) => [role, `${roleCommandsDir}/${role}.md`])),
91
- roleLogPaths: Object.fromEntries(ROLE_NAMES.map((role) => [role, `${logsDir}/${role}.log`])),
91
+ roleLogPaths: Object.fromEntries(ROLE_NAMES
92
+ .filter((role) => role !== "codex-translator")
93
+ .map((role) => [role, `${logsDir}/${role}.log`])),
92
94
  messageRoutePaths: {},
93
95
  architecturePlanPath: `${handoffDir}/architecture-plan.md`,
94
96
  knownIssuesPath: `${handoffDir}/known-issues.md`,
@@ -75,7 +75,10 @@ export async function createServer(deps, options = {}) {
75
75
  projectService: deps.projectService,
76
76
  codexTranslationService: deps.codexTranslationService
77
77
  });
78
- registerProjectRoutes(app, { projectService: deps.projectService });
78
+ registerProjectRoutes(app, {
79
+ projectService: deps.projectService,
80
+ codexTranslationService: deps.codexTranslationService
81
+ });
79
82
  registerHarnessRoutes(app, {
80
83
  projectService: deps.projectService,
81
84
  harnessService: deps.harnessService
@@ -118,6 +121,7 @@ export async function createServer(deps, options = {}) {
118
121
  registerGatewayRoutes(app, { gatewayService: deps.gatewayService });
119
122
  registerTerminalWs(app, { runtime: deps.runtime });
120
123
  app.addHook("onReady", async () => {
124
+ await cleanupRecentTranslationRuntime(deps);
121
125
  await deps.gatewayService.start();
122
126
  });
123
127
  app.addHook("onClose", async () => {
@@ -134,6 +138,10 @@ export async function createServer(deps, options = {}) {
134
138
  }
135
139
  return app;
136
140
  }
141
+ async function cleanupRecentTranslationRuntime(deps) {
142
+ const repoRoots = await deps.projectService.getRecentRepositoryPaths();
143
+ await Promise.all(repoRoots.map((repoRoot) => deps.codexTranslationService.cleanupStartupRuntime(repoRoot)));
144
+ }
137
145
  export async function startServer(options = {}) {
138
146
  const host = options.host ?? "127.0.0.1";
139
147
  const port = options.port ?? 4173;
@@ -42,8 +42,7 @@ export function createArtifactService(fs) {
42
42
  architect: path.posix.join(logsDir, "architect.log"),
43
43
  coder: path.posix.join(logsDir, "coder.log"),
44
44
  reviewer: path.posix.join(logsDir, "reviewer.log"),
45
- "codex-reviewer": path.posix.join(logsDir, "codex-reviewer.log"),
46
- "codex-translator": path.posix.join(logsDir, "codex-translator.log")
45
+ "codex-reviewer": path.posix.join(logsDir, "codex-reviewer.log")
47
46
  },
48
47
  messageRoutePaths: getDefaultMessageRoutePaths(messagesDir),
49
48
  architecturePlanPath: path.posix.join(handoffDir, "architecture-plan.md"),
@@ -179,7 +178,15 @@ export function createArtifactService(fs) {
179
178
  });
180
179
  }
181
180
  const paths = this.getHandoffPaths(input.repoRoot, input.handoffDir);
182
- await fs.appendText(resolveRepoPath(input.repoRoot, paths.roleLogPaths[input.role]), input.content);
181
+ const roleLogPath = paths.roleLogPaths[input.role];
182
+ if (!roleLogPath) {
183
+ throw new VcmError({
184
+ code: "ROLE_LOG_UNAVAILABLE",
185
+ message: `${input.role} does not write a handoff log.`,
186
+ statusCode: 409
187
+ });
188
+ }
189
+ await fs.appendText(resolveRepoPath(input.repoRoot, roleLogPath), input.content);
183
190
  }
184
191
  };
185
192
  }
@@ -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);
@@ -577,6 +560,7 @@ export function createCodexTranslationService(deps) {
577
560
  try {
578
561
  const request = await deps.fs.readJson(resolveRepoPath(repoRoot, requestPath));
579
562
  return {
563
+ job: isFileJob(request.job) ? request.job : undefined,
580
564
  chunks: Array.isArray(request.chunks) ? request.chunks.filter(isFileTranslationChunk) : []
581
565
  };
582
566
  }
@@ -584,6 +568,37 @@ export function createCodexTranslationService(deps) {
584
568
  return {};
585
569
  }
586
570
  }
571
+ async function loadRuntimeFileJob(repoRoot, item) {
572
+ if (!isFileTranslationQueueItem(item)) {
573
+ return undefined;
574
+ }
575
+ const request = await loadFileTranslationRequest(repoRoot, item.requestPath);
576
+ if (!request.job) {
577
+ return undefined;
578
+ }
579
+ return {
580
+ ...request.job,
581
+ status: toFileJobStatus(item.status),
582
+ queueItemId: item.id,
583
+ updatedAt: item.updatedAt
584
+ };
585
+ }
586
+ async function loadRuntimeFileJobs(repoRoot, queue) {
587
+ const sourceQueue = queue ?? await loadQueue(repoRoot);
588
+ const jobs = await Promise.all(sourceQueue.items
589
+ .filter(isFileTranslationQueueItem)
590
+ .filter((item) => item.status !== "completed")
591
+ .map((item) => loadRuntimeFileJob(repoRoot, item)));
592
+ return jobs
593
+ .filter((job) => Boolean(job))
594
+ .sort(compareFileJobUpdatedAtDesc);
595
+ }
596
+ async function findRuntimeFileJobById(repoRoot, jobId) {
597
+ const queue = await loadQueue(repoRoot);
598
+ const item = queue.items.find((candidate) => isFileTranslationQueueItem(candidate) &&
599
+ candidate.jobId === jobId);
600
+ return item ? loadRuntimeFileJob(repoRoot, item) : undefined;
601
+ }
587
602
  async function validateMemoryBudget(repoRoot) {
588
603
  const [usage, unexpectedEntries] = await Promise.all([
589
604
  getMemoryUsage(repoRoot, deps.fs),
@@ -630,19 +645,29 @@ export function createCodexTranslationService(deps) {
630
645
  if (item.type === "conversation") {
631
646
  return;
632
647
  }
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);
648
+ if (!isFileTranslationQueueItem(item) || item.status !== "completed") {
649
+ return;
650
+ }
651
+ const runtimeJob = await loadRuntimeFileJob(repoRoot, item);
652
+ if (!runtimeJob) {
653
+ return;
645
654
  }
655
+ const completedAt = now();
656
+ const completedJob = {
657
+ ...runtimeJob,
658
+ status: "completed",
659
+ updatedAt: completedAt,
660
+ completedAt
661
+ };
662
+ await finalizeCompletedFileJob(repoRoot, completedJob);
663
+ const index = await loadFileIndex(repoRoot);
664
+ index.jobs = [
665
+ completedJob,
666
+ ...index.jobs.filter((job) => job.id !== completedJob.id)
667
+ ];
668
+ await cleanupSupersededCompletedFileJobs(repoRoot, index);
669
+ index.updatedAt = completedAt;
670
+ await saveFileIndex(repoRoot, index);
646
671
  }
647
672
  async function cleanupCompletedRuntime(repoRoot) {
648
673
  const fileIndex = await loadFileIndex(repoRoot);
@@ -674,6 +699,48 @@ export function createCodexTranslationService(deps) {
674
699
  .map((item) => cleanupRuntimeDirectoryForPath(repoRoot, item.requestPath)));
675
700
  await pruneQueueItems(repoRoot, isPrunableCompletedQueueItem);
676
701
  }
702
+ async function cleanupStartupFileIndex(repoRoot) {
703
+ const indexPath = resolveRepoPath(repoRoot, FILE_INDEX_PATH);
704
+ if (!(await deps.fs.pathExists(indexPath))) {
705
+ return;
706
+ }
707
+ const index = await loadFileIndex(repoRoot);
708
+ const seenKeys = new Set();
709
+ const jobs = [];
710
+ for (const job of index.jobs) {
711
+ if (job.status !== "completed" || !isCompletedFileResultPath(job.resultPath)) {
712
+ continue;
713
+ }
714
+ const key = fileTranslationReplacementKey(job);
715
+ if (seenKeys.has(key)) {
716
+ continue;
717
+ }
718
+ if (await deps.fs.pathExists(resolveRepoPath(repoRoot, job.resultPath))) {
719
+ seenKeys.add(key);
720
+ jobs.push(job);
721
+ }
722
+ }
723
+ if (jobs.length === index.jobs.length) {
724
+ return;
725
+ }
726
+ index.jobs = jobs;
727
+ index.updatedAt = now();
728
+ await saveFileIndex(repoRoot, index);
729
+ }
730
+ async function cleanupStartupBootstrapIndex(repoRoot) {
731
+ const indexPath = resolveRepoPath(repoRoot, BOOTSTRAP_INDEX_PATH);
732
+ if (!(await deps.fs.pathExists(indexPath))) {
733
+ return;
734
+ }
735
+ const index = await loadBootstrapIndex(repoRoot);
736
+ const runs = index.runs.filter((run) => run.status === "completed");
737
+ if (runs.length === index.runs.length) {
738
+ return;
739
+ }
740
+ index.runs = runs;
741
+ index.updatedAt = now();
742
+ await saveBootstrapIndex(repoRoot, index);
743
+ }
677
744
  async function finalizeCompletedFileJob(repoRoot, job) {
678
745
  const finalResultPath = completedFileResultPath(job.sourcePath, job.targetLanguage, job.translationProfile);
679
746
  const absoluteCurrentResultPath = resolveRepoPath(repoRoot, job.resultPath);
@@ -750,6 +817,11 @@ export function createCodexTranslationService(deps) {
750
817
  await saveQueue(repoRoot, queue);
751
818
  }
752
819
  return {
820
+ async cleanupStartupRuntime(repoRoot) {
821
+ await removeRepoPath(repoRoot, TRANSLATIONS_RUNTIME_DIR, true);
822
+ await cleanupStartupFileIndex(repoRoot);
823
+ await cleanupStartupBootstrapIndex(repoRoot);
824
+ },
753
825
  async getState(repoRoot) {
754
826
  await ensureLayout(repoRoot);
755
827
  await cleanupCompletedRuntime(repoRoot);
@@ -759,9 +831,13 @@ export function createCodexTranslationService(deps) {
759
831
  loadBootstrapIndex(repoRoot),
760
832
  isMemoryInitialized(repoRoot, deps.fs)
761
833
  ]);
834
+ const runtimeFileJobs = await loadRuntimeFileJobs(repoRoot, queue);
762
835
  return {
763
836
  queue,
764
- fileIndex,
837
+ fileIndex: visibleFileTranslationIndex({
838
+ ...fileIndex,
839
+ jobs: [...runtimeFileJobs, ...fileIndex.jobs]
840
+ }),
765
841
  bootstrapIndex,
766
842
  memoryInitialized
767
843
  };
@@ -822,7 +898,15 @@ export function createCodexTranslationService(deps) {
822
898
  const targetLanguage = input.targetLanguage.trim() || "zh-CN";
823
899
  const profile = input.translationProfile?.trim() || DEFAULT_PROFILE;
824
900
  const dedupeKey = sha256(`${sourceHash}|${targetLanguage}|${profile}`);
825
- const index = await loadFileIndex(repoRoot);
901
+ const replacementKey = fileTranslationReplacementKeyFromParts(sourcePath, targetLanguage, profile);
902
+ const activeExisting = (await loadRuntimeFileJobs(repoRoot)).find((job) => fileTranslationReplacementKey(job) === replacementKey &&
903
+ isActiveFileTranslationJobStatus(job.status));
904
+ if (activeExisting) {
905
+ if (input.taskSlug) {
906
+ void dispatchNext(repoRoot, input.taskSlug);
907
+ }
908
+ return activeExisting;
909
+ }
826
910
  const timestamp = now();
827
911
  const jobId = `file-${safeId(path.basename(sourcePath, path.extname(sourcePath)))}-${Date.now()}-${createId().slice(0, 8)}`;
828
912
  const jobRoot = `${FILE_RUNTIME_JOBS_DIR}/${jobId}`;
@@ -919,9 +1003,6 @@ export function createCodexTranslationService(deps) {
919
1003
  lastUpdatedAt: timestamp
920
1004
  });
921
1005
  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
1006
  if (input.taskSlug) {
926
1007
  void dispatchNext(repoRoot, input.taskSlug);
927
1008
  }
@@ -1047,7 +1128,8 @@ export function createCodexTranslationService(deps) {
1047
1128
  async readFileJobOutput(repoRoot, jobId) {
1048
1129
  await ensureLayout(repoRoot);
1049
1130
  const index = await loadFileIndex(repoRoot);
1050
- const job = index.jobs.find((candidate) => candidate.id === jobId);
1131
+ const job = index.jobs.find((candidate) => candidate.id === jobId)
1132
+ ?? await findRuntimeFileJobById(repoRoot, jobId);
1051
1133
  if (!job) {
1052
1134
  throw new VcmError({
1053
1135
  code: "TRANSLATION_JOB_MISSING",
@@ -1607,12 +1689,60 @@ function completedFileResultPath(sourcePath, targetLanguage, translationProfile)
1607
1689
  return `${FILE_COMPLETED_DIR}/${sourceBaseName}-${languagePart}-${profilePart}-${sourcePathHash}.md`;
1608
1690
  }
1609
1691
  function fileTranslationReplacementKey(job) {
1692
+ return fileTranslationReplacementKeyFromParts(job.sourcePath, job.targetLanguage, job.translationProfile);
1693
+ }
1694
+ function fileTranslationReplacementKeyFromParts(sourcePath, targetLanguage, translationProfile) {
1610
1695
  return [
1611
- normalizeRepoRelative(job.sourcePath),
1612
- job.targetLanguage.trim(),
1613
- (job.translationProfile || DEFAULT_PROFILE).trim()
1696
+ normalizeRepoRelative(sourcePath),
1697
+ targetLanguage.trim(),
1698
+ (translationProfile || DEFAULT_PROFILE).trim()
1614
1699
  ].join("\0");
1615
1700
  }
1701
+ function isActiveFileTranslationJobStatus(status) {
1702
+ return status === "queued" || status === "running" || status === "validating";
1703
+ }
1704
+ function isFileTranslationQueueItem(item) {
1705
+ return item.type === "file" || item.type === "force-retranslate";
1706
+ }
1707
+ function toFileJobStatus(status) {
1708
+ if (status === "dispatching") {
1709
+ return "running";
1710
+ }
1711
+ return status === "completed" ||
1712
+ status === "queued" ||
1713
+ status === "running" ||
1714
+ status === "validating" ||
1715
+ status === "needs_review" ||
1716
+ status === "failed" ||
1717
+ status === "interrupted" ||
1718
+ status === "skipped" ||
1719
+ status === "cancelled"
1720
+ ? status
1721
+ : "failed";
1722
+ }
1723
+ function compareFileJobUpdatedAtDesc(left, right) {
1724
+ return (right.updatedAt ?? "").localeCompare(left.updatedAt ?? "");
1725
+ }
1726
+ function isCompletedFileResultPath(relativePath) {
1727
+ const normalized = normalizeRepoRelative(relativePath);
1728
+ return normalized.startsWith(`${FILE_COMPLETED_DIR}/`);
1729
+ }
1730
+ function visibleFileTranslationIndex(index) {
1731
+ const seenKeys = new Set();
1732
+ const jobs = [];
1733
+ for (const job of index.jobs) {
1734
+ const key = fileTranslationReplacementKey(job);
1735
+ if (seenKeys.has(key)) {
1736
+ continue;
1737
+ }
1738
+ seenKeys.add(key);
1739
+ jobs.push(job);
1740
+ }
1741
+ return {
1742
+ ...index,
1743
+ jobs
1744
+ };
1745
+ }
1616
1746
  function retainedCompletedFileJobIds(index) {
1617
1747
  const seenKeys = new Set();
1618
1748
  const retainedIds = new Set();
@@ -1637,10 +1767,7 @@ function isPrunableCompletedQueueItem(item) {
1637
1767
  }
1638
1768
  function isTranslationRuntimeDirectory(relativePath) {
1639
1769
  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/`);
1770
+ return normalized.startsWith(`${TRANSLATIONS_RUNTIME_DIR}/`);
1644
1771
  }
1645
1772
  async function readStandaloneConversationResult(repoRoot, resultRelativePath, fs) {
1646
1773
  const resultPath = resolveRepoPath(repoRoot, resultRelativePath);
@@ -13,11 +13,6 @@ const CODEX_CONFIG_PATH = ".ai/codex/config.toml";
13
13
  const CODEX_TRANSLATOR_DIR = ".ai/codex-translator";
14
14
  const CODEX_TRANSLATION_DIR = ".ai/vcm/translations";
15
15
  const CODEX_TRANSLATOR_SESSION_PATH = ".ai/vcm/translations/runtime/session.json";
16
- const LEGACY_CODEX_TRANSLATOR_SESSION_PATH = ".ai/vcm/translations/session.json";
17
- const CODEX_TRANSLATOR_LOG_PATHS = [
18
- ".ai/vcm/translations/runtime/codex-translator.log",
19
- ".ai/vcm/translations/codex-translator.log"
20
- ];
21
16
  const CODEX_TRANSLATOR_CONFIG_PATH = ".ai/codex-translator/config.toml";
22
17
  export function createSessionService(deps) {
23
18
  const now = deps.now ?? (() => new Date().toISOString());
@@ -42,9 +37,6 @@ export function createSessionService(deps) {
42
37
  const effort = isCodexRole
43
38
  ? normalizeCodexEffort(input.effort ?? persisted?.effort)
44
39
  : normalizeClaudeEffort(input.effort ?? persisted?.effort);
45
- if (isTranslator) {
46
- await cleanupCodexTranslatorLogs(deps.fs, repoRoot);
47
- }
48
40
  const claudeSessionId = launchMode === "resume"
49
41
  ? persisted?.claudeSessionId
50
42
  : randomUUID();
@@ -412,34 +404,17 @@ async function loadPersistedRoleRecordForRole(fs, baseRepoRoot, taskRepoRoot, st
412
404
  return loadPersistedRoleRecord(fs, taskRepoRoot, stateRoot, taskSlug, role);
413
405
  }
414
406
  async function loadPersistedCodexTranslatorSession(fs, repoRoot, taskSlug) {
415
- let sessionPath = resolveRepoPath(repoRoot, CODEX_TRANSLATOR_SESSION_PATH);
407
+ const sessionPath = resolveRepoPath(repoRoot, CODEX_TRANSLATOR_SESSION_PATH);
416
408
  if (!(await fs.pathExists(sessionPath))) {
417
- const legacySessionPath = resolveRepoPath(repoRoot, LEGACY_CODEX_TRANSLATOR_SESSION_PATH);
418
- if (!(await fs.pathExists(legacySessionPath))) {
419
- return undefined;
420
- }
421
- sessionPath = legacySessionPath;
409
+ return undefined;
422
410
  }
423
411
  const payload = await fs.readJson(sessionPath);
424
412
  const record = normalizePersistedRoleRecord(isProjectRoleSessionFile(payload) ? payload.record : payload);
425
413
  if (!record) {
426
414
  return undefined;
427
415
  }
428
- if (sessionPath.endsWith(LEGACY_CODEX_TRANSLATOR_SESSION_PATH)) {
429
- await persistCodexTranslatorSession(fs, repoRoot, {
430
- ...record,
431
- taskSlug
432
- });
433
- await fs.removePath?.(sessionPath, { force: true });
434
- }
435
416
  return scopeProjectRoleSession(record, taskSlug);
436
417
  }
437
- async function cleanupCodexTranslatorLogs(fs, repoRoot) {
438
- if (!fs.removePath) {
439
- return;
440
- }
441
- await Promise.all(CODEX_TRANSLATOR_LOG_PATHS.map((relativePath) => fs.removePath?.(resolveRepoPath(repoRoot, relativePath), { force: true })));
442
- }
443
418
  async function loadPersistedRoleRecord(fs, repoRoot, stateRoot, taskSlug, role) {
444
419
  const current = await loadPersistedTaskSessionRecord(fs, repoRoot, stateRoot, taskSlug);
445
420
  return normalizePersistedRoleRecord(current?.roles[role]?.record);
@@ -54,7 +54,9 @@ function degradedArtifactSummary(handoffDir) {
54
54
  logsDir,
55
55
  messagesDir,
56
56
  roleCommandPaths: Object.fromEntries(DISPATCHABLE_ROLES.map((role) => [role, `${roleCommandsDir}/${role}.md`])),
57
- roleLogPaths: Object.fromEntries(ROLE_NAMES.map((role) => [role, `${logsDir}/${role}.log`])),
57
+ roleLogPaths: Object.fromEntries(ROLE_NAMES
58
+ .filter((role) => role !== "codex-translator")
59
+ .map((role) => [role, `${logsDir}/${role}.log`])),
58
60
  messageRoutePaths: {},
59
61
  architecturePlanPath: `${handoffDir}/architecture-plan.md`,
60
62
  knownIssuesPath: `${handoffDir}/known-issues.md`,
@@ -79,7 +79,7 @@ Error generating stack: `+l.message+`
79
79
  `))}function c(w,E,x,v){const S=x.enter("tableCell"),g=x.enter("phrasing"),_=x.containerPhrasing(w,{...v,before:y,after:y});return g(),S(),_}function h(w,E){return cw(w,{align:E,alignDelimiters:o,padding:s,stringLength:p})}function d(w,E,x){const v=w.children;let S=-1;const g=[],_=E.enter("table");for(;++S<v.length;)g[S]=u(v[S],E,x);return _(),g}function u(w,E,x){const v=w.children;let S=-1;const g=[],_=E.enter("tableRow");for(;++S<v.length;)g[S]=c(v[S],w,E,x);return _(),g}function b(w,E,x){let v=h_.inlineCode(w,E,x);return x.stack.includes("tableCell")&&(v=v.replace(/\|/g,"\\$&")),v}}function Xw(){return{exit:{taskListCheckValueChecked:Xm,taskListCheckValueUnchecked:Xm,paragraph:Zw}}}function Qw(){return{unsafe:[{atBreak:!0,character:"-",after:"[:|-]"}],handlers:{listItem:Jw}}}function Xm(n){const r=this.stack[this.stack.length-2];r.type,r.checked=n.type==="taskListCheckValueChecked"}function Zw(n){const r=this.stack[this.stack.length-2];if(r&&r.type==="listItem"&&typeof r.checked=="boolean"){const s=this.stack[this.stack.length-1];s.type;const o=s.children[0];if(o&&o.type==="text"){const p=r.children;let y=-1,f;for(;++y<p.length;){const a=p[y];if(a.type==="paragraph"){f=a;break}}f===s&&(o.value=o.value.slice(1),o.value.length===0?s.children.shift():s.position&&o.position&&typeof o.position.start.offset=="number"&&(o.position.start.column++,o.position.start.offset++,s.position.start=Object.assign({},o.position.start)))}}this.exit(n)}function Jw(n,r,s,o){const p=n.children[0],y=typeof n.checked=="boolean"&&p&&p.type==="paragraph",f="["+(n.checked?"x":" ")+"] ",a=s.createTracker(o);y&&a.move(f);let c=h_.listItem(n,r,s,{...o,...a.current()});return y&&(c=c.replace(/^(?:[*+-]|\d+\.)([\r\n]| {1,3})/,h)),c;function h(d){return d+f}}function ex(){return[LC(),JC(),iw(),qw(),Xw()]}function tx(n){return{extensions:[OC(),ew(n),rw(),Ww(n),Qw()]}}const nx={tokenize:ox,partial:!0},f_={tokenize:cx,partial:!0},d_={tokenize:ux,partial:!0},p_={tokenize:hx,partial:!0},ix={tokenize:fx,partial:!0},m_={name:"wwwAutolink",tokenize:lx,previous:__},g_={name:"protocolAutolink",tokenize:ax,previous:v_},ii={name:"emailAutolink",tokenize:sx,previous:y_},Nn={};function rx(){return{text:Nn}}let Ji=48;for(;Ji<123;)Nn[Ji]=ii,Ji++,Ji===58?Ji=65:Ji===91&&(Ji=97);Nn[43]=ii;Nn[45]=ii;Nn[46]=ii;Nn[95]=ii;Nn[72]=[ii,g_];Nn[104]=[ii,g_];Nn[87]=[ii,m_];Nn[119]=[ii,m_];function sx(n,r,s){const o=this;let p,y;return f;function f(u){return!Ou(u)||!y_.call(o,o.previous)||nh(o.events)?s(u):(n.enter("literalAutolink"),n.enter("literalAutolinkEmail"),a(u))}function a(u){return Ou(u)?(n.consume(u),a):u===64?(n.consume(u),c):s(u)}function c(u){return u===46?n.check(ix,d,h)(u):u===45||u===95||It(u)?(y=!0,n.consume(u),c):d(u)}function h(u){return n.consume(u),p=!0,c}function d(u){return y&&p&&qt(o.previous)?(n.exit("literalAutolinkEmail"),n.exit("literalAutolink"),r(u)):s(u)}}function lx(n,r,s){const o=this;return p;function p(f){return f!==87&&f!==119||!__.call(o,o.previous)||nh(o.events)?s(f):(n.enter("literalAutolink"),n.enter("literalAutolinkWww"),n.check(nx,n.attempt(f_,n.attempt(d_,y),s),s)(f))}function y(f){return n.exit("literalAutolinkWww"),n.exit("literalAutolink"),r(f)}}function ax(n,r,s){const o=this;let p="",y=!1;return f;function f(u){return(u===72||u===104)&&v_.call(o,o.previous)&&!nh(o.events)?(n.enter("literalAutolink"),n.enter("literalAutolinkHttp"),p+=String.fromCodePoint(u),n.consume(u),a):s(u)}function a(u){if(qt(u)&&p.length<5)return p+=String.fromCodePoint(u),n.consume(u),a;if(u===58){const b=p.toLowerCase();if(b==="http"||b==="https")return n.consume(u),c}return s(u)}function c(u){return u===47?(n.consume(u),y?h:(y=!0,c)):s(u)}function h(u){return u===null||Ra(u)||ot(u)||er(u)||ja(u)?s(u):n.attempt(f_,n.attempt(d_,d),s)(u)}function d(u){return n.exit("literalAutolinkHttp"),n.exit("literalAutolink"),r(u)}}function ox(n,r,s){let o=0;return p;function p(f){return(f===87||f===119)&&o<3?(o++,n.consume(f),p):f===46&&o===3?(n.consume(f),y):s(f)}function y(f){return f===null?s(f):r(f)}}function cx(n,r,s){let o,p,y;return f;function f(h){return h===46||h===95?n.check(p_,c,a)(h):h===null||ot(h)||er(h)||h!==45&&ja(h)?c(h):(y=!0,n.consume(h),f)}function a(h){return h===95?o=!0:(p=o,o=void 0),n.consume(h),f}function c(h){return p||o||!y?s(h):r(h)}}function ux(n,r){let s=0,o=0;return p;function p(f){return f===40?(s++,n.consume(f),p):f===41&&o<s?y(f):f===33||f===34||f===38||f===39||f===41||f===42||f===44||f===46||f===58||f===59||f===60||f===63||f===93||f===95||f===126?n.check(p_,r,y)(f):f===null||ot(f)||er(f)?r(f):(n.consume(f),p)}function y(f){return f===41&&o++,n.consume(f),p}}function hx(n,r,s){return o;function o(a){return a===33||a===34||a===39||a===41||a===42||a===44||a===46||a===58||a===59||a===63||a===95||a===126?(n.consume(a),o):a===38?(n.consume(a),y):a===93?(n.consume(a),p):a===60||a===null||ot(a)||er(a)?r(a):s(a)}function p(a){return a===null||a===40||a===91||ot(a)||er(a)?r(a):o(a)}function y(a){return qt(a)?f(a):s(a)}function f(a){return a===59?(n.consume(a),o):qt(a)?(n.consume(a),f):s(a)}}function fx(n,r,s){return o;function o(y){return n.consume(y),p}function p(y){return It(y)?s(y):r(y)}}function __(n){return n===null||n===40||n===42||n===95||n===91||n===93||n===126||ot(n)}function v_(n){return!qt(n)}function y_(n){return!(n===47||Ou(n))}function Ou(n){return n===43||n===45||n===46||n===95||It(n)}function nh(n){let r=n.length,s=!1;for(;r--;){const o=n[r][1];if((o.type==="labelLink"||o.type==="labelImage")&&!o._balanced){s=!0;break}if(o._gfmAutolinkLiteralWalkedInto){s=!1;break}}return n.length>0&&!s&&(n[n.length-1][1]._gfmAutolinkLiteralWalkedInto=!0),s}const dx={tokenize:bx,partial:!0};function px(){return{document:{91:{name:"gfmFootnoteDefinition",tokenize:vx,continuation:{tokenize:yx},exit:Sx}},text:{91:{name:"gfmFootnoteCall",tokenize:_x},93:{name:"gfmPotentialFootnoteCall",add:"after",tokenize:mx,resolveTo:gx}}}}function mx(n,r,s){const o=this;let p=o.events.length;const y=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let f;for(;p--;){const c=o.events[p][1];if(c.type==="labelImage"){f=c;break}if(c.type==="gfmFootnoteCall"||c.type==="labelLink"||c.type==="label"||c.type==="image"||c.type==="link")break}return a;function a(c){if(!f||!f._balanced)return s(c);const h=An(o.sliceSerialize({start:f.end,end:o.now()}));return h.codePointAt(0)!==94||!y.includes(h.slice(1))?s(c):(n.enter("gfmFootnoteCallLabelMarker"),n.consume(c),n.exit("gfmFootnoteCallLabelMarker"),r(c))}}function gx(n,r){let s=n.length;for(;s--;)if(n[s][1].type==="labelImage"&&n[s][0]==="enter"){n[s][1];break}n[s+1][1].type="data",n[s+3][1].type="gfmFootnoteCallLabelMarker";const o={type:"gfmFootnoteCall",start:Object.assign({},n[s+3][1].start),end:Object.assign({},n[n.length-1][1].end)},p={type:"gfmFootnoteCallMarker",start:Object.assign({},n[s+3][1].end),end:Object.assign({},n[s+3][1].end)};p.end.column++,p.end.offset++,p.end._bufferIndex++;const y={type:"gfmFootnoteCallString",start:Object.assign({},p.end),end:Object.assign({},n[n.length-1][1].start)},f={type:"chunkString",contentType:"string",start:Object.assign({},y.start),end:Object.assign({},y.end)},a=[n[s+1],n[s+2],["enter",o,r],n[s+3],n[s+4],["enter",p,r],["exit",p,r],["enter",y,r],["enter",f,r],["exit",f,r],["exit",y,r],n[n.length-2],n[n.length-1],["exit",o,r]];return n.splice(s,n.length-s+1,...a),n}function _x(n,r,s){const o=this,p=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let y=0,f;return a;function a(u){return n.enter("gfmFootnoteCall"),n.enter("gfmFootnoteCallLabelMarker"),n.consume(u),n.exit("gfmFootnoteCallLabelMarker"),c}function c(u){return u!==94?s(u):(n.enter("gfmFootnoteCallMarker"),n.consume(u),n.exit("gfmFootnoteCallMarker"),n.enter("gfmFootnoteCallString"),n.enter("chunkString").contentType="string",h)}function h(u){if(y>999||u===93&&!f||u===null||u===91||ot(u))return s(u);if(u===93){n.exit("chunkString");const b=n.exit("gfmFootnoteCallString");return p.includes(An(o.sliceSerialize(b)))?(n.enter("gfmFootnoteCallLabelMarker"),n.consume(u),n.exit("gfmFootnoteCallLabelMarker"),n.exit("gfmFootnoteCall"),r):s(u)}return ot(u)||(f=!0),y++,n.consume(u),u===92?d:h}function d(u){return u===91||u===92||u===93?(n.consume(u),y++,h):h(u)}}function vx(n,r,s){const o=this,p=o.parser.gfmFootnotes||(o.parser.gfmFootnotes=[]);let y,f=0,a;return c;function c(E){return n.enter("gfmFootnoteDefinition")._container=!0,n.enter("gfmFootnoteDefinitionLabel"),n.enter("gfmFootnoteDefinitionLabelMarker"),n.consume(E),n.exit("gfmFootnoteDefinitionLabelMarker"),h}function h(E){return E===94?(n.enter("gfmFootnoteDefinitionMarker"),n.consume(E),n.exit("gfmFootnoteDefinitionMarker"),n.enter("gfmFootnoteDefinitionLabelString"),n.enter("chunkString").contentType="string",d):s(E)}function d(E){if(f>999||E===93&&!a||E===null||E===91||ot(E))return s(E);if(E===93){n.exit("chunkString");const x=n.exit("gfmFootnoteDefinitionLabelString");return y=An(o.sliceSerialize(x)),n.enter("gfmFootnoteDefinitionLabelMarker"),n.consume(E),n.exit("gfmFootnoteDefinitionLabelMarker"),n.exit("gfmFootnoteDefinitionLabel"),b}return ot(E)||(a=!0),f++,n.consume(E),E===92?u:d}function u(E){return E===91||E===92||E===93?(n.consume(E),f++,d):d(E)}function b(E){return E===58?(n.enter("definitionMarker"),n.consume(E),n.exit("definitionMarker"),p.includes(y)||p.push(y),Ke(n,w,"gfmFootnoteDefinitionWhitespace")):s(E)}function w(E){return r(E)}}function yx(n,r,s){return n.check(ll,r,n.attempt(dx,r,s))}function Sx(n){n.exit("gfmFootnoteDefinition")}function bx(n,r,s){const o=this;return Ke(n,p,"gfmFootnoteDefinitionIndent",5);function p(y){const f=o.events[o.events.length-1];return f&&f[1].type==="gfmFootnoteDefinitionIndent"&&f[2].sliceSerialize(f[1],!0).length===4?r(y):s(y)}}function Cx(n){let s=(n||{}).singleTilde;const o={name:"strikethrough",tokenize:y,resolveAll:p};return s==null&&(s=!0),{text:{126:o},insideSpan:{null:[o]},attentionMarkers:{null:[126]}};function p(f,a){let c=-1;for(;++c<f.length;)if(f[c][0]==="enter"&&f[c][1].type==="strikethroughSequenceTemporary"&&f[c][1]._close){let h=c;for(;h--;)if(f[h][0]==="exit"&&f[h][1].type==="strikethroughSequenceTemporary"&&f[h][1]._open&&f[c][1].end.offset-f[c][1].start.offset===f[h][1].end.offset-f[h][1].start.offset){f[c][1].type="strikethroughSequence",f[h][1].type="strikethroughSequence";const d={type:"strikethrough",start:Object.assign({},f[h][1].start),end:Object.assign({},f[c][1].end)},u={type:"strikethroughText",start:Object.assign({},f[h][1].end),end:Object.assign({},f[c][1].start)},b=[["enter",d,a],["enter",f[h][1],a],["exit",f[h][1],a],["enter",u,a]],w=a.parser.constructs.insideSpan.null;w&&hn(b,b.length,0,za(w,f.slice(h+1,c),a)),hn(b,b.length,0,[["exit",u,a],["enter",f[c][1],a],["exit",f[c][1],a],["exit",d,a]]),hn(f,h-1,c-h+3,b),c=h+b.length-2;break}}for(c=-1;++c<f.length;)f[c][1].type==="strikethroughSequenceTemporary"&&(f[c][1].type="data");return f}function y(f,a,c){const h=this.previous,d=this.events;let u=0;return b;function b(E){return h===126&&d[d.length-1][1].type!=="characterEscape"?c(E):(f.enter("strikethroughSequenceTemporary"),w(E))}function w(E){const x=Xr(h);if(E===126)return u>1?c(E):(f.consume(E),u++,w);if(u<2&&!s)return c(E);const v=f.exit("strikethroughSequenceTemporary"),S=Xr(E);return v._open=!S||S===2&&!!x,v._close=!x||x===2&&!!S,a(E)}}}class wx{constructor(){this.map=[]}add(r,s,o){xx(this,r,s,o)}consume(r){if(this.map.sort(function(y,f){return y[0]-f[0]}),this.map.length===0)return;let s=this.map.length;const o=[];for(;s>0;)s-=1,o.push(r.slice(this.map[s][0]+this.map[s][1]),this.map[s][2]),r.length=this.map[s][0];o.push(r.slice()),r.length=0;let p=o.pop();for(;p;){for(const y of p)r.push(y);p=o.pop()}this.map.length=0}}function xx(n,r,s,o){let p=0;if(!(s===0&&o.length===0)){for(;p<n.map.length;){if(n.map[p][0]===r){n.map[p][1]+=s,n.map[p][2].push(...o);return}p+=1}n.map.push([r,s,o])}}function Ex(n,r){let s=!1;const o=[];for(;r<n.length;){const p=n[r];if(s){if(p[0]==="enter")p[1].type==="tableContent"&&o.push(n[r+1][1].type==="tableDelimiterMarker"?"left":"none");else if(p[1].type==="tableContent"){if(n[r-1][1].type==="tableDelimiterMarker"){const y=o.length-1;o[y]=o[y]==="left"?"center":"right"}}else if(p[1].type==="tableDelimiterRow")break}else p[0]==="enter"&&p[1].type==="tableDelimiterRow"&&(s=!0);r+=1}return o}function kx(){return{flow:{null:{name:"table",tokenize:Ax,resolveAll:Tx}}}}function Ax(n,r,s){const o=this;let p=0,y=0,f;return a;function a(N){let I=o.events.length-1;for(;I>-1;){const Y=o.events[I][1].type;if(Y==="lineEnding"||Y==="linePrefix")I--;else break}const P=I>-1?o.events[I][1].type:null,F=P==="tableHead"||P==="tableRow"?D:c;return F===D&&o.parser.lazy[o.now().line]?s(N):F(N)}function c(N){return n.enter("tableHead"),n.enter("tableRow"),h(N)}function h(N){return N===124||(f=!0,y+=1),d(N)}function d(N){return N===null?s(N):Ne(N)?y>1?(y=0,o.interrupt=!0,n.exit("tableRow"),n.enter("lineEnding"),n.consume(N),n.exit("lineEnding"),w):s(N):Ve(N)?Ke(n,d,"whitespace")(N):(y+=1,f&&(f=!1,p+=1),N===124?(n.enter("tableCellDivider"),n.consume(N),n.exit("tableCellDivider"),f=!0,d):(n.enter("data"),u(N)))}function u(N){return N===null||N===124||ot(N)?(n.exit("data"),d(N)):(n.consume(N),N===92?b:u)}function b(N){return N===92||N===124?(n.consume(N),u):u(N)}function w(N){return o.interrupt=!1,o.parser.lazy[o.now().line]?s(N):(n.enter("tableDelimiterRow"),f=!1,Ve(N)?Ke(n,E,"linePrefix",o.parser.constructs.disable.null.includes("codeIndented")?void 0:4)(N):E(N))}function E(N){return N===45||N===58?v(N):N===124?(f=!0,n.enter("tableCellDivider"),n.consume(N),n.exit("tableCellDivider"),x):M(N)}function x(N){return Ve(N)?Ke(n,v,"whitespace")(N):v(N)}function v(N){return N===58?(y+=1,f=!0,n.enter("tableDelimiterMarker"),n.consume(N),n.exit("tableDelimiterMarker"),S):N===45?(y+=1,S(N)):N===null||Ne(N)?A(N):M(N)}function S(N){return N===45?(n.enter("tableDelimiterFiller"),g(N)):M(N)}function g(N){return N===45?(n.consume(N),g):N===58?(f=!0,n.exit("tableDelimiterFiller"),n.enter("tableDelimiterMarker"),n.consume(N),n.exit("tableDelimiterMarker"),_):(n.exit("tableDelimiterFiller"),_(N))}function _(N){return Ve(N)?Ke(n,A,"whitespace")(N):A(N)}function A(N){return N===124?E(N):N===null||Ne(N)?!f||p!==y?M(N):(n.exit("tableDelimiterRow"),n.exit("tableHead"),r(N)):M(N)}function M(N){return s(N)}function D(N){return n.enter("tableRow"),T(N)}function T(N){return N===124?(n.enter("tableCellDivider"),n.consume(N),n.exit("tableCellDivider"),T):N===null||Ne(N)?(n.exit("tableRow"),r(N)):Ve(N)?Ke(n,T,"whitespace")(N):(n.enter("data"),k(N))}function k(N){return N===null||N===124||ot(N)?(n.exit("data"),T(N)):(n.consume(N),N===92?R:k)}function R(N){return N===92||N===124?(n.consume(N),k):k(N)}}function Tx(n,r){let s=-1,o=!0,p=0,y=[0,0,0,0],f=[0,0,0,0],a=!1,c=0,h,d,u;const b=new wx;for(;++s<n.length;){const w=n[s],E=w[1];w[0]==="enter"?E.type==="tableHead"?(a=!1,c!==0&&(Qm(b,r,c,h,d),d=void 0,c=0),h={type:"table",start:Object.assign({},E.start),end:Object.assign({},E.end)},b.add(s,0,[["enter",h,r]])):E.type==="tableRow"||E.type==="tableDelimiterRow"?(o=!0,u=void 0,y=[0,0,0,0],f=[0,s+1,0,0],a&&(a=!1,d={type:"tableBody",start:Object.assign({},E.start),end:Object.assign({},E.end)},b.add(s,0,[["enter",d,r]])),p=E.type==="tableDelimiterRow"?2:d?3:1):p&&(E.type==="data"||E.type==="tableDelimiterMarker"||E.type==="tableDelimiterFiller")?(o=!1,f[2]===0&&(y[1]!==0&&(f[0]=f[1],u=ka(b,r,y,p,void 0,u),y=[0,0,0,0]),f[2]=s)):E.type==="tableCellDivider"&&(o?o=!1:(y[1]!==0&&(f[0]=f[1],u=ka(b,r,y,p,void 0,u)),y=f,f=[y[1],s,0,0])):E.type==="tableHead"?(a=!0,c=s):E.type==="tableRow"||E.type==="tableDelimiterRow"?(c=s,y[1]!==0?(f[0]=f[1],u=ka(b,r,y,p,s,u)):f[1]!==0&&(u=ka(b,r,f,p,s,u)),p=0):p&&(E.type==="data"||E.type==="tableDelimiterMarker"||E.type==="tableDelimiterFiller")&&(f[3]=s)}for(c!==0&&Qm(b,r,c,h,d),b.consume(r.events),s=-1;++s<r.events.length;){const w=r.events[s];w[0]==="enter"&&w[1].type==="table"&&(w[1]._align=Ex(r.events,s))}return n}function ka(n,r,s,o,p,y){const f=o===1?"tableHeader":o===2?"tableDelimiter":"tableData",a="tableContent";s[0]!==0&&(y.end=Object.assign({},$r(r.events,s[0])),n.add(s[0],0,[["exit",y,r]]));const c=$r(r.events,s[1]);if(y={type:f,start:Object.assign({},c),end:Object.assign({},c)},n.add(s[1],0,[["enter",y,r]]),s[2]!==0){const h=$r(r.events,s[2]),d=$r(r.events,s[3]),u={type:a,start:Object.assign({},h),end:Object.assign({},d)};if(n.add(s[2],0,[["enter",u,r]]),o!==2){const b=r.events[s[2]],w=r.events[s[3]];if(b[1].end=Object.assign({},w[1].end),b[1].type="chunkText",b[1].contentType="text",s[3]>s[2]+1){const E=s[2]+1,x=s[3]-s[2]-1;n.add(E,x,[])}}n.add(s[3]+1,0,[["exit",u,r]])}return p!==void 0&&(y.end=Object.assign({},$r(r.events,p)),n.add(p,0,[["exit",y,r]]),y=void 0),y}function Qm(n,r,s,o,p){const y=[],f=$r(r.events,s);p&&(p.end=Object.assign({},f),y.push(["exit",p,r])),o.end=Object.assign({},f),y.push(["exit",o,r]),n.add(s+1,0,y)}function $r(n,r){const s=n[r],o=s[0]==="enter"?"start":"end";return s[1][o]}const Dx={name:"tasklistCheck",tokenize:Mx};function Rx(){return{text:{91:Dx}}}function Mx(n,r,s){const o=this;return p;function p(c){return o.previous!==null||!o._gfmTasklistFirstContentOfListItem?s(c):(n.enter("taskListCheck"),n.enter("taskListCheckMarker"),n.consume(c),n.exit("taskListCheckMarker"),y)}function y(c){return ot(c)?(n.enter("taskListCheckValueUnchecked"),n.consume(c),n.exit("taskListCheckValueUnchecked"),f):c===88||c===120?(n.enter("taskListCheckValueChecked"),n.consume(c),n.exit("taskListCheckValueChecked"),f):s(c)}function f(c){return c===93?(n.enter("taskListCheckMarker"),n.consume(c),n.exit("taskListCheckMarker"),n.exit("taskListCheck"),a):s(c)}function a(c){return Ne(c)?r(c):Ve(c)?n.check({tokenize:Lx},r,s)(c):s(c)}}function Lx(n,r,s){return Ke(n,o,"whitespace");function o(p){return p===null?s(p):r(p)}}function Ox(n){return Dg([rx(),px(),Cx(n),kx(),Rx()])}const Bx={};function S_(n){const r=this,s=n||Bx,o=r.data(),p=o.micromarkExtensions||(o.micromarkExtensions=[]),y=o.fromMarkdownExtensions||(o.fromMarkdownExtensions=[]),f=o.toMarkdownExtensions||(o.toMarkdownExtensions=[]);p.push(Ox(s)),y.push(ex()),f.push(tx(s))}const Nx=500,Ce={getAppPreferences(){return Me("/api/settings/preferences")},updateAppPreferences(n){return Me("/api/settings/preferences",{method:"PUT",body:JSON.stringify(n)})},getRuntimeDiagnostics(){return Me("/api/diagnostics/runtime")},getCurrentProject(){return Me("/api/projects/current")},pullCurrentProject(){return Me("/api/projects/current/pull",{method:"POST"})},getRecentRepositoryPaths(){return Me("/api/projects/recent")},connectProject(n){return Me("/api/projects/connect",{method:"POST",body:JSON.stringify(n)})},listTasks(){return Me("/api/tasks")},createTask(n){return Me("/api/tasks",{method:"POST",body:JSON.stringify(n)})},cleanupTask(n,r={}){return Me(`/api/tasks/${encodeURIComponent(n)}/cleanup`,{method:"POST",body:JSON.stringify(r)})},getHarnessStatus(){return Me("/api/projects/harness")},applyHarness(){return Me("/api/projects/harness/apply",{method:"POST"})},getHarnessBootstrapStatus(){return Me("/api/projects/harness/bootstrap")},startHarnessBootstrap(n={}){return Me("/api/projects/harness/bootstrap/start",{method:"POST",body:JSON.stringify(n)})},getTaskStatus(n){return Me(`/api/tasks/${encodeURIComponent(n)}/status`)},listSessions(n){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions`)},startRoleSession(n,r,s={}){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/start`,{method:"POST",body:JSON.stringify(s)})},stopRoleSession(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/stop`,{method:"POST"})},restartRoleSession(n,r,s={}){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/restart`,{method:"POST",body:JSON.stringify(s)})},resumeRoleSession(n,r,s={}){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/resume`,{method:"POST",body:JSON.stringify(s)})},dispatchRoleCommand(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/dispatch`,{method:"POST"})},listMessages(n){return Me(`/api/tasks/${encodeURIComponent(n)}/messages`)},markAllMessagesDone(n){return Me(`/api/tasks/${encodeURIComponent(n)}/messages/mark-all-done`,{method:"POST"})},deleteMessageHistory(n){return Me(`/api/tasks/${encodeURIComponent(n)}/messages/history`,{method:"DELETE"})},getOrchestrationState(n){return Me(`/api/tasks/${encodeURIComponent(n)}/orchestration`)},updateOrchestrationState(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/orchestration`,{method:"PUT",body:JSON.stringify(r)})},getSessionRoundState(n){return Me(`/api/tasks/${encodeURIComponent(n)}/round`)},getCodexReviewState(n){return Me(`/api/tasks/${encodeURIComponent(n)}/codex-review`)},updateCodexReviewSettings(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/codex-review/settings`,{method:"PUT",body:JSON.stringify(r)})},requestCodexReviewGate(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/codex-review/${r}/request`,{method:"POST"})},retryCodexReviewGate(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/codex-review/${r}/retry`,{method:"POST"})},skipCodexReviewGate(n,r,s){return Me(`/api/tasks/${encodeURIComponent(n)}/codex-review/${r}/skip`,{method:"POST",body:JSON.stringify(s)})},overrideCodexReviewGate(n,r,s){return Me(`/api/tasks/${encodeURIComponent(n)}/codex-review/${r}/override`,{method:"POST",body:JSON.stringify(s)})},getCodexReviewReport(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/codex-review/${r}/report`)},startTranslationSession(n,r){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/translation/start`,{method:"POST"})},pollTranslationSession(n,r,s){const o=new URLSearchParams({after:String(r)});return s!==void 0&&o.set("limit",String(s)),Me(`/api/translation/sessions/${encodeURIComponent(n)}/events?${o.toString()}`)},translateUserInput(n,r,s){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/translation/input`,{method:"POST",body:JSON.stringify(s)})},sendTranslatedInput(n,r,s){return Me(`/api/tasks/${encodeURIComponent(n)}/sessions/${r}/translation/send`,{method:"POST",body:JSON.stringify(s)})},clearTranslationSession(n){return Me(`/api/translation/sessions/${encodeURIComponent(n)}/clear`,{method:"POST"})},stopTranslationSession(n){return Me(`/api/translation/sessions/${encodeURIComponent(n)}/stop`,{method:"POST"})},retryTranslation(n,r){return Me(`/api/translation/sessions/${encodeURIComponent(n)}/retry/${encodeURIComponent(r)}`,{method:"POST"})},ignoreTranslationFailures(n){return Me(`/api/translation/sessions/${encodeURIComponent(n)}/failures/ignore`,{method:"POST"})},retryTranslationFailures(n){return Me(`/api/translation/sessions/${encodeURIComponent(n)}/failures/retry`,{method:"POST"})},getCodexTranslationState(){return Me("/api/translation/codex/state")},browseCodexTranslationSourceFiles(n={}){const r=new URLSearchParams;n.path&&r.set("path",n.path),n.query&&r.set("query",n.query),n.limit!==void 0&&r.set("limit",String(n.limit));const s=r.toString()?`?${r.toString()}`:"";return Me(`/api/translation/codex/source-files${s}`)},createCodexFileTranslation(n){return Me("/api/translation/codex/files",{method:"POST",body:JSON.stringify(n)})},readCodexFileTranslation(n){return Me(`/api/translation/codex/files/${encodeURIComponent(n)}`)},createCodexBootstrap(n){return Me("/api/translation/codex/bootstrap",{method:"POST",body:JSON.stringify(n)})},createCodexMemoryUpdate(n){return Me("/api/translation/codex/memory-update",{method:"POST",body:JSON.stringify(n)})},promoteCodexTranslation(n,r){return Me(`/api/translation/codex/files/${encodeURIComponent(n)}/promote`,{method:"POST",body:JSON.stringify({targetPath:r})})},getGatewayStatus(){return Me("/api/gateway/status")},updateGatewaySettings(n){return Me("/api/gateway/settings",{method:"PUT",body:JSON.stringify(n)})},startGatewayQrLogin(){return Me("/api/gateway/qr/start",{method:"POST"})},checkGatewayQrLogin(n={}){return Me("/api/gateway/qr/check",{method:"POST",body:JSON.stringify(n)})},resetGatewayBinding(){return Me("/api/gateway/binding/reset",{method:"POST"})}};async function Me(n,r={}){var p,y,f;const s=new Headers(r.headers);r.body!==void 0&&r.body!==null&&!s.has("content-type")&&s.set("content-type","application/json");const o=await fetch(n,{...r,headers:s});if(!o.ok){const a=await o.json().catch(()=>null),c=(p=a==null?void 0:a.error)!=null&&p.hint?`${a.error.message} ${a.error.hint}`:((y=a==null?void 0:a.error)==null?void 0:y.message)??`Request failed: ${o.status}`,h=(f=a==null?void 0:a.error)==null?void 0:f.runtime,d=h?` [backend ${h.version??"unknown"} pid=${h.pid??"unknown"} cwd=${h.cwd??"unknown"}]`:"";throw new Error(`${c}${d}`)}return o.json()}const Ba=`
80
80
 
81
81
  --- Translation ---
82
- `;function jx({active:n=!0,autoSendEnabled:r,targetLanguage:s,taskSlug:o,role:p,sessionId:y}){const[f,a]=he.useState([]),[c,h]=he.useState([]),[d,u]=he.useState(""),[b,w]=he.useState(!1),[E,x]=he.useState("ready"),[v,S]=he.useState(""),[g,_]=he.useState(Date.now()),[A,M]=he.useState(!1),[D,T]=he.useState(""),[k,R]=he.useState(0),N=he.useRef(n),I=he.useRef(1),P=he.useRef(null);he.useEffect(()=>{N.current=n},[n]),he.useEffect(()=>{a([]),h([]),T(""),x("ready"),S(""),I.current=1;let j=!1,ee;const ae=()=>{j||(ee=window.setTimeout(ge,N.current?200:1e3))},ge=async()=>{if(!j)try{const K=await Ce.pollTranslationSession(y,I.current);if(j)return;W(K.events),I.current=K.nextCursor,x(K.status),N.current&&S(Qx(new Date().toISOString()))}catch(K){j||T(K instanceof Error?K.message:"Translation poll failed.")}finally{ae()}};return Ce.startTranslationSession(o,p).then(K=>{j||(x(K.status),I.current=K.nextCursor,ge())}).catch(K=>{j||T(K instanceof Error?K.message:"Translation start failed.")}),()=>{j=!0,ee!==void 0&&window.clearTimeout(ee),Ce.stopTranslationSession(y).catch(()=>{})}},[y,o,p]),he.useEffect(()=>{if(!n)return;const j=P.current;if(!j)return;const ee=window.requestAnimationFrame(()=>{j.scrollTop=j.scrollHeight});return()=>window.cancelAnimationFrame(ee)},[n,k]);const F=qx(f);he.useEffect(()=>{if(!F)return;_(Date.now());const j=window.setInterval(()=>_(Date.now()),250);return()=>window.clearInterval(j)},[F]);async function Y(j=!1){const ee=d;M(!0),T(""),w(!1);try{const ae=await Ce.translateUserInput(o,p,{text:ee,mode:j?"auto-send":"review-before-send",useContext:!1,send:j});ae.sent?(u(""),w(!1)):(u(b_(ee,ae.englishPreview)),w(!0))}catch(ae){T(ae instanceof Error?ae.message:"Translation failed.")}finally{M(!1)}}function W(j){if(j.length===0)return;for(const ae of j)ae.type==="status"?x(ae.status):ae.type==="error"?T(ae.message):ae.type==="failures"&&h(ae.failures);const ee=j.filter(ae=>ae.type==="entry");ee.length>0&&(a(ae=>{const ge=ee.reduce((q,ce)=>Wx(q,ce.entry),ae),K=Gx(ge);return K.removedIds.size>0&&h(q=>q.filter(ce=>!K.removedIds.has(ce.translationId))),K.entries}),R(ae=>ae+1))}async function G(){const j=b?Jm(d):d;if(j.trim()){M(!0),T("");try{await Ce.sendTranslatedInput(o,p,{englishText:j}),u(""),w(!1)}catch(ee){T(ee instanceof Error?ee.message:"Failed to send English input.")}finally{M(!1)}}}function $(j){j.key!=="Enter"||j.shiftKey||j.nativeEvent.isComposing||(j.preventDefault(),!A&&d.trim()&&(b?G():Y(r)))}async function Q(){a([]),h([]),I.current=1,await Ce.clearTranslationSession(y).catch(j=>T(j.message))}async function H(){M(!0),T("");try{const j=await Ce.ignoreTranslationFailures(y);h(j.failures)}catch(j){T(j instanceof Error?j.message:"Failed to ignore translation failures.")}finally{M(!1)}}async function O(){M(!0),T("");try{const j=await Ce.retryTranslationFailures(y);h(j.failures)}catch(j){T(j instanceof Error?j.message:"Failed to retry translation failures.")}finally{M(!1)}}const z=Vx(f,E,g),V=c.length;return B.jsxs("aside",{className:"translation-panel",children:[B.jsxs("header",{className:"translation-panel-header",children:[B.jsxs("div",{className:"translation-panel-titlebar",children:[B.jsx("h2",{children:"Translation"}),B.jsxs("div",{className:"translation-panel-actions",children:[V>0?B.jsxs(B.Fragment,{children:[B.jsxs("button",{type:"button",disabled:A,onClick:()=>void H(),children:["Ignore ",V]}),B.jsxs("button",{type:"button",disabled:A,onClick:()=>void O(),children:["Retry ",V]})]}):null,B.jsx("button",{type:"button",onClick:()=>void Q(),children:"Clear"})]})]}),B.jsxs("div",{className:"translation-status-row",children:[B.jsxs("p",{children:["Codex · target ",zx(s)," · ",z]}),B.jsx("p",{children:v?`poll ${v}`:"poll -"})]})]}),D?B.jsx("div",{className:"error-banner",children:D}):null,B.jsxs("div",{className:"translation-entry-list",ref:P,children:[f.length===0?B.jsx("p",{className:"muted",children:"Translated Claude Code output will appear here."}):null,f.map(j=>B.jsx(Px,{entry:j},j.id))]}),B.jsx("div",{className:"translation-composer",children:B.jsxs("div",{className:"translation-composer-row",children:[B.jsx("textarea",{value:d,onChange:j=>{u(j.target.value),(!j.target.value.trim()||b&&!Kx(j.target.value))&&w(!1)},onKeyDown:$,placeholder:"输入中文,先翻译成英文工程指令..."}),B.jsx("div",{className:"translation-composer-actions",children:B.jsx("button",{type:"button",disabled:A||!b||!Jm(d).trim(),onClick:()=>void G(),children:"Send English"})})]})})]})}function zx(n){var r;return((r=pg.find(s=>s.value===n))==null?void 0:r.label)??n}function Hx({open:n,taskSlug:r,targetLanguage:s,onClose:o}){const[p,y]=he.useState(!1),[f,a]=he.useState(""),[c,h]=he.useState(null),[d,u]=he.useState(""),[b,w]=he.useState(""),[E,x]=he.useState(""),[v,S]=he.useState(!1),[g,_]=he.useState(null),[A,M]=he.useState(""),[D,T]=he.useState(""),[k,R]=he.useState(""),[N,I]=he.useState(!1);he.useEffect(()=>{if(!n)return;let $=!1,Q;const H=async()=>{$||(await P(!0),$||(Q=window.setTimeout(H,2e3)))};return H(),()=>{$=!0,Q!==void 0&&window.clearTimeout(Q)}},[n,d]);async function P($=!1){try{const Q=await Ce.getCodexTranslationState();if(h(Q),!d&&Q.fileIndex.jobs[0])F(Q.fileIndex.jobs[0].id);else if($&&d){const H=await Ce.readCodexFileTranslation(d);w(H.output),x(H.report)}}catch(Q){a(Q instanceof Error?Q.message:"Failed to load file translations.")}}async function F($){u($),w(""),x("");try{const Q=await Ce.readCodexFileTranslation($);w(Q.output),x(Q.report)}catch(Q){a(Q instanceof Error?Q.message:"Failed to read translated file.")}}async function Y(){S(!0),await W(A,D)}async function W($="",Q=""){I(!0),a("");try{const H=await Ce.browseCodexTranslationSourceFiles({path:$,query:Q,limit:250});_(H),M(H.currentPath),T(Q)}catch(H){a(H instanceof Error?H.message:"Failed to browse source files.")}finally{I(!1)}}async function G($=k){const Q=$.trim();if(!(!Q||!r)){y(!0),a("");try{const H=await Ce.createCodexFileTranslation({taskSlug:r,sourcePath:Q,targetLanguage:s});S(!1),await P(),await F(H.id)}catch(H){a(H instanceof Error?H.message:"Failed to create file translation.")}finally{y(!1)}}}return n?B.jsxs(B.Fragment,{children:[B.jsx("div",{className:"modal-backdrop file-translation-backdrop",children:B.jsx(Ux,{busy:p,error:f,state:c,selectedJobId:d,output:b,report:E,onClose:()=>{S(!1),o()},onRefresh:()=>void P(),onSelectJob:$=>void F($),onTranslate:()=>void Y()})}),v?B.jsx(Ix,{busy:p||N,state:g,currentPath:A,query:D,selectedPath:k,onBrowse:($,Q)=>void W($,Q),onClose:()=>S(!1),onQueryChange:T,onSelectPath:R,onTranslate:()=>void G()}):null]}):null}function Ix({busy:n,state:r,currentPath:s,query:o,selectedPath:p,onBrowse:y,onClose:f,onQueryChange:a,onSelectPath:c,onTranslate:h}){const d=(r==null?void 0:r.entries)??[],u=d.filter(w=>w.type==="directory"),b=d.filter(w=>w.type==="file");return B.jsx("div",{className:"modal-backdrop translation-file-browser-backdrop",children:B.jsxs("section",{className:"translation-file-browser-modal",role:"dialog","aria-modal":"true","aria-label":"Select Source File",children:[B.jsxs("header",{children:[B.jsxs("div",{children:[B.jsx("h2",{children:"Select Source File"}),B.jsx("p",{children:s||"."})]}),B.jsx("button",{type:"button",onClick:f,children:"Close"})]}),B.jsxs("div",{className:"translation-file-browser-controls",children:[B.jsxs("div",{className:"translation-file-browser-nav",children:[B.jsx("button",{type:"button",disabled:n||!s,onClick:()=>y((r==null?void 0:r.parentPath)??"",""),children:"Up"}),B.jsx("button",{type:"button",disabled:n||!s,onClick:()=>y("",""),children:"Root"})]}),B.jsxs("form",{className:"translation-file-browser-search",onSubmit:w=>{w.preventDefault(),y(s,o)},children:[B.jsx("input",{value:o,onChange:w=>a(w.target.value),placeholder:"Search files"}),B.jsx("button",{type:"submit",disabled:n,children:"Search"}),B.jsx("button",{type:"button",disabled:n||!o,onClick:()=>y(s,""),children:"Clear"})]})]}),B.jsxs("div",{className:"translation-file-browser-layout",children:[B.jsxs("div",{className:"translation-file-browser-list",children:[n&&!r?B.jsx("p",{className:"muted",children:"Loading files..."}):null,!n&&d.length===0?B.jsx("p",{className:"muted",children:"No source files found."}):null,u.length>0?B.jsxs("div",{className:"translation-file-browser-group",children:[B.jsx("h3",{children:"Folders"}),u.map(w=>B.jsx(Zm,{entry:w,selected:p===w.path,onBrowse:y,onSelectPath:c},w.path))]}):null,b.length>0?B.jsxs("div",{className:"translation-file-browser-group",children:[B.jsx("h3",{children:"Files"}),b.map(w=>B.jsx(Zm,{entry:w,selected:p===w.path,onBrowse:y,onSelectPath:c},w.path))]}):null,r!=null&&r.truncated?B.jsx("p",{className:"translation-entry-note",children:"Result limit reached."}):null]}),B.jsxs("aside",{className:"translation-file-browser-selection",children:[B.jsxs("label",{children:[B.jsx("span",{children:"Source path"}),B.jsx("input",{value:p,onChange:w=>c(w.target.value)})]}),B.jsx("button",{type:"button",disabled:n||!p.trim(),onClick:h,children:"Translate File"})]})]})]})})}function Zm({entry:n,selected:r,onBrowse:s,onSelectPath:o}){const p=n.type==="directory";return B.jsxs("button",{className:r?"translation-file-browser-entry is-selected":"translation-file-browser-entry",type:"button",onClick:()=>p?s(n.path,""):o(n.path),onDoubleClick:()=>p?s(n.path,""):void 0,children:[B.jsx("span",{children:p?"DIR":"FILE"}),B.jsx("strong",{children:n.name}),B.jsx("small",{children:n.path})]})}function Ux({busy:n,error:r,state:s,selectedJobId:o,output:p,report:y,onClose:f,onRefresh:a,onSelectJob:c,onTranslate:h}){const d=(s==null?void 0:s.fileIndex.jobs)??[],u=d.find(b=>b.id===o);return B.jsxs("section",{className:"file-translation-modal",role:"dialog","aria-modal":"true","aria-label":"File Translation",children:[B.jsxs("header",{className:"file-translation-header",children:[B.jsxs("div",{children:[B.jsx("h2",{children:"File Translation"}),B.jsx("p",{children:"Codex · 中英互译"})]}),B.jsxs("div",{className:"file-translation-toolbar",children:[B.jsx("button",{type:"button",disabled:n,onClick:h,children:"Translate"}),B.jsx("button",{type:"button",disabled:n,onClick:a,children:"Refresh"}),B.jsx("button",{type:"button",onClick:f,children:"Close"})]})]}),r?B.jsx("div",{className:"error-banner",children:r}):null,s!=null&&s.memoryInitialized?null:B.jsx("p",{className:"translation-entry-note",children:"Translation memory is not initialized. Run Bootstrap from the sidebar before important file translations."}),B.jsxs("div",{className:"file-translation-layout",children:[B.jsxs("div",{className:"file-translation-list",children:[d.length===0?B.jsx("p",{className:"muted",children:"No translated files yet."}):null,d.map(b=>B.jsxs("button",{className:b.id===o?"file-translation-item is-active":"file-translation-item",type:"button",onClick:()=>c(b.id),children:[B.jsx("strong",{children:b.sourcePath}),B.jsxs("span",{children:[b.status," · ",b.targetLanguage]})]},b.id))]}),B.jsx("div",{className:"file-translation-preview",children:u?B.jsxs(B.Fragment,{children:[B.jsxs("header",{children:[B.jsx("strong",{children:u.sourcePath}),B.jsx("span",{children:u.status})]}),B.jsx("div",{className:"translation-markdown",children:B.jsx(Xg,{remarkPlugins:[S_],children:p||y||"Translation output is not available yet."})})]}):B.jsx("p",{className:"muted",children:"Select a translated file to preview it."})})]})]})}function Px({entry:n}){if(n.sourceKind==="conversation-boundary")return B.jsx(Fx,{entry:n});const r=Yx(n),s=n.sourceKind==="tool-output",o=n.direction==="user-input-to-english",p=["translation-entry",`is-${n.sourceKind}`,o?"is-user-input":""].filter(Boolean).join(" ");return B.jsxs("article",{className:p,children:[s?B.jsx("pre",{children:r}):B.jsx("div",{className:"translation-markdown",children:B.jsx(Xg,{remarkPlugins:[S_],children:r})}),n.warning?B.jsx("p",{className:"translation-entry-note",children:n.warning}):null,n.error?B.jsx("p",{className:"translation-entry-note is-error",children:n.error}):null]})}function Fx({entry:n}){const r=n.boundaryKind==="end"?"结束":"开始",s=n.conversationTurn??0,o=Zx(n.occurredAt??n.createdAt);return B.jsxs("div",{className:"translation-conversation-boundary","aria-label":`${r} 第 ${s} 轮 ${o}`,children:[B.jsx("span",{className:"translation-boundary-dash","aria-hidden":"true"}),B.jsx("span",{children:r}),B.jsxs("span",{children:["第 ",s," 轮"]}),B.jsx("time",{children:o}),B.jsx("span",{className:"translation-boundary-dash","aria-hidden":"true"})]})}function qx(n){const r=n.find(ih);return(r==null?void 0:r.translationStartedAt)??(r==null?void 0:r.createdAt)}function Vx(n,r,s){const o=n.find(ih);if(o)return`translating ${Xx(Math.max(0,s-$x(o)))}`;const p=n.at(-1);return(p==null?void 0:p.status)==="failed"||r==="failed"?"error":r}function ih(n){return n.status==="queued"||n.status==="translating"}function Gx(n){const r=n.length-Nx;if(r<=0)return{entries:n,removedIds:new Set};const s=new Set;for(const o of n){if(s.size>=r)break;ih(o)||s.add(o.id)}return s.size===0?{entries:n,removedIds:s}:{entries:n.filter(o=>!s.has(o.id)),removedIds:s}}function $x(n){const r=Date.parse(n.translationStartedAt??n.createdAt);return Number.isFinite(r)?r:Date.now()}function Yx(n){return n.status==="queued"||n.status==="translating"?n.sourceText:n.status==="translated"?n.direction==="user-input-to-english"?b_(n.sourceText,n.translatedText):n.translatedText:n.translatedText||n.sourceText}function b_(n,r){return`${n.trimEnd()}${Ba}${r.trimStart()}`}function Kx(n){return n.includes(Ba)}function Jm(n){const r=n.indexOf(Ba);return r===-1?n:n.slice(r+Ba.length)}function Wx(n,r){return n.findIndex(o=>o.id===r.id)===-1?[...n,r]:n.map(o=>o.id===r.id?r:o)}function Xx(n){if(n<1e3)return`${Math.max(.1,n/1e3).toFixed(1)}s`;const r=n/1e3;if(r<60)return`${r.toFixed(1)}s`;const s=Math.floor(r/60),o=Math.floor(r%60).toString().padStart(2,"0");return`${s}:${o}`}function Qx(n){const r=new Date(n);return Number.isNaN(r.getTime())?n:r.toLocaleTimeString()}function Zx(n){const r=new Date(n);return Number.isNaN(r.getTime())?n:r.toLocaleTimeString()}function Jx(n,r){return n.find(s=>s.taskSlug===r)??n[0]??null}const e2={role:"codex-reviewer",permissionMode:"default",model:"gpt-5.5",effort:"xhigh"};function t2(n,r){const s=Kr.map(o=>({role:o.name,permissionMode:n.roles[o.name].permissionMode,model:n.roles[o.name].model,effort:n.roles[o.name].effort}));return r.codexReviewerEnabled&&s.push(e2),s}const n2=["architecture-plan","validation-adequacy","final-diff"];function i2({events:n,maxEvents:r=8,showHeader:s=!0}){const o=r===null?n:n.slice(-r);return B.jsxs("section",{className:"event-log",children:[s?B.jsx("h2",{children:"Events"}):null,n.length===0?B.jsx("p",{className:"muted",children:"No terminal events yet."}):B.jsx("ol",{children:o.map((p,y)=>B.jsx("li",{children:p},`${p}-${y}`))})]})}var Su={exports:{}},eg;function r2(){return eg||(eg=1,(function(n,r){(function(s,o){n.exports=o()})(self,(()=>(()=>{var s={};return(()=>{var o=s;Object.defineProperty(o,"__esModule",{value:!0}),o.FitAddon=void 0,o.FitAddon=class{activate(p){this._terminal=p}dispose(){}fit(){const p=this.proposeDimensions();if(!p||!this._terminal||isNaN(p.cols)||isNaN(p.rows))return;const y=this._terminal._core;this._terminal.rows===p.rows&&this._terminal.cols===p.cols||(y._renderService.clear(),this._terminal.resize(p.cols,p.rows))}proposeDimensions(){if(!this._terminal||!this._terminal.element||!this._terminal.element.parentElement)return;const p=this._terminal._core,y=p._renderService.dimensions;if(y.css.cell.width===0||y.css.cell.height===0)return;const f=this._terminal.options.scrollback===0?0:p.viewport.scrollBarWidth,a=window.getComputedStyle(this._terminal.element.parentElement),c=parseInt(a.getPropertyValue("height")),h=Math.max(0,parseInt(a.getPropertyValue("width"))),d=window.getComputedStyle(this._terminal.element),u=c-(parseInt(d.getPropertyValue("padding-top"))+parseInt(d.getPropertyValue("padding-bottom"))),b=h-(parseInt(d.getPropertyValue("padding-right"))+parseInt(d.getPropertyValue("padding-left")))-f;return{cols:Math.max(2,Math.floor(b/y.css.cell.width)),rows:Math.max(1,Math.floor(u/y.css.cell.height))}}}})(),s})()))})(Su)),Su.exports}var s2=r2(),bu={exports:{}},tg;function l2(){return tg||(tg=1,(function(n,r){(function(s,o){n.exports=o()})(self,(()=>(()=>{var s={6:(f,a)=>{function c(d){try{const u=new URL(d),b=u.password&&u.username?`${u.protocol}//${u.username}:${u.password}@${u.host}`:u.username?`${u.protocol}//${u.username}@${u.host}`:`${u.protocol}//${u.host}`;return d.toLocaleLowerCase().startsWith(b.toLocaleLowerCase())}catch{return!1}}Object.defineProperty(a,"__esModule",{value:!0}),a.LinkComputer=a.WebLinkProvider=void 0,a.WebLinkProvider=class{constructor(d,u,b,w={}){this._terminal=d,this._regex=u,this._handler=b,this._options=w}provideLinks(d,u){const b=h.computeLink(d,this._regex,this._terminal,this._handler);u(this._addCallbacks(b))}_addCallbacks(d){return d.map((u=>(u.leave=this._options.leave,u.hover=(b,w)=>{if(this._options.hover){const{range:E}=u;this._options.hover(b,w,E)}},u)))}};class h{static computeLink(u,b,w,E){const x=new RegExp(b.source,(b.flags||"")+"g"),[v,S]=h._getWindowedLineStrings(u-1,w),g=v.join("");let _;const A=[];for(;_=x.exec(g);){const M=_[0];if(!c(M))continue;const[D,T]=h._mapStrIdx(w,S,0,_.index),[k,R]=h._mapStrIdx(w,D,T,M.length);if(D===-1||T===-1||k===-1||R===-1)continue;const N={start:{x:T+1,y:D+1},end:{x:R,y:k+1}};A.push({range:N,text:M,activate:E})}return A}static _getWindowedLineStrings(u,b){let w,E=u,x=u,v=0,S="";const g=[];if(w=b.buffer.active.getLine(u)){const _=w.translateToString(!0);if(w.isWrapped&&_[0]!==" "){for(v=0;(w=b.buffer.active.getLine(--E))&&v<2048&&(S=w.translateToString(!0),v+=S.length,g.push(S),w.isWrapped&&S.indexOf(" ")===-1););g.reverse()}for(g.push(_),v=0;(w=b.buffer.active.getLine(++x))&&w.isWrapped&&v<2048&&(S=w.translateToString(!0),v+=S.length,g.push(S),S.indexOf(" ")===-1););}return[g,E]}static _mapStrIdx(u,b,w,E){const x=u.buffer.active,v=x.getNullCell();let S=w;for(;E;){const g=x.getLine(b);if(!g)return[-1,-1];for(let _=S;_<g.length;++_){g.getCell(_,v);const A=v.getChars();if(v.getWidth()&&(E-=A.length||1,_===g.length-1&&A==="")){const M=x.getLine(b+1);M&&M.isWrapped&&(M.getCell(0,v),v.getWidth()===2&&(E+=1))}if(E<0)return[b,_]}b++,S=0}return[b,S]}}a.LinkComputer=h}},o={};function p(f){var a=o[f];if(a!==void 0)return a.exports;var c=o[f]={exports:{}};return s[f](c,c.exports,p),c.exports}var y={};return(()=>{var f=y;Object.defineProperty(f,"__esModule",{value:!0}),f.WebLinksAddon=void 0;const a=p(6),c=/(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function h(d,u){const b=window.open();if(b){try{b.opener=null}catch{}b.location.href=u}else console.warn("Opening link blocked as opener could not be cleared")}f.WebLinksAddon=class{constructor(d=h,u={}){this._handler=d,this._options=u}activate(d){this._terminal=d;const u=this._options,b=u.urlRegex||c;this._linkProvider=this._terminal.registerLinkProvider(new a.WebLinkProvider(this._terminal,b,this._handler,u))}dispose(){var d;(d=this._linkProvider)==null||d.dispose()}}})(),y})()))})(bu)),bu.exports}var a2=l2(),Cu={exports:{}},ng;function o2(){return ng||(ng=1,(function(n,r){(function(s,o){n.exports=o()})(globalThis,(()=>(()=>{var s={4567:function(f,a,c){var h=this&&this.__decorate||function(g,_,A,M){var D,T=arguments.length,k=T<3?_:M===null?M=Object.getOwnPropertyDescriptor(_,A):M;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")k=Reflect.decorate(g,_,A,M);else for(var R=g.length-1;R>=0;R--)(D=g[R])&&(k=(T<3?D(k):T>3?D(_,A,k):D(_,A))||k);return T>3&&k&&Object.defineProperty(_,A,k),k},d=this&&this.__param||function(g,_){return function(A,M){_(A,M,g)}};Object.defineProperty(a,"__esModule",{value:!0}),a.AccessibilityManager=void 0;const u=c(9042),b=c(9924),w=c(844),E=c(4725),x=c(2585),v=c(3656);let S=a.AccessibilityManager=class extends w.Disposable{constructor(g,_,A,M){super(),this._terminal=g,this._coreBrowserService=A,this._renderService=M,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let D=0;D<this._terminal.rows;D++)this._rowElements[D]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[D]);if(this._topBoundaryFocusListener=D=>this._handleBoundaryFocus(D,0),this._bottomBoundaryFocusListener=D=>this._handleBoundaryFocus(D,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new b.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((D=>this._handleResize(D.rows)))),this.register(this._terminal.onRender((D=>this._refreshRows(D.start,D.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((D=>this._handleChar(D)))),this.register(this._terminal.onLineFeed((()=>this._handleChar(`
82
+ `;function jx({active:n=!0,autoSendEnabled:r,targetLanguage:s,taskSlug:o,role:p,sessionId:y}){const[f,a]=he.useState([]),[c,h]=he.useState([]),[d,u]=he.useState(""),[b,w]=he.useState(!1),[E,x]=he.useState("ready"),[v,S]=he.useState(""),[g,_]=he.useState(Date.now()),[A,M]=he.useState(!1),[D,T]=he.useState(""),[k,R]=he.useState(0),N=he.useRef(n),I=he.useRef(1),P=he.useRef(null);he.useEffect(()=>{N.current=n},[n]),he.useEffect(()=>{a([]),h([]),T(""),x("ready"),S(""),I.current=1;let j=!1,ee;const ae=()=>{j||(ee=window.setTimeout(ge,N.current?200:1e3))},ge=async()=>{if(!j)try{const K=await Ce.pollTranslationSession(y,I.current);if(j)return;W(K.events),I.current=K.nextCursor,x(K.status),N.current&&S(Qx(new Date().toISOString()))}catch(K){j||T(K instanceof Error?K.message:"Translation poll failed.")}finally{ae()}};return Ce.startTranslationSession(o,p).then(K=>{j||(x(K.status),I.current=K.nextCursor,ge())}).catch(K=>{j||T(K instanceof Error?K.message:"Translation start failed.")}),()=>{j=!0,ee!==void 0&&window.clearTimeout(ee),Ce.stopTranslationSession(y).catch(()=>{})}},[y,o,p]),he.useEffect(()=>{if(!n)return;const j=P.current;if(!j)return;const ee=window.requestAnimationFrame(()=>{j.scrollTop=j.scrollHeight});return()=>window.cancelAnimationFrame(ee)},[n,k]);const F=qx(f);he.useEffect(()=>{if(!F)return;_(Date.now());const j=window.setInterval(()=>_(Date.now()),250);return()=>window.clearInterval(j)},[F]);async function Y(j=!1){const ee=d;M(!0),T(""),w(!1);try{const ae=await Ce.translateUserInput(o,p,{text:ee,mode:j?"auto-send":"review-before-send",useContext:!1,send:j});ae.sent?(u(""),w(!1)):(u(b_(ee,ae.englishPreview)),w(!0))}catch(ae){T(ae instanceof Error?ae.message:"Translation failed.")}finally{M(!1)}}function W(j){if(j.length===0)return;for(const ae of j)ae.type==="status"?x(ae.status):ae.type==="error"?T(ae.message):ae.type==="failures"&&h(ae.failures);const ee=j.filter(ae=>ae.type==="entry");ee.length>0&&(a(ae=>{const ge=ee.reduce((q,ce)=>Wx(q,ce.entry),ae),K=Gx(ge);return K.removedIds.size>0&&h(q=>q.filter(ce=>!K.removedIds.has(ce.translationId))),K.entries}),R(ae=>ae+1))}async function G(){const j=b?Jm(d):d;if(j.trim()){M(!0),T("");try{await Ce.sendTranslatedInput(o,p,{englishText:j}),u(""),w(!1)}catch(ee){T(ee instanceof Error?ee.message:"Failed to send English input.")}finally{M(!1)}}}function $(j){j.key!=="Enter"||j.shiftKey||j.nativeEvent.isComposing||(j.preventDefault(),!A&&d.trim()&&(b?G():Y(r)))}async function Q(){a([]),h([]),I.current=1,await Ce.clearTranslationSession(y).catch(j=>T(j.message))}async function H(){M(!0),T("");try{const j=await Ce.ignoreTranslationFailures(y);h(j.failures)}catch(j){T(j instanceof Error?j.message:"Failed to ignore translation failures.")}finally{M(!1)}}async function O(){M(!0),T("");try{const j=await Ce.retryTranslationFailures(y);h(j.failures)}catch(j){T(j instanceof Error?j.message:"Failed to retry translation failures.")}finally{M(!1)}}const z=Vx(f,E,g),V=c.length;return B.jsxs("aside",{className:"translation-panel",children:[B.jsxs("header",{className:"translation-panel-header",children:[B.jsxs("div",{className:"translation-panel-titlebar",children:[B.jsx("h2",{children:"Translation"}),B.jsxs("div",{className:"translation-panel-actions",children:[V>0?B.jsxs(B.Fragment,{children:[B.jsxs("button",{type:"button",disabled:A,onClick:()=>void H(),children:["Ignore ",V]}),B.jsxs("button",{type:"button",disabled:A,onClick:()=>void O(),children:["Retry ",V]})]}):null,B.jsx("button",{type:"button",onClick:()=>void Q(),children:"Clear"})]})]}),B.jsxs("div",{className:"translation-status-row",children:[B.jsxs("p",{children:["Codex · target ",zx(s)," · ",z]}),B.jsx("p",{children:v?`poll ${v}`:"poll -"})]})]}),D?B.jsx("div",{className:"error-banner",children:D}):null,B.jsxs("div",{className:"translation-entry-list",ref:P,children:[f.length===0?B.jsx("p",{className:"muted",children:"Translated Claude Code output will appear here."}):null,f.map(j=>B.jsx(Px,{entry:j},j.id))]}),B.jsx("div",{className:"translation-composer",children:B.jsxs("div",{className:"translation-composer-row",children:[B.jsx("textarea",{value:d,onChange:j=>{u(j.target.value),(!j.target.value.trim()||b&&!Kx(j.target.value))&&w(!1)},onKeyDown:$,placeholder:"输入中文,先翻译成英文工程指令..."}),B.jsx("div",{className:"translation-composer-actions",children:B.jsx("button",{type:"button",disabled:A||!b||!Jm(d).trim(),onClick:()=>void G(),children:"Send English"})})]})})]})}function zx(n){var r;return((r=pg.find(s=>s.value===n))==null?void 0:r.label)??n}function Hx({open:n,taskSlug:r,targetLanguage:s,onClose:o}){const[p,y]=he.useState(!1),[f,a]=he.useState(""),[c,h]=he.useState(null),[d,u]=he.useState(""),[b,w]=he.useState(""),[E,x]=he.useState(""),[v,S]=he.useState(!1),[g,_]=he.useState(null),[A,M]=he.useState(""),[D,T]=he.useState(""),[k,R]=he.useState(""),[N,I]=he.useState(!1);he.useEffect(()=>{if(!n)return;let $=!1,Q;const H=async()=>{$||(await P(!0),$||(Q=window.setTimeout(H,2e3)))};return H(),()=>{$=!0,Q!==void 0&&window.clearTimeout(Q)}},[n,d]);async function P($=!1){try{const Q=await Ce.getCodexTranslationState();h(Q);const H=d?Q.fileIndex.jobs.some(O=>O.id===d):!1;if((!d||!H)&&Q.fileIndex.jobs[0])F(Q.fileIndex.jobs[0].id);else if(!Q.fileIndex.jobs[0])u(""),w(""),x("");else if($&&d){const O=await Ce.readCodexFileTranslation(d);w(O.output),x(O.report)}}catch(Q){a(Q instanceof Error?Q.message:"Failed to load file translations.")}}async function F($){u($),w(""),x("");try{const Q=await Ce.readCodexFileTranslation($);w(Q.output),x(Q.report)}catch(Q){a(Q instanceof Error?Q.message:"Failed to read translated file.")}}async function Y(){S(!0),await W(A,D)}async function W($="",Q=""){I(!0),a("");try{const H=await Ce.browseCodexTranslationSourceFiles({path:$,query:Q,limit:250});_(H),M(H.currentPath),T(Q)}catch(H){a(H instanceof Error?H.message:"Failed to browse source files.")}finally{I(!1)}}async function G($=k){const Q=$.trim();if(!(!Q||!r)){y(!0),a("");try{const H=await Ce.createCodexFileTranslation({taskSlug:r,sourcePath:Q,targetLanguage:s});S(!1),await P(),await F(H.id)}catch(H){a(H instanceof Error?H.message:"Failed to create file translation.")}finally{y(!1)}}}return n?B.jsxs(B.Fragment,{children:[B.jsx("div",{className:"modal-backdrop file-translation-backdrop",children:B.jsx(Ux,{busy:p,error:f,state:c,selectedJobId:d,output:b,report:E,onClose:()=>{S(!1),o()},onRefresh:()=>void P(),onSelectJob:$=>void F($),onTranslate:()=>void Y()})}),v?B.jsx(Ix,{busy:p||N,state:g,currentPath:A,query:D,selectedPath:k,onBrowse:($,Q)=>void W($,Q),onClose:()=>S(!1),onQueryChange:T,onSelectPath:R,onTranslate:()=>void G()}):null]}):null}function Ix({busy:n,state:r,currentPath:s,query:o,selectedPath:p,onBrowse:y,onClose:f,onQueryChange:a,onSelectPath:c,onTranslate:h}){const d=(r==null?void 0:r.entries)??[],u=d.filter(w=>w.type==="directory"),b=d.filter(w=>w.type==="file");return B.jsx("div",{className:"modal-backdrop translation-file-browser-backdrop",children:B.jsxs("section",{className:"translation-file-browser-modal",role:"dialog","aria-modal":"true","aria-label":"Select Source File",children:[B.jsxs("header",{children:[B.jsxs("div",{children:[B.jsx("h2",{children:"Select Source File"}),B.jsx("p",{children:s||"."})]}),B.jsx("button",{type:"button",onClick:f,children:"Close"})]}),B.jsxs("div",{className:"translation-file-browser-controls",children:[B.jsxs("div",{className:"translation-file-browser-nav",children:[B.jsx("button",{type:"button",disabled:n||!s,onClick:()=>y((r==null?void 0:r.parentPath)??"",""),children:"Up"}),B.jsx("button",{type:"button",disabled:n||!s,onClick:()=>y("",""),children:"Root"})]}),B.jsxs("form",{className:"translation-file-browser-search",onSubmit:w=>{w.preventDefault(),y(s,o)},children:[B.jsx("input",{value:o,onChange:w=>a(w.target.value),placeholder:"Search files"}),B.jsx("button",{type:"submit",disabled:n,children:"Search"}),B.jsx("button",{type:"button",disabled:n||!o,onClick:()=>y(s,""),children:"Clear"})]})]}),B.jsxs("div",{className:"translation-file-browser-layout",children:[B.jsxs("div",{className:"translation-file-browser-list",children:[n&&!r?B.jsx("p",{className:"muted",children:"Loading files..."}):null,!n&&d.length===0?B.jsx("p",{className:"muted",children:"No source files found."}):null,u.length>0?B.jsxs("div",{className:"translation-file-browser-group",children:[B.jsx("h3",{children:"Folders"}),u.map(w=>B.jsx(Zm,{entry:w,selected:p===w.path,onBrowse:y,onSelectPath:c},w.path))]}):null,b.length>0?B.jsxs("div",{className:"translation-file-browser-group",children:[B.jsx("h3",{children:"Files"}),b.map(w=>B.jsx(Zm,{entry:w,selected:p===w.path,onBrowse:y,onSelectPath:c},w.path))]}):null,r!=null&&r.truncated?B.jsx("p",{className:"translation-entry-note",children:"Result limit reached."}):null]}),B.jsxs("aside",{className:"translation-file-browser-selection",children:[B.jsxs("label",{children:[B.jsx("span",{children:"Source path"}),B.jsx("input",{value:p,onChange:w=>c(w.target.value)})]}),B.jsx("button",{type:"button",disabled:n||!p.trim(),onClick:h,children:"Translate File"})]})]})]})})}function Zm({entry:n,selected:r,onBrowse:s,onSelectPath:o}){const p=n.type==="directory";return B.jsxs("button",{className:r?"translation-file-browser-entry is-selected":"translation-file-browser-entry",type:"button",onClick:()=>p?s(n.path,""):o(n.path),onDoubleClick:()=>p?s(n.path,""):void 0,children:[B.jsx("span",{children:p?"DIR":"FILE"}),B.jsx("strong",{children:n.name}),B.jsx("small",{children:n.path})]})}function Ux({busy:n,error:r,state:s,selectedJobId:o,output:p,report:y,onClose:f,onRefresh:a,onSelectJob:c,onTranslate:h}){const d=(s==null?void 0:s.fileIndex.jobs)??[],u=d.find(b=>b.id===o);return B.jsxs("section",{className:"file-translation-modal",role:"dialog","aria-modal":"true","aria-label":"File Translation",children:[B.jsxs("header",{className:"file-translation-header",children:[B.jsxs("div",{children:[B.jsx("h2",{children:"File Translation"}),B.jsx("p",{children:"Codex · 中英互译"})]}),B.jsxs("div",{className:"file-translation-toolbar",children:[B.jsx("button",{type:"button",disabled:n,onClick:h,children:"Translate"}),B.jsx("button",{type:"button",disabled:n,onClick:a,children:"Refresh"}),B.jsx("button",{type:"button",onClick:f,children:"Close"})]})]}),r?B.jsx("div",{className:"error-banner",children:r}):null,s!=null&&s.memoryInitialized?null:B.jsx("p",{className:"translation-entry-note",children:"Translation memory is not initialized. Run Bootstrap from the sidebar before important file translations."}),B.jsxs("div",{className:"file-translation-layout",children:[B.jsxs("div",{className:"file-translation-list",children:[d.length===0?B.jsx("p",{className:"muted",children:"No translated files yet."}):null,d.map(b=>B.jsxs("button",{className:b.id===o?"file-translation-item is-active":"file-translation-item",type:"button",onClick:()=>c(b.id),children:[B.jsx("strong",{children:b.sourcePath}),B.jsxs("span",{children:[b.status," · ",b.targetLanguage]})]},b.id))]}),B.jsx("div",{className:"file-translation-preview",children:u?B.jsxs(B.Fragment,{children:[B.jsxs("header",{children:[B.jsx("strong",{children:u.sourcePath}),B.jsx("span",{children:u.status})]}),B.jsx("div",{className:"translation-markdown",children:B.jsx(Xg,{remarkPlugins:[S_],children:p||y||"Translation output is not available yet."})})]}):B.jsx("p",{className:"muted",children:"Select a translated file to preview it."})})]})]})}function Px({entry:n}){if(n.sourceKind==="conversation-boundary")return B.jsx(Fx,{entry:n});const r=Yx(n),s=n.sourceKind==="tool-output",o=n.direction==="user-input-to-english",p=["translation-entry",`is-${n.sourceKind}`,o?"is-user-input":""].filter(Boolean).join(" ");return B.jsxs("article",{className:p,children:[s?B.jsx("pre",{children:r}):B.jsx("div",{className:"translation-markdown",children:B.jsx(Xg,{remarkPlugins:[S_],children:r})}),n.warning?B.jsx("p",{className:"translation-entry-note",children:n.warning}):null,n.error?B.jsx("p",{className:"translation-entry-note is-error",children:n.error}):null]})}function Fx({entry:n}){const r=n.boundaryKind==="end"?"结束":"开始",s=n.conversationTurn??0,o=Zx(n.occurredAt??n.createdAt);return B.jsxs("div",{className:"translation-conversation-boundary","aria-label":`${r} 第 ${s} 轮 ${o}`,children:[B.jsx("span",{className:"translation-boundary-dash","aria-hidden":"true"}),B.jsx("span",{children:r}),B.jsxs("span",{children:["第 ",s," 轮"]}),B.jsx("time",{children:o}),B.jsx("span",{className:"translation-boundary-dash","aria-hidden":"true"})]})}function qx(n){const r=n.find(ih);return(r==null?void 0:r.translationStartedAt)??(r==null?void 0:r.createdAt)}function Vx(n,r,s){const o=n.find(ih);if(o)return`translating ${Xx(Math.max(0,s-$x(o)))}`;const p=n.at(-1);return(p==null?void 0:p.status)==="failed"||r==="failed"?"error":r}function ih(n){return n.status==="queued"||n.status==="translating"}function Gx(n){const r=n.length-Nx;if(r<=0)return{entries:n,removedIds:new Set};const s=new Set;for(const o of n){if(s.size>=r)break;ih(o)||s.add(o.id)}return s.size===0?{entries:n,removedIds:s}:{entries:n.filter(o=>!s.has(o.id)),removedIds:s}}function $x(n){const r=Date.parse(n.translationStartedAt??n.createdAt);return Number.isFinite(r)?r:Date.now()}function Yx(n){return n.status==="queued"||n.status==="translating"?n.sourceText:n.status==="translated"?n.direction==="user-input-to-english"?b_(n.sourceText,n.translatedText):n.translatedText:n.translatedText||n.sourceText}function b_(n,r){return`${n.trimEnd()}${Ba}${r.trimStart()}`}function Kx(n){return n.includes(Ba)}function Jm(n){const r=n.indexOf(Ba);return r===-1?n:n.slice(r+Ba.length)}function Wx(n,r){return n.findIndex(o=>o.id===r.id)===-1?[...n,r]:n.map(o=>o.id===r.id?r:o)}function Xx(n){if(n<1e3)return`${Math.max(.1,n/1e3).toFixed(1)}s`;const r=n/1e3;if(r<60)return`${r.toFixed(1)}s`;const s=Math.floor(r/60),o=Math.floor(r%60).toString().padStart(2,"0");return`${s}:${o}`}function Qx(n){const r=new Date(n);return Number.isNaN(r.getTime())?n:r.toLocaleTimeString()}function Zx(n){const r=new Date(n);return Number.isNaN(r.getTime())?n:r.toLocaleTimeString()}function Jx(n,r){return n.find(s=>s.taskSlug===r)??n[0]??null}const e2={role:"codex-reviewer",permissionMode:"default",model:"gpt-5.5",effort:"xhigh"};function t2(n,r){const s=Kr.map(o=>({role:o.name,permissionMode:n.roles[o.name].permissionMode,model:n.roles[o.name].model,effort:n.roles[o.name].effort}));return r.codexReviewerEnabled&&s.push(e2),s}const n2=["architecture-plan","validation-adequacy","final-diff"];function i2({events:n,maxEvents:r=8,showHeader:s=!0}){const o=r===null?n:n.slice(-r);return B.jsxs("section",{className:"event-log",children:[s?B.jsx("h2",{children:"Events"}):null,n.length===0?B.jsx("p",{className:"muted",children:"No terminal events yet."}):B.jsx("ol",{children:o.map((p,y)=>B.jsx("li",{children:p},`${p}-${y}`))})]})}var Su={exports:{}},eg;function r2(){return eg||(eg=1,(function(n,r){(function(s,o){n.exports=o()})(self,(()=>(()=>{var s={};return(()=>{var o=s;Object.defineProperty(o,"__esModule",{value:!0}),o.FitAddon=void 0,o.FitAddon=class{activate(p){this._terminal=p}dispose(){}fit(){const p=this.proposeDimensions();if(!p||!this._terminal||isNaN(p.cols)||isNaN(p.rows))return;const y=this._terminal._core;this._terminal.rows===p.rows&&this._terminal.cols===p.cols||(y._renderService.clear(),this._terminal.resize(p.cols,p.rows))}proposeDimensions(){if(!this._terminal||!this._terminal.element||!this._terminal.element.parentElement)return;const p=this._terminal._core,y=p._renderService.dimensions;if(y.css.cell.width===0||y.css.cell.height===0)return;const f=this._terminal.options.scrollback===0?0:p.viewport.scrollBarWidth,a=window.getComputedStyle(this._terminal.element.parentElement),c=parseInt(a.getPropertyValue("height")),h=Math.max(0,parseInt(a.getPropertyValue("width"))),d=window.getComputedStyle(this._terminal.element),u=c-(parseInt(d.getPropertyValue("padding-top"))+parseInt(d.getPropertyValue("padding-bottom"))),b=h-(parseInt(d.getPropertyValue("padding-right"))+parseInt(d.getPropertyValue("padding-left")))-f;return{cols:Math.max(2,Math.floor(b/y.css.cell.width)),rows:Math.max(1,Math.floor(u/y.css.cell.height))}}}})(),s})()))})(Su)),Su.exports}var s2=r2(),bu={exports:{}},tg;function l2(){return tg||(tg=1,(function(n,r){(function(s,o){n.exports=o()})(self,(()=>(()=>{var s={6:(f,a)=>{function c(d){try{const u=new URL(d),b=u.password&&u.username?`${u.protocol}//${u.username}:${u.password}@${u.host}`:u.username?`${u.protocol}//${u.username}@${u.host}`:`${u.protocol}//${u.host}`;return d.toLocaleLowerCase().startsWith(b.toLocaleLowerCase())}catch{return!1}}Object.defineProperty(a,"__esModule",{value:!0}),a.LinkComputer=a.WebLinkProvider=void 0,a.WebLinkProvider=class{constructor(d,u,b,w={}){this._terminal=d,this._regex=u,this._handler=b,this._options=w}provideLinks(d,u){const b=h.computeLink(d,this._regex,this._terminal,this._handler);u(this._addCallbacks(b))}_addCallbacks(d){return d.map((u=>(u.leave=this._options.leave,u.hover=(b,w)=>{if(this._options.hover){const{range:E}=u;this._options.hover(b,w,E)}},u)))}};class h{static computeLink(u,b,w,E){const x=new RegExp(b.source,(b.flags||"")+"g"),[v,S]=h._getWindowedLineStrings(u-1,w),g=v.join("");let _;const A=[];for(;_=x.exec(g);){const M=_[0];if(!c(M))continue;const[D,T]=h._mapStrIdx(w,S,0,_.index),[k,R]=h._mapStrIdx(w,D,T,M.length);if(D===-1||T===-1||k===-1||R===-1)continue;const N={start:{x:T+1,y:D+1},end:{x:R,y:k+1}};A.push({range:N,text:M,activate:E})}return A}static _getWindowedLineStrings(u,b){let w,E=u,x=u,v=0,S="";const g=[];if(w=b.buffer.active.getLine(u)){const _=w.translateToString(!0);if(w.isWrapped&&_[0]!==" "){for(v=0;(w=b.buffer.active.getLine(--E))&&v<2048&&(S=w.translateToString(!0),v+=S.length,g.push(S),w.isWrapped&&S.indexOf(" ")===-1););g.reverse()}for(g.push(_),v=0;(w=b.buffer.active.getLine(++x))&&w.isWrapped&&v<2048&&(S=w.translateToString(!0),v+=S.length,g.push(S),S.indexOf(" ")===-1););}return[g,E]}static _mapStrIdx(u,b,w,E){const x=u.buffer.active,v=x.getNullCell();let S=w;for(;E;){const g=x.getLine(b);if(!g)return[-1,-1];for(let _=S;_<g.length;++_){g.getCell(_,v);const A=v.getChars();if(v.getWidth()&&(E-=A.length||1,_===g.length-1&&A==="")){const M=x.getLine(b+1);M&&M.isWrapped&&(M.getCell(0,v),v.getWidth()===2&&(E+=1))}if(E<0)return[b,_]}b++,S=0}return[b,S]}}a.LinkComputer=h}},o={};function p(f){var a=o[f];if(a!==void 0)return a.exports;var c=o[f]={exports:{}};return s[f](c,c.exports,p),c.exports}var y={};return(()=>{var f=y;Object.defineProperty(f,"__esModule",{value:!0}),f.WebLinksAddon=void 0;const a=p(6),c=/(https?|HTTPS?):[/]{2}[^\s"'!*(){}|\\\^<>`]*[^\s"':,.!?{}|\\\^~\[\]`()<>]/;function h(d,u){const b=window.open();if(b){try{b.opener=null}catch{}b.location.href=u}else console.warn("Opening link blocked as opener could not be cleared")}f.WebLinksAddon=class{constructor(d=h,u={}){this._handler=d,this._options=u}activate(d){this._terminal=d;const u=this._options,b=u.urlRegex||c;this._linkProvider=this._terminal.registerLinkProvider(new a.WebLinkProvider(this._terminal,b,this._handler,u))}dispose(){var d;(d=this._linkProvider)==null||d.dispose()}}})(),y})()))})(bu)),bu.exports}var a2=l2(),Cu={exports:{}},ng;function o2(){return ng||(ng=1,(function(n,r){(function(s,o){n.exports=o()})(globalThis,(()=>(()=>{var s={4567:function(f,a,c){var h=this&&this.__decorate||function(g,_,A,M){var D,T=arguments.length,k=T<3?_:M===null?M=Object.getOwnPropertyDescriptor(_,A):M;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")k=Reflect.decorate(g,_,A,M);else for(var R=g.length-1;R>=0;R--)(D=g[R])&&(k=(T<3?D(k):T>3?D(_,A,k):D(_,A))||k);return T>3&&k&&Object.defineProperty(_,A,k),k},d=this&&this.__param||function(g,_){return function(A,M){_(A,M,g)}};Object.defineProperty(a,"__esModule",{value:!0}),a.AccessibilityManager=void 0;const u=c(9042),b=c(9924),w=c(844),E=c(4725),x=c(2585),v=c(3656);let S=a.AccessibilityManager=class extends w.Disposable{constructor(g,_,A,M){super(),this._terminal=g,this._coreBrowserService=A,this._renderService=M,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let D=0;D<this._terminal.rows;D++)this._rowElements[D]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[D]);if(this._topBoundaryFocusListener=D=>this._handleBoundaryFocus(D,0),this._bottomBoundaryFocusListener=D=>this._handleBoundaryFocus(D,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new b.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((D=>this._handleResize(D.rows)))),this.register(this._terminal.onRender((D=>this._refreshRows(D.start,D.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((D=>this._handleChar(D)))),this.register(this._terminal.onLineFeed((()=>this._handleChar(`
83
83
  `)))),this.register(this._terminal.onA11yTab((D=>this._handleTab(D)))),this.register(this._terminal.onKey((D=>this._handleKey(D.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this.register((0,v.addDisposableDomListener)(document,"selectionchange",(()=>this._handleSelectionChange()))),this.register(this._coreBrowserService.onDprChange((()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,w.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(g){for(let _=0;_<g;_++)this._handleChar(" ")}_handleChar(g){this._liveRegionLineCount<21&&(this._charsToConsume.length>0?this._charsToConsume.shift()!==g&&(this._charsToAnnounce+=g):this._charsToAnnounce+=g,g===`
84
84
  `&&(this._liveRegionLineCount++,this._liveRegionLineCount===21&&(this._liveRegion.textContent+=u.tooMuchOutput)))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0}_handleKey(g){this._clearLiveRegion(),new RegExp("\\p{Control}","u").test(g)||this._charsToConsume.push(g)}_refreshRows(g,_){this._liveRegionDebouncer.refresh(g,_,this._terminal.rows)}_renderRows(g,_){const A=this._terminal.buffer,M=A.lines.length.toString();for(let D=g;D<=_;D++){const T=A.lines.get(A.ydisp+D),k=[],R=(T==null?void 0:T.translateToString(!0,void 0,void 0,k))||"",N=(A.ydisp+D+1).toString(),I=this._rowElements[D];I&&(R.length===0?(I.innerText=" ",this._rowColumns.set(I,[0,1])):(I.textContent=R,this._rowColumns.set(I,k)),I.setAttribute("aria-posinset",N),I.setAttribute("aria-setsize",M))}this._announceCharacters()}_announceCharacters(){this._charsToAnnounce.length!==0&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(g,_){const A=g.target,M=this._rowElements[_===0?1:this._rowElements.length-2];if(A.getAttribute("aria-posinset")===(_===0?"1":`${this._terminal.buffer.lines.length}`)||g.relatedTarget!==M)return;let D,T;if(_===0?(D=A,T=this._rowElements.pop(),this._rowContainer.removeChild(T)):(D=this._rowElements.shift(),T=A,this._rowContainer.removeChild(D)),D.removeEventListener("focus",this._topBoundaryFocusListener),T.removeEventListener("focus",this._bottomBoundaryFocusListener),_===0){const k=this._createAccessibilityTreeNode();this._rowElements.unshift(k),this._rowContainer.insertAdjacentElement("afterbegin",k)}else{const k=this._createAccessibilityTreeNode();this._rowElements.push(k),this._rowContainer.appendChild(k)}this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._terminal.scrollLines(_===0?-1:1),this._rowElements[_===0?1:this._rowElements.length-2].focus(),g.preventDefault(),g.stopImmediatePropagation()}_handleSelectionChange(){var R;if(this._rowElements.length===0)return;const g=document.getSelection();if(!g)return;if(g.isCollapsed)return void(this._rowContainer.contains(g.anchorNode)&&this._terminal.clearSelection());if(!g.anchorNode||!g.focusNode)return void console.error("anchorNode and/or focusNode are null");let _={node:g.anchorNode,offset:g.anchorOffset},A={node:g.focusNode,offset:g.focusOffset};if((_.node.compareDocumentPosition(A.node)&Node.DOCUMENT_POSITION_PRECEDING||_.node===A.node&&_.offset>A.offset)&&([_,A]=[A,_]),_.node.compareDocumentPosition(this._rowElements[0])&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_FOLLOWING)&&(_={node:this._rowElements[0].childNodes[0],offset:0}),!this._rowContainer.contains(_.node))return;const M=this._rowElements.slice(-1)[0];if(A.node.compareDocumentPosition(M)&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_PRECEDING)&&(A={node:M,offset:((R=M.textContent)==null?void 0:R.length)??0}),!this._rowContainer.contains(A.node))return;const D=({node:N,offset:I})=>{const P=N instanceof Text?N.parentNode:N;let F=parseInt(P==null?void 0:P.getAttribute("aria-posinset"),10)-1;if(isNaN(F))return console.warn("row is invalid. Race condition?"),null;const Y=this._rowColumns.get(P);if(!Y)return console.warn("columns is null. Race condition?"),null;let W=I<Y.length?Y[I]:Y.slice(-1)[0]+1;return W>=this._terminal.cols&&(++F,W=0),{row:F,column:W}},T=D(_),k=D(A);if(T&&k){if(T.row>k.row||T.row===k.row&&T.column>=k.column)throw new Error("invalid range");this._terminal.select(T.column,T.row,(k.row-T.row)*this._terminal.cols-T.column+k.column)}}_handleResize(g){this._rowElements[this._rowElements.length-1].removeEventListener("focus",this._bottomBoundaryFocusListener);for(let _=this._rowContainer.children.length;_<this._terminal.rows;_++)this._rowElements[_]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[_]);for(;this._rowElements.length>g;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()}_createAccessibilityTreeNode(){const g=this._coreBrowserService.mainDocument.createElement("div");return g.setAttribute("role","listitem"),g.tabIndex=-1,this._refreshRowDimensions(g),g}_refreshRowsDimensions(){if(this._renderService.dimensions.css.cell.height){this._accessibilityContainer.style.width=`${this._renderService.dimensions.css.canvas.width}px`,this._rowElements.length!==this._terminal.rows&&this._handleResize(this._terminal.rows);for(let g=0;g<this._terminal.rows;g++)this._refreshRowDimensions(this._rowElements[g])}}_refreshRowDimensions(g){g.style.height=`${this._renderService.dimensions.css.cell.height}px`}};a.AccessibilityManager=S=h([d(1,x.IInstantiationService),d(2,E.ICoreBrowserService),d(3,E.IRenderService)],S)},3614:(f,a)=>{function c(b){return b.replace(/\r?\n/g,"\r")}function h(b,w){return w?"\x1B[200~"+b+"\x1B[201~":b}function d(b,w,E,x){b=h(b=c(b),E.decPrivateModes.bracketedPasteMode&&x.rawOptions.ignoreBracketedPasteMode!==!0),E.triggerDataEvent(b,!0),w.value=""}function u(b,w,E){const x=E.getBoundingClientRect(),v=b.clientX-x.left-10,S=b.clientY-x.top-10;w.style.width="20px",w.style.height="20px",w.style.left=`${v}px`,w.style.top=`${S}px`,w.style.zIndex="1000",w.focus()}Object.defineProperty(a,"__esModule",{value:!0}),a.rightClickHandler=a.moveTextAreaUnderMouseCursor=a.paste=a.handlePasteEvent=a.copyHandler=a.bracketTextForPaste=a.prepareTextForTerminal=void 0,a.prepareTextForTerminal=c,a.bracketTextForPaste=h,a.copyHandler=function(b,w){b.clipboardData&&b.clipboardData.setData("text/plain",w.selectionText),b.preventDefault()},a.handlePasteEvent=function(b,w,E,x){b.stopPropagation(),b.clipboardData&&d(b.clipboardData.getData("text/plain"),w,E,x)},a.paste=d,a.moveTextAreaUnderMouseCursor=u,a.rightClickHandler=function(b,w,E,x,v){u(b,w,E),v&&x.rightClickSelect(b),w.value=x.selectionText,w.select()}},7239:(f,a,c)=>{Object.defineProperty(a,"__esModule",{value:!0}),a.ColorContrastCache=void 0;const h=c(1505);a.ColorContrastCache=class{constructor(){this._color=new h.TwoKeyMap,this._css=new h.TwoKeyMap}setCss(d,u,b){this._css.set(d,u,b)}getCss(d,u){return this._css.get(d,u)}setColor(d,u,b){this._color.set(d,u,b)}getColor(d,u){return this._color.get(d,u)}clear(){this._color.clear(),this._css.clear()}}},3656:(f,a)=>{Object.defineProperty(a,"__esModule",{value:!0}),a.addDisposableDomListener=void 0,a.addDisposableDomListener=function(c,h,d,u){c.addEventListener(h,d,u);let b=!1;return{dispose:()=>{b||(b=!0,c.removeEventListener(h,d,u))}}}},3551:function(f,a,c){var h=this&&this.__decorate||function(S,g,_,A){var M,D=arguments.length,T=D<3?g:A===null?A=Object.getOwnPropertyDescriptor(g,_):A;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")T=Reflect.decorate(S,g,_,A);else for(var k=S.length-1;k>=0;k--)(M=S[k])&&(T=(D<3?M(T):D>3?M(g,_,T):M(g,_))||T);return D>3&&T&&Object.defineProperty(g,_,T),T},d=this&&this.__param||function(S,g){return function(_,A){g(_,A,S)}};Object.defineProperty(a,"__esModule",{value:!0}),a.Linkifier=void 0;const u=c(3656),b=c(8460),w=c(844),E=c(2585),x=c(4725);let v=a.Linkifier=class extends w.Disposable{get currentLink(){return this._currentLink}constructor(S,g,_,A,M){super(),this._element=S,this._mouseService=g,this._renderService=_,this._bufferService=A,this._linkProviderService=M,this._linkCacheDisposables=[],this._isMouseOut=!0,this._wasResized=!1,this._activeLine=-1,this._onShowLinkUnderline=this.register(new b.EventEmitter),this.onShowLinkUnderline=this._onShowLinkUnderline.event,this._onHideLinkUnderline=this.register(new b.EventEmitter),this.onHideLinkUnderline=this._onHideLinkUnderline.event,this.register((0,w.getDisposeArrayDisposable)(this._linkCacheDisposables)),this.register((0,w.toDisposable)((()=>{var D;this._lastMouseEvent=void 0,(D=this._activeProviderReplies)==null||D.clear()}))),this.register(this._bufferService.onResize((()=>{this._clearCurrentLink(),this._wasResized=!0}))),this.register((0,u.addDisposableDomListener)(this._element,"mouseleave",(()=>{this._isMouseOut=!0,this._clearCurrentLink()}))),this.register((0,u.addDisposableDomListener)(this._element,"mousemove",this._handleMouseMove.bind(this))),this.register((0,u.addDisposableDomListener)(this._element,"mousedown",this._handleMouseDown.bind(this))),this.register((0,u.addDisposableDomListener)(this._element,"mouseup",this._handleMouseUp.bind(this)))}_handleMouseMove(S){this._lastMouseEvent=S;const g=this._positionFromMouseEvent(S,this._element,this._mouseService);if(!g)return;this._isMouseOut=!1;const _=S.composedPath();for(let A=0;A<_.length;A++){const M=_[A];if(M.classList.contains("xterm"))break;if(M.classList.contains("xterm-hover"))return}this._lastBufferCell&&g.x===this._lastBufferCell.x&&g.y===this._lastBufferCell.y||(this._handleHover(g),this._lastBufferCell=g)}_handleHover(S){if(this._activeLine!==S.y||this._wasResized)return this._clearCurrentLink(),this._askForLink(S,!1),void(this._wasResized=!1);this._currentLink&&this._linkAtPosition(this._currentLink.link,S)||(this._clearCurrentLink(),this._askForLink(S,!0))}_askForLink(S,g){var A,M;this._activeProviderReplies&&g||((A=this._activeProviderReplies)==null||A.forEach((D=>{D==null||D.forEach((T=>{T.link.dispose&&T.link.dispose()}))})),this._activeProviderReplies=new Map,this._activeLine=S.y);let _=!1;for(const[D,T]of this._linkProviderService.linkProviders.entries())g?(M=this._activeProviderReplies)!=null&&M.get(D)&&(_=this._checkLinkProviderResult(D,S,_)):T.provideLinks(S.y,(k=>{var N,I;if(this._isMouseOut)return;const R=k==null?void 0:k.map((P=>({link:P})));(N=this._activeProviderReplies)==null||N.set(D,R),_=this._checkLinkProviderResult(D,S,_),((I=this._activeProviderReplies)==null?void 0:I.size)===this._linkProviderService.linkProviders.length&&this._removeIntersectingLinks(S.y,this._activeProviderReplies)}))}_removeIntersectingLinks(S,g){const _=new Set;for(let A=0;A<g.size;A++){const M=g.get(A);if(M)for(let D=0;D<M.length;D++){const T=M[D],k=T.link.range.start.y<S?0:T.link.range.start.x,R=T.link.range.end.y>S?this._bufferService.cols:T.link.range.end.x;for(let N=k;N<=R;N++){if(_.has(N)){M.splice(D--,1);break}_.add(N)}}}}_checkLinkProviderResult(S,g,_){var D;if(!this._activeProviderReplies)return _;const A=this._activeProviderReplies.get(S);let M=!1;for(let T=0;T<S;T++)this._activeProviderReplies.has(T)&&!this._activeProviderReplies.get(T)||(M=!0);if(!M&&A){const T=A.find((k=>this._linkAtPosition(k.link,g)));T&&(_=!0,this._handleNewLink(T))}if(this._activeProviderReplies.size===this._linkProviderService.linkProviders.length&&!_)for(let T=0;T<this._activeProviderReplies.size;T++){const k=(D=this._activeProviderReplies.get(T))==null?void 0:D.find((R=>this._linkAtPosition(R.link,g)));if(k){_=!0,this._handleNewLink(k);break}}return _}_handleMouseDown(){this._mouseDownLink=this._currentLink}_handleMouseUp(S){if(!this._currentLink)return;const g=this._positionFromMouseEvent(S,this._element,this._mouseService);g&&this._mouseDownLink===this._currentLink&&this._linkAtPosition(this._currentLink.link,g)&&this._currentLink.link.activate(S,this._currentLink.link.text)}_clearCurrentLink(S,g){this._currentLink&&this._lastMouseEvent&&(!S||!g||this._currentLink.link.range.start.y>=S&&this._currentLink.link.range.end.y<=g)&&(this._linkLeave(this._element,this._currentLink.link,this._lastMouseEvent),this._currentLink=void 0,(0,w.disposeArray)(this._linkCacheDisposables))}_handleNewLink(S){if(!this._lastMouseEvent)return;const g=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);g&&this._linkAtPosition(S.link,g)&&(this._currentLink=S,this._currentLink.state={decorations:{underline:S.link.decorations===void 0||S.link.decorations.underline,pointerCursor:S.link.decorations===void 0||S.link.decorations.pointerCursor},isHovered:!0},this._linkHover(this._element,S.link,this._lastMouseEvent),S.link.decorations={},Object.defineProperties(S.link.decorations,{pointerCursor:{get:()=>{var _,A;return(A=(_=this._currentLink)==null?void 0:_.state)==null?void 0:A.decorations.pointerCursor},set:_=>{var A;(A=this._currentLink)!=null&&A.state&&this._currentLink.state.decorations.pointerCursor!==_&&(this._currentLink.state.decorations.pointerCursor=_,this._currentLink.state.isHovered&&this._element.classList.toggle("xterm-cursor-pointer",_))}},underline:{get:()=>{var _,A;return(A=(_=this._currentLink)==null?void 0:_.state)==null?void 0:A.decorations.underline},set:_=>{var A,M,D;(A=this._currentLink)!=null&&A.state&&((D=(M=this._currentLink)==null?void 0:M.state)==null?void 0:D.decorations.underline)!==_&&(this._currentLink.state.decorations.underline=_,this._currentLink.state.isHovered&&this._fireUnderlineEvent(S.link,_))}}}),this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange((_=>{if(!this._currentLink)return;const A=_.start===0?0:_.start+1+this._bufferService.buffer.ydisp,M=this._bufferService.buffer.ydisp+1+_.end;if(this._currentLink.link.range.start.y>=A&&this._currentLink.link.range.end.y<=M&&(this._clearCurrentLink(A,M),this._lastMouseEvent)){const D=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);D&&this._askForLink(D,!1)}}))))}_linkHover(S,g,_){var A;(A=this._currentLink)!=null&&A.state&&(this._currentLink.state.isHovered=!0,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(g,!0),this._currentLink.state.decorations.pointerCursor&&S.classList.add("xterm-cursor-pointer")),g.hover&&g.hover(_,g.text)}_fireUnderlineEvent(S,g){const _=S.range,A=this._bufferService.buffer.ydisp,M=this._createLinkUnderlineEvent(_.start.x-1,_.start.y-A-1,_.end.x,_.end.y-A-1,void 0);(g?this._onShowLinkUnderline:this._onHideLinkUnderline).fire(M)}_linkLeave(S,g,_){var A;(A=this._currentLink)!=null&&A.state&&(this._currentLink.state.isHovered=!1,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(g,!1),this._currentLink.state.decorations.pointerCursor&&S.classList.remove("xterm-cursor-pointer")),g.leave&&g.leave(_,g.text)}_linkAtPosition(S,g){const _=S.range.start.y*this._bufferService.cols+S.range.start.x,A=S.range.end.y*this._bufferService.cols+S.range.end.x,M=g.y*this._bufferService.cols+g.x;return _<=M&&M<=A}_positionFromMouseEvent(S,g,_){const A=_.getCoords(S,g,this._bufferService.cols,this._bufferService.rows);if(A)return{x:A[0],y:A[1]+this._bufferService.buffer.ydisp}}_createLinkUnderlineEvent(S,g,_,A,M){return{x1:S,y1:g,x2:_,y2:A,cols:this._bufferService.cols,fg:M}}};a.Linkifier=v=h([d(1,x.IMouseService),d(2,x.IRenderService),d(3,E.IBufferService),d(4,x.ILinkProviderService)],v)},9042:(f,a)=>{Object.defineProperty(a,"__esModule",{value:!0}),a.tooMuchOutput=a.promptLabel=void 0,a.promptLabel="Terminal input",a.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},3730:function(f,a,c){var h=this&&this.__decorate||function(x,v,S,g){var _,A=arguments.length,M=A<3?v:g===null?g=Object.getOwnPropertyDescriptor(v,S):g;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")M=Reflect.decorate(x,v,S,g);else for(var D=x.length-1;D>=0;D--)(_=x[D])&&(M=(A<3?_(M):A>3?_(v,S,M):_(v,S))||M);return A>3&&M&&Object.defineProperty(v,S,M),M},d=this&&this.__param||function(x,v){return function(S,g){v(S,g,x)}};Object.defineProperty(a,"__esModule",{value:!0}),a.OscLinkProvider=void 0;const u=c(511),b=c(2585);let w=a.OscLinkProvider=class{constructor(x,v,S){this._bufferService=x,this._optionsService=v,this._oscLinkService=S}provideLinks(x,v){var R;const S=this._bufferService.buffer.lines.get(x-1);if(!S)return void v(void 0);const g=[],_=this._optionsService.rawOptions.linkHandler,A=new u.CellData,M=S.getTrimmedLength();let D=-1,T=-1,k=!1;for(let N=0;N<M;N++)if(T!==-1||S.hasContent(N)){if(S.loadCell(N,A),A.hasExtendedAttrs()&&A.extended.urlId){if(T===-1){T=N,D=A.extended.urlId;continue}k=A.extended.urlId!==D}else T!==-1&&(k=!0);if(k||T!==-1&&N===M-1){const I=(R=this._oscLinkService.getLinkData(D))==null?void 0:R.uri;if(I){const P={start:{x:T+1,y:x},end:{x:N+(k||N!==M-1?0:1),y:x}};let F=!1;if(!(_!=null&&_.allowNonHttpProtocols))try{const Y=new URL(I);["http:","https:"].includes(Y.protocol)||(F=!0)}catch{F=!0}F||g.push({text:I,range:P,activate:(Y,W)=>_?_.activate(Y,W,P):E(0,W),hover:(Y,W)=>{var G;return(G=_==null?void 0:_.hover)==null?void 0:G.call(_,Y,W,P)},leave:(Y,W)=>{var G;return(G=_==null?void 0:_.leave)==null?void 0:G.call(_,Y,W,P)}})}k=!1,A.hasExtendedAttrs()&&A.extended.urlId?(T=N,D=A.extended.urlId):(T=-1,D=-1)}}v(g)}};function E(x,v){if(confirm(`Do you want to navigate to ${v}?
85
85
 
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>VibeCodingMaster</title>
7
- <script type="module" crossorigin src="/assets/index-DOKW0Y5n.js"></script>
7
+ <script type="module" crossorigin src="/assets/index-CEB6Bssn.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="/assets/index-Dmefx9m7.css">
9
9
  </head>
10
10
  <body>
@@ -36,7 +36,7 @@ conversation translation. It should:
36
36
  `<baseRepoRoot>/.ai/vcm/translations/`
37
37
  - write only the exact output paths assigned by VCM
38
38
  - record file metadata so unchanged files are not translated repeatedly
39
- - support resume/retry after interruption
39
+ - support retry or retranslation after interruption
40
40
  - produce a translation report with required light QA checks
41
41
  - translate short conversation items sent by VCM and write the translated text to
42
42
  VCM-assigned temporary result files
@@ -69,7 +69,7 @@ Codex session translation improves this because:
69
69
  - the session can inspect the whole repository and the whole source document
70
70
  - Codex can keep a long conversation state and use its normal context
71
71
  compaction behavior
72
- - durable memory files can preserve decisions across session compaction,
72
+ - durable memory files can preserve decisions across session compaction, VCM
73
73
  restarts, and future translation jobs
74
74
  - translation output can be written to files instead of returned through one
75
75
  very large API response
@@ -92,9 +92,9 @@ model. Their lifecycles are still different:
92
92
 
93
93
  | Translation type | Purpose | Root | Lifecycle | Cleanup |
94
94
  | --- | --- | --- | --- | --- |
95
- | Translation bootstrap | First-run project understanding and memory initialization | `<baseRepoRoot>/.ai/vcm/translations/bootstrap/` plus temporary runtime files | Long-term index and memory, temporary run files | Runtime files are deleted after completion |
96
- | File translation | Project documents, whitepapers, specs, long-form artifacts | `<baseRepoRoot>/.ai/vcm/translations/files/completed/` | Long-term project-local state | Completed outputs survive; request/progress/report files are deleted after completion |
97
- | Conversation translation | Role console output, user prompt translation, gateway replies | `<baseRepoRoot>/.ai/vcm/translations/runtime/conversations/<taskSlug>/...` | Task-scoped runtime cache | Deleted after the translated result is consumed |
95
+ | Translation bootstrap | First-run project understanding and memory initialization | `<baseRepoRoot>/.ai/vcm/translations/bootstrap/` plus temporary runtime files | Long-term index and memory, temporary run files | Runtime files are deleted on VCM startup and after completion |
96
+ | File translation | Project documents, whitepapers, specs, long-form artifacts | `<baseRepoRoot>/.ai/vcm/translations/files/completed/` | Long-term project-local state | Completed outputs survive; request/progress/report/chunk files are deleted on VCM startup and after completion |
97
+ | Conversation translation | Role console output, user prompt translation, gateway replies | `<baseRepoRoot>/.ai/vcm/translations/runtime/conversations/<taskSlug>/...` | Task-scoped runtime cache | Deleted on VCM startup or after the translated result is consumed |
98
98
  | Translation memory | Shared terminology and style rules | `<baseRepoRoot>/.ai/vcm/translations/memory/` | Long-term project-local state | Survives task cleanup and worktree deletion |
99
99
 
100
100
  Recommended layout:
@@ -138,9 +138,10 @@ Recommended layout:
138
138
  report.md
139
139
  ```
140
140
 
141
- Files under `runtime/` are working state. Completed file translations are
142
- moved into `files/completed/`; the matching runtime job directory is deleted
143
- after validation.
141
+ Files under `runtime/` are temporary working state. VCM deletes the entire
142
+ `translations/runtime/` tree on startup for recent or connected projects.
143
+ Completed file translations are moved into `files/completed/`; the matching
144
+ runtime job directory is also deleted after validation.
144
145
 
145
146
  The root is intentionally under `<baseRepoRoot>`, not `<taskRepoRoot>`. In
146
147
  worktree-backed tasks, `<taskRepoRoot>` points at
@@ -148,9 +149,10 @@ worktree-backed tasks, `<taskRepoRoot>` points at
148
149
  closed. Translation state must not be split between the base repo and task
149
150
  worktrees.
150
151
 
151
- Conversation translation entries are temporary. VCM should remove only matching
152
- runtime conversation files after their result JSON has been consumed. It must
153
- not remove `translations/files/completed/` or `translations/memory/`.
152
+ Conversation translation entries are temporary. VCM removes matching runtime
153
+ conversation files after their result JSON has been consumed and removes all
154
+ runtime conversation files on startup. Startup cleanup must not remove
155
+ `translations/files/completed/` or `translations/memory/`.
154
156
 
155
157
  All translation state is local VCM state and is normally ignored by git through
156
158
  `.ai/vcm/`. If the user wants a translated file committed to the project, VCM
@@ -312,13 +314,16 @@ User enables translation
312
314
  ```
313
315
 
314
316
  Bootstrap should be rerunnable. A rerun creates a new bootstrap id and preserves
315
- previous reports. Codex may append new memory entries, but user corrections in
316
- memory files override automatic bootstrap entries.
317
+ durable memory files and completed-run index history; runtime reports are
318
+ temporary. Codex may append new memory entries, but user corrections in memory
319
+ files override automatic bootstrap entries.
317
320
 
318
321
  ## 7. File Index And Replacement
319
322
 
320
- `index.json` tracks file translation jobs, completed-output replacement, and
321
- resume state.
323
+ `index.json` is the durable completed-translation index. It records only file
324
+ translations that passed validation and were moved into `files/completed/`.
325
+ Queued, running, failed, interrupted, and `needs_review` jobs stay under
326
+ `runtime/` and must not be written to this index.
322
327
 
323
328
  Suggested schema shape:
324
329
 
@@ -362,18 +367,19 @@ Replacement rules:
362
367
  - Selecting `Translate` always creates a new file translation job for the
363
368
  chosen source file and target language.
364
369
  - If a completed translation already exists for the same `sourcePath`,
365
- `targetLanguage`, and `translationProfile`, VCM keeps it visible until the new
366
- job completes successfully.
367
- - After the new job passes validation, VCM replaces the completed output for
368
- that same file/language/profile and removes the superseded job from
370
+ `targetLanguage`, and `translationProfile`, VCM keeps the old completed file
371
+ and index entry on disk until the new job completes successfully. During the
372
+ run, the UI may show the latest runtime job by merging `runtime/queue.json`
373
+ with `files/index.json`, but the durable index itself is unchanged.
374
+ - After the new job passes validation, VCM writes the completed output for that
375
+ same file/language/profile, then replaces the superseded entry in
369
376
  `files/index.json`.
370
377
  - If the new job fails, is interrupted, or needs review, the previous completed
371
378
  output remains intact.
372
379
  - If the same file is selected from a task worktree, VCM should normalize the
373
380
  source path back to the base repo path when possible; the long-term job still
374
381
  belongs to `<baseRepoRoot>/.ai/vcm/translations/files/completed/`.
375
- - Failed or interrupted jobs can be resumed when `progress.json` has enough
376
- section state.
382
+ - Failed or interrupted jobs can be retried by creating a new translation job.
377
383
 
378
384
  ## 8. Codex Translator Role
379
385
 
@@ -396,26 +402,27 @@ management pattern:
396
402
  - start/resume/restart/stop terminal controls
397
403
  - model and effort selectors
398
404
  - hook-based running/idle state
399
- - persisted Codex session id
400
- - long-lived terminal session for follow-up discussion
405
+ - runtime Codex session id for the current VCM process
406
+ - long-lived terminal session for follow-up discussion until VCM is restarted
401
407
 
402
- VCM persists the active translator session at:
408
+ VCM stores the active translator session runtime record at:
403
409
 
404
410
  ```text
405
411
  <baseRepoRoot>/.ai/vcm/translations/runtime/session.json
406
412
  ```
407
413
 
408
- This record is project-level state, not task-level state. It stores the Codex
409
- session id, selected model, selected effort, terminal cwd, log path, and hook
410
- activity state needed to show `Resume` after VCM restarts or after the user opens
411
- another task. The embedded terminal `Restart` control must stop the current
412
- runtime process, create a fresh Codex session id, overwrite this record, and keep
413
- old translation outputs intact.
414
+ This record is project-level runtime state, not task-level durable state. It
415
+ stores the Codex session id, selected model, selected effort, terminal cwd, and
416
+ hook activity state for the current VCM process. VCM deletes
417
+ `translations/runtime/` on startup, so this record must not be used for restart
418
+ recovery. The embedded terminal `Restart` control must stop the current runtime
419
+ process, create a fresh Codex session id, overwrite this record, and keep old
420
+ translation outputs intact.
414
421
 
415
- When a Codex hook has captured the real Codex `session_id`, `Resume` must run
416
- `codex resume <session_id>` so it reconnects the same translator conversation.
417
- Before the first hook captures a real id, VCM may fall back to `codex resume
418
- --last`.
422
+ When a Codex hook has captured the real Codex `session_id`, `Resume` may run
423
+ `codex resume <session_id>` during the same VCM runtime. After VCM restarts,
424
+ the user should start a fresh translator session and rely on durable memory
425
+ files plus completed translations.
419
426
 
420
427
  Session identity is fixed by base repository. If VCM later supports multiple
421
428
  parallel target-language translator sessions, split this file into a
@@ -600,7 +607,7 @@ All translation work enters the same VCM-managed queue:
600
607
  - conversation translation requests
601
608
  - bootstrap runs
602
609
  - retry requests
603
- - resume requests
610
+ - retranslation requests
604
611
 
605
612
  Queue rules:
606
613
 
@@ -645,7 +652,7 @@ Suggested queue item shape:
645
652
  "items": [
646
653
  {
647
654
  "id": "queue-item-001",
648
- "type": "bootstrap | file | conversation | retry | resume",
655
+ "type": "bootstrap | file | conversation | retry | force-retranslate",
649
656
  "status": "running",
650
657
  "targetLanguage": "zh-CN",
651
658
  "jobId": "whitepaper-v0-8-zh-20260614-001",
@@ -733,8 +740,8 @@ Completion rule:
733
740
  structure, corrupted code blocks, invalid result metadata, or unresolved risky
734
741
  choices, mark the job `needs_review`.
735
742
  - If required output files are missing or unreadable, mark the job `failed`.
736
- - `needs_review` jobs remain visible in the file list and can be resumed,
737
- retried, or manually resolved.
743
+ - `needs_review` jobs remain visible in the file list during the current VCM
744
+ runtime and can be retried or manually resolved.
738
745
 
739
746
  ## 14. Conversation Translation Workflow
740
747
 
@@ -936,10 +943,13 @@ on one giant prompt or one giant assistant response to translate the entire file
936
943
 
937
944
  Resume behavior:
938
945
 
939
- - If Codex session is still available, continue in the same session.
940
- - If the terminal was stopped, resume the Codex session id when possible.
941
- - If the session cannot resume, start a new Codex Translator session and reload
942
- memory plus runtime `request.json`, `progress.json`, and partial `output.md`.
946
+ - If Codex session is still available in the current VCM process, continue in
947
+ the same session.
948
+ - If the terminal was stopped during the same VCM process, resume the Codex
949
+ session id when possible.
950
+ - After VCM restarts, do not resume runtime jobs or partial runtime outputs.
951
+ Start a fresh Codex Translator session and requeue the translation from the
952
+ durable source file or conversation source.
943
953
  - Never replace a completed output until the new job has passed validation.
944
954
 
945
955
  Cancellation and interruption behavior:
@@ -948,10 +958,11 @@ Cancellation and interruption behavior:
948
958
  leave its request files for debugging.
949
959
  - If the user stops Codex Translator, closes VCM, or the hook flow does not
950
960
  return, mark the active item `interrupted` on the next state reconciliation.
951
- - On VCM restart, reload `runtime/queue.json`; any item left in `dispatching`,
952
- `running`, or `validating` without a confirmed result becomes `interrupted`.
953
- - Interrupted file jobs can be resumed from `progress.json` and partial
954
- `output.md` when available.
961
+ - On VCM startup, delete `translations/runtime/` entirely. Do not resume
962
+ queued, dispatching, running, validating, failed, or interrupted runtime
963
+ jobs from a previous process.
964
+ - Startup cleanup also removes file-index entries that do not point at a
965
+ validated completed output under `translations/files/completed/`.
955
966
  - Interrupted conversation translation requests should normally be retried from
956
967
  the original request file because they are short and temporary.
957
968
  - Manual resolve can mark an item completed only after the expected result file
@@ -974,13 +985,16 @@ Recommended UI:
974
985
  - right pane: selected translated file content preview
975
986
  - The view has a `Translate` action. Clicking it opens a file picker or path
976
987
  selector and creates a file translation job for the chosen file.
977
- - Selecting an item in the left pane loads the completed translated Markdown
978
- output in the right pane. Runtime reports are only retained while a job is
979
- queued, running, failed, or interrupted.
988
+ - Selecting a completed item in the left pane loads the completed translated
989
+ Markdown output in the right pane. Runtime reports are only retained while a
990
+ job is queued, running, failed, or interrupted.
980
991
  - Existing translated files come from
981
- `<baseRepoRoot>/.ai/vcm/translations/files/index.json`.
982
- - Active and queued jobs should appear in the left pane with status such as
983
- queued, translating, QA, completed, failed, or interrupted.
992
+ `<baseRepoRoot>/.ai/vcm/translations/files/index.json`; active and queued
993
+ jobs are derived from `runtime/queue.json` and their runtime `request.json`
994
+ files.
995
+ - The merged list should show at most one row for each
996
+ `sourcePath + targetLanguage + translationProfile`; runtime rows win over
997
+ completed rows while a retranslation is in progress.
984
998
 
985
999
  Controls in the file translation view:
986
1000
 
@@ -1059,11 +1073,12 @@ New backend pieces:
1059
1073
  - validate file and conversation result files
1060
1074
  - record promote metadata when users export translations into the repo tree
1061
1075
  - translation queue service
1062
- - enqueue bootstrap, file, conversation, retry, and resume tasks
1076
+ - enqueue bootstrap, file, conversation, retry, and retranslation tasks
1063
1077
  - persist `runtime/queue.json`
1064
1078
  - persist queue item status
1065
1079
  - ensure only one active Codex Translator task at a time
1066
- - restore interrupted state after VCM restart
1080
+ - delete startup runtime state instead of restoring interrupted state after
1081
+ VCM restart
1067
1082
  - advance the queue only after hook completion and result-file validation
1068
1083
  - start/resume Codex Translator
1069
1084
  - send job prompt
@@ -1081,7 +1096,7 @@ New backend pieces:
1081
1096
  - create job
1082
1097
  - get job status
1083
1098
  - read result/report
1084
- - resume/retry/force retranslate
1099
+ - retry/force retranslate
1085
1100
  - cancel/skip/manual resolve queue items
1086
1101
  - promote completed translations into explicit user-selected repo paths
1087
1102
  - get conversation translation request status when needed for debugging
@@ -1143,6 +1158,8 @@ durable under `translations/files/completed/`.
1143
1158
  - Add the unified `.ai/vcm/translations/` directory contract, including
1144
1159
  `runtime/queue.json`, `memory/`, `bootstrap/`, `files/completed/`, and
1145
1160
  `runtime/conversations/`.
1161
+ - Define `runtime/` as startup-cleaned temporary state; only memory, completed
1162
+ files, and durable indexes survive VCM restart.
1146
1163
  - Define index, request, progress, report, queue, and conversation result
1147
1164
  schemas.
1148
1165
  - Define memory file format, bootstrap candidate discovery, scan budgets, and
@@ -1158,10 +1175,10 @@ durable under `translations/files/completed/`.
1158
1175
 
1159
1176
  - Implement bootstrap state, candidate discovery, and bootstrap run creation.
1160
1177
  - Implement source hash and de-duplication.
1161
- - Implement job create/list/read/resume.
1178
+ - Implement job create/list/read/retranslate.
1162
1179
  - Implement the shared translation queue and persist `runtime/queue.json`.
1163
1180
  - Implement result-file validation for file and conversation translation.
1164
- - Implement interrupted-state reconciliation on VCM restart.
1181
+ - Implement startup runtime cleanup and durable-index pruning on VCM restart.
1165
1182
  - Persist completed file outputs under
1166
1183
  `<baseRepoRoot>/.ai/vcm/translations/files/completed/`.
1167
1184
  - Persist active queue, file/bootstrap request files, and conversation
@@ -1174,8 +1191,8 @@ durable under `translations/files/completed/`.
1174
1191
  ### Phase 3: Codex Session Integration
1175
1192
 
1176
1193
  - Add `codex-translator` role/session support.
1177
- - Persist session identity by `<baseRepoRoot> + targetLanguage`; do not split
1178
- sessions by translation profile.
1194
+ - Keep session identity as current-process runtime state by `<baseRepoRoot> +
1195
+ targetLanguage`; do not split sessions by translation profile.
1179
1196
  - Reuse Codex embedded terminal startup with model/effort selectors.
1180
1197
  - Add hook endpoints and running/idle tracking.
1181
1198
  - Send translation job prompts into the long-lived Codex session.
@@ -1191,7 +1208,8 @@ durable under `translations/files/completed/`.
1191
1208
  - Add a file-translation button to the existing translation panel.
1192
1209
  - Add the file translation modal.
1193
1210
  - Add first-use bootstrap recommendation and bootstrap controls.
1194
- - Add the translated-file left pane backed by `files/index.json`.
1211
+ - Add the translated-file left pane backed by completed entries from
1212
+ `files/index.json` plus active runtime file jobs from the queue.
1195
1213
  - Add the translated-content right pane backed by completed output files.
1196
1214
  - Show selected job status; show runtime report details only while a job is not
1197
1215
  completed.
@@ -1219,11 +1237,11 @@ durable under `translations/files/completed/`.
1219
1237
  conversation or file translation.
1220
1238
  - Add bootstrap tests for candidate discovery, memory writes, queue ordering,
1221
1239
  and rerun behavior.
1222
- - Add queue status-machine tests, including interrupted restart recovery.
1240
+ - Add queue status-machine tests, including startup runtime cleanup.
1223
1241
  - Add conversation result text validation tests.
1224
1242
  - Add memory priority tests proving user entries override automatic entries.
1225
1243
  - Add promote tests proving source files are not overwritten by default.
1226
- - Add resume tests with partial output.
1244
+ - Add retry/retranslation tests after failed or interrupted work.
1227
1245
  - Test with `docs/whitepaper-v0.8.md` scale files.
1228
1246
 
1229
1247
  ## 21. Resolved Decisions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibe-coding-master",
3
- "version": "0.3.21",
3
+ "version": "0.3.22",
4
4
  "description": "Local GUI session cockpit for Claude Code role sessions.",
5
5
  "type": "module",
6
6
  "files": [