# 更新日志 ## Unreleased ## [1.6.5] - 2026-10-14 - CI 移除 Node.js 20,改为 Node.js 22 / 24;同步包的 Node 版本要求和中英文开发说明,与 DSH 官方范围 `^22.19.0 || >=24.0.0` 对齐。 - 修复 Node.js 20 CI 中 React 测试缺少 `navigator` 的环境问题,完整恢复测试前的浏览器全局对象;已通过关闭 Node 原生 navigator 的完整测试验证。 - 修复刚保存首条批注后仍覆盖消息操作栏、滚动才恢复的时序问题:贴底时立即补偿新增高度,下一帧重新定位;保留历史阅读位置,取消后不执行迟到滚动。 - 新增 4 项首次保存/滚动生命周期回归测试;完整测试总数为 115。 - 待发送批注数量入口放在输入区左侧的预留行内,避免覆盖上一条消息的正文/操作栏和输入队列;清空、会话切换、输入区替换及停用时恢复原布局。 - 新增 4 项批注布局/生命周期回归测试,并用 Chrome 检查普通和窄窗口的消息/队列避让。 - 单消息与跨消息统一使用批注 / 引用 / 侧边对话工具条,移除独立引用浮窗及隐藏/延迟降级逻辑。 - 修复范围绕过、重复文字锚点跳转、旧按钮状态、快速重选以及失焦后拖拽残留。 - 主动取消清除选区快照;流式重渲染导致缩短或丢失时保留完整摘录,支持引用、批注和侧边对话恢复。 - 修复跨消息选区经过复制 / 状态按钮时被误拦截:仅限制按钮内的选区端点,消息间按钮不再阻止弹窗;流式恢复使用相同规则。 - 新增 26 项选区回归测试,迁移旧浮窗契约。 - 修复独立引用按钮绕过侧边栏范围限制;选区进入侧边栏时清除旧摘录。 - 侧边对话按创建的线程绑定新 tab,并核对已提交 React 组件中的会话、线程和可见状态,拒绝误写其他草稿。 - 停用、热替换和主会话切换取消异步操作与轮询,迟到响应不再改变界面或存储。 - 新增 12 项回归测试(含真实 React 18 受控输入框);补强原有侧边栏测试。 - 固定 LF 行尾,保证 Windows checkout 的 vendor 原字节哈希与构建一致。 本项目的所有重要变更都记在这里。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/), 版本号遵循[语义化版本](https://semver.org/lang/zh-CN/)。 > 项目名 `dsh-selection-group`(包名 / 插件 id / 仓库名),插件面板显示为 **Selection Toolbar**。 > 仓库的 git 历史从 **1.3.3**(首次公开发布)开始;更早的条目按开发记录重建,按版本倒序排列。 ## [1.6.4] ### 修复(发布包) - **npm 发布包缺构建输入,装下去无法自测**:`files` 白名单里没有 `vendor/`、`patches/`、`scripts/`、`src/`, 而 `scripts/build.mjs` 第一步就要读它们。实测在解包目录里跑 `npm test`: `Error: ENOENT .../src/toolbar.js`(补 `src/` 之前)与 `vendor/manifest.json`(补之前)。 现在四者都在 `files` 里,发布包大小 103 KB → **204 KB**(26 个文件), 并在**解包出来的干净目录**里验证过:`npm test` → **69/69 通过**,其中包含 vendor sha256 校验与补丁落盘断言。 - **`build.mjs` 新增 `--check` 模式**:只校验 `client.js` 是否与 `vendor/ + src/` 一致,**不重写文件**。 `npm test` / `npm run verify` 与 CI 都改用它——否则测试流程可能先把产物"修好"再去断言它,漂移就被洗掉了。 已实测:无漂移时退出 0 并打印版本号与行数/字节数;人为改动后退出 1 并打印两边尺寸**以及第一处差异** (行号、字符偏移、两侧各 24 个字符的上下文)——只报尺寸是不够的:版本号从 1.6.3 换成 1.6.4 时 两个尺寸完全相同,报告会变成"漂移了但看起来一模一样"。 - `build.mjs` 读取构建输入失败时,现在抛出**指名的诊断**(哪个文件、哪个目录该带上),而不是深层 ENOENT。 - `.gitignore` 忽略 `*.tgz`(本地打包验证用,不提交)。 - **分发方式定为 GitHub**:README 的安装节改成三种来源——`github:` 仓库 URL(推荐)、 GitHub Release 的 tarball 直链(钉版本)、clone + `link:`(开发),并写明**本项目不通过 npm registry 分发**。三者在 pnpm 11.7.0 下均已实测:`github:` 装出的 `client.js` 与仓库里的 sha256 完全一致,且在该包内 `node scripts/build.mjs --check` 与 69 项测试全部通过。 ## [1.6.3] ### 修复(**范围收紧**:只在聊天里生效) - **在侧边栏打开的文件里选文字,也会弹出这个框。** 现在整个插件**只在对话内容里生效**;右侧栏 (文件树 / 文件查看器 / 侧边对话 / 终端 / 任务)与**任何文件内容**——不管在右侧栏还是中间主区打开 ——都**不再出现**这个框。 - **根因是我自己的补丁,不是上游**:上游 annotation 的 settle 里有 `if (rootEl === null) return` 这道 "这算不算可批注的根"的门;我为了"选中当回合立即出框"(`immediate-toolbar`)重写了那段,**把这道门漏掉了**。 而这个工具条只在**点击动作时**才用到 `ui.selectionRoot`,画框从不检查它——所以任何选区都会被画上框。 现在把 `rootEl === null` 的判断**原样保留**在立即绘制之前。 - 同时按要求把**文件正文路径也关掉**:上游 annotation 本来主动支持宿主文本预览(`DOCUMENT_TEXT` + `[data-textpreview-url]`),而 `dsh-better-sidebar` 自己已经在文件查看器上提供「添加到对话」—— 两套叠在一起既有噪音、动作又是错语境的,所以合并包彻底不做文件选区。 - **右侧栏整体拒绝**:注解包里任何落在 `[data-slot="sidebar"]` / `sidebar.*` 子树内的选区都返回"没有根", 这样即使是一个聊天行被渲染在右侧栏(例如侧边对话视图),也不会弹框。 ### 测试 69 项(原 66 项)。新增三条:**文件预览里选文字 → 完全没有框**(且独立「引用」按钮保持隐藏); **先选文件再选对话 → 对话照常出框**(确认不是一刀切关掉);**右侧栏里的聊天行也不出框** (按列拒绝,而不是只按行类型判断)。 ## [1.6.2] ### 变更 - 按钮文案从「◧ 放进侧边对话」改回 **「◧ 侧边对话」**(英文 `◧ Side chat`)——功能不变, 只是名字更短。悬浮提示仍写明"不自动发出、发送与否由你决定"。 ## [1.6.1] ### 修复(实测两次踩空:输入框定位) - **「放进侧边对话」在真机上完全没生效**:提示"输入框 4 秒内没有出现"。我按结构定位那个输入框的**四条规则全错**, 而且每一条都被我自己写的**过浅测试桩**放过了: | 我写的规则 | 真实情况 | |---|---| | 卡片的**第一个子元素是按钮** | 第一个子元素是 `