# Changelog

## 0.7.7 (2026-10-27)

两条外部 issue（feidky）的修复；无宿主兼容面变更，`engines.dsh` 枚举与 peers 保持 0.7.6。

### 修复：多条排队时自动折叠，与用户抢开关（issue #4）

- 多条排队**默认展开**（`listVisible` 仍保留单条直显）：排队信息的价值就是看得见。
- 删除「队列清空 → `setCollapsed(true)`」的自动收回 effect；折叠态只由用户手动决定。
- 持久化键升 v2（`dsh-input-traffic:collapsed:v2`）：v1 的值含自动折叠写入的结果，
  不是用户选择，不能压过新默认值。
- `collapseTouched` latch：未手动点过表头前**不写存储**，避免首帧把默认值物化成决定。

### 修复：红档「打断并输入」在多条排队时投了队首行（issue #3）

- 根因（确定性，非竞态）：宿主唤醒只经 `followup`，而 `followup` 永远追加到 `next-turn`
  尾部（`agent.ts` `inbox.splice(…, Infinity, …)`），唤醒后 driver 按 FIFO 取**队首**。
  旧实现 `cancel → remove(目标) → send(目标)` 让目标落在队尾，被消费的是队首。
  另：`conversation.send()` 的 mode 硬编码为 `queue`，与 `busyEnter` 设置无关。
- 新流程：`cancel`（宿主 park 队列，收敛期不 claim）→ 摘出全部其它行 →
  `send(目标)`（此时唯一，即队首）→ 其余行按原序重投。
- 语义：红档只投入当条；其余行（含黄档插入行）统一降级回绿色等待档——
  被打断的回合不存在「下一个 step」可插入。
- 顺序：`cancel` 提到最前，所有摘取都发生在 park 之后，去掉「摘到一半被消费」的窗口。
- `send(目标)` 失败时仍恢复其余排队行（try/finally），不吞队列；
  `queue-item-not-found` 视为已被宿主取走，该行不重投（避免重复投递）。

### 限制：附件行仍锁红档

- 重投只有 `send(text)` 一条通道：`file` 块的 `receiptId` 一次性、无反向解析；
  图片需 `readAttachment` 回读字节（未实现）。
- 因此待处理行含非文本内容时**整队**红档禁用（不只那一条），文案改为队列口径（9 语）。
- 根治需宿主提供队列位置操作（`move` / `prepend`），届时红档与重排的附件锁可一并解除。

0.7.6: host enumeration addendum for DSH 0.2.1-rc.3 (declaration-only bump; contract plane zero diff).

## 0.7.5 (2026-10-18)

- hosts: 追加 0.2.1-rc.2 声明面枚举（34/34 @deepseek-ai/* 宿主 peer 逐包 npm 实测 rc.2 在版；本插件不触 ctx.web provider 与 conversation.input.model.label 槽，代码零改动，纯元数据发版；农场 rc.2 格挂账待命）

所有重要变更与 bug 修复记录于此。版本遵循语义化版本（`dsh plugin --profile web add dsh-input-traffic` 安装）。

## 0.7.3 — 2026-10-08

### 新增：settings 数据桥（T20-b，perm-gate 5260fe6 泛化形移植）

- 老线（≤0.1.5）上 client settings 句柄永不 resolve（settingsScope 死路），家族卡
  降级「设置服务不可用」、busyEnter 钉值静默失效。node 半区从 no-op 转正：loader
  `inject=['webServer']` + `settings` 子注入挂活引用，暴露
  `/api/ui-conversation/settings/{describe,mutate}`；client 半区 BridgeDocHandle
  双轨（原生句柄优先、桥兜底），钉值在原生缺席时由桥首拉 ready 后补发一次。
  前提实证：0.1.0 宿主 settings 服务全款具备 describe/mutate/redactSecrets 面，
  最老线无需兜底。五格验收：四条桥线卡片真数据、0.1.7 原生无回归、桥写回落盘。
- 顺修 family-card 条件 hook（useSyncExternalStore 无条件调用；降级快照走模块级
  常量）。

### 0.7.1 / 0.7.2 未单独发版（tgz 直铺五格），随本版一并进 npm

- 0.7.0：15rc 枚举单版本线（六 peer × 15 rc 全存在），latest + 四线 tag 收敛（已发）。
- 0.7.1：`dsh-family.tab` 注册提顶层 + scopeRef 活引用（≤0.1.5 家族节贡献卡缺席修复）。
- 0.7.2：settings waist 回调按 cordis 契约从 scope 对象按名读服务（裸服务调用 =
  每代 TypeError、纤维暗死，busyEnter 钉值因此从未生效）。

## 0.5.5 — 2026-09-30

### 修复：队列行改读 inbox 投影（真实宿主渲染修复，实测 0.1.7-rc.2）

- 真实宿主的排队行不在会话快照上：组件改从 useProjection('inbox') 读取（next-turn=排队/绿档，next-step=插话/黄档），与官方 QueueDock 同源。此前读取的 s.queue 为类型镜像自造字段，行渲染必崩并回退官方队列。
- queueMutable 与官方判定对齐：continuable 子代理上下文同样可操作（此前整块操作按钮会在子代理会话中消失）。
- 移除真机上失效的「打回输入框」按钮（setDraft 为未文档化面）；黄色档位是唯一插话入口。
- 行文本改由 content 块派生（textOf，对齐官方 textOf/previewOf），修复行预览空白。
- 三色档位圆点固定字面量配色：自定义皮肤（如 ui-skin-maid-atelier）重定义 warn 别名 token 会把黄点洗成不可见。
- CSS 压制官方 QueueDock 容器（仅崩溃回退态的可见性兜底）；修复 verify-assembly 陈旧断言（settingsScope → configForms）。
## 0.5.4 — 2026-09-29

### 修复：0.1.7 线 devDeps 基线对齐 + dock 图标渲染崩溃

- devDeps 三处陈旧钉版拉平到 0.1.7 线：`client-ui-primitives ^0.0.1-rc.1`（`^0.0.x` 永远装不到 0.1.x）、`client-store` / `util-workspace-path ^0.1.2-alpha.2`（预发布解析规则卡死）→ 全部 `^0.1.7-rc.1`（实装 rc.2）。
- 源码跟进 primitives `*16`/`*14` 图标导出改名（0.1.7-rc.1 起只剩 `*Medium`/`*Regular` 族）：8 处改用 `*Medium`。
- **此版本替换已发布 0.5.3 的坏 tarball**：0.5.3 的 bundle 外部引用了 primitives 0.1.7 中不存在的图标导出名，在真实 0.1.7 宿主上 dock 渲染即崩——陈旧 devDeps 钉版把它掩盖成构建期假绿。
- 测试环境加固：宿主专属路径桩化 + micromark/mdast 栈显式 devDep + `react-dom` 钉 18（5 套件 59 用例全部真实执行）。

## 0.4.1 — 2026-09-20

### 修复：等待队列尾部按钮被「调整对话宽度」把手抢走点击

- **现象**：队列卡片「取消并清空」与三档规划按钮（绿/黄/红）落在对话栏右侧的全高宽度把手（`div.wSkVaW_widthHandle[data-side="right"]`）覆盖范围内，点击被把手解释为拖拽，按钮无法操作。
- **根因**：把手位于 `.body`（`position: absolute`、`z-index: 8`），而 composer 座位 `.composerSeat` 是 `z-index: 7` 的层叠上下文；本插件的 `.dock` 原为 `width: 100%`（铺满 composer 栈），比输入卡片宽约 32px，尾部控件因此伸进把手的命中带。作为层叠上下文内的后代，dock 无法用 `z-index` 越出撤销层级，只能从几何上让位。
- **修复**：`.dock` 收敛到官方 `QueueDock` 同款卡片列——按「两侧 clearance + 两侧 dock inset」从栈宽扣除、上限为 composer 卡片宽减去 dock inners、`margin: 0 auto` 居中、inset 以 `padding` 返还，使面板仍与输入卡片对齐；并额外用 `min()` 叠加顶层 `--dsh-chat-content-width` 上限，让面板右缘距把手内缘稳定留出 24px 安全带（窄栏下该把手宽度为 0，`min()` 自动回落为卡片列宽）。离线 Chrome 几何探针：对齐场景把手到面板间距 24.5px → 48.5px，位移 16px 的错位场景 8.5px → 32.5px，四个按钮 `elementFromPoint` 命中自身。

## Unreleased

### 变更：仅支持 DSH 0.1.5+，compat/0.1.5 线（0.2.12-beta.1）

- **`engines.dsh` 收窄为 `>=0.1.5-alpha.1 <0.2.0-0`**：0.1.5 引入 Session V3（surface node）、dockkit Sidebar 重写与 Lexical composer。核查确认本插件依赖的三个 slot 锚点（`conversation.input.dock` / `conversation.input.right` / `settings.general.item`）在 0.1.5 全部保留，`session.updateQueue` / `prompt` / `cancel` remote 无破坏记录，因此**代码零结构改动**，仅收窄支持分段。DSH 0.1.2/0.1.3 用户请留在 main 线（0.2.11-beta.1）。
- **全部 `@deepseek-ai/*` peer 区间同步收窄**到 `>=0.1.5-alpha.1 <0.2.0-0`（`@deepseek-ai/cordis` 保持 `^4.0.1`）。
- **类型契约锚点**：`src/types/contracts.d.ts` 的镜像锚点已于 2026-09-11 对照 `dsh-v0.1.5-rc.2` 验证，本版仅把头部 supported segment 更新为 0.1.5 分段。
- **注释现代化**：`src/client/index.ts` 与 `freeze-button.tsx` 中 0.1.1/0.1.2 双版本历史注释改写为 0.1.5 现状（含 0.1.5 新增相邻 slot `conversation.composer.dock` / `conversation.input.left` 说明）。无行为变更。
- **README 新增「0.1.5 已知回归」节**（宿主侧，非插件 bug）：fork 继承排队 prompt（#6314/#6197）、Lexical composer IME（#6231/#6052）、阻塞等待期间 steer 无法抢占（#6030）、升级后 client combo 缓存陈旧需强制刷新（#5999/#6374）。
- ⚠️ **无实机验证声明**：本版在无 DSH 0.1.5 实机环境下发布（lint/test/build/assembly 通过 + 文档契约静态核对），`input.for(actx)` / `blocks.set` / dock 注入 props 三个未文档化面待实机回归（清单见仓库 checklist.md）。

### 破坏性：仅支持 DSH 0.1.2+，完成 `dsh-client-runtime` 移除替换（0.2.11-beta.1）

- **`engines.dsh` 收窄为 `>=0.1.2-alpha.1 <0.2.0-0`**：`@deepseek-ai/dsh-client-runtime` 在 0.1.2-alpha.1 被整体删除（commit `be531688f3`），该版本即为本插件的硬分段点。旧版线（≤0.2.10-beta.2）继续服务 DSH 0.1.0/0.1.1。
- **`ClientContext` / `SessionId` 改由真实归属包提供**：`src/client/index.ts` 改为 `import type { Context as ClientContext } from '@deepseek-ai/cordis'` 与 `import type { SessionId } from '@deepseek-ai/dsh-session/types'`，与官方客户端插件一致。
- **契约拆除 `dsh-client-runtime` 镜像**：`src/types/contracts.d.ts` 删除 `declare module '@deepseek-ai/dsh-client-runtime/client'`；`QueuedMessage` / `SessionSnapshot` / `ISessions` 迁回 `@deepseek-ai/dsh-api-session-controller/client`，`SnapshotSelectorHook` 迁回 `@deepseek-ai/dsh-client-store`。
- **新增 `src/types/cordis-augment.d.ts`**：把 `slots` / `sessions` / `locale` / `settingsScope` / `conversation` 声明到 cordis `Context`（官方客户端插件的做法），替代已删除的 `ClientContext`；`ctx.get<IConversation>('conversation')` 相应改为 `ctx.get('conversation')`，因为真实 cordis `get` 由 `Context[K]` 决定返回类型。
- **`SettingsScopeSnapshot` 补齐 `base` / `user` / `revision`**，`SettingsScopeFace.bind` 增加可选 `decode`。
- **新增 `@deepseek-ai/dsh-session` peerDependency**；其余 `@deepseek-ai/dsh-client-*` peer 区间同步收窄到 `>=0.1.2-alpha.1 <0.2.0-0`。

### 变更：冻结按钮文案与 session-guard 的分工说明

- **按钮文案**：`steer.freeze` →「冻结追加」（Freeze & append / 凍結して追加 / 동결 후 추가），
  `steer.resume` →「恢复追加」（Resume & append / 再開して追加 / 재개 후 추가）——与 session-guard 新增的
  「暂停会话 / 继续会话」按钮并列，避免两个「恢复」混淆。只改文案，行为不变。
- **职责边界**（README 新增小节）：本插件只负责「排」——决定用户输入进 `next-step` 还是 `next-turn`、
  什么档位、何时被消费（`updateQueue(steer|remove|edit)` / `send` / `cancel`）；session-guard 只负责「停」——
  `agent/pre-step` step 门、回合级暂停、请求级 hold。`next-step` 的物理含义是「与工具返回同级的下一步
  （同一 turn 内）」，`next-turn` 才是新回合。

### 新增：DSH 双版本兼容（0.1.1-rc.2 / 0.1.2-rc.1）

- **单一产物，运行时自适应**：同一份 `lib/client.js` 在两个版本都能加载，无版本号字符串分支。
- **冻结按钮改读会话标准件**：`conversation.input.right` 在 0.1.2 起不再传 `InputZone` owner（`InputBar.tsx:466` 传 `{}`），原先读 `session.queue` 会在该版本直接抛错。现改为 `useSession(s => s.queue)`——`useSession` / `sessionId` 在两版 `SessionStandardProps` 中均存在。
- **本地契约收紧到两版交集**：`src/types/contracts.d.ts` 的 `conversation.input.right` 去掉 `owner`，`InputZone` 只声明被消费的 `input.draft`；再引入版本专属 owner 会直接 `tsc` 报错。
- **元数据**：`engines.dsh` 收窄为 `>=0.1.0-rc.7 <0.2.0-0`；`peerDependencies` 移除 `@deepseek-ai/dsh-client-runtime`（0.1.2 已改名 `dsh-client-store`，本插件运行时不依赖它）。

### 修复：等待队列被其他条目插到输入卡片之间

- **现象**：`dsh-perm-gate` 的审批提示条出现在等待队列与输入卡片之间。
- **根因**：list 型 slot 的显示位置只由 `order` 决定（`scoped-slots.tsx` 把 shadowing 胜者按 `order` 排序），`priority` 只决定同 `id` 单元格的胜者。队列条沿用官方 `order: 20`，因此排在提示条的 `30` 之前。
- **修复**：保持 `priority: -1`（赢得官方 `queue` 单元格），`order` 提到 `QUEUE_DOCK_ORDER = 1000`，排在 `conversation.input.dock` 带内所有已知条目之后，紧贴输入卡片。DSH 无 "last" 语义，第三方注册更大 `order` 仍可能插入（README 已注明该前提）。

## 0.2.8 — 2026-08-24

### 新增：日夜模式自动适配

- 队列框（等待区 dock）与冻结按钮的配色从自绘 `--ds-color-*`（dsh 中不存在该 token）改为引用 dsh 官方语义 token（`--dsw-alias-*`：bg-layer / border-l / label / interactive-bg-hover / state-success|warn|error-primary）。
- 效果：系统深色模式或 dsh 暗色主题（`body[data-ds-dark-theme]`）下自动切换为**深灰底 + 白色反色字**，三档色使用官方暗色适配值（对比度由 dsh 保证）；白天外观保持不变。
- 纯 CSS token 映射，零 JS 改动、无新增设置项。

## 0.2.6 — 2026-08-19

### Bug 修复：拖拽启动兼容（部分浏览器无法拖动）

- **现象**：部分浏览器（引擎要求 `setData` 才启动 HTML5 拖拽）中，队列行无法拖动排序。
- **根因**：`dragStart` 只设置了 `effectAllowed='move'`，未调用 `dataTransfer.setData()`。
- **修复**：正常队列行与冻结队列行的 `dragStart` 均补齐 `setData('text/plain', index)`。

## 0.2.5 — 2026-08-19

### Bug 修复：冻结队列无法拖动排序

- **现象**：冻结时队列行只能靠上移/下移按钮排序，拖拽无效。
- **根因**：冻结列表 `li` 未挂 `draggable` 与 drag 事件（拖拽只实现了正常队列行，冻结行遗漏）。
- **修复**：冻结行补齐 `draggable` + `dragStart/dragOver/drop/dragEnd`，drop 调用 `movePending(from, to)`，并加拖拽虚位提示。

## 0.2.4 — 2026-08-19

### Bug 修复：冻结时队列被锁定（顺序/内容/插入模式全不可改）

- **现象**：冻结状态下队列"不让改"——上移/下移、编辑、删除、红/黄/绿插入档位全部失效。
- **根因**：冻结列表只读渲染（无操作按钮）；残留的正常队列行按钮带 `disabled={frozen}`。
- **修复**（冻结与队列完全解耦）：
  - 冻结队列每行提供与未冻结一致的编辑（行内 textarea）/ 删除 / 上移 / 下移；
  - 冻结队列每行提供**红/黄/绿插入档位**按钮（设定恢复时的预定档位，`setTierAt`）；
  - 冻结行编辑用 `frozen:${i}` id，避开正常队列的 stale 清理；
  - 恢复（resume）按每条预定档位执行：红色档位先 `cancel()` 再发送（打断），黄/绿按序唤醒。

## 0.2.3 — 2026-08-19

### Bug 修复：冻结时等待队列被隐藏

- **现象**：冻结后等待队列消失，用户无法查看/修改已冻结的消息。
- **根因**：冻结实现把队列消息逐条 `remove` 到插件 store（driver 无 pending 自然停止），dock 渲染条件 `queue.length === 0 && !running` 触发 `return null`。
- **修复**：
  - 渲染条件增加 `!frozen`（冻结时 dock 保持挂载）；
  - 冻结列表从 freeze-store 的 `pending` 渲染（横幅 + 每行「已冻结」标记）；
  - freeze-store 增加可变操作：`pushPending` / `updatePendingAt` / `removePendingAt` / `movePending`。

## 0.2.2 — 2026-08-19

### 新增：清空确认的显式取消按钮

- 冻结队列保持可见（横幅），清空两步确认增加「取消清空」按钮（点击还原，另 3 秒超时自动还原）。

## 0.2.1 — 2026-08-18

### 新增：清空两步确认

- 首次点击「取消并清空」出现红色「确认清空？」，再点执行；避免误触清空整个等待区。

## 0.2.0 — 2026-08-18

### 新增（借鉴 dsh-queue-plus）

- **拖拽排序**：队列行直接拖动调整顺序（原生 HTML5 DnD，零运行时依赖）；箭头按钮键盘兜底保留。
- **排序并发保护**：重建期间某条消息已被 agent 认领（`queue-item-not-found`）→ 立即中止且不重发，提示「队列已变化，本次排序已取消」，绝不排乱变化中的队列。
- **折叠状态记忆**：等待区收起/展开状态持久化到 localStorage，跨会话保持。
- **清空两步确认**（见 0.2.1）。

### 工程化

- **描述更新**：package.json / GitHub repo / npm 描述加入 queue / drag-to-reorder / interject / batch clear。
- **TDD + Lint**：ESLint flat config（`eslint.config.mjs`，typescript-eslint + react-hooks）；`npm run tdd`（vitest watch）；`npm run verify` 一体化门禁（lint + test + build + 12 项装配断言）；README 双语「开发（TDD + Lint）」章节。
- 测试 32 → 43 项。
