# Changelog 本文件记录每个**已发布**版本对使用者可见的变更。 English: [CHANGELOG.en.md](./CHANGELOG.en.md) - 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。 - 安装方式、受支持的上游运行时与已知限制见 [README](./README.md)。 - 每个版本的实施证据、编号口径与发布状态见[路线图 §进度总账](./docs/plans/active/2026-09-12-multi-root-workspace.md#进度总账);GitHub Release 的正文由 `scripts/release-notes.mjs` 从 commit 历史生成,是本文件之外的完整原始清单。 ## [0.1.13] - 2026-10-31 ### Added - **共享 Registry 后台恢复(默认开启)**:多个 Host 共享登记表时,可重试的权威争用、断线或存储打开失败会以退避和抖动自动重试;follower 重新同步已跟踪主根后才视为恢复。`multi-root-registry` 的 `backgroundRecovery: false` 可关闭后台重试,按需恢复仍可用;配置错误和状态不明的写入仍需修正配置或重启。恢复期间继续保留拒绝边界,每个新操作仍须授权,结果不明的变更不会自动重放。只读诊断信息和去重的状态转换日志有助于排查故障([ADR-0026](./docs/decisions/ADR-0026-registry-background-recovery.md))。 ### Fixed - **Files 页签打开文件后保留所选根**:打开附加根中的文件导致 Files 页签卸载并重新挂载时,保留该页签所选的根、目录展开状态与滚动位置;列表尚未应答或请求失败不会误将选择切回主根,关闭页签时会清理监听与目录树资源。 - **共享权威恢复的安全性和一致性**:介质与锁绑定校验失败后重试不能绕过校验;恢复时同步根投影并批量发布一致的状态,空快照能清除过期边界,失败的恢复轮次不再产生重复通知。Windows 连接握手期间保持请求计时器有效,避免进程提前退出。 ## [0.1.12] - 2026-10-30 ### Added - **多个 Host 可同时使用附加根(默认开启)**:bundle 现默认配置共享存储权威(`sharedStorageRoot`)——此前只有持有 store 租约的 Host 能使用附加根,共享同一登记的第二个 Host 一律 fail-closed。现在唯一 owner 打开存储介质并管理持久化,其余 Host 经本机内核认证的 IPC 通过各自的 Registry facade 读写;所有变更与每个新操作的授权在 owner 处统一排序:撤权后的新操作立即被拒,撤权前已准入的操作可以完成,断线/失联时保留既有拒绝边界;owner 退出或崩溃时 follower 竞选接管并以新 epoch 恢复,丢失的已提交应答不会自动重放。已复制的执行参数与过期句柄不能顶替新准入,同步 confine/spawn 入口保持原有返回形状;fs、sandbox、shell/PTC/agent PTY、LSP、Files/watch、指令与 Skills 消费路径全部接入准入。未启用 `sharedStorageRoot` 的 profile 保留旧的「争用即 fail-closed」行为([ADR-0024](./docs/decisions/ADR-0024-registry-operation-admission.md)、[ADR-0025](./docs/decisions/ADR-0025-shared-registry-authority.md)、[共享服务架构](./docs/architecture/registry-authority-service.md))。 - **精确支持 DSH `0.2.1-rc.5`**:相对 `0.2.1-rc.4` 没有触及本插件的接口变化,不新增适配分支;开发 pin 保持 `0.2.2-alpha.2`,支持矩阵现为 20 个精确版本。 ### Changed - **依赖安全下限提升**:本插件直接依赖的 `zod` 下限升至 `^4.6.7`;开发侧 `vitest` 升至 `^4.1.12`,并显式声明 `@modelcontextprotocol/sdk` `^1.32.2` 以保留 GenAI `mcpToTool` 的可选能力。完整开发树的公告告警从 1 critical / 17 high / 27 moderate 降为 5 high / 6 moderate;宿主树中剩余告警均由 DSH 精确 pin 引入(如 zod `4.4.3`、Undici `8.11.2`),不随本插件版本解决([依赖安全排查](./docs/troubleshooting/dependency-security-alerts.md))。 ## [0.1.11] - 2026-10-29 ### Added - **精确支持 DSH `0.2.1-rc.4` 与 `0.2.2-alpha.2`**:`rc.4` 探针全绿、无需任何适配改动;`0.2.2-alpha.2` 把工具执行从 `dsh-tools` 拆出为独立执行器,`AgentRegistry` 新增注入 `sessionProjections`,本插件源码均不受影响。上游新增 `SandboxExecutionPolicy.additionalWritableRoots`(原生与 fork 无关的第三路可写根),宽授权 provider 与其正确复合——新回归用例钉住双方 grant 同时生效。开发 pin 提升到 `0.2.2-alpha.2`(cordis `4.0.6-alpha.1`,Node ≥24.9)。客户端 fork(files-tree、open-in-app)已对齐 `0.2.2-alpha.2` 基线——hover 规则移入 `@media (hover: hover)`,open-in-app 失败反馈改为应用级 `shell.overlay` outcome toast。 - **升级通道与 CI**:CI verify 矩阵改为按已知名单分流——`0.1.*` / `0.2.0` / `0.2.1` 走 Node `22.19.0`,其余(含 0.2.2 及以后)走 Node `24.9.0`;升级脚本在重指旧版本时会顺带钉住该版本自带的 cordis 生态(plugin-loader/group/include、schemastery、cosmokit),避免与提交锁文件的 alpha 行混树。 ### Fixed - **Registry Authority 重复通知引发的 Skills 刷新反馈循环([Issue #24](https://github.com/cherrchen/dsh-plugin-multi-root-workspace/issues/24))**:第二个 DSH 进程争用登记表 lease(或存储打开失败)时,附加根 Skills 的每次查询都经 `refresh()` 重试 lease;失败后 `setRegistryAuthority(false)` 即使状态没有变化也通知监听者,使 Skills 缓存失效并广播 `skills/change`,收到事件的客户端立即重查,形成无界反馈循环——等待方 Host 空闲时持续占用约一个 CPU 核心、内存增长直至 V8 OOM,零附加根同样可触发。现在仅在实际状态变化时通知;lease 重试、持锁方退出后的接管、以及「权限不可用时仅主根可写」的 fail-closed 语义不变([故障排查](./docs/troubleshooting/registry-owned-by-another-process.md#skills-查询导致持续刷新issue-24)、[ADR-0023 修订](./docs/decisions/ADR-0023-multi-root-skill-discovery-and-invocation.md#4-生命周期缓存与撤销))。 ## [0.1.10] - 2026-10-25 ### Added - **附属根 Skills**:发现附属目录的 `.dsh/skills` 和 `.agents/skills`,首个模型步骤可见名称与描述,正文按需加载。主根使用 `/skill-name`;附属根始终使用 `/alias-id:skill-name` 命名空间引用(Slash 菜单可补全,模型经原生 `skill` 工具用内部名称调用)。新登记的 `inherit` / `read-write` 根默认开启,`read-only` 根默认关闭;Workspace Folders 对话框提供独立的 Skills 开关与 `aliasId` 编辑,Settings → Plugins → Multi-root Workspace 的「启用附属根 Skills」全局开关默认开启,关闭只阻止新发现与调用、保留每根选择。升级时旧 `inherit` / `read-write` 登记默认开启 Skills;持久化迁移保留原有 grant,但旧版写回可能剥离 `aliasId` 与手动开关,**不保证 Skills 配置无损降级**(降级前可备份 `$DSH_HOME/storages/multi_root_workspace.json`)。只读根开启 Skills 不授予写权限;禁用不回收已投递正文或已启动进程([ADR-0023](./docs/decisions/ADR-0023-multi-root-skill-discovery-and-invocation.md))。 - **精确支持 DSH `0.2.1-rc.3`**。上游 `rc.2`→`rc.3` 的差异全部为新增(新 sidebar 槽位、导航 pins、DeepSeek `/models` 列表),不需要新增适配分支;开发 pin 提升到 `0.2.1-rc.3`(cordis `4.0.5` 不变)。 ### Fixed - **Workspace Folders 面板与上游 UI 对齐**:设置开关行布局、Skills 开关收入图标动作区、按钮背景只出现在 hover、保存期间动作外观保持、根策略与生效访问合并为一个标签;移除上移/下移排序按钮(排序接口保留,供后续拖动排序)与对话框顶部的权限说明文字。 - **命名空间 Skill 引用的展示**:已发送的 `/alias-id:skill-name` 引用按普通用户文字渲染,不再携带独立按钮样式、高亮或点击预览(ADR-0023 同日修订);普通会话的 activity/title 更新不再误关闭已打开的 Skill 正文预览。 ## [0.1.9] - 2026-10-20 ### Added - **可选 Auto Review(默认关闭)**:主包新增 `./auto-review` 子路径导出与 `multi-root-auto-review` patch 行——fork 上游实验性「自动授权审查」,向 Reviewer 补充附加根的审查上下文:当前工作区拓扑、各根有效访问级别与实时指令文件。该行出厂 `disabled: true`,关闭时不挂载 reviewer 或 review context、不注册 Auto preset;普通支持矩阵不变,仅 DSH `0.2.1-rc.2` 可启用——在任何其他版本上打开会响亮失败,不会静默降级。启用方式:在插件管理器的行列表中打开 `@dsh-electron/dsh-plugin-multi-root-workspace/auto-review` 行(无热重载的 profile 按提示重启),或在 profile 的 `cordis.patch.yml` 中置 `disabled: false`;context 与 reviewer 共用这一个开关。 - **启用后接管官方 reviewer**:同一个开关挂载多根 review context 与 fork reviewer,并在运行时停止同组官方 `@deepseek-ai/dsh-experimental-auto-review` 行——官方 bundle 位于主包前后均可,接管只改运行时状态、不写回官方的持久配置;官方 bundle 未被选择时该行独立运行(自带注册 Auto preset)。关闭后官方按原配置随 reload/restart 恢复,不自动重选 Auto;任何存活 Auto owner 的卸载沿用官方 Auto → Full access 语义。曾以本地 tarball/link 安装过旧独立 companion 包的 profile,须先移除其 bundle 与依赖再启用本行(残留 companion 与内置入口共存会被明确拒绝)。使用说明见 [src/auto-review/README.md](./src/auto-review/README.md)([ADR-0021](./docs/decisions/ADR-0021-auto-review-context-companion.md)、[ADR-0022](./docs/decisions/ADR-0022-auto-review-loader-entry.md))。 ## [0.1.8] - 2026-10-18 ### Fixed - **DSH 0.2.0 上权限设置页不可用**:以 `link:` 方式安装时,插件把只作为宿主服务消费、自身从不加载的可选包(`dsh-lsp` / `dsh-lsp-stdio` / `dsh-working-directory` 等)解析到检出目录自己的 devDependencies,版本统一的宿主被误判为 `mixed`;同时两个 provider 替身行 inject 兼容门禁而上游 `fs-sandbox` / `sandbox` 已被无条件禁用,门禁一旦拒绝,`ctx.fs` / `ctx.sandbox` 消失并连带 `ctx.shell` 与 `permissionPresets` 瘫痪(`permissionPresets/catalog` 报 `service-unavailable`)。可选包现按"谁加载副本、经哪个锚点"分为运行时加载、宿主服务与 runner 锚定三类——插件根内的宿主服务副本不再作证,Windows ACL 包改从 `dsh-sandbox-local` 锚点取证;两个 provider 行不再 inject 门禁,在被拒安装上退化为上游等价行为,宽授权行的门禁不变([ADR-0009 修订](./docs/decisions/ADR-0009-dsh-compat-contract.md#修订2026-10-18permissionpresetscatalog-事故误报检测--被门禁的-provider))。 ## [0.1.7] - 2026-10-17 ### Added - **Files 页签内浏览附加根**:文件树 header 新增根切换器(伪装成路径标签的菜单入口,列出主根与全部附加根及其状态);选中附加根时由逐字节复刻的上游 Files 树接管树区——行高、图标、缩进、空态与原生逐项一致,原生 reload 由 header 原位同款图标钮顶替,切回主根即完整还原。原生 open-in-app 按钮由复刻件顶替并把目标换成选中根([ADR-0015](./docs/decisions/ADR-0015-files-tab-plugin-owned-browsing.md)、[ADR-0016](./docs/decisions/ADR-0016-files-tab-native-tree-fork.md))。面板行带访问级别徽标,所有路径用同一 `PathCopy` 控件一点即复制;只读 → 读写升级经确认层;添加行的权限选择器为锚定下拉。 - **附加根访问级别升级为三态**:`add [--inherit|--read-only|--read-write]`(或面板添加行选择)。`inherit` 跟随会话模式——新登记的默认值,旧版插件登记的可写记录也迁移为 `inherit`;`read-only` 可读、可浏览、参与 LSP 与指令注入,但任何模式(包括 `danger-full-access`)都不授予写权限;`read-write` 固定在全局只读会话里仍可写。`/workspace-folders access inherit|read-only|read-write` 与面板按根切换(扩权要求该根此刻可用且不重新授权路径)。持久化布局向下兼容:旧版本插件把只读记录判为无效而非升级为可写([ADR-0013](./docs/decisions/ADR-0013-per-root-and-per-tool-access.md)、[ADR-0017](./docs/decisions/ADR-0017-three-state-root-access-and-sandbox-modes.md))。 - **Full-access 也强制执行拒写边界**:shell / pwsh 执行器、`run_code`(PTC)与 agent PTY 在 `danger-full-access` 下绕过 `confine`,进程围栏为它们统一套用受限内核 profile(macOS Seatbelt、Linux bwrap——上游选定 Landlock 的主机同样改走 bubblewrap,bwrap 不可用时该组合在启动前拒绝),显式只读根与被工具封顶的根在该模式下依旧拒写;fs fence 读取同一份 deny 集([ADR-0017](./docs/decisions/ADR-0017-three-state-root-access-and-sandbox-modes.md))。 - **受限 Full-access 保护 `$DSH_HOME`**:只要存在任何拒写边界(只读根、工具封顶成员或注册表权限不可用),home 目录就进入 deny 集——存根存储、注册表 lease 与用户 profile 都在其中;零附加根且注册表健康时 Full-access 与上游逐字节一致([ADR-0017](./docs/decisions/ADR-0017-three-state-root-access-and-sandbox-modes.md))。 - **面板用户终端不受约束**:进程围栏只对 env 带 `DSH_PTY_SESSION_ID` 的 spawn 生效(agent PTY 由 terminal-bash backend 盖章);你在面板打开的终端属于用户行为,任何模式直通([ADR-0017](./docs/decisions/ADR-0017-three-state-root-access-and-sandbox-modes.md))。 - **Windows 上 Full-access 的局部拒写**:随包提供需管理员安装的每用户特权 broker——安装器只向专用虚拟服务账户 `NT SERVICE\DshMultiRootBroker-<安装哈希>` 授予固定 LSA 权限(`SeServiceLogonRight`、`SeCreateTokenPrivilege`、`SeAssignPrimaryTokenPrivilege`、`SeTcbPrivilege`、`SeDebugPrivilege`、`SeImpersonatePrivilege`),不为宿主用户提权;broker 为受限子进程构造普通 deny-only 组 token,runner 读回验证后才放行。未安装 broker 时该组合拒绝启动;Windows 执行仍如实报告 partial 边界([ADR-0020](./docs/decisions/ADR-0020-windows-normal-deny-groups.md))。 - **per-tool 写权限封顶**:`multi-root-scope` 行配置 `toolAccess: { <工具名>: 'read-only' }` 后,该工具永远不能写任何附加根(主根不受影响);封顶经 `tools/execute` 的真实 dispatch 上下文执行,非法配置 fail closed([ADR-0013](./docs/decisions/ADR-0013-per-root-and-per-tool-access.md))。 - **附加根数量上限**:每个主根默认最多登记 16 条附加根记录(`maxAdditionalRoots` 可调至 64);超限的新增被拒绝,历史超限记录照常授予。列表如实显示 `N of LIMIT`([ADR-0014](./docs/decisions/ADR-0014-root-limit-and-provider-conflict.md))。 - **Provider 冲突检测**:另一插件也替换 `ctx.fs` / `ctx.sandbox` 时,多根行响亮失败并拒绝一切授予,而不是依赖装载顺序([ADR-0014](./docs/decisions/ADR-0014-root-limit-and-provider-conflict.md))。 - **精确支持 DSH `0.2.1-alpha.3`、`0.2.1-alpha.4`、`0.2.1-alpha.5`、`0.2.1-rc.1` 与 `0.2.1-rc.2`**。上游 `alpha.3` 起 `dsh-storage-domain` 把 `zod` 固定为 `4.4.3`,两个 zod 副本的类型互不兼容,域 schema 改由存储域自身解析的 zod 构建;`alpha.4` 起上游版本需求优先读 `engines.dsh`,本插件仍以 `peerDependencies` 为唯一版本契约。开发 pin 提升到 `0.2.1-rc.2`(cordis `4.0.5`;`alpha.3`–`alpha.5` 的 cordis 为 `4.0.5-alpha.2`)。 ### Changed - **模型侧拓扑文案重写**:按当前模式与平台如实陈述授权——可写与只读根分组列出,声明 cwd/worktree 切换不改变授权、授权变化只约束后续操作与新进程;配置封顶工具时点名;Windows 附带 restricted-token partial-enforcement 与读不受其 confine 的说明([ADR-0013](./docs/decisions/ADR-0013-per-root-and-per-tool-access.md))。 ### Fixed - **注册表权限不可用不再读作「没有限制」**:读到空根表的进程(争用、存储故障、配置非法)曾在 Full-access 下放行一切写;现在 `danger-full-access` 与 `workspace-write` 都只授予主根写权限(共享平台临时区不再可写),显式拒写边界仍优先,接管 lease 后恢复([ADR-0017](./docs/decisions/ADR-0017-three-state-root-access-and-sandbox-modes.md))。 - **改名祖先目录不能再解除只读边界**:此前把被拒根的父目录改名即可把整棵树搬出路径拒写边界;现在 Seatbelt 同时拒写被拒根的每个祖先目录本身(`(literal …)`),bwrap 把祖先自绑为挂接点使 rename 返回 EBUSY;Windows 用不共享删除的目录句柄钉住根及祖先,直到受限 Job 后代排空,防止 shell 搬走目录后经宿主文件工具绕过。祖先目录的元数据或改名操作会受相应机制限制([ADR-0017](./docs/decisions/ADR-0017-three-state-root-access-and-sandbox-modes.md)、[ADR-0020](./docs/decisions/ADR-0020-windows-normal-deny-groups.md))。 - **负授权不随排序、消失或冲突丢失**:存量重叠登记双方撤销成员授权,但可信记录的拒写边界仍保留;新增根也检查 missing / redirected 根的保留边界。全局只读会话追加固定读写根后统一应用 deny,无法表达子树减法的后端在启动前拒绝。 - **Windows 拒写前检查全部根的硬链接**:任一根存在多链接文件或不可检查节点时,在任何 ACL 写入前拒绝启动,避免改写 pnpm store 或其他链接的共享对象。新增宿主维护命令 `/workspace-folders isolate-profiles [--apply]`:默认只读检查,显式 apply 仅将 profile 导入配置设为 copy;存量依赖仍需按报告重装,不修复历史 ACL([ADR-0020](./docs/decisions/ADR-0020-windows-normal-deny-groups.md))。 - **Linux 上消失的拒写根失败关闭而非放行**:deny 根的 bwrap 挂载恢复为强制项——目录在登记后或 profile 构造后被删除时命名空间搭建失败、命令不会执行,不再出现在可写父挂载下被重建写入的缺口([ADR-0017](./docs/decisions/ADR-0017-three-state-root-access-and-sandbox-modes.md))。 - **附加根重新登记保留原权限**:命令与面板在未显式选择访问级别时不发送默认值,避免 revive 把只读登记静默升级;达到根上限时仍可从面板重新登记既有的不可用项。 - **面板兼容旧宿主的根列表**:旧响应缺少 `limit` / `count` 时仍可显示和操作,显式非法值仍拒绝。 - **非法 toolAccess 的拓扑文案与执行一致**:模型明确看到所有附加根写被拒,不再被告知 read-write 登记可写;根上限配置 `null` 同样 fail closed。 - **安装副本在 Windows(DSH 0.1.7-alpha.1+)上的受限命令恢复可用**:发布的 v0.1.6 从 npm/tarball 安装后,独立 Windows runner 在首行之前就死于 `ERR_MODULE_NOT_FOUND`——它的静态模块图 import 的上游包无法从插件安装目录解析,受影响版本上配置了附加根的会话里每条受限命令都会失败。runner 的静态图现在只含 `node:` 内置,上游 ACL 包改为从上游 runner 自身位置按包自引用加载。 - **Windows 上的网络与设备根被拒绝**:UNC(`\\server\share`)、`\\?\`、`\\.\` 与映射网络盘此前会被当成普通附加根登记;现在在任何文件系统触碰之前以 `unsupported-path` 词法拒绝,存量记录标记为 `invalid`,受限执行侧 fail closed(`SandboxUnavailableError` / 退出 127),绝不静默放开([ADR-0011 修订](./docs/decisions/ADR-0011-multi-root-workspace-consumers.md))。 - **Windows runner 在 spawn 前重新验证根**:授权 ACL 之后、启动子进程之前重新确认每个根仍存在且是同一 canonical 目录,并要求 `--temp` 已存在;不满足即退出 127,不启动无约束进程。 - **Windows 上「在文件管理器中显示」不再误报失败**:`explorer.exe` 成功时也返回 1,win32 现在接受退出码 0/1。 - **面板文件端点拒绝反斜杠路径**:POSIX 上 `..\..\x` 此前会解析到所选根内部;现在词法拒绝。 - **Windows broker 放行 UAC 过滤调用方并诊断打包子进程**:非提权 UAC 管理员发起的受限命令此前被 broker 以「unrestricted 身份」拒绝;现在只拒绝携带 restricting SID 或 AppContainer 的调用方,Store/MSIX 版子进程(如 WindowsApps 别名的 `pwsh.exe`)在启动前给出指向 MSI/ZIP 版的诊断。升级后需用 `install.ps1` 重装一次 broker 才会生效([ADR-0020 修订](./docs/decisions/ADR-0020-windows-normal-deny-groups.md))。 - **面板文件树调用可中止**:组件卸载、路径或会话变化时取消在飞的 `files` / `readFile` 调用,过期响应不再渲染为错误。 ### Changed - **Windows 受限 shell 行为说明**:受限 shell 是 pwsh(Git Bash/MSYS 在 restricted token 下无法启动,与上游 runner 一致);在插件 runner 下 confined 子进程能收到 Ctrl+C 且 runner 镜像其退出码,而上游 runner 的子进程因继承 ignore-Ctrl+C 标志收不到(两者均为既成事实,见 [ADR-0011 修订](./docs/decisions/ADR-0011-multi-root-workspace-consumers.md))。 - 安装提示补充:被 `koffi` 构建授权打断的首次安装,在授权后若插件未进 `dsh.profile.bundles`,需一次 `remove` + `add` 完成激活([故障排查](./docs/troubleshooting/install-stops-at-build-approval.md))。 ## [0.1.6] - 2026-10-11 ### Added - 精确支持 DSH `0.2.1-alpha.1` 与 `0.2.1-alpha.2`。动态 working directory 与 Session origin 分离:cwd 切换不改变注册表归属或授权根;新增 Worktree 管理、附加根 LSP 路由、Windows 内核级多根,以及 Workspace Folders 附加根文件浏览与预览。 - 附加根说明文件的 cwd 切换恢复与补发行为,避免上游撤回后遗漏仍有效的说明。 ### Changed - 附加根文件树与 LSP 按根隔离;Worktree 操作不改变根注册表授权。 ## [0.1.5] - 2026-09-30 ### Added - 精确支持 DSH `0.2.0-rc.1` 与 `0.2.0-rc.2`,保留此前全部支持版本。CI 会在所有启用的操作系统上验证兼容合同中的每个版本。 ## [0.1.4] - 2026-09-25 在 `v0.1.3` 的精确 allowlist 契约不变的前提下,把受支持的上游运行时扩展到 `0.1.7-rc.2`;设计取舍仍见 [ADR-0009](./docs/decisions/ADR-0009-dsh-compat-contract.md)。 ### Added - **支持上游运行时 `0.1.7-rc.2`**。相对 `0.1.7-rc.1`,`confine`、指令渲染、session format 4、工具失败位、面板图标、当前会话目录、进程内启动和 bash 执行的形状都没变,适配层没有新分支。cordis 仍是 `~4.0.4`。`rc.1` 起的安装期 peer 门禁仍然要求这个精确版本出现在 `peerDependencies` 里。开发 pin 仍是 `0.1.5-rc.2`。 ## [0.1.3] - 2026-09-24 在 `v0.1.2` 的精确 allowlist 契约不变的前提下,把受支持的上游运行时扩展到 `0.1.7-alpha.2` 与 `0.1.7-rc.1`;设计取舍仍见 [ADR-0009](./docs/decisions/ADR-0009-dsh-compat-contract.md)。 ### Added - **支持上游运行时 `0.1.7-alpha.2` 与 `0.1.7-rc.1`**。相对 `0.1.7-alpha.1`,`confine`、指令渲染、session format 4、工具失败位、面板图标、当前会话目录、进程内启动和 bash 执行的形状都没变,适配层没有新分支。`0.1.7-rc.1` 起,`dsh plugin add` 会按 `peerDependencies` 拒绝不满足当前运行时的插件,所以这两项必须出现在精确 allowlist 里。开发 pin 仍是 `0.1.5-rc.2`。 ## [0.1.2] - 2026-09-22 在 `v0.1.1` 的精确 allowlist 契约不变的前提下,把受支持的上游运行时扩展到 `0.1.6-alpha.2` 与 `0.1.7-alpha.1`;设计取舍仍见 [ADR-0009](./docs/decisions/ADR-0009-dsh-compat-contract.md)。 ### Added - **支持上游运行时 `0.1.6-alpha.2`**,与 `0.1.5-rc.2`、`0.1.6-alpha.1` 一起进 allowlist。该版本的 `confine` 异步形状与 instruction renderer 名字与 `0.1.6-alpha.1` 相同;客户端当前会话改从目录行的 `retainedBy.mainView` 读取(见 Fixed)。开发 pin 仍是 `0.1.5-rc.2`。 - **支持上游运行时 `0.1.7-alpha.1`**。`confine` 与 instruction renderer 的形状没变,但这一版有几处必须适配:session format 4 不再接受 `kind: 'plugin'`,附加根指令改用本插件自己的 source kind `multi-root-workspace`(format 3 及更早仍是 `plugin`);工具失败位从 content block 移到消息本身;面板图标从像素命名改为 Regular 线宽;进程内启动改为 `createRuntimeResolution` + `PluginPackages`;bash 执行从 `shell.run` 改为 `shell.execute().result()`。该版本的 `dsh` 依赖 cordis `^4.0.3`,探测时必须把 cordis 钉到这个版本,否则两份 `@deepseek-ai/dsh-tools` 会让工具调度用的 Symbol 对不上、工具调用在第一步失败。开发 pin 仍是 `0.1.5-rc.2`。 ### Fixed - **`0.1.6-alpha.2` 上已打开的会话被面板显示成「当前没有活动会话」**:该版本从 Session 目录快照删除了 `current`,当前会话改由主视图 `retain(..., { source: 'mainView' })` 持有,投影在目录行的 `retainedBy.mainView`。`src/compat/client-session.ts` 用结构探测同时认两种形状;目录有行但没有主视图时仍显示空态,不会把 `ids[0]` 当成当前会话。 ## [0.1.1] - 2026-09-16 `v0.1.0` 之后的**硬化批次(H1–H4)**:不新增面向使用者的"功能",而是补齐跨进程、面板权威、上游兼容性与附加根指令四类边界。设计取舍见 [ADR-0007](./docs/decisions/ADR-0007-registry-authority-lease.md)、[ADR-0008](./docs/decisions/ADR-0008-panel-session-derived-authority.md)、[ADR-0009](./docs/decisions/ADR-0009-dsh-compat-contract.md)、[ADR-0010](./docs/decisions/ADR-0010-additional-root-instruction-scope.md)。 ### 升级注意(不兼容变更) - **首次 `dsh plugin add` 会失败一次,四种安装来源皆然**:本版本新引入原生依赖 `koffi`(Windows 上 Registry Authority 的 FFI 封装),而 pnpm ≥10 默认不运行依赖的构建脚本,因此第一次 `add` 会以 `[ERR_PNPM_IGNORED_BUILDS]` 退出、插件不会进 `dsh.profile.bundles`。`dsh` 会把待决项留在该 profile 的 `pnpm-workspace.yaml` 里(`koffi: set this to true or false`),改成 `true` 再执行一次 `add` 即完成。`v0.1.0` 的 npm / tarball 来源没有这一步。详见[故障排查:安装停在构建授权](./docs/troubleshooting/install-stops-at-build-approval.md)。 - **支持的上游运行时收窄为精确清单 `0.1.5-rc.2`、`0.1.6-alpha.1`**(原先是 `>=0.1.2-alpha.4 <0.2.0` 范围)。宿主版本不在这两个之一,或若干 `@deepseek-ai/dsh-*` 包混装了不同版本时,`fs` / `sandbox` / `registry` / `instructions` 四行**不启动**,组合退化为"未装这个插件"并在启动时打印说明。理由是这个插件替换的是围栏本身、靠识别上游实测出的方言 argv 形状工作,而 npm 语义化范围等于对未验证版本做承诺([ADR-0009](./docs/decisions/ADR-0009-dsh-compat-contract.md))。诊断步骤见[故障排查:DSH 版本不在支持矩阵上](./docs/troubleshooting/unsupported-dsh-release.md)。**若你仍在 `v0.1.0` 时代实测可用的 `0.1.2-rc.1` 运行时上(例如某些已安装的桌面端自带运行时),请先升级该运行时,否则本版本不会生效。** - **面板不再接受客户端指名的根**:所有面板端点必填 `sessionId`,主根只来自 host 侧的 `session.header.cwd`;客户端 `primaryRoot` 字段与 `sandboxPolicy` 回退已删除。浏览器当前没有活动会话时,面板显示"当前没有活动会话"并且不向 host 发请求([ADR-0008](./docs/decisions/ADR-0008-panel-session-derived-authority.md))。 ### Added - **跨进程 Registry Authority(H1)**:同一 `$DSH_HOME` 上同时只允许一个 DSH 进程持有根登记表(POSIX `flock` / Windows named semaphore,进程退出或崩溃由内核释放锁)。争用方 fail-closed——发布空 scope、注册表写操作报 `registry-contended`;持锁者退出后,`/workspace-folders list` 或面板刷新即经 `refresh()` 接管([ADR-0007](./docs/decisions/ADR-0007-registry-authority-lease.md))。 - **附加根自身的指令文件进入模型上下文(H4)**:附加根**顶层**的 `AGENTS.md` / `CLAUDE.md` 在会话第一步之前注入;本会话**成功** `read` / `write` / `edit` 触碰过的子目录(含被触碰文件的每个祖先目录,直到该附加根)在其目录被考察到时增量补投;文件内容变化只重发该文件,文件或根消失时**显式撤回**。全部附加根共享 64 KiB 预算,以 `user` role 的 `{ kind: 'plugin', form: 'instructions' }` 消息投递(不是 `systemPrompt`)。上游的指令发现从会话 cwd 向上走,永远到不了附加根,这是本项存在的原因([ADR-0010](./docs/decisions/ADR-0010-additional-root-instruction-scope.md))。 - **支持第二个上游运行时 `0.1.6-alpha.1`**,与基线 `0.1.5-rc.2` 一起进 allowlist;两者都跑过完整矩阵(`confine` 的同步/异步形状差异、instruction renderer 改名、两种 LLM wire 协议均由适配层与 smoke 吸收)。 - **`pnpm compat:check`**:allowlist / `peerDependencies` / 开发 pin / 已安装树四者一致性门禁,是 CI 的第一步。 - **`multi-root-compat` 启动门禁行**:版本判定变成其余安全相关行的前置条件,而不是一条日志。 - **按周升级车道**(`upgrade.yml`):自动重指最新上游 pre-release 并跑完整矩阵,只读权限、不提交、不自动扩大 allowlist。 - 两个故障排查条目:[DSH 版本不在支持矩阵上](./docs/troubleshooting/unsupported-dsh-release.md)、[根登记表被另一个进程持有](./docs/troubleshooting/registry-owned-by-another-process.md)。 ### Changed - 上游版本差异集中在 `src/compat/` 适配层,一律按**结构探测**(返回值是否 thenable、导出的是哪个名字)判断,不比较版本字符串;业务代码不再出现任何版本判断。 - 两个可选 peer(`@deepseek-ai/dsh-llm`、`@deepseek-ai/dsh-agent-instructions`)改为**按需加载**:barrel 的加载期依赖集合等于必需包集合,一个从不需要构造消息的最小组合不会在加载时失败。 - `pnpm verify:all` 有意**不含** `compat:check`(升级车道要在一个还不在 allowlist 上的候选版本上跑完整矩阵);CI 主车道单独把它排在最前。 - 新增 `./compat` 与 `./instructions` 子路径导出。 - 安装与发版:`prepare` 脚本改为自包含(git 安装由 pnpm 现场构建,用户需先授权 `allowBuilds`);README 补齐 npm / tarball / 本地路径 / GitHub 四种安装来源;npm 发布改用 **trusted publishing(OIDC)**,仓库不再保存任何 npm 凭证。 ### Fixed - **注册表拆除顺序**:原先"先释放内核 lease 再关闭 domain",继任进程可能拿到 lease 后打开一份缺了本进程最后一次写入的快照;现在整个拆除在 store-wide authority 转场队列内按"排空在飞 mutation → 关闭 domain → 释放 lease"执行,并置 `disposed` 拒绝后续 acquisition(`tests/registry-lease.spec.ts`)。 - **指令投递状态按实际产物提交**:renderer 省略或截断文件时不再记录完整 digest;消息构造失败或被取消不再把指令当成已送达;预算耗尽后仍检查撤回,跨根撤回与延迟触碰不再被跳过。 - **附加根中间目录的指令文件**此前永远到不了模型(只考察被触碰文件的父目录),现在其每个祖先目录都会被考察。 - **`DSH_MULTI_ROOT_COMPAT=warn` 收紧**:只放宽 `unsupported`(版本一致、allowlist 未列名——升级车道要探测的正是这一种),`mixed` / `incomplete` 在两种模式下都拒绝。 - **"包不存在"与"已安装但求值失败"分离**:后者不再被当成缺失缓存,进程不会静默停止投递附加根指令。 - **Windows 锁命名按物理路径归一化**:经路径别名(junction / 符号链接)访问同一 store 的两个进程此前会各持一把锁,可同时成为 authority。 - **会话事件配对按会话分隔**:不同会话使用相同 `tool/call` id 时不再互相覆盖、把目录记到另一个会话。 - **升级工作流的 shell 输入处理**:手动版本与候选版本经 step `env` 传值并校验为单行,不再拼进 `run` 源码。 - **本地打包不再夹带历史构建产物**:`lib/` 在 `bundle` 之前先清掉上一轮的 JS 面(tsdown 的共享 chunk 按内容哈希命名,旧名字不会自己消失)。`pnpm pack` 出的 tarball 现在只含一轮构建的制品,不再把历史 chunk 当死代码发出去(`files` 里的 `lib/*.js` 会全部进包)。 ## [0.1.0] - 2026-09-13 首个发布版本:MVP 的三个里程碑(M1–M3)。 ### Added - **插件骨架与组合方式(M1)**:以 bundle patch 替换上游 `fs-sandbox` 与 `sandbox` 两行 provider 并插入本插件的行(`bash-sandbox` 保持上游——bash 与 PTY 的 confinement 全部经 `ctx.sandbox`)。未配置附加根时行为与未装插件逐项一致;组合、disable/insert 时序与 provide 冲突三类结构性风险由差分测试钉住。 - **多根能力(M2)**:`ctx.multiRootScope`(唯一授权源)、`MultiRootFileSystem`(进程内 containment fence,子类自上游 `LocalFileSystem`,`LocalFileSystem` 自身没有 fence)、`MultiRootSandboxProvider`(在 Seatbelt / bwrap / Landlock 三种方言的 profile 上克隆上游 grant 拼法追加附加根);fs 与 bash/PTY 共享同一条 scope,安全不降级。 - **模型可见的拓扑快照**:仅 `workspace-write` + 非空附加根时经 `systemPrompt.context` 输出(同 workspace、cwd 不变);空根与只读模式逐字节不变。 - **根注册表(M3)**:以 canonical 主根为键持久化在 `multi_root_workspace` storage domain,写入与读取都做校验;每条记录带 `recordedPath`,**重新解析路径不等于重新授权**——目录被替换成指向别处的符号链接时该根标为 `redirected` 并暂不授予。 - **`/workspace-folders` 命令**:`list` / `add <路径>`(无参数时打开系统目录选择器)/ `alias` / `remove` / `reveal`,headless 下同样可用。 - **Workspace Folders 浏览器面板**:侧栏底部动作 + 自绘对话框,经插件自己的 Connection RPC 通道与 host 通信;文案中英双语跟随界面语言,配色全部使用 host 的 `var(--dsw-*)` 设计 token。 - **跨仓库旅程 e2e**(`pnpm smoke:journey`):在 `web` 与 `headless` 两种组合下各驱动一轮真实 agent 回合,跨两个 Git 仓库(主根 `repo-a`、附加根 `repo-b`)并断言根外写入被拒。无需模型凭据(脚本化模型端点)。 - **安装形态**:npm 注册表 / tarball / 本地路径 / GitHub;tag 触发的 `release.yml` 完成 verify → npm publish(provenance)→ GitHub Release。 - **平台范围**:macOS(Seatbelt)与 Linux(bwrap / Landlock)的内核级多根全量;Windows 覆盖 `fs` 写路径,受限 bash/PTY 的多根不在本期(非空 scope 时输出一次显式告警)。 ### Fixed - 发布前外部评审提出的 8 项发现(其中 3 项发布阻断)全部修复,每项各带一个回归测试:登记目录被替换为符号链接后授权转移(引入 `recordedPath`,**重新解析路径不等于重新授权**)、并发修改注册表丢写或复活已撤销的授权(每个主根的变更串行)、刷新不重新检查目录、手输路径被目录选择器覆盖、`reveal` 的应答契约与失败码、重复 id 未校验、主根未纳入嵌套校验、CI 先测后构建。 [Unreleased]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.13...HEAD [0.1.13]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.12...v0.1.13 [0.1.12]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.11...v0.1.12 [0.1.11]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.10...v0.1.11 [0.1.10]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.9...v0.1.10 [0.1.9]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.8...v0.1.9 [0.1.8]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.7...v0.1.8 [0.1.7]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.6...v0.1.7 [0.1.6]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.5...v0.1.6 [0.1.5]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.4...v0.1.5 [0.1.4]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.3...v0.1.4 [0.1.3]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.2...v0.1.3 [0.1.2]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.1...v0.1.2 [0.1.1]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/releases/tag/v0.1.0