dsh-workflow-worktree
by lisycotana
DeepSeek Harness 工作流的 git worktree 隔离:每个可写工作流 agent 拥有独立 checkout,碰不到你的工作树,且崩溃后仍在
Git worktree isolation for DeepSeek Harness workflows — every write-capable workflow agent gets its own checkout that cannot touch your working tree, and survives a crash.
安装
dsh plugin --profile web add github:lisycotana/dsh-workflow-worktreeGitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试
安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗
安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。
README
目录
Git worktree isolation for DeepSeek Harness workflows — every write-capable workflow agent gets its own checkout that cannot touch your working tree, and survives a crash.
The gap this fills
@dsh-external/workflow reserves a
seam for worktree isolation and deliberately ships no implementation. Its README
is explicit: "worktree 通过 registerIsolationAdapter() 接入,未注册时明确失败."
So a workflow task declaring isolation: 'worktree' fails today:
workflow worktree isolation requested but no isolation adapter is configured
This plugin is that adapter.
Not another worktree manager
Several plugins manage git worktrees. This one is not for you to use — it is for the workflow engine to use.
| manual worktree plugins | dsh-workflow-worktree | |
|---|---|---|
| who creates it | you, or the model, on request | the workflow engine, per task |
| bound to | a name you pick | runId + taskId + session |
| lifetime | permanent until you delete it | the task's, with dirty-lane retention |
| entry point | agent tools / chat commands | registerIsolationAdapter() |
If you want to fork a workspace and keep working in it, use a manual plugin such
as dsh-worktree. If you want
spawnAgent({ isolation: 'worktree' }) to work, use this one. They coexist.
Install
dsh plugin --profile web add @dsh-external/workflow
dsh plugin --profile web add dsh-workflow-worktree
Then a workflow task can ask for isolation:
await wf.spawnAgent({
name: 'refactor-auth',
prompt: '…',
isolation: 'worktree', // ← previously a hard failure
})
What a lane is
<repo>/.dsh-worktrees/wf-<runId>-<taskId> the checkout
dsh/wf-<runId>-<taskId> its branch
<repo>/.dsh-worktrees/lanes.json the manifest
The manifest records runId, taskId, worktree path, branch, base commit,
session id, and status. Git already knows which worktrees exist; it does not
know which workflow task owned one. That binding is what survives a crash.
Inspect lanes with the worktree_lanes tool:
run-7/task-3 dirty
worktree: /repo/.dsh-worktrees/wf-run-7-task-3
branch: dsh/wf-run-7-task-3
base: d1015c2e…
changed: ?? agent-work.txt
Design commitments
Never degrade to the shared checkout. If the directory is not a git working
tree, or the worktree cannot be created, prepare() rejects. The engine then
fails the task loudly. An isolation backend that quietly runs the agent in your
tree is worse than one that refuses, because the failure is invisible until the
damage is done.
The returned agent is a new agent. The engine does
parent = isolation.parent and reads cwdOf(parent) afterwards, so the
returned agent's session must be created in the worktree. Returning the
caller's parent unchanged type-checks and silently defeats the whole plugin —
verify-contract.mjs asserts this binding directly.
Uncommitted work is never discarded. A lane that still has changes when the
task ends is retained and marked retained-dirty, with its path and branch
logged. Git refuses to remove a dirty worktree; so does this.
Your git status stays clean. The lane directory is added to
.git/info/exclude, not to a tracked .gitignore — an isolation backend must
not author changes in the tree it protects. Without this the directory reads as
?? .dsh-worktrees/ and perturbs the workspace fingerprints workflow
verification takes around each task.
dispose() is idempotent. The engine calls it on task settle, run failure,
and explicit stop.
Verified against
@deepseek-ai/dsh@0.1.0-rc.6, @dsh-external/workflow@0.1.2, git 2.47, Node 24,
Windows.
verify-contract.mjs runs the adapter against a real repository and asserts the
load-bearing invariants:
CONTRACT cwd bound to worktree : true
CONTRACT not the main checkout : true
main tree after agent write : []
dirty lane retained on dispose : retained-dirty
clean lane removed : true
double dispose survived : true
Known limitations
- No merge. This creates and recovers isolated workspaces; deciding what to do with the result is the operator's. Diff/merge-preflight are deliberately out of scope for v1.
- Dirty lanes accumulate. Retention is the safe default;
recoverLanes()prunes only lanes git no longer knows about, never live ones. - One repository per lane. A task whose cwd is outside the repository root is refused rather than isolated somewhere surprising.
License
MIT
原始 README: https://github.com/lisycotana/dsh-workflow-worktree/blob/main/README.md ↗
同类插件
查看全部 →
dsh-anchored-standard
两阶段 DeepSeek Harness 预设:先 Minimal 对齐的 bootstrap,再切完整 Standard 工具(Project2 98/99)

PicGo-Core
极致的图片上传引擎,CLI 与 API 双支持

awesome-deepseek-harness
DeepSeek Harness(DSH)及其优秀社区插件的精选指南。

awesome-deepseek-harness
DeepSeek Harness (DSH)生态系统:来自dsh-external/hub和公共dsh-plugin主题的精选插件、工具和基础设施。

AI-Novel-Writer
本地优先 AI 小说创作工作台,提供 Windows/macOS 桌面版与 DeepSeek Harness 插件开发预览,支持角色、大纲、章节蓝图、审稿修稿和本地模型。

mcp-for-stata
MCP-for-Stata:把 Stata 集成进你的 agent