# Changelog

本文件记录本插件的所有重要变更，格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)，
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。

## [0.2.0] - 2026-09-11

面向 dsh `0.1.5-rc.1` 的兼容性修复 + 可维护性改造。四个 bug 都会让功能**静默失效**（不报错、只是不工作），
因此建议 0.1.x 用户升级。

### 修复

- **「已归档的聊天」空列表**：`sessionPersistence.list()` 已从 `SessionHeader[]` 变为
  `{ header, revision, sizeBytes }[]` 快照，旧代码按 `header.id` 取值得到 `undefined`，
  于是每个归档项都被当成「已删除」跳过。新增 `headerOfEntry()` 同时接受两种形状。
- **永久删除不删磁盘文件**：同一处形状不匹配使 `deleteArchived()` 里的 `locate()` 分支被整段跳过，
  但归档集合照常改写 —— UI 报成功、日志文件留在 `$DSH_HOME/sessions/` 下，
  任何直接读持久化的列表路径都可能重新发现它。现在按适配后的 header 解析路径并真实删除（有单测覆盖）。
- **运行中会话可被删除 / 「运行中」标记从不出现**：活跃 `Session` 没有 `events` 成员，
  `sessionHasOpenTurn()` 恒为 `false`。现在优先读 `turnBoundary` 投影（harness 自身的权威判断），
  回退到公开的 `snapshotEvents()`。
- **永久删除必报 `unsafe-path`**：安全校验按 `session.jsonl` + `session-<id>` 目录判断，
  而真实工件是 `<root>/<project>/<encoded-id>/session.v3.jsonl.zstd`。
  `assertSafeSessionArtifact()` 现在按当前命名规则（各代次 + 压缩后缀 + 编码 id）校验，
  仍拒绝非会话文件与不属于该会话的目录。

### 变更

- 归档列表标题改用批量 `readTitleSnapshots()`（一次观测取全部标题），缺失时回退逐条读取。
- 语言文案统一走 DSH 语言服务：角色名、条目计数、导出抬头不再读 `navigator.language`，
  同一界面不会中英混排；导出接口接受客户端上报的 `locale`。
- 提示条（toast）队列注册进 `shell.overlay`，由 slot 生命周期管理，不再为每条提示创建游离的 body root
  （无该 slot 的组合保留退化的逐条 root 方案）。
- 传输层：超大请求体返回 **413**（此前静默读成空对象）、未知方法返回 **404**、错误码映射到
  403/404/409/501，响应统一加 `cache-control: no-store` 与 `x-content-type-options: nosniff`。
- 归档集合的读-改-写自带串行化与提交后校验重试（缓解与官方 `archiveSession` 的丢失更新），
  持续冲突时返回 `conflict` 而非静默吞掉。
- 退役空闲活跃会话优先调用 entry 的公开 `detach()`，私有方法仅作回退并记警告。
- 构建脚本的 externals 对齐平台单一真源 `PLATFORM_MODULES`，避免将来把种子模块打成私有副本。
- peer 范围改为 `^0.1.0-rc.6 || >=0.1.5-rc.1 <0.2.0`：semver 要求显式列出后续 prerelease，
  否则 pnpm 永远报 peer 警告。

### 新增

- **57 条 vitest 用例**（`npm test`）：兼容性形状适配、永久删除真实删盘、运行中拒绝、
  路径安全校验、归档集合重试、防火墙判定、路由层（403/405/404/413/400）、转写映射。
- `npm run typecheck`（host 半 + 测试）。
- 本 CHANGELOG。

## [0.1.3]

- 仓库更名为 `dsh-session-admin`。

## [0.1.2] 及更早

- 会话删除入口、已归档聊天管理（查看 / 恢复 / 导出 Markdown 与 JSONL / 永久删除）。
