@1yefuwang1/dsh-worktrees 0.0.0-stage → 0.2.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.
- package/CHANGELOG.md +218 -0
- package/LICENSE +21 -0
- package/README.md +471 -2
- package/client.js +1398 -0
- package/cordis.patch.yml +6 -0
- package/dist/context.d.ts +20 -0
- package/dist/context.js +70 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.js +30 -0
- package/dist/first-message.d.ts +19 -0
- package/dist/first-message.js +121 -0
- package/dist/git.d.ts +45 -0
- package/dist/git.js +806 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +183 -0
- package/dist/naming.d.ts +25 -0
- package/dist/naming.js +151 -0
- package/dist/project-context.d.ts +20 -0
- package/dist/project-context.js +82 -0
- package/dist/project-rpc.d.ts +10 -0
- package/dist/project-rpc.js +103 -0
- package/dist/project-store.d.ts +121 -0
- package/dist/project-store.js +32 -0
- package/dist/projects.d.ts +149 -0
- package/dist/projects.js +603 -0
- package/dist/quiet-rpc.d.ts +7 -0
- package/dist/quiet-rpc.js +125 -0
- package/dist/rpc.d.ts +10 -0
- package/dist/rpc.js +418 -0
- package/dist/runtime.d.ts +22 -0
- package/dist/runtime.js +123 -0
- package/dist/schema.d.ts +50 -0
- package/dist/schema.js +86 -0
- package/dist/service.d.ts +98 -0
- package/dist/service.js +943 -0
- package/dist/sessions.d.ts +31 -0
- package/dist/sessions.js +130 -0
- package/dist/store.d.ts +114 -0
- package/dist/store.js +44 -0
- package/dist/types.d.ts +262 -0
- package/dist/types.js +1 -0
- package/icon.svg +1 -0
- package/locale/en.json +6 -0
- package/package.json +106 -3
package/README.md
CHANGED
|
@@ -1,3 +1,472 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @1yefuwang1/dsh-worktrees
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Multi-folder projects with Local and isolated Git worktree threads for DeepSeek
|
|
4
|
+
Harness. This experimental Host + Web Client package is **`0.2.13`**, prepared for
|
|
5
|
+
scoped npm release with maintainer review/2FA. It does not require Copilot, the
|
|
6
|
+
catalog plugin, or the search plugin. The scoped name avoids collision with the
|
|
7
|
+
unrelated npm package `dsh-worktrees`; stable tool, command and metadata names are
|
|
8
|
+
unchanged.
|
|
9
|
+
|
|
10
|
+
## Projects and threads
|
|
11
|
+
|
|
12
|
+
A **project** is a durable logical group containing one or more existing folders.
|
|
13
|
+
A **thread** belongs to that project and executes in one selected folder: either
|
|
14
|
+
its Local directory or a managed linked Git checkout. Project membership is not
|
|
15
|
+
native Workspace membership, a working-directory change or a permission grant.
|
|
16
|
+
|
|
17
|
+
- The compact **Projects** header uses Search, View options and Add project icon
|
|
18
|
+
controls. Search appears only when opened; Escape/Close clears it and restores
|
|
19
|
+
focus. Archive filters are in View options, not an always-visible dropdown.
|
|
20
|
+
- The **Projects** sidebar lists project headers and their Local/worktree threads
|
|
21
|
+
together, using the native Folder view's open/closed workspace icons, regular
|
|
22
|
+
14px session titles, compact last-active times and 12px **Show X more sessions**
|
|
23
|
+
controls. Dates use session activity, not project edits; counts reflect only
|
|
24
|
+
hidden sessions. Hover/focus reveals row actions without permanently reserving
|
|
25
|
+
their width. Activity uses the native neutral 14px animated ring (including
|
|
26
|
+
reduced-motion behavior); pending/completion use solid state dots. A permanent
|
|
27
|
+
branch/worktree icon separately identifies managed worktree backing,
|
|
28
|
+
independent of whether a row is hovered. Worktree/branch names are not shown
|
|
29
|
+
inline; hover the thread title or worktree icon to see them, or open thread
|
|
30
|
+
details. The accessible label and details retain the original folder and actual
|
|
31
|
+
execution directory; branch names are cached
|
|
32
|
+
last-known values, not a background Git status poll.
|
|
33
|
+
- Existing Local native workspaces are imported as one-folder projects. Managed
|
|
34
|
+
checkout workspaces are grouped under their source project, not promoted into
|
|
35
|
+
separate projects. **Edit project** can combine imported folders into an
|
|
36
|
+
explicitly named multi-folder project without moving files, sessions or logs.
|
|
37
|
+
- **Create project** uses a compact project-name field and **Source folders** card.
|
|
38
|
+
Click **Add** to browse Host folders, check several folders (including folders
|
|
39
|
+
from different directories), then add the batch. Selections survive directory
|
|
40
|
+
navigation. Repeat Add to extend the list; each selected folder shows its name,
|
|
41
|
+
full path and a remove action. A project supports **1–32 folders**; duplicate
|
|
42
|
+
picks are ignored and over-limit batches are refused without dropping entries.
|
|
43
|
+
The source dropdown also offers manual absolute paths and the optional native
|
|
44
|
+
system chooser (one folder per pick). Use **Cancel** to discard unsaved edits;
|
|
45
|
+
saving/native picking blocks dismissal until it settles, and Host refusals preserve the
|
|
46
|
+
draft. The same folder-list design is used by **Manage project**. Removal edits
|
|
47
|
+
membership only, never deletes files; ownership/use restrictions remain Host-
|
|
48
|
+
authoritative. Canonical aliases are checked by the Host, not guessed in the UI.
|
|
49
|
+
- **Main folder** is required when creating a new multi-folder project in the GUI.
|
|
50
|
+
Choose it in Create/Manage project; a one-folder project uses its only folder.
|
|
51
|
+
The choice is saved by stable folder ID, so reordering folders does not change
|
|
52
|
+
it. Existing projects without a choice adopt their first folder on upgrade.
|
|
53
|
+
Changing main never moves or rebinds existing conversations or worktrees.
|
|
54
|
+
- The project's **+ / New Thread** uses the normal new-conversation flow in its
|
|
55
|
+
main folder. Use the adjacent folder arrow to start in another project folder,
|
|
56
|
+
or change **Conversation folder** in an empty blank composer before typing or
|
|
57
|
+
attaching files. An override is per conversation and never changes main. Drafts,
|
|
58
|
+
attachments, queued work and active setup block folder switching. The native
|
|
59
|
+
workspace picker/editor stay installed; there is no first-message dialog.
|
|
60
|
+
Choose **New worktree** before the first Send; mode selection only changes
|
|
61
|
+
intent and leaves the native draft/chips/files intact.
|
|
62
|
+
- Search, pinned order, running/pending indicators, archived-thread access and
|
|
63
|
+
native row actions remain available. Installed row extensions are mirrored into
|
|
64
|
+
plugin-owned aliases through public slot APIs; native entries and declarations
|
|
65
|
+
are never changed. The footer **Folder view** switch restores the original
|
|
66
|
+
native browser; **Projects** switches back. Plugin unload restores native UI.
|
|
67
|
+
- **Manage project → Remove project** asks for confirmation and removes only the
|
|
68
|
+
logical project and its folder/thread associations. Source folders, files,
|
|
69
|
+
native workspaces, conversations, managed worktrees and start receipts are kept,
|
|
70
|
+
even if threads are running. Conversations remain available under **Other
|
|
71
|
+
threads** and **Folder view**, with permanent worktree icons and path/branch
|
|
72
|
+
details. Cancel keeps all unsaved edits; failures preserve the editor draft.
|
|
73
|
+
- Removal remains effective after refresh/restart: a minimal durable removal
|
|
74
|
+
receipt suppresses automatic folder import and repairs interrupted metadata
|
|
75
|
+
cleanup. The project storage domain remains additive v1. To group the retained
|
|
76
|
+
folders again, explicitly create a project with a fresh UUID; existing native
|
|
77
|
+
folder identities and conversations are reused. Removed UUIDs are not recycled.
|
|
78
|
+
- A folder has one project owner. Explicit custom-project conflicts are refused;
|
|
79
|
+
imported ownership can be adopted. Removing individual folders from a retained
|
|
80
|
+
project is still refused if they have threads, worktrees or start receipts;
|
|
81
|
+
removing the project itself is metadata-only and has no such restriction.
|
|
82
|
+
Existing cwd values and history stay immutable.
|
|
83
|
+
|
|
84
|
+
For a multi-folder project, only the **selected Git folder** is isolated in a new
|
|
85
|
+
worktree. Other folders still refer to Local directories; the plugin does not
|
|
86
|
+
clone/synchronize every repository or loosen filesystem policy. The agent's
|
|
87
|
+
native **system reminder** states the project, main/default folder, actual selected
|
|
88
|
+
source folder, execution directory and truthful thread backing. Its bounded
|
|
89
|
+
folder list includes IDs and Local paths (first eight plus main/selected when
|
|
90
|
+
needed, at most ten); omitted folders/truncated values are marked, and an exact
|
|
91
|
+
`workspace_project` list request retrieves full metadata. Main/folder edits appear
|
|
92
|
+
on the next prompt assembly from cached metadata, without scanning repositories
|
|
93
|
+
or injecting user messages. Membership and defaults do not grant permissions.
|
|
94
|
+
|
|
95
|
+
All these changes are plugin-only. Native Workspace records retain their exact
|
|
96
|
+
canonical execution paths; DSH core and the application shell are not modified.
|
|
97
|
+
|
|
98
|
+
## New Conversation: Local or New worktree
|
|
99
|
+
|
|
100
|
+
Start a new conversation through the default UI. Its **normal composer** offers
|
|
101
|
+
**New worktree** only after its actual selected folder passes local Git validation
|
|
102
|
+
and has a configured remote. Ordinary non-Git folders, unverified/unsupported
|
|
103
|
+
sources and failed checks show **Local** only, with no remote-branch controls.
|
|
104
|
+
Git repository subfolders remain eligible; no `.git`-directory heuristic is used.
|
|
105
|
+
The workspace picker, rich editor, attachments, native Enter/Send and rollback
|
|
106
|
+
stay installed; there is no separate first-message dialog.
|
|
107
|
+
|
|
108
|
+
A ready blank target performs one coalesced authenticated read-only status request
|
|
109
|
+
(several bounded local Git commands), not fetch/remote advertising, naming,
|
|
110
|
+
checkout or session creation. Observations are cached for the exact actor binding,
|
|
111
|
+
selected folder and connection generation. Target/view/panel changes, reconnect
|
|
112
|
+
and disposal abort stale reads. Main/title/token changes do not poll Git; failed
|
|
113
|
+
checks leave Local usable. Fresh configure/Send discovery remains authoritative
|
|
114
|
+
and can revoke an earlier positive. If New was already selected, revocation
|
|
115
|
+
preserves that intent and refuses Send safely until you explicitly choose Local.
|
|
116
|
+
A positive observation is not a permission grant or guarantee of remote/fetched-
|
|
117
|
+
tree support; normal creation checks still apply.
|
|
118
|
+
|
|
119
|
+
1. Choose **New worktree**. This only selects the mode: no Git work, checkout,
|
|
120
|
+
branch, setup request or naming inference is performed on selection. Existing
|
|
121
|
+
draft text, reference chips and attachment objects stay in their native editor.
|
|
122
|
+
2. Write your first ordinary message and press the **native Send** button (or its
|
|
123
|
+
native keyboard gesture). Native command adjudication and chip serialization
|
|
124
|
+
run first; claimed/handled commands keep their original command path and do
|
|
125
|
+
not provision a checkout.
|
|
126
|
+
3. A full-width progress panel shows **Fetching latest remote branch → Creating
|
|
127
|
+
worktree → Generating and applying branch name**. The Host freshly fetches the
|
|
128
|
+
chosen base, creates a random directory/initial local branch, then runs the
|
|
129
|
+
configured fast auxiliary naming model and renames only that branch. Naming
|
|
130
|
+
completes before the new conversation receives the prompt.
|
|
131
|
+
4. After the named checkout and exact blank session are ready, generic file drafts
|
|
132
|
+
are re-uploaded for that exact session (receipts cannot cross sessions). The
|
|
133
|
+
original, natively serialized prompt and ordered attachments are admitted once
|
|
134
|
+
to the **normal conversation LLM**, then that conversation opens.
|
|
135
|
+
|
|
136
|
+
The checkout directory, execution cwd, pinned base and session identity do not
|
|
137
|
+
move during naming. Naming uses `github-copilot/gpt-6-luna` by default, independent
|
|
138
|
+
of the normal conversation model. The foreground naming deadline is at most
|
|
139
|
+
15 seconds (or a shorter configured deadline); unavailable or invalid output
|
|
140
|
+
uses a deterministic safe fallback, never another-model retry.
|
|
141
|
+
|
|
142
|
+
The optional **Base branch** control explicitly reads advertised branches so you
|
|
143
|
+
can choose any configured remote/base before Send. Selecting the worktree mode
|
|
144
|
+
itself does not query Git. `origin`/`main` are preferences, not restrictions. The
|
|
145
|
+
actual checkout always uses a fresh selected-branch fetch; failed fetches never
|
|
146
|
+
substitute cached commits. Only the selected project folder is isolated.
|
|
147
|
+
|
|
148
|
+
Progress uses bounded, event-driven wait requests over authenticated Connection
|
|
149
|
+
RPC, not periodic status polling. Preparation holds message admission and shows a
|
|
150
|
+
Cancel action; it does not freeze navigation or invoke the normal LLM early.
|
|
151
|
+
Failures return through native draft/chip restoration rather than a replacement
|
|
152
|
+
editor. A created checkout is retained if preparation or admission is cancelled.
|
|
153
|
+
Unknown admission is never blindly resent: inspect/open the exact created session.
|
|
154
|
+
|
|
155
|
+
### Guarded native submission adapter
|
|
156
|
+
|
|
157
|
+
The installed runtime has no public ordinary-message target-resolution hook.
|
|
158
|
+
This version uses the **explicitly approved version-pinned adapter**: it leases
|
|
159
|
+
only the per-session native submit sink plus the trigger-controller thunk needed
|
|
160
|
+
to capture Send-time intent before asynchronous codecs/adjudication. The editor,
|
|
161
|
+
command machine, serialization, undo/rollback and normal prompt transport remain
|
|
162
|
+
native. No core file, global business service, native endpoint, keyboard handler
|
|
163
|
+
or other plugin's DOM is replaced.
|
|
164
|
+
|
|
165
|
+
Compatibility is the exact manifest/peer pin to DSH `0.2.0-rc.2` **plus structural
|
|
166
|
+
callback/owner checks**, not a runtime-source fingerprint or an upgrade-stability
|
|
167
|
+
claim. Missing/changed shapes fail closed rather than sending a worktree-selected
|
|
168
|
+
prompt to Local. Descriptor ownership is identity-checked on teardown; pending
|
|
169
|
+
attempts settle before restoration. Future runtime upgrades require reviewing this
|
|
170
|
+
adapter. Do not grant a version exemption to bypass that compatibility boundary.
|
|
171
|
+
|
|
172
|
+
### Configurable automatic naming
|
|
173
|
+
|
|
174
|
+
Naming uses a small auxiliary call independent of the conversation model. Defaults:
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
namingEnabled: true
|
|
178
|
+
namingProvider: github-copilot
|
|
179
|
+
namingModel: gpt-6-luna
|
|
180
|
+
namingTimeoutMs: 15000
|
|
181
|
+
namingMaxTokens: 256
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
These are plugin Config fields, not another New Chat form. The first ordinary
|
|
185
|
+
prompt is bounded before branch naming. Inference happens only after successful
|
|
186
|
+
fresh fetch and checkout creation, and the exact generated result is persisted
|
|
187
|
+
before rename; ready same-operation replay does no fetch, inference or creation.
|
|
188
|
+
The foreground deadline is `min(namingTimeoutMs, 15000)`. Disabled/unavailable,
|
|
189
|
+
timed-out or malformed naming yields a safe deterministic branch name and can
|
|
190
|
+
consume no more than the bounded configured auxiliary call.
|
|
191
|
+
|
|
192
|
+
The directory remains the random `worktree-<UUID>` name; the record's
|
|
193
|
+
`naming.directoryName` is suggestion metadata, not its actual basename. Session
|
|
194
|
+
titles stay with the native title feature. A branch collision or changed initial
|
|
195
|
+
branch is not forced; preparation fails and retains its receipts/files.
|
|
196
|
+
|
|
197
|
+
Explicit command/tool `create` with `firstPrompt` uses the same checkout-first
|
|
198
|
+
foreground naming order. Legacy no-`firstPrompt` tool creates may still use the
|
|
199
|
+
previous post-first-message naming path (with its idle/maintenance checks); the
|
|
200
|
+
new lazy UI supplies `firstPrompt` and never schedules that background rename.
|
|
201
|
+
|
|
202
|
+
## Manager, reminders and guarded Local handoff
|
|
203
|
+
|
|
204
|
+
The advanced **Worktrees** sidebar panel shows recorded checkouts, fetched bases,
|
|
205
|
+
current/last-known branch and dirty state, conversations, protection, archive
|
|
206
|
+
state and errors. The started-conversation header reads cached project/backing
|
|
207
|
+
metadata only; there is no Worktrees button beside the project name in the chat
|
|
208
|
+
header. Open the manager from its sidebar entry, with no background Git query.
|
|
209
|
+
A ready blank conversation checks only its actual target's local Git availability;
|
|
210
|
+
Local mode sends no setup/fetch and remains usable if discovery fails. There is no
|
|
211
|
+
sidebar-wide or per-token Git polling. Project metadata refreshes on connection
|
|
212
|
+
generation, explicit edits and structural native Workspace changes, not per render/token or timer.
|
|
213
|
+
UI requests use the existing authenticated Connection RPC transport, not the
|
|
214
|
+
slash-command registry. The plugin owns exact POST routes
|
|
215
|
+
`/api/dsh-worktrees/projects`, `/api/dsh-worktrees/execute`,
|
|
216
|
+
`/api/dsh-worktrees/prepare` and `/api/dsh-worktrees/progress`, preserving the
|
|
217
|
+
public RPC envelope/correlation. It does not claim the shared `/api` interceptor,
|
|
218
|
+
which is exclusive and already belongs to the native API gateway. Selecting New worktree, opening or refreshing the manager,
|
|
219
|
+
reading checkout status and cancelling a UI request therefore create no
|
|
220
|
+
`command/run` or `command/done` conversation rows. Explicit user-entered
|
|
221
|
+
`/worktree` commands and agent `git_worktree` calls remain visible normally.
|
|
222
|
+
There is no periodic polling; actor identity and filesystem authorization are
|
|
223
|
+
unchanged, and UI errors are shown inline. Existing historical rows are not erased.
|
|
224
|
+
Agent runtime-context reminders are separate from these UI queries.
|
|
225
|
+
Open an exact conversation, create a branch in the worktree, protect/unprotect it,
|
|
226
|
+
or archive/restore its plugin record. **Archive is not deletion**: checkout files,
|
|
227
|
+
pinned base refs, sessions and logs remain. Protection prevents branch creation,
|
|
228
|
+
handoff and archiving until explicitly removed; it is not an OS write lock.
|
|
229
|
+
|
|
230
|
+
For handoff, open a conversation belonging to the chosen worktree first:
|
|
231
|
+
|
|
232
|
+
1. Stop all writers in both checkouts, including external editors, processes,
|
|
233
|
+
terminals, jobs and other sessions.
|
|
234
|
+
2. Preview the patch relative to the saved fetched base. The default target is
|
|
235
|
+
the original Local checkout; an optional explicit Local path must pass the
|
|
236
|
+
same repository and identity checks.
|
|
237
|
+
3. Review changed files, binary markers, byte count, base identity and retained
|
|
238
|
+
patch path. Export can return bounded inline text; for a large patch, copy the
|
|
239
|
+
retained path. No unauthenticated download endpoint is invented.
|
|
240
|
+
4. Explicitly confirm that other writers are stopped, then apply and continue in
|
|
241
|
+
the exact Local continuation returned by the Host.
|
|
242
|
+
|
|
243
|
+
Handoff requires Full access, idle known source/target sessions and a clean
|
|
244
|
+
Local checkout at the saved base. It checks repository identities, source/target
|
|
245
|
+
fingerprints, patch integrity and optimistic preconditions, and obtains Host
|
|
246
|
+
maintenance claims for known sessions. It never pulls, resets or switches the
|
|
247
|
+
Local branch to make a mismatch fit. **It is not globally atomic**: outside
|
|
248
|
+
writers must remain stopped through completion. Applying from an agent tool in
|
|
249
|
+
its own running source turn is unsupported and returns `BUSY`, rather than
|
|
250
|
+
waiting for that turn to become idle. Use the idle GUI command path instead.
|
|
251
|
+
|
|
252
|
+
Sources, original history and retained patch files are not deleted. Continuation
|
|
253
|
+
uses the normal fork seed through the last completed turn, not a log rewrite;
|
|
254
|
+
older paths in inherited history may refer to the original checkout. Normal
|
|
255
|
+
preset/model/permission/approval/plan and Goal semantics remain authoritative;
|
|
256
|
+
the plugin does not reinterpret Goal state or grant permission through a copied
|
|
257
|
+
history or a confirmation checkbox.
|
|
258
|
+
|
|
259
|
+
## Permissions, supported repositories and limits
|
|
260
|
+
|
|
261
|
+
**Cross-root Git mutations are Full-access-only.** Creation, starting a session
|
|
262
|
+
in a recorded checkout, branch creation, preview/export (which write snapshots),
|
|
263
|
+
and handoff require the receiving ordinary session's existing `danger-full-access`
|
|
264
|
+
policy. Shared Git administration cannot be honestly confined to a single
|
|
265
|
+
workspace-write checkout. List/status/branch discovery use the caller's managed
|
|
266
|
+
filesystem/subprocess capabilities and may still be refused by its sandbox.
|
|
267
|
+
Protect/archive change plugin metadata rather than deleting repository data.
|
|
268
|
+
Agent mutation tools are refused while plan mode is active or pending enabled.
|
|
269
|
+
|
|
270
|
+
The GUI never creates a more-privileged blank actor to bypass the current
|
|
271
|
+
conversation's policy. Without a usable current ordinary conversation, the root
|
|
272
|
+
manager asks you to open one. An acknowledgement confirms user intent only;
|
|
273
|
+
change permissions through the existing permission control if needed. No
|
|
274
|
+
privilege flags or automatic escalation are supplied.
|
|
275
|
+
|
|
276
|
+
Supported: ordinary non-bare, non-shallow local Git repositories with a committed
|
|
277
|
+
HEAD, canonical local filesystem/subprocess execution, and HTTPS, SSH or local
|
|
278
|
+
file remotes. Repository files must fit the configured count/byte bounds and
|
|
279
|
+
supported UTF-8 paths/mappings. Git authentication uses existing noninteractive
|
|
280
|
+
Git transport configuration; the plugin does not add a sign-in or password prompt.
|
|
281
|
+
|
|
282
|
+
Unsupported cases fail explicitly, including:
|
|
283
|
+
|
|
284
|
+
- Git LFS and clean/smudge filters or working-tree encoding attributes;
|
|
285
|
+
- sparse checkouts, partial/promisor clones, shallow clones, submodules and
|
|
286
|
+
unsupported/custom Git worktree or ref-storage mappings;
|
|
287
|
+
- unborn/bare repositories, executable remote helpers, unsafe/escaping paths or
|
|
288
|
+
symlinks, unmerged files, and unavailable project subdirectories;
|
|
289
|
+
- remote filesystem execution providers without the required local capability
|
|
290
|
+
mapping, stale previews/cursors, changed remote identities, or over-limit output.
|
|
291
|
+
|
|
292
|
+
Hooks, external diff/fsmonitor and recursive submodule behavior are suppressed
|
|
293
|
+
for plugin Git operations. This is not a claim that arbitrary configured Git
|
|
294
|
+
transports or external writers are globally sandboxed in Full access.
|
|
295
|
+
|
|
296
|
+
## Cancellation and recovery
|
|
297
|
+
|
|
298
|
+
Cancellation is not destructive rollback. A fetch, checkout, registered session,
|
|
299
|
+
or applied patch may already be committed when cancellation arrives. Inspect
|
|
300
|
+
**operation status** and the manager before retrying; recovery-required records
|
|
301
|
+
are retained with errors. A successfully committed operation replay with the
|
|
302
|
+
**same immutable request and operation UUID** returns its original session and
|
|
303
|
+
fetched commit, rather than allocating another blank session or fetching again.
|
|
304
|
+
Changed settings, changed request or a new fresh preparation require a new UUID.
|
|
305
|
+
|
|
306
|
+
The adapter never writes/clears the source draft; native submit machinery owns
|
|
307
|
+
its optimistic commit and exact chip-aware rollback. Its temporary message block
|
|
308
|
+
is released after preparation/admission settlement, cancellation or disposal. If creation has an
|
|
309
|
+
uncertain outcome, **Check operation status** uses the same UUID before another
|
|
310
|
+
creation is allowed; an exact created conversation can be opened without sending
|
|
311
|
+
a message. Progress/transport receipts are scope-local and bounded to the latest
|
|
312
|
+
128 terminal operations; durable controller receipts own recovery after reload. Re-preview after Host restart: preview registrations and page cursors
|
|
313
|
+
are transient, even though snapshot files and durable operation/worktree records
|
|
314
|
+
are retained. Deferred naming receipts are durable and tied to the exact original
|
|
315
|
+
first message, not later messages or inherited/replaced history.
|
|
316
|
+
|
|
317
|
+
There is no physical worktree-delete operation. Disabling/removing the plugin
|
|
318
|
+
does not remove checkout files or rewrite original session logs. Any manual Git
|
|
319
|
+
cleanup is a separate user-owned task after inspecting identities and retained
|
|
320
|
+
records; do not infer cleanup authority from an archive flag.
|
|
321
|
+
|
|
322
|
+
## Install from this repository
|
|
323
|
+
|
|
324
|
+
Requires DSH/DSH peers `0.2.0-rc.2`, Node.js `>=22.19.0`, a suitable local Git
|
|
325
|
+
executable, and the ordinary session/filesystem/subprocess/sandbox/preset/plan
|
|
326
|
+
capabilities. The manifest names `@deepseek-ai/dsh-agent-preset-registry` and
|
|
327
|
+
`@deepseek-ai/dsh-plan-mode`; the Web Client mounts beside the existing
|
|
328
|
+
conversation/workspace UI. Development uses pnpm `11.7.0`.
|
|
329
|
+
|
|
330
|
+
After the staged release is approved and appears on npm, install the scoped
|
|
331
|
+
package (the similarly named unscoped package is unrelated):
|
|
332
|
+
|
|
333
|
+
```sh
|
|
334
|
+
dsh plugin --profile <profile> add @1yefuwang1/dsh-worktrees@0.2.13
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
For local development or while release approval is pending, build explicitly from
|
|
338
|
+
the private monorepo root, then opt into a local leaf installation:
|
|
339
|
+
|
|
340
|
+
```sh
|
|
341
|
+
pnpm install --frozen-lockfile --ignore-scripts
|
|
342
|
+
pnpm --filter @1yefuwang1/dsh-worktrees run build
|
|
343
|
+
# Alters the chosen profile only if you choose to run it:
|
|
344
|
+
dsh plugin --profile <profile> add -w packages/worktrees
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Or build a standalone tarball:
|
|
348
|
+
|
|
349
|
+
```sh
|
|
350
|
+
pnpm --dir packages/worktrees pack --pack-destination ../../artifacts --config.ignore-scripts=true
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
The root Git URL is not an installable plugin. The package contains compiled ESM,
|
|
354
|
+
declarations, its plain-JS Client factory, bundle patch, metadata, docs and license;
|
|
355
|
+
there are no required `prepare` or install-time build scripts. Follow the plugin
|
|
356
|
+
manager's activation/restart result and refresh the existing GUI when needed;
|
|
357
|
+
no automatic Client updates without the normal development watcher are promised.
|
|
358
|
+
Development checks never install/configure an active profile or start a server.
|
|
359
|
+
|
|
360
|
+
## Configurable worktree root folder
|
|
361
|
+
|
|
362
|
+
Open the **Plugins** page, choose **Projects and worktrees**, then configure its
|
|
363
|
+
**git-worktrees** entry. The **Worktree root folder** field edits the active
|
|
364
|
+
profile's existing `root` setting through native Host-backed settings. Enter an
|
|
365
|
+
absolute Host folder path outside your source repositories and choose **Save**.
|
|
366
|
+
**Reset to inherited default** removes only the root override. The default is
|
|
367
|
+
`worktrees/` under the harness home (normally `~/.dsh/worktrees`).
|
|
368
|
+
|
|
369
|
+
After this version is activated, saved root changes apply to **new creates live**;
|
|
370
|
+
there is no directory migration. An operation captures its root once at admission,
|
|
371
|
+
so a save during fetch/naming or a repository queue does not relocate that create.
|
|
372
|
+
Existing threads, working directories, retained files and same-operation replays
|
|
373
|
+
keep their original paths and identities. Saving this setting does not create a
|
|
374
|
+
folder, fetch Git, or grant filesystem permission.
|
|
375
|
+
|
|
376
|
+
The form uses native revision fences; conflicting/refused writes preserve the
|
|
377
|
+
path draft. Non-Host-backed/remote-browser forms are unavailable rather than
|
|
378
|
+
pretending to persist locally. Private snapshot/export/handoff storage remains
|
|
379
|
+
pinned to the root resolved at this plugin load, preserving existing previews;
|
|
380
|
+
the next normal Host/plugin load adopts the persisted root for those snapshots.
|
|
381
|
+
|
|
382
|
+
## Configuration and command/tool surface
|
|
383
|
+
|
|
384
|
+
The bundle inserts the `git-worktrees` Host entry. Change its supported config
|
|
385
|
+
through normal profile composition/settings, not the plugin's package files.
|
|
386
|
+
|
|
387
|
+
| Field | Default | Meaning |
|
|
388
|
+
| --- | --- | --- |
|
|
389
|
+
| `root` | Harness home `worktrees/` | Persisted native settings field for new worktree directories; absolute Host path, outside source repositories; snapshots retain their load-time root |
|
|
390
|
+
| `gitExecutable` | `git` | Executable resolved by the managed subprocess provider |
|
|
391
|
+
| `defaultRemote` / `defaultBranch` | `origin` / `main` | Initial preferences, never an allowlist |
|
|
392
|
+
| `commandTimeoutMs` | `30000` | Git command deadline |
|
|
393
|
+
| `fetchTimeoutMs` | `60000` | Advertisement/fetch deadline |
|
|
394
|
+
| `operationTimeoutMs` | `120000` | Overall operation deadline |
|
|
395
|
+
| `maxSnapshotBytes` | `33554432` | Snapshot byte limit (32 MiB) |
|
|
396
|
+
| `maxFiles` | `1000` | Repository/snapshot and advertised-branch count limit |
|
|
397
|
+
| `maxRefBytes` | `8388608` | Bounded Git output (8 MiB) |
|
|
398
|
+
|
|
399
|
+
The `/worktree` command and `git_worktree` agent tool share the Host controller.
|
|
400
|
+
Commands accept `<action> [JSON arguments]` or one JSON request object; no input
|
|
401
|
+
means `list`. IDs and operation/preview IDs are UUIDs. Example read operations:
|
|
402
|
+
|
|
403
|
+
```text
|
|
404
|
+
/worktree status
|
|
405
|
+
/worktree list {"includeArchived":true,"limit":50}
|
|
406
|
+
/worktree branches {"remote":"upstream","query":"feature","limit":50}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
Actions: `list`, `status`, `branches`, `create`, `start`, `branch`, `protect`,
|
|
410
|
+
`archive`, `preview`, `export`, `handoff`. `repoPath` defaults to the caller's
|
|
411
|
+
execution directory where supported. `create` requires a new `operationId`,
|
|
412
|
+
remote and remote branch; the UI also captures remote identity/settings hash and
|
|
413
|
+
requires an unchanged blank source. `sessionMode: "new"` starts empty history;
|
|
414
|
+
`"continue"` inherits through a completed turn. `status` can inspect a worktree
|
|
415
|
+
`id` or an `operationId`, not both. `export` consumes a retained `previewId`;
|
|
416
|
+
`handoff` requires that preview and its own operation UUID.
|
|
417
|
+
|
|
418
|
+
The Client uses authenticated quiet Connection RPC, not commands. Git requests
|
|
419
|
+
resolve the actual selected ordinary session; metadata-only project reads omit an
|
|
420
|
+
actor and never resume a conversation. UI Local creation delegates to the native
|
|
421
|
+
new-session service; it is never a fallback actor for Git operations. The explicit
|
|
422
|
+
project `start` operation remains available to commands and tools.
|
|
423
|
+
Versioned results are `{v:1,ok:true,data:...}` or
|
|
424
|
+
`{v:1,ok:false,error:{code,message}}`; transport and decode failures are shown inline.
|
|
425
|
+
Explicit commands remain normally logged.
|
|
426
|
+
|
|
427
|
+
`/project` (one JSON action object) and `workspace_project` share the project
|
|
428
|
+
controller: `list` (optional `projectId` filter), `create`, `update`, `remove`,
|
|
429
|
+
`bind`, and `start`. `remove` takes only `projectId` and returns
|
|
430
|
+
`{removed:true,projectId,scope:"project-metadata"}`. Repeating a committed removal
|
|
431
|
+
is safe; it never deletes directories, sessions or Git data. UI removal uses the
|
|
432
|
+
actual authenticated operator without activating an unrelated conversation;
|
|
433
|
+
commands/tools retain their genuine caller and normal mutation policy.
|
|
434
|
+
`create` takes a fresh UUID `id`, title and absolute existing `folders`.
|
|
435
|
+
Optional `mainFolder` is an absolute path matching a resulting source folder
|
|
436
|
+
canonically; omitted create uses first for API compatibility. `update.folders`
|
|
437
|
+
replaces the complete list; `update.mainFolder` can change only the default.
|
|
438
|
+
Omitted update preserves main across reordering; removing it with multiple folders
|
|
439
|
+
remaining requires a replacement (a sole remaining folder becomes main).
|
|
440
|
+
Snapshots expose `mainFolderId`. `bind` validates actual ordinary cwd/backing;
|
|
441
|
+
it cannot move a session. `start` takes a unique `operationId`, `projectId` and
|
|
442
|
+
optional native `folderId`: omitted uses main, explicit selects another folder.
|
|
443
|
+
It returns an exact blank session and never sends a prompt. Ready replay uses
|
|
444
|
+
its original receipt folder/session even after main changes; ambiguous partial
|
|
445
|
+
starts refuse duplication. `git_worktree create` accepts paired
|
|
446
|
+
`projectId`/`folderId`; the selected original folder must match its creation path.
|
|
447
|
+
Project metadata never grants Full access; cross-root thread starts retain caller
|
|
448
|
+
checks and tool mutations respect active/pending plan mode.
|
|
449
|
+
|
|
450
|
+
Public ESM exports are the root plugin/config/types, `./git`, `./naming`,
|
|
451
|
+
`./projects`, `./types`, `./client`, `./package.json` and `./locale/en.json`.
|
|
452
|
+
|
|
453
|
+
## Verification and release status
|
|
454
|
+
|
|
455
|
+
```sh
|
|
456
|
+
pnpm --filter @1yefuwang1/dsh-worktrees run test
|
|
457
|
+
pnpm --filter @1yefuwang1/dsh-worktrees run test:integration
|
|
458
|
+
pnpm --filter @1yefuwang1/dsh-worktrees run test:types
|
|
459
|
+
pnpm --filter @1yefuwang1/dsh-worktrees run test:pack
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Unit/protocol tests and temporary local-Git fixtures are not a live GUI, remote
|
|
463
|
+
credential or transport-compatibility probe. Client tests are static/pure protocol
|
|
464
|
+
checks, not a fake DOM or screenshot renderer. Browser interaction, visible slot
|
|
465
|
+
registration and light/dark appearance still require verification in the installed
|
|
466
|
+
GUI; they were unavailable during initial Client implementation.
|
|
467
|
+
|
|
468
|
+
Release tags use `@1yefuwang1/dsh-worktrees-vX.Y.Z`, matching this leaf's full scoped
|
|
469
|
+
name and version. The shared release gate/staged OIDC workflow never publishes the
|
|
470
|
+
private root or all leaves together. The workflow stages the release; a maintainer
|
|
471
|
+
reviews and approves it with npm 2FA before the version becomes publicly available.
|
|
472
|
+
See [the package changelog](<CHANGELOG.md>) and [MIT license](<LICENSE>).
|