fix(worktrees): protect user changes across ambiguous move failures

Post-merge hardening of the session-to-worktree move (#2998), driven by
review findings on the follow-up pass:

- an ambiguous transport failure (relay abort, timeout) on the
  change-carrying move no longer force-deletes the fresh worktree that
  may hold the user's only copy of their changes; both intent kinds
  surface honest guidance and refresh both directories
- assertSdkSuccess re-tags ambiguous transport errors when wrapping SDK
  failures, so ambiguity classification survives the wrapper on every
  path, matching the prompt-send precedent
- session liveness checks scan all child stores plus the global status
  index, and report unknown (not idle) when no store covers the session
  — an evicted background directory can no longer make a busy session
  look movable
- incomplete-rollback errors carry the changes-may-be-in-destination
  guidance instead of swallowing it
- move-message assembly shared across the three call sites; tests now
  exercise the real ambiguity classifier (extracted to
  send-failure-classification.ts) instead of a hand-mirrored mock
- i18n fallout from the merge train: Turkish gains the 21 worktree-move
  keys, all 12 locales get the hedged ambiguous-failure toast; owning
  DOCUMENTATION.md files record the new contracts
This commit is contained in:
Bohdan Triapitsyn
2026-08-28 12:03:55 +03:00
parent 9d279137ce
commit 4f53db17e6
21 changed files with 493 additions and 107 deletions
+22
View File
@@ -524,6 +524,28 @@ export const dict = {
'sessions.sidebar.session.moveToWorktree.tooltip': 'Geçerli branch\'ten yeni bir worktree oluşturur, commit edilmemiş değişiklikleri aktarır ve bu session\'ı alt session\'larıyla birlikte oraya taşır.',
'sessions.sidebar.session.moveToWorktree.tooltipBusy': 'Session boşta olduğunda kullanılabilir. Geçerli etkinliği durdur veya bitmesini bekle.',
'sessions.sidebar.session.moveToWorktree.tooltipMoving': 'Bu session zaten yeni bir worktree\'ye taşınıyor.',
'sessions.sidebar.session.menu.moveToWorktreeTargets': 'Worktree\'ye taşı',
'sessions.sidebar.session.menu.newWorktree': 'Yeni worktree...',
'sessions.sidebar.session.moveToWorktree.main': 'Ana worktree',
'sessions.sidebar.session.moveToWorktree.refreshing': 'Worktree\'ler yenileniyor...',
'sessions.sidebar.session.moveToWorktree.loadFailed': 'Worktree\'ler yüklenemedi',
'sessions.sidebar.session.moveToWorktree.current': 'Geçerli worktree',
'sessions.sidebar.session.moveToWorktree.existingSuccess': 'Session worktree\'ye taşındı',
'sessions.sidebar.session.moveToWorktree.existingFailed': 'Session worktree\'ye taşınamadı',
'sessions.sidebar.session.moveToWorktree.tooltipTargets': 'Mevcut worktree\'leri ve bu session için yeni bir tane oluşturma seçeneğini gösterir.',
'sessions.sidebar.session.moveToWorktree.confirm.title': 'Kaynakta commit edilmemiş değişiklikler var',
'sessions.sidebar.session.moveToWorktree.confirm.changedFiles': 'Bu worktree\'de değişen dosya sayısı: {count}.',
'sessions.sidebar.session.moveToWorktree.confirm.ownership': 'OpenCode bu değişiklikleri session\'a göre değil, dizine göre izler.',
'sessions.sidebar.session.moveToWorktree.confirm.sessionOnlyHelp': 'Bu session\'ı ve alt session\'larını taşır, kaynaktaki dosyalara hiç dokunmaz.',
'sessions.sidebar.session.moveToWorktree.confirm.allChangesHelp': 'Session dizinindeki değişiklikleri aktarır. Stage\'lenmemiş ve takip edilmeyen dosyalar başarıdan sonra kaynaktan çıkar.',
'sessions.sidebar.session.moveToWorktree.confirm.stagedWarning': 'Stage\'lenmiş değişiklikler kaynakta kalır ve hedefe kopyalanır.',
'sessions.sidebar.session.moveToWorktree.confirm.baseWarning': 'Hedef farklı bir Git tabanı kullanıyorsa aktarım başarısız olabilir.',
'sessions.sidebar.session.moveToWorktree.confirm.sessionOnly': 'Yalnızca session\'ı taşı',
'sessions.sidebar.session.moveToWorktree.confirm.allChanges': 'Kaynaktaki tüm değişiklikleri taşı',
'sessions.sidebar.session.moveToWorktree.confirm.cancel': 'İptal',
'sessions.sidebar.session.moveToWorktree.sourceVerificationFailed': 'Kaynaktaki değişiklikler doğrulanamadı. Hiçbir worktree veya session değiştirilmedi.',
'sessions.sidebar.session.moveToWorktree.applyChangesFailed': 'Hedef, kaynaktaki değişiklikleri kabul edemedi. Session da kaynaktaki değişiklikler de taşınmadı. Tekrar deneyip Yalnızca session\'ı taşı seçeneğini kullan.',
'sessions.sidebar.session.moveToWorktree.changesMayBeInDestination': 'Hedef taşımayı onaylamadan önce bağlantı koptu. Session taşınmamış olabilir ve commit edilmemiş değişikliklerin hedef worktree içinde olabilir. Tekrar denemeden önce oraya bak.',
'sessions.sidebar.session.menu.runFusion': 'Fusion\'ı çalıştır',
'sessions.sidebar.session.menu.openInSidePanel': 'Yan panelde aç',
'sessions.sidebar.session.actions.openInEditor': 'Editörde aç',