dsh-git-worktree 0.7.5 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.en.md +11 -5
  3. package/README.md +11 -5
  4. package/docs/i18n.md +63 -0
  5. package/lib/adapters/files.d.ts +0 -7
  6. package/lib/adapters/files.js +4 -3
  7. package/lib/adapters/files.js.map +1 -1
  8. package/lib/adapters/git.d.ts +0 -10
  9. package/lib/adapters/git.js +92 -18
  10. package/lib/adapters/git.js.map +1 -1
  11. package/lib/adapters/initial-commit.d.ts +16 -0
  12. package/lib/adapters/initial-commit.js +112 -0
  13. package/lib/adapters/initial-commit.js.map +1 -0
  14. package/lib/adapters/lookup.js +21 -0
  15. package/lib/adapters/lookup.js.map +1 -1
  16. package/lib/adapters/registry.d.ts +0 -7
  17. package/lib/adapters/registry.js +2 -1
  18. package/lib/adapters/registry.js.map +1 -1
  19. package/lib/adapters/safe-file.d.ts +0 -7
  20. package/lib/adapters/safe-file.js +5 -4
  21. package/lib/adapters/safe-file.js.map +1 -1
  22. package/lib/client/WorktreeCreateRow.js +5 -2
  23. package/lib/client/WorktreeCreateRow.js.map +1 -1
  24. package/lib/client/WorktreeReviewRow.d.ts +1 -1
  25. package/lib/client/WorktreeReviewRow.js +11 -9
  26. package/lib/client/WorktreeReviewRow.js.map +1 -1
  27. package/lib/client/actions.d.ts +4 -7
  28. package/lib/client/actions.js +17 -13
  29. package/lib/client/actions.js.map +1 -1
  30. package/lib/client/console-remote/adapter.d.ts +2 -1
  31. package/lib/client/console-remote/adapter.js +37 -32
  32. package/lib/client/console-remote/adapter.js.map +1 -1
  33. package/lib/client/console-remote/index.js +6 -2
  34. package/lib/client/console-remote/index.js.map +1 -1
  35. package/lib/client/i18n.d.ts +25 -0
  36. package/lib/client/i18n.js +43 -0
  37. package/lib/client/i18n.js.map +1 -0
  38. package/lib/client/index.d.ts +1 -1
  39. package/lib/client/index.js +17 -4
  40. package/lib/client/index.js.map +1 -1
  41. package/lib/client/model.d.ts +3 -2
  42. package/lib/client/model.js +8 -8
  43. package/lib/client/model.js.map +1 -1
  44. package/lib/client/pre-session/PreSessionWorktreeToggle.d.ts +2 -2
  45. package/lib/client/pre-session/PreSessionWorktreeToggle.js +95 -80
  46. package/lib/client/pre-session/PreSessionWorktreeToggle.js.map +1 -1
  47. package/lib/client/pre-session/controller.d.ts +3 -0
  48. package/lib/client/pre-session/controller.js +27 -13
  49. package/lib/client/pre-session/controller.js.map +1 -1
  50. package/lib/client/pre-session/harness-input.d.ts +13 -0
  51. package/lib/client/pre-session/harness-input.js +18 -0
  52. package/lib/client/pre-session/harness-input.js.map +1 -0
  53. package/lib/client/pre-session/index.d.ts +13 -2
  54. package/lib/client/pre-session/index.js +11 -2
  55. package/lib/client/pre-session/index.js.map +1 -1
  56. package/lib/client/review-console/DeliveryProof.js +15 -12
  57. package/lib/client/review-console/DeliveryProof.js.map +1 -1
  58. package/lib/client/review-console/PreflightStatus.js +15 -8
  59. package/lib/client/review-console/PreflightStatus.js.map +1 -1
  60. package/lib/client/review-console/ReviewActions.d.ts +4 -1
  61. package/lib/client/review-console/ReviewActions.js +139 -114
  62. package/lib/client/review-console/ReviewActions.js.map +1 -1
  63. package/lib/client/review-console/ReviewDetailsModal.d.ts +12 -0
  64. package/lib/client/review-console/ReviewDetailsModal.js +56 -0
  65. package/lib/client/review-console/ReviewDetailsModal.js.map +1 -0
  66. package/lib/client/review-console/ReviewIcon.d.ts +35 -0
  67. package/lib/client/review-console/ReviewIcon.js +14 -0
  68. package/lib/client/review-console/ReviewIcon.js.map +1 -0
  69. package/lib/client/review-console/WorktreeReviewPanel.d.ts +3 -7
  70. package/lib/client/review-console/WorktreeReviewPanel.js +20 -82
  71. package/lib/client/review-console/WorktreeReviewPanel.js.map +1 -1
  72. package/lib/client/review-console/recovery-continuation.d.ts +2 -1
  73. package/lib/client/review-console/recovery-continuation.js +12 -8
  74. package/lib/client/review-console/recovery-continuation.js.map +1 -1
  75. package/lib/client/review-console/review-console.styles.js +101 -23
  76. package/lib/client/review-console/review-console.styles.js.map +1 -1
  77. package/lib/client/styles.js +13 -10
  78. package/lib/client/styles.js.map +1 -1
  79. package/lib/client/target-console/TargetStatusAction.js +87 -65
  80. package/lib/client/target-console/TargetStatusAction.js.map +1 -1
  81. package/lib/client/target-console/WorktreeConsoleView.d.ts +2 -1
  82. package/lib/client/target-console/WorktreeConsoleView.js +42 -37
  83. package/lib/client/target-console/WorktreeConsoleView.js.map +1 -1
  84. package/lib/client/target-console/WorktreeManagerModal.js +3 -1
  85. package/lib/client/target-console/WorktreeManagerModal.js.map +1 -1
  86. package/lib/client/target-console/WorktreeReviewStatus.js +45 -88
  87. package/lib/client/target-console/WorktreeReviewStatus.js.map +1 -1
  88. package/lib/client/target-console/current-polling.d.ts +11 -0
  89. package/lib/client/target-console/current-polling.js +104 -0
  90. package/lib/client/target-console/current-polling.js.map +1 -0
  91. package/lib/client/target-console/target-console.styles.js +8 -0
  92. package/lib/client/target-console/target-console.styles.js.map +1 -1
  93. package/lib/client/workspace-sidebar/index.js +8 -3
  94. package/lib/client/workspace-sidebar/index.js.map +1 -1
  95. package/lib/client/workspace-sidebar/model.d.ts +5 -1
  96. package/lib/client/workspace-sidebar/model.js +97 -23
  97. package/lib/client/workspace-sidebar/model.js.map +1 -1
  98. package/lib/client.js +12228 -8928
  99. package/lib/commands.js +32 -35
  100. package/lib/commands.js.map +1 -1
  101. package/lib/console-contract.d.ts +20 -0
  102. package/lib/console-contract.js.map +1 -1
  103. package/lib/console-host/control-plane.d.ts +3 -1
  104. package/lib/console-host/control-plane.js +186 -95
  105. package/lib/console-host/control-plane.js.map +1 -1
  106. package/lib/console-host/errors.js +2 -1
  107. package/lib/console-host/errors.js.map +1 -1
  108. package/lib/console-host/projection.js +3 -1
  109. package/lib/console-host/projection.js.map +1 -1
  110. package/lib/console-host/review-diff.js +6 -5
  111. package/lib/console-host/review-diff.js.map +1 -1
  112. package/lib/console-host/service.d.ts +27 -23
  113. package/lib/console-host/service.js +66 -51
  114. package/lib/console-host/service.js.map +1 -1
  115. package/lib/console-remote/descriptors.js +4 -2
  116. package/lib/console-remote/descriptors.js.map +1 -1
  117. package/lib/console-remote/remote.d.ts +25 -22
  118. package/lib/console-remote/remote.js.map +1 -1
  119. package/lib/console-remote/schemas.d.ts +14 -2
  120. package/lib/console-remote/schemas.js +8 -0
  121. package/lib/console-remote/schemas.js.map +1 -1
  122. package/lib/i18n/client-messages.d.ts +1671 -0
  123. package/lib/i18n/client-messages.js +1468 -0
  124. package/lib/i18n/client-messages.js.map +1 -0
  125. package/lib/i18n/core.d.ts +12 -0
  126. package/lib/i18n/core.js +10 -0
  127. package/lib/i18n/core.js.map +1 -0
  128. package/lib/i18n/host-messages.d.ts +1495 -0
  129. package/lib/i18n/host-messages.js +1485 -0
  130. package/lib/i18n/host-messages.js.map +1 -0
  131. package/lib/i18n/host.d.ts +9 -0
  132. package/lib/i18n/host.js +34 -0
  133. package/lib/i18n/host.js.map +1 -0
  134. package/lib/i18n/transport-messages.d.ts +10 -0
  135. package/lib/i18n/transport-messages.js +11 -0
  136. package/lib/i18n/transport-messages.js.map +1 -0
  137. package/lib/ports.d.ts +15 -0
  138. package/lib/session-checkout-apply.js +93 -92
  139. package/lib/session-checkout-apply.js.map +1 -1
  140. package/lib/session-checkout-module.js +234 -229
  141. package/lib/session-checkout-module.js.map +1 -1
  142. package/lib/session-target-context.js +2 -1
  143. package/lib/session-target-context.js.map +1 -1
  144. package/lib/tools.d.ts +0 -8
  145. package/lib/tools.js +108 -96
  146. package/lib/tools.js.map +1 -1
  147. package/package.json +3 -1
  148. package/scripts/check-publish.mjs +1 -1
  149. package/scripts/dev-dsh-lib.mjs +1 -1
  150. package/scripts/workspace-sidebar-upstream.mjs +1 -1
@@ -1,4 +1,6 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { ReviewIcon } from './ReviewIcon.js';
3
+ import { useClientTranslator, defaultClientTranslator } from '../i18n.js';
2
4
  import { useEffect, useId, useRef, useState } from 'react';
3
5
  import { Modal } from '@deepseek-ai/dsh-client-ui-primitives';
4
6
  import { worktreeConsoleErrorMeta } from '../../console-contract.js';
@@ -18,20 +20,21 @@ function isStale(error) {
18
20
  function sameStrings(left, right) {
19
21
  return left.length === right.length && left.every((value, index) => value === right[index]);
20
22
  }
21
- function preflightMessage(preflight) {
23
+ function preflightMessage(preflight, t = defaultClientTranslator) {
22
24
  if (preflight.status === 'ready')
23
- return '同步预检通过,正在创建可撤回的 Local Preview。';
25
+ return t("sync.preflight.passed.creating.a.reversible.local.preview");
24
26
  if (preflight.status === 'local_advanced')
25
- return 'Local 已前进,但预检确认可以安全合并。';
27
+ return t("local.advanced.but.preflight.confirmed.a.safe.merge");
26
28
  if (preflight.status === 'already_in_local')
27
- return '本轮内容已在 Local 中;同步将是安全空操作。';
29
+ return t("this.iteration.is.already.in.local.sync.will");
28
30
  if (preflight.status === 'conflict')
29
- return `同步预检发现 ${preflight.conflictingFiles.length} 个冲突文件;Local 未修改。`;
31
+ return t("sync.preflight.found.conflicting.files.local.is.unchanged", { p0: preflight.conflictingFiles.length });
30
32
  if (preflight.status === 'blocked')
31
- return `同步暂时阻塞:${preflight.message}`;
32
- return '同步预检完成;Local 未修改。';
33
+ return t("sync.is.temporarily.blocked", { p0: preflight.message });
34
+ return t("sync.preflight.finished.local.is.unchanged");
33
35
  }
34
- export function ReviewActions({ review, adapter, services, identity, target, disabled, unavailableMessage, focusReview, isActive = () => true, onStale, onTargetChange, }) {
36
+ export function ReviewActions({ review, adapter, services, identity, target, disabled, unavailableMessage, focusReview, renderStatus, isActive = () => true, onStale, onTargetChange, }) {
37
+ const t = useClientTranslator();
35
38
  const formId = useId();
36
39
  const moreMenuRef = useRef(null);
37
40
  const [submitting, setSubmitting] = useState(null);
@@ -44,7 +47,8 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
44
47
  const [retainEnvironment, setRetainEnvironment] = useState(false);
45
48
  const [retention, setRetention] = useState('retain_24h');
46
49
  const [message, setMessage] = useState(null);
47
- const [error, setError] = useState(null);
50
+ const [errorText, setError] = useState(null);
51
+ const error = errorText?.(t) ?? null;
48
52
  const [runtimeConflict, setRuntimeConflict] = useState(null);
49
53
  const mutationLock = useRef(false);
50
54
  const observedTargetRevision = useRef(target?.revision);
@@ -156,15 +160,17 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
156
160
  setRuntimeConflict(nextError.continuation);
157
161
  setCommitMode(null);
158
162
  setError(null);
159
- setMessage('实时写入校验发现冲突;Local 未修改。请明确让 Agent 在 managed Worktree 中解决。');
163
+ setMessage(() => (t) => t("the.live.write.check.found.conflicts.local.is"));
160
164
  finish();
161
165
  return;
162
166
  }
163
- setError(nextError);
164
- if (nextError.code === 'stale_target')
167
+ setError(() => (t) => (nextError));
168
+ if (nextError.code === 'stale_target') {
169
+ setMessage(() => (t) => t("state.changed.before.writing.the.operation.stopped.recover"));
165
170
  onStale(nextError);
171
+ }
166
172
  if (nextError.code === 'stale_local' || nextError.code === 'stale_isolated') {
167
- setMessage('状态在写入前发生变化;已停止操作,请按最新只读预检恢复。');
173
+ setMessage(() => (t) => t("state.changed.before.writing.the.operation.stopped.recover"));
168
174
  void refreshPreflight();
169
175
  }
170
176
  finish();
@@ -201,7 +207,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
201
207
  return;
202
208
  }
203
209
  if (latest.status !== 'success' || latest.preflight.status !== 'conflict') {
204
- setMessage(latest.status === 'success' ? preflightMessage(latest.preflight) : '冲突预检未完成。');
210
+ setMessage(() => (t) => latest.status === 'success' ? preflightMessage(latest.preflight, t) : t("conflict.preflight.has.not.finished"));
205
211
  finish();
206
212
  return;
207
213
  }
@@ -210,7 +216,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
210
216
  || latest.preflight.revision !== preflight.revision
211
217
  || latest.preflight.localHeadOid !== preflight.localHeadOid
212
218
  || !sameStrings(latest.preflight.conflictingFiles, preflight.conflictingFiles)) {
213
- setError({ code: 'stale_target', message: '冲突身份在恢复前已变化,请按最新预检重试。' });
219
+ setError(() => (t) => ({ code: 'stale_target', message: t("the.conflict.identity.changed.before.recovery.retry.using") }));
214
220
  finish();
215
221
  return;
216
222
  }
@@ -237,7 +243,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
237
243
  || nextTarget.targetSessionId !== identity.sessionId
238
244
  || nextTarget.state !== 'working'
239
245
  || nextTarget.revision !== preflight.revision + 1) {
240
- setError({ code: 'checkout_mismatch', message: '恢复编辑后 Host 返回的 Working 身份不一致。' });
246
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("the.working.identity.returned.by.host.after.resuming") }));
241
247
  finish();
242
248
  return;
243
249
  }
@@ -249,7 +255,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
249
255
  || recovery.revision !== nextTarget.revision
250
256
  || recovery.localHeadOid !== preflight.localHeadOid
251
257
  || !sameStrings(recovery.conflictingFiles, preflight.conflictingFiles)) {
252
- setError({ code: 'checkout_mismatch', message: 'Host 未返回精确的冲突恢复凭证。' });
258
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.did.not.return.an.exact.conflict.recovery") }));
253
259
  finish();
254
260
  return;
255
261
  }
@@ -265,7 +271,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
265
271
  localHeadOid: recovery.localHeadOid,
266
272
  conflictingFiles: [...recovery.conflictingFiles],
267
273
  });
268
- setMessage('已安全恢复 Working,冲突解决请求正在等待精确 owner Session 空闲。Local 未修改。');
274
+ setMessage(() => (t) => t("safely.resumed.working.the.conflict.resolution.request.is"));
269
275
  finish();
270
276
  };
271
277
  const startReviewRegeneration = async (preflight) => {
@@ -292,7 +298,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
292
298
  || latest.preflight.checkoutId !== preflight.checkoutId
293
299
  || latest.preflight.reviewId !== preflight.reviewId
294
300
  || latest.preflight.revision !== preflight.revision) {
295
- setMessage(latest.status === 'success' ? preflightMessage(latest.preflight) : '只读复核未完成。');
301
+ setMessage(() => (t) => latest.status === 'success' ? preflightMessage(latest.preflight, t) : t("read.only.recheck.has.not.finished"));
296
302
  finish();
297
303
  return;
298
304
  }
@@ -311,7 +317,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
311
317
  || recovery.checkoutId !== preflight.checkoutId
312
318
  || recovery.reviewId !== preflight.reviewId
313
319
  || recovery.revision !== preflight.revision) {
314
- setError({ code: 'checkout_mismatch', message: 'Host 未返回精确的只读验收再生成凭证。' });
320
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.did.not.return.an.exact.read.only") }));
315
321
  finish();
316
322
  return;
317
323
  }
@@ -323,7 +329,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
323
329
  reviewId: recovery.reviewId,
324
330
  revision: recovery.revision,
325
331
  });
326
- setMessage('只读验收再生成请求正在等待精确 owner Session 空闲;不会恢复 Working 或修改文件。');
332
+ setMessage(() => (t) => t("read.only.review.regeneration.is.waiting.for.the"));
327
333
  finish();
328
334
  };
329
335
  const recoverPreflight = (preflight) => {
@@ -370,7 +376,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
370
376
  finish();
371
377
  return;
372
378
  }
373
- setMessage(preflightMessage(inspected.preflight));
379
+ setMessage(() => (t) => preflightMessage(inspected.preflight, t));
374
380
  if (inspected.preflight.status === 'conflict' || inspected.preflight.status === 'blocked') {
375
381
  finish();
376
382
  return;
@@ -385,7 +391,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
385
391
  return;
386
392
  }
387
393
  applyTarget(outcome.value.target);
388
- setMessage('已同步为可撤回的 Local Preview;请在 Local 中验收。');
394
+ setMessage(renderStatus ? null : () => (t) => t("synced.as.a.reversible.local.preview.review.the"));
389
395
  finish();
390
396
  };
391
397
  const openCheckpoint = () => {
@@ -425,14 +431,14 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
425
431
  || nextTarget.state !== 'working'
426
432
  || nextTarget.review !== undefined
427
433
  || nextTarget.checkpoints?.at(-1)?.checkpointId !== saved.checkpointId) {
428
- setError({ code: 'checkout_mismatch', message: 'Host 返回的 Checkpoint 身份或 Working 状态不一致。' });
434
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.returned.a.mismatched.checkpoint.identity.or.working") }));
429
435
  finish();
430
436
  return;
431
437
  }
432
438
  applyTarget(nextTarget);
433
439
  setCheckpointOpen(false);
434
440
  checkpointRequestId.current = null;
435
- setMessage(`已保存第 ${saved.sequence} 个 Worktree 阶段并继续修改;阶段尚未发布到 Local。`);
441
+ setMessage(() => (t) => t("saved.worktree.stage.and.resumed.editing.the.stage", { p0: saved.sequence }));
436
442
  finish();
437
443
  };
438
444
  const resumeRevision = async () => {
@@ -449,11 +455,11 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
449
455
  }
450
456
  applyTarget(outcome.value.target);
451
457
  const drafted = services
452
- ? prefillSessionDraft(services, identity.sessionId, '请重新检查当前 Worktree 的修改,重新运行必要验证,并重新生成验收稿。')
458
+ ? prefillSessionDraft(services, identity.sessionId, t("please.recheck.the.current.worktree.changes.rerun.the"))
453
459
  : false;
454
- setMessage(drafted
455
- ? '已恢复编辑并预填重新验收请求;Local 未受影响。'
456
- : '已恢复编辑;请重新检查、验证并生成新的验收稿。Local 未受影响。');
460
+ setMessage(() => (t) => drafted
461
+ ? t("resumed.editing.and.prefilled.a.new.review.request")
462
+ : t("resumed.editing.recheck.validate.and.generate.a.new"));
457
463
  finish();
458
464
  };
459
465
  const rollbackPreview = async (resumeRevision = false) => {
@@ -462,7 +468,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
462
468
  let freshProof;
463
469
  if (target?.state === 'preview_detached') {
464
470
  if (!recoveryIdentity) {
465
- setError({ code: 'stale_target', message: 'Detached Preview 身份不完整,请刷新。' });
471
+ setError(() => (t) => ({ code: 'stale_target', message: t("detached.preview.identity.is.incomplete.please.refresh") }));
466
472
  finish();
467
473
  return;
468
474
  }
@@ -476,24 +482,37 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
476
482
  return;
477
483
  }
478
484
  if (inspected.status !== 'success' || inspected.preflight.status !== 'assessed') {
479
- setMessage(inspected.status === 'success' && inspected.preflight.status === 'blocked'
485
+ setMessage(() => (t) => inspected.status === 'success' && inspected.preflight.status === 'blocked'
480
486
  ? inspected.preflight.message
481
- : 'Preview Recovery 预检未完成。');
487
+ : t("preview.recovery.preflight.has.not.finished"));
482
488
  finish();
483
489
  return;
484
490
  }
485
491
  if (inspected.preflight.proof.rollback.status !== 'safe') {
486
- setMessage(inspected.preflight.proof.rollback.message);
492
+ const explanation = inspected.preflight.proof.rollback.message;
493
+ setMessage(() => () => explanation);
487
494
  finish();
488
495
  return;
489
496
  }
490
497
  freshProof = inspected.preflight.proof;
491
498
  }
492
- const outcome = await adapter.rollbackPreview({
493
- ...identity,
494
- resumeRevision,
495
- ...(freshProof ? { recoveryProof: freshProof } : {}),
496
- });
499
+ let outcome;
500
+ try {
501
+ outcome = await adapter.rollbackPreview({
502
+ ...identity,
503
+ resumeRevision,
504
+ ...(freshProof ? { recoveryProof: freshProof } : {}),
505
+ });
506
+ }
507
+ catch (reason) {
508
+ if (isActive()) {
509
+ finishError({ code: 'transport_unavailable', message: reason instanceof Error ? reason.message : String(reason) });
510
+ requestWorktreeReviewRefresh(identity.sessionId);
511
+ }
512
+ else
513
+ finish();
514
+ return;
515
+ }
497
516
  if (!isActive()) {
498
517
  finish();
499
518
  return;
@@ -503,9 +522,11 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
503
522
  return;
504
523
  }
505
524
  applyTarget(outcome.value.target);
506
- setMessage(outcome.value.target.state === 'preview_detached'
507
- ? '恢复条件在写入前发生变化;Preview 证据和 Worktree 已保留,请重新检查。'
508
- : resumeRevision ? '已撤回 Local Preview,可以继续修改 Worktree。' : '已撤回 Local Preview,验收卡仍可再次同步。');
525
+ if (!renderStatus || outcome.value.target.state === 'preview_detached') {
526
+ setMessage(() => (t) => outcome.value.target.state === 'preview_detached'
527
+ ? t("recovery.conditions.changed.before.writing.preview.evidence.and")
528
+ : resumeRevision ? t("local.preview.rolled.back.you.can.continue.editing") : t("local.preview.rolled.back.the.review.can.be"));
529
+ }
509
530
  finish();
510
531
  };
511
532
  const submitCommit = async () => {
@@ -526,7 +547,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
526
547
  return;
527
548
  }
528
549
  if (inspected.status !== 'success' || inspected.preflight.status === 'blocked' || inspected.preflight.status === 'conflict') {
529
- setMessage(inspected.status === 'success' ? preflightMessage(inspected.preflight) : '同步预检未完成。');
550
+ setMessage(() => (t) => inspected.status === 'success' ? preflightMessage(inspected.preflight, t) : t("sync.preflight.has.not.finished"));
530
551
  finish();
531
552
  return;
532
553
  }
@@ -534,7 +555,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
534
555
  let previewProof;
535
556
  if (mode === 'finalize_preview' && target?.state === 'preview_detached') {
536
557
  if (!recoveryIdentity) {
537
- setError({ code: 'stale_target', message: 'Detached Preview 身份不完整,请刷新。' });
558
+ setError(() => (t) => ({ code: 'stale_target', message: t("detached.preview.identity.is.incomplete.please.refresh") }));
538
559
  finish();
539
560
  return;
540
561
  }
@@ -548,14 +569,15 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
548
569
  return;
549
570
  }
550
571
  if (inspected.status !== 'success' || inspected.preflight.status !== 'assessed') {
551
- setMessage(inspected.status === 'success' && inspected.preflight.status === 'blocked'
572
+ setMessage(() => (t) => inspected.status === 'success' && inspected.preflight.status === 'blocked'
552
573
  ? inspected.preflight.message
553
- : 'Preview Recovery 预检未完成。');
574
+ : t("preview.recovery.preflight.has.not.finished"));
554
575
  finish();
555
576
  return;
556
577
  }
557
578
  if (inspected.preflight.proof.finalize.status !== 'safe') {
558
- setMessage(inspected.preflight.proof.finalize.message);
579
+ const explanation = inspected.preflight.proof.finalize.message;
580
+ setMessage(() => () => explanation);
559
581
  finish();
560
582
  return;
561
583
  }
@@ -574,10 +596,10 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
574
596
  }
575
597
  applyTarget(outcome.value.target);
576
598
  if (outcome.value.target.state === 'preview_detached') {
577
- setMessage('Local 已变化,无法可靠提交;Preview 恢复证据和 Worktree 已保留。');
599
+ setMessage(() => (t) => t("local.changed.a.reliable.commit.is.not.possible"));
578
600
  }
579
601
  else {
580
- setMessage(selectedRetention === 'cleanup' ? '已提交到 Local,并开始清理 Worktree。' : '已提交到 Local,并保留当前运行环境。');
602
+ setMessage(() => (t) => selectedRetention === 'cleanup' ? t("committed.to.local.and.started.worktree.cleanup") : t("committed.to.local.and.retained.the.current.environment"));
581
603
  }
582
604
  setCommitMode(null);
583
605
  finish();
@@ -601,9 +623,9 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
601
623
  return;
602
624
  }
603
625
  applyTarget(outcome.value.target);
604
- setMessage(outcome.value.target.state === 'preview_detached'
605
- ? 'Local 已变化,无法无损撤回;未删除 Worktree。'
606
- : '已放弃本轮 Worktree 修改,Local 未受影响。');
626
+ setMessage(() => (t) => outcome.value.target.state === 'preview_detached'
627
+ ? t("local.changed.lossless.rollback.is.not.possible.the")
628
+ : t("discarded.this.iteration.s.worktree.changes.local.is"));
607
629
  setDiscardOpen(false);
608
630
  finish();
609
631
  };
@@ -618,9 +640,9 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
618
640
  return null;
619
641
  }
620
642
  if (inspected.status !== 'success' || inspected.preflight.status !== 'assessed') {
621
- setMessage(inspected.status === 'success' && inspected.preflight.status === 'blocked'
643
+ setMessage(() => (t) => inspected.status === 'success' && inspected.preflight.status === 'blocked'
622
644
  ? inspected.preflight.message
623
- : 'Preview Recovery 预检未完成。');
645
+ : t("preview.recovery.preflight.has.not.finished"));
624
646
  return null;
625
647
  }
626
648
  return inspected.preflight.proof;
@@ -649,7 +671,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
649
671
  || continuation.previewId !== recoveryIdentity.expectedPreviewId
650
672
  || continuation.revision !== identity.expectedRevision
651
673
  || continuation.generation !== proof.generation) {
652
- setError({ code: 'checkout_mismatch', message: 'Host 未返回精确的 detached Recovery 分析凭证。' });
674
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.did.not.return.an.exact.detached.recovery") }));
653
675
  finish();
654
676
  return;
655
677
  }
@@ -662,23 +684,23 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
662
684
  if (!verified.ok || verified.value.target.recoveryContinuation?.kind !== continuation.kind
663
685
  || verified.value.target.recoveryContinuation.requestId !== continuation.requestId
664
686
  || verified.value.target.recoveryContinuation.generation !== continuation.generation) {
665
- throw new Error('二次 Host 检查未确认 detached Recovery 分析凭证。');
687
+ throw new Error(t("the.second.host.inspection.did.not.confirm.the"));
666
688
  }
667
689
  const binding = services.sessions.binding(identity.sessionId);
668
690
  const prompt = binding?.session.prompt;
669
691
  if (!binding || !prompt)
670
- throw new Error('Owner Session 尚未提供 Harness prompt API。');
692
+ throw new Error(t("the.owner.session.has.not.provided.the.harness"));
671
693
  const result = await prompt.call(binding.session, [{ type: 'text', text: [
672
- `请只读分析 detached Preview Recovery:checkout ${identity.checkoutId},review ${identity.expectedReviewId},preview ${recoveryIdentity.expectedPreviewId},generation ${proof.generation}。`,
673
- '禁止修改旧 managed Worktree、Local、Git refs、index、receipt 或 retained artifacts;不要运行 reset/rebase/force checkout/clean。',
674
- '请解释 rollback/finalize blocker、仍缺失的任务增量与最安全的人工下一步。',
694
+ t("analyze.detached.preview.recovery.in.read.only.mode", { p0: identity.checkoutId, p1: identity.expectedReviewId, p2: recoveryIdentity.expectedPreviewId, p3: proof.generation }),
695
+ t("do.not.modify.the.old.managed.worktree.local"),
696
+ t("explain.the.rollback.finalize.blockers.missing.task.changes"),
675
697
  ].join('\n') }], 'queue');
676
698
  if (!result.ok)
677
699
  throw new Error(`${result.error.code}: ${result.error.message}`);
678
- setMessage('已向精确 owner Session 发送只读 Recovery 分析请求。');
700
+ setMessage(() => (t) => t("sent.a.read.only.recovery.analysis.request.to"));
679
701
  }
680
702
  catch (reason) {
681
- setError({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) });
703
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) }));
682
704
  }
683
705
  finish();
684
706
  };
@@ -708,7 +730,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
708
730
  || continuation.generation !== proof.generation
709
731
  || continuation.checkoutId !== created.value.target.checkoutId
710
732
  || continuation.checkoutId === identity.checkoutId) {
711
- setError({ code: 'checkout_mismatch', message: 'Host 返回的 Recovery handoff 身份不一致。' });
733
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.returned.a.mismatched.recovery.handoff.identity") }));
712
734
  finish();
713
735
  return;
714
736
  }
@@ -724,23 +746,23 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
724
746
  if (!verified.ok || verified.value.target.managedRoot !== created.value.managedRoot
725
747
  || verified.value.target.recoveryContinuation?.kind !== continuation.kind
726
748
  || verified.value.target.recoveryContinuation.requestId !== continuation.requestId) {
727
- throw new Error('新 Worktree 的二次 Host/cwd 检查未通过。');
749
+ throw new Error(t("the.second.host.cwd.check.of.the.new"));
728
750
  }
729
751
  const binding = services.sessions.binding(created.value.targetSessionId);
730
752
  const prompt = binding?.session.prompt;
731
753
  if (!binding || !prompt)
732
- throw new Error('新 owner Session 尚未提供 Harness prompt API。');
754
+ throw new Error(t("the.new.owner.session.has.not.provided.the"));
733
755
  const result = await prompt.call(binding.session, [{ type: 'text', text: [
734
- `这是 detached Preview Recovery handoff。旧 checkout ${identity.checkoutId} / review ${identity.expectedReviewId} / preview ${recoveryIdentity.expectedPreviewId} / generation ${proof.generation} 只读。`,
735
- '当前新 Worktree 基于最新 Local HEAD;只恢复仍缺失的任务增量。禁止修改 Local、旧 Worktree、旧 receipt/refs,禁止 reset/rebase/force checkout/clean。',
736
- '完成后运行必要验证并生成新的 Ready for Review。',
756
+ t("this.is.a.detached.preview.recovery.handoff.the", { p0: identity.checkoutId, p1: identity.expectedReviewId, p2: recoveryIdentity.expectedPreviewId, p3: proof.generation }),
757
+ t("the.new.worktree.is.based.on.the.latest"),
758
+ t("run.the.necessary.validation.and.generate.a.new"),
737
759
  ].join('\n') }], 'queue');
738
760
  if (!result.ok)
739
761
  throw new Error(`${result.error.code}: ${result.error.message}`);
740
- setMessage('已创建并打开基于最新 Local HEAD 的 fresh Worktree,Recovery handoff 请求已发送。');
762
+ setMessage(() => (t) => t("created.and.opened.a.fresh.worktree.based.on"));
741
763
  }
742
764
  catch (reason) {
743
- setError({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) });
765
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) }));
744
766
  }
745
767
  finish();
746
768
  };
@@ -761,7 +783,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
761
783
  return;
762
784
  }
763
785
  applyTarget(outcome.value.target);
764
- setMessage(outcome.value.target.state === 'delivered' ? 'Worktree 环境已清理。' : '清理仍未完成,已保留恢复信息。');
786
+ setMessage(() => (t) => outcome.value.target.state === 'delivered' ? t("worktree.environment.cleaned.up") : t("cleanup.is.still.incomplete.recovery.information.was.retained"));
765
787
  finish();
766
788
  };
767
789
  const openHolder = async () => {
@@ -779,7 +801,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
779
801
  await openAuthorizedWorktreeTarget(adapter, services, identity.sessionId, holder, isActive);
780
802
  }
781
803
  catch (reason) {
782
- setError({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) });
804
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) }));
783
805
  }
784
806
  finally {
785
807
  finish();
@@ -812,51 +834,54 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
812
834
  if (submitting === null)
813
835
  setDiscardOpen(false);
814
836
  };
815
- const primary = ready ? (_jsx("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: allDisabled || !target.capabilities.preview || !safeReadyPreflight, onClick: () => { void previewLocal(); }, children: submitting === 'preview'
816
- ? '同步中…'
817
- : autoPreflightEnabled && (preflightSnapshot.status === 'idle' || preflightSnapshot.status === 'loading')
818
- ? '检查中…'
819
- : '预览修改' })) : previewActive ? (_jsx("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: allDisabled || !target.capabilities.finalizePreview, onClick: () => setCommitMode('finalize_preview'), children: "\u786E\u8BA4\u5E76\u4FDD\u5B58" })) : previewRecovery ? (rollbackRecoverySafe ? (_jsx("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || !target?.capabilities.rollbackPreview, onClick: () => { void rollbackPreview(true); }, children: submitting === 'rollback' ? '处理中…' : '恢复并撤回预览' })) : (_jsx("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || target?.state !== 'preview_detached', onClick: () => { void refreshRecoveryPreflight(); }, children: recoveryPreflight.status === 'loading' ? '检查中…' : '重新检查' }))) : cleanupPending ? (_jsx("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || !target?.capabilities.retryCleanup, onClick: () => { void retryCleanup(); }, children: submitting === 'retry_cleanup' ? '清理中…' : '重试清理环境' })) : null;
820
- return (_jsxs("section", { className: "dsh-wt-review-actions", "aria-label": "\u9A8C\u6536\u64CD\u4F5C", children: [!live ? _jsx("p", { className: "dsh-wt-status", children: unavailableMessage }) : null, terminal ? (_jsx("p", { className: "dsh-wt-status", children: target.state === 'retained'
821
- ? `本轮已提交,运行环境暂时保留${target.commitOid ? ` · ${target.commitOid.slice(0, 8)}` : ''}`
822
- : `本轮已交付${target.commitOid ? ` · ${target.commitOid.slice(0, 8)}` : ''}` })) : (_jsxs("div", { className: "dsh-wt-actions", children: [primary, _jsxs("details", { ref: moreMenuRef, className: "dsh-wt-more-menu", children: [_jsx("summary", { className: "dsh-wt-more-trigger", "aria-label": "\u66F4\u591A\u4EA4\u4ED8\u64CD\u4F5C", children: "\u2022\u2022\u2022" }), _jsxs("div", { className: "dsh-wt-more-content", role: "menu", children: [focusReview ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", onClick: () => {
823
- focusReview();
824
- closeMoreMenu();
825
- }, children: "\u67E5\u770B\u9A8C\u6536\u5361" })) : null, ready ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.checkpoint || !target.checkpointGeneration, onClick: () => {
837
+ const primary = ready ? (_jsxs("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: allDisabled || !target.capabilities.preview || !safeReadyPreflight, onClick: () => { void previewLocal(); }, children: [_jsx(ReviewIcon, { name: "preview" }), submitting === 'preview'
838
+ ? t("syncing")
839
+ : autoPreflightEnabled && (preflightSnapshot.status === 'idle' || preflightSnapshot.status === 'loading')
840
+ ? t("checking")
841
+ : t("preview.changes")] })) : previewActive ? (_jsxs("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: allDisabled || !target.capabilities.finalizePreview, onClick: () => setCommitMode('finalize_preview'), children: [_jsx(ReviewIcon, { name: "confirm" }), t("confirm.and.save"), " "] })) : previewRecovery ? (rollbackRecoverySafe ? (_jsxs("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || !target?.capabilities.rollbackPreview, onClick: () => { void rollbackPreview(); }, children: [_jsx(ReviewIcon, { name: "rollback" }), submitting === 'rollback' ? t("processing") : t("recover.and.roll.back.preview")] })) : (_jsxs("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || target?.state !== 'preview_detached', onClick: () => { void refreshRecoveryPreflight(); }, children: [_jsx(ReviewIcon, { name: "refresh" }), recoveryPreflight.status === 'loading' ? t("checking") : t("check.again")] }))) : cleanupPending ? (_jsxs("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || !target?.capabilities.retryCleanup, onClick: () => { void retryCleanup(); }, children: [_jsx(ReviewIcon, { name: "refresh" }), submitting === 'retry_cleanup' ? t("cleaning.up") : t("retry.environment.cleanup")] })) : null;
842
+ return (_jsxs(_Fragment, { children: [renderStatus?.(submitting), _jsxs("section", { className: "dsh-wt-review-actions", "aria-label": t("review.actions"), children: [!live ? _jsx("p", { className: "dsh-wt-status", children: unavailableMessage }) : null, terminal ? (_jsx("p", { className: "dsh-wt-status", children: target.state === 'retained'
843
+ ? t("this.iteration.was.committed.the.environment.is.temporarily", { p0: target.commitOid ? ` · ${target.commitOid.slice(0, 8)}` : '' })
844
+ : t("this.iteration.was.delivered", { p0: target.commitOid ? ` · ${target.commitOid.slice(0, 8)}` : '' }) })) : (_jsxs("div", { className: "dsh-wt-actions", children: [primary, _jsxs("details", { ref: moreMenuRef, className: "dsh-wt-more-menu", children: [_jsx("summary", { className: "dsh-wt-more-trigger", "aria-label": t("more.delivery.actions"), children: _jsx(ReviewIcon, { name: "more" }) }), _jsxs("div", { className: "dsh-wt-more-content", role: "menu", children: [focusReview && !renderStatus ? (_jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", onClick: () => {
845
+ focusReview();
846
+ closeMoreMenu();
847
+ }, children: [_jsx(ReviewIcon, { name: "list" }), t("view.review")] })) : null, ready ? (_jsxs(_Fragment, { children: [_jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.checkpoint || !target.checkpointGeneration, onClick: () => {
848
+ openCheckpoint();
849
+ closeMoreMenu();
850
+ }, children: [_jsx(ReviewIcon, { name: "save" }), t("save.stage.and.continue")] }), _jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.resumeRevision, onClick: () => {
851
+ void resumeRevision();
852
+ closeMoreMenu();
853
+ }, children: [_jsx(ReviewIcon, { name: "edit" }), submitting === 'resume_revision' ? t("recovering") : t("continue.editing")] }), _jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalize || !safeReadyPreflight, onClick: () => {
854
+ setCommitMode('finish');
855
+ closeMoreMenu();
856
+ }, children: [_jsx(ReviewIcon, { name: "confirm" }), t("skip.preview.and.save")] })] })) : null, previewActive && target.capabilities.checkpoint && target.checkpointGeneration ? (_jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled, onClick: () => {
826
857
  openCheckpoint();
827
858
  closeMoreMenu();
828
- }, children: "\u4FDD\u5B58\u9636\u6BB5\u5E76\u7EE7\u7EED" }), _jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.resumeRevision, onClick: () => {
829
- void resumeRevision();
859
+ }, children: [_jsx(ReviewIcon, { name: "save" }), t("save.stage.and.continue")] })) : null, previewActive ? (_jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.rollbackPreview, onClick: () => {
860
+ void rollbackPreview(true);
861
+ closeMoreMenu();
862
+ }, children: [_jsx(ReviewIcon, { name: "edit" }), t("continue.editing")] })) : null, previewActive || rollbackRecoverySafe ? (_jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.rollbackPreview, onClick: () => {
863
+ void rollbackPreview();
864
+ closeMoreMenu();
865
+ }, children: [_jsx(ReviewIcon, { name: "rollback" }), previewActive ? t("roll.back.this.preview") : t("retry.rollback")] })) : null, finalizeRecoverySafe ? (_jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalizePreview, onClick: () => {
866
+ setCommitMode('finalize_preview');
830
867
  closeMoreMenu();
831
- }, children: submitting === 'resume_revision' ? '恢复中…' : '继续修改' }), _jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalize || !safeReadyPreflight, onClick: () => {
832
- setCommitMode('finish');
868
+ }, children: [_jsx(ReviewIcon, { name: "confirm" }), t("save.changes")] })) : null, canDiscard ? (_jsxs("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item dsh-wt-danger-text", disabled: allDisabled, onClick: () => {
869
+ setDiscardOpen(true);
833
870
  closeMoreMenu();
834
- }, children: "\u8DF3\u8FC7\u9884\u89C8\u5E76\u4FDD\u5B58" })] })) : null, previewActive && target.capabilities.checkpoint && target.checkpointGeneration ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled, onClick: () => {
835
- openCheckpoint();
836
- closeMoreMenu();
837
- }, children: "\u4FDD\u5B58\u9636\u6BB5\u5E76\u7EE7\u7EED" })) : null, previewActive || rollbackRecoverySafe ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.rollbackPreview, onClick: () => {
838
- void rollbackPreview(true);
839
- closeMoreMenu();
840
- }, children: previewActive ? '撤回本次预览' : '重新尝试撤回' })) : null, finalizeRecoverySafe ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalizePreview, onClick: () => {
841
- setCommitMode('finalize_preview');
842
- closeMoreMenu();
843
- }, children: "\u4FDD\u5B58\u4FEE\u6539" })) : null, canDiscard ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item dsh-wt-danger-text", disabled: allDisabled, onClick: () => {
844
- setDiscardOpen(true);
845
- closeMoreMenu();
846
- }, children: "\u653E\u5F03\u4EFB\u52A1" })) : null] })] })] })), _jsx(Modal, { open: checkpointOpen, onClose: closeCheckpoint, title: "\u4FDD\u5B58\u5F53\u524D\u8FDB\u5EA6\u5E76\u7EE7\u7EED\uFF1F", closeLabel: "\u5173\u95ED\u4FDD\u5B58\u8FDB\u5EA6\u786E\u8BA4", description: previewActive
847
- ? '会先安全撤回当前预览,再保存本轮任务进度并继续开发;无法证明可以安全撤回时会停止。当前项目不会立即更新。'
848
- : '保存当前任务进度并继续下一阶段;当前项目不会立即更新,最终确认时仍只会生成一次交付。', footer: (_jsxs("div", { className: "dsh-wt-modal-footer", children: [_jsx("button", { type: "button", className: "dsh-wt-button", disabled: submitting !== null, onClick: closeCheckpoint, children: "\u53D6\u6D88" }), _jsx("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: submitting !== null || !checkpointMessage.trim() || checkpointMessage.trim().length > 500, onClick: () => { void checkpoint(); }, children: submitting === 'checkpoint' ? '正在保存…' : '保存进度并继续' })] })), children: _jsxs("div", { className: "dsh-wt-commit-dialog", children: [_jsxs("div", { className: "dsh-wt-checkpoint-note", children: [_jsx("strong", { children: "\u9636\u6BB5\u4E0D\u4F1A\u53D1\u5E03\u5230 Local" }), _jsxs("span", { children: ["\u5DF2\u6709 ", target?.checkpoints?.length ?? 0, " \u4E2A\u9636\u6BB5\uFF1B\u6700\u7EC8\u4EA4\u4ED8\u4ECD\u4F1A\u4ECE\u539F\u59CB\u4EFB\u52A1\u57FA\u7EBF\u6C47\u603B\u4E3A\u4E00\u4E2A Local Commit\u3002"] })] }), _jsx("label", { htmlFor: `${formId}-checkpoint-message`, children: "Checkpoint Commit Message" }), _jsx("textarea", { id: `${formId}-checkpoint-message`, "aria-label": "Checkpoint Commit Message", rows: 6, maxLength: 500, value: checkpointMessage, onChange: event => setCheckpointMessage(event.target.value) }), _jsxs("div", { className: "dsh-wt-character-count", children: [checkpointMessage.length, "/500"] })] }) }), _jsx(Modal, { open: commitMode !== null, onClose: closeCommit, title: commitMode === 'finalize_preview'
849
- ? '确认并保存本次修改?'
850
- : target?.state === 'preview_detached' ? '保存本次修改?' : '跳过预览并直接保存?', closeLabel: "\u5173\u95ED\u4FDD\u5B58\u786E\u8BA4", description: commitMode === 'finalize_preview'
851
- ? '只会保存当前预览对应的本轮任务内容;Local 中已有或之后新增的无关修改不会进入该 Commit。'
852
- : '将跳过 Local Preview,直接把本轮 Worktree 增量保存为一个 Commit。', footer: (_jsxs("div", { className: "dsh-wt-modal-footer", children: [_jsx("button", { type: "button", className: "dsh-wt-button", disabled: submitting !== null, onClick: closeCommit, children: "\u53D6\u6D88" }), _jsx("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: submitting !== null || !commitMessage.trim() || commitMessage.trim().length > 500, onClick: () => { void submitCommit(); }, children: submitting === 'finish' || submitting === 'finalize_preview'
853
- ? '正在保存…'
854
- : retainEnvironment ? '确认交付并保留环境' : '确认交付并清理' })] })), children: _jsxs("div", { className: "dsh-wt-commit-dialog", children: [_jsx("label", { htmlFor: `${formId}-message`, children: "Commit Message" }), _jsx("textarea", { id: `${formId}-message`, "aria-label": "Commit Message", rows: 6, maxLength: 500, value: commitMessage, onChange: event => setCommitMessage(event.target.value) }), _jsxs("div", { className: "dsh-wt-character-count", children: [commitMessage.length, "/500"] }), _jsxs("label", { className: "dsh-wt-retention-check", children: [_jsx("input", { type: "checkbox", checked: retainEnvironment, onChange: event => setRetainEnvironment(event.target.checked) }), _jsx("span", { children: "\u63D0\u4EA4\u540E\u6682\u65F6\u4FDD\u7559\u5F53\u524D\u8FD0\u884C\u73AF\u5883" })] }), retainEnvironment ? (_jsxs("label", { className: "dsh-wt-retention-select", children: [_jsx("span", { children: "\u4FDD\u7559\u65F6\u957F" }), _jsxs("select", { "aria-label": "\u4FDD\u7559\u65F6\u957F", value: retention, onChange: event => setRetention(event.target.value), children: [_jsx("option", { value: "retain_24h", children: "\u4FDD\u7559 24 \u5C0F\u65F6" }), _jsx("option", { value: "retain_3d", children: "\u4FDD\u7559 3 \u5929" }), _jsx("option", { value: "retain_manual", children: "\u624B\u52A8\u6E05\u7406" })] })] })) : null] }) }), _jsx(Modal, { open: discardOpen, onClose: closeDiscard, title: "\u653E\u5F03\u672C\u8F6E\u4EFB\u52A1\uFF1F", closeLabel: "\u5173\u95ED\u653E\u5F03\u786E\u8BA4", description: previewActive
855
- ? '会先安全撤回本次 Local Preview,再清理 Worktree;无法无损撤回时会停止,不会覆盖 Local 修改。'
856
- : 'Worktree 中尚未交付的修改将被永久丢弃,Local 不受影响。', footer: (_jsxs("div", { className: "dsh-wt-modal-footer", children: [_jsx("button", { type: "button", className: "dsh-wt-button", disabled: submitting !== null, onClick: closeDiscard, children: "\u53D6\u6D88" }), _jsx("button", { type: "button", className: "dsh-wt-button dsh-wt-danger", disabled: submitting !== null, onClick: () => { void discard(); }, children: submitting === 'discard' ? '正在放弃…' : '确认放弃任务' })] })) }), ready ? (_jsx(PreflightStatus, { snapshot: preflightSnapshot, target: target, onRefresh: () => { void refreshPreflight(); }, onRecovery: recoverPreflight, onOpenHolder: () => { void openHolder(); }, busy: submitting !== null || activeRecovery?.status === 'queued' || activeRecovery?.status === 'sending' || activeRecovery?.status === 'sent' })) : null, target?.state === 'preview_detached' ? (_jsxs("div", { className: "dsh-wt-preflight", "data-status": recoveryPreflight.status, children: [_jsxs("div", { className: "dsh-wt-preflight-head", children: [_jsx("strong", { children: "Detached Preview Recovery" }), _jsx("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || recoveryPreflight.status === 'loading', onClick: () => { void refreshRecoveryPreflight(); }, children: "\u91CD\u65B0\u68C0\u67E5" })] }), _jsx("p", { children: "Detached \u662F\u4EA4\u4ED8\u6062\u590D\u72B6\u6001\uFF0C\u4E0D\u662F Git detached HEAD\u3002\u68C0\u67E5\u4E25\u683C\u53EA\u8BFB\uFF0C\u5199\u64CD\u4F5C\u4F1A\u5728 Host \u9501\u5185\u518D\u6B21\u9A8C\u8BC1\u3002" }), recoveryPreflight.status === 'loading' ? _jsx("p", { children: "\u6B63\u5728\u68C0\u67E5 Local HEAD\u3001index\u3001working tree\u3001retained artifacts \u4E0E\u9A8C\u6536\u69FD\u4F4D\u2026" }) : null, recoveryPreflight.status === 'error' ? _jsx("p", { className: "dsh-wt-error", children: recoveryPreflight.error.message }) : null, recoveryPreflight.status === 'success' && recoveryPreflight.preflight.status === 'blocked' ? (_jsx("p", { className: "dsh-wt-error", children: recoveryPreflight.preflight.message })) : null, recoveryProof ? (_jsxs(_Fragment, { children: [_jsxs("p", { className: "dsh-wt-code", children: ["generation ", recoveryProof.generation.slice(0, 12), " \u00B7 HEAD ", recoveryProof.localHeadOid.slice(0, 12), " \u00B7 ", recoveryProof.localHeadRef ?? 'detached HEAD'] }), _jsxs("ul", { className: "dsh-wt-test-list", "aria-label": "Preview Recovery \u7ED3\u8BBA", children: [_jsxs("li", { children: ["\u64A4\u56DE\uFF1A", recoveryProof.rollback.status === 'safe' ? '可证明安全' : recoveryProof.rollback.message] }), _jsxs("li", { children: ["\u63D0\u4EA4\uFF1A", recoveryProof.finalize.status === 'safe' ? '可证明安全' : recoveryProof.finalize.message] })] }), recoveryProof.rollback.status === 'blocked' && recoveryProof.rollback.conflictingFiles?.length ? (_jsxs("p", { children: ["\u64A4\u56DE\u51B2\u7A81\uFF1A", recoveryProof.rollback.conflictingFiles.join('、')] })) : null, recoveryProof.finalize.status === 'blocked' && recoveryProof.finalize.conflictingFiles?.length ? (_jsxs("p", { children: ["\u63D0\u4EA4\u51B2\u7A81\uFF1A", recoveryProof.finalize.conflictingFiles.join('、')] })) : null, recoveryProof.blocker ? (_jsx("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: () => { void openHolder(); }, children: "\u6253\u5F00\u5360\u7528 Local \u9A8C\u6536\u69FD\u4F4D\u7684 Worktree" })) : null, _jsxs("div", { className: "dsh-wt-recovery-actions", children: [_jsx("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: () => { void analyzeRecovery(); }, children: "\u8BA9 Agent \u53EA\u8BFB\u5206\u6790" }), _jsx("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: () => { void handoffRecovery(); }, children: "\u4EA4\u63A5\u5230\u65B0 Worktree" })] })] })) : null] })) : null, runtimeConflict ? (_jsx("div", { className: "dsh-wt-recovery-actions", children: _jsx("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: recoverRuntimeConflict, children: "\u8BA9 Agent \u89E3\u51B3\u51B2\u7A81" }) })) : null, activeRecovery ? (_jsxs("div", { className: "dsh-wt-action-status", "data-recovery-status": activeRecovery.status, children: [activeRecovery.status === 'queued' ? '恢复请求已排队,等待 owner Session 加载完成且停止 streaming。' : null, activeRecovery.status === 'sending' ? '正在通过 Harness 官方 Session API 发送恢复请求…' : null, activeRecovery.status === 'sent'
857
- ? activeRecovery.request.kind === 'worktree_apply_conflict'
858
- ? '已交给 Agent 解决冲突;完成后必须生成新的验收卡。'
859
- : '已交给 Agent 只读重新生成验收结果;不会修改 Worktree。'
860
- : null, activeRecovery.status === 'cancelled' ? 'Session/checkout 已切换,旧恢复请求已取消。' : null, activeRecovery.status === 'failed' ? (_jsxs(_Fragment, { children: [_jsxs("span", { children: ["\u6062\u590D\u8BF7\u6C42\u53D1\u9001\u5931\u8D25\uFF1A", activeRecovery.error] }), _jsx("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null, onClick: () => retryWorktreeRecovery(activeRecovery.request.sessionId), children: "\u91CD\u65B0\u53D1\u9001" })] })) : null] })) : null, target && (target.state === 'cleanup_pending' || terminal) ? _jsx(DeliveryProof, { target: target }) : null, _jsx("div", { className: "dsh-wt-action-status", "aria-live": "polite", children: submitting ? '正在处理 Worktree,请稍候…' : message }), error && !isStale(error) ? (_jsxs("div", { className: "dsh-wt-error", role: "alert", children: [error.message, "\uFF08", worktreeConsoleErrorMeta(error.code).category, "\uFF1B\u6062\u590D\u65B9\u5F0F\uFF1A", worktreeConsoleErrorMeta(error.code).recovery, "\uFF09"] })) : null] }));
871
+ }, children: [_jsx(ReviewIcon, { name: "discard" }), t("discard.task")] })) : null] })] })] })), _jsx(Modal, { open: checkpointOpen, onClose: closeCheckpoint, title: t("save.current.progress.and.continue"), closeLabel: t("close.save.progress.confirmation"), description: previewActive
872
+ ? t("first.safely.roll.back.the.preview.then.save")
873
+ : t("save.task.progress.and.continue.to.the.next"), footer: (_jsxs("div", { className: "dsh-wt-modal-footer", children: [_jsx("button", { type: "button", className: "dsh-wt-button", disabled: submitting !== null, onClick: closeCheckpoint, children: t("cancel") }), _jsxs("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: submitting !== null || !checkpointMessage.trim() || checkpointMessage.trim().length > 500, onClick: () => { void checkpoint(); }, children: [_jsx(ReviewIcon, { name: "save" }), submitting === 'checkpoint' ? t("saving") : t("save.progress.and.continue")] })] })), children: _jsxs("div", { className: "dsh-wt-commit-dialog", children: [_jsxs("div", { className: "dsh-wt-checkpoint-note", children: [_jsx("strong", { children: t("stages.are.not.published.to.local") }), _jsx("span", { children: t("checkpoint.summary", { count: target?.checkpoints?.length ?? 0 }) })] }), _jsx("label", { htmlFor: `${formId}-checkpoint-message`, children: t("checkpoint.commit.message") }), _jsx("textarea", { id: `${formId}-checkpoint-message`, "aria-label": t("checkpoint.commit.message"), rows: 6, maxLength: 500, value: checkpointMessage, onChange: event => setCheckpointMessage(event.target.value) }), _jsxs("div", { className: "dsh-wt-character-count", children: [checkpointMessage.length, t("500")] })] }) }), _jsx(Modal, { open: commitMode !== null, onClose: closeCommit, title: commitMode === 'finalize_preview'
874
+ ? t("confirm.and.save.these.changes")
875
+ : target?.state === 'preview_detached' ? t("save.these.changes") : t("skip.preview.and.save.directly"), closeLabel: t("close.save.confirmation"), description: commitMode === 'finalize_preview'
876
+ ? t("only.this.iteration.s.task.changes.in.the")
877
+ : t("skip.local.preview.and.save.this.iteration.s"), footer: (_jsxs("div", { className: "dsh-wt-modal-footer", children: [_jsx("button", { type: "button", className: "dsh-wt-button", disabled: submitting !== null, onClick: closeCommit, children: t("cancel") }), _jsxs("button", { type: "button", className: "dsh-wt-button dsh-wt-primary", disabled: submitting !== null || !commitMessage.trim() || commitMessage.trim().length > 500, onClick: () => { void submitCommit(); }, children: [_jsx(ReviewIcon, { name: "confirm" }), submitting === 'finish' || submitting === 'finalize_preview'
878
+ ? t("saving")
879
+ : retainEnvironment ? t("confirm.delivery.and.retain.environment") : t("confirm.delivery.and.clean.up")] })] })), children: _jsxs("div", { className: "dsh-wt-commit-dialog", children: [_jsx("label", { htmlFor: `${formId}-message`, children: t("commit.message") }), _jsx("textarea", { id: `${formId}-message`, "aria-label": t("commit.message"), rows: 6, maxLength: 500, value: commitMessage, onChange: event => setCommitMessage(event.target.value) }), _jsxs("div", { className: "dsh-wt-character-count", children: [commitMessage.length, t("500")] }), _jsxs("label", { className: "dsh-wt-retention-check", children: [_jsx("input", { type: "checkbox", checked: retainEnvironment, onChange: event => setRetainEnvironment(event.target.checked) }), _jsx("span", { children: t("temporarily.retain.the.current.environment.after.committing") })] }), retainEnvironment ? (_jsxs("label", { className: "dsh-wt-retention-select", children: [_jsx("span", { children: t("retention.period") }), _jsxs("select", { "aria-label": t("retention.period"), value: retention, onChange: event => setRetention(event.target.value), children: [_jsx("option", { value: "retain_24h", children: t("retain.for.24.hours") }), _jsx("option", { value: "retain_3d", children: t("retain.for.3.days") }), _jsx("option", { value: "retain_manual", children: t("manual.cleanup") })] })] })) : null] }) }), _jsx(Modal, { open: discardOpen, onClose: closeDiscard, title: t("discard.this.iteration"), closeLabel: t("close.discard.confirmation"), description: previewActive
880
+ ? t("first.safely.roll.back.this.local.preview.then")
881
+ : t("undelivered.worktree.changes.will.be.permanently.discarded.local"), footer: (_jsxs("div", { className: "dsh-wt-modal-footer", children: [_jsx("button", { type: "button", className: "dsh-wt-button", disabled: submitting !== null, onClick: closeDiscard, children: t("cancel") }), _jsxs("button", { type: "button", className: "dsh-wt-button dsh-wt-danger", disabled: submitting !== null, onClick: () => { void discard(); }, children: [_jsx(ReviewIcon, { name: "discard" }), submitting === 'discard' ? t("discarding") : t("confirm.discard.task")] })] })) }), ready ? (_jsx(PreflightStatus, { snapshot: preflightSnapshot, target: target, onRefresh: () => { void refreshPreflight(); }, onRecovery: recoverPreflight, onOpenHolder: () => { void openHolder(); }, busy: submitting !== null || activeRecovery?.status === 'queued' || activeRecovery?.status === 'sending' || activeRecovery?.status === 'sent' })) : null, target?.state === 'preview_detached' ? (_jsxs("div", { className: "dsh-wt-preflight", "data-status": recoveryPreflight.status, children: [_jsxs("div", { className: "dsh-wt-preflight-head", children: [_jsx("strong", { children: t("detached.preview.recovery") }), _jsxs("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || recoveryPreflight.status === 'loading', onClick: () => { void refreshRecoveryPreflight(); }, children: [_jsx(ReviewIcon, { name: "refresh" }), t("check.again"), " "] })] }), _jsx("p", { children: t("detached.is.a.delivery.recovery.state.not.git") }), _jsx(ReviewIcon, { name: "refresh" }), recoveryPreflight.status === 'loading' ? _jsx("p", { children: t("checking.local.head.index.working.tree.retained.artifacts") }) : null, recoveryPreflight.status === 'error' ? _jsx("p", { className: "dsh-wt-error", children: recoveryPreflight.error.message }) : null, recoveryPreflight.status === 'success' && recoveryPreflight.preflight.status === 'blocked' ? (_jsx("p", { className: "dsh-wt-error", children: recoveryPreflight.preflight.message })) : null, recoveryProof ? (_jsxs(_Fragment, { children: [_jsxs("p", { className: "dsh-wt-code", children: [t("generation"), " ", recoveryProof.generation.slice(0, 12), " ", t("head"), " ", recoveryProof.localHeadOid.slice(0, 12), " \u00B7 ", recoveryProof.localHeadRef ?? 'detached HEAD'] }), _jsxs("ul", { className: "dsh-wt-test-list", "aria-label": t("preview.recovery.outcome"), children: [_jsxs("li", { children: [t("rollback"), recoveryProof.rollback.status === 'safe' ? t("verified.safe") : recoveryProof.rollback.message] }), _jsxs("li", { children: [t("commit.2"), recoveryProof.finalize.status === 'safe' ? t("verified.safe") : recoveryProof.finalize.message] })] }), recoveryProof.rollback.status === 'blocked' && recoveryProof.rollback.conflictingFiles?.length ? (_jsxs("p", { children: [t("rollback.conflicts"), recoveryProof.rollback.conflictingFiles.join('、')] })) : null, recoveryProof.finalize.status === 'blocked' && recoveryProof.finalize.conflictingFiles?.length ? (_jsxs("p", { children: [t("commit.conflicts"), recoveryProof.finalize.conflictingFiles.join('、')] })) : null, recoveryProof.blocker ? (_jsxs("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: () => { void openHolder(); }, children: [_jsx(ReviewIcon, { name: "external" }), t("open.the.worktree.holding.the.local.review.slot"), " "] })) : null, _jsxs("div", { className: "dsh-wt-recovery-actions", children: [_jsxs("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: () => { void analyzeRecovery(); }, children: [_jsx(ReviewIcon, { name: "search" }), t("ask.agent.for.read.only.analysis"), " "] }), _jsxs("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: () => { void handoffRecovery(); }, children: [_jsx(ReviewIcon, { name: "branch" }), t("hand.off.to.a.new.worktree"), " "] })] })] })) : null] })) : null, runtimeConflict ? (_jsx("div", { className: "dsh-wt-recovery-actions", children: _jsxs("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: recoverRuntimeConflict, children: [_jsx(ReviewIcon, { name: "warning" }), t("ask.agent.to.resolve.conflicts"), " "] }) })) : null, activeRecovery ? (_jsxs("div", { className: "dsh-wt-action-status", "data-recovery-status": activeRecovery.status, children: [activeRecovery.status === 'queued' ? t("recovery.request.queued.waiting.for.the.owner.session") : null, activeRecovery.status === 'sending' ? t("sending.the.recovery.request.through.the.official.harness") : null, activeRecovery.status === 'sent'
882
+ ? activeRecovery.request.kind === 'worktree_apply_conflict'
883
+ ? t("agent.will.resolve.the.conflicts.and.must.generate")
884
+ : t("agent.will.regenerate.the.review.in.read.only")
885
+ : null, activeRecovery.status === 'cancelled' ? t("session.checkout.changed.the.old.recovery.request.was") : null, activeRecovery.status === 'failed' ? (_jsxs(_Fragment, { children: [_jsxs("span", { children: [t("recovery.request.failed"), activeRecovery.error] }), _jsxs("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null, onClick: () => retryWorktreeRecovery(activeRecovery.request.sessionId), children: [_jsx(ReviewIcon, { name: "send" }), t("resend")] })] })) : null] })) : null, target && (target.state === 'cleanup_pending' || terminal) ? _jsx(DeliveryProof, { target: target }) : null, _jsx("div", { className: "dsh-wt-action-status", "aria-live": "polite", children: submitting ? (renderStatus ? null : t("processing.worktree.please.wait")) : message?.(t) }), error && !isStale(error) ? (_jsxs("div", { className: "dsh-wt-error", role: "alert", children: [t("error.detail", { message: error.message, category: t(`error.category.${worktreeConsoleErrorMeta(error.code).category}`), recovery: t(`error.recovery.${worktreeConsoleErrorMeta(error.code).recovery}`) }), " "] })) : null] })] }));
861
886
  }
862
887
  //# sourceMappingURL=ReviewActions.js.map