# 版本记录

> **只记「这一版改了什么、为什么」，不写推演过程**。完整来龙去脉见 git log / [GitHub Releases](https://github.com/bbqisbbq/dsh-tiddlywiki/releases)；当前状态与踩过的坑见 AGENTS.md §2 与 wiki「dsh-tiddlywiki 事实总表」。

> **维护规则**：「最近版本」保持 8 条详细条目，新条目加在最上面；超过 8 条就把最老的一条压成历史表的一行。历史表一行只需说清「改了什么」，别把守门条数、行数对比这些过程数据抄进来。

## 最近版本（详细）

- **v0.34.0**（2026-10-27）：**移除「发布到微信公众号」功能**（作者裁定：没必要）。
- **删了什么**：三条路由 `/wechat/{ready,publish,publish/status}`；配置 `wechat{enabled,command,adapter,token,dsn,endpoint}` 与设置页「可选功能：微信公众号发布」整块（含提示词预览里随开关变化的草稿字段）；注入提示词里的发布前约定（`PUBLISH_RULE`）；三个 gated seed `publish-spec` / `wechat-setup` / `wechat-publish`；`WechatPublishRunner` + 契约层（`wechat-publish.ts` / `wechat-publish-contract.ts`，约 900 行）；TW 工具栏「发布到公众号」按钮 bundle 及其 `build-*` / `gen-*` / 三个 `verify-wechat-*` 守门；`tools/wechat/` 的 opencli adapter 全家（`wechat-html.js` / `weixin-flow.js` / `publish-note*` / 安装与回填脚本）；文档 `docs/wechat-publish-setup.md` 与设计稿。
- **顺手拆掉的机制**：seed 的 `gate` 机制随最后一个使用者一起删除 —— `runAllSeeds` 不再有 gate 分支，`SeedContext.wechat` 也没了；seed 注册表 **13 → 10 项**（核心 3 + 起步 2 + 可选 5）。`admin-secrets` 不再打码 `wechat.token`，`STRING_CONFIG_PATHS` / `BOOLEAN_CONFIG_PATHS` 去掉五条 `wechat.*`。客户端 i18n 475 → 467 键，`index.ts` 公共面 −33 个名字（289 个）。
- **旧 wiki 怎么办**：插件**不会**替你删已写进 wiki 的那几篇内容（`发布元数据规范` / `微信公众号发布指南` / `$:/plugins/dsh/wechat-publish`）——自行在 TW 里删除即可。旧配置 tiddler 里残留的 `wechat` 块按未知键透传保留、不再被读取。
- **为什么一起删而不是留着**：它是本插件里唯一会**按配置去 spawn 外部 CLI** 的能力，牵着一整条 opencli + 浏览器扩展的安装链（插件替你装不了），维护面却是四个守门脚本加两份生成脚本；收益只在「一键存草稿箱」，而发表仍要人手扫码。

- **v0.33.4**（2026-10-26）：**四路只读审计（host / 工具与数据路径 / 客户端 / 死代码）后的修复版**。
- **数据安全**：trashbin 软删除把副本标签整体替换成 `$:/tags/trashbin`，恢复时又从 `fields.tags` 找原文——而 TW 的 `tags` 是已知字段、永远不进 `fields`，于是装了 trashbin 的库删完再恢复**标签全丢**且静默（现在副本写 `[标记, ...原标签]`，恢复只剥标记）；写工具（put / batch_put / delete / rename / append / replace / attach）**没有** `isBlockedProxyTitle()` 守卫，模型可直接改写 `$:/plugins/dsh-tiddlywiki/config`（`wechat.command` 会被 spawn、`git.remote` 下次同步生效）——读侧早就拦了，写侧一直敞着。
- **互斥与假成功**：`MutationLock.end()` 没有所有权校验，而 `/admin/seeds/run` 对**每条**响应都调它（最常见的「重新初始化但什么都没改」压根没 begin）⇒ 会把此刻正持锁的 `/sync` 释放掉，`/admin/restart` 随即拿锁、两条路径同时排干 + 停子进程；现在 `end(label)` 校验持有者。`/admin/info`（改插件/主题/语言也会 drain + 重启）一直没接这把锁；`/restart` 与 `/admin/restart` 在目标库没在跑时回 `{ok:true,drained:true}`（什么都没重启）。
- **多库与会话**：会话汇总的引用正则只认裸 `/tw/#标题`（多库注入的是 `/tw/<id>/#标题` ⇒ 「知识库」Tab 的读取列表系统性为空）、`NOTE_TOOL_NAMES` 漏 `tiddlywiki_replace`、汇总缓存不按库分键（3s 内串库）、工具层 `autoCommit()` 永远 touch 默认库的 committer、设置页跑 seed 丢了 `proxyBase`（多库下「重新初始化」把 `$:/config/tiddlyweb/host` 写回裸路径，那个库的编辑器此后所有 API 打到默认库）、`/admin/prompt` 预览漏掉 wechat 规则与多库链接格式。
- **其他确定缺陷**：`config.load(undefined)` 清缓存却把 `loaded` 留成 true（下一次 `set()` 会把配置抹成只剩本次补丁）、`stop()` 打断 `start()` 后 health 永远停在 `starting`、`/note` 的 `=== true` 把「默认开启」倒过来、剪藏兜底标题的最后一个候选从未校验、剪藏正文上限（20 万字符）大于 body 上限（256KB）、不带 heading 的 append 仍塞 LF 块（CRLF 笔记被写混）、attach 吞 `tags: []`、put 回执的 `字段:` 是「调用方传了什么」、wechat 启动 spawn 抛错仍回 `ok:true`、`/api` 代理不排空 DELETE body。
- **死代码 / 无效逻辑**：`delete` 的 `permanent: true` 逃生通道写在 `canTrash` 之前（文案指的路永远走不通）、trash list 的 `slice(-limit).reverse()` 把「字母序副本 + 时间序索引」混当「最新在前」、`empty` 在从没有索引的库上凭空建索引、`listTrashbin` 单条读取失败会掀掉整张列表、`库目录 === 仓库根` 的库在「diff 未知 ⇒ 保守重启」里被漏掉、`isPlausibleTitle` 放行 `[`、7 处被 `\t` 吃字/粘行的注释；`tiddlywiki_status`（不存在的工具名）又一次出现在错误文案里。
- **文档**：`docs/CHANGELOG.md` 从 292 KB 压到 ~32 KB —— 最近 8 条保持详细，其余 150 条压成一句话表（演进细节交给 git log / GitHub Releases）。

- **v0.33.3**（2026-10-26）：**`.tid` 预览的第一眼改成看内容，而不是看元数据**。
v0.33.2 修好注册之后，预览能出图了，但顶部把**所有**字段原样铺开：`created`/`modified` 是 17 位 UTC 戳（`20260920070533227`），`revision`/`workspace`/`ws/<项目>`/`agent-written` 这类机械字段也一字不落地占版面 —— 打开一个笔记，前两屏全是元数据。
现在新增纯函数 `summarizeTid()`（`src/client/tid-parse.ts`）：单列 `title` / `tags` / 时间，时间戳按 `YYYY-MM-DD HH:mm` 格式化（不是 17 位数字就**原样返回**，不装作看懂了）；`ws/*` 与 `agent-written` 不再占标签位，但会在「另外 N 个字段」那行留一个 `tags(hidden)=…` 的影子 —— **折叠不等于丢弃**。
另把实现名从 `.tid 文件预览` 改成 **「真 TiddlyWiki 渲染」**（en: `Rendered TiddlyWiki`）：宿主在 `candidates.length > 1` 时会画一个实现选择菜单（`rendererId` 按标签页记忆，这是它让"修好了"看起来像"没修好"的原因），名字写清楚用户才能自己切回来。
守门 `verify-tid-preview` 17 条：新增「17 位戳格式化 / 非 17 位原样」「摘要只单列 title·tags·时间且机械字段进 other」「没有 title/时间时不硬造」三条；i18n 475 → 476 键（`frame.tidMoreFields`）。

- **v0.33.2**（2026-10-26）：**`.tid` 预览仍不生效 —— 这次是"服务还没出现就放弃"**。
v0.33.1 修好了 `key` 配对，但用户实测仍是纯文本，且 devtools 里 `[class*="dsh-tw-tid"]` 数量为 0（正文组件压根没渲染）。
根因在插件的**加载顺序**：`documentPreviews` 是另一个插件（宿主的 `dsh-client-ui-sidebar-documentpreview`）用 `ctx.reflect.provide(...)` 提供的，本插件若先加载，`ctx.get(...)` 那一瞬间拿到 `undefined`，v0.32/0.33.0/0.33.1 就**静默 return** 了 —— 界面上看不出差别（宿主用内置纯文本兜底），console 里也一条日志都没有，等于把失败藏起来。
现在改成**短轮询等它出现**（250ms × 40 ≈ 10s），并给每一步补 `[dsh-tiddlywiki]` 前缀的诊断日志：`ctx.get`/`ctx.slots` 是否存在、第几次尝试注册上元数据、正文是否注册进 keyed 子槽、等不到时的 warn。正文外壳加 `data-dsh-tw-tid` 标记，devtools 里一条 `document.querySelectorAll('[data-dsh-tw-tid]').length` 就能判定我们的组件到底有没有渲染。
守门同步改判据：不再钉"查一次就返回"，改钉 `setTimeout(attempt, 250)` 的轮询、`getter('documentPreviews')` 的取值形态、以及"服务始终没出现"那条可诊断 warn —— 静默跳过从这一版起是**被测出来的**行为，不再是遗漏。

- **v0.33.1**（2026-10-26）：**`.tid` 预览改为真正生效**（v0.32.0 那一版静默失效：打开 `.tid` 仍显示纯文本）。
根因是宿主契约里我读错的一处：DSH 的文件预览分「元数据 + keyed 正文」两半，**正文按 `key` 配对** ——
宿主自己写的是 `ctx.slots.register({ name: sidebar.right.tab.document, key: BODY_ID }, Body)`，而 v0.32.0 写成了 `id:`。
**它不报错、不告警**，宿主找不到渲染器就安静地用内置纯文本兜底，于是症状看起来像「功能没做」。
同一轮照抄宿主补齐另外三个形状：`priority` 是**字符串**（宿主只判 `=== builtin ? 0 : 1`，非 builtin 才压得过内置纯文本）、`title` 传**函数**（语言切换可重取）、`wrap: false`（我们产出 HTML 而不是按行折行的纯文本）；
正文取文本也从「只认 `content.text`」改成读 `content.pages`（`loading: text-pages` 时宿主给 `{ kind: text, pages }`，每页 `{ offset, lines, text }`，按 offset 排序拼接）。
守门同步加严（`verify-tid-preview` 12 条）：**正向**钉 `slots.register({ name, key: TID_PREVIEW_ID })`、**反向**钉「不许出现 `slots.register({ … id: TID_PREVIEW_ID })`」、外加 priority/title/wrap/loading 与 pages 读取四条。
另：`i18n` 键数自述 467 → 475 对齐；`profiles/desktop/package-lock.json`（npm 事故遗留、含 `link: true` 软链记账）已删除。

- **v0.33.0**（2026-10-26）：**客户端文案目录接进宿主 locale 服务（⑥b 的落地形态：注册，但不搬）**。原计划把 470+ 条键整体迁进 `ctx.locale.register(ns, {zh,en})`，但官方要求命名空间先并入 `LocaleNamespaceMap` 由**编译器**按类型化键并集校验 —— 本插件客户端是 esbuild 产出的单文件、无 `.d.ts`，参与不了那个类型合并，迁过去等于**放弃 `scripts/verify-client-i18n.mjs` 现有的键名校验**，去换一个「改语言即时生效」。现在两条都不放弃：**目录仍只有一份**（`i18n-catalog.ts` 的 7 个分片，宿主与本地共用同一个对象），启动时注册进宿主 locale 服务，并把宿主的 `bind(ns)` 接到 `t()` 前面 —— **宿主优先、本地表兜底**：服务缺失（老版本 DSH）、`register` 抛错、`bind` 不存在、宿主回空串 / 回键名本身 / 回非字符串，一律退回本地表，所以最差行为等于 v0.32.0。⚠️ 每次注册尝试都会先清掉上一次的绑定：留着旧解析器会让 `t()` 继续问一个已经不存在的命名空间（这一点是写守门时被自己的用例抓出来的）。**守门**：新增 `scripts/verify-locale-host.mjs`（进 `verify:unit`，7 条）—— 命名空间常量、无服务时静默跳过、注册的必须是**同一份** `MESSAGES`（另抄一份会慢慢分叉而界面看着正常）、`register` 的 disposer 必须回收、宿主优先、四类宿主异常必须回落、`t()` 必须委托给 `translate` 且保留本地兜底、接线必须在 `safeMount` 里。

- **v0.32.0**（2026-10-26）：**新增 `.tid` / `.tiddler` 文件的侧栏预览**（⑦ 的第三项）。wiki 文件夹本身就是一堆 `.tid`，而 DSH 的文件预览把未知扩展名当纯文本 —— 打开一个 `.tid` 看到的是 `title: …` 字段行加原始 wikitext，`[[链接]]`/`<<宏>>` 几乎不可读。现在注册一个预览实现：元数据用 `ctx.documentPreviews.register({ id, extensions: ['tid','tiddler'], priority, title, loading: 'text-pages' })`，正文以**同一个 id** 注入 keyed、Session 作用域的 `sidebar.right.tab.document`；正文把 wikitext POST 到本插件自己的 `/dsh-tiddlywiki/render`（铁律 #7 的净化管道）换成真 TW 渲染结果，字段行单独排一行摘要。**绝不白屏**是这个功能的硬约束：拿不到内容 → "等待文件内容…"；只有字段没有正文 → 明确说明；渲染失败 → `<pre>` 原文 + 一句"渲染失败，下面是原文"。宿主没有 `documentPreviews` 服务时**什么都不做**（老版本 DSH 不受影响），且元数据与正文必须**成对**（拿不到 slots 就把已注册的元数据撤回，单边注册会让面板空白）。契约是从宿主 `app.asar` 的 `dsh-client-ui-sidebar-documentpreview/lib/client.js` 逐行核实后写的（含 `TextPreview` 的完整 props 签名与 `content` 三态），全部记在 `docs/development.md`。**守门**：新增 `scripts/verify-tid-preview.mjs`（进 `verify:unit`，10 条）——纯解析用例（字段/CRLF/没有字段必须整份当正文/只有字段/空文本）+ **成对注册**（两处必须用同一个 `TID_PREVIEW_ID` 常量、正文必须先 `slots.inject` 再 `register`）+ **绝不白屏**（`<pre>` 兜底、三种空态各自的 `t()` 文案）+ 渲染必须走 `RENDER_ENDPOINT` 且失败回 `null` 不抛 + 可选依赖的静默跳过与回滚。纯逻辑拆在 `client/tid-parse.ts`（宿主 barrel 也要导它，而宿主包里不能出现 `react`），`client/tid-preview.ts` 只放 UI。客户端 i18n 473 → 477 键。

- **v0.31.1**（2026-10-26）：**新增 `tiddlywiki_export`（笔记落盘，配合 `present` 交付）**。「把这条笔记给我」此前只有两条路：正文贴进回复（长笔记会撞回执预算，`get` 还得分页），或者让人类自己去 TW 里复制；DSH 的 `present` 能交付**文件**，但一直缺「把笔记变成文件」这一步。新工具 `export(title, format?, dir?)`：读一篇笔记 → 按格式落盘 → 回 `{path, bytes, format}`，助手紧接着 `present([{path, description}])` 即可。三种格式：`md`（YAML frontmatter + 正文，默认）、`tid`（TiddlyWiki 原生字段行 + 空行 + 正文）、`json`（完整 tiddler）。三条纪律都不是可选项：① **绝不覆盖同名文件**（导出是旁路产物，静默覆盖等于毁掉上次的交付物）；② **`$:/plugins/dsh-tiddlywiki/` 系统条目拒绝导出**（可能是密钥，走铁律 #6 的共享原语）；③ 读失败 ≠ 不存在（铁律 #3）。自定义字段两处都收（顶层键 + `fields`）—— 只收一处会让「导出丢字段」。守门 `scripts/verify-tools.mjs` 新增一条 7 组断言的 E2E（三格式内容逐项核对、同名拒绝、不存在回 `notFound` 且不写空文件、系统条目拒绝、相对 `dir` 拒绝），并与既有的「真实返回值必须通过 `output.schema`」自动联动。工具数 16 → 17（AGENTS §2、`verify-tool-views` / `verify-prompt` 的计数断言、`TOOL_VIEW_KEYS` + `TOOL_LABELS` + `i18n-card` 的 `card.toolExport` 同步）。


## 历史版本（一句话，151 条，新的在上）

| 版本 | 日期 | 变更 |
|---|---|---|
| v0.31.0 | 2026-10-26 | 对齐 DSH 0.2.1 的改造（选库入口搬到 `conversation.input.left`、`verify-dsh-contract`、`get` 分页、16 个工具补 `output.schema`、skill 走 `ctx.skills.register`、新增 `/note` 命令、提示词加「先查再答」「时效与去重」） |
| v0.30.65 | 2026-10-09 | 新增 tiddlywiki_replace 工具（笔记正文局部替换） |
| v0.30.63 | 2026-10-09 | 默认提示词把「笔记内引用」与「聊天引用」拆成两条链接规则；`config.prompt.override` 设置页说明勘误 |
| v0.30.62 | 2026-10-09 | 第二轮审查三类修复（回收站两种格式合并 / `git_sync`·`git_resolve` 改用会话作用域目录 / 剪藏目标库没在跑改 503 点名）+ 提示词 −14% |
| v0.30.61 | 2026-10-09 | 修 tiddlywiki_trash list 少报一条 —— TW 给块级片段的首元素套 <p> |
| v0.30.60 | 2026-10-09 | 修 v0.30.59 的 tiddlywiki_trash 静默谎报「回收站是空的」 |
| v0.30.59 | 2026-10-09 | 软删除改为「跟着 wiki 已有的回收站机制走」；同时把一条会误导人的注释改成实测事实 |
| v0.30.58 | 2026-10-09 | tiddlywiki_git_sync 不再要求显式配 git.remote —— 配置为空时回落到该库所在仓库自己的 origin |
| v0.30.57 | 2026-09-30 | 给 AGENTS.md 的注入预算装上守门 |
| v0.30.56 | 2026-09-30 | AGENTS.md 的 wiki 指针现在有守门了 |
| v0.30.55 | 2026-09-30 | 把新守门接进 prepublishOnly + 修 verify-all 的收尾 |
| v0.30.54 | 2026-09-30 | 铁律 #12 终于有了执行者 —— 范围本身一致 |
| v0.30.53 | 2026-09-30 | 让「本地全绿 = 可以提交」这条等式真正成立 |
| v0.30.52 | 2026-09-30 | 新增 `verify:sync` —— `lib/` 与 `src/` 的同步此前只有 CI 查（全仓唯一「本地全绿、CI 才红」的类别） |
| v0.30.51 | 2026-09-30 | 把「barrel 公共面」从人肉纪律变成机器棘轮 |
| v0.30.50 | 2026-09-30 | index.ts 724 → 674：拆出自举阶段 `index-startup.ts` |
| v0.30.49 | 2026-09-30 | 修 v0.30.48 引入的真缺陷 + 补「barrel 公共面」守门 |
| v0.30.48 | 2026-09-30 | index.ts 955 → 724：拆出路由 / admin 装配 `index-routes.ts` |
| v0.30.47 | 2026-09-30 | note-widget 588 → 573：拆出底栏 `note-widget-foot.ts` |
| v0.30.46 | 2026-09-30 | note-widget 615 → 588：拆出上传接线 `note-widget-upload-ui.ts` |
| v0.30.45 | 2026-09-29 | note-widget.ts 拆分第四轮 —— 抽出「保存 / 在 TW 中编辑」整组（677 → 615 行），并在同一轮 —— 其余守门一条都不用改 |
| v0.30.44 | 2026-09-29 | note-widget 750 → 677：拆出草稿生命周期整族（两个状态跟着函数走） |
| v0.30.43 | 2026-09-29 | note-widget 817 → 750：拆出卡片定位与拖动 `note-widget-placement.ts`；顺手修 7 处写错版本号的注释 |
| v0.30.42 | 2026-09-29 | index.ts 1036 → 955：拆出纯配置面 `index-config.ts`（先切纯的那半边） |
| v0.30.41 | 2026-09-29 | note-widget.ts 拆分第一轮 —— 抽出两片，993 → 817 行 —— 守门同步三处（都是"钉语义不钉排版"） |
| v0.30.40 | 2026-09-29 | tw-frame.ts 内核抽出 tw-frame-hash.ts —— 关键设计：只读状态用访问器传，不改名；守门同步 |
| v0.30.39 | 2026-09-29 | tw-frame 状态合并第二片：`pendingHash` / `wikiSwitchPending` 进 `surfaceState`（行为零变化） |
| v0.30.38 | 2026-09-29 | tw-frame.ts 内核：第一步「状态合并」起手 —— 为什么不是"直接抽取"；先量爆炸半径再动手 |
| v0.30.37 | 2026-09-29 | 给 v0.30.36 补上缺的那条行为守门 |
| v0.30.36 | 2026-09-29 | 补完 v0.30.35 的另一半：未知变化 ⇒ 保守重启该仓库下的全部库 —— 仍未加行为守门 |
| v0.30.35 | 2026-09-29 | `pull` 的 diff 失败不再被当成「没有变化 ⇒ 不重启任何库」（本版修「不再沉默」那一半） |
| v0.30.34 | 2026-09-29 | 把三个「手动浏览器守门」写进文档 |
| v0.30.33 | 2026-09-29 | ConfigStore 的写路径：核实后决定「不改」，并把理由写具体 |
| v0.30.32 | 2026-09-29 | 给「共享写策略」补上调用点守门 |
| v0.30.31 | 2026-09-29 | 把「共享写策略」的例外清单写进代码与铁律 |
| v0.30.30 | 2026-09-29 | $:/language 的条件写入改走共享写策略 |
| v0.30.29 | 2026-09-29 | wechat-publish.ts 拆出「契约层」 —— 先核实再动手 |
| v0.30.28 | 2026-09-29 | tw-frame.ts 拆出「公共 API 层」 —— 先证明了无环才动手；两处 tabLabel 直接读改成 getTabLabel() |
| v0.30.27 | 2026-09-29 | seeds.ts 拆出「注册表装配层」 —— 分界线是「策略 vs 编排」；依赖方向单向；搬迁手法升级为「编译器驱动」 |
| v0.30.26 | 2026-09-29 | 补上 v0.30.22 漏掉的用户文档 |
| v0.30.25 | 2026-09-29 | admin-routes.ts 拆出最后两条业务路由 —— 依赖面这次是「按代码生成」而不是手抄；两次自我纠错值得记下来 |
| v0.30.24 | 2026-09-29 | admin-routes.ts 再拆出「状态 / 插件·主题·语言」那一组 |
| v0.30.23 | 2026-09-29 | 核实后把一条审计假阳性（两条看似冗余的 id 正则）就地钉死 |
| v0.30.22 | 2026-09-29 | 修 tiddlywiki_attach 把文本文件存成 base64 |
| v0.30.21 | 2026-09-29 | 修掉剪藏桥「同一秒内连剪两次会撞名」 |
| v0.30.20 | 2026-09-29 | admin-routes.ts 再拆出「一次性预置（seed）」那一组 —— 为什么这一组值得单独出去 |
| v0.30.19 | 2026-09-29 | admin-routes.ts（746 行）拆出「知识库列表 / 位置」那一组 —— 「什么都没丢」的证据 |
| v0.30.18 | 2026-09-29 | src/host/session-summary.ts（633 行）拆出扫描层 —— 顺手纠正速查表里的一个错；搬迁纪律；"什么都没丢"的证据 |
| v0.30.17 | 2026-09-29 | 公众号三条路由补上「已登记但没在跑 → 503 点名」+ 铁律「行尾必须 LF」终于有了执行者 —— 过程中揪出一处静默的仓库不一致 |
| v0.30.16 | 2026-09-29 | 数值配置项的「同一组数字」收成一条通用守门 |
| v0.30.15 | 2026-09-29 | 就绪窗口的上下界收成「唯一来源」+ 一条反向验证过的守门 |
| v0.30.14 | 2026-09-29 | 客户端 i18n 全量落地 + `tool-views.ts` 拆成 7 个模块 + 设置页重启后顺手重载面板 |
| v0.30.13 | 2026-09-29 | 客户端 i18n 收尾（第 3 条裁定，283 键 / 20 个文件已转，只剩 3 个） —— 顺手修掉三处语言相关的真缺陷；守门同步 |
| v0.30.12 | 2026-09-29 | 两个真缺陷 + 三条新守门 —— tiddlywiki_append 的 heading 会把 Markdown 图片当成标题；变更锁只覆盖了一半 |
| v0.30.11 | 2026-09-29 | 客户端 i18n 继续推进（283 键 / 20 个文件已转）+ 守门解析器加固 |
| v0.30.10 | 2026-09-29 | routes.ts 拆分第 3 步（笔记组）+ 修掉 /upload 的多库 URL 缺陷 —— 顺手修的真缺陷 |
| v0.30.9 | 2026-09-29 | routes.ts 拆分（第 5 条裁定）—— 两步纯搬迁/工厂抽取，行为零变化 —— 守门铺路的第三处 |
| v0.30.8 | 2026-09-29 | 给 routes.ts 的拆分铺路：两处守门改成按模块族读 |
| v0.30.7 | 2026-09-29 | `tools-notes.ts` 683 → 14 行 barrel：七个工具工厂按职责搬进 `tools-notes-{write,structure,lifecycle}.ts` |
| v0.30.6 | 2026-09-29 | 客户端 i18n 层落地 —— 唯一入口；目录按区域分片；语言来源是同一个 uiLanguage |
| v0.30.5 | 2026-09-29 | `git_sync` 改为同步「所有可同步的库」：按仓库去重、逐仓库独立成败、回执逐仓库标注 |
| v0.30.4 | 2026-09-29 | 剪藏桥「不做认证、对任意页面开放」的姿态落地（只拒 `$:/` 系统命名空间）+ 守门加固 |
| v0.30.3 | 2026-09-29 | `clip-bridge.ts` 574 → 414：payload 层独立成 `clip-bridge-payload.ts` |
| v0.30.2 | 2026-09-29 | `routes-session.ts` 632 → 274：432 行的 `createSessionRoutes()` 按族拆成两条工厂 |
| v0.30.1 | 2026-09-29 | 纯搬迁：`styles.ts` 945 → 47 行（CSS 进 `styles-css.ts`）、剪藏桥出 SSRF 层、seeds 出排干层 |
| v0.30.0 | 2026-09-29 | 第二轮全面审计修复（`get` 漏密钥命名空间守卫 / 剪藏桥可写系统命名空间 / `bridge.wiki` 运行期恒被丢掉 / `git_sync` 排干是空守护） |
| v0.29.0 | 2026-09-29 | 只读审计修复（快速笔记 native 路径不解析目标库 / 已登记未运行的库静默回落默认库 / 两处裸 `server.restart()` / 提示词 −47%） |
| v0.28.14 | 2026-09-29 | 修「点击切换知识库感觉会卡那么一下」 —— 先量再改；两段来源分开处理；侧边栏不再重复打 /status |
| v0.28.13 | 2026-09-29 | 修「左侧多 wiki 入口有时候要点两次才能切到对应的库」 —— 顺带修好一个长期红着没人看的守门 |
| v0.28.12 | 2026-09-29 | 「默认库」不再是一个名字：哪里都直接用被设为默认的那个库的真实显示名 —— 会话选择器；快速笔记「写入」目标；设置页剪藏目标 |
| v0.28.11 | 2026-09-29 | 卡片「在 TW 打开」跳错库 + 新会话出现两个选择器；README 不再放版本记录 |
| v0.28.10 | 2026-09-28 | 修「图标弹层出现在设置弹窗后面、被遮挡」 —— 根因是层级用错了数；顺带补 styles.ts 模板串守门；这条守门的第一版是错的，值得单独记 |
| v0.28.9 | 2026-09-28 | 修「点击图标没有正常弹出」 —— 守门为什么没拦住（本版最重要的部分）；新守门（双向）；新守门当场抓出第二处漏写 |
| v0.28.8 | 2026-09-28 | 多库第五批反馈（12 条一次做完）+ 拆大文件 —— 图标选择器接上 DSH 官方图标系统；修「选了图标立刻变回默认」；多库下设置页按作用域分页 |
| v0.28.7 | 2026-09-28 | 会话知识库选择器改成与「快速笔记」同一行 + 单库专属配置项不再在多库下出现 —— 选择器"没和对话框对齐"；「侧边栏 TW 入口显示名称」在多库下不该出现 |
| v0.28.6 | 2026-09-28 | 修两个多库界面的真机报障 —— 「插件管理 / 主题管理 / 语言包 / 初始化」看起来是混在一起管理的；左侧入口点一个却三个都高亮 |
| v0.28.5 | 2026-09-28 | 修「多库模式下侧边栏多出一个没有库名的 TiddlyWiki 入口」 |
| v0.28.4 | 2026-09-28 | 每库自定义图标 + 修「右键菜单切库后选中项不更新」 —— 右侧「知识库」菜单的选中项停在旧值；每个库的入口图标可自定义 |
| v0.28.3 | 2026-09-28 | 三个真机报障 + 插件说明补「多库 / 升级」两节 |
| v0.28.2 | 2026-09-28 | 设置页去掉重复的「知识库位置」 |
| v0.28.1 | 2026-09-28 | 修「拆库 skill 在 wiki 启动慢 / 起不来时永远装不上」+ 快速笔记的目标库可切换（R7） —— 真实事故；R7 快速笔记目标 |
| v0.28.0 | 2026-09-28 | 多知识库 |
| v0.27.0 | 2026-09-28 | 重新定位：从「AI 记忆工具」改写成「你和 Agent 共用的本地文档中心」——纯元数据 + 文档发布，运行时行为零变化 |
| v0.26.7 | 2026-09-26 | 修「DSH 桌面版里 TW 面板没有『添加条目』按钮」——嵌入式 TW 被渲染在自定义 scheme 上，于是它根本没有同步器 |
| v0.26.6 | 2026-09-26 | 修 tiddlywiki_append 的 heading 在 CRLF 笔记上完全失效、且静默回退到文末 |
| v0.26.5 | 2026-09-23 | 修 P0：fields 参数被按字符拆成几十个垃圾字段 |
| v0.26.4 | 2026-09-23 | 修「发送给 Agent」因配置被浏览器自动填充而 404 + 设置页文本框防自动填充 |
| v0.26.3 | 2026-09-23 | 修正 starter-docs 教程里一处技术性错误说法 |
| v0.26.2 | 2026-09-22 | catalog 标题不再用目录名推导（`codemirror-fullscreen-editing` 的真名不同） |
| v0.26.1 | 2026-09-22 | 修 P0：设置页插件/主题/语言的勾选框全部显示为「未勾选」，且误点「应用」会把启动清单整个清空 |
| v0.26.0 | 2026-09-22 | 修「设置页插件管理与 TW 实际状态对不上」——两套真相源不再互相说谎 |
| v0.25.1 | 2026-09-21 | 修「回复流里的 wiki 链接点了打不开」 |
| v0.25.0 | 2026-09-20 | 第五轮代码审计修复（只留 `/render` title 分支 `{{…}}` 转写一条，判定单机可接受） |
| v0.24.2 | 2026-09-20 | 修「$:/language 每次 dsh web 启动都被无条件重写 → 两台机器每次 pull 都冲突」 |
| v0.24.1 | 2026-09-20 | 修「重启/停止 TW 的四个路径里有三个没排干 syncer 队列」——一类静默丢写入的缺陷 |
| v0.24.0 | 2026-09-20 | 三处「Agent 读写 wiki 的规矩」按用户要求改进 + 一个 lint 误报修复 |
| v0.23.5 | 2026-09-18 | 修 15 处审计缺陷（最重：`delete` 先删条目后读回收站索引 ⇒ 未进索引的永久孤儿） |
| v0.23.4 | 2026-09-18 | 三处硬化，全部来自 v0.23.3 上线当天暴露的真实事故 —— 提交前拦冲突（数据安全）；配置解析失败拒绝写（数据丢失）；adapter 版本校验 |
| v0.23.3 | 2026-09-18 | TW 笔记工具栏新增「发布到公众号」按钮 —— 标题不进 argv；任务化而非同步请求；可选功能默认不打扰 |
| v0.23.2 | 2026-09-17 | 多图发布命令 publish-note-imgs + 发布策略定为「到草稿箱为止」 |
| v0.23.1 | 2026-09-17 | 新增 wechat-setup seed——「微信公众号发布指南」也随插件分发 |
| v0.23.0 | 2026-09-17 | 新增「发布到微信公众号」+ 发布元数据 |
| v0.22.10 | 2026-09-17 | 修「写入丢失 created/modified，新笔记在按修改时间排序的页面上沉到最后一名」 |
| v0.22.9 | 2026-09-16 | 修「TiddlyWiki 编辑者署名被静默清空」 |
| v0.22.8 | 2026-09-15 | 第六轮代码审计修复 —— 数据丢失（P0）；设置页超时（P0）；净化器崩服务 |
| v0.22.7 | 2026-09-14 | 设置页「预览注入文本」改为按表单当前值渲染 |
| v0.22.6 | 2026-09-14 | 修「快速笔记」两处用户实测报障 —— 原生编辑弹窗里删掉笔记后，弹窗变永久白板、再点「快速笔记」也回不来；card 模式底部操作条把按钮文字压成两行 |
| v0.22.5 | 2026-09-14 | 修「大知识库冷启动被误判为启动失败」 |
| v0.22.4 | 2026-09-13 | 重构：把 TW frame 的生命周期收敛成唯一一份实现 |
| v0.22.3 | 2026-09-12 | 客户端审计修复（`iframe` 空 `src` 被当成合法地址使用 / 主题「活动」单选等） |
| v0.22.2 | 2026-09-12 | 修「主题汇总页·模板」seed 内容被渲染成几千遍重复 |
| v0.22.1 | 2026-09-11 | 修首页「快速记笔记」创建出的条目日期时间错误 |
| v0.22.0 | 2026-09-11 | 设置页运行期切换知识库位置 + seed 文档「过期」检测 + 一个隐藏很久的数据丢失竞态 |
| v0.21.0 | 2026-09-11 | 注入提示词改为「默认精简 + 可配置 + 不再过期」 —— 保存后无需重启 dsh web |
| v0.20.1 | 2026-09-11 | 修复「覆盖已有条目时内容类型被静默重置」 |
| v0.20.0 | 2026-09-11 | 第四轮代码审计修复（`/render` 未拦插件命名空间 ⇒ 可读出配置与 token 等） |
| v0.19.5 | 2026-09-11 | 第三轮代码审计修复（`attach` 不读旧条目就 PUT ⇒ 撞名静默覆盖既有笔记 等） |
| v0.19.4 | 2026-09-11 | 标签列表全面「有界」——最后一个没有上限的列表接口 |
| v0.19.3 | 2026-09-11 | 清掉审计剩余中优先级项（`/admin/state` 与 `/admin/config` 回包把 token / PAT 打码 等） |
| v0.19.2 | 2026-09-11 | v0.19.1 的内容 + 让 flush 哨兵真正生效 |
| v0.19.1 | 2026-09-11 | 第二轮代码审计的修复版 + 让 CI 重新变绿 |
| v0.19.0 | 2026-09-11 | 按审计结论全量修复 + 新能力（每个路由校验 HTTP 方法：`GET /sync` 曾能 push 等） |
| v0.18.0 | 2026-09-10 | 全量审计后 40+ 项修复（重头：seed 只在真 404 时才认为条目缺失，瞬时故障曾会覆盖笔记） |
| v0.17.0 | 2026-09-10 | 移除：DSH Better Sidebar（dsh-better-sidebar）Tab 集成 |
| v0.16.28 | 2026-09-10 | 修：拖拽版剪藏书签在知乎等真实页面报 SyntaxError: Unexpected token ';' |
| v0.16.27 | 2026-09-10 | 剪藏书签支持「拖拽安装」 |
| v0.16.26 | 2026-09-10 | 修：剪藏书签在真实页面上崩溃 |
| v0.16.25 | 2026-09-10 | 剪藏桥支持图片剪藏（浮层选图） |
| v0.16.24 | 2026-09-09 | 新：本地剪藏桥 + 书签小工具 |
| v0.16.23 | 2026-09-09 | 新：DSH Better Sidebar（dsh-better-sidebar）集成 |
| v0.16.22 | 2026-09-09 | seed 体系三层化 + 文档中心起步包 |
| v0.16.21 | 2026-09-09 | 新：DSH 右侧边栏（rightbar）集成 |
| v0.16.20 | 2026-09-09 | 修 search / recent 在大 wiki 上超时 |
| v0.16.19 | 2026-09-07 | 修：会话「知识库」Tab 把汇总当源码显示 |
| v0.16.18 | 2026-09-07 | README 全面精简重写；seed 优化——首页 seed 跟随 wiki 现状、修「所有文章」回主页死链、doc-note 文案修正 |
| v0.16.17 | 2026-09-07 | 点击快速笔记可选直达 TW 原生编辑页（ui.quickNoteMode）+ 修「在 TW 中编辑」弹窗 ✕ 关不掉 |
| v0.16.16 | 2026-09-07 | 修会话知识库 Tab 误入编辑草稿显示源码——三层防误编辑（清残留草稿/吞草稿创建/禁 ✏️） |
| v0.16.15 | 2026-09-07 | put/batch_put 未指定类型自动默认 text/markdown；警告 fields.type 是内容类型保留字段 |
| v0.16.14 | 2026-09-07 | 修知识库 Tab「佚失条目」根因——浏览器端 TW 天生排除 $:/temp，改为 iframe 就绪后注入 + 原生 hash 导航 |
| v0.16.11 | 2026-09-06 | 新增会话顶部「知识库」Tab（本会话相关 wiki 汇总，volatile $:/temp） |
| v0.16.0 | 2026-09-05 | 回复流原生 TW 工具卡片 + 可点击 wiki 链接（新增 render-route seed） |
| v0.15.0 | 2026-09-05 | 初始化不强制 + 可反初始化（seed 拆核心/可选两层） |
| v0.14.0 | 2026-09-05 | 「发送给 Agent」按钮独立图标 + 附加说明 + 权限选择 |
| v0.13.0 | 2026-09-04 | menubar 顶栏主题自适应 |
| v0.12.0 | 2026-09-04 | 新默认主页 + 「所有文章」两列分页页 |
| v0.11.0 | 2026-09-04 | 「发送给 Agent」支持选择工作模式（Agent 预设） |
| v0.10.0 | 2026-09-04 | 统一 seed 注册表 + 设置页「初始化」 |
| v0.8.0 | 2026-09-04 | 嵌入式 TW 跟随 DSH 深浅主题 |
| v0.7.0 | 2026-09-03 | TW 一键把当前笔记发送到 dsh 会话 |
| v0.6.0 | 2026-09-03 | 同源代理（远程访问核心） |
| v0.5.0 | 2026-09-03 | Agent 工具扩充 + 快速笔记草稿自动保存 + 统一知识库 FAB |
