improve delete worktree failure diagnostics (#302)
## Summary - move delete-worktree failures out of transient toast-only UX and keep them inline in the delete modal - add parsed diagnostics for common failure modes, including a short summary, likely cause, and suggested next step - make the raw error easier to review and share with raw and sanitized copy actions Closes #301. ## BEFORE: <img width="1127" height="860" alt="image" src="https://github.com/user-attachments/assets/dd09ba1e-be8c-450c-a1dd-f1cde2a48802" /> ## AFTER: <img width="1384" height="835" alt="image" src="https://github.com/user-attachments/assets/6b0d1459-21fa-4264-9e54-45540f584538" /> ## Problem Before this change, delete-worktree failures were difficult to work with: 1. The failure message was effectively raw backend or git output. 2. Users had to infer the meaning of the error themselves. 3. The UI did not explain what likely went wrong or what to do next. 4. Sharing the error for debugging was awkward when it included machine-local absolute paths. 5. The confirmation modal was not being used as the primary diagnostic surface for a destructive action that frequently fails for understandable reasons. This was especially frustrating for common cases such as: - modified or untracked files in the worktree - a process still using the worktree directory - permission errors on Windows - missing worktree directories or stale worktree records ## What changed ### Modal failure UX - keep delete failures inline inside `packages/ui/src/components/worktree-selector.tsx` - clear modal-local error state when opening or closing the dialog - keep the success toast on successful deletion, but use the modal itself for failure presentation ### Human-readable diagnostics - parse JSON-shaped backend error payloads such as `{"error":"..."}` before classification - classify common delete failure patterns into: - `localChanges` - `inUse` - `notFound` - `permissionDenied` - `unknown` - render three user-facing lines above the raw error: - summary - likely cause - suggested next step ### Copy flows - add `Copy error` for the original failure text - add `Copy sanitized` to redact common absolute path and username patterns before copying ### Modal content and sizing - present the target worktree in a simpler two-line summary block - update the delete description text to plain English: `Deletes this branch worktree and its local folder.` - size the delete modal deliberately for desktop use while allowing vertical expansion to the viewport limit before scrolling ### i18n coverage - add the new delete diagnostic strings across all currently supported locales touched by this area: - `en` - `es` - `fr` - `he` - `ja` - `ru` - `zh-Hans` ## Why this approach - It keeps the backend contract unchanged and solves the UX problem where it occurs. - It preserves access to the raw failure text instead of hiding implementation detail entirely. - It gives users immediate guidance without forcing them to translate git errors into next actions. - It improves bug reporting without requiring a separate logging or export workflow. ## Not included - server-side preflight guards that block delete when the worktree is still assigned or in use - process-aware worktree locking detection - automatic retry or force-delete-and-retry flows Those are useful follow-ups, but this PR is intentionally scoped to failure presentation and debuggability. ## Files changed - `packages/ui/src/components/worktree-selector.tsx` - `packages/ui/src/lib/i18n/messages/en/instance.ts` - `packages/ui/src/lib/i18n/messages/es/instance.ts` - `packages/ui/src/lib/i18n/messages/fr/instance.ts` - `packages/ui/src/lib/i18n/messages/he/instance.ts` - `packages/ui/src/lib/i18n/messages/ja/instance.ts` - `packages/ui/src/lib/i18n/messages/ru/instance.ts` - `packages/ui/src/lib/i18n/messages/zh-Hans/instance.ts` ## Validation - `npm run typecheck --workspace @codenomad/ui` - `npm run build --workspace @codenomad/ui` - `npm run typecheck --workspace @neuralnomads/codenomad-electron-app` ## Notes for reviewers - The error classifier is intentionally heuristic and string-based. It is meant to improve the common cases without increasing backend coupling. - The sanitized copy flow is conservative and focused on path and username redaction, not full structured log scrubbing. --------- Co-authored-by: Shantur Rathore <i@shantur.com>
This commit is contained in:
@@ -166,6 +166,30 @@ export const instanceMessages = {
|
||||
"instanceShell.backgroundProcesses.actions.output": "输出",
|
||||
"instanceShell.backgroundProcesses.actions.stop": "停止",
|
||||
"instanceShell.backgroundProcesses.actions.terminate": "终止",
|
||||
"instanceShell.worktree.delete.error.title": "删除失败",
|
||||
"instanceShell.worktree.delete.error.fallback": "删除 worktree 失败",
|
||||
"instanceShell.worktree.delete.error.causeLabel": "可能原因:",
|
||||
"instanceShell.worktree.delete.error.nextStepLabel": "建议的下一步:",
|
||||
"instanceShell.worktree.delete.error.summary.localChanges": "Git 拒绝删除这个 worktree,因为其中包含已修改或未跟踪的文件。",
|
||||
"instanceShell.worktree.delete.error.summary.inUse": "CodeNomad 无法删除这个 worktree,因为目录中的文件仍在被某些进程使用。",
|
||||
"instanceShell.worktree.delete.error.summary.notFound": "CodeNomad 无法删除这个 worktree,因为目录或 worktree 记录未找到。",
|
||||
"instanceShell.worktree.delete.error.summary.permissionDenied": "CodeNomad 无法删除这个 worktree,因为目录访问被拒绝。",
|
||||
"instanceShell.worktree.delete.error.summary.unknown": "CodeNomad 无法删除这个 worktree。",
|
||||
"instanceShell.worktree.delete.error.cause.localChanges": "本地更改",
|
||||
"instanceShell.worktree.delete.error.cause.inUse": "另一个进程正在使用这个 worktree",
|
||||
"instanceShell.worktree.delete.error.cause.notFound": "worktree 目录或记录缺失",
|
||||
"instanceShell.worktree.delete.error.cause.permissionDenied": "文件系统权限不足",
|
||||
"instanceShell.worktree.delete.error.cause.unknown": "后端返回了未分类的删除错误",
|
||||
"instanceShell.worktree.delete.error.nextStep.localChanges": "如果你想丢弃本地更改,请启用强制删除,或者先清理 worktree 后再重试。",
|
||||
"instanceShell.worktree.delete.error.nextStep.inUse": "关闭正在使用这个 worktree 的终端、编辑器、watcher 或后台进程,然后再试一次。",
|
||||
"instanceShell.worktree.delete.error.nextStep.notFound": "刷新 worktree 列表后再试一次。如果仍然失败,请检查磁盘上的 worktree 路径。",
|
||||
"instanceShell.worktree.delete.error.nextStep.permissionDenied": "检查文件系统权限,并关闭可能锁定此目录的应用程序,然后再试一次。",
|
||||
"instanceShell.worktree.delete.error.nextStep.unknown": "查看下方原始错误详情,并在处理提示的问题后再次重试。",
|
||||
"instanceShell.worktree.delete.error.copyRaw": "复制错误",
|
||||
"instanceShell.worktree.delete.error.copySanitized": "复制脱敏内容",
|
||||
"instanceShell.worktree.delete.error.copySuccess": "已复制删除错误",
|
||||
"instanceShell.worktree.delete.error.copySanitizedSuccess": "已复制脱敏后的删除错误",
|
||||
"instanceShell.worktree.delete.error.copyFailure": "复制删除错误失败",
|
||||
|
||||
"versionPill.appWithVersion": "应用 {version}",
|
||||
"versionPill.ui": "UI",
|
||||
|
||||
Reference in New Issue
Block a user