# 更新日志 记录每个版本的改动。更早的版本只留在 git 历史里;宿主兼容性的逐版本实测证据在 [`docs/store-evidence.md`](docs/store-evidence.md)。英文版见 [`CHANGELOG.en.md`](CHANGELOG.en.md)。 ## 1.3.0 — 2026-10-16 本次收录自 1.2.1 起的全部改动。这里只写使用者与 Agent 能观察到的变化;它是怎么做成的不在这里。 ### 破坏性变更 - **工具改名为 `wts_worktree_space`**(原 `task_worktree_space`)。这一版同时新增了 8 个 `wts_session_tool_*` 会话工具,工具名从此统一在 `wts_` 这一组下。 **使用上要做的**:把调用里的工具名换掉。`action` 与其余参数名不变(下面两条除外)。 - **`done` 的 `merge` 现在是必填。** 原先它可选、缺省为 `false`;现在不传布尔值会被直接拒绝(E7006)。 **缘由**:合并是这套工具里唯一不可逆的一步——已经合进目标分支的要手工回退,没合的则留在任务分支上, 两个方向的代价完全不同。缺省等于替使用者做了这个决定。 **使用上要做的**:`done` 显式传 `merge: true`(合并进目标分支)或 `merge: false`(留在任务分支)。 - **收尾的「未跟踪内容」参数换成 `strays`。** 原 `cleanStray`(布尔,决定清不清构建产物)与 `keep` (要原样保留的条目名)并成一个 `strays`:`archive`(省略时的默认)、`keep`、`discard`;要保留的条目名 改由 `keepEntries` 传。 **默认行为也变了**:`archive` 会把未跟踪内容归档并清掉构建产物,所以**省略 `strays` 的收尾会把任务空间 从磁盘上删掉**;1.2.1 的缺省是把任务空间留在原地。 **工具侧不接受 `discard`**(E7007):丢弃不可逆,属于使用者自己的决定,只能在管理页面上做。需要把 内容留在原处时传 `strays: "keep"`。 - **插件自己的文件收进 `.worktree-space/`。** 原先记录写在 `<任务空间>/worktree-space.json`、说明写在 `<任务空间>/worktree-space.md`(都在任务空间根下);现在两者都在 `<任务空间>/.worktree-space/` 里, 同目录下还会出现部署根 `<任务空间>/.worktree-space/deploy/`。**旧位置不再被读取。** 操作日志仍在 `<容器根>/worktree-space-log.jsonl`,位置未变。 - **随包 skill 改名**:`task-worktree-space` → `worktree-space`,文件路径随之变为 `assets/skill/worktree-space/SKILL.md`。正文里的工具名同步更新,并补上了部署验收。 ### 新增 - **部署与验收整条链。** - 创建任务空间时可以声明 `deployTarget: docker`,此时工作区的 `.worktree-space/deploy/` 会**整份复制**到 任务空间里的同一位置;入口脚本默认 `.worktree-space/deploy/deploy.sh`,可用 `deployScript` 指名 (必须落在该目录下,否则 E4014),它实现 `up`、`smoke`、`destroy` 三个子命令。 - `up` 结束时把验收地址写进状态文件(默认 `.worktree-space/deploy/.state.json`),`smoke` 结束时把 `lastSmoke: { result, at }` 合并写进去。 - **验收围栏**:声明了 `deployTarget: docker` 的任务,在冒烟记录到 `pass` 之前,带 `merge: true` 的 `done` 会被拒绝(E5006)。 - 面板在新建对话框里给出「部署到 Docker」勾选与部署脚本站位,并新增部署卡片(up / smoke / destroy, 显示状态与验收地址)。 - 勾了部署却没有任何可部署的东西(没指定脚本、工作区里没有 `deploy.sh`、所选仓库也都不自带), 创建会被拒绝(E4015),而不是建出一个没有围栏的任务空间。 - **8 个会话控制工具**:`wts_session_tool_find`、`status`、`read`、`send`、`create`、`resume`、`wait`、 `cancel`。有了它们,Agent 能查看一个会话进展到哪、发消息纠正它、等它给出结果、在它中途停下时说出 事实、把它接回来。 - **新的 `dispatch` action**:创建一个任务空间,并把一份完整的工作交给其中的会话(`prompt`)。可以指名 该会话的写入权限(`permission`,默认继承派单方),以及是否盯住它(`watchSession`,默认盯)。被盯住的 会话在中途异常结束时会回报派单方——这种结束它自己报不出来。 - **任务空间可以登记为 DSH Workspace**:`create` 用 `registerWorkspace`(默认登记,与面板一致), `done` 用 `unregisterWorkspace`(默认随收尾撤销登记,传 `false` 可保留)。 - **任务记录在源码根下再留一份**:`<源码根>/.worktree-space/tasks/<项目>/<任务>.json`,归档写进 `<源码根>/.worktree-space/tasks-archive/`。原先在源码根下什么都不写。 - **会话权限可以放宽**:新设置项 `handoffFullAccess`(默认关)。开着的时候,派单方才能对被派会话传 `permission: "danger-full-access"`;没指名会话就要求放宽会被拒(E4011),设置关着却要求完全权限会被拒 (E4012)。被放宽的会话,其会话日志里会留下权限档位。 - **收尾多了两道守卫**:任务空间里还有会话在工作时拒绝收尾(E5012),面板在同一个判断上再做一次; 两个收尾不会同时进行。 - **失败与警告分得更细**:收尾结果按仓库给出 `conflict`、`needsCommit`、`dirtyCheckout` 三个行内标志, 并把「平白失败」与「真冲突」分开;另有一张警告码表随结果返回(例如分支留下没删、分支没删成)。 - **面板把宿主的错误码与警告说成读者自己的语言**:20 个错误码文案与 30 条警告文案进了面板的双语文案, 1.2.1 里这些一律是宿主的原文。 ### 变更 - **工具失败信息现在带错误码**,形如 `E7006: ...`;1.2.1 只给消息。 - **`maxScanDirectories` 有了上限 10000**(1.2.1 无上限;默认值仍是 2000)。 - **内置跳过目录由 23 项变为 25 项**,新增 `worktree-space` 与 `dsh-worktree-space`;默认扫描深度仍是 3。 - **`E4006` 的含义与它真实的抛出点对齐**:现在指「请求没指名可操作的东西」(没有可用的 Workspace 路径, 或仓库不在源码根内)。1.2.1 的码表把它写成「扫描撞上目录上限」。 ### 修复 - **删除围栏原先按文本前缀比较,父链上有一个链接就能穿出容器。** 现在先问该路径是不是链接、再按它真实的 指向判断,越界一律拒绝。 - **`add` 会改写任务记录的 `baseRef`。** 原先传 `baseRef` 会让记录跟着变,同一个任务的起点在两次 `add` 之后不再一致;现在记录里的起点不被改写。 - **多仓库 `add` 回滚时不收回已经建好的分支。** 那条分支留在磁盘上、任务名从此不可用,而没有任何路径能 清掉它;现在回滚把它一起收回。 - **`worktree add` 建到一半失败时,那个 worktree 不在回滚范围内。** 结果是留下一个没有记录的任务空间, 之后每次调用都撞 E2001;现在它也属于回滚范围。 - **仓库发现的目录上限缺省是无界的**(`Infinity`)。现在回落到 2000。 - **`git` 子进程原先没有截止时间。** 一个卡住的 `git` 会一直占着调用;现在 30 秒截止。 - **有仓库失败的收尾仍然以 `Task 'x' finished.` 开头。** 半途中止的收尾现在分开报,不再被读成完成。 - **冲突路径按行切分读取。** 文件名里带换行时会读错;现在按 `-z` 读原样路径。 - **扫描缓存的键不含深度与忽略集合。** 改了扫描深度看起来没生效;现在键里带着这两项边界。 ### 文档 - **新增 [`USAGE.md`](USAGE.md) 一份全生命周期手册**,分两部分:**面板手动流程**(第 1–9 节:管理页面、 新建任务空间、在里面工作、补仓库、部署验收、结束任务、冲突与「停在工作上」、排障)与**Agent 自动编排** (第 10–14 节:适用与不适用、队长与队员、工具与接口、只有人能做的事),另有错误码速查与会话控制工具 附录。1.2.1 没有手册。英文版 [`USAGE.en.md`](USAGE.en.md) 与它逐节对应。 - **README 新增「部署验收」与「高级用法:让 Agent 全自动编排」两节**,agent 那一部分随之重排。 - **[`PERMISSIONS.md`](PERMISSIONS.md) / [`PERMISSIONS.en.md`](PERMISSIONS.en.md) 补上这一版增出的运行时行为**: 部署与 `.state.json`、会话创建与权限档位、8 个会话工具,以及 E4011、E4012 两条失败边界。 - **新增「环境隔离模型」示意图并接进两个 README**,画出任务空间、容器根、源码根三者的位置关系。 - **随包 skill 的正文重写**:补上部署验收,角色词统一为 leader agent(队长)与 member agent(队员)。 ## 1.2.1 — 2026-10-06 ### 新增 - **管理页导航列底部加了「⚙ 插件设置」。** 对话框和整页两种形态共用这一行,点击直达宿主插件页里 本插件的详情配置页(走插件管理器发布的 `pluginNavigation.openBundle`,不改当前会话);从对话框 点时先关窗再跳。宿主没有提供该服务时这行什么都不做,管理页照常工作。 - **整页面板的标题下补上了「使用反馈」链接。** 此前只有对话框带这个链接,而面板恰恰是多数人的 入口——最需要报告问题的地方反而没有路。 - **标题下的描述多了第二行「使用流程」**:选择工作区 -> 创建任务空间 -> Agent处理工作 -> 结束任务 (合并回目标分支,归档遗留文档,销毁任务空间),「使用反馈」挪到这一行末尾。 ### 修复 - **README 里管理页面一节的描述与实际不符**:它说对话框的视图切换在工具栏里,而两种形态早已共用 同一条导航列。 ## 1.2.0 — 2026-10-04 本版修的都是「看得见但做不到」的事:一行路径读得出来却复制不出来,一个注册在更深布局上面的 工作区读起来像一个空目录,一个已经登记过的仓库被当成错误推回给用户。 ### 新增 - **「添加仓库」按扫描结果判定。** 决定一个仓库该不该被添加的,是**扫描列表里有没有它**,而不是它的 某个上级目录是不是已注册的工作区。这是两个不同的问题,而页面只回答前一个:注册工作区下面的仓库 本来就通过那个工作区出现在列表里,所以因为上级已注册而拒绝添加,拒绝掉的正是用户要的东西。 ### 修复 - **行上的名字和路径可以选中了。** 整行本来是一个按钮,点任何地方都会折叠;而按钮里的文字在浏览器 自己的样式表里就是不可选的——**一条读得出来的路径,复制不出去**。而折叠后出现的那些行在这个按钮 之外,所以它们复制得出来,它们的父行复制不出来。现在箭头是控件,文字不在按钮里,选中它就是普通 的事,而不是要绕开的事。给按钮加 `user-select: text` 也能得到同样的选中,但会拖来一个附带的东西: 拖选路径的动作同时落在折叠行的点击上,于是这一行会在自己的路径被复制出去的时候折叠又展开。没有 按钮要防的时候,这里什么都不用防。 - **嵌套的工作区不再被扫描两遍。** 包含判断从一个反斜杠路径拼出前缀再补一个正斜杠,所以在 Windows 上它什么都不匹配——它自己的注释承诺了忽略大小写和两种分隔符写法,两样都没做。同时注册 `E:/workspace` 和 `E:/workspace/public`,同一棵树会被走两遍,里面的仓库会报两遍。 - **默认扫描深度从两层改成三层。** 它原来是两层,是量出来的——对着一个真实工作区,第三层找到的仓库 是九十六个里的两个。但仓库是这次遍历的叶子,深度买到的只是源码根和仓库之间那些**不含仓库**的目录; 仓库全在两层之内的源码根上,多出来那一层什么都不会走到。而真正限制一次遍历的是目录预算,不是深度。 两层意味着注册在更深布局上面的工作区一个仓库都报不出来,读起来像一个空目录,而不是一个够不着的目录。 - **工作区下面一层的仓库可以创建了。** 它原来按字符串命名,现在按路径——和判断一个目录在哪用的是 同一套归一,两边不会对同一个目录各说各话。 - **任务空间按位置查找,不再按字符串。** 同一个目录的两种写法——分隔符、末尾斜杠、Windows 上不同的 大小写——是同一个地方,把它当不同的去比较,就找不到一个确实存在的任务空间。 - **420px 的确认宽度不再越过结束弹窗。** 那个宽度比它所在的对话框还宽。百分比会跟着对话框走, 而不是坚持一个尺寸。 ### 修复(复查轮) 一轮代码复查按严重度重排了一遍,挖出的全是同一类:**为失败路径写的保护,没有在失败路径上生效。** - **任务收尾时,detached HEAD 上的提交会被静默丢弃。** worktree 停在 detached 状态时 `rev-parse --abbrev-ref HEAD` 返回字面量 `HEAD`,拿它去合并就是拿目标分支合并它自己—— `Already up to date.`、退出码 0、目标分支没有前进。**任务提交从未被合并**,worktree 干净所以被删掉, 而用户看到的是「合并成功」。那些提交成了悬空对象,一次 `git gc` 就再也找不回来。删分支那条路径 早就挡了这种情况,合并这条没有。触发条件是一次没做完的 rebase,或者手工 `git checkout `。 这一版之后它会明确拒绝,而不是报告成功。 - **创建失败后的回滚留下分支。** `worktree add -b` 建的分支不会随着 `worktree remove` 一起消失, 同名重试于是撞上「分支已存在」。现在回滚把分支一起带走,带不走时会点名。 - **同一个创建错误,审计记录和调用方看到的码不一样。** 回滚重建错误对象时丢掉了 `.code`, 创建过程中的任何 git 失败到调用方那里都塌缩成 `E9001`,而审计日志记的是 `E2005`。 现在一个码只决定一次,两边共用。 - **`E7007` 被抛出却不在错误码表里**,公开时被压成 `E9001`:一句写得很仔细的拒绝, 报给调用方时变成「出了点问题」。 - **新建任务空间时勾了「保存为默认」且表单抛异常,会把刚建好的任务空间整个删掉。** 「拒绝」这条路径处理了,「抛异常」没有,而后者落进外层 catch 触发回滚——十二行之上的注释 承诺的正好相反。插件设置里改策略同理:宿主没接受时,预览值永远卡住且无提示。 - **两个工作区各有同名仓库时,「添加仓库」的勾选会串。** 元素 id 从目录名拼的, 目录名里有空格时还会生成非法 id。 - **用键盘打开任务菜单,动作会挂到鼠标最近用过的那一行上。** 行归属只记 `pointerdown`。 - **审计文案说「什么都没留下」,而它在两种情况下没看。** 容器读不到或删不掉时照样写着。 现在只有 `ENOENT` 能证明容器确实没了,其余情况都点名报告。 验收脚本这一轮也修了几处会毁掉证据的:带空格路径下全线断裂;`$page` 在 try 里赋值却在 try 外读, StrictMode 下抛错又没有 finally,于是服务器泄漏占着端口、卸载与回滚证据全丢;版本排序曾让正式版 输给自己的预发布版;矩阵报告在 5.1 上带 BOM、7 上不带,而 JSON 的存在意义正是给不看散文的门禁读的。 `store-evidence.md` 第 5 节已按本轮实测重写。**4/4 只覆盖安装、配置组合、可见性、卸载与回滚, 不覆盖任务空间的创建与收尾、容器校验和界面字段。** ### 修改 - **「已经在了」现在是提示,不是错误。** 用户要的就是这个仓库出现在列表里,它已经在;把它做成错误, 会让人去找一个并不存在的问题。它是提示——警示色、按状态播报、输入框保持打开——因为一个在红色错误 下保持打开的输入框,是在告诉读者他刚才做的事错了。他没有。 - **扫描剪枝,分类不剪枝。** 两边都剪看着更干净,而且是错的:被从分类里剪掉的嵌套工作区会丢掉 `isSourceRoot`,连带丢掉「这里能不能建任务空间」这个答案。于是遍历接受一份排除列表,每个根排除它 下面嵌套的子树;而分类仍然看到问它的每一条路径。 ## 1.1.0 — 2026-10-01 本版只调整界面文案与文档措辞,插件的行为与 1.0.8 一致。 ### 新增 - **三个视图各带一句说明。** 视图切换下方各有一行,说明这个视图里列的是什么、一行能做什 么(建任务空间还是结束任务)。它们不编号:三个视图之间没有先后,且任务空间可以从其中两个 里创建。说明行放在控件下方——它描述的正是控件所筛选的那张列表——并用摘要的弱化色,不与 控件读作一排。 ### 修改 - **管理页默认打开工作区视图。** 页面进入时停在工作区。此前停在任务空间,而那恰恰是唯一开不了 任务的视图:任务空间从工作区或仓库创建,从任务结束。切换器的顺序是**工作区、Git 仓库、任务 空间**,与「功能」一节列出的顺序一致。 - **结束任务的按钮不再填满。** 实心填充比它正上方那行提示说得更多,按钮改用提示自己的处理方 式:同色描边加 10% 的同色填充,警告态与危险态一致。 - **容器有了全名。** 插件存放任务空间的专用目录定名为「Worktree Space 容器」(下称「容 器」),容器自己那一层叫「容器根」。此前只有设置项上的一个标签、没有定义,文档与界面文案 在「任务空间根」「容器」和光秃秃的目录名之间来回摇摆。同样的改名同步进了 i18n 键,并删掉 两条已无人引用的键。 - **三处「合并回当前分支」改为「合并回目标分支」。** 那句话只在没有另选目标时才成立,而结 束对话框、按钮文案与宿主早就这么说;市场描述是唯一还在讲窄一层的地方。 - **README、面板与市场描述统一为同一句话。** 插件列表里的简介与 `package.json` 的 `description` 此前还带着改版前的句子,读者落地的那一页与 README 对插件的讲法并不一致。 - **三个使用小节按动作对象命名。** 改为「创建 / 管理 / 结束 Worktree Space」——此前的标题 按任务命名,而其中每一步作用的都是任务空间。指向它们的地方一并跟着改。 - **归档时间戳写全格式。** 读者要照着抄的地方(目录树、层次说明、布局规则、设置表格)都给出 `<任务名>-` 的完整写法,不再是光秃秃的占位符;设置表格另注明这是归档 那一刻的本地时间,精确到秒。 - **首图换成用户流程图。** 两个 README 徽章下的主图改为 `docs/img/user-story-flow.png` (创建 → 使用 → 结束的完整流程),原首图 `new-session.png` 随之删除;`package.json` 的 `files`、打包白名单与市场截图清单 `screenshots.json` 一并跟着换。 - **README 大幅精简。** README.md 419 → 328 行,README.en.md 529 → 414 行。删去 manifest 字 段表、逐版本操作矩阵、依赖表、提交失败的六种成因、合并排障步骤;保留 Beta 提示、失败边界 表、「为什么先反着试一次、再正着合」,以及各选项组合表——留下的每一项都对应读者当时正在做 的某个决定。面向用户的文档改为陈述插件做什么,不通篇用第二人称;这项调整同时覆盖 PERMISSIONS.md / PERMISSIONS.en.md 与 `docs/store-evidence.md`。 ### 兼容性 - **DSH 兼容范围为 `>=0.1.7-rc.1 <0.3.0-0`。** `engines.dsh`、两个 DSH peer 与 `dsh.compatibility.dsh` 三处写的是同一个字符串;`dshReleases` 与 `dshOperations` 覆盖 `0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2` 四个版本。 - **可用端为网页端与桌面端。** `dsh.compatibility.profiles` 声明 `["web", "desktop"]`, `dsh.client.platform` 为 `web`——桌面端跑的是同一份 web 客户端与同一个 `client/client.js`。 ## 1.0.8 — 2026-09-29 ### 新增 - **任务空间上面多一层项目目录。** 任务空间从 `<容器根>/<任务>/<仓库>/` 变成 `<容器根>/<项目>/<任务>/<仓库>/`,项目层就是源工作区的目录名,由插件推导,不用填。同一个容器根下跑多个 项目时,各项目下同名的任务(都叫 `hotfix`)各占一层,不再挤在一起;布局深度恒定为三层,源工作区本身 就是仓库时项目层与仓库层同名,得到 `repo-x/task-x/repo-x`。 - **容器根成为插件的专用区。** 第一次在它底下建任务空间时,插件写一份 `README.md` 说明这里是 Worktree 专用区、不要直接 `git init` 或 `clone`(已存在就不覆盖)。反过来说,容器根本身已经是 Git 仓库(下面有 `.git`)时创建会被**拒绝**,且一个目录都不会被建出来。 - **任务空间位置可配置。** 新增「任务空间位置」设置:默认按推荐规则从源工作区推导,也可以指定一个固定 目录。新建对话框里改了容器根并勾选「设为默认任务空间根目录」,点创建时把这两项一并写回配置。 - **归档根可配置。** 新增「归档文档位置」设置。「跟随容器根」(默认)把非 Git 产物收在 `<容器根>/archived-docs/` 下,全项目共用一份;「指定目录」收在所指定的根目录下。两档都在其下再建 `<项目>/<任务名>-<时间戳>/` 一层,归档结构与任务空间同形。 ### 修改 - **创建对话框的说明改写。** 原来按「空间建在仓库目录旁边」描述位置,任务空间移到容器根下之后这句不再 成立;现在说明的是任务空间目录建在任务空间容器根目录下,每个选中的仓库各得到一份同名分支的 worktree。 - **结束任务面板的小字与实验性功能说明同号。** 「提交代码会变更源仓库的 .git 目录可能需要提权」这句, 连同同一面板里的冲突提示和「正在开启会话」状态,从对话框正文的 14px/22px 改成 12px/18px,与它下方 那条 Beta 说明一致。 - **创建对话框宽了十分之一。** 690px → 759px,三个字段提示因此各自回到一行;结束任务对话框保持 690px。 - **兼容 DSH 0.2.0 线。** 两个 DSH peer、`engines.dsh` 与 `dsh.compatibility.dsh` 统一为 `>=0.1.7-alpha.2 <0.3.0-0`。此前 peer 停在 `^0.1.7-rc.1`,而 DSH 0.2.0 起安装与启动会强制校验 peer, 已发布的 1.0.7 装到 0.2.0-rc.1 / 0.2.0-rc.2 上会在 pnpm 运行之前就被拒(`nothing was installed`)。 `0.2.0-rc.1` 与 `0.2.0-rc.2` 随之进入 `dshReleases` 与 `dshOperations`,窗口五个版本逐个跑过安装 / 启动 / 卸载 / 回滚。 - **文档与截图同步。** README.md / README.en.md、PERMISSIONS.md / PERMISSIONS.en.md 跟着上面的改动更新; `docs/img` 里三张截图重拍。