# dsh-git-worktree 使用指南 本指南说明日常操作、恢复场景、命令和常见问题。底层状态机、CAS 与权限不变量见 [Worktree Console 架构](WORKTREE-CONSOLE-ARCHITECTURE.md)。 [返回 README](../README.md) · [English](USAGE.en.md) ## 用户流程 ```mermaid stateDiagram-v2 [*] --> Local: 打开 Git Workspace Local --> Working: 创建 Worktree Session Working --> Ready: Agent 完成并提交验收结果 Ready --> Working: 保存阶段并继续 Ready --> Preview: 预览修改 Ready --> Delivered: 跳过预览并保存 Ready --> Discarded: 放弃任务 Preview --> Working: 撤回本次预览 Preview --> Working: 保存阶段并继续 Preview --> Delivered: 确认并保存 Preview --> Recovery: Local 或 Preview 发生变化 Recovery --> Working: 安全撤回或交接 Recovery --> Delivered: 保存修改 Delivered --> Retained: 保留运行环境 Delivered --> Next: cleanup Retained --> Next: 清理环境 Next --> Working: 开始下一轮 Discarded --> [*] ``` ## Git 超时与创建失败 Windows 下,插件发起的 Git 命令自动启用命令级 `core.longpaths=true`,覆盖创建、检出、状态检查以及验收和交付,避免 Worktree 路径前缀变长导致原仓库可检出、隔离目录却失败。不修改全局或仓库 Git 配置,也不自动跳过 LFS;LFS 服务拒绝访问仍需单独处理。 在现有 `dsh-git-worktree` 插件配置中可设置(单位:毫秒): | 配置 | 默认值 | 有效范围 | | --- | --- | --- | | `gitTimeoutMs` | `120000`(2 分钟) | 1000–3600000 的整数 | | `worktreeAddTimeoutMs` | `300000`(5 分钟) | 1000–3600000 的整数 | `worktreeAddTimeoutMs` 是注册与检出的共享创建时限,不是每一步重新计时。普通 Git 查询仍使用 `gitTimeoutMs`;Worktree 删除保持 5 分钟。超时后还需要等待进程树退出及安全检查,因此失败反馈可能晚于配置时限。没有额外的环境变量配置。 创建失败时,插件只在确认进程已退出、目录及 Git 元数据属于本次创建,且残留文件原始内容可验证时清理本次尝试。清理成功会恢复创建前的会话绑定,可以重新点击创建;不会自动重复等待另一个完整创建周期,也不会修改 Local 文件或提交。 以下情况会保留现场并报告需要恢复:进程退出无法确认、路径被替换、未知文件或元数据、`initializing` / `index.lock` 等锁残留、子模块、内容转换规则,或原始内容无法验证(例如转换后的换行符)。稀疏检出保留 Git 原生的文件选择语义,但失败时不保证自动清理。此前版本留下的残留没有本次创建凭据,不会自动删除;新协议的未完成创建也不会被“恢复”或“放弃”误判为可直接接管或删除。 不要通过全局 `git worktree prune`、删除未知锁文件或递归删除目录来试错。出现需要恢复的状态时,保留错误信息及现场,核对残留归属后再处理。 ## 创建 Worktree Session ### 新 Session 1. 打开 Git Workspace。 2. 创建 blank/new Session。 3. 启用 **Worktree**。 4. 输入任务并确认。 确认前不会创建 Worktree。确认后,草稿会迁移到新的隔离 Session,Local Session 不会被偷偷切换 cwd。迁移成功后,空白 source launcher 会自动归档,避免“新会话”复用它并阻塞下一项并发任务;owner Worktree Session 会直接显示在原 Local 项目下面。 ### 侧边栏归属 Local 项目仍可包含多个普通会话。每个 Managed Worktree 只对应一个 owner Session,因此侧边栏直接显示任务会话和状态,不再把 UUID Worktree 作为独立顶级项目,也不会增加“Worktree → Session”的空层级。 - Managed 行可直接打开 owner Session,并保留官方重命名与归档;归档只影响侧边栏可见性,不会放弃任务或改变 Worktree 状态; - 普通 Fork 在本版隐藏;正确的 Worktree-aware Fork 需要创建新的 Managed Worktree 与 owner Session,将在后续版本提供; - Managed 行拖动和 Managed Workspace 的“新会话”入口会被阻止,避免产生第二个 Session 或破坏归属; - 可证明为空的预会话 launcher 会从侧边栏投影中隐藏,真实额外 Session 则保留原 Workspace 以便人工处理; - cleanup 后,历史任务仍按 Registry 归入原项目并显示“已完成”或“已放弃”; - 非托管 Workspace 和普通会话继续使用标准 Workspace 操作。 ### 已有 Local Session 模型可以调用 `worktree_create` 创建新的 owner Session。返回卡片后打开目标 Session,再让 Agent 修改代码。 ## Ready for Review Agent 完成实现和验证后调用 `worktree_ready_for_review`,保存: - 变更摘要; - changed files; - 验证状态和测试命令; - 建议 Commit Message。 Ready 不写入 Local,也不创建 Commit。Review 卡会自动执行只读 Preflight。 ### Ready 操作 | 操作 | 结果 | | --- | --- | | **预览修改** | 把任务增量写入 Local,保持未提交且可撤回 | | **保存阶段并继续** | 在 managed Worktree 内创建 Checkpoint,Local 不更新 | | **继续修改** | 使旧 Review 失效并返回当前 iteration 的 Working | | **跳过预览并保存** | 经确认后直接保存本轮增量 | | **放弃任务** | 在安全检查通过后清理 Worktree | 普通讨论不会使 Ready 失效;新的代码或文件修改会先恢复 Working。 ## Local Preview 点击 **预览修改** 后,本轮任务增量会进入 Local working tree,但尚未创建用户 Commit。 ### Preview 操作 | 操作 | 结果 | | --- | --- | | **确认并保存** | 只保存当前 Preview 对应的任务增量 | | **撤回本次预览** | 移除 Preview,返回 Worktree 继续修改 | | **保存阶段并继续** | 先安全撤回 Preview,再保存 Checkpoint | | **放弃任务** | 尝试安全收口 Preview 并清理 Worktree | Local 中与任务可分离的 staged、unstaged、untracked 修改会保留。若任务增量与这些修改重叠,操作会停止而不是覆盖。 ## Checkpoint **保存阶段并继续**适合长任务: - 阶段 Commit 只存在于 managed Worktree; - Local branch、index 和 working tree 不参与; - 保存后 Worktree 回到 clean Working; - 后续可以继续生成新的 Ready; - 最终 Local 仍只得到一个累计任务 Commit。 当前仅支持线性阶段摘要,不支持编辑、删除、重排或任意回退历史 Checkpoint。 ## Detached Preview 恢复 如果 Preview 后 Local branch/HEAD、index 或 working tree 继续变化,交付可能进入 `preview_detached`。界面会先执行只读 Recovery Preflight,再显示当前可证明安全的操作。 可能出现: - **重新尝试撤回**:移除 Preview,同时保留后续可分离的 Local 修改; - **保存修改**:把任务增量应用到当前可验证的 Local HEAD 并保存; - **让 Agent 只读分析**:分析现场,不修改旧 Worktree 或 Local; - **交接到新 Worktree**:从最新 Local HEAD 创建新环境继续恢复。 无法证明安全时,插件保留 receipt、journal 和恢复证据,不自动重试写入。 ## 常见状态 | 状态 | 含义 | 建议操作 | | --- | --- | --- | | `stale_local` | Local 在检查后变化 | 刷新并重新 Preflight | | `stale_isolated` | Worktree 在 Ready 后变化 | 重新检查或重新生成验收结果 | | conflict | Local 与任务增量重叠 | 让 Agent 在原 Worktree 中解决冲突 | | `project_acceptance_busy` | 其他任务正在预览同一 Local 项目 | 查看占用任务,等待其提交或撤回 | | `preview_detached` | Preview 与当前 Local 状态分离 | 使用 Recovery Preflight 提供的操作 | | `recovery_required` | 写入或清理结果无法完整证明 | 保留现场,按界面提示恢复 | | `cleanup_pending` | 已交付,但 Worktree 清理未完成 | 重试清理环境 | | `retained` | 已交付并保留运行环境 | 调整保留期限或手动清理 | ## 模型工具 | 工具 | 作用 | | --- | --- | | `worktree_create` | 从 Local Session 创建 managed Worktree 和独立 target Session | | `worktree_list` | 列出当前 Session 可见的关联 Worktrees | | `worktree_resume_revision` | 使旧 Review 失效并恢复当前 iteration | | `worktree_begin_next_iteration` | 为已交付且 cleanup 完成的 Session 重建 Worktree cwd | | `worktree_ready_for_review` | 保存交付报告并等待用户验收 | Preview、Finalize、Discard 和 Remove 不属于普通模型工具,由用户界面或 Host 命令控制。 ## `/worktree` 命令 ```text /worktree status /worktree list /worktree continue /worktree next /worktree finalize [ ] [cleanup|retain_24h|retain_3d|retain_manual] /worktree finish /worktree discard /worktree remove ``` - `finalize` 使用当前 Review 的建议 Commit Message; - `finish` 使用用户提供的 Commit Message; - 日常操作优先使用 Web UI,命令适合诊断或无 UI 场景。 ## 安装与排错 ### npm 安装 ```bash dsh plugin --profile web add dsh-git-worktree ``` ### Git tag 安装 ```bash dsh plugin --profile web add github:wloops/dsh-git-worktree#v0.10.0 ``` pnpm 10+ 如果阻止 Git dependency 执行 `prepare`,在 profile 的 `pnpm-workspace.yaml` 中加入: ```yaml allowBuilds: dsh-git-worktree: true ``` 然后重新安装插件。 ### 升级 Harness 后插件加载失败 Web 界面显示 **Failed to load plugins** 时,先检查错误详情和已安装版本: - 报错包含 `require("@deepseek-ai/dsh-client-runtime/client") missed the module table`:当前仍是 `0.7.2` 或更早版本,而 Harness `0.1.2-rc.1` 起已移除 `dsh-client-runtime`。 - 报错显示 `dsh-git-worktree` 等待 `conversation`,同时官方 Conversation/Sidebar 等待 `uiWorkspace`:当前是 `0.7.3` 的 Client 启动循环依赖。 上述启动环修复始于 `0.7.4`。当前开发版 DSH peers 使用最低版本 `>=0.2.1-rc.2`,不再精确锁定单个 RC;已发布的 `0.11.0` 仍精确要求 `0.2.1-rc.2`,DSH `0.2.0-rc.2` 可使用历史插件 `0.10.0`;旧版 `0.1.x` 的支持记录详见[兼容矩阵](COMPATIBILITY.md#中文)。不要绕过 peer 版本检查。下方仅以 DSH `0.2.0-rc.2` 的历史组合为安装示例,安装后完整重启 Harness: ```bash dsh plugin --profile web add dsh-git-worktree@0.10.0 ``` 重装后先 `dsh plugin --profile web list` 确认版本,再重启 Harness。注意 pnpm 的供应链策略会推迟安装刚发布的版本:新版本发布后几天内,不带版本号的 `add` 可能仍解析到旧版。需要立即安装时,把精确版本加入 profile `pnpm-workspace.yaml` 已有的 `minimumReleaseAgeExclude` 列表(如 `- dsh-git-worktree@0.10.0`)后重新安装。 从 Git tag 安装的用户改用上方 Git tag 命令安装最新 tag 即可。如果版本确认无误仍报同样错误,说明上次安装时 `prepare` 构建被 pnpm 拦截,按上文加入 `allowBuilds` 后重新安装。 ### 界面未出现 检查: 1. 当前 profile 是否为 `web`; 2. Workspace 是否为 Git 仓库; 3. 插件是否出现在 `dsh plugin --profile web list`; 4. 安装后是否重启 Harness; 5. 浏览器 bundle 是否加载当前插件版本。 ### 禁用插件后 Workspace 或会话打不开 启用插件时,侧边栏使用带 Managed 会话聚合的 Workspace 实现;禁用插件时恢复官方 Workspace。修改启用状态后,请完整重启 `dsh web` 并重新加载页面,不要仅依赖浏览器内已有模块的热切换。桌面端需完全退出 Harness(不是仅关闭窗口)再启动。重启是排除旧模块状态的取证步骤,不保证修复 Provider 冲突或样式缺失。 #### Workspace 异常:重启前后取证 1. 先不要改配置、静态禁用官方 Workspace 或手改打包 JS。记录 Host/插件精确版本、同一 profile、启用状态、安装后是否完整重启、复现时间及截图。 2. 在开发者工具 Console 运行下面的只读探针并保存输出;Network 勾选 Preserve log,记录 `/plugins/??…` 响应内是否同时出现官方 Workspace 与 `dsh-git-worktree/client.js`,保存相关错误栈(包括 `uiWorkspace has been registered`)。共享前删除路径、会话标题、令牌及其它隐私;无需导出完整 HAR。 3. 完整停止并重新启动使用该 profile 的 Host,页面强制刷新;桌面端完全退出再启动。保持同一项目与启用状态,重复探针、截图及模块记录。区分“只刷新页面”与“Host 完整重启 + 页面刷新”两次结果。若仍异常,请附两份脱敏结果,不要把重启当成已确认的修复。 ```js (() => ({ worktreeStyle: !!document.querySelector("style[data-dsh-git-worktree]"), worktreeSwitch: !!document.querySelector(".dsh-wt-pre-session"), workspaceStyles: [...document.querySelectorAll("style[data-plugin-css]")] .filter(el => /workspace/i.test(el.getAttribute("data-plugin-css") || "")) .map(el => ({ owner: el.getAttribute("data-plugin"), key: el.getAttribute("data-plugin-css"), bytes: el.textContent.length })), sidebarElements: [...document.querySelectorAll( '[class$="_root"], [class$="_searchInput"], [class$="_projectRow"]' )].filter(el => /workspaces|workspace|bhn1Oq/i.test(el.className)) .slice(0, 8).map(el => ({ classes: el.className, display: getComputedStyle(el).display, border: getComputedStyle(el).borderStyle })) }))() ``` `style[data-dsh-git-worktree]` 仅证明插件自身样式存在,不证明 Workspace CSS 或 Provider 正常。旧派生保留官方 `data-plugin` / `data-plugin-css` 标识:多个版本先到先得,且官方卸载清理可能删掉派生仍使用的样式,因此热切换与冷启动可能不同。资源修复后,每代派生使用独立的 `dsh-git-worktree/workspace-<版本>/…` CSS key,并由插件自身拥有;CSS 字节与 class map 保持上游原样。仅凭截图不能断言是该缺陷,更不能解释 issue #11 的 Host 双 Provider 原因。 如果旧版插件禁用后出现 `waiting for service: uiWorkspace`,可先卸载插件并重启以恢复界面: ```bash dsh plugin --profile web remove dsh-git-worktree ``` 如需继续使用,请安装包含此修复的版本。无需为了恢复界面删除会话历史或手工清空 Worktree registry。 ### Worktree 无法创建 常见原因包括项目根不可访问、Git 命令失败、目标目录存在未知内容,或 Session/Workspace 身份不匹配。插件不会自动删除无法确认归属的目录。 如果当前 Git 仓库还没有任何提交,Worktree 开关会先显示预检与确认提示。确认后插件只创建空的首次提交,不会提交工作区文件或暂存内容,也不会自动配置或改写 Git 身份;状态在确认期间变化时会保守停止,可检查后重试。 Project Skills 的确定性预检失败会显示具体原因及路径,例如 `Project Skills: link escapes Git repository: .claude/skills/helper`。同一真实 Git 仓库内的链接会在 Managed Worktree 中快照物化为普通文件/目录,不会链接回 Local;仓库外、Git 元数据、循环、悬空或特殊文件目标会阻断创建。不会通过切换存储目录重试此类失败,应先检查具体诊断。 在仓库根目录检查链接(只检查存在的目录,不展开链接): ```bash for dir in .dsh/skills .agents/skills .claude/skills; do if [ -e "$dir" ] || [ -L "$dir" ]; then find "$dir" -type l -print; fi done ``` 确认报错链接的目标及所需内容后,将所需目标保留在同一 Git 仓库内,或手动将不支持的链接替换为普通文件/目录;不要直接删除目标内容。已跟踪 Skill、其已跟踪目标及中间链接的改动需先提交后再创建。若错误提示未提交的 tracked Skill 改动、读取权限或快照安全上限,也应先处理对应原因,而不是反复重试。Windows 可用 PowerShell 的 `Get-Item -Force <路径> | Select-Object FullName,LinkType,Target` 检查报错路径是否为 junction/reparse point。 ### 无法预览修改 先查看 Preflight 提示:可能是冲突、Review 已过期、验收槽位占用、Local 分支变化或 Worktree 内容已变化。刷新状态后按界面提供的下一步处理。 ## 完整交付示例 1. 创建 Worktree Session: ![创建 Worktree Session](screenshots/01-create-worktree.png) 2. Managed owner 聚合到原项目,并持续显示当前任务状态: ![项目聚合侧边栏](screenshots/00-project-sidebar.png) 3. Agent 完成后生成 Ready for Review,主操作为“预览修改”: ![Ready for Review](screenshots/02-ready-for-review.png) 可从输入框上方的验收条查看摘要、文件数和验证状态;点击“查看详情”打开只读弹窗,查看文件列表、验证记录和版本信息,不需要展开聊天工具记录。弹窗内不提供交付操作,关闭后仍从底部验收条操作。 4. Local Preview 中确认实际效果;可以“确认并保存”,也可以从更多菜单“撤回本次预览”。 5. 保存时选择立即 cleanup,或按需保留运行环境。 6. cleanup 完成后,底部操作条收起;可从同一 owner Session 顶部的 Worktree 菜单选择“开始下一轮修改”。 > 界面文案以当前安装版本为准。本指南不再展示旧版“同步到 Local 验收 / 验收通过并提交”截图。 ## 本地开发 标准检查: ```bash pnpm install pnpm run typecheck pnpm test pnpm run build pnpm run check:publish ``` 用已安装依赖并完成构建的 Harness 源码做**隔离**联调(在插件仓库目录执行): ```bash DSH_HOME="$(mktemp -d -t dsh-worktree-test)" pnpm run dev:dsh -- --harness /Users/dev/Projects/open/deepseek-harness ``` 该命令自动选用 Harness 源码所需的 pnpm、初始化空 `web` Profile、打包并安装当前插件;同时将默认 Workspace 与一次性 Git 测试仓库放在隔离 `DSH_HOME` 内。打开命令打印的本地 Web 地址即可测试,`Ctrl+C` 停止。要在相同 Profile 上复查安装,保留同一个 `DSH_HOME` 值,再执行 `pnpm run dev:dsh:smoke -- --harness /Users/dev/Projects/open/deepseek-harness`。未设置 `DSH_HOME` 时会使用 DSH 的常规 Profile,隔离联调不要省略它。源码首次使用前应在 Harness 仓库完成依赖安装和构建。 其他选项:`--repo <测试仓库>`、`--port <端口>`、`--profile web`;`pnpm run dev:dsh:install` 仅安装,`pnpm run dev:dsh:remove` 从指定 Profile 卸载。`dev:dsh` 不会发布 npm 包或 push Git refs。 ## 进一步阅读 - [README](../README.md) - [Worktree Console 架构](WORKTREE-CONSOLE-ARCHITECTURE.md) - [Session Target 迁移说明](PORTING.md) - [UI 开发说明](UI-DEVELOPMENT.md) - [发布清单](RELEASE.md) - [变更记录](../CHANGELOG.md) ## 项目 Skills 首次创建及交付后的下一轮创建,会一次性携带 Local 项目中的 `.dsh/skills/`、`.agents/skills/`、`.claude/skills/`,包括未跟踪、忽略的文件、资源及空目录。不会复制整个配置目录,也不会持续同步或反向写回 Local;已有 Worktree 不会自动补拷。 `.dsh` 和 `.agents` 继续使用 Host 默认加载器;`.claude` 通过上游文件系统 Skill provider 加载,仅作用于当前插件确认的 Managed Worktree。同名 Skill 的优先级是 `.dsh`、`.agents`、`.claude`,然后全局来源。 - Local 中已跟踪 Skill 存在未提交修改、删除或与创建基线冲突时,先处理这些改动再创建;不会静默覆盖。 - 普通携带辅助文件及其 Skill 目录内新生成的未跟踪资源,不自动进入验收、checkpoint、预览或最终提交。正常已跟踪改动仍可交付;确实要交付普通辅助文件时,显式 `git add`(忽略文件需 `git add -f`),但链接物化副本适用下述例外。 - 修改、删除携带资源或产生未知资源后,清理会保留 Worktree,避免丢失这些未交付内容。复制中断也会保留恢复现场,不自动删除。 - Skill 根目录链接(目标须为目录)及其内部文件/目录链接,可以指向 Git 报告的真实仓库根内的目标,支持共享目标与多层链接;`.dsh`/`.agents`/`.claude` 父目录本身不能是链接。任何仓库外跳转、`.git`/Git 元数据、循环、悬空、特殊文件或不支持的路径均拒绝。物化展开副本合计文件上限 5000、总大小 64 MiB、检查上限 10000 项、目录/链接深度 64 层。 - 链接副本是冻结的辅助快照,不是可写别名。链接物化造成的删除/新增不会进入交付,checkpoint 与最终提交仍保留原 tracked link 条目。修改、删除、暂存物化副本,向其内部新增资源/目录或更改权限,会明确阻止验收、交付和清理。请保留 Worktree,将预期改动移至 canonical 源文件并恢复副本后重试;暂存副本不是受支持的晋升方式。独立的已跟踪 canonical 源文件仍按普通规则交付;两份都改则阻止交付,不静默选边。下一轮重新快照当前 Local。 复制使用 Node 文件 API,无需新增原生插件依赖。适用于可信本地项目;复制期间不要由其他进程替换或修改相关目录。路径检查不是针对恶意并发目录替换的原子隔离保证。