@cerbur/clutch-dsh-worktree 0.1.4 → 0.1.6

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 (115) hide show
  1. package/README.md +89 -24
  2. package/README.zh.md +81 -23
  3. package/lib/client/WorktreeContext.d.ts.map +1 -1
  4. package/lib/client/WorktreeContext.js.map +1 -1
  5. package/lib/client/WorktreeHeroContext.d.ts +1 -1
  6. package/lib/client/WorktreeHeroContext.d.ts.map +1 -1
  7. package/lib/client/WorktreeHeroContext.js +10 -5
  8. package/lib/client/WorktreeHeroContext.js.map +1 -1
  9. package/lib/client/WorktreeSurface.d.ts +1 -1
  10. package/lib/client/WorktreeSurface.d.ts.map +1 -1
  11. package/lib/client/WorktreeSurface.js +349 -88
  12. package/lib/client/WorktreeSurface.js.map +1 -1
  13. package/lib/client/entry.d.ts.map +1 -1
  14. package/lib/client/entry.js +3 -0
  15. package/lib/client/entry.js.map +1 -1
  16. package/lib/client/locales.d.ts +28 -0
  17. package/lib/client/locales.d.ts.map +1 -1
  18. package/lib/client/locales.js +30 -2
  19. package/lib/client/locales.js.map +1 -1
  20. package/lib/client/virtual-workspace-membership.js +1 -1
  21. package/lib/client/virtual-workspace-membership.js.map +1 -1
  22. package/lib/client/worktree-connection.d.ts +2 -0
  23. package/lib/client/worktree-connection.d.ts.map +1 -1
  24. package/lib/client/worktree-connection.js +4 -0
  25. package/lib/client/worktree-connection.js.map +1 -1
  26. package/lib/client/worktree-context-store.d.ts.map +1 -1
  27. package/lib/client/worktree-context-store.js +51 -11
  28. package/lib/client/worktree-context-store.js.map +1 -1
  29. package/lib/client/worktree-error-copy.d.ts.map +1 -1
  30. package/lib/client/worktree-error-copy.js +8 -0
  31. package/lib/client/worktree-error-copy.js.map +1 -1
  32. package/lib/client/worktree-expand-state.d.ts +33 -0
  33. package/lib/client/worktree-expand-state.d.ts.map +1 -0
  34. package/lib/client/worktree-expand-state.js +83 -0
  35. package/lib/client/worktree-expand-state.js.map +1 -0
  36. package/lib/client/worktree-session-position.d.ts +2 -0
  37. package/lib/client/worktree-session-position.d.ts.map +1 -0
  38. package/lib/client/worktree-session-position.js +11 -0
  39. package/lib/client/worktree-session-position.js.map +1 -0
  40. package/lib/client/worktree-surface-dialogs.d.ts +1 -1
  41. package/lib/client/worktree-surface-dialogs.d.ts.map +1 -1
  42. package/lib/client/worktree-surface-dialogs.js +33 -13
  43. package/lib/client/worktree-surface-dialogs.js.map +1 -1
  44. package/lib/client/worktree-surface-rows.d.ts +2 -2
  45. package/lib/client/worktree-surface-rows.d.ts.map +1 -1
  46. package/lib/client/worktree-surface-rows.js +5 -5
  47. package/lib/client/worktree-surface-rows.js.map +1 -1
  48. package/lib/client/worktree-surface-selectors.d.ts +16 -0
  49. package/lib/client/worktree-surface-selectors.d.ts.map +1 -1
  50. package/lib/client/worktree-surface-selectors.js +54 -0
  51. package/lib/client/worktree-surface-selectors.js.map +1 -1
  52. package/lib/client/worktree-surface-types.d.ts +28 -1
  53. package/lib/client/worktree-surface-types.d.ts.map +1 -1
  54. package/lib/client/worktree-view-actions.d.ts +3 -0
  55. package/lib/client/worktree-view-actions.d.ts.map +1 -1
  56. package/lib/client/worktree-view-actions.js +3 -0
  57. package/lib/client/worktree-view-actions.js.map +1 -1
  58. package/lib/client/worktree-view-read.d.ts +11 -0
  59. package/lib/client/worktree-view-read.d.ts.map +1 -1
  60. package/lib/client/worktree-view-read.js +24 -0
  61. package/lib/client/worktree-view-read.js.map +1 -1
  62. package/lib/client.js +697 -137
  63. package/lib/client.js.map +1 -1
  64. package/lib/contract/index.contract.js +14 -0
  65. package/lib/contract/index.contract.js.map +1 -1
  66. package/lib/contract/index.d.ts +22 -2
  67. package/lib/contract/index.d.ts.map +1 -1
  68. package/lib/contract/index.js +5 -0
  69. package/lib/contract/index.js.map +1 -1
  70. package/lib/host/remote.d.ts.map +1 -1
  71. package/lib/host/remote.js +2 -0
  72. package/lib/host/remote.js.map +1 -1
  73. package/lib/host/service.d.ts +8 -1
  74. package/lib/host/service.d.ts.map +1 -1
  75. package/lib/host/service.js +12 -0
  76. package/lib/host/service.js.map +1 -1
  77. package/lib/index.d.ts +1 -1
  78. package/lib/index.d.ts.map +1 -1
  79. package/lib/index.js.map +1 -1
  80. package/lib/manage/manager-support.d.ts +2 -0
  81. package/lib/manage/manager-support.d.ts.map +1 -1
  82. package/lib/manage/manager-support.js +9 -0
  83. package/lib/manage/manager-support.js.map +1 -1
  84. package/lib/manage/manager-worktrees.d.ts +10 -1
  85. package/lib/manage/manager-worktrees.d.ts.map +1 -1
  86. package/lib/manage/manager-worktrees.js +121 -5
  87. package/lib/manage/manager-worktrees.js.map +1 -1
  88. package/lib/manage/manager.d.ts +8 -1
  89. package/lib/manage/manager.d.ts.map +1 -1
  90. package/lib/manage/manager.js +7 -1
  91. package/lib/manage/manager.js.map +1 -1
  92. package/lib/provider/git.d.ts +8 -0
  93. package/lib/provider/git.d.ts.map +1 -1
  94. package/lib/provider/git.js +57 -11
  95. package/lib/provider/git.js.map +1 -1
  96. package/lib/provider/index.d.ts +1 -1
  97. package/lib/provider/index.d.ts.map +1 -1
  98. package/lib/provider/index.js +1 -1
  99. package/lib/provider/index.js.map +1 -1
  100. package/lib/provider/sidecar-schema.d.ts +1 -1
  101. package/lib/provider/sidecar-schema.d.ts.map +1 -1
  102. package/lib/provider/sidecar-schema.js +33 -37
  103. package/lib/provider/sidecar-schema.js.map +1 -1
  104. package/lib/provider/sidecar.d.ts.map +1 -1
  105. package/lib/provider/sidecar.js +3 -1
  106. package/lib/provider/sidecar.js.map +1 -1
  107. package/lib/provider/types.d.ts +9 -1
  108. package/lib/provider/types.d.ts.map +1 -1
  109. package/lib/provider/types.js +2 -1
  110. package/lib/provider/types.js.map +1 -1
  111. package/lib/typert.host.js +115 -21
  112. package/lib/typert.remote-client.d.ts +5 -1
  113. package/lib/typert.remote-client.d.ts.map +1 -1
  114. package/lib/typert.remote-client.js +115 -21
  115. package/package.json +30 -30
package/lib/client.js CHANGED
@@ -42,19 +42,29 @@ window.__ModuleLoader__.load({
42
42
  "worktree.options": "Worktree 选项:{name}",
43
43
  "worktree.remove": "移除 Worktree",
44
44
  "worktree.removeDescription": "移除“{name}”?Session 会保留在 DSH 中,并作为已分离关系继续可用。",
45
+ "worktree.removeExternalDescription": "移除“{name}”?这会删除关联的外部 Worktree 目录。Session 会保留在 DSH 中,并作为已分离关系继续可用。",
45
46
  "worktree.addSession": "向 {name} 添加会话",
46
47
  "worktree.noWorktrees": "暂无 Worktree",
47
48
  "worktree.createTitle": "新建 Worktree",
48
49
  "worktree.createDescription": "“{name}” · Worktree 路径由 DSH 管理。",
50
+ "worktree.tabCreate": "创建",
51
+ "worktree.tabImport": "导入",
52
+ "worktree.importDescription": "向“{name}”注册已有的 Worktree。注册不会移动目录;之后移除会删除关联的 Worktree 目录。",
53
+ "worktree.importLoading": "正在查找可导入的 Worktree…",
54
+ "worktree.importEmpty": "没有可导入的 Worktree。",
55
+ "worktree.importPlaceholder": "请选择要导入的 Worktree",
56
+ "worktree.importSelected": "已选择",
49
57
  "worktree.baseBranch": "Worktree 基线分支",
50
58
  "worktree.noLocalBranch": "没有本地分支",
51
59
  "worktree.noBranches": "此工作区中没有找到本地分支。",
60
+ "worktree.setup.gitNotInstalled": "Git 未安装或不在 PATH 中。请先安装 Git,然后重启 DSH 再重试。",
52
61
  "worktree.setup.noRepository": "此 Workspace 不是 Git 仓库。请在 Workspace 目录执行以下命令:",
53
62
  "worktree.setup.noInitialCommit": "此 Git 仓库还没有首次 commit。请先执行以下命令:",
54
63
  "worktree.setup.noLocalBranch": "此 Git 仓库没有本地分支。请先创建一个本地分支:",
55
64
  "worktree.setup.commands": "可复制的命令",
56
65
  "worktree.name": "Worktree 名称",
57
66
  "worktree.create": "创建 Worktree",
67
+ "worktree.import": "导入 Worktree",
58
68
  "session.options": "会话选项:{name}",
59
69
  "session.new": "新会话",
60
70
  "session.rename": "重命名会话",
@@ -76,6 +86,7 @@ window.__ModuleLoader__.load({
76
86
  "action.openCreatedSession": "打开已创建的 Session",
77
87
  "status.loading": "正在加载工作区…",
78
88
  "error.worktreeDataUnavailable": "Worktree 数据不可用,请重试。",
89
+ "error.gitNotInstalled": "Git 未安装或不可用,请安装 Git 后重试。",
79
90
  "error.connectionDisposed": "Worktree 连接已释放,请重新加载插件后重试。",
80
91
  "error.connectionFailed": "Worktree endpoint {endpoint} 调用失败;连接错误,可重试:{reason}",
81
92
  "error.invalidResult": "Worktree endpoint {endpoint} 返回了无效结果,请重试请求。",
@@ -84,7 +95,10 @@ window.__ModuleLoader__.load({
84
95
  "error.worktreeOrderingUnavailable": "Worktree 排序不可用,请重新连接后重试。",
85
96
  "error.worktreeCreatedSessionUnavailable": "Worktree 已创建,但 Session 创建不可用,请重新连接后重试。",
86
97
  "error.sessionCreationUnavailable": "Session 创建不可用,请重新连接后重试。",
87
- "error.worktreeRecordMissing": "Worktree 创建未返回 Worktree 记录,请重试请求。",
98
+ "error.worktreeRecordMissing": "Worktree 注册未返回 Worktree 记录,请重试请求。",
99
+ "error.worktreeImportInvalid": "这个 Worktree 无法导入,请选择同一 Workspace 中有效的绝对路径。",
100
+ "error.worktreeAlreadyManaged": "这个 Worktree 已由插件管理。",
101
+ "error.worktreeRegistrationSessionUnavailable": "Worktree 已注册,但 Session 创建不可用,请重新连接后重试。",
88
102
  "error.workspaceRenameUnavailable": "工作区重命名不可用,请重新连接后重试。",
89
103
  "error.workspaceDeleteUnavailable": "工作区删除不可用,请重新连接后重试。",
90
104
  "error.sessionRenameUnavailable": "会话重命名不可用,请重新连接后重试。",
@@ -130,19 +144,29 @@ window.__ModuleLoader__.load({
130
144
  "worktree.options": "Worktree options for {name}",
131
145
  "worktree.remove": "Remove Worktree",
132
146
  "worktree.removeDescription": "Remove {name}? Sessions stay in DSH and remain available as detached bindings.",
147
+ "worktree.removeExternalDescription": "Remove {name}? This deletes the linked external Worktree directory. Sessions stay in DSH and remain available as detached bindings.",
133
148
  "worktree.addSession": "Add Session to {name}",
134
149
  "worktree.noWorktrees": "No Worktrees",
135
150
  "worktree.createTitle": "New Worktree",
136
151
  "worktree.createDescription": "{name} · the Worktree path is managed by DSH.",
152
+ "worktree.tabCreate": "Create",
153
+ "worktree.tabImport": "Import",
154
+ "worktree.importDescription": "Register an existing Worktree for {name}. Registration leaves the directory in place; removing it later deletes the linked Worktree directory.",
155
+ "worktree.importLoading": "Finding importable Worktrees…",
156
+ "worktree.importEmpty": "No importable Worktrees found.",
157
+ "worktree.importPlaceholder": "Select a Worktree to import",
158
+ "worktree.importSelected": "Selected",
137
159
  "worktree.baseBranch": "Worktree base branch",
138
160
  "worktree.noLocalBranch": "No local branch",
139
161
  "worktree.noBranches": "No local branches found in this Workspace.",
162
+ "worktree.setup.gitNotInstalled": "Git is not installed or is not available on PATH. Install Git, restart DSH, and retry.",
140
163
  "worktree.setup.noRepository": "This Workspace is not a Git repository. Run these commands in the Workspace directory:",
141
164
  "worktree.setup.noInitialCommit": "This Git repository has no initial commit. Run these commands first:",
142
165
  "worktree.setup.noLocalBranch": "This Git repository has no local branch. Create one first:",
143
166
  "worktree.setup.commands": "Copyable commands",
144
167
  "worktree.name": "Worktree name",
145
168
  "worktree.create": "Create Worktree",
169
+ "worktree.import": "Import Worktree",
146
170
  "session.options": "Session options for {name}",
147
171
  "session.new": "New Session",
148
172
  "session.rename": "Rename session",
@@ -164,6 +188,7 @@ window.__ModuleLoader__.load({
164
188
  "action.openCreatedSession": "Open Created Session",
165
189
  "status.loading": "Loading Workspaces…",
166
190
  "error.worktreeDataUnavailable": "Worktree data is unavailable. Retry the request.",
191
+ "error.gitNotInstalled": "Git is not installed or unavailable. Install Git and retry.",
167
192
  "error.connectionDisposed": "Worktree connection is disposed; reload the plugin and retry.",
168
193
  "error.connectionFailed": "Worktree endpoint {endpoint} failed; retryable connection error: {reason}",
169
194
  "error.invalidResult": "Worktree endpoint {endpoint} returned an invalid result; retry the request.",
@@ -172,7 +197,10 @@ window.__ModuleLoader__.load({
172
197
  "error.worktreeOrderingUnavailable": "Worktree ordering is unavailable; retry after reconnecting.",
173
198
  "error.worktreeCreatedSessionUnavailable": "Worktree created, but Session creation is unavailable; retry after reconnecting.",
174
199
  "error.sessionCreationUnavailable": "Session creation is unavailable; retry after reconnecting.",
175
- "error.worktreeRecordMissing": "Worktree creation returned no Worktree record; retry the request.",
200
+ "error.worktreeRecordMissing": "Worktree registration returned no Worktree record; retry the request.",
201
+ "error.worktreeImportInvalid": "This Worktree cannot be imported. Choose a valid absolute path in this Workspace.",
202
+ "error.worktreeAlreadyManaged": "This Worktree is already managed by the plugin.",
203
+ "error.worktreeRegistrationSessionUnavailable": "The Worktree was registered, but Session creation is unavailable; retry after reconnecting.",
176
204
  "error.workspaceRenameUnavailable": "Workspace rename is unavailable; retry after reconnecting.",
177
205
  "error.workspaceDeleteUnavailable": "Workspace delete is unavailable; retry after reconnecting.",
178
206
  "error.sessionRenameUnavailable": "Session rename is unavailable; retry after reconnecting.",
@@ -196,8 +224,10 @@ window.__ModuleLoader__.load({
196
224
  */
197
225
  const WORKTREE_CONNECTION_ENDPOINTS = Object.freeze({
198
226
  listWorktrees: "worktreeManager/listWorktrees",
227
+ listImportCandidates: "worktreeManager/listImportCandidates",
199
228
  listBranches: "worktreeManager/listBranches",
200
229
  createWorktree: "worktreeManager/createWorktree",
230
+ importWorktree: "worktreeManager/importWorktree",
201
231
  removeWorktree: "worktreeManager/removeWorktree",
202
232
  insertWorktreeBefore: "worktreeManager/insertWorktreeBefore",
203
233
  listBindings: "worktreeManager/listBindings",
@@ -216,14 +246,14 @@ window.__ModuleLoader__.load({
216
246
  this.retryable = options.retryable;
217
247
  }
218
248
  };
219
- function isRecord(value) {
249
+ function isRecord$1(value) {
220
250
  return typeof value === "object" && value !== null && !Array.isArray(value);
221
251
  }
222
252
  function isWorktreeError(value) {
223
- return isRecord(value) && typeof value.code === "string" && typeof value.message === "string" && isRecord(value.details);
253
+ return isRecord$1(value) && typeof value.code === "string" && typeof value.message === "string" && isRecord$1(value.details);
224
254
  }
225
255
  function isWorktreeRemoteResult(value) {
226
- if (!isRecord(value) || typeof value.ok !== "boolean") return false;
256
+ if (!isRecord$1(value) || typeof value.ok !== "boolean") return false;
227
257
  return value.ok || isWorktreeError(value.error) && value.error.details !== void 0;
228
258
  }
229
259
  function disposedError() {
@@ -244,7 +274,7 @@ window.__ModuleLoader__.load({
244
274
  });
245
275
  }
246
276
  function gatewayFailure(endpoint, result) {
247
- const rawDetails = isRecord(result.error.details) ? result.error.details : {};
277
+ const rawDetails = isRecord$1(result.error.details) ? result.error.details : {};
248
278
  throw new WorktreeConnectionError({
249
279
  code: result.error.code,
250
280
  message: result.error.message,
@@ -301,8 +331,10 @@ window.__ModuleLoader__.load({
301
331
  }
302
332
  return {
303
333
  listWorktrees: (input) => invoke("listWorktrees", input),
334
+ listImportCandidates: (input) => invoke("listImportCandidates", input),
304
335
  listBranches: (input) => invoke("listBranches", input),
305
336
  createWorktree: (input) => invoke("createWorktree", input),
337
+ importWorktree: (input) => invoke("importWorktree", input),
306
338
  async removeWorktree(input) {
307
339
  await invoke("removeWorktree", input);
308
340
  },
@@ -320,8 +352,8 @@ window.__ModuleLoader__.load({
320
352
  };
321
353
  }
322
354
  //#endregion
323
- //#region \0clutch-dsh-worktree-css:/Users/yuancheng/Documents/Code/clutch-dsh/packages/clutch-dsh-worktree/src/client/worktree-context.css.mjs
324
- const css$1 = ".-cerbur-clutch-dsh-worktree-headerContext {\n display: inline-flex;\n min-width: 0;\n height: 22px;\n align-items: center;\n gap: 4px;\n max-width: 180px;\n overflow: hidden;\n border-radius: 6px;\n padding: 0 2px 0 0;\n background: var(--dsw-alias-fill-tsp-secondary);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-contextIcon {\n flex: none;\n opacity: 0.7;\n}\n\n.-cerbur-clutch-dsh-worktree-contextLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-heroContext {\n position: absolute;\n z-index: 1;\n display: inline-flex;\n box-sizing: border-box;\n max-width: 260px;\n min-height: 22px;\n align-items: center;\n overflow: hidden;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n padding: 0 8px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 20px;\n pointer-events: none;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n";
355
+ //#region \0clutch-dsh-worktree-css:/Users/yuancheng/.dsh/clutch-dsh-worktree/worktree/wt_0c53e50f-f169-4c5e-9664-1c2d58ae1212/packages/clutch-dsh-worktree/src/client/worktree-context.css.mjs
356
+ const css$1 = ".-cerbur-clutch-dsh-worktree-headerContext {\n display: inline-flex;\n min-width: 0;\n height: 22px;\n align-items: center;\n gap: 4px;\n max-width: 180px;\n overflow: hidden;\n border-radius: 6px;\n padding: 0 2px 0 0;\n background: var(--dsw-alias-fill-tsp-secondary);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-contextIcon {\n flex: none;\n opacity: 0.7;\n}\n\n.-cerbur-clutch-dsh-worktree-contextLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-contextHoverTitle {\n max-width: 360px;\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n white-space: normal;\n}\n\n.-cerbur-clutch-dsh-worktree-heroContextHost {\n position: absolute;\n z-index: 1;\n display: block;\n width: max-content;\n max-width: 260px;\n min-height: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-heroContext {\n display: inline-flex;\n box-sizing: border-box;\n max-width: 260px;\n min-height: 22px;\n align-items: center;\n overflow: hidden;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n padding: 0 8px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 20px;\n pointer-events: auto;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n";
325
357
  const styleId$1 = "@cerbur/clutch-dsh-worktree/worktree-context.css";
326
358
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"@cerbur/clutch-dsh-worktree/worktree-context.css\"]") === null) {
327
359
  const tag = document.createElement("style");
@@ -334,6 +366,8 @@ window.__ModuleLoader__.load({
334
366
  "headerContext": "-cerbur-clutch-dsh-worktree-headerContext",
335
367
  "contextIcon": "-cerbur-clutch-dsh-worktree-contextIcon",
336
368
  "contextLabel": "-cerbur-clutch-dsh-worktree-contextLabel",
369
+ "contextHoverTitle": "-cerbur-clutch-dsh-worktree-contextHoverTitle",
370
+ "heroContextHost": "-cerbur-clutch-dsh-worktree-heroContextHost",
337
371
  "heroContext": "-cerbur-clutch-dsh-worktree-heroContext"
338
372
  };
339
373
  //#endregion
@@ -365,8 +399,8 @@ window.__ModuleLoader__.load({
365
399
  });
366
400
  }
367
401
  //#endregion
368
- //#region \0clutch-dsh-worktree-css:/Users/yuancheng/Documents/Code/clutch-dsh/packages/clutch-dsh-worktree/src/client/worktree.css.mjs
369
- const css = ".-cerbur-clutch-dsh-worktree-action {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n width: calc(100% + 4px);\n height: 42px;\n margin: 4px -2px;\n box-sizing: border-box;\n border: 0;\n border-radius: 12px;\n padding: 0 10px 0 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n overflow: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-action:hover,\n.-cerbur-clutch-dsh-worktree-action[data-active='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-action[data-collapsed='true'] {\n width: 36px;\n height: 36px;\n margin: 8px 0 10px;\n justify-content: center;\n gap: 0;\n padding: 0;\n border-radius: 50%;\n}\n\n.-cerbur-clutch-dsh-worktree-actionLabel {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-surface {\n position: absolute;\n top: 0;\n left: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n min-width: 56px;\n overflow: hidden;\n border-right: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-specific-sidebar-fill);\n color: var(--dsw-alias-label-primary);\n pointer-events: auto;\n transition: width var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .-cerbur-clutch-dsh-worktree-surface {\n transition: none;\n }\n}\n\n.-cerbur-clutch-dsh-worktree-wideContent {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n}\n\n.-cerbur-clutch-dsh-worktree-surface[data-collapsed='true'] .-cerbur-clutch-dsh-worktree-wideContent {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-railContent {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-surface[data-collapsed='true'] .-cerbur-clutch-dsh-worktree-railContent {\n display: flex;\n flex: 1;\n align-items: flex-start;\n justify-content: center;\n padding-top: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-railButton,\n.-cerbur-clutch-dsh-worktree-closeButton {\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-railButton {\n width: 36px;\n height: 36px;\n color: var(--dsw-alias-label-secondary);\n font-size: 11px;\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-railButton:hover,\n.-cerbur-clutch-dsh-worktree-closeButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-header {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n min-height: 44px;\n padding: 6px 10px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-title {\n min-width: 0;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n flex: none;\n width: 28px;\n height: 28px;\n font-size: 18px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-modeButton[data-active='true'] {\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspacePicker {\n display: block;\n width: calc(100% - 20px);\n margin: 6px 10px 8px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceLabel {\n display: block;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n padding: 0 10px 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-content:focus-visible {\n outline: 2px solid var(--dsw-alias-border-l3);\n outline-offset: -2px;\n}\n\n.-cerbur-clutch-dsh-worktree-error {\n margin: 12px 0 0;\n padding: 8px;\n border: 1px solid var(--dsw-alias-state-error-primary);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n border: 0;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n width: 100%;\n padding: 6px 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-recoveryActions {\n display: grid;\n gap: 6px;\n margin-top: 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton:disabled,\n.-cerbur-clutch-dsh-worktree-actionButton:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.-cerbur-clutch-dsh-worktree-actions {\n display: grid;\n gap: 6px;\n margin-top: 10px;\n padding: 8px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-actionLabel {\n display: grid;\n gap: 3px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-actionSelect {\n min-width: 0;\n padding: 5px 6px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-section {\n margin: 12px 0 0;\n}\n\n.-cerbur-clutch-dsh-worktree-sectionTitle {\n margin: 0 2px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-empty,\n.-cerbur-clutch-dsh-worktree-message {\n margin: 0;\n padding: 8px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-gitReadiness {\n display: grid;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-commandBlock {\n margin: 6px 0 0;\n padding: 8px;\n overflow-x: auto;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-secondary);\n font: 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n}\n\n.-cerbur-clutch-dsh-worktree-message[data-error='true'] {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktree,\n.-cerbur-clutch-dsh-worktree-session {\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 6px 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree {\n cursor: default;\n}\n\n.-cerbur-clutch-dsh-worktree-session {\n cursor: pointer;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree:hover,\n.-cerbur-clutch-dsh-worktree-session:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeLabel,\n.-cerbur-clutch-dsh-worktree-sessionLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-status {\n flex: none;\n margin-left: auto;\n padding-left: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchRow {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchIcon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n min-width: 0;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n outline: none;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n width: 100%;\n padding: 6px 8px;\n font-size: 13px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput:focus,\n.-cerbur-clutch-dsh-worktree-actionSelect:focus {\n border-color: #3b82f6;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 20px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceList {\n min-width: 0;\n min-height: 0;\n display: grid;\n gap: 4px;\n overflow-x: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceGroup {\n min-width: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow,\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n position: relative;\n display: flex;\n align-items: center;\n min-width: 0;\n min-height: 36px;\n box-sizing: border-box;\n border-radius: 8px;\n padding: 3px 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceDisclosure,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeDisclosure,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 28px;\n border: 0;\n border-radius: 6px;\n padding: 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 17px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton > svg {\n display: block;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-worktreeIcon {\n flex: none;\n width: 24px;\n color: var(--dsw-alias-label-secondary);\n font-size: 20px;\n line-height: 1;\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeState {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 12px;\n margin-right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon {\n color: var(--dsw-alias-brand-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceTitle,\n.-cerbur-clutch-dsh-worktree-worktreeLabel {\n min-width: 0;\n overflow: hidden;\n flex: 1;\n padding: 0 6px;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-main-group='true'] .-cerbur-clutch-dsh-worktree-worktreeLabel {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeHoverTitle {\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot,\n.-cerbur-clutch-dsh-worktree-workspaceActions {\n position: relative;\n display: inline-flex;\n flex: 0 0 64px;\n align-items: center;\n justify-content: flex-end;\n width: 64px;\n height: 28px;\n margin-left: auto;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-menuAction {\n position: absolute;\n top: 0;\n right: 32px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-iconButton:last-child {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-menuAction {\n display: inline-flex;\n width: 28px;\n height: 28px;\n visibility: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction {\n visibility: visible;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeChildren {\n margin-left: 24px;\n padding: 2px 0 5px 12px;\n border-left: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-groupLabel {\n padding: 6px 8px 3px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader {\n display: flex;\n align-items: center;\n min-height: 34px;\n padding-right: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader .-cerbur-clutch-dsh-worktree-groupLabel {\n flex: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeGroup {\n margin-top: 2px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n min-height: 34px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-disclosureButton {\n width: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent {\n display: flex;\n align-items: center;\n flex: 1;\n width: 0;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 4px 4px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent:hover {\n background: transparent;\n}\n\n.-cerbur-clutch-dsh-worktree-rowActions {\n display: none;\n flex: none;\n align-items: center;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton {\n display: block;\n width: calc(100% - 24px);\n margin: 2px 0 4px 24px;\n padding: 4px 8px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover .-cerbur-clutch-dsh-worktree-rowActions,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-rowActions {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-renameInput {\n width: 100%;\n}\n\n.-cerbur-clutch-dsh-worktree-renameError {\n margin: 8px 0 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeGuide {\n flex: none;\n width: 20px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-emptyNested {\n margin: 0;\n padding: 4px 8px 5px 28px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-modalField {\n display: grid;\n gap: 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n";
402
+ //#region \0clutch-dsh-worktree-css:/Users/yuancheng/.dsh/clutch-dsh-worktree/worktree/wt_0c53e50f-f169-4c5e-9664-1c2d58ae1212/packages/clutch-dsh-worktree/src/client/worktree.css.mjs
403
+ const css = ".-cerbur-clutch-dsh-worktree-action {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n width: calc(100% + 4px);\n height: 42px;\n margin: 4px -2px;\n box-sizing: border-box;\n border: 0;\n border-radius: 12px;\n padding: 0 10px 0 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n overflow: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-action:hover,\n.-cerbur-clutch-dsh-worktree-action[data-active='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-action[data-collapsed='true'] {\n width: 36px;\n height: 36px;\n margin: 8px 0 10px;\n justify-content: center;\n gap: 0;\n padding: 0;\n border-radius: 50%;\n}\n\n.-cerbur-clutch-dsh-worktree-actionLabel {\n display: inline-flex;\n min-width: 0;\n align-items: center;\n height: 22px;\n overflow: hidden;\n font-weight: 400;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-surface {\n position: absolute;\n top: 0;\n left: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n min-width: 56px;\n overflow: hidden;\n border-right: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-specific-sidebar-fill);\n color: var(--dsw-alias-label-primary);\n pointer-events: auto;\n transition: width var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .-cerbur-clutch-dsh-worktree-surface {\n transition: none;\n }\n}\n\n.-cerbur-clutch-dsh-worktree-wideContent {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n}\n\n.-cerbur-clutch-dsh-worktree-surface[data-collapsed='true'] .-cerbur-clutch-dsh-worktree-wideContent {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTabs {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTab {\n border: 0;\n border-bottom: 2px solid transparent;\n padding: 4px 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTab[aria-selected='true'] {\n border-bottom-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportCandidates {\n display: grid;\n gap: 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportSelect {\n width: 100%;\n min-width: 0;\n padding: 7px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportError {\n display: grid;\n gap: 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-header {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n min-height: 44px;\n padding: 6px 10px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-title {\n min-width: 0;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n flex: none;\n width: 28px;\n height: 28px;\n font-size: 18px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-modeButton[data-active='true'] {\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspacePicker {\n display: block;\n width: calc(100% - 20px);\n margin: 6px 10px 8px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceLabel {\n display: block;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n padding: 0 10px 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-content:focus-visible {\n outline: 2px solid var(--dsw-alias-border-l3);\n outline-offset: -2px;\n}\n\n.-cerbur-clutch-dsh-worktree-error {\n margin: 12px 0 0;\n padding: 8px;\n border: 1px solid var(--dsw-alias-state-error-primary);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n border: 0;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n width: 100%;\n padding: 6px 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-recoveryActions {\n display: grid;\n gap: 6px;\n margin-top: 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton:disabled,\n.-cerbur-clutch-dsh-worktree-actionButton:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.-cerbur-clutch-dsh-worktree-actions {\n display: grid;\n gap: 6px;\n margin-top: 10px;\n padding: 8px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-actionSelect {\n min-width: 0;\n padding: 5px 6px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-section {\n margin: 12px 0 0;\n}\n\n.-cerbur-clutch-dsh-worktree-sectionTitle {\n margin: 0 2px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-empty,\n.-cerbur-clutch-dsh-worktree-message {\n margin: 0;\n padding: 8px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-gitReadiness {\n display: grid;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-commandBlock {\n margin: 6px 0 0;\n padding: 8px;\n overflow-x: auto;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-secondary);\n font: 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n}\n\n.-cerbur-clutch-dsh-worktree-message[data-error='true'] {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktree,\n.-cerbur-clutch-dsh-worktree-session {\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 6px 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree {\n cursor: default;\n}\n\n.-cerbur-clutch-dsh-worktree-session {\n cursor: pointer;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree:hover,\n.-cerbur-clutch-dsh-worktree-session:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeLabel,\n.-cerbur-clutch-dsh-worktree-sessionLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-status {\n flex: none;\n margin-left: auto;\n padding-left: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchRow {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchIcon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n min-width: 0;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n outline: none;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n width: 100%;\n padding: 6px 8px;\n font-size: 13px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput:focus,\n.-cerbur-clutch-dsh-worktree-actionSelect:focus,\n.-cerbur-clutch-dsh-worktree-worktreeImportSelect:focus {\n border-color: #3b82f6;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 20px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceList {\n min-width: 0;\n min-height: 0;\n display: grid;\n gap: 4px;\n overflow-x: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceGroup {\n min-width: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow,\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n position: relative;\n display: flex;\n align-items: center;\n min-width: 0;\n min-height: 36px;\n box-sizing: border-box;\n border-radius: 8px;\n padding: 3px 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceDisclosure,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeDisclosure,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 28px;\n border: 0;\n border-radius: 6px;\n padding: 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 17px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton > svg {\n display: block;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-worktreeIcon {\n flex: none;\n width: 24px;\n color: var(--dsw-alias-label-secondary);\n font-size: 20px;\n line-height: 1;\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeState {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 12px;\n margin-right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon {\n color: var(--dsw-alias-brand-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceTitle,\n.-cerbur-clutch-dsh-worktree-worktreeLabel {\n min-width: 0;\n overflow: hidden;\n flex: 1;\n padding: 0 6px;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-main-group='true'] .-cerbur-clutch-dsh-worktree-worktreeLabel {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeHoverTitle {\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot,\n.-cerbur-clutch-dsh-worktree-workspaceActions {\n position: relative;\n display: inline-flex;\n flex: 0 0 64px;\n align-items: center;\n justify-content: flex-end;\n width: 64px;\n height: 28px;\n margin-left: auto;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-menuAction {\n position: absolute;\n top: 0;\n right: 32px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-iconButton:last-child {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-menuAction {\n display: inline-flex;\n width: 28px;\n height: 28px;\n visibility: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction {\n visibility: visible;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeChildren {\n margin-left: 16px;\n padding: 2px 0 5px 12px;\n border-left: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-groupLabel {\n padding: 6px 8px 3px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader {\n display: flex;\n align-items: center;\n min-height: 34px;\n padding-right: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader .-cerbur-clutch-dsh-worktree-groupLabel {\n flex: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeGroup {\n margin-top: 2px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n min-height: 34px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-disclosureButton {\n width: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow {\n position: relative;\n display: flex;\n align-items: center;\n width: calc(100% - 22px);\n margin-left: 22px;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-session-current='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-session-current='true'] .-cerbur-clutch-dsh-worktree-treeSessionContent {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent {\n display: flex;\n align-items: center;\n flex: 1;\n width: 0;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 4px 4px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent:hover {\n background: transparent;\n}\n\n.-cerbur-clutch-dsh-worktree-rowActions {\n display: none;\n flex: none;\n align-items: center;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton {\n display: block;\n width: calc(100% - 24px);\n margin: 2px 0 4px 24px;\n padding: 4px 8px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover .-cerbur-clutch-dsh-worktree-rowActions,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-rowActions {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-renameInput {\n width: 100%;\n}\n\n.-cerbur-clutch-dsh-worktree-renameError {\n margin: 8px 0 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-emptyNested {\n margin: 0;\n padding: 4px 8px 5px 28px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-modalField {\n display: grid;\n gap: 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n";
370
404
  const styleId = "@cerbur/clutch-dsh-worktree/worktree.css";
371
405
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"@cerbur/clutch-dsh-worktree/worktree.css\"]") === null) {
372
406
  const tag = document.createElement("style");
@@ -380,8 +414,11 @@ window.__ModuleLoader__.load({
380
414
  "actionLabel": "-cerbur-clutch-dsh-worktree-actionLabel",
381
415
  "surface": "-cerbur-clutch-dsh-worktree-surface",
382
416
  "wideContent": "-cerbur-clutch-dsh-worktree-wideContent",
383
- "railContent": "-cerbur-clutch-dsh-worktree-railContent",
384
- "railButton": "-cerbur-clutch-dsh-worktree-railButton",
417
+ "worktreeModalTabs": "-cerbur-clutch-dsh-worktree-worktreeModalTabs",
418
+ "worktreeModalTab": "-cerbur-clutch-dsh-worktree-worktreeModalTab",
419
+ "worktreeImportCandidates": "-cerbur-clutch-dsh-worktree-worktreeImportCandidates",
420
+ "worktreeImportSelect": "-cerbur-clutch-dsh-worktree-worktreeImportSelect",
421
+ "worktreeImportError": "-cerbur-clutch-dsh-worktree-worktreeImportError",
385
422
  "closeButton": "-cerbur-clutch-dsh-worktree-closeButton",
386
423
  "header": "-cerbur-clutch-dsh-worktree-header",
387
424
  "title": "-cerbur-clutch-dsh-worktree-title",
@@ -437,7 +474,6 @@ window.__ModuleLoader__.load({
437
474
  "sessionOverflowButton": "-cerbur-clutch-dsh-worktree-sessionOverflowButton",
438
475
  "renameInput": "-cerbur-clutch-dsh-worktree-renameInput",
439
476
  "renameError": "-cerbur-clutch-dsh-worktree-renameError",
440
- "treeGuide": "-cerbur-clutch-dsh-worktree-treeGuide",
441
477
  "emptyNested": "-cerbur-clutch-dsh-worktree-emptyNested",
442
478
  "modalField": "-cerbur-clutch-dsh-worktree-modalField"
443
479
  };
@@ -484,9 +520,12 @@ window.__ModuleLoader__.load({
484
520
  for (let ancestor = element.parentElement; ancestor !== null; ancestor = ancestor.parentElement) if (getComputedStyle(ancestor).position !== "static") return ancestor;
485
521
  return null;
486
522
  }
523
+ function overlayFor(element) {
524
+ return positionedAncestor(element.closest("[data-worktree-hero-host]") ?? element);
525
+ }
487
526
  function measurePlacement(element) {
488
527
  const hero = document.querySelector("[data-phase=\"hero\"]");
489
- const overlay = positionedAncestor(element);
528
+ const overlay = overlayFor(element);
490
529
  const headline = hero === null ? null : headlineElement(hero);
491
530
  if (hero === null || headline === null || overlay === null) return null;
492
531
  const anchor = headline.getBoundingClientRect();
@@ -505,7 +544,7 @@ window.__ModuleLoader__.load({
505
544
  }
506
545
  /**
507
546
  * Browser-local Hero suffix. It intentionally uses the frame overlay because
508
- * rc.8 exposes no additive slot beside the native Hero headline.
547
+ * The current upstream DSH exposes no additive slot beside the native Hero headline.
509
548
  */
510
549
  function WorktreeHeroContext({ useWorktreeContext, t }) {
511
550
  const state = useWorktreeContext((snapshot) => snapshot);
@@ -538,7 +577,7 @@ window.__ModuleLoader__.load({
538
577
  attributeFilter: ["class", "data-phase"]
539
578
  });
540
579
  const resizeObserver = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(schedule);
541
- resizeObserver?.observe(positionedAncestor(element) ?? element);
580
+ resizeObserver?.observe(overlayFor(element) ?? element);
542
581
  window.addEventListener("resize", schedule);
543
582
  schedule();
544
583
  return () => {
@@ -551,16 +590,27 @@ window.__ModuleLoader__.load({
551
590
  const ariaLabel = contextAriaLabel(state, t);
552
591
  if (label === void 0) return null;
553
592
  return (0, react_jsx_runtime.jsx)("span", {
554
- ref: measure,
555
- className: worktree_context_css_default.heroContext,
556
- "data-worktree-hero-context": true,
557
- "aria-label": ariaLabel,
558
- title: label,
593
+ className: worktree_context_css_default.heroContextHost,
594
+ "data-worktree-hero-host": true,
559
595
  style: placement === null ? { visibility: "hidden" } : {
560
596
  left: `${placement.left}px`,
561
597
  top: `${placement.top}px`
562
598
  },
563
- children: label
599
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.HoverCard, {
600
+ anchor: (0, react_jsx_runtime.jsx)("span", {
601
+ ref: measure,
602
+ className: worktree_context_css_default.heroContext,
603
+ "data-worktree-hero-context": true,
604
+ "aria-label": ariaLabel,
605
+ title: label,
606
+ children: label
607
+ }),
608
+ content: (0, react_jsx_runtime.jsx)("div", {
609
+ className: worktree_context_css_default.contextHoverTitle,
610
+ children: label
611
+ }),
612
+ openDelayMs: 500
613
+ })
564
614
  });
565
615
  }
566
616
  //#endregion
@@ -693,6 +743,84 @@ window.__ModuleLoader__.load({
693
743
  };
694
744
  }
695
745
  //#endregion
746
+ //#region lib/client/worktree-expand-state.js
747
+ /** Browser-local storage identity; never sent to DSH or the plugin sidecar. */
748
+ const WORKTREE_EXPAND_STATE_STORAGE_KEY = "clutch-dsh-worktree.expand-state";
749
+ function emptyState() {
750
+ return {
751
+ collapsedWorkspaceIds: {},
752
+ collapsedMainWorkspaceIds: {},
753
+ collapsedWorktreeIds: {}
754
+ };
755
+ }
756
+ function isRecord(value) {
757
+ return typeof value === "object" && value !== null && !Array.isArray(value);
758
+ }
759
+ function normalizeIds(value) {
760
+ if (!isRecord(value)) return {};
761
+ return Object.fromEntries(Object.entries(value).filter(([id, collapsed]) => id.length > 0 && collapsed === true));
762
+ }
763
+ /** Turn any persisted JSON value into the current state shape. */
764
+ function normalizeWorktreeExpandState(value) {
765
+ const source = isRecord(value) ? value : {};
766
+ return {
767
+ collapsedWorkspaceIds: normalizeIds(source.collapsedWorkspaceIds),
768
+ collapsedMainWorkspaceIds: normalizeIds(source.collapsedMainWorkspaceIds),
769
+ collapsedWorktreeIds: normalizeIds(source.collapsedWorktreeIds)
770
+ };
771
+ }
772
+ function isWorkspaceExpanded(state, workspaceId) {
773
+ return state.collapsedWorkspaceIds[workspaceId] !== true;
774
+ }
775
+ function isMainExpanded(state, workspaceId) {
776
+ return state.collapsedMainWorkspaceIds[workspaceId] !== true;
777
+ }
778
+ function isWorktreeExpanded(state, worktreeId) {
779
+ return state.collapsedWorktreeIds[worktreeId] !== true;
780
+ }
781
+ function toggle(record, id) {
782
+ if (record[id] === true) delete record[id];
783
+ else record[id] = true;
784
+ }
785
+ function retain(record, ids) {
786
+ const allowed = new Set(ids);
787
+ for (const id of Object.keys(record)) if (!allowed.has(id)) delete record[id];
788
+ }
789
+ /** Create one apply-scoped store; component remounts share this instance. */
790
+ function createWorktreeExpandStateStore(snapshotStoreFactory) {
791
+ let store;
792
+ try {
793
+ store = snapshotStoreFactory(emptyState(), { persist: { name: WORKTREE_EXPAND_STATE_STORAGE_KEY } });
794
+ } catch {
795
+ store = snapshotStoreFactory(emptyState());
796
+ }
797
+ store.set(normalizeWorktreeExpandState(store.getSnapshot()));
798
+ return Object.assign(store, { actions: {
799
+ toggleWorkspace: (workspaceId) => {
800
+ store.update((draft) => {
801
+ toggle(draft.collapsedWorkspaceIds, workspaceId);
802
+ });
803
+ },
804
+ toggleMain: (workspaceId) => {
805
+ store.update((draft) => {
806
+ toggle(draft.collapsedMainWorkspaceIds, workspaceId);
807
+ });
808
+ },
809
+ toggleWorktree: (worktreeId) => {
810
+ store.update((draft) => {
811
+ toggle(draft.collapsedWorktreeIds, worktreeId);
812
+ });
813
+ },
814
+ retain: (workspaceIds, worktreeIds) => {
815
+ store.update((draft) => {
816
+ retain(draft.collapsedWorkspaceIds, workspaceIds);
817
+ retain(draft.collapsedMainWorkspaceIds, workspaceIds);
818
+ retain(draft.collapsedWorktreeIds, worktreeIds);
819
+ });
820
+ }
821
+ } });
822
+ }
823
+ //#endregion
696
824
  //#region lib/client/view-mode.js
697
825
  /** Browser-local storage key; it is never sent to DSH or the sidecar. */
698
826
  const WORKTREE_VIEW_MODE_STORAGE_KEY = "clutch-dsh-worktree.view-mode";
@@ -769,6 +897,9 @@ window.__ModuleLoader__.load({
769
897
  case "SESSION_CREATE_UNAVAILABLE": return t("error.sessionCreationUnavailable");
770
898
  case "WORKTREE_CREATED_SESSION_UNAVAILABLE": return t("error.worktreeCreatedSessionUnavailable");
771
899
  case "WORKTREE_RECORD_MISSING": return t("error.worktreeRecordMissing");
900
+ case "WORKTREE_IMPORT_INVALID": return t("error.worktreeImportInvalid");
901
+ case "WORKTREE_ALREADY_MANAGED": return t("error.worktreeAlreadyManaged");
902
+ case "WORKTREE_REGISTRATION_SESSION_UNAVAILABLE": return t("error.worktreeRegistrationSessionUnavailable");
772
903
  case "WORKSPACE_RENAME_UNAVAILABLE": return t("error.workspaceRenameUnavailable");
773
904
  case "WORKSPACE_DELETE_UNAVAILABLE": return t("error.workspaceDeleteUnavailable");
774
905
  case "SESSION_RENAME_UNAVAILABLE": return t("error.sessionRenameUnavailable");
@@ -782,6 +913,7 @@ window.__ModuleLoader__.load({
782
913
  case "WORKTREE_SESSION_REPAIR_REQUIRED": return t("error.worktreeSessionRepairRequired");
783
914
  case "WORKTREE_SESSION_UNAVAILABLE": return t("error.worktreeSessionUnavailable");
784
915
  case "SESSION_ARCHIVED": return t("error.sessionArchived");
916
+ case "GIT_NOT_INSTALLED": return t("error.gitNotInstalled");
785
917
  default: return error.message.length > 0 ? error.message : t("error.worktreeDataUnavailable");
786
918
  }
787
919
  }
@@ -898,6 +1030,7 @@ window.__ModuleLoader__.load({
898
1030
  /** Keep mutation routing in the browser Consumer while leaving wire details to the adapter. */
899
1031
  async function executeWorktreeAction(manager, action) {
900
1032
  if (action.type === "createWorktree") return manager.createWorktree(action.input);
1033
+ if (action.type === "importWorktree") return manager.importWorktree(action.input);
901
1034
  if (action.type === "removeWorktree") {
902
1035
  await manager.removeWorktree(action.input);
903
1036
  return;
@@ -924,6 +1057,14 @@ window.__ModuleLoader__.load({
924
1057
  }
925
1058
  //#endregion
926
1059
  //#region lib/client/worktree-view-read.js
1060
+ /** Merge one freshly read Workspace projection without clearing other ready views. */
1061
+ function mergeWorktreeView(views, nextView) {
1062
+ const index = views.findIndex((view) => view.workspaceId === nextView.workspaceId);
1063
+ if (index === -1) return [...views, nextView];
1064
+ const merged = [...views];
1065
+ merged[index] = nextView;
1066
+ return merged;
1067
+ }
927
1068
  /** Reuse the previous ID snapshot when DSH republishes equivalent Workspace items. */
928
1069
  function stableWorkspaceIds(previous, next) {
929
1070
  if (previous.length !== next.length) return next;
@@ -972,6 +1113,7 @@ window.__ModuleLoader__.load({
972
1113
  /** Return copyable, read-only setup commands for a Git readiness state. */
973
1114
  function worktreeSetupCommands(status) {
974
1115
  switch (status) {
1116
+ case "gitNotInstalled": return [];
975
1117
  case "noRepository": return [
976
1118
  "git init",
977
1119
  "printf \"# README\\n\" > README.md",
@@ -989,6 +1131,10 @@ window.__ModuleLoader__.load({
989
1131
  }
990
1132
  function readinessFromBranchError(error) {
991
1133
  const viewError = toWorktreeViewError(error);
1134
+ if (viewError.code === "GIT_NOT_INSTALLED") return {
1135
+ status: "gitNotInstalled",
1136
+ error: viewError
1137
+ };
992
1138
  if (viewError.code === "WORKSPACE_NOT_GIT_REPOSITORY") return {
993
1139
  status: "noRepository",
994
1140
  error: viewError
@@ -1024,6 +1170,19 @@ window.__ModuleLoader__.load({
1024
1170
  readiness: branchesResult.value.length > 0 ? { status: "ready" } : { status: "noLocalBranch" }
1025
1171
  };
1026
1172
  }
1173
+ /** Isolate modal-target reads from full-surface refresh generations. */
1174
+ function createWorktreeModalViewLoader() {
1175
+ const guard = createWorktreeRefreshGuard();
1176
+ return {
1177
+ invalidate: guard.invalidate,
1178
+ load(manager, workspaceId, onSuccess, onError) {
1179
+ return guard.run(() => loadWorktreeView(manager, workspaceId), (data) => onSuccess({
1180
+ workspaceId,
1181
+ ...data
1182
+ }), (error) => onError(toWorktreeViewError(error)));
1183
+ }
1184
+ };
1185
+ }
1027
1186
  /** Load one independent projection per DSH Workspace for the flat sidebar hierarchy. */
1028
1187
  async function loadWorktreeViews(manager, workspaceIds, options = {}) {
1029
1188
  const views = await Promise.all(workspaceIds.map(async (workspaceId) => ({
@@ -1193,6 +1352,7 @@ window.__ModuleLoader__.load({
1193
1352
  //#region lib/client/worktree-surface-dialogs.js
1194
1353
  function worktreeSetupMessage(status, t) {
1195
1354
  switch (status) {
1355
+ case "gitNotInstalled": return t("worktree.setup.gitNotInstalled");
1196
1356
  case "noRepository": return t("worktree.setup.noRepository");
1197
1357
  case "noInitialCommit": return t("worktree.setup.noInitialCommit");
1198
1358
  case "noLocalBranch": return t("worktree.setup.noLocalBranch");
@@ -1323,9 +1483,12 @@ window.__ModuleLoader__.load({
1323
1483
  })
1324
1484
  });
1325
1485
  }
1326
- function WorktreeCreateDialog({ t, workspace, view, setupStatus, canCreate, selectedBranch, newBranch, actionPending, onClose, onSelectedBranchChange, onNewBranchChange, onSubmit }) {
1486
+ function WorktreeCreateDialog({ t, workspace, view, readError, setupStatus, canCreate, mode, importCandidates, selectedImportPath, selectedBranch, newBranch, actionPending, onClose, onRetry, onModeChange, onRetryImportCandidates, onSelectedImportPathChange, onSelectedBranchChange, onNewBranchChange, onSubmit }) {
1327
1487
  if (workspace === void 0) return null;
1328
- return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
1488
+ const setupCommands = setupStatus === void 0 ? [] : worktreeSetupCommands(setupStatus);
1489
+ const importing = mode === "import";
1490
+ const importBlocked = actionPending || importCandidates.status === "loading" || selectedImportPath === void 0;
1491
+ return (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
1329
1492
  open: true,
1330
1493
  onClose: () => {
1331
1494
  if (actionPending) return;
@@ -1333,7 +1496,7 @@ window.__ModuleLoader__.load({
1333
1496
  },
1334
1497
  closeLabel: t("dialog.closeWorktreeCreate"),
1335
1498
  title: t("worktree.createTitle"),
1336
- description: t("worktree.createDescription", { name: workspace.title }),
1499
+ description: importing ? t("worktree.importDescription", { name: workspace.title }) : t("worktree.createDescription", { name: workspace.title }),
1337
1500
  footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1338
1501
  variant: "outline",
1339
1502
  disabled: actionPending,
@@ -1341,13 +1504,104 @@ window.__ModuleLoader__.load({
1341
1504
  children: t("dialog.cancel")
1342
1505
  }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1343
1506
  variant: "primary",
1344
- disabled: actionPending || selectedBranch.length === 0 || newBranch.trim().length === 0,
1507
+ disabled: importing ? importBlocked : actionPending || !canCreate || selectedBranch.length === 0 || newBranch.trim().length === 0,
1345
1508
  onClick: () => {
1346
1509
  onSubmit();
1347
1510
  },
1348
- children: t("worktree.create")
1511
+ children: importing ? t("worktree.import") : t("worktree.create")
1349
1512
  })] }),
1350
- children: canCreate ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("label", {
1513
+ children: [(0, react_jsx_runtime.jsxs)("div", {
1514
+ className: worktree_css_default.worktreeModalTabs,
1515
+ role: "tablist",
1516
+ "aria-label": t("worktree.title"),
1517
+ children: [(0, react_jsx_runtime.jsx)("button", {
1518
+ className: worktree_css_default.worktreeModalTab,
1519
+ type: "button",
1520
+ role: "tab",
1521
+ "aria-selected": mode === "create",
1522
+ disabled: actionPending,
1523
+ onClick: () => {
1524
+ onModeChange("create");
1525
+ },
1526
+ children: t("worktree.tabCreate")
1527
+ }), (0, react_jsx_runtime.jsx)("button", {
1528
+ className: worktree_css_default.worktreeModalTab,
1529
+ type: "button",
1530
+ role: "tab",
1531
+ "aria-selected": mode === "import",
1532
+ disabled: actionPending,
1533
+ onClick: () => {
1534
+ onModeChange("import");
1535
+ },
1536
+ children: t("worktree.tabImport")
1537
+ })]
1538
+ }), importing ? (0, react_jsx_runtime.jsxs)("div", {
1539
+ className: worktree_css_default.worktreeImportCandidates,
1540
+ role: "tabpanel",
1541
+ children: [
1542
+ importCandidates.status === "loading" && importCandidates.candidates.length === 0 && (0, react_jsx_runtime.jsx)("p", {
1543
+ className: worktree_css_default.message,
1544
+ children: t("worktree.importLoading")
1545
+ }),
1546
+ importCandidates.status === "error" && (0, react_jsx_runtime.jsxs)("div", {
1547
+ className: worktree_css_default.worktreeImportError,
1548
+ role: "alert",
1549
+ children: [(0, react_jsx_runtime.jsx)("p", {
1550
+ className: worktree_css_default.message,
1551
+ children: formatWorktreeViewError(importCandidates.error, t)
1552
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1553
+ variant: "outline",
1554
+ disabled: actionPending,
1555
+ onClick: onRetryImportCandidates,
1556
+ children: t("action.retry")
1557
+ })]
1558
+ }),
1559
+ importCandidates.candidates.length === 0 && importCandidates.status === "ready" && (0, react_jsx_runtime.jsx)("p", {
1560
+ className: worktree_css_default.message,
1561
+ children: t("worktree.importEmpty")
1562
+ }),
1563
+ importCandidates.candidates.length > 0 && (0, react_jsx_runtime.jsxs)("label", {
1564
+ className: worktree_css_default.modalField,
1565
+ children: [t("worktree.tabImport"), (0, react_jsx_runtime.jsxs)("select", {
1566
+ className: worktree_css_default.worktreeImportSelect,
1567
+ "data-worktree-import-select": true,
1568
+ "aria-label": t("worktree.tabImport"),
1569
+ value: selectedImportPath ?? "",
1570
+ disabled: actionPending,
1571
+ onChange: (event) => {
1572
+ onSelectedImportPathChange(event.currentTarget.value);
1573
+ },
1574
+ children: [(0, react_jsx_runtime.jsx)("option", {
1575
+ value: "",
1576
+ disabled: true,
1577
+ children: t("worktree.importPlaceholder")
1578
+ }), importCandidates.candidates.map((candidate) => (0, react_jsx_runtime.jsxs)("option", {
1579
+ value: candidate.absolutePath,
1580
+ children: [
1581
+ candidate.branch,
1582
+ " — ",
1583
+ candidate.absolutePath
1584
+ ]
1585
+ }, candidate.absolutePath))]
1586
+ })]
1587
+ })
1588
+ ]
1589
+ }) : readError !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
1590
+ className: worktree_css_default.gitReadiness,
1591
+ "data-worktree-readiness": "error",
1592
+ role: "alert",
1593
+ children: [(0, react_jsx_runtime.jsx)("p", {
1594
+ className: worktree_css_default.message,
1595
+ "data-error": "true",
1596
+ children: formatWorktreeViewError(readError, t)
1597
+ }), readError.retryable && onRetry !== void 0 && (0, react_jsx_runtime.jsx)("button", {
1598
+ type: "button",
1599
+ className: worktree_css_default.retryButton,
1600
+ disabled: actionPending,
1601
+ onClick: onRetry,
1602
+ children: t("action.retry")
1603
+ })]
1604
+ }) : canCreate ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("label", {
1351
1605
  className: worktree_css_default.modalField,
1352
1606
  children: [t("worktree.baseBranch"), (0, react_jsx_runtime.jsx)("select", {
1353
1607
  className: worktree_css_default.actionSelect,
@@ -1385,12 +1639,12 @@ window.__ModuleLoader__.load({
1385
1639
  children: [(0, react_jsx_runtime.jsx)("p", {
1386
1640
  className: worktree_css_default.message,
1387
1641
  children: setupStatus === void 0 ? t("status.loading") : worktreeSetupMessage(setupStatus, t)
1388
- }), setupStatus !== void 0 && (0, react_jsx_runtime.jsx)("pre", {
1642
+ }), setupCommands.length > 0 && (0, react_jsx_runtime.jsx)("pre", {
1389
1643
  className: worktree_css_default.commandBlock,
1390
1644
  "aria-label": t("worktree.setup.commands"),
1391
- children: worktreeSetupCommands(setupStatus).join("\n")
1645
+ children: setupCommands.join("\n")
1392
1646
  })]
1393
- })
1647
+ })]
1394
1648
  });
1395
1649
  }
1396
1650
  function WorktreeRemovalDialog({ t, worktree, actionPending, onClose, onSubmit }) {
@@ -1403,7 +1657,7 @@ window.__ModuleLoader__.load({
1403
1657
  },
1404
1658
  closeLabel: t("dialog.closeWorktreeRemove"),
1405
1659
  title: t("worktree.remove"),
1406
- description: t("worktree.removeDescription", { name: worktree.branch }),
1660
+ description: worktree.source === "external" ? t("worktree.removeExternalDescription", { name: worktree.branch }) : t("worktree.removeDescription", { name: worktree.branch }),
1407
1661
  footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1408
1662
  variant: "outline",
1409
1663
  disabled: actionPending,
@@ -1427,6 +1681,17 @@ window.__ModuleLoader__.load({
1427
1681
  function bindingIdsFor(bindings, worktreeId) {
1428
1682
  return bindings.filter((binding) => binding.worktreeId === worktreeId).map((binding) => binding.sessionId);
1429
1683
  }
1684
+ function clearSessionGroupExpansion(current, groupKeys) {
1685
+ const next = { ...current };
1686
+ for (const key of groupKeys) delete next[key];
1687
+ return next;
1688
+ }
1689
+ function isCompleteWorktreeWorkspaceSnapshot(workspaceIds, views) {
1690
+ if (views.length !== workspaceIds.length) return false;
1691
+ const expected = new Set(workspaceIds);
1692
+ const actual = new Set(views.map((view) => view.workspaceId));
1693
+ return actual.size === expected.size && [...expected].every((id) => actual.has(id));
1694
+ }
1430
1695
  function includesText(value, query) {
1431
1696
  return value.toLocaleLowerCase().includes(query);
1432
1697
  }
@@ -1438,6 +1703,46 @@ window.__ModuleLoader__.load({
1438
1703
  if (view.worktrees.some((record) => includesText(record.branch, query) || includesText(record.absolutePath, query))) return true;
1439
1704
  return view.bindings.some((binding) => sessionMatchesQuery(binding.sessionId, sessions, query));
1440
1705
  }
1706
+ function resolveCurrentSessionLocation(currentSessionId, workspaces, views) {
1707
+ if (currentSessionId === void 0) return void 0;
1708
+ const workspace = workspaces.find((candidate) => candidate.sessionIds.includes(currentSessionId));
1709
+ if (workspace === void 0) return void 0;
1710
+ const view = views.find((candidate) => candidate.workspaceId === workspace.workspaceId);
1711
+ if (view === void 0) return void 0;
1712
+ const binding = view.bindings.find((candidate) => candidate.sessionId === currentSessionId);
1713
+ if (binding === void 0) return {
1714
+ sessionId: currentSessionId,
1715
+ workspaceId: workspace.workspaceId,
1716
+ groupKey: "main:" + workspace.workspaceId,
1717
+ kind: "main"
1718
+ };
1719
+ const worktree = view.worktrees.find((candidate) => candidate.worktreeId === binding.worktreeId && candidate.workspaceId === workspace.workspaceId);
1720
+ if (worktree === void 0) return void 0;
1721
+ return {
1722
+ sessionId: currentSessionId,
1723
+ workspaceId: workspace.workspaceId,
1724
+ groupKey: "worktree:" + worktree.worktreeId,
1725
+ kind: "worktree",
1726
+ worktreeId: worktree.worktreeId
1727
+ };
1728
+ }
1729
+ function currentSessionRevealKeys(location) {
1730
+ if (location === void 0) return [];
1731
+ return [
1732
+ "workspace:" + location.workspaceId,
1733
+ location.kind === "main" ? "main:" + location.workspaceId : "worktree:" + location.worktreeId,
1734
+ "session-group:" + location.groupKey
1735
+ ];
1736
+ }
1737
+ //#endregion
1738
+ //#region lib/client/worktree-session-position.js
1739
+ function scrollCurrentSessionIntoView(root, sessionId) {
1740
+ if (root === null) return false;
1741
+ const row = Array.from(root.querySelectorAll("[data-session-id]")).find((candidate) => candidate.dataset.sessionId === sessionId);
1742
+ if (row === void 0) return false;
1743
+ row.scrollIntoView({ block: "nearest" });
1744
+ return true;
1745
+ }
1441
1746
  //#endregion
1442
1747
  //#region lib/client/worktree-surface-rows.js
1443
1748
  function rowHalf(event) {
@@ -1670,7 +1975,7 @@ window.__ModuleLoader__.load({
1670
1975
  });
1671
1976
  }
1672
1977
  /** Worktree-mode Session row with the same trailing options menu as native DSH rows. */
1673
- function WorktreeSessionRow({ t, sessionId, blank, label, drag, actionPending, onOpen, onRename, onFork, onArchive }) {
1978
+ function WorktreeSessionRow({ t, sessionId, blank, current, label, drag, actionPending, onOpen, onRename, onFork, onArchive }) {
1674
1979
  const [menuOpen, setMenuOpen] = (0, react.useState)(false);
1675
1980
  const markerClass = drag.marker === "before" ? worktree_css_default.dropBefore : drag.marker === "after" ? worktree_css_default.dropAfter : "";
1676
1981
  const sessionMenuItems = [
@@ -1697,9 +2002,11 @@ window.__ModuleLoader__.load({
1697
2002
  className: `${worktree_css_default.treeSessionRow} ${markerClass}`,
1698
2003
  "data-session-id": sessionId,
1699
2004
  "data-session-blank": blank ? "true" : void 0,
2005
+ "data-session-current": current ? "true" : void 0,
1700
2006
  "data-session-drag": drag.active ? "active" : void 0,
1701
2007
  "data-menu-open": menuOpen || void 0,
1702
2008
  role: "treeitem",
2009
+ "aria-current": current ? "true" : void 0,
1703
2010
  draggable: true,
1704
2011
  onDragStart: (event) => {
1705
2012
  event.dataTransfer.effectAllowed = "move";
@@ -1718,18 +2025,14 @@ window.__ModuleLoader__.load({
1718
2025
  event.preventDefault();
1719
2026
  drag.drop(rowHalf(event));
1720
2027
  },
1721
- children: [(0, react_jsx_runtime.jsxs)("button", {
2028
+ children: [(0, react_jsx_runtime.jsx)("button", {
1722
2029
  type: "button",
1723
2030
  className: worktree_css_default.treeSessionContent,
1724
2031
  onClick: onOpen,
1725
- children: [(0, react_jsx_runtime.jsx)("span", {
1726
- className: worktree_css_default.treeGuide,
1727
- "aria-hidden": "true",
1728
- children: "└"
1729
- }), (0, react_jsx_runtime.jsx)("span", {
2032
+ children: (0, react_jsx_runtime.jsx)("span", {
1730
2033
  className: worktree_css_default.sessionLabel,
1731
2034
  children: label
1732
- })]
2035
+ })
1733
2036
  }), !blank && (0, react_jsx_runtime.jsx)("span", {
1734
2037
  className: worktree_css_default.rowActions,
1735
2038
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
@@ -1761,13 +2064,14 @@ window.__ModuleLoader__.load({
1761
2064
  })]
1762
2065
  });
1763
2066
  }
1764
- function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, expanded, actionPending, sessions, dragState, onToggleExpanded, onStartDrag, onHoverDrag, onClearDrag, onFinishDrag, onCommitDrag, onOpen, onRename, onFork, onArchive }) {
2067
+ function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, currentSessionId, expanded, actionPending, sessions, dragState, onToggleExpanded, onStartDrag, onHoverDrag, onClearDrag, onFinishDrag, onCommitDrag, onOpen, onRename, onFork, onArchive }) {
1765
2068
  const visibleSessionIds = expanded ? sessionIds : sessionIds.slice(0, 5);
1766
2069
  const sameGroupDrag = dragState?.groupKey === groupKey;
1767
2070
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [visibleSessionIds.map((sessionId) => (0, react_jsx_runtime.jsx)(WorktreeSessionRow, {
1768
2071
  t,
1769
2072
  sessionId,
1770
2073
  blank: isBlankSession(sessionId, sessions),
2074
+ current: sessionId === currentSessionId,
1771
2075
  label: sessionLabel(sessionId, sessions, t),
1772
2076
  drag: {
1773
2077
  active: sameGroupDrag,
@@ -1831,19 +2135,31 @@ window.__ModuleLoader__.load({
1831
2135
  * Peer Worktree navigation surface. It keeps the original DSH Workspace mode
1832
2136
  * intact and renders a browser-local Workspace → Worktree → Session projection.
1833
2137
  */
1834
- function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, manager, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession }) {
2138
+ function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, expandState, manager, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession }) {
1835
2139
  const mode = effectiveViewMode(useStore((state) => state.viewMode), available && manager !== void 0);
1836
2140
  const sessions = useSessions((state) => state);
1837
2141
  const workspaces = useWorkspaces((state) => state);
2142
+ const currentSessionId = sessions.current;
1838
2143
  const workspaceIds = useStableWorkspaceIds(workspaces.items);
1839
2144
  const [readState, setReadState] = (0, react.useState)(EMPTY_READ_STATE);
2145
+ const expandSnapshot = (0, react.useSyncExternalStore)(expandState.subscribe, expandState.getSnapshot, expandState.getSnapshot);
1840
2146
  const readStateRef = (0, react.useRef)(readState);
1841
2147
  readStateRef.current = readState;
1842
2148
  const [searchQuery, setSearchQuery] = (0, react.useState)("");
1843
- const [expandedWorkspaces, setExpandedWorkspaces] = (0, react.useState)({});
1844
- const [expandedMains, setExpandedMains] = (0, react.useState)({});
1845
- const [expandedWorktrees, setExpandedWorktrees] = (0, react.useState)({});
2149
+ const [currentSessionReveal, setCurrentSessionReveal] = (0, react.useState)();
2150
+ const searchQueryRef = (0, react.useRef)(searchQuery);
2151
+ searchQueryRef.current = searchQuery;
2152
+ const locateGenerationRef = (0, react.useRef)(0);
2153
+ const positionedLocateGenerationRef = (0, react.useRef)();
1846
2154
  const [worktreeModalWorkspaceId, setWorktreeModalWorkspaceId] = (0, react.useState)();
2155
+ const [modalReadError, setModalReadError] = (0, react.useState)();
2156
+ const [modalReadLoading, setModalReadLoading] = (0, react.useState)(false);
2157
+ const [worktreeModalMode, setWorktreeModalMode] = (0, react.useState)("create");
2158
+ const [importCandidates, setImportCandidates] = (0, react.useState)({
2159
+ status: "idle",
2160
+ candidates: []
2161
+ });
2162
+ const [selectedImportPath, setSelectedImportPath] = (0, react.useState)();
1847
2163
  const [openWorkspaceMenuId, setOpenWorkspaceMenuId] = (0, react.useState)();
1848
2164
  const [openWorktreeMenuId, setOpenWorktreeMenuId] = (0, react.useState)();
1849
2165
  const [worktreeRemoval, setWorktreeRemoval] = (0, react.useState)();
@@ -1871,6 +2187,11 @@ window.__ModuleLoader__.load({
1871
2187
  const [worktreeDrag, setWorktreeDrag] = (0, react.useState)();
1872
2188
  const worktreeDropCommitted = (0, react.useRef)(false);
1873
2189
  const refreshGuard = (0, react.useRef)(createWorktreeRefreshGuard());
2190
+ const modalReadLoader = (0, react.useRef)(createWorktreeModalViewLoader());
2191
+ const modalReadViewRef = (0, react.useRef)();
2192
+ const importCandidatesGuard = (0, react.useRef)(createWorktreeRefreshGuard());
2193
+ const modalWorkspaceIdRef = (0, react.useRef)(worktreeModalWorkspaceId);
2194
+ modalWorkspaceIdRef.current = worktreeModalWorkspaceId;
1874
2195
  const { ref, width, bounds } = useSidebarOverlayGeometry(mode === "worktree");
1875
2196
  const collapsed = width <= 64;
1876
2197
  const query = searchQuery.trim().toLocaleLowerCase();
@@ -1893,13 +2214,13 @@ window.__ModuleLoader__.load({
1893
2214
  }), (views) => {
1894
2215
  setReadState({
1895
2216
  status: "ready",
1896
- views
2217
+ views: modalReadViewRef.current === void 0 ? views : mergeWorktreeView(views, modalReadViewRef.current)
1897
2218
  });
1898
2219
  }, (error) => {
1899
2220
  if (preserveCurrent) throw error;
1900
2221
  setReadState({
1901
2222
  status: "error",
1902
- views: [],
2223
+ views: modalReadViewRef.current === void 0 ? [] : [modalReadViewRef.current],
1903
2224
  error: toWorktreeViewError(error)
1904
2225
  });
1905
2226
  });
@@ -1908,10 +2229,39 @@ window.__ModuleLoader__.load({
1908
2229
  manager,
1909
2230
  workspaceIds
1910
2231
  ]);
2232
+ const loadModalWorktreeView = (0, react.useCallback)((workspaceId) => {
2233
+ setModalReadError(void 0);
2234
+ setModalReadLoading(true);
2235
+ if (manager === void 0) {
2236
+ setModalReadLoading(false);
2237
+ setModalReadError({
2238
+ code: "WORKTREE_VIEW_UNAVAILABLE",
2239
+ message: "",
2240
+ retryable: true
2241
+ });
2242
+ return;
2243
+ }
2244
+ modalReadLoader.current.load(manager, workspaceId, (view) => {
2245
+ modalReadViewRef.current = view;
2246
+ setModalReadLoading(false);
2247
+ setReadState((current) => ({
2248
+ ...current,
2249
+ views: mergeWorktreeView(current.views, view)
2250
+ }));
2251
+ }, (error) => {
2252
+ setModalReadLoading(false);
2253
+ setModalReadError(toWorktreeViewError(error));
2254
+ });
2255
+ }, [manager]);
1911
2256
  (0, react.useEffect)(() => {
1912
2257
  if (mode === "worktree") refresh({ preserveCurrent: readStateRef.current.status === "ready" });
1913
2258
  else {
1914
2259
  refreshGuard.current.invalidate();
2260
+ modalReadLoader.current.invalidate();
2261
+ modalReadViewRef.current = void 0;
2262
+ setWorktreeModalWorkspaceId(void 0);
2263
+ setModalReadError(void 0);
2264
+ setModalReadLoading(false);
1915
2265
  setReadState(EMPTY_READ_STATE);
1916
2266
  }
1917
2267
  }, [mode, refresh]);
@@ -1927,18 +2277,76 @@ window.__ModuleLoader__.load({
1927
2277
  syncSessionWorkspaces
1928
2278
  ]);
1929
2279
  const viewByWorkspace = (0, react.useMemo)(() => new Map(readState.views.map((view) => [view.workspaceId, view])), [readState.views]);
2280
+ const currentSessionLocation = (0, react.useMemo)(() => readState.status === "ready" ? resolveCurrentSessionLocation(currentSessionId, workspaces.items, readState.views) : void 0, [
2281
+ currentSessionId,
2282
+ readState.status,
2283
+ readState.views,
2284
+ workspaces.items
2285
+ ]);
2286
+ const currentRevealKeys = (0, react.useMemo)(() => new Set(currentSessionRevealKeys(currentSessionLocation)), [currentSessionLocation]);
2287
+ const isCurrentSessionReveal = (key) => currentSessionReveal !== void 0 && currentSessionReveal.sessionId === currentSessionId && currentRevealKeys.has(key) && currentSessionReveal.suppressedKeys[key] !== true;
2288
+ (0, react.useLayoutEffect)(() => {
2289
+ locateGenerationRef.current += 1;
2290
+ positionedLocateGenerationRef.current = void 0;
2291
+ if (mode !== "worktree") {
2292
+ setCurrentSessionReveal(void 0);
2293
+ return;
2294
+ }
2295
+ if (searchQueryRef.current.trim().length > 0) setSearchQuery("");
2296
+ setCurrentSessionReveal(currentSessionId === void 0 ? void 0 : {
2297
+ sessionId: currentSessionId,
2298
+ suppressedKeys: {}
2299
+ });
2300
+ }, [currentSessionId, mode]);
2301
+ (0, react.useLayoutEffect)(() => {
2302
+ if (mode !== "worktree" || currentSessionId === void 0 || currentSessionLocation === void 0) return;
2303
+ const generation = locateGenerationRef.current;
2304
+ if (positionedLocateGenerationRef.current === generation) return;
2305
+ let cancelled = false;
2306
+ const frame = requestAnimationFrame(() => {
2307
+ if (cancelled || generation !== locateGenerationRef.current) return;
2308
+ if (!scrollCurrentSessionIntoView(ref.current, currentSessionId)) return;
2309
+ positionedLocateGenerationRef.current = generation;
2310
+ });
2311
+ return () => {
2312
+ cancelled = true;
2313
+ cancelAnimationFrame(frame);
2314
+ };
2315
+ }, [
2316
+ currentSessionId,
2317
+ currentSessionLocation,
2318
+ currentSessionReveal,
2319
+ expandSnapshot,
2320
+ mode,
2321
+ query,
2322
+ readState.status
2323
+ ]);
2324
+ (0, react.useEffect)(() => {
2325
+ if (readState.status !== "ready" || !isCompleteWorktreeWorkspaceSnapshot(workspaceIds, readState.views)) return;
2326
+ expandState.actions.retain(workspaceIds, readState.views.flatMap((view) => view.worktrees.map((record) => record.worktreeId)));
2327
+ }, [
2328
+ expandState,
2329
+ readState.status,
2330
+ readState.views,
2331
+ workspaceIds
2332
+ ]);
1930
2333
  const modalWorkspace = workspaces.items.find((workspace) => workspace.workspaceId === worktreeModalWorkspaceId);
1931
2334
  const modalView = worktreeModalWorkspaceId === void 0 ? void 0 : viewByWorkspace.get(worktreeModalWorkspaceId);
1932
2335
  const modalReadiness = modalView?.readiness;
1933
2336
  const modalSetupStatus = modalView === void 0 ? void 0 : modalReadiness?.status === "ready" ? modalView.branches.length === 0 ? "noLocalBranch" : void 0 : modalReadiness?.status;
1934
- const modalCanCreate = modalSetupStatus === void 0 && modalReadiness?.status === "ready";
2337
+ const modalCanCreate = !modalReadLoading && modalSetupStatus === void 0 && modalReadiness?.status === "ready";
1935
2338
  (0, react.useEffect)(() => {
1936
2339
  if (worktreeModalWorkspaceId === void 0 || modalView === void 0) return;
1937
2340
  if (modalView.readiness.status !== "ready") {
1938
2341
  setSelectedBranch("");
2342
+ setNewBranch("");
1939
2343
  return;
1940
2344
  }
1941
2345
  setSelectedBranch((current) => reconcileBaseBranchSelection(current, modalView.branches));
2346
+ setNewBranch((current) => {
2347
+ if (current.length > 0) return current;
2348
+ return createDefaultWorktreeName([...modalView.branches.map((branch) => branch.name), ...modalView.worktrees.map((worktree) => worktree.branch)]);
2349
+ });
1942
2350
  }, [modalView, worktreeModalWorkspaceId]);
1943
2351
  const runMutation = async (operation) => {
1944
2352
  setActionPending(true);
@@ -1952,6 +2360,27 @@ window.__ModuleLoader__.load({
1952
2360
  setActionPending(false);
1953
2361
  }
1954
2362
  };
2363
+ const loadImportCandidates = (0, react.useCallback)(async (workspaceId) => {
2364
+ if (manager === void 0) return;
2365
+ setImportCandidates((current) => ({
2366
+ status: "loading",
2367
+ candidates: current.candidates
2368
+ }));
2369
+ await importCandidatesGuard.current.run(() => manager.listImportCandidates({ workspaceId }), (candidates) => {
2370
+ if (modalWorkspaceIdRef.current !== workspaceId) return;
2371
+ setImportCandidates({
2372
+ status: "ready",
2373
+ candidates
2374
+ });
2375
+ }, (error) => {
2376
+ if (modalWorkspaceIdRef.current !== workspaceId) return;
2377
+ setImportCandidates((current) => ({
2378
+ status: "error",
2379
+ candidates: current.candidates,
2380
+ error: toWorktreeViewError(error)
2381
+ }));
2382
+ });
2383
+ }, [manager]);
1955
2384
  const workspaceRenameTrimmed = workspaceRenameDraft.trim();
1956
2385
  const workspaceRenameDuplicate = workspaceRenameTarget !== void 0 && workspaceRenameTrimmed.length > 0 && workspaces.items.some((workspace) => workspace.workspaceId !== workspaceRenameTarget.workspaceId && workspace.title === workspaceRenameTrimmed);
1957
2386
  const workspaceRenameBlocked = workspaceRenamePending || workspaceRenameTarget === void 0 || workspaceRenameTrimmed.length === 0 || workspaceRenameTrimmed === workspaceRenameTarget?.currentTitle || workspaceRenameDuplicate;
@@ -2134,80 +2563,172 @@ window.__ModuleLoader__.load({
2134
2563
  if (archiveSession === void 0) return;
2135
2564
  await runMutation(() => archiveSession(sessionId));
2136
2565
  };
2566
+ const clearSessionGroups = (groupKeys) => {
2567
+ if (groupKeys.length === 0) return;
2568
+ setExpandedSessionGroups((current) => clearSessionGroupExpansion(current, groupKeys));
2569
+ };
2570
+ const suppressCurrentSessionReveal = (key) => {
2571
+ if (!isCurrentSessionReveal(key)) return false;
2572
+ setCurrentSessionReveal((current) => {
2573
+ if (current === void 0 || current.sessionId !== currentSessionId) return current;
2574
+ return {
2575
+ ...current,
2576
+ suppressedKeys: {
2577
+ ...current.suppressedKeys,
2578
+ [key]: true
2579
+ }
2580
+ };
2581
+ });
2582
+ return true;
2583
+ };
2137
2584
  const toggleWorkspace = (workspaceId) => {
2138
- setExpandedWorkspaces((current) => ({
2139
- ...current,
2140
- [workspaceId]: current[workspaceId] === false
2141
- }));
2585
+ const persistedExpanded = isWorkspaceExpanded(expandSnapshot, workspaceId);
2586
+ const autoExpanded = isCurrentSessionReveal("workspace:" + workspaceId);
2587
+ const visuallyExpanded = persistedExpanded || autoExpanded;
2588
+ if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("workspace:" + workspaceId);
2589
+ if (visuallyExpanded && !persistedExpanded) {
2590
+ clearSessionGroups(["main:" + workspaceId, ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => "worktree:" + worktreeId)]);
2591
+ return;
2592
+ }
2593
+ expandState.actions.toggleWorkspace(workspaceId);
2594
+ if (visuallyExpanded) clearSessionGroups(["main:" + workspaceId, ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => "worktree:" + worktreeId)]);
2142
2595
  };
2143
2596
  const toggleMain = (workspaceId) => {
2144
- setExpandedMains((current) => ({
2145
- ...current,
2146
- [workspaceId]: current[workspaceId] === false
2147
- }));
2597
+ const persistedExpanded = isMainExpanded(expandSnapshot, workspaceId);
2598
+ const autoExpanded = isCurrentSessionReveal("main:" + workspaceId);
2599
+ const visuallyExpanded = persistedExpanded || autoExpanded;
2600
+ if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("main:" + workspaceId);
2601
+ if (visuallyExpanded && !persistedExpanded) {
2602
+ clearSessionGroups(["main:" + workspaceId]);
2603
+ return;
2604
+ }
2605
+ expandState.actions.toggleMain(workspaceId);
2606
+ if (visuallyExpanded) clearSessionGroups(["main:" + workspaceId]);
2148
2607
  };
2149
2608
  const toggleWorktree = (worktreeId) => {
2150
- setExpandedWorktrees((current) => ({
2609
+ const persistedExpanded = isWorktreeExpanded(expandSnapshot, worktreeId);
2610
+ const autoExpanded = isCurrentSessionReveal("worktree:" + worktreeId);
2611
+ const visuallyExpanded = persistedExpanded || autoExpanded;
2612
+ if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("worktree:" + worktreeId);
2613
+ if (visuallyExpanded && !persistedExpanded) {
2614
+ clearSessionGroups(["worktree:" + worktreeId]);
2615
+ return;
2616
+ }
2617
+ expandState.actions.toggleWorktree(worktreeId);
2618
+ if (visuallyExpanded) clearSessionGroups(["worktree:" + worktreeId]);
2619
+ };
2620
+ const toggleSessionGroup = (groupKey) => {
2621
+ const autoExpanded = isCurrentSessionReveal("session-group:" + groupKey);
2622
+ const transientExpanded = expandedSessionGroups[groupKey] === true;
2623
+ if (autoExpanded) {
2624
+ suppressCurrentSessionReveal("session-group:" + groupKey);
2625
+ setExpandedSessionGroups((current) => {
2626
+ const next = { ...current };
2627
+ delete next[groupKey];
2628
+ return next;
2629
+ });
2630
+ return;
2631
+ }
2632
+ setExpandedSessionGroups((current) => ({
2151
2633
  ...current,
2152
- [worktreeId]: current[worktreeId] === false
2634
+ [groupKey]: !transientExpanded
2153
2635
  }));
2154
2636
  };
2637
+ const closeWorktreeCreator = (force = false) => {
2638
+ if (actionPending && !force) return;
2639
+ modalReadLoader.current.invalidate();
2640
+ modalReadViewRef.current = void 0;
2641
+ importCandidatesGuard.current.invalidate();
2642
+ setWorktreeModalWorkspaceId(void 0);
2643
+ setModalReadError(void 0);
2644
+ setModalReadLoading(false);
2645
+ };
2155
2646
  const openWorktreeCreator = (workspace) => {
2156
2647
  const view = viewByWorkspace.get(workspace.workspaceId);
2157
- const baseBranch = selectDefaultBaseBranch(view?.branches ?? []);
2158
- const existingNames = [...(view?.branches ?? []).map((branch) => branch.name), ...(view?.worktrees ?? []).map((worktree) => worktree.branch)];
2648
+ modalReadLoader.current.invalidate();
2649
+ modalReadViewRef.current = void 0;
2650
+ importCandidatesGuard.current.invalidate();
2159
2651
  setWorktreeModalWorkspaceId(workspace.workspaceId);
2160
- setSelectedBranch(baseBranch);
2161
- setNewBranch(createDefaultWorktreeName(existingNames));
2652
+ setWorktreeModalMode("create");
2653
+ setImportCandidates({
2654
+ status: "idle",
2655
+ candidates: []
2656
+ });
2657
+ setSelectedImportPath(void 0);
2162
2658
  setActionError(void 0);
2659
+ setModalReadError(void 0);
2660
+ setModalReadLoading(false);
2661
+ if (view === void 0) {
2662
+ setSelectedBranch("");
2663
+ setNewBranch("");
2664
+ loadModalWorktreeView(workspace.workspaceId);
2665
+ return;
2666
+ }
2667
+ setSelectedBranch(selectDefaultBaseBranch(view.branches));
2668
+ setNewBranch(createDefaultWorktreeName([...view.branches.map((branch) => branch.name), ...view.worktrees.map((worktree) => worktree.branch)]));
2669
+ };
2670
+ const changeWorktreeModalMode = (mode) => {
2671
+ setWorktreeModalMode(mode);
2672
+ if (mode === "import" && worktreeModalWorkspaceId !== void 0 && importCandidates.status === "idle") loadImportCandidates(worktreeModalWorkspaceId);
2673
+ };
2674
+ const continueWorktreeRegistration = async (registeredWorktree) => {
2675
+ closeWorktreeCreator(true);
2676
+ if (createSessionCallback === void 0) {
2677
+ await refresh({ preserveCurrent: true });
2678
+ setActionError({
2679
+ code: "WORKTREE_REGISTRATION_SESSION_UNAVAILABLE",
2680
+ message: "",
2681
+ retryable: true
2682
+ });
2683
+ return;
2684
+ }
2685
+ const sessionInput = {
2686
+ workspaceId: registeredWorktree.workspaceId,
2687
+ worktreeId: registeredWorktree.worktreeId,
2688
+ cwd: registeredWorktree.absolutePath
2689
+ };
2690
+ try {
2691
+ await createSessionCallback(sessionInput);
2692
+ await invalidateWorktreeContext?.(registeredWorktree.workspaceId);
2693
+ } catch (error) {
2694
+ if (error instanceof WorktreeSessionBindingError && error.retryable) setPendingSessionBinding({
2695
+ ...sessionInput,
2696
+ sessionId: error.sessionId
2697
+ });
2698
+ throw error;
2699
+ }
2700
+ await refresh({ preserveCurrent: true });
2163
2701
  };
2164
2702
  const submitWorktree = async () => {
2165
2703
  const worktreeName = newBranch.trim();
2166
- if (manager === void 0 || modalWorkspace === void 0 || !modalCanCreate || selectedBranch.length === 0 || worktreeName.length === 0) return;
2167
- const input = {
2168
- workspaceId: modalWorkspace.workspaceId,
2169
- branch: selectedBranch,
2170
- newBranch: worktreeName
2171
- };
2704
+ const selectedImportCandidate = importCandidates.candidates.find((candidate) => candidate.absolutePath === selectedImportPath);
2705
+ if (manager === void 0 || modalWorkspace === void 0) return;
2706
+ if (worktreeModalMode === "create" && (!modalCanCreate || selectedBranch.length === 0 || worktreeName.length === 0)) return;
2707
+ if (worktreeModalMode === "import" && selectedImportCandidate === void 0) return;
2172
2708
  setActionPending(true);
2173
2709
  setActionError(void 0);
2174
2710
  setPendingSessionBinding(void 0);
2175
2711
  try {
2176
- const createdWorktree = await executeWorktreeAction(manager, {
2712
+ const registeredWorktree = worktreeModalMode === "create" ? await executeWorktreeAction(manager, {
2177
2713
  type: "createWorktree",
2178
- input
2714
+ input: {
2715
+ workspaceId: modalWorkspace.workspaceId,
2716
+ branch: selectedBranch,
2717
+ newBranch: worktreeName
2718
+ }
2719
+ }) : await executeWorktreeAction(manager, {
2720
+ type: "importWorktree",
2721
+ input: {
2722
+ workspaceId: modalWorkspace.workspaceId,
2723
+ absolutePath: selectedImportCandidate.absolutePath
2724
+ }
2179
2725
  });
2180
- if (createdWorktree === void 0) throw {
2726
+ if (registeredWorktree === void 0) throw {
2181
2727
  code: "WORKTREE_RECORD_MISSING",
2182
2728
  message: "",
2183
2729
  retryable: true
2184
2730
  };
2185
- setWorktreeModalWorkspaceId(void 0);
2186
- if (createSessionCallback === void 0) {
2187
- await refresh({ preserveCurrent: true });
2188
- setActionError({
2189
- code: "WORKTREE_CREATED_SESSION_UNAVAILABLE",
2190
- message: "",
2191
- retryable: true
2192
- });
2193
- return;
2194
- }
2195
- const sessionInput = {
2196
- workspaceId: createdWorktree.workspaceId,
2197
- worktreeId: createdWorktree.worktreeId,
2198
- cwd: createdWorktree.absolutePath
2199
- };
2200
- try {
2201
- await createSessionCallback(sessionInput);
2202
- await invalidateWorktreeContext?.(createdWorktree.workspaceId);
2203
- } catch (error) {
2204
- if (error instanceof WorktreeSessionBindingError && error.retryable) setPendingSessionBinding({
2205
- ...sessionInput,
2206
- sessionId: error.sessionId
2207
- });
2208
- throw error;
2209
- }
2210
- await refresh({ preserveCurrent: true });
2731
+ await continueWorktreeRegistration(registeredWorktree);
2211
2732
  } catch (error) {
2212
2733
  setActionError(toWorktreeViewError(error));
2213
2734
  } finally {
@@ -2411,13 +2932,15 @@ window.__ModuleLoader__.load({
2411
2932
  const view = viewByWorkspace.get(workspace.workspaceId);
2412
2933
  const currentBranch = view?.branches.find((branch) => branch.isCurrent)?.name;
2413
2934
  const mainLabel = currentBranch === void 0 ? t("worktree.main") : t("worktree.mainWithBranch", { branch: currentBranch });
2414
- const expanded = expandedWorkspaces[workspace.workspaceId] !== false;
2935
+ const expanded = isWorkspaceExpanded(expandSnapshot, workspace.workspaceId) || isCurrentSessionReveal("workspace:" + workspace.workspaceId);
2415
2936
  const workspaceMatchesQuery = includesText(workspace.title, query);
2416
2937
  const allWorkspaceSessionIds = filterArchivedSessionIds(workspaceSessionIds(workspaces, workspace.workspaceId, sessions.ids), archivedSessionIds);
2417
2938
  const bindings = view?.bindings ?? [];
2418
2939
  const visibleMainSessionIds = filterVisibleSessionIds(unboundSessionIds(allWorkspaceSessionIds, [...new Set(bindings.map((binding) => binding.sessionId))]), sessions).filter((sessionId) => workspaceMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
2419
- const mainExpanded = expandedMains[workspace.workspaceId] !== false;
2940
+ const mainExpanded = isMainExpanded(expandSnapshot, workspace.workspaceId) || isCurrentSessionReveal("main:" + workspace.workspaceId);
2420
2941
  const mainGroupKey = `main:${workspace.workspaceId}`;
2942
+ const sessionIds = visibleMainSessionIds;
2943
+ const mainSessionGroupExpanded = expandedSessionGroups[mainGroupKey] === true || sessionIds.length > 5 && isCurrentSessionReveal("session-group:" + mainGroupKey);
2421
2944
  const worktrees = view?.worktrees ?? [];
2422
2945
  const sameWorkspaceWorktreeDrag = worktreeDrag?.workspaceId === workspace.workspaceId;
2423
2946
  return (0, react_jsx_runtime.jsxs)("section", {
@@ -2496,17 +3019,15 @@ window.__ModuleLoader__.load({
2496
3019
  mainExpanded && (0, react_jsx_runtime.jsx)(WorktreeSessionGroup, {
2497
3020
  t,
2498
3021
  groupKey: mainGroupKey,
2499
- sessionIds: visibleMainSessionIds,
3022
+ sessionIds,
2500
3023
  workspaceId: workspace.workspaceId,
2501
- expanded: expandedSessionGroups[mainGroupKey] === true,
3024
+ currentSessionId,
3025
+ expanded: mainSessionGroupExpanded,
2502
3026
  actionPending,
2503
3027
  sessions,
2504
3028
  dragState: sessionDrag,
2505
3029
  onToggleExpanded: () => {
2506
- setExpandedSessionGroups((current) => ({
2507
- ...current,
2508
- [mainGroupKey]: current[mainGroupKey] !== true
2509
- }));
3030
+ toggleSessionGroup(mainGroupKey);
2510
3031
  },
2511
3032
  onStartDrag: (groupKey, sessionId) => {
2512
3033
  sessionDropCommitted.current = false;
@@ -2549,9 +3070,11 @@ window.__ModuleLoader__.load({
2549
3070
  if (query.length > 0 && !worktreeMatchesQuery && !worktreeSessionIds.some((sessionId) => sessionMatchesQuery(sessionId, sessions, query))) return null;
2550
3071
  const visibleWorktreeSessionIds = worktreeSessionIds.filter((sessionId) => worktreeMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
2551
3072
  const worktreeGroupKey = `worktree:${record.worktreeId}`;
3073
+ const sessionIds = visibleWorktreeSessionIds;
3074
+ const sessionGroupExpanded = expandedSessionGroups[worktreeGroupKey] === true || sessionIds.length > 5 && isCurrentSessionReveal("session-group:" + worktreeGroupKey);
2552
3075
  const state = record.status === "removed" ? "warning" : record.health === "repair" ? "error" : "done";
2553
3076
  const stateLabel = record.status === "removed" ? t("worktree.detached") : record.health === "repair" ? t("worktree.repair") : t("worktree.ready");
2554
- const worktreeExpanded = expandedWorktrees[record.worktreeId] !== false;
3077
+ const worktreeExpanded = isWorktreeExpanded(expandSnapshot, record.worktreeId) || isCurrentSessionReveal("worktree:" + record.worktreeId);
2555
3078
  return (0, react_jsx_runtime.jsxs)("div", {
2556
3079
  className: worktree_css_default.worktreeGroup,
2557
3080
  "data-worktree-id": record.worktreeId,
@@ -2622,17 +3145,15 @@ window.__ModuleLoader__.load({
2622
3145
  }), worktreeExpanded && (0, react_jsx_runtime.jsx)(WorktreeSessionGroup, {
2623
3146
  t,
2624
3147
  groupKey: worktreeGroupKey,
2625
- sessionIds: visibleWorktreeSessionIds,
3148
+ sessionIds,
2626
3149
  workspaceId: workspace.workspaceId,
2627
- expanded: expandedSessionGroups[worktreeGroupKey] === true,
3150
+ currentSessionId,
3151
+ expanded: sessionGroupExpanded,
2628
3152
  actionPending,
2629
3153
  sessions,
2630
3154
  dragState: sessionDrag,
2631
3155
  onToggleExpanded: () => {
2632
- setExpandedSessionGroups((current) => ({
2633
- ...current,
2634
- [worktreeGroupKey]: current[worktreeGroupKey] !== true
2635
- }));
3156
+ toggleSessionGroup(worktreeGroupKey);
2636
3157
  },
2637
3158
  onStartDrag: (groupKey, sessionId) => {
2638
3159
  sessionDropCommitted.current = false;
@@ -2676,18 +3197,6 @@ window.__ModuleLoader__.load({
2676
3197
  })
2677
3198
  ]
2678
3199
  }),
2679
- (0, react_jsx_runtime.jsx)("div", {
2680
- className: worktree_css_default.railContent,
2681
- children: (0, react_jsx_runtime.jsx)("button", {
2682
- type: "button",
2683
- className: worktree_css_default.railButton,
2684
- "aria-label": t("mode.exit"),
2685
- onClick: () => {
2686
- actions.setViewMode("workspace-session");
2687
- },
2688
- children: "WT"
2689
- })
2690
- }),
2691
3200
  (0, react_jsx_runtime.jsx)(WorktreeSessionRenameDialog, {
2692
3201
  t,
2693
3202
  target: sessionRenameTarget,
@@ -2727,14 +3236,28 @@ window.__ModuleLoader__.load({
2727
3236
  t,
2728
3237
  workspace: modalWorkspace,
2729
3238
  view: modalView,
3239
+ readError: modalReadError,
2730
3240
  setupStatus: modalSetupStatus,
2731
3241
  canCreate: modalCanCreate,
3242
+ mode: worktreeModalMode,
3243
+ importCandidates,
3244
+ selectedImportPath,
2732
3245
  selectedBranch,
2733
3246
  newBranch,
2734
3247
  actionPending,
2735
- onClose: () => {
2736
- setWorktreeModalWorkspaceId(void 0);
3248
+ onClose: closeWorktreeCreator,
3249
+ onRetry: () => {
3250
+ if (worktreeModalWorkspaceId === void 0) return;
3251
+ modalReadViewRef.current = void 0;
3252
+ setSelectedBranch("");
3253
+ setNewBranch("");
3254
+ loadModalWorktreeView(worktreeModalWorkspaceId);
2737
3255
  },
3256
+ onModeChange: changeWorktreeModalMode,
3257
+ onRetryImportCandidates: () => {
3258
+ if (worktreeModalWorkspaceId !== void 0) loadImportCandidates(worktreeModalWorkspaceId);
3259
+ },
3260
+ onSelectedImportPathChange: setSelectedImportPath,
2738
3261
  onSelectedBranchChange: setSelectedBranch,
2739
3262
  onNewBranchChange: setNewBranch,
2740
3263
  onSubmit: submitWorktree
@@ -2848,6 +3371,28 @@ window.__ModuleLoader__.load({
2848
3371
  let scheduleTicket = 0;
2849
3372
  let scheduledCompletion;
2850
3373
  let latestRefresh = Promise.resolve();
3374
+ const viewCache = /* @__PURE__ */ new Map();
3375
+ let lastObservedIdentity;
3376
+ const sameIdentity = (left, right) => left?.sessionId === right.sessionId && left?.workspaceId === right.workspaceId;
3377
+ const workspaceTitleFor = (workspaceId) => input.workspaces.getSnapshot().items.find((candidate) => candidate.workspaceId === workspaceId)?.title;
3378
+ const valueFrom = (identity, data) => resolveWorktreeSessionContext({
3379
+ currentSessionId: identity.sessionId,
3380
+ currentWorkspaceId: identity.workspaceId,
3381
+ workspaces: input.workspaces.getSnapshot().items,
3382
+ branches: data.branches,
3383
+ worktrees: data.worktrees,
3384
+ bindings: data.bindings
3385
+ });
3386
+ const syncWorkspaceTitle = (identity) => {
3387
+ const current = store.getSnapshot();
3388
+ if (current.sessionId !== identity.sessionId || current.workspaceId !== identity.workspaceId || identity.workspaceId === void 0) return;
3389
+ const workspaceTitle = workspaceTitleFor(identity.workspaceId);
3390
+ if (current.workspaceTitle === workspaceTitle) return;
3391
+ store.set({
3392
+ ...current,
3393
+ workspaceTitle
3394
+ });
3395
+ };
2851
3396
  const setPending = (identity) => {
2852
3397
  if (identity.workspaceId === void 0) {
2853
3398
  store.set({
@@ -2863,12 +3408,22 @@ window.__ModuleLoader__.load({
2863
3408
  });
2864
3409
  return;
2865
3410
  }
2866
- const workspace = input.workspaces.getSnapshot().items.find((candidate) => candidate.workspaceId === identity.workspaceId);
3411
+ const cachedView = viewCache.get(identity.workspaceId);
3412
+ if (cachedView !== void 0) {
3413
+ store.set({
3414
+ status: "ready",
3415
+ ...identity.sessionId === void 0 ? {} : { sessionId: identity.sessionId },
3416
+ workspaceId: identity.workspaceId,
3417
+ workspaceTitle: workspaceTitleFor(identity.workspaceId),
3418
+ value: valueFrom(identity, cachedView)
3419
+ });
3420
+ return;
3421
+ }
2867
3422
  store.set({
2868
3423
  status: "loading",
2869
3424
  ...identity.sessionId === void 0 ? {} : { sessionId: identity.sessionId },
2870
3425
  workspaceId: identity.workspaceId,
2871
- workspaceTitle: workspace?.title,
3426
+ workspaceTitle: workspaceTitleFor(identity.workspaceId),
2872
3427
  value: notReady()
2873
3428
  });
2874
3429
  };
@@ -2881,6 +3436,7 @@ window.__ModuleLoader__.load({
2881
3436
  if (disposed) return;
2882
3437
  const requestGeneration = ++generation;
2883
3438
  const identity = identityFrom(input.sessions, input.workspaces);
3439
+ lastObservedIdentity = identity;
2884
3440
  setPending(identity);
2885
3441
  if (identity.workspaceId === void 0) return;
2886
3442
  const request = {
@@ -2902,19 +3458,13 @@ window.__ModuleLoader__.load({
2902
3458
  });
2903
3459
  return;
2904
3460
  }
3461
+ if (data.readiness.status === "ready") viewCache.set(request.workspaceId, data);
2905
3462
  store.set({
2906
3463
  status: "ready",
2907
3464
  ...request.sessionId === void 0 ? {} : { sessionId: request.sessionId },
2908
3465
  workspaceId: request.workspaceId,
2909
3466
  workspaceTitle: workspace?.title,
2910
- value: resolveWorktreeSessionContext({
2911
- currentSessionId: request.sessionId,
2912
- currentWorkspaceId: request.workspaceId,
2913
- workspaces: input.workspaces.getSnapshot().items,
2914
- branches: data.branches,
2915
- worktrees: data.worktrees,
2916
- bindings: data.bindings
2917
- })
3467
+ value: valueFrom(request, data)
2918
3468
  });
2919
3469
  } catch (error) {
2920
3470
  if (!matchesCurrent(request, requestGeneration)) return;
@@ -2937,15 +3487,22 @@ window.__ModuleLoader__.load({
2937
3487
  };
2938
3488
  const refresh = () => {
2939
3489
  cancelScheduledRefresh();
3490
+ lastObservedIdentity = identityFrom(input.sessions, input.workspaces);
2940
3491
  const completion = runRefresh();
2941
3492
  latestRefresh = completion;
2942
3493
  return completion;
2943
3494
  };
2944
3495
  const scheduleRefresh = () => {
2945
3496
  if (disposed) return;
3497
+ const identity = identityFrom(input.sessions, input.workspaces);
3498
+ if (sameIdentity(lastObservedIdentity, identity)) {
3499
+ syncWorkspaceTitle(identity);
3500
+ return;
3501
+ }
3502
+ lastObservedIdentity = identity;
2946
3503
  generation += 1;
3504
+ setPending(identity);
2947
3505
  if (scheduled) return;
2948
- setPending(identityFrom(input.sessions, input.workspaces));
2949
3506
  scheduled = true;
2950
3507
  const ticket = ++scheduleTicket;
2951
3508
  const completion = scheduledRefresh();
@@ -2992,6 +3549,7 @@ window.__ModuleLoader__.load({
2992
3549
  cancelScheduledRefresh();
2993
3550
  unsubscribeSessions();
2994
3551
  unsubscribeWorkspaces();
3552
+ viewCache.clear();
2995
3553
  store.set({
2996
3554
  status: "idle",
2997
3555
  value: notReady()
@@ -3123,6 +3681,7 @@ window.__ModuleLoader__.load({
3123
3681
  ctx.effect(() => () => contextProjection.dispose(), "clutch-dsh-worktree: Session context cleanup");
3124
3682
  contextProjection.refresh();
3125
3683
  const viewStore = createWorktreeViewStore();
3684
+ const expandState = createWorktreeExpandStateStore(_deepseek_ai_dsh_client_runtime_client.createSnapshotStore);
3126
3685
  const ensureSessionWorkspace = (workspaceId, sessionId) => {
3127
3686
  virtualWorkspaceMembership.ensure({
3128
3687
  workspaceId,
@@ -3164,6 +3723,7 @@ window.__ModuleLoader__.load({
3164
3723
  locale: WORKTREE_NS,
3165
3724
  inject: () => ({
3166
3725
  available: true,
3726
+ expandState,
3167
3727
  hooks: { worktreeContext: contextProjection.store },
3168
3728
  manager,
3169
3729
  createWorkspace: async () => {