dsh-git-worktree 0.7.5 → 0.8.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 (117) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.en.md +7 -3
  3. package/README.md +7 -3
  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 +6 -5
  10. package/lib/adapters/git.js.map +1 -1
  11. package/lib/adapters/registry.d.ts +0 -7
  12. package/lib/adapters/registry.js +2 -1
  13. package/lib/adapters/registry.js.map +1 -1
  14. package/lib/adapters/safe-file.d.ts +0 -7
  15. package/lib/adapters/safe-file.js +5 -4
  16. package/lib/adapters/safe-file.js.map +1 -1
  17. package/lib/client/WorktreeCreateRow.js +4 -2
  18. package/lib/client/WorktreeCreateRow.js.map +1 -1
  19. package/lib/client/WorktreeReviewRow.js +10 -8
  20. package/lib/client/WorktreeReviewRow.js.map +1 -1
  21. package/lib/client/actions.d.ts +3 -2
  22. package/lib/client/actions.js +17 -13
  23. package/lib/client/actions.js.map +1 -1
  24. package/lib/client/console-remote/adapter.d.ts +2 -1
  25. package/lib/client/console-remote/adapter.js +35 -32
  26. package/lib/client/console-remote/adapter.js.map +1 -1
  27. package/lib/client/console-remote/index.js +6 -2
  28. package/lib/client/console-remote/index.js.map +1 -1
  29. package/lib/client/i18n.d.ts +25 -0
  30. package/lib/client/i18n.js +43 -0
  31. package/lib/client/i18n.js.map +1 -0
  32. package/lib/client/index.d.ts +1 -1
  33. package/lib/client/index.js +17 -4
  34. package/lib/client/index.js.map +1 -1
  35. package/lib/client/model.d.ts +3 -2
  36. package/lib/client/model.js +8 -8
  37. package/lib/client/model.js.map +1 -1
  38. package/lib/client/pre-session/PreSessionWorktreeToggle.js +14 -12
  39. package/lib/client/pre-session/PreSessionWorktreeToggle.js.map +1 -1
  40. package/lib/client/pre-session/controller.js +11 -9
  41. package/lib/client/pre-session/controller.js.map +1 -1
  42. package/lib/client/pre-session/index.d.ts +12 -1
  43. package/lib/client/pre-session/index.js +9 -1
  44. package/lib/client/pre-session/index.js.map +1 -1
  45. package/lib/client/review-console/DeliveryProof.js +15 -12
  46. package/lib/client/review-console/DeliveryProof.js.map +1 -1
  47. package/lib/client/review-console/PreflightStatus.js +14 -8
  48. package/lib/client/review-console/PreflightStatus.js.map +1 -1
  49. package/lib/client/review-console/ReviewActions.js +97 -92
  50. package/lib/client/review-console/ReviewActions.js.map +1 -1
  51. package/lib/client/review-console/WorktreeReviewPanel.d.ts +1 -1
  52. package/lib/client/review-console/WorktreeReviewPanel.js +19 -16
  53. package/lib/client/review-console/WorktreeReviewPanel.js.map +1 -1
  54. package/lib/client/review-console/recovery-continuation.d.ts +2 -1
  55. package/lib/client/review-console/recovery-continuation.js +12 -8
  56. package/lib/client/review-console/recovery-continuation.js.map +1 -1
  57. package/lib/client/target-console/TargetStatusAction.js +28 -25
  58. package/lib/client/target-console/TargetStatusAction.js.map +1 -1
  59. package/lib/client/target-console/WorktreeConsoleView.js +40 -36
  60. package/lib/client/target-console/WorktreeConsoleView.js.map +1 -1
  61. package/lib/client/target-console/WorktreeManagerModal.js +3 -1
  62. package/lib/client/target-console/WorktreeManagerModal.js.map +1 -1
  63. package/lib/client/target-console/WorktreeReviewStatus.js +14 -12
  64. package/lib/client/target-console/WorktreeReviewStatus.js.map +1 -1
  65. package/lib/client/workspace-sidebar/index.js +4 -2
  66. package/lib/client/workspace-sidebar/index.js.map +1 -1
  67. package/lib/client/workspace-sidebar/model.d.ts +2 -1
  68. package/lib/client/workspace-sidebar/model.js +14 -13
  69. package/lib/client/workspace-sidebar/model.js.map +1 -1
  70. package/lib/client.js +2173 -477
  71. package/lib/commands.js +32 -35
  72. package/lib/commands.js.map +1 -1
  73. package/lib/console-host/control-plane.js +82 -81
  74. package/lib/console-host/control-plane.js.map +1 -1
  75. package/lib/console-host/errors.js +2 -1
  76. package/lib/console-host/errors.js.map +1 -1
  77. package/lib/console-host/projection.js +3 -1
  78. package/lib/console-host/projection.js.map +1 -1
  79. package/lib/console-host/review-diff.js +6 -5
  80. package/lib/console-host/review-diff.js.map +1 -1
  81. package/lib/console-host/service.d.ts +24 -22
  82. package/lib/console-host/service.js +54 -51
  83. package/lib/console-host/service.js.map +1 -1
  84. package/lib/console-remote/descriptors.js +2 -2
  85. package/lib/console-remote/descriptors.js.map +1 -1
  86. package/lib/console-remote/remote.d.ts +22 -21
  87. package/lib/console-remote/remote.js.map +1 -1
  88. package/lib/console-remote/schemas.d.ts +4 -0
  89. package/lib/console-remote/schemas.js +1 -0
  90. package/lib/console-remote/schemas.js.map +1 -1
  91. package/lib/i18n/client-messages.d.ts +1523 -0
  92. package/lib/i18n/client-messages.js +1431 -0
  93. package/lib/i18n/client-messages.js.map +1 -0
  94. package/lib/i18n/core.d.ts +12 -0
  95. package/lib/i18n/core.js +10 -0
  96. package/lib/i18n/core.js.map +1 -0
  97. package/lib/i18n/host-messages.d.ts +1463 -0
  98. package/lib/i18n/host-messages.js +1474 -0
  99. package/lib/i18n/host-messages.js.map +1 -0
  100. package/lib/i18n/host.d.ts +9 -0
  101. package/lib/i18n/host.js +34 -0
  102. package/lib/i18n/host.js.map +1 -0
  103. package/lib/i18n/transport-messages.d.ts +10 -0
  104. package/lib/i18n/transport-messages.js +11 -0
  105. package/lib/i18n/transport-messages.js.map +1 -0
  106. package/lib/session-checkout-apply.js +93 -92
  107. package/lib/session-checkout-apply.js.map +1 -1
  108. package/lib/session-checkout-module.js +232 -229
  109. package/lib/session-checkout-module.js.map +1 -1
  110. package/lib/session-target-context.js +2 -1
  111. package/lib/session-target-context.js.map +1 -1
  112. package/lib/tools.d.ts +0 -8
  113. package/lib/tools.js +108 -96
  114. package/lib/tools.js.map +1 -1
  115. package/package.json +2 -1
  116. package/scripts/dev-dsh-lib.mjs +1 -1
  117. package/scripts/workspace-sidebar-upstream.mjs +1 -1
@@ -1,4 +1,5 @@
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 { useClientTranslator, defaultClientTranslator } from '../i18n.js';
2
3
  import { useEffect, useId, useRef, useState } from 'react';
3
4
  import { Modal } from '@deepseek-ai/dsh-client-ui-primitives';
4
5
  import { worktreeConsoleErrorMeta } from '../../console-contract.js';
@@ -18,20 +19,21 @@ function isStale(error) {
18
19
  function sameStrings(left, right) {
19
20
  return left.length === right.length && left.every((value, index) => value === right[index]);
20
21
  }
21
- function preflightMessage(preflight) {
22
+ function preflightMessage(preflight, t = defaultClientTranslator) {
22
23
  if (preflight.status === 'ready')
23
- return '同步预检通过,正在创建可撤回的 Local Preview。';
24
+ return t("sync.preflight.passed.creating.a.reversible.local.preview");
24
25
  if (preflight.status === 'local_advanced')
25
- return 'Local 已前进,但预检确认可以安全合并。';
26
+ return t("local.advanced.but.preflight.confirmed.a.safe.merge");
26
27
  if (preflight.status === 'already_in_local')
27
- return '本轮内容已在 Local 中;同步将是安全空操作。';
28
+ return t("this.iteration.is.already.in.local.sync.will");
28
29
  if (preflight.status === 'conflict')
29
- return `同步预检发现 ${preflight.conflictingFiles.length} 个冲突文件;Local 未修改。`;
30
+ return t("sync.preflight.found.conflicting.files.local.is.unchanged", { p0: preflight.conflictingFiles.length });
30
31
  if (preflight.status === 'blocked')
31
- return `同步暂时阻塞:${preflight.message}`;
32
- return '同步预检完成;Local 未修改。';
32
+ return t("sync.is.temporarily.blocked", { p0: preflight.message });
33
+ return t("sync.preflight.finished.local.is.unchanged");
33
34
  }
34
35
  export function ReviewActions({ review, adapter, services, identity, target, disabled, unavailableMessage, focusReview, isActive = () => true, onStale, onTargetChange, }) {
36
+ const t = useClientTranslator();
35
37
  const formId = useId();
36
38
  const moreMenuRef = useRef(null);
37
39
  const [submitting, setSubmitting] = useState(null);
@@ -44,7 +46,8 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
44
46
  const [retainEnvironment, setRetainEnvironment] = useState(false);
45
47
  const [retention, setRetention] = useState('retain_24h');
46
48
  const [message, setMessage] = useState(null);
47
- const [error, setError] = useState(null);
49
+ const [errorText, setError] = useState(null);
50
+ const error = errorText?.(t) ?? null;
48
51
  const [runtimeConflict, setRuntimeConflict] = useState(null);
49
52
  const mutationLock = useRef(false);
50
53
  const observedTargetRevision = useRef(target?.revision);
@@ -156,15 +159,15 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
156
159
  setRuntimeConflict(nextError.continuation);
157
160
  setCommitMode(null);
158
161
  setError(null);
159
- setMessage('实时写入校验发现冲突;Local 未修改。请明确让 Agent 在 managed Worktree 中解决。');
162
+ setMessage(() => (t) => t("the.live.write.check.found.conflicts.local.is"));
160
163
  finish();
161
164
  return;
162
165
  }
163
- setError(nextError);
166
+ setError(() => (t) => (nextError));
164
167
  if (nextError.code === 'stale_target')
165
168
  onStale(nextError);
166
169
  if (nextError.code === 'stale_local' || nextError.code === 'stale_isolated') {
167
- setMessage('状态在写入前发生变化;已停止操作,请按最新只读预检恢复。');
170
+ setMessage(() => (t) => t("state.changed.before.writing.the.operation.stopped.recover"));
168
171
  void refreshPreflight();
169
172
  }
170
173
  finish();
@@ -201,7 +204,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
201
204
  return;
202
205
  }
203
206
  if (latest.status !== 'success' || latest.preflight.status !== 'conflict') {
204
- setMessage(latest.status === 'success' ? preflightMessage(latest.preflight) : '冲突预检未完成。');
207
+ setMessage(() => (t) => latest.status === 'success' ? preflightMessage(latest.preflight, t) : t("conflict.preflight.has.not.finished"));
205
208
  finish();
206
209
  return;
207
210
  }
@@ -210,7 +213,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
210
213
  || latest.preflight.revision !== preflight.revision
211
214
  || latest.preflight.localHeadOid !== preflight.localHeadOid
212
215
  || !sameStrings(latest.preflight.conflictingFiles, preflight.conflictingFiles)) {
213
- setError({ code: 'stale_target', message: '冲突身份在恢复前已变化,请按最新预检重试。' });
216
+ setError(() => (t) => ({ code: 'stale_target', message: t("the.conflict.identity.changed.before.recovery.retry.using") }));
214
217
  finish();
215
218
  return;
216
219
  }
@@ -237,7 +240,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
237
240
  || nextTarget.targetSessionId !== identity.sessionId
238
241
  || nextTarget.state !== 'working'
239
242
  || nextTarget.revision !== preflight.revision + 1) {
240
- setError({ code: 'checkout_mismatch', message: '恢复编辑后 Host 返回的 Working 身份不一致。' });
243
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("the.working.identity.returned.by.host.after.resuming") }));
241
244
  finish();
242
245
  return;
243
246
  }
@@ -249,7 +252,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
249
252
  || recovery.revision !== nextTarget.revision
250
253
  || recovery.localHeadOid !== preflight.localHeadOid
251
254
  || !sameStrings(recovery.conflictingFiles, preflight.conflictingFiles)) {
252
- setError({ code: 'checkout_mismatch', message: 'Host 未返回精确的冲突恢复凭证。' });
255
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.did.not.return.an.exact.conflict.recovery") }));
253
256
  finish();
254
257
  return;
255
258
  }
@@ -265,7 +268,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
265
268
  localHeadOid: recovery.localHeadOid,
266
269
  conflictingFiles: [...recovery.conflictingFiles],
267
270
  });
268
- setMessage('已安全恢复 Working,冲突解决请求正在等待精确 owner Session 空闲。Local 未修改。');
271
+ setMessage(() => (t) => t("safely.resumed.working.the.conflict.resolution.request.is"));
269
272
  finish();
270
273
  };
271
274
  const startReviewRegeneration = async (preflight) => {
@@ -292,7 +295,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
292
295
  || latest.preflight.checkoutId !== preflight.checkoutId
293
296
  || latest.preflight.reviewId !== preflight.reviewId
294
297
  || latest.preflight.revision !== preflight.revision) {
295
- setMessage(latest.status === 'success' ? preflightMessage(latest.preflight) : '只读复核未完成。');
298
+ setMessage(() => (t) => latest.status === 'success' ? preflightMessage(latest.preflight, t) : t("read.only.recheck.has.not.finished"));
296
299
  finish();
297
300
  return;
298
301
  }
@@ -311,7 +314,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
311
314
  || recovery.checkoutId !== preflight.checkoutId
312
315
  || recovery.reviewId !== preflight.reviewId
313
316
  || recovery.revision !== preflight.revision) {
314
- setError({ code: 'checkout_mismatch', message: 'Host 未返回精确的只读验收再生成凭证。' });
317
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.did.not.return.an.exact.read.only") }));
315
318
  finish();
316
319
  return;
317
320
  }
@@ -323,7 +326,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
323
326
  reviewId: recovery.reviewId,
324
327
  revision: recovery.revision,
325
328
  });
326
- setMessage('只读验收再生成请求正在等待精确 owner Session 空闲;不会恢复 Working 或修改文件。');
329
+ setMessage(() => (t) => t("read.only.review.regeneration.is.waiting.for.the"));
327
330
  finish();
328
331
  };
329
332
  const recoverPreflight = (preflight) => {
@@ -370,7 +373,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
370
373
  finish();
371
374
  return;
372
375
  }
373
- setMessage(preflightMessage(inspected.preflight));
376
+ setMessage(() => (t) => preflightMessage(inspected.preflight, t));
374
377
  if (inspected.preflight.status === 'conflict' || inspected.preflight.status === 'blocked') {
375
378
  finish();
376
379
  return;
@@ -385,7 +388,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
385
388
  return;
386
389
  }
387
390
  applyTarget(outcome.value.target);
388
- setMessage('已同步为可撤回的 Local Preview;请在 Local 中验收。');
391
+ setMessage(() => (t) => t("synced.as.a.reversible.local.preview.review.the"));
389
392
  finish();
390
393
  };
391
394
  const openCheckpoint = () => {
@@ -425,14 +428,14 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
425
428
  || nextTarget.state !== 'working'
426
429
  || nextTarget.review !== undefined
427
430
  || nextTarget.checkpoints?.at(-1)?.checkpointId !== saved.checkpointId) {
428
- setError({ code: 'checkout_mismatch', message: 'Host 返回的 Checkpoint 身份或 Working 状态不一致。' });
431
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.returned.a.mismatched.checkpoint.identity.or.working") }));
429
432
  finish();
430
433
  return;
431
434
  }
432
435
  applyTarget(nextTarget);
433
436
  setCheckpointOpen(false);
434
437
  checkpointRequestId.current = null;
435
- setMessage(`已保存第 ${saved.sequence} 个 Worktree 阶段并继续修改;阶段尚未发布到 Local。`);
438
+ setMessage(() => (t) => t("saved.worktree.stage.and.resumed.editing.the.stage", { p0: saved.sequence }));
436
439
  finish();
437
440
  };
438
441
  const resumeRevision = async () => {
@@ -449,11 +452,11 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
449
452
  }
450
453
  applyTarget(outcome.value.target);
451
454
  const drafted = services
452
- ? prefillSessionDraft(services, identity.sessionId, '请重新检查当前 Worktree 的修改,重新运行必要验证,并重新生成验收稿。')
455
+ ? prefillSessionDraft(services, identity.sessionId, t("please.recheck.the.current.worktree.changes.rerun.the"))
453
456
  : false;
454
- setMessage(drafted
455
- ? '已恢复编辑并预填重新验收请求;Local 未受影响。'
456
- : '已恢复编辑;请重新检查、验证并生成新的验收稿。Local 未受影响。');
457
+ setMessage(() => (t) => drafted
458
+ ? t("resumed.editing.and.prefilled.a.new.review.request")
459
+ : t("resumed.editing.recheck.validate.and.generate.a.new"));
457
460
  finish();
458
461
  };
459
462
  const rollbackPreview = async (resumeRevision = false) => {
@@ -462,7 +465,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
462
465
  let freshProof;
463
466
  if (target?.state === 'preview_detached') {
464
467
  if (!recoveryIdentity) {
465
- setError({ code: 'stale_target', message: 'Detached Preview 身份不完整,请刷新。' });
468
+ setError(() => (t) => ({ code: 'stale_target', message: t("detached.preview.identity.is.incomplete.please.refresh") }));
466
469
  finish();
467
470
  return;
468
471
  }
@@ -476,14 +479,15 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
476
479
  return;
477
480
  }
478
481
  if (inspected.status !== 'success' || inspected.preflight.status !== 'assessed') {
479
- setMessage(inspected.status === 'success' && inspected.preflight.status === 'blocked'
482
+ setMessage(() => (t) => inspected.status === 'success' && inspected.preflight.status === 'blocked'
480
483
  ? inspected.preflight.message
481
- : 'Preview Recovery 预检未完成。');
484
+ : t("preview.recovery.preflight.has.not.finished"));
482
485
  finish();
483
486
  return;
484
487
  }
485
488
  if (inspected.preflight.proof.rollback.status !== 'safe') {
486
- setMessage(inspected.preflight.proof.rollback.message);
489
+ const explanation = inspected.preflight.proof.rollback.message;
490
+ setMessage(() => () => explanation);
487
491
  finish();
488
492
  return;
489
493
  }
@@ -503,9 +507,9 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
503
507
  return;
504
508
  }
505
509
  applyTarget(outcome.value.target);
506
- setMessage(outcome.value.target.state === 'preview_detached'
507
- ? '恢复条件在写入前发生变化;Preview 证据和 Worktree 已保留,请重新检查。'
508
- : resumeRevision ? '已撤回 Local Preview,可以继续修改 Worktree。' : '已撤回 Local Preview,验收卡仍可再次同步。');
510
+ setMessage(() => (t) => outcome.value.target.state === 'preview_detached'
511
+ ? t("recovery.conditions.changed.before.writing.preview.evidence.and")
512
+ : resumeRevision ? t("local.preview.rolled.back.you.can.continue.editing") : t("local.preview.rolled.back.the.review.can.be"));
509
513
  finish();
510
514
  };
511
515
  const submitCommit = async () => {
@@ -526,7 +530,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
526
530
  return;
527
531
  }
528
532
  if (inspected.status !== 'success' || inspected.preflight.status === 'blocked' || inspected.preflight.status === 'conflict') {
529
- setMessage(inspected.status === 'success' ? preflightMessage(inspected.preflight) : '同步预检未完成。');
533
+ setMessage(() => (t) => inspected.status === 'success' ? preflightMessage(inspected.preflight, t) : t("sync.preflight.has.not.finished"));
530
534
  finish();
531
535
  return;
532
536
  }
@@ -534,7 +538,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
534
538
  let previewProof;
535
539
  if (mode === 'finalize_preview' && target?.state === 'preview_detached') {
536
540
  if (!recoveryIdentity) {
537
- setError({ code: 'stale_target', message: 'Detached Preview 身份不完整,请刷新。' });
541
+ setError(() => (t) => ({ code: 'stale_target', message: t("detached.preview.identity.is.incomplete.please.refresh") }));
538
542
  finish();
539
543
  return;
540
544
  }
@@ -548,14 +552,15 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
548
552
  return;
549
553
  }
550
554
  if (inspected.status !== 'success' || inspected.preflight.status !== 'assessed') {
551
- setMessage(inspected.status === 'success' && inspected.preflight.status === 'blocked'
555
+ setMessage(() => (t) => inspected.status === 'success' && inspected.preflight.status === 'blocked'
552
556
  ? inspected.preflight.message
553
- : 'Preview Recovery 预检未完成。');
557
+ : t("preview.recovery.preflight.has.not.finished"));
554
558
  finish();
555
559
  return;
556
560
  }
557
561
  if (inspected.preflight.proof.finalize.status !== 'safe') {
558
- setMessage(inspected.preflight.proof.finalize.message);
562
+ const explanation = inspected.preflight.proof.finalize.message;
563
+ setMessage(() => () => explanation);
559
564
  finish();
560
565
  return;
561
566
  }
@@ -574,10 +579,10 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
574
579
  }
575
580
  applyTarget(outcome.value.target);
576
581
  if (outcome.value.target.state === 'preview_detached') {
577
- setMessage('Local 已变化,无法可靠提交;Preview 恢复证据和 Worktree 已保留。');
582
+ setMessage(() => (t) => t("local.changed.a.reliable.commit.is.not.possible"));
578
583
  }
579
584
  else {
580
- setMessage(selectedRetention === 'cleanup' ? '已提交到 Local,并开始清理 Worktree。' : '已提交到 Local,并保留当前运行环境。');
585
+ setMessage(() => (t) => selectedRetention === 'cleanup' ? t("committed.to.local.and.started.worktree.cleanup") : t("committed.to.local.and.retained.the.current.environment"));
581
586
  }
582
587
  setCommitMode(null);
583
588
  finish();
@@ -601,9 +606,9 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
601
606
  return;
602
607
  }
603
608
  applyTarget(outcome.value.target);
604
- setMessage(outcome.value.target.state === 'preview_detached'
605
- ? 'Local 已变化,无法无损撤回;未删除 Worktree。'
606
- : '已放弃本轮 Worktree 修改,Local 未受影响。');
609
+ setMessage(() => (t) => outcome.value.target.state === 'preview_detached'
610
+ ? t("local.changed.lossless.rollback.is.not.possible.the")
611
+ : t("discarded.this.iteration.s.worktree.changes.local.is"));
607
612
  setDiscardOpen(false);
608
613
  finish();
609
614
  };
@@ -618,9 +623,9 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
618
623
  return null;
619
624
  }
620
625
  if (inspected.status !== 'success' || inspected.preflight.status !== 'assessed') {
621
- setMessage(inspected.status === 'success' && inspected.preflight.status === 'blocked'
626
+ setMessage(() => (t) => inspected.status === 'success' && inspected.preflight.status === 'blocked'
622
627
  ? inspected.preflight.message
623
- : 'Preview Recovery 预检未完成。');
628
+ : t("preview.recovery.preflight.has.not.finished"));
624
629
  return null;
625
630
  }
626
631
  return inspected.preflight.proof;
@@ -649,7 +654,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
649
654
  || continuation.previewId !== recoveryIdentity.expectedPreviewId
650
655
  || continuation.revision !== identity.expectedRevision
651
656
  || continuation.generation !== proof.generation) {
652
- setError({ code: 'checkout_mismatch', message: 'Host 未返回精确的 detached Recovery 分析凭证。' });
657
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.did.not.return.an.exact.detached.recovery") }));
653
658
  finish();
654
659
  return;
655
660
  }
@@ -662,23 +667,23 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
662
667
  if (!verified.ok || verified.value.target.recoveryContinuation?.kind !== continuation.kind
663
668
  || verified.value.target.recoveryContinuation.requestId !== continuation.requestId
664
669
  || verified.value.target.recoveryContinuation.generation !== continuation.generation) {
665
- throw new Error('二次 Host 检查未确认 detached Recovery 分析凭证。');
670
+ throw new Error(t("the.second.host.inspection.did.not.confirm.the"));
666
671
  }
667
672
  const binding = services.sessions.binding(identity.sessionId);
668
673
  const prompt = binding?.session.prompt;
669
674
  if (!binding || !prompt)
670
- throw new Error('Owner Session 尚未提供 Harness prompt API。');
675
+ throw new Error(t("the.owner.session.has.not.provided.the.harness"));
671
676
  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、仍缺失的任务增量与最安全的人工下一步。',
677
+ t("analyze.detached.preview.recovery.in.read.only.mode", { p0: identity.checkoutId, p1: identity.expectedReviewId, p2: recoveryIdentity.expectedPreviewId, p3: proof.generation }),
678
+ t("do.not.modify.the.old.managed.worktree.local"),
679
+ t("explain.the.rollback.finalize.blockers.missing.task.changes"),
675
680
  ].join('\n') }], 'queue');
676
681
  if (!result.ok)
677
682
  throw new Error(`${result.error.code}: ${result.error.message}`);
678
- setMessage('已向精确 owner Session 发送只读 Recovery 分析请求。');
683
+ setMessage(() => (t) => t("sent.a.read.only.recovery.analysis.request.to"));
679
684
  }
680
685
  catch (reason) {
681
- setError({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) });
686
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) }));
682
687
  }
683
688
  finish();
684
689
  };
@@ -708,7 +713,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
708
713
  || continuation.generation !== proof.generation
709
714
  || continuation.checkoutId !== created.value.target.checkoutId
710
715
  || continuation.checkoutId === identity.checkoutId) {
711
- setError({ code: 'checkout_mismatch', message: 'Host 返回的 Recovery handoff 身份不一致。' });
716
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: t("host.returned.a.mismatched.recovery.handoff.identity") }));
712
717
  finish();
713
718
  return;
714
719
  }
@@ -724,23 +729,23 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
724
729
  if (!verified.ok || verified.value.target.managedRoot !== created.value.managedRoot
725
730
  || verified.value.target.recoveryContinuation?.kind !== continuation.kind
726
731
  || verified.value.target.recoveryContinuation.requestId !== continuation.requestId) {
727
- throw new Error('新 Worktree 的二次 Host/cwd 检查未通过。');
732
+ throw new Error(t("the.second.host.cwd.check.of.the.new"));
728
733
  }
729
734
  const binding = services.sessions.binding(created.value.targetSessionId);
730
735
  const prompt = binding?.session.prompt;
731
736
  if (!binding || !prompt)
732
- throw new Error('新 owner Session 尚未提供 Harness prompt API。');
737
+ throw new Error(t("the.new.owner.session.has.not.provided.the"));
733
738
  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。',
739
+ t("this.is.a.detached.preview.recovery.handoff.the", { p0: identity.checkoutId, p1: identity.expectedReviewId, p2: recoveryIdentity.expectedPreviewId, p3: proof.generation }),
740
+ t("the.new.worktree.is.based.on.the.latest"),
741
+ t("run.the.necessary.validation.and.generate.a.new"),
737
742
  ].join('\n') }], 'queue');
738
743
  if (!result.ok)
739
744
  throw new Error(`${result.error.code}: ${result.error.message}`);
740
- setMessage('已创建并打开基于最新 Local HEAD 的 fresh Worktree,Recovery handoff 请求已发送。');
745
+ setMessage(() => (t) => t("created.and.opened.a.fresh.worktree.based.on"));
741
746
  }
742
747
  catch (reason) {
743
- setError({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) });
748
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) }));
744
749
  }
745
750
  finish();
746
751
  };
@@ -761,7 +766,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
761
766
  return;
762
767
  }
763
768
  applyTarget(outcome.value.target);
764
- setMessage(outcome.value.target.state === 'delivered' ? 'Worktree 环境已清理。' : '清理仍未完成,已保留恢复信息。');
769
+ setMessage(() => (t) => outcome.value.target.state === 'delivered' ? t("worktree.environment.cleaned.up") : t("cleanup.is.still.incomplete.recovery.information.was.retained"));
765
770
  finish();
766
771
  };
767
772
  const openHolder = async () => {
@@ -779,7 +784,7 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
779
784
  await openAuthorizedWorktreeTarget(adapter, services, identity.sessionId, holder, isActive);
780
785
  }
781
786
  catch (reason) {
782
- setError({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) });
787
+ setError(() => (t) => ({ code: 'checkout_mismatch', message: reason instanceof Error ? reason.message : String(reason) }));
783
788
  }
784
789
  finally {
785
790
  finish();
@@ -813,50 +818,50 @@ export function ReviewActions({ review, adapter, services, identity, target, dis
813
818
  setDiscardOpen(false);
814
819
  };
815
820
  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
- ? '同步中…'
821
+ ? t("syncing")
817
822
  : 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
+ ? t("checking")
824
+ : 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: [t("confirm.and.save"), " "] })) : previewRecovery ? (rollbackRecoverySafe ? (_jsx("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || !target?.capabilities.rollbackPreview, onClick: () => { void rollbackPreview(true); }, children: submitting === 'rollback' ? t("processing") : t("recover.and.roll.back.preview") })) : (_jsx("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || target?.state !== 'preview_detached', onClick: () => { void refreshRecoveryPreflight(); }, children: recoveryPreflight.status === 'loading' ? t("checking") : t("check.again") }))) : cleanupPending ? (_jsx("button", { type: "button", className: "dsh-wt-button", disabled: allDisabled || !target?.capabilities.retryCleanup, onClick: () => { void retryCleanup(); }, children: submitting === 'retry_cleanup' ? t("cleaning.up") : t("retry.environment.cleanup") })) : null;
825
+ return (_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'
826
+ ? t("this.iteration.was.committed.the.environment.is.temporarily", { p0: target.commitOid ? ` · ${target.commitOid.slice(0, 8)}` : '' })
827
+ : 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: t("symbol") }), _jsxs("div", { className: "dsh-wt-more-content", role: "menu", children: [focusReview ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", onClick: () => {
823
828
  focusReview();
824
829
  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: () => {
830
+ }, children: t("view.review") })) : null, ready ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.checkpoint || !target.checkpointGeneration, onClick: () => {
826
831
  openCheckpoint();
827
832
  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: () => {
833
+ }, children: t("save.stage.and.continue") }), _jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.resumeRevision, onClick: () => {
829
834
  void resumeRevision();
830
835
  closeMoreMenu();
831
- }, children: submitting === 'resume_revision' ? '恢复中…' : '继续修改' }), _jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalize || !safeReadyPreflight, onClick: () => {
836
+ }, children: submitting === 'resume_revision' ? t("recovering") : t("continue.editing") }), _jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalize || !safeReadyPreflight, onClick: () => {
832
837
  setCommitMode('finish');
833
838
  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: () => {
839
+ }, children: t("skip.preview.and.save") })] })) : null, previewActive && target.capabilities.checkpoint && target.checkpointGeneration ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled, onClick: () => {
835
840
  openCheckpoint();
836
841
  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: () => {
842
+ }, children: t("save.stage.and.continue") })) : null, previewActive || rollbackRecoverySafe ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.rollbackPreview, onClick: () => {
838
843
  void rollbackPreview(true);
839
844
  closeMoreMenu();
840
- }, children: previewActive ? '撤回本次预览' : '重新尝试撤回' })) : null, finalizeRecoverySafe ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalizePreview, onClick: () => {
845
+ }, children: previewActive ? t("roll.back.this.preview") : t("retry.rollback") })) : null, finalizeRecoverySafe ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item", disabled: allDisabled || !target.capabilities.finalizePreview, onClick: () => {
841
846
  setCommitMode('finalize_preview');
842
847
  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: () => {
848
+ }, children: t("save.changes") })) : null, canDiscard ? (_jsx("button", { type: "button", role: "menuitem", className: "dsh-wt-more-item dsh-wt-danger-text", disabled: allDisabled, onClick: () => {
844
849
  setDiscardOpen(true);
845
850
  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'
851
+ }, children: 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
852
+ ? t("first.safely.roll.back.the.preview.then.save")
853
+ : 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") }), _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' ? 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'
854
+ ? t("confirm.and.save.these.changes")
855
+ : target?.state === 'preview_detached' ? t("save.these.changes") : t("skip.preview.and.save.directly"), closeLabel: t("close.save.confirmation"), description: commitMode === 'finalize_preview'
856
+ ? t("only.this.iteration.s.task.changes.in.the")
857
+ : 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") }), _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'
858
+ ? t("saving")
859
+ : 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
860
+ ? t("first.safely.roll.back.this.local.preview.then")
861
+ : 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") }), _jsx("button", { type: "button", className: "dsh-wt-button dsh-wt-danger", disabled: submitting !== null, onClick: () => { void discard(); }, children: 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: [t("check.again"), " "] })] }), _jsx("p", { children: t("detached.is.a.delivery.recovery.state.not.git") }), 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: [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: [t("ask.agent.for.read.only.analysis"), " "] }), _jsxs("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null || !services, onClick: () => { void handoffRecovery(); }, children: [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: [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'
857
862
  ? 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] }));
863
+ ? t("agent.will.resolve.the.conflicts.and.must.generate")
864
+ : t("agent.will.regenerate.the.review.in.read.only")
865
+ : 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] }), _jsx("button", { type: "button", className: "dsh-wt-inline-action", disabled: submitting !== null, onClick: () => retryWorktreeRecovery(activeRecovery.request.sessionId), children: 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 ? 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
866
  }
862
867
  //# sourceMappingURL=ReviewActions.js.map