@cerbur/clutch-dsh-worktree 0.1.12 → 0.1.13

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 (230) hide show
  1. package/README.md +290 -433
  2. package/README.zh.md +244 -348
  3. package/assets/screenshots/screenshots-dashboard.png +0 -0
  4. package/assets/screenshots/screenshots-git-reviewer.png +0 -0
  5. package/lib/client/WorktreeSurface.d.ts.map +1 -1
  6. package/lib/client/WorktreeSurface.js +139 -17
  7. package/lib/client/WorktreeSurface.js.map +1 -1
  8. package/lib/client/context/WorktreeHeroContext.d.ts +4 -3
  9. package/lib/client/context/WorktreeHeroContext.d.ts.map +1 -1
  10. package/lib/client/context/WorktreeHeroContext.js +29 -11
  11. package/lib/client/context/WorktreeHeroContext.js.map +1 -1
  12. package/lib/client/dashboard/WorktreeDashboard.d.ts +9 -2
  13. package/lib/client/dashboard/WorktreeDashboard.d.ts.map +1 -1
  14. package/lib/client/dashboard/WorktreeDashboard.js +165 -14
  15. package/lib/client/dashboard/WorktreeDashboard.js.map +1 -1
  16. package/lib/client/dashboard/dashboard-navigation.d.ts +35 -0
  17. package/lib/client/dashboard/dashboard-navigation.d.ts.map +1 -0
  18. package/lib/client/dashboard/dashboard-navigation.js +48 -0
  19. package/lib/client/dashboard/dashboard-navigation.js.map +1 -0
  20. package/lib/client/dashboard/dashboard-overlay.d.ts +7 -2
  21. package/lib/client/dashboard/dashboard-overlay.d.ts.map +1 -1
  22. package/lib/client/dashboard/dashboard-overlay.js +81 -16
  23. package/lib/client/dashboard/dashboard-overlay.js.map +1 -1
  24. package/lib/client/dashboard/dashboard-selection.d.ts +2 -1
  25. package/lib/client/dashboard/dashboard-selection.d.ts.map +1 -1
  26. package/lib/client/dashboard/dashboard-selection.js +1 -1
  27. package/lib/client/dashboard/dashboard-selection.js.map +1 -1
  28. package/lib/client/dashboard/git/GitChangedFiles.d.ts +11 -0
  29. package/lib/client/dashboard/git/GitChangedFiles.d.ts.map +1 -0
  30. package/lib/client/dashboard/git/GitChangedFiles.js +101 -0
  31. package/lib/client/dashboard/git/GitChangedFiles.js.map +1 -0
  32. package/lib/client/dashboard/git/GitCommitList.d.ts +15 -0
  33. package/lib/client/dashboard/git/GitCommitList.d.ts.map +1 -0
  34. package/lib/client/dashboard/git/GitCommitList.js +55 -0
  35. package/lib/client/dashboard/git/GitCommitList.js.map +1 -0
  36. package/lib/client/dashboard/git/GitDiffView.d.ts +10 -0
  37. package/lib/client/dashboard/git/GitDiffView.d.ts.map +1 -0
  38. package/lib/client/dashboard/git/GitDiffView.js +65 -0
  39. package/lib/client/dashboard/git/GitDiffView.js.map +1 -0
  40. package/lib/client/dashboard/git/GitFileTypeIcon.d.ts +8 -0
  41. package/lib/client/dashboard/git/GitFileTypeIcon.d.ts.map +1 -0
  42. package/lib/client/dashboard/git/GitFileTypeIcon.js +24 -0
  43. package/lib/client/dashboard/git/GitFileTypeIcon.js.map +1 -0
  44. package/lib/client/dashboard/git/GitLineStats.d.ts +10 -0
  45. package/lib/client/dashboard/git/GitLineStats.d.ts.map +1 -0
  46. package/lib/client/dashboard/git/GitLineStats.js +9 -0
  47. package/lib/client/dashboard/git/GitLineStats.js.map +1 -0
  48. package/lib/client/dashboard/git/WorktreeGitOverview.d.ts +31 -0
  49. package/lib/client/dashboard/git/WorktreeGitOverview.d.ts.map +1 -0
  50. package/lib/client/dashboard/git/WorktreeGitOverview.js +89 -0
  51. package/lib/client/dashboard/git/WorktreeGitOverview.js.map +1 -0
  52. package/lib/client/dashboard/git/WorktreeGitPanel.d.ts +16 -0
  53. package/lib/client/dashboard/git/WorktreeGitPanel.d.ts.map +1 -0
  54. package/lib/client/dashboard/git/WorktreeGitPanel.js +126 -0
  55. package/lib/client/dashboard/git/WorktreeGitPanel.js.map +1 -0
  56. package/lib/client/dashboard/git/file-address.d.ts +2 -0
  57. package/lib/client/dashboard/git/file-address.d.ts.map +1 -0
  58. package/lib/client/dashboard/git/file-address.js +16 -0
  59. package/lib/client/dashboard/git/file-address.js.map +1 -0
  60. package/lib/client/dashboard/git/git-column-split.d.ts +34 -0
  61. package/lib/client/dashboard/git/git-column-split.d.ts.map +1 -0
  62. package/lib/client/dashboard/git/git-column-split.js +41 -0
  63. package/lib/client/dashboard/git/git-column-split.js.map +1 -0
  64. package/lib/client/dashboard/git/git-diff-parser.d.ts +24 -0
  65. package/lib/client/dashboard/git/git-diff-parser.d.ts.map +1 -0
  66. package/lib/client/dashboard/git/git-diff-parser.js +56 -0
  67. package/lib/client/dashboard/git/git-diff-parser.js.map +1 -0
  68. package/lib/client/dashboard/git/git-facts.d.ts +18 -0
  69. package/lib/client/dashboard/git/git-facts.d.ts.map +1 -0
  70. package/lib/client/dashboard/git/git-facts.js +31 -0
  71. package/lib/client/dashboard/git/git-facts.js.map +1 -0
  72. package/lib/client/dashboard/git/git-file-tree.d.ts +16 -0
  73. package/lib/client/dashboard/git/git-file-tree.d.ts.map +1 -0
  74. package/lib/client/dashboard/git/git-file-tree.js +52 -0
  75. package/lib/client/dashboard/git/git-file-tree.js.map +1 -0
  76. package/lib/client/dashboard/git/git-state-cache.d.ts +49 -0
  77. package/lib/client/dashboard/git/git-state-cache.d.ts.map +1 -0
  78. package/lib/client/dashboard/git/git-state-cache.js +80 -0
  79. package/lib/client/dashboard/git/git-state-cache.js.map +1 -0
  80. package/lib/client/dashboard/git/useGitPaneSplit.d.ts +33 -0
  81. package/lib/client/dashboard/git/useGitPaneSplit.d.ts.map +1 -0
  82. package/lib/client/dashboard/git/useGitPaneSplit.js +119 -0
  83. package/lib/client/dashboard/git/useGitPaneSplit.js.map +1 -0
  84. package/lib/client/dashboard/git/useWorktreeGitState.d.ts +60 -0
  85. package/lib/client/dashboard/git/useWorktreeGitState.d.ts.map +1 -0
  86. package/lib/client/dashboard/git/useWorktreeGitState.js +654 -0
  87. package/lib/client/dashboard/git/useWorktreeGitState.js.map +1 -0
  88. package/lib/client/entry.d.ts.map +1 -1
  89. package/lib/client/entry.js +28 -0
  90. package/lib/client/entry.js.map +1 -1
  91. package/lib/client/locales.d.ts +158 -0
  92. package/lib/client/locales.d.ts.map +1 -1
  93. package/lib/client/locales.js +166 -8
  94. package/lib/client/locales.js.map +1 -1
  95. package/lib/client/session/session-view.d.ts +10 -0
  96. package/lib/client/session/session-view.d.ts.map +1 -1
  97. package/lib/client/session/session-view.js +57 -0
  98. package/lib/client/session/session-view.js.map +1 -1
  99. package/lib/client/session/worktree-session-order.d.ts +2 -5
  100. package/lib/client/session/worktree-session-order.d.ts.map +1 -1
  101. package/lib/client/session/worktree-session-order.js +35 -10
  102. package/lib/client/session/worktree-session-order.js.map +1 -1
  103. package/lib/client/session/worktree-session-position.d.ts +2 -1
  104. package/lib/client/session/worktree-session-position.d.ts.map +1 -1
  105. package/lib/client/session/worktree-session-position.js +10 -3
  106. package/lib/client/session/worktree-session-position.js.map +1 -1
  107. package/lib/client/surface/actions/useDragActions.d.ts +33 -2
  108. package/lib/client/surface/actions/useDragActions.d.ts.map +1 -1
  109. package/lib/client/surface/actions/useDragActions.js +66 -18
  110. package/lib/client/surface/actions/useDragActions.js.map +1 -1
  111. package/lib/client/surface/components/ActiveWorktree.js +2 -2
  112. package/lib/client/surface/components/ActiveWorktree.js.map +1 -1
  113. package/lib/client/surface/components/ArchivedWorktree.js +2 -2
  114. package/lib/client/surface/components/ArchivedWorktree.js.map +1 -1
  115. package/lib/client/surface/components/ArchivedWorktrees.js +2 -2
  116. package/lib/client/surface/components/ArchivedWorktrees.js.map +1 -1
  117. package/lib/client/surface/components/SurfaceContent.d.ts +1 -1
  118. package/lib/client/surface/components/SurfaceContent.d.ts.map +1 -1
  119. package/lib/client/surface/components/SurfaceContent.js +1 -1
  120. package/lib/client/surface/components/SurfaceContent.js.map +1 -1
  121. package/lib/client/surface/components/SurfaceHeader.d.ts +1 -1
  122. package/lib/client/surface/components/SurfaceHeader.d.ts.map +1 -1
  123. package/lib/client/surface/components/SurfaceHeader.js +12 -3
  124. package/lib/client/surface/components/SurfaceHeader.js.map +1 -1
  125. package/lib/client/surface/components/WorkspaceTree.js +4 -4
  126. package/lib/client/surface/components/WorkspaceTree.js.map +1 -1
  127. package/lib/client/surface/components/rows.d.ts +2 -2
  128. package/lib/client/surface/components/rows.d.ts.map +1 -1
  129. package/lib/client/surface/components/rows.js +14 -9
  130. package/lib/client/surface/components/rows.js.map +1 -1
  131. package/lib/client/surface/selectors.d.ts +10 -0
  132. package/lib/client/surface/selectors.d.ts.map +1 -1
  133. package/lib/client/surface/selectors.js +14 -0
  134. package/lib/client/surface/selectors.js.map +1 -1
  135. package/lib/client/surface/state/useSessionExpansion.d.ts +2 -1
  136. package/lib/client/surface/state/useSessionExpansion.d.ts.map +1 -1
  137. package/lib/client/surface/state/useSessionExpansion.js +26 -13
  138. package/lib/client/surface/state/useSessionExpansion.js.map +1 -1
  139. package/lib/client/surface/state/useSessionOrdering.d.ts +1 -1
  140. package/lib/client/surface/state/useSessionOrdering.d.ts.map +1 -1
  141. package/lib/client/surface/state/useSessionOrdering.js +23 -8
  142. package/lib/client/surface/state/useSessionOrdering.js.map +1 -1
  143. package/lib/client/surface/types.d.ts +15 -3
  144. package/lib/client/surface/types.d.ts.map +1 -1
  145. package/lib/client/view/worktree-expand-state.d.ts +1 -1
  146. package/lib/client/view/worktree-expand-state.d.ts.map +1 -1
  147. package/lib/client/view/worktree-expand-state.js +8 -1
  148. package/lib/client/view/worktree-expand-state.js.map +1 -1
  149. package/lib/client/worktree-connection.d.ts +4 -0
  150. package/lib/client/worktree-connection.d.ts.map +1 -1
  151. package/lib/client/worktree-connection.js +10 -0
  152. package/lib/client/worktree-connection.js.map +1 -1
  153. package/lib/client.js +3454 -307
  154. package/lib/client.js.map +1 -1
  155. package/lib/contract/index.contract.js +8 -0
  156. package/lib/contract/index.contract.js.map +1 -1
  157. package/lib/contract/index.d.ts +145 -1
  158. package/lib/contract/index.d.ts.map +1 -1
  159. package/lib/contract/index.js +18 -0
  160. package/lib/contract/index.js.map +1 -1
  161. package/lib/host/remote.d.ts.map +1 -1
  162. package/lib/host/remote.js +4 -0
  163. package/lib/host/remote.js.map +1 -1
  164. package/lib/host/service.d.ts +14 -1
  165. package/lib/host/service.d.ts.map +1 -1
  166. package/lib/host/service.js +24 -0
  167. package/lib/host/service.js.map +1 -1
  168. package/lib/index.d.ts +4 -4
  169. package/lib/index.d.ts.map +1 -1
  170. package/lib/index.js +3 -3
  171. package/lib/index.js.map +1 -1
  172. package/lib/manage/manager-git-history.d.ts +17 -0
  173. package/lib/manage/manager-git-history.d.ts.map +1 -0
  174. package/lib/manage/manager-git-history.js +717 -0
  175. package/lib/manage/manager-git-history.js.map +1 -0
  176. package/lib/manage/manager-worktrees.d.ts.map +1 -1
  177. package/lib/manage/manager-worktrees.js +24 -0
  178. package/lib/manage/manager-worktrees.js.map +1 -1
  179. package/lib/manage/manager.d.ts +14 -1
  180. package/lib/manage/manager.d.ts.map +1 -1
  181. package/lib/manage/manager.js +13 -0
  182. package/lib/manage/manager.js.map +1 -1
  183. package/lib/provider/git/adapter.d.ts +54 -1
  184. package/lib/provider/git/adapter.d.ts.map +1 -1
  185. package/lib/provider/git/adapter.js +820 -1
  186. package/lib/provider/git/adapter.js.map +1 -1
  187. package/lib/provider/index.d.ts +2 -2
  188. package/lib/provider/index.d.ts.map +1 -1
  189. package/lib/provider/index.js +1 -1
  190. package/lib/provider/index.js.map +1 -1
  191. package/lib/provider/mutation-token.d.ts +1 -1
  192. package/lib/provider/mutation-token.d.ts.map +1 -1
  193. package/lib/provider/mutation-token.js +1 -0
  194. package/lib/provider/mutation-token.js.map +1 -1
  195. package/lib/provider/sidecar/repository.d.ts +1 -1
  196. package/lib/provider/sidecar/repository.d.ts.map +1 -1
  197. package/lib/provider/sidecar/repository.js +3 -2
  198. package/lib/provider/sidecar/repository.js.map +1 -1
  199. package/lib/provider/sidecar/sidecar-schema.d.ts +16 -3
  200. package/lib/provider/sidecar/sidecar-schema.d.ts.map +1 -1
  201. package/lib/provider/sidecar/sidecar-schema.js +105 -23
  202. package/lib/provider/sidecar/sidecar-schema.js.map +1 -1
  203. package/lib/provider/transaction/operations/create.d.ts.map +1 -1
  204. package/lib/provider/transaction/operations/create.js +21 -6
  205. package/lib/provider/transaction/operations/create.js.map +1 -1
  206. package/lib/provider/transaction/recovery/failure-recovery.d.ts.map +1 -1
  207. package/lib/provider/transaction/recovery/failure-recovery.js +11 -4
  208. package/lib/provider/transaction/recovery/failure-recovery.js.map +1 -1
  209. package/lib/provider/transaction/recovery/recover.d.ts.map +1 -1
  210. package/lib/provider/transaction/recovery/recover.js +9 -11
  211. package/lib/provider/transaction/recovery/recover.js.map +1 -1
  212. package/lib/provider/transaction/support/inspection.d.ts +0 -2
  213. package/lib/provider/transaction/support/inspection.d.ts.map +1 -1
  214. package/lib/provider/transaction/support/inspection.js +0 -4
  215. package/lib/provider/transaction/support/inspection.js.map +1 -1
  216. package/lib/provider/transaction/support/journal.d.ts.map +1 -1
  217. package/lib/provider/transaction/support/journal.js +2 -0
  218. package/lib/provider/transaction/support/journal.js.map +1 -1
  219. package/lib/provider/transaction/types.d.ts +1 -0
  220. package/lib/provider/transaction/types.d.ts.map +1 -1
  221. package/lib/provider/types.d.ts +53 -5
  222. package/lib/provider/types.d.ts.map +1 -1
  223. package/lib/provider/types.js +1 -1
  224. package/lib/provider/types.js.map +1 -1
  225. package/lib/typert.host.js +295 -34
  226. package/lib/typert.remote-client.d.ts +9 -1
  227. package/lib/typert.remote-client.d.ts.map +1 -1
  228. package/lib/typert.remote-client.js +295 -34
  229. package/package.json +3 -1
  230. package/assets/screenshots/screenshots-dashboard.webp +0 -0
package/README.md CHANGED
@@ -1,118 +1,23 @@
1
+ [English](README.md) | [简体中文](README.zh.md)
2
+
1
3
  # @cerbur/clutch-dsh-worktree
2
4
 
3
5
  `@cerbur/clutch-dsh-worktree` adds a Git Worktree view to the DSH Web UI. It groups
4
6
  Sessions as Workspace → Worktree → Session while keeping DSH as the source of truth for
5
- Project/Workspace identity, Session metadata, native lists, and conversation history.
6
- The plugin stores external Worktree/Session relationships, acquisition facts, and user-authored
7
- Worktree instructions in its own sidecar.
8
-
9
- > **Preview:** Worktree Dashboard is an early, plugin-only MVP preview. The overview, Session
10
- > navigation, Worktree instructions, Worktree creation/archive, and the open-in-app action are
11
- > connected; Git details, derived Worktrees, Settings, and other actions marked **Coming soon** remain
12
- > placeholders.
13
-
14
- ## Screenshots
15
-
16
- ![English Worktree sidebar and blank-session Hero](assets/screenshots/screenshots-en.png)
17
-
18
- The English screenshot shows Worktree mode in the Sidebar, a Workspace tree with Main and
19
- Worktree rows, and the read-only blank-session Hero context.
20
-
21
- ![English Worktree Create/Import dialog](assets/screenshots/screenshots-import.png)
22
-
23
- The Import screenshot shows the existing Workspace `+` dialog with Create selected by default,
24
- the adjacent Import tab, and a standard dropdown containing safe example branch/path values.
25
-
26
- ![Worktree Dashboard preview (Chinese UI)](assets/screenshots/screenshots-dashboard.webp)
27
-
28
- The Dashboard screenshot records the current preview UI: Worktree identity, acquisition facts,
29
- connected Session and Worktree actions, and clearly marked placeholder cards.
30
-
31
- ## Capabilities
32
-
33
- - Enter Worktree mode from the DSH Sidebar footer and browse Workspace → Worktree → Session.
34
- - Open Dashboard from the Local/Main or active/archived Worktree menu or its hover-only row action, or use
35
- the quick Dashboard icon to the left of the native Session-header More actions button. View the
36
- real name and cwd, copy the full path, and switch between Dashboard, Git & Changes, Sessions,
37
- Children, and Settings. Unconnected MVP cards and actions are explicitly marked Coming soon.
38
- - Search Workspaces and create a Git Worktree and branch from an existing local branch.
39
- - Choose Import in the same dialog to discover unmanaged, branch-attached Git Worktrees linked to the Workspace repository. The first version omits the repository root and detached HEAD entries.
40
- - Register an existing Worktree in place without moving, copying, or editing its directory; the imported record follows the same Session, binding, health, ordering, cwd, projection, refresh, and recovery flow as a plugin-created record.
41
- - Archive Worktrees non-destructively, preserving disk files, active bindings, and runtime cwd. Disk cleanup (`git worktree remove`) requires secondary confirmation: users must confirm all Sessions, subagents, and other tasks using the directory have stopped. Worktrees can also be forgotten from plugin management while retaining disk files and Sessions.
42
- - Create a normal Session from Main or a Session whose runtime cwd is an active Worktree, then open it directly.
43
- - For active Worktree Sessions, request the named `worktree-full-access` preset after an
44
- explicit confirmation. It combines DSH `danger-full-access` with `ask`: it removes filesystem
45
- confinement for linked Git metadata while keeping approval prompts enabled; network and
46
- process policy are unchanged. The native Access menu marks `Worktree Full Access` with a
47
- Worktree branch icon.
48
- - Preserve an explicit restriction selected in DSH's native Access UI. If the custom preset is
49
- unavailable, fall back to `workspace-write + ask` when possible; if the permission capability
50
- cannot be verified, show a retryable degraded state instead of claiming Full Access.
51
- - Reuse the native `StateDot` for Session status indicators. Running, running-subagent, warning,
52
- and completed states occupy the trailing slot; idle Sessions show native relative time for the
53
- last human-authored message there. Hover or an open menu gives the trailing slot back to the
54
- existing actions menu.
55
- - Dashboard Session cards use the same status-or-relative-time metadata in both the overview
56
- preview and the full Sessions tab, keeping status semantics consistent with the Worktree list.
57
- - Show the native DSH Session hover detail card with the complete title, relative time, and current
58
- status; the card yields to the Session actions menu and row dragging.
59
- - Cover native waiting-for-approval, plan-review, question, completed, idle, and running-subagent
60
- states without copying the animation implementation into the plugin.
61
- - Show one native running indicator on a collapsed Workspace, Main, or Worktree when any of its
62
- non-archived Sessions is active. A collapsed active group reserves the indicator's 28px box plus
63
- a 4px label gap, and its long Worktree label scrolls while activity remains active; expanded groups
64
- keep their normal action rail instead.
65
- - Promote a Session to the head of its Main or Worktree visual group after a newer user message.
66
- This ordering is browser-local and does not mutate DSH Workspace order or the Worktree sidecar.
67
- - Fork a Session from the native DSH Workspace tab, the Worktree view, or the Conversation fork
68
- action. When the parent has an active Worktree binding, the child is bound to the same Worktree
69
- and opens directly in the Worktree view. The child remains a normal DSH Session.
70
- - See ready, repair, active, and detached Worktree states, including retryable operation errors.
71
- - Use the shared Main and Worktree row options menu to copy the selected row's absolute path.
72
- Local/Main and managed Worktree rows expose Dashboard through the existing menu and a hover-only row action.
73
- The Worktree group rail is zero-width at rest unless a group is collapsed with active Session activity;
74
- that state reserves the 28px running indicator and a 4px text gap. Hover, focus, or an open menu
75
- reveals the available Dashboard, menu, and Session `+` controls at intrinsic width. Long Worktree labels
76
- automatically scroll while hovered or while collapsed activity remains active, using one shared scroll
77
- loop and resetting when neither trigger applies.
78
- Active rows offer Archive Worktree with confirmation.
79
- - Create a new Worktree from the Local or an active Worktree's options menu. The Create dialog
80
- uses the selected row's current branch as its base and suggests the next available numbered
81
- name, such as `feature-2` or `feature-3`; detached Worktrees do not expose this action.
82
- - Continue using DSH-native Workspace rename/delete/reorder and Session menus. Worktree rows can
83
- be reordered within their owning Workspace; order is stored in the plugin sidecar and Main is
84
- fixed first.
85
- - Persist Workspace, Main, and Worktree expansion choices in browser-local storage; the five-row Session overflow state remains transient and resets after refresh or parent collapse.
86
- - Provide a Collapse All button in the Worktree Header to collapse all Workspaces and Worktrees at once.
87
- - Highlight the DSH current Session in Worktree view; entering Worktree mode or switching the current Session temporarily reveals its Workspace/Main/Worktree path, expands Session overflow only when the row is outside the first five, clears a hiding search, and scrolls the row into view; this browser-local behavior does not change persisted expansion choices.
88
- - Keep the current local branch or Worktree branch visible as read-only context in the existing
89
- Conversation title row and in the blank-session Hero.
90
- - Copy the ID of any non-blank Worktree Session from its Session actions menu.
91
- - Keep Conversation and Hero context stable across same-Session snapshot updates and Session
92
- switches, while retaining the last valid context during replacement reads.
93
- - Truncate long branch labels to fit their chips and reveal the complete value through a native
94
- hover card; the Sidebar footer action follows native typography and does not add a duplicate
95
- `WT` button when the Sidebar is collapsed.
96
- - Keep Worktree Sessions in the original DSH Project/Workspace view; the plugin does not copy
97
- Session content or modify messages, prompts, transcripts, or history.
98
-
99
- ### Compatibility and prerequisites
100
-
101
- Session reload is compatible with DSH rc.1 persisted headers and newer DSH header snapshots.
102
- The Worktree Dashboard preview records acquisition facts for new Worktrees and injects saved instructions for active sessions.
103
-
104
- The supported compatibility requirements are:
105
-
106
- | Component | Min Version | Notes |
107
- | ---------- | -------------- | --------------------------------------------------------------------- |
108
- | DSH Client | `>=0.1.5-rc.1` | Requires the Session/Workspace Controllers and Client Store |
109
- | DSH Host | `>=0.1.5-rc.1` | Requires the Typert Gateway `/api` protocol and subprocess capability |
110
- | Git | `>=2.20.0` | Requires worktree core commands and branch discovery |
111
- | Node.js | `>=20.0.0` | LTS is recommended |
7
+ Workspace identity, Session metadata, native lists, messages, and conversation history.
8
+
9
+ The plugin stores Worktree relationships, acquisition facts, and shared Worktree instructions in
10
+ its own sidecar. Managed Worktrees also expose a read-only Git & Changes dashboard where users can
11
+ choose a local branch baseline; the plugin does not copy transcripts or rewrite DSH Sessions.
12
+
13
+ > **Preview:** Worktree Dashboard is an early, plugin-only MVP preview. Worktree navigation,
14
+ > lifecycle actions, Session actions, instructions, and the managed Worktree Git & Changes view
15
+ > are connected. Derived Worktrees, Settings, and other unfinished actions remain marked
16
+ > **Coming soon**.
112
17
 
113
18
  ## Installation
114
19
 
115
- ### Install from npm (recommended)
20
+ ### Install from npm
116
21
 
117
22
  With an installed DSH CLI:
118
23
 
@@ -121,370 +26,322 @@ dsh plugin --profile web add @cerbur/clutch-dsh-worktree
121
26
  dsh web
122
27
  ```
123
28
 
124
- When using a `deepseek-harness` source checkout without a standalone `dsh` command, use the
125
- equivalent forwarding form:
29
+ When using a DeepSeek Harness source checkout without a standalone `dsh` command, use the
30
+ equivalent `pnpm dsh` form.
126
31
 
127
- ```bash
128
- cd /path/to/deepseek-harness
129
- pnpm dsh plugin --profile web add @cerbur/clutch-dsh-worktree
130
- pnpm dsh web
131
- ```
32
+ ### Install from a local checkout
132
33
 
133
- To inspect the currently published version on the official registry:
34
+ Build this package, build the DSH source checkout, and add the package by absolute path:
134
35
 
135
36
  ```bash
136
- npm view @cerbur/clutch-dsh-worktree version --registry=https://registry.npmjs.org/
37
+ cd /absolute/path/to/clutch-dsh
38
+ pnpm install
39
+ pnpm --filter @cerbur/clutch-dsh-worktree build
40
+
41
+ cd /absolute/path/to/deepseek-harness
42
+ pnpm install
43
+ pnpm run build
44
+ pnpm dsh plugin --profile web add /absolute/path/to/clutch-dsh/packages/clutch-dsh-worktree
45
+ pnpm dsh web
137
46
  ```
138
47
 
139
- ### Install from GitHub source
48
+ The DSH Web profile must be able to start before this plugin is added. Re-run the absolute-path
49
+ install command after changing `package.json` or `cordis.patch.yml`.
140
50
 
141
- The source path generated by `awesome-dsh-plugin` is:
51
+ ### Install from GitHub source (optional)
52
+
53
+ The package also supports the source dependency form used by the DSH plugin market:
142
54
 
143
55
  ```bash
144
56
  dsh plugin --profile web add "github:Cerbur/clutch-dsh#path:/packages/clutch-dsh-worktree"
145
57
  ```
146
58
 
147
- This is a source Git dependency that builds during installation. For pnpm 11 `allowBuilds`
148
- authorization, local development, and contributor workflows, see [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).
59
+ This form builds the package during installation. For pnpm build-script authorization and local
60
+ development details, see [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md).
149
61
 
150
- ### Uninstall
62
+ ## Features
151
63
 
152
- ```bash
153
- cd /path/to/deepseek-harness
154
- pnpm dsh plugin --profile web remove @cerbur/clutch-dsh-worktree
155
- ```
64
+ | Feature | Preview | What it does |
65
+ | --- | --- | --- |
66
+ | **Worktree navigation** | <img src="assets/screenshots/screenshots-en.png" width="420" alt="DSH Worktree navigation with Workspace, Main, Worktree, and Session rows"> | Adds a Worktree mode to the Sidebar. Browse each Workspace through Local/Main and Git Worktree rows, then open the Sessions bound to each row. |
67
+ | **Create and import Worktrees** | <img src="assets/screenshots/screenshots-import.png" width="420" alt="Worktree create and import dialog"> | Create a Worktree from a local branch, or register an existing branch-attached Worktree in place. Import does not move, copy, or edit the existing directory. |
68
+ | **Worktree Dashboard** | <img src="assets/screenshots/screenshots-dashboard.png" width="420" alt="Worktree Dashboard preview with Sessions and Worktree actions"> | The preview Dashboard shows Worktree identity, path, Sessions, instructions, connected actions, and the read-only Git & Changes view for eligible managed Worktrees. Derived Worktrees, Settings, and other unfinished cards remain **Coming soon**. |
156
69
 
157
70
  ## Usage
158
71
 
159
72
  ### Open Worktree mode
160
73
 
161
- 1. Start the DSH Web UI and select Worktree from the Sidebar footer. Worktree mode is an
162
- additive surface; it does not add a separate Workspace/Worktree tab.
163
- 2. Use the Workspace tree to search, expand, and select the Main or Worktree view. Each group
164
- initially shows five rows; use Expand more/Collapse for additional rows.
165
-
166
- ![Worktree sidebar and blank-session Hero while using Worktree mode](assets/screenshots/screenshots-en.png)
167
-
168
- The screenshot above illustrates the Sidebar entry point and the visual context shown in the
169
- blank-session Hero. The displayed language follows DSH's current language setting.
170
-
171
- ### Open a Worktree dashboard
172
-
173
- The Dashboard is a plugin-only preview MVP; it does not replace DSH's native Session page or
174
- write DSH-owned Workspace/Session data.
175
-
176
- In Worktree mode, hover a managed Worktree row and click its Dashboard icon, or open the row's
177
- options menu and choose **Dashboard**. For a current Session with a ready Main or Worktree
178
- context, click the Dashboard icon to the left of the native **More actions** button in the
179
- Session header. The dashboard temporarily replaces the area beside the Sidebar, including the
180
- Session page.
181
- The native conversation remains mounted. Use **Back to session**, press **Escape**, open
182
- a Session from the Sidebar, or exit Worktree mode to restore the native page. No Session
183
- is created or changed by opening the dashboard. Local/Main and managed Worktree rows can use the
184
- inline Dashboard icon; the current Session can also use the Session-header shortcut. The Dashboard keeps the
185
- Sidebar resize handle available while it is open.
186
-
187
- ![Worktree Dashboard preview](assets/screenshots/screenshots-dashboard.webp)
188
-
189
- The screenshot above shows the preview Dashboard beside the native Worktree Sidebar. Its connected
190
- controls are intentionally limited to the MVP surface; unfinished cards remain visibly marked.
191
-
192
- The title uses the same accepted branch name as the Worktree row. Click the title to copy the
193
- branch name directly. The cwd is the record's full absolute path; its copy button reports success
194
- or failure. If DSH cannot provide Main's current branch, the Dashboard labels it unavailable and
195
- does not offer branch copying. Current branch, availability, and source use the existing Worktree projection. Ready means the Worktree is available;
196
- it does **not** assert that Git files are clean. An archived or cleaned record still shows
197
- its recorded path, which need not exist on disk.
198
-
199
- The five tabs support Left/Right, Home, and End keys. Overview shows up to five current
200
- Worktree Sessions; Sessions shows the full list. Both consume the existing in-memory Sessions
201
- and bindings with Sidebar ordering and visibility rules, independent of Sidebar search.
202
- Click a Session to return to its native page. New Session uses the existing create/bind/open
203
- flow, including blank-Session reuse and failure recovery, and leaves the dashboard.
204
- New Worktree opens the existing Create dialog with the current branch and numbered-name
205
- defaults. Archive Worktree opens the existing non-destructive confirmation. These actions
206
- follow the Sidebar's health, archive, and pending-operation gates.
207
- Open in VS Code uses an encoded `vscode://file/...` link for the recorded cwd. VS Code must be
208
- installed on the browser's machine and able to access that path; the browser may request
209
- permission to open the app. This link does not verify directory existence or launch success.
210
- Git details, derived Worktrees, settings, and other marked quick actions
211
- remain placeholders. The layout follows DSH's theme and stacks cards on narrow screens.
212
- Dashboard selection is transient and is not restored after a reload.
213
-
214
- Use **Edit** on the Worktree instructions card to edit, save, or clear shared guidance
215
- (up to 32,000 UTF-16 code units). Saved text enters bound Sessions' next model request as
216
- `<system-reminder>` through DSH `agent/pre-step`, as a separate context entry in the
217
- Session trajectory. DSH records the message; existing history is not rewritten.
218
- Instruction text is inserted literally, including any `{{...}}` examples.
219
- Archiving preserves active bindings and instructions; detached bindings, disk cleanup, and
220
- removal from management stop the guidance. Clearing or losing the binding appends a
221
- reminder invalidating earlier Worktree instructions on the next step. Unchanged guidance
222
- is not repeated while its message remains visible, including after restart; compacted
223
- guidance is republished when needed.
224
- Failed saves retain the draft. Concurrent edits are rejected; cancel and reopen to load the
225
- latest saved text before retrying. Instructions remain in the plugin sidecar, never AGENTS.md.
226
-
227
- New plugin-created Worktrees show their recorded creation time and selected base branch.
228
- Imported Worktrees show their registration time and do not infer an original creation time or
229
- base. When these historical facts are unavailable, the Dashboard shows **Unavailable for
230
- historical Worktrees** instead of Unknown. The base is the acquisition
231
- branch name, not a live merge-base or ahead/behind calculation, and does not change on checkout.
232
- The open-editor split button follows DSH's native styling and offers detected host applications;
233
- if unavailable, it falls back to the VS Code protocol link described above.
74
+ 1. Start DSH Web and select **Worktree** from the DSH Sidebar footer.
75
+ 2. Search or expand a Workspace in the Worktree tree.
76
+ 3. Select Local/Main or a Worktree to browse its Sessions. The view is additive; DSH's native
77
+ Workspace and Session navigation remains available. Each group initially shows five rows;
78
+ use **Expand more** and **Collapse** for additional rows.
79
+ 4. Use **Collapse All** in the header to collapse other unrelated Workspaces and Worktrees;
80
+ the Workspace and Worktree containing the current Session remain expanded.
234
81
 
235
82
  ### Create a Worktree
236
83
 
237
- New directories use `$dshHome/clutch-dsh-worktree/worktree/wt_<12-hex-characters>`
238
- (15 characters in the folder name, with 48 bits of cryptographic randomness).
239
- Occupied directory names, Git registrations, and sidecar identities are automatically retried.
240
- After eight random candidates collide, numeric suffixes such as `_1` and `_2` are tried until
241
- available or cancelled. Existing Worktree paths and IDs stay unchanged; branch conflicts and
242
- other Git failures retain their normal error handling.
243
-
244
- 1. Select a Workspace, press its `+`, choose a baseline local branch, and enter a Worktree name.
245
- The default branch name is `dsh/<8-character-random-string>`.
246
- 2. To create a sibling from an existing Worktree, open that active Worktree's options menu and
247
- choose `Create new Worktree`. The dialog preselects the Worktree branch as the base and
248
- chooses the next available numeric suffix for the name; existing names are skipped.
249
- 3. The target Worktree path must be absolute, belong to the same Project, and differ from the
250
- Project root. Relative paths, a different Project, or the Project root are rejected.
251
- 4. Git must be installed and available on `PATH`. A missing Git executable shows install guidance and no command block;
252
- install Git, restart DSH, and retry. If the repository, initial commit,
253
- or local branch is missing, follow the copyable setup commands in the dialog. The plugin only
254
- renders this guidance; it does not run setup or installation commands or edit business files.
84
+ 1. Open the options menu for Local/Main or an active Worktree and choose **Create Worktree**.
85
+ 2. Choose the local base branch. You can also provide a new branch name.
86
+ 3. Confirm the dialog. The plugin creates the Git Worktree, records its acquisition facts, and
87
+ continues through the normal Session and binding flow when you open a Session from that Worktree.
88
+
89
+ Git must have a usable repository, local branch, and initial commit. If setup is incomplete, DSH
90
+ shows the relevant readiness message and copyable setup guidance.
255
91
 
256
92
  ### Import an existing Worktree
257
93
 
258
- 1. Select a Workspace, press its `+`, and choose the `Import` tab. The dialog loads Git-linked
259
- Worktrees for that repository through the existing DSH `/api` Connection.
260
- 2. The first version lists only branch-attached, non-root Worktrees that are not already present
261
- in the plugin sidecar. Detached HEAD, bare, prunable, missing-directory and missing-`.git`
262
- entries are omitted. Managed health and import eligibility share one runtime status mapping;
263
- importing rechecks that status. Locked Worktrees remain eligible when otherwise ready.
264
- Candidates are presented
265
- in a standard dropdown; each option shows its branch first and absolute path as secondary
266
- diagnostic text.
267
- 3. Choose an option and select `Import Worktree`. Registration writes only the plugin sidecar;
268
- the existing Worktree directory and Git working state remain in place. Import then creates or
269
- reuses a Session at that Worktree cwd and runs the same bind → open → binding refresh flow as
270
- Create.
271
- 4. An active external import for the same Workspace and physical path is idempotent. A path already
272
- managed by the plugin returns an error; invalid or stale candidates can be retried after the repository state is fixed.
273
-
274
- ### Create Main and Worktree Sessions
275
-
276
- - Use Main's `+` to create a normal DSH Session in the Project-root view.
277
- - Use a Worktree's `+` to create or reuse a Session with that Worktree as its runtime cwd. The Session
278
- opens directly in the Worktree view without briefly appearing in Main.
279
- - The connector reuses an unarchived blank Session with the exact target cwd when possible. An
280
- already-bound Session opens directly; an unbound candidate is bound before opening. Otherwise, a
281
- new Session is created and bound, and concurrent clicks for the same Worktree are coalesced.
282
- - If binding fails after DSH has created the Session, the Session ID remains available for Retry
283
- or Open recovery. The plugin does not delete or mutate that DSH Session.
284
- - Before opening an active Worktree Session, the plugin explains in a DSH-styled in-page dialog why
285
- linked Git metadata may need access outside the Session directory. The dialog requires an explicit
286
- risk acknowledgement; cancelling keeps the Session and binding, does not change permissions, and
287
- leaves a retryable pending state. The native DSH Access selector remains the way to switch to
288
- another permission mode.
289
- - A provisional blank Session follows DSH's native display rules: it is shown only in the
290
- selected view, uses the localized `New Session` label, hides its generated ID, and has no
291
- Rename, Fork, or Archive menu. After the first prompt is accepted, it becomes an ordinary
292
- Session row; hiding the blank row does not delete the Session or its Worktree binding.
293
-
294
- ### Session activity and ordering
295
-
296
- - Session rows reuse DSH's native `StateDot`: running Sessions, Sessions with running subagents,
297
- waiting approval, plan review, question, and completed states show their status dot in the
298
- trailing slot instead of relative time. Idle Sessions use that slot for the native compact
299
- relative-time label.
300
- - The trailing metadata uses the native compact buckets (`now`, minutes, hours, days, months, and
301
- years). It is based on DSH's `updatedAt`, which advances with the latest human-authored message;
302
- blank New Session rows have no time label. The display follows snapshot renders and does not add
303
- an independent minute ticker.
304
- - Hovering a Worktree Session row opens the native detail card after 500 ms with its full title,
305
- relative time, and status; the card is suppressed while the Session menu is open or a row is
306
- being dragged.
307
- - A collapsed Workspace, Main group, or Worktree group shows the same running dot when any
308
- non-archived member is ongoing, including activity hidden by search. Expanding the group hides
309
- the aggregate dot; hover, focus, or an open menu reveals the existing action controls and only then
310
- reserves their width.
311
- - A newer user message promotes its Session to the head of the current Main or Worktree visual
312
- group. The promotion, observed timestamps, and per-group order live only in browser-local state;
313
- successful manual drag still uses the native DSH ordering API before updating that local order.
314
-
315
- ### Fork Worktree Sessions
316
-
317
- - Use any native DSH fork entry point: a Session-list tab, a Worktree Session menu, or the
318
- Conversation fork action. Lineage, title increments, and conversation fork history remain native DSH behavior.
319
- - When the parent Session has an active Worktree binding, the forked child Session is automatically
320
- bound to the same Worktree and opens directly in that Worktree view. Ready content is retained during the binding refresh.
321
- - If the child is created but binding fails, DSH keeps the child Session, and the Worktree view provides
322
- Retry Binding and Open recovery actions. Later plugin initializations also retry recoverable fork children
323
- from native Session lineage; unrelated subagents are never bound automatically.
324
- - Fork binding is maintained by the plugin's external index without mutating DSH's durable Workspace storage.
325
-
326
- ### Reorder and manage Worktrees
327
-
328
- - Drag Worktrees within their owning Workspace to reorder them. The custom order is preserved by the plugin;
329
- Main is always fixed as the first row, and Worktrees cannot be dragged across Workspaces.
330
- - Newly created or imported Worktrees are inserted at the head of their Workspace's Worktree list; existing Worktree order is preserved.
331
- - Open the shared Main and Worktree options menu to copy the selected row's absolute path. Active
332
- Worktrees show `Copy path` and `Archive Worktree`. Archiving an active Worktree is an internal
333
- archive operation: it preserves disk files, active bindings, and runtime cwd, and moves the Worktree into
334
- the default-collapsed `Archived` group at the bottom of the Workspace.
335
- - The `Archived` group is rendered at the bottom of the Workspace when archived Worktrees exist and is
336
- collapsed by default. Its label includes the total archived Worktree count, even when collapsed.
337
- Each Workspace tracks its own collapsed state independently.
338
- - Active Worktrees requiring repair also offer `Archive Worktree` to archive the record without
339
- touching disk files or bindings. Worktrees in recovery-needed state block removal until recovery completes.
340
- - For archived Worktrees whose disk has not been cleaned, the options menu provides:
341
- 1. `Unarchive Worktree`: Restores a metadata-archived Worktree whose disk directory is intact back to active status, without secondary confirmation.
342
- 2. `Clean Up Disk`: Prompts for secondary confirmation detailing the path and irreversible deletion,
343
- tells you that the plugin does not check Session or subagent activity and requires you to confirm
344
- that all tasks using the directory have stopped (otherwise deletion may cause task failures or data loss),
345
- runs real non-forced `git worktree remove`, and upon success records the record as cleaned, transitions
346
- bindings to detached, and normalizes Full Access permissions to `workspace-write + ask`. Disk removal
347
- commitment is decoupled from permission normalization: once disk removal commits, the dialog closes and the
348
- record updates to cleaned; any follow-up permission or refresh failure provides independent retry without
349
- re-executing disk removal. If the Worktree directory or its `.git` entry was already deleted externally,
350
- confirming cleanup marks the plugin record as completed and detaches its bindings without running Git removal.
351
- 3. `Remove from Management`: Prompts for confirmation and removes the Worktree sidecar record and all
352
- its bindings, while preserving disk files and native DSH Sessions. It retires in-flight fork operations,
353
- recovery state, and permission notices for that Worktree. No Session activity check is required.
354
- - For archived Worktrees whose disk has already been cleaned, the menu provides `Remove from Management`
355
- to prune the sidecar record completely.
356
- - Session activity is informational and does not block cleanup or removal from management. Stop all tasks
357
- using the directory yourself before confirming disk cleanup; the plugin does not verify that they have stopped.
358
- - Deleting a Workspace removes only DSH's Workspace registration; its directory, Sessions, Git Worktrees,
359
- and plugin sidecar remain.
360
- - DSH-native Workspace rename/delete/reorder and Session menus remain available. Session drag
361
- ordering is limited to the current visual Main or Worktree group.
362
- - The Main group shows the current local branch as `Local (branch)` and falls back to `Local` if
363
- DSH reports no current branch. When a Workspace is imported from a Git subdirectory, the Git
364
- root is resolved first and the same branch/worktree information is used as for the root.
365
- Branch names, paths, Workspace names, Session titles, and raw DSH/Git errors keep their
366
- original values.
367
- - Existing Sessions show read-only context in the form `Session title` → `Agent mode` →
368
- `current branch / Worktree branch`. Long values remain ellipsized in the compact chip and show
369
- their complete value in a hover card. The blank Hero shows `Workspace (branch)` after the native
370
- title when its anchors are available and offers the same complete-value hover card.
371
- - When the Sidebar is collapsed, the footer keeps its icon-only native action geometry; the plugin
372
- does not render a separate `WT` rail control.
373
-
374
- ### Reconcile a branch changed in Git
375
-
376
- After an external `git checkout`, the next Worktree read shows `old branch → current branch`
377
- and a branch-change warning. Reads occur on refresh and when opening a Worktree menu; the
378
- plugin does not watch Git continuously. Detached HEAD is shown explicitly. Session bindings
379
- and runtime cwd remain unchanged, and normal branch changes do not lock the Workspace.
380
-
381
- Choose `Adopt current branch` from the active or archived Worktree menu and confirm the
382
- displayed transition. This updates only the plugin's recorded branch. A changed branch or
383
- stale snapshot during confirmation is rejected; refresh and confirm again. Detached HEAD
384
- must first be switched to a branch in Git. Disk cleanup requires adopting the current branch
385
- first. Creating a Worktree on the old branch is allowed when Git proves the existing record
386
- has switched away; genuinely checked-out branches remain unavailable.
387
-
388
- Confirmation failures appear inside the dialog. Choose `Retry` to reload the observed branch
389
- and snapshot token, then confirm the updated transition; the old confirmation stays disabled
390
- until refresh succeeds. If the Worktree is no longer branch-drifted or has entered detached HEAD,
391
- the dialog closes. Creating a sibling Worktree uses the observed current branch, even before
392
- adoption; detached HEAD does not offer this action.
393
-
394
- For `recovery-needed`, the Worktree menu offers `Retry recovery` for its Workspace.
395
- This retries safe journal recovery; it does not adopt branches, delete unknown paths, or
396
- clear unresolved identity issues. Successful adoption and recovery refresh only the owning
397
- Workspace while preserving existing ready content.
398
-
399
- ### Understand status and recovery messages
400
-
401
- - Operation, permission, binding, and refresh failures use DSH's native toast, one at a time.
402
- Unchanged errors are not repeated on every render. Full messages and existing Retry/Open
403
- actions remain in the expandable Notification details and recovery entry after the toast fades.
404
- Form validation and Workspace Git setup guidance remain next to their inputs.
405
- - Hover or focus an active Worktree row to see its status, path, and repair guidance for missing
406
- directories/Git registration, branch drift/detached HEAD, or incomplete recovery. Opening its
407
- menu or dragging suppresses the hover card. Archive confirmation explicitly preserves the
408
- directory, Session bindings, and cwd for both plugin-created and external Worktrees;
409
- Clean Disk remains a separate action.
410
- - `ready` means the Worktree is available. `cleaned` indicates disk cleanup completed while the
411
- sidecar archive entry is retained. `repair` identifies a missing or invalid Worktree, Session, binding,
412
- or cwd. `recovery-needed` means a Git/sidecar operation or identity check is unresolved and
413
- destructive actions are blocked. `detached` means the Git Worktree was removed while the relationship
414
- was retained. An active binding pointing to a missing Worktree produces
415
- an explicit repair warning or error; it never silently falls back to another Worktree.
416
- - Without a pending Git transaction, missing active or archived Worktrees remain `repair` and
417
- can be archived without blocking healthy Worktree Session bindings.
418
- - Worktree health is a runtime Git projection and is not written to the sidecar. Git readiness
419
- failures are shown per Workspace: a missing Git executable shows installation guidance without
420
- commands, while repository, initial commit, or local branch failures show copyable setup
421
- commands. Connection, Gateway, and unexpected Worktree-domain failures remain visible as
422
- retryable errors rather than empty lists.
423
- - Permission status is also explicit: Full Access, fallback `workspace-write`, preserved user
424
- restriction, unverified capability, confirmation pending, and retryable setup failure are not
425
- silently collapsed into an empty or falsely successful Worktree state.
426
- - Refreshing an already-ready view preserves its current projection until replacement data is
427
- available. Same-Session snapshot updates do not blank the context or trigger redundant reads;
428
- initial entry and explicit Retry may show a loading state when no cached view is available.
94
+ 1. Select a Workspace, open its `+` action, and switch to **Import**.
95
+ 2. Choose a candidate from the branch-and-path list.
96
+ 3. Select **Import Worktree**. The plugin registers the existing directory without moving,
97
+ copying, or changing its files, then uses the same Session flow as a created Worktree.
98
+
99
+ The first version lists only ready, branch-attached, non-root Git Worktrees that are not already
100
+ managed by the plugin. Detached, bare, prunable, missing, and invalid entries are omitted. Imported
101
+ Worktrees can still use Git & Changes after you choose a local baseline branch.
102
+
103
+ ### Create and open Sessions
104
+
105
+ - Use **+** on Local/Main for a normal DSH Session whose runtime directory is the Workspace root.
106
+ - Use **+** on a Worktree for a Session whose runtime directory is that Worktree.
107
+ - When possible, the plugin reuses an unarchived blank Session with the exact target directory.
108
+ - Use native DSH fork actions from a Session list, Worktree Session menu, or conversation. A
109
+ child of a Worktree-bound Session is bound to the same Worktree and opens in that view.
110
+
111
+ If DSH creates a Session but binding fails, the Session is kept. The Worktree view exposes retry
112
+ or open recovery actions; the plugin does not delete or rewrite the DSH Session.
113
+
114
+ ### Open the Worktree Dashboard
115
+
116
+ Open **Dashboard** from a Local/Main or Worktree row menu, its hover action, or the Dashboard icon
117
+ beside the native Session-header actions. The Dashboard is a peer page to the native Session content: it
118
+ occupies the center area beside the Sidebar while leaving an already-open right sidebar visible for a
119
+ session-bound target. When the target Worktree has Sessions, opening its Dashboard waits for an initial pending
120
+ Session list to become ready, then keeps the current Session if it belongs to that Worktree; otherwise it
121
+ switches to the retained head Session so both views stay aligned. A ready
122
+ empty Session list opens a page-level Dashboard without changing the current Session, collapses any currently
123
+ open native right sidebar because there is no target Session, and does not create a Session automatically. The
124
+ Dashboard header keeps the native right-sidebar button available whenever a current Session can host it and the
125
+ sidebar is collapsed; once opened, the button is hidden following native behavior.
126
+
127
+ Use **Back to session**, Escape, a Sidebar Session, or Worktree mode exit to close it. For a Worktree with no
128
+ Sessions, the top-right action becomes **New Session** and starts one in that Worktree. The connected MVP surface
129
+ can show Overview and Sessions, create a Session or Worktree, archive a Worktree, edit instructions, copy a
130
+ path, open the recorded directory in VS Code, and inspect Git & Changes.
131
+ Derived Worktrees, Settings, and other marked quick actions remain placeholders. VS Code must be
132
+ installed on the browser's machine and able to access the recorded path; the link does not verify
133
+ launch success.
134
+
135
+ ### Use Git & Changes
136
+
137
+ Open the **Git & Changes** tab from a managed Worktree Dashboard. For a managed Worktree with a
138
+ persisted `baseBranch` that differs from the current branch, or with a captured acquisition commit that
139
+ supplies the implicit baseline, the Overview performs one compact, on-demand Git status read through the
140
+ existing `/api` Connection. It shows ahead/behind commit counts plus separate
141
+ committed (baseline-to-HEAD) and uncommitted (live working-tree) line totals; this is an ephemeral
142
+ projection, not a watcher or a Worktree-record field. Main,
143
+ unavailable, or baseline-unselected views honestly remain **Not connected**. Opening Overview does not
144
+ load the branch list; the first Git tab activation loads local branches and, once a baseline is resolved,
145
+ commit history. To replace that baseline, click the pencil icon beside the Base fact to open the branch
146
+ picker: its search field sits permanently above a bounded branch list that shows roughly seven rows and
147
+ scrolls internally, so the dialog keeps one size while you filter. Choose any local branch except the
148
+ current Worktree branch and save.
149
+ The save replaces the persisted `baseBranch` in the plugin sidecar; the saved value becomes the default for
150
+ the Git selector. Once the Git tab is open, changing its selector remains a transient view choice and reloads
151
+ history, changed files, and diffs without another Worktree-record write. If no usable saved baseline exists
152
+ (absent or equal to the current Worktree branch), the Git tab and the Overview read against the Worktree's
153
+ immutable captured acquisition commit and show that resolved commit as the Base fact; only a Worktree with
154
+ neither a usable saved baseline nor a captured commit stays baseline-unselected and prompts you to choose
155
+ one. When the selected branch has diverged, Git resolves the two heads' common ancestor. The
156
+ Git & Changes view reports Worktree commits after that ancestor as `+N` ahead and base-branch commits after it
157
+ as `-N` behind; history and file reads remain available. If the two heads have no common ancestor, the
158
+ committed summary falls back to the full tree diff between the base branch tip and Worktree `HEAD`, while
159
+ history uses the Worktree commits not reachable from that base tip.
160
+ With a valid baseline loaded, the Git & Changes tab initially selects **Baseline summary** rather than the
161
+ first commit; changing the baseline branch also returns to that summary. Choose a commit or **Uncommitted
162
+ changes** when you need a narrower target.
163
+
164
+ The selected local branch is resolved again for each read. The browser can choose only a plain local branch
165
+ name, not a raw commit SHA or arbitrary Git ref: a full ref path, tag, or remote-tracking ref is rejected
166
+ outright, while a selected branch that no longer exists shows the honest unavailable state instead of a
167
+ generic Git failure. `baseCommit` is immutable acquisition metadata, is never user-selectable directly, and
168
+ is the implicit baseline whenever no saved branch baseline is usable; creation recovery never overwrites
169
+ it. When the Worktree has staged, unstaged, or untracked
170
+ files, the list prepends an **Uncommitted changes** entry; selecting it compares the live working tree with
171
+ `HEAD` and uses the same changed-file and diff views.
172
+
173
+ The **Baseline summary** is a separate target that shows the net committed tree diff from the resolved
174
+ common ancestor to the request's captured `HEAD` (or the two branch tips when no common ancestor exists);
175
+ it excludes working-tree changes by default. Turn on **Include working tree** to replace that target with
176
+ one net diff from the same comparison boundary to the current working tree, including committed, staged,
177
+ unstaged, untracked, deleted, and renamed changes. This is a
178
+ fresh on-demand projection rather than a concatenation of two diffs. Clicking a commit shows that
179
+ commit's own diff. Turn on **Multi-select commits** in the commits header to pick several committed rows
180
+ and view the exact union of their first-parent deltas; the switch is off by default, and turning it off
181
+ collapses the selection back to the focused commit. The changed-file list
182
+ records the contributing commits, and each selected commit is rendered as its own diff segment; this is
183
+ not an implicit range and does not include unselected commits. The changed-files column header shows the
184
+ aggregate green `+N` and red `-N` totals for the current target, including the Baseline summary, selected
185
+ commits, or Uncommitted changes; binary-only totals show Unknown. The working-tree entry remains mutually
186
+ exclusive with committed multi-selection. The **Open in Sidebar** action in the summary diff toolbar
187
+ reveals the current file in the native right sidebar using the current Session, only when that Session
188
+ belongs to the Dashboard Worktree. An empty Worktree
189
+ or an unrelated current Session cannot open a file through this action.
190
+
191
+ The history is capped at 200 commits and marks longer histories as truncated. A changed-file list larger
192
+ than the Git adapter's output bound reports an explicit truncated state instead of a generic error.
193
+ Commit details use
194
+ first-parent comparisons; root commits compare against the empty tree; rename and copy rows retain
195
+ both paths; binary or oversized diffs show an explicit display-safe state. Changed-file rows show text
196
+ line counts as green `+N` additions and red `-N` deletions; binary files omit those counts. File names use
197
+ green for additions, red for deletions, and blue for other changes, and each row's title and accessible
198
+ label spells the status out. Folder icons indicate whether each folder is
199
+ expanded or collapsed. The **Uncommitted changes** entry is an on-demand snapshot, is not persisted, and is not a
200
+ Git watcher; refresh it to see later edits.
201
+
202
+ Git & Changes uses a viewport-bounded, fixed-size surface. Wide layouts show two columns: commits and
203
+ changed files stack in the narrower left column around a draggable divider, while the diff keeps the full
204
+ height on the right. Narrow layouts keep two rows: commits and changed files side by side on the first row,
205
+ with the summary diff underneath. Both dividers stay draggable in either layout — the vertical one trades
206
+ width between the columns, or between commits and changed files inside the first row, and the horizontal one
207
+ trades height between the commits and changed-file panes, or between the first row and the diff. Drag a
208
+ divider, or focus it and press the arrow keys, to move it, and double-click it to restore the default split.
209
+ Long commit and changed-file lists scroll inside their panes instead of expanding the Dashboard. The
210
+ changed-file pane also scrolls horizontally when paths are wider than the pane, keeping file and folder
211
+ names untruncated. Changed files are grouped by folders; folders start expanded and can be opened or
212
+ collapsed independently. Diff content also scrolls inside its bounded pane, while the read-only selection
213
+ and refresh behavior remains unchanged.
214
+
215
+ The view is read-only and does not provide commit or staging controls. The plugin validates committed
216
+ entries against the selected branch-to-`HEAD` projection and re-reads working-tree paths against a fresh
217
+ status projection, so these endpoints are not generic Git object or file readers. Refresh keeps ready
218
+ content visible while replacement data loads, and late responses for an older commit or file selection
219
+ are ignored.
220
+
221
+ ### Add Worktree instructions
222
+
223
+ In the Dashboard, use **Edit** on the instructions card to save or clear shared guidance, up to
224
+ 32,000 UTF-16 code units. For an active binding, the next model request receives the text as a
225
+ separate `<system-reminder>` context entry through DSH's pre-step hook.
226
+
227
+ Instructions stay in the plugin's own data. They are not written to the project directory or an
228
+ `AGENTS.md` file. Clearing, detaching, archiving, cleaning, or forgetting a Worktree stops future
229
+ injection; unchanged instruction text is not repeatedly added while its message remains visible.
230
+
231
+ ### Archive or remove a Worktree
232
+
233
+ - **Archive Worktree** is non-destructive. It keeps the directory, bindings, instructions, and
234
+ runtime Worktree context. An archived Worktree can be unarchived while its Git registration is
235
+ intact.
236
+ - **Clean Up Disk** is a separate action. It requires a second confirmation and runs the normal
237
+ non-forced `git worktree remove`. The plugin does not check whether Sessions or subagents are
238
+ still using the directory; stop those tasks before confirming. Successful cleanup detaches the
239
+ bindings while keeping the recorded history until it is forgotten.
240
+ - **Remove from Management** deletes only the plugin's Worktree and binding records. It preserves
241
+ the disk files and native DSH Sessions, and does not require a Session activity check.
242
+
243
+ ## Requirements
244
+
245
+ | Component | Requirement |
246
+ | --- | --- |
247
+ | DSH Client | `>=0.1.5-rc.1`, including the Session and Workspace Controllers and Client Store |
248
+ | DSH Host | `>=0.1.5-rc.1`, including the Typert Gateway `/api` connection and subprocess capability |
249
+ | Git | `>=2.20.0`, installed and available on `PATH` |
250
+ | Node.js | `>=20.0.0` for the DSH host runtime |
251
+
252
+ ## Behavior and limitations
253
+
254
+ - DSH owns Workspace identity and root paths, Session identity and metadata, native lists,
255
+ messages, prompts, transcripts, and history. The plugin never copies or rewrites those values.
256
+ - The plugin's external index stores Worktree paths, branches, sources, lifecycle state, bindings,
257
+ ordering, instructions, acquisition facts, and related metadata. For managed Worktrees, the
258
+ Dashboard Base fact is the persisted `baseBranch`; users can replace it with a local branch other
259
+ than the current Worktree branch, and the saved value becomes the Git-tab selector default. The
260
+ immutable acquisition `baseCommit` remains separate and is not rewritten by that edit. The index is
261
+ kept in the DSH host plugin data directory, not in a project directory or DSH's raw data store. It
262
+ does not store Session content or a copy of the Workspace root.
263
+ - Runtime `cwd` is derived for each execution. No binding, Main, or detached binding uses the
264
+ Workspace root; an active Worktree binding uses that Worktree path. The cwd is never persisted
265
+ into DSH Session metadata.
266
+ - One Session can have at most one active Worktree binding, while a Worktree can have many Sessions.
267
+ Removing or cleaning a Worktree never deletes a DSH Session. A broken active binding reports a
268
+ repair state instead of silently falling back to another Worktree.
269
+ - Git is read on relevant refreshes, when relevant menus open, and on Git Dashboard activation;
270
+ the plugin does not watch Git continuously. An external branch change is shown as branch drift
271
+ and requires explicit **Adopt current branch** before disk cleanup. Detached HEAD and
272
+ recovery-needed states remain visible and retryable.
273
+ - Worktree health is shown by tinting the branch icon: ready uses the success (green) color, branch drift uses the warning color, and repair/recovery-needed uses the error color. The localized health label remains available to assistive technology even when hover replaces the icon with the disclosure control.
274
+ - Newly created or imported Worktrees are inserted at the head of their Workspace's Worktree list; existing Worktree order is preserved and Main remains fixed first.
275
+ - Persist Workspace, Main, and Worktree expansion choices in browser-local storage; the five-row Session overflow state remains transient and resets after refresh or parent collapse. **Collapse All** collapses unrelated nodes while keeping the current Session's Workspace and Worktree expanded.
276
+ - When the current Session is outside the visible tree, the matching row is highlighted and temporarily revealed; positioning keeps the navigation scroll unchanged when the row is already visible and moves only enough to expose it otherwise. This does not change persisted expansion choices.
277
+ - Git Dashboard reads run on the Host through the existing DSH `/api` transport. The browser does
278
+ not execute Git, read sidecar files or `.git`, or expose working-tree mutation controls. File
279
+ diffs disable external diff and text conversion and are bounded for safe display.
280
+ - The Git Dashboard is intentionally limited to committed history, a read-only **Baseline summary**
281
+ (optionally including one fresh baseline-to-working-tree projection), one **Uncommitted changes**
282
+ snapshot, changed files, and one unified diff at a time. These projections combine staged, unstaged,
283
+ and untracked files when requested but are never written back to Git. The Dashboard does not provide
284
+ commit, staging, reset, revert, cherry-pick, fetch, push, pull, pull requests, graph lanes, pagination,
285
+ or syntax highlighting.
286
+ - Session rows use DSH's native status and relative-time presentation. Collapsed Workspace, Main,
287
+ and Worktree groups derive one aggregate `StateDot` from their complete eligible membership (after native blank/archive filtering): waiting
288
+ approval (and other pending-interaction warnings) takes priority over running, and running
289
+ takes priority over completed. Idle Sessions do not contribute a group dot; Worktree health
290
+ remains a separate leading indicator. Visual Session ordering initially follows the newest `updatedAt` values and
291
+ remains browser-local; Main remains fixed first, Worktree drag updates only this local order projection,
292
+ and Main drag updates native Workspace order only after DSH accepts it.
293
+ - Active Worktree Sessions may request the named `worktree-full-access` preset after an explicit
294
+ confirmation. It combines DSH `danger-full-access` with `ask`, keeps approval prompts enabled,
295
+ and does not change network or process policy. If unavailable, the plugin falls back to
296
+ `workspace-write + ask` when possible or reports an unverified, retryable state. It cannot
297
+ exceed the sandbox imposed by the host running DSH.
298
+ - Git must be installed and available on `PATH`. A missing Git executable shows install guidance
299
+ and no command block; the plugin does not run setup or installation commands.
300
+ - If the plugin's external index is unavailable or corrupt, native DSH Workspace and Session views
301
+ remain readable and the plugin enters a degraded read-only state. It never replaces native data
302
+ with an empty index.
429
303
 
430
304
  ## Language behavior
431
305
 
432
- Worktree mode follows DSH's current interface language. DSH owns the language preference; the
433
- plugin does not add an independent language setting. The Worktree entry point, Workspace →
434
- Worktree → Session tree, menus, dialogs, statuses, and retry messages are localized in English
435
- and Chinese.
436
-
437
- Workspace names, Session titles, branch names, paths, and raw DSH/Host error messages remain
438
- unchanged for diagnosis and continued use of native DSH data. The Main group is localized as
439
- `Local (branch)` in English and `本地(branch)` in Chinese, with `Local`/`本地` as the fallback
440
- when no current branch is reported.
306
+ Worktree mode follows DSH's current interface language. The entry point, tree, menus, dialogs,
307
+ statuses, Dashboard labels, and retry messages are localized in English and Chinese. Workspace
308
+ names, Session titles, branch names, paths, and raw DSH or Git errors keep their original values.
441
309
 
442
- ## Data boundaries and current limitations
310
+ ## Development
443
311
 
444
- DSH owns the original Project/Workspace identity and root, Session identity and metadata, native
445
- Project/Session lists, messages, prompts, transcripts, and history. The plugin does not copy or
446
- rewrite any of those values. Its external index lives in the DSH host's plugin data directory or
447
- an independent sidecar store and contains only relationship facts such as:
312
+ For architecture, local DSH integration, testing, and contribution details, see:
448
313
 
449
- - `projectId`, `worktreeId`, and `sessionId` mappings;
450
- - an absolute Worktree path, branch, and lifecycle state;
451
- - the Worktree source (`plugin` or `external`);
452
- - binding status and schema version.
314
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)
315
+ - [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md)
316
+ - [docs/RELEASING.md](docs/RELEASING.md)
317
+ - [AGENTS.md](AGENTS.md)
318
+ - [src/client/README.md](src/client/README.md)
453
319
 
454
- The index is not written into a Project working tree or DSH's raw data directory. It does not
455
- store a copy of `projectRoot` or any Session content. If the sidecar is unavailable or corrupt,
456
- the native Project/Session view remains readable and the plugin becomes degraded/read-only; an
457
- empty index must never overwrite the native DSH lists.
320
+ The focused package commands are:
458
321
 
459
- Each Session has at most one active Worktree binding, while a Worktree may have multiple bound
460
- Sessions. Rebinding the same Session to the same Worktree is idempotent; binding it to two active
461
- Worktrees is a conflict. A Session with no binding, a Main binding, or a detached binding runs
462
- with the Project root as cwd. An active Worktree binding runs with that Worktree path. The cwd is
463
- derived for each execution and is never persisted back into DSH Session metadata.
322
+ ```bash
323
+ pnpm --filter @cerbur/clutch-dsh-worktree typecheck
324
+ pnpm --filter @cerbur/clutch-dsh-worktree build
325
+ pnpm --filter @cerbur/clutch-dsh-worktree test
326
+ ```
464
327
 
465
- Worktree creation creates the Git Worktree before recording its external relationship; if a sidecar
466
- write fails, the newly created Git Worktree is cleaned up when possible. Session creation uses the
467
- native DSH API before binding; a binding failure never deletes or modifies the already-created Session.
328
+ The bilingual README structure is checked with:
468
329
 
469
- The Worktree session flow presents Sessions in their bound Worktree context using browser-side
470
- view projections without mutating DSH native Workspace storage.
330
+ ```bash
331
+ node --test test/readme-parity.test.mjs
332
+ ```
471
333
 
472
- Permission changes use only the public DSH per-Session permission service. The plugin does not
473
- write messages, prompts, transcripts, Workspace data, or Session metadata, and cannot enlarge a
474
- filesystem sandbox imposed by the host running DSH.
334
+ ## Uninstall
475
335
 
476
- The blank Hero context is visual only. Because the current upstream DSH source checkout has no
477
- additive Hero headline slot, its placement depends on native DOM anchors; it disappears when those
478
- anchors are unavailable and should move to a formal DSH slot when one exists.
336
+ With the DSH CLI:
479
337
 
480
- For detailed architectural models, lifecycle transitions, recovery guarantees, and developer documentation, see:
338
+ ```bash
339
+ dsh plugin --profile web remove @cerbur/clutch-dsh-worktree
340
+ ```
481
341
 
482
- - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — Canonical architecture, lifecycle, and recovery invariants
483
- - [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) — Local development, testing, and contribution guide
484
- - [docs/RELEASING.md](docs/RELEASING.md) — Release parameters and versioning policy
485
- - [AGENTS.md](AGENTS.md) — Coding agent working instructions
486
- - [src/client/README.md](src/client/README.md) — Browser client integration and surface boundaries
342
+ From a DeepSeek Harness checkout, use `pnpm dsh plugin --profile web remove` with the same package
343
+ name.
487
344
 
488
345
  ## Friendly Links
489
346
 
490
- - [LINUX DO](https://linux.do/) — A new ideal community
347
+ - [LINUX DO](https://linux.do/) — A new ideal community.