# Changelog

## 0.20.1 — 2026-10-14

- 修复：同一台机器上另一个 DSH home（例如临时验证用的 profile）装了本插件后，会把 `~/.agents/skills/landfill-project/SKILL.md` 链接抢过去指向自己，那个 home 删掉后链接就断了。现在指向本插件另一份安装、且版本不比自己旧时保持不动，只有旧版或断链才重建。

## 0.20.0 — 2026-10-14

**卡片组统计 + 新建会话体验 + 同名检测 + 落盘中断 + 落盘项目按卡片组归档与按规范迁移**

- 卡片组标题旁：卡片数改成蓝底胶囊（0 张变灰）；新增「活跃会话」胶囊 = 本组卡片关联、没归档的会话数，会话开 / 归档 / 恢复实时更新（变化时轻跳一下）；仓库 / 阶段降为灰色小字。
- 「以此卡片新建会话」：点了立刻进入「正在新建会话…」并锁住（再点不会叠请求）；侧栏同时出现占位行；建好后侧栏这一行第一次出现就是「卡片标题 · 未开始 · 删除」（当前打开的空会话也由插件画，宿主那行只写「新会话」的被藏起）。
- 卡片详情「相关链接」：编辑 / 删除按钮常驻显示（拖动把手仍是悬停出现）。
- 会话信息卡：收起时箭头朝上、展开时朝下。
- 未关联落盘项目时的「新建落盘项目」：边输入边做同名检测——还没输入时按卡片名提示「可能就是这个」；文件名或别名完全相同时主按钮换成「关联并落盘」（同名不能再新建）并给改名建议；名字相近时只提示。每个候选显示字数、更新时间、已关联哪些卡片、落盘时会不会迁移，可「只关联」或「关联并落盘」。
- 信息卡发起的落盘按这一轮的真实结局更新：被停止 →「已停止，没写入」+ 重新落盘 / 忽略；出错 → 写出原因；AI 在问你 →「等你回复」；写好了 →「落盘完成」。不再一直转圈。
- 落盘项目按卡片组归档：卡片组有自己的落盘文件夹 `~/.ai/projects/<文件夹>/`（卡片组设置里可改；第一次在这个组落盘时信息卡请你确认一次，按组名给建议；第一次用到时登记到 ~/.ai，别名带组名）。新建、合并的落盘项目都放进这里。
- 修复 DSH Desktop 下所有写操作返回 403 CROSS_ORIGIN（#2）：桌面壳转发请求时会去掉 Origin，写操作守卫改为「带 Origin 时必须与 Host 同源，没有 Origin 放行」（仍只接受本机回环 + Host 为 127.0.0.1 / localhost），与 dsh-manage-sessions 同一口径。
- 修复 Windows 下挂载本地文件夹失败（#1）：仓库路径、相关文件、粘贴路径都认 Windows 绝对路径（`C:\…`、`C:/…`、`\\server\share\…`）；Windows 上仓库挂载用 junction（不需要管理员权限）。
- 按规范迁移：落盘项目规范是一张带版本号的检查清单（v2：位置、标题行、文件索引、别名行含卡片名），每次落盘都把整张清单跑一遍，所以任何旧版本的 STATE 下次落盘都会被拉到最新规范。位置不对 → 插件在写入前把整个文件夹迁到卡片组的落盘文件夹（子文档一起搬、里面的旧路径改指新位置、~/.ai 里的外部引用改指向、卡片关联换成新 key、旧文件夹进原项目 `inbox/retired/`）；其余项交给落盘的 AI 改，没改好 persist 拒绝（`SPEC_ISSUES`）。信息卡提前标出「落盘时迁到 xxx」，迁移后显示「已按规范迁移」卡片，可撤销（搬回原处，之后不再自动迁）或删除旧文件夹。跨组共用的留在第一个关联它的组。旧文件夹不会被主动扫描迁移，只在被落盘时迁。

## 0.19.0 — 2026-10-13

**会话信息卡 + 合并落盘项目**

- 会话信息卡（会话输入框上方，替代原来的记忆提示条）：收起时一行（组 / 卡片、落盘项目数、仓库 / 链接 / 子任务 / 说明 / 文件胶囊、看板直达、展开）；展开后分「落盘项目」「卡片资料」两组。有关联用项目看板按钮同款浅蓝填充，没关联用浅灰。每个落盘项目一行：名字、所属项目、指针 / 合并结果 / 关联来源标签、别名、next_action、注入状态与字数、「落盘」按钮（发到本会话）。没关联时第一行是「新建落盘项目」输入框（空格分隔多个名字：第一个不含中文的当文件名，其余是别名；留空由 AI 起名）。
- 「查看 AI 收到的原文」浮层：系统提示（常驻规则 + 本卡片档案与落盘项目索引）与注入会话的全文，和发给 AI 的逐字一致；显示版本、是否已在本会话、约多少 token，可复制，Esc 关闭。
- 合并落盘项目：卡片关联多于 1 个时可「合并」。勾选（默认全选、全选 / 全不选），没选的照常显示；面板列出别名、计划和「文件去向」。点「开始合并」后由本会话的 AI 读全每份来源（每读完一份先写要点，防压缩丢进度）、整体重写一份 STATE，插件 `landfill op=merge action=commit` 校验（读全、要点齐、来源里的关键事实都在、文件索引覆盖所有文件、`[必读]` 只标文本）后写入。
  - 文件全部归位到 `~/.ai`：合并结果文件夹 = STATE.md + notes/（文档、每份来源的要点）+ evidence/（图片、从 ~/.ai 外复制进来的文件）；内容相同只留一份，同名不同内容按来源分目录，`*.bak` 不带；STATE 里引用的 ~/.ai 外文件复制进 evidence/ 并改路径（原文件不动），本机已不存在的列出来；来源整个文件夹移到各自项目的 `inbox/retired/<时间>-merge-<名字>/`。
  - 被合并的名字写进 STATE 的 `aliases:`，说「回忆 / 落盘 + 旧名字」照样能找到；卡片和卡片组的关联换成合并结果；`~/.ai/memory` 下与相关项目 MEMORY_INDEX 里指向旧路径的引用一并改指向（报告列出改了哪几处）。
  - 每次合并的结果和它自己的「合并完成」卡片包成一个单元（可折叠，最新的展开）：列出合并前的落盘项目（含回收区路径），「撤销合并」只退一步（合并后又写过或回收区缺文件时拒绝并说明），「删除合并前的落盘项目」永久删除这次合并在回收区里的全部（连同更早合并的）；回收区里还有就一直显示，删完不显示。
  - 合并结果可以再合并：合并前列表按层级显示，更早那次合并的来源缩进列在它下面，可单独删除（它本身留着，撤销上一层后回来）。
  - 中途失败按已做的倒着撤回；本会话还没提交时可取消；回合结束还没提交会拉回（每条合并指令最多 2 次）。
- ai-memory v3：新增 `retire-dir` / `restore-dir` / `purge-retired`（整个文件夹移进 / 移回 / 永久删除回收区，逐文件记 journal）。合并需要 v3，旧版时提示在看板顶部点「升级 ai-memory」。
- 看板：会话信息卡的看板按钮直达这张卡片（选中、打开详情、闪一下）；「相关说明」去掉「重置」，只留「清空」（可 ⌘Z 撤回）；每条相关链接加复制按钮（与 dsh-manage-sessions 同款图标，对勾 1.2 秒 + 提示）；截断的文字悬停时走马灯（减少动效时改成悬停提示）。
- 「N 进行中」改为：没归档、且至少有 1 个没归档会话（不算子代理）的卡片；会话或卡片归档 / 恢复后立刻刷新，悬停显示口径。

## 0.18.0 — 2026-10-13

**落盘项目：一个项目一个文件夹 + 卡片档案 + 完整读取 + 最新版注入**

- 项目文件夹：`STATE.md` + `plans/` `notes/` `evidence/`；STATE「📁 文件索引」每个文件一行（`[必读]` / `[参考]`）。persist 拒绝 `UNINDEXED_FILES`（有文件没索引）、`BAD_TAG`（二进制标必读）；报告 `files.dangling` / `requiredWarning` / `folderWarning`。
- 完整读取：`recall` 加 `file` 读子文档；`complete` = STATE + 全部 `[必读]` 读完，否则给 `pending`；`persist` / `write` / `retire` 都要先读完。首段带 `docs` 文件清单。
- 新 op：`write`（文件夹里的文本）、`retire`（移到 `inbox/retired/`）、`import`（本机文件 → `evidence/`，要 ai-memory v2）。`slug` 可省 = 卡片的 STATE；卡片已有 STATE 再新建别的 → `CARD_HAS_STATE`（`newState:true` 放行）。
- 卡片档案块：persist 时按看板生成写进 STATE（`<!-- dpm:card -->`），不参与锚点比对；块内失效路径报 `cardMissingPaths`；recall 时看板已变 → `cardStale` + 实时块。
- 注入：系统提示合成一段（卡片档案实时 + 记忆索引带版本）；STATE 与 `[必读]` 全文由插件按当前版本注入会话，别处改了下一步补新版（`replaces` + `writer`），压缩后重注，超出 96000 字符的列出续读位置并拉回。已知版本跨重启保存（`landfill-known.json`），分叉继承。StateCatalog 改为按 mtime + 大小失效。
- 批准的计划自动存到 `plans/<日期>-<标题>.md`。
- 修复：讨论「落盘项目」功能时误判为落盘指令（只认行首 / 带项目名 / 末尾，引号里的不算）；规划模式下仍要求落盘并拉回（改为只提示）；连续两轮被忽略仍拉回（第三轮起不拉）。
- ai-memory v2：新增 `version`、`import`（锁内复制 + journal，支持二进制）；看板检测到本机旧版时显示「升级 ai-memory」按钮（先备份）。

## 0.17.0 — 2026-10-13

**落盘项目：STATE 整体优化 + 分段完整回忆**

- `recall` 分段：每段 ≤32000 字符（切在 `## ` 标题或换行处），返回 `next` / `complete` / `missing`，第一段带 `toc`。原来超过 64000 字符只给前半段，模型照着改写会丢尾部；现在按 `offset` 读到 `complete:true`。段长按宿主直给上限（`maxInlineTokens` 12500）定，本机 243 份 STATE 每段最多约 9000 token。
- `persist` 两道防丢：①本会话没读全当前版本 → `NEED_FULL_READ`（列出缺的 offset）；②新稿少了旧稿里的 commit / 版本号 / 路径 / URL / 单号且没写进 `drop` → `DROPPED_ANCHORS`（列出缺的），都不写盘。分段之间被别处改过 → `CHANGED`，从头读。
- `persist` 返回报告：前后字符数、删掉的标题、删掉的锚点数、超过 30000 字符或大 STATE 没变小时 `sizeWarning`、本机不存在的路径 `missingPaths`。
- skill 新增「Holistic Optimization」：每次落盘重写整份 STATE（推荐结构、删什么、怎么精简、哪些原样保留、先核实再写）；落盘提示和常驻规则同步。
- 回忆只认 `recall` 读全才算完成（`read` 有行数上限，不再算）。
- 不留历史版本，不新增会增长的存储。

## 0.16.0 — 2026-10-13

**新增：落盘项目并入插件（只装本插件即可完整使用）**

- `landfill` 工具（`recall / persist / append / list / register / validate`），经 `~/.ai/tools/ai-memory` 读写：自动认项目（卡片仓库 → 会话目录）、已存在的 STATE 必须本会话读过才能写、写后回读校验、冲突原样返回 inbox 路径不重试、落盘成功自动关联当前卡片、登记新项目必须 `confirm:true`（先问用户）。
- 自动触发：`agent/pre-step` 识别用户原话「落盘项目 / 回忆 / 继续 + 项目名」（项目名来自 `~/.ai` 现有 STATE），追加一条瞬态提示；`systemPrompt.context` 常驻落盘规则。
- 拦截：`write` / `edit` / `bash` 直接改 `~/.ai` 下记忆文件（`memory/**`、`projects/<id>/memory/**`、`REGISTRY.md`）一律拒绝；只读命令与经 ai-memory 的命令放行。
- 收尾检查：本轮要求落盘 / 回忆却没做到 → `agent/turn-stopping` 里 `steer` 拉回，每轮最多 2 次；模型在问用户时不拉回。
- 命令 `/landfill [项目]`、`/recall [项目]`；卡片详情「关联的落盘项目」下新增「回忆」「落盘」按钮（发到卡片最近的会话并打开，没有就新建）。
- 插件包自带 `bin/ai-memory`（含测试）与 `skills/landfill-project/SKILL.md`（DSH 内外两用）。启动时只补缺：建 `~/.ai` 骨架、复制 ai-memory、在 `~/.agents` 下建 skill 链接；已有单独 SKILL.md 时看板顶部提示「接管」（备份到 `<dataDir>/backups/` 后换成链接）。
- 环境不满足（Windows / 没有 python3 / macOS 未装命令行开发工具时不调用 `/usr/bin/python3`，避免弹安装框）时只关闭落盘这块，看板顶部说明原因。
- 新配置：`landfill`（默认 true）、`agentsHome`；`aiRoot` 不再标「只读」。

**调整**

- 卡片组目录里生成的 AGENTS.md：「~/.ai 只读」改为「不要直接改文件，读写 STATE 用 landfill 工具」。

## 0.15.0 — 2026-10-12

**修复**

- 分叉会话（宿主「分叉」出来的会话）被当成子智能体过滤掉：卡片组数字少算、卡片详情里看不到、侧栏不补画。宿主给分叉也带 `parentId`，现在只按 `origin = subagent` 排除子智能体。详情里分叉会话标「分叉自「源会话」」。
- 0.14 之前分出的旧分叉（源会话关联了卡片、它自己没关联）打开看板时自动补关联到源会话的卡片；写盘前备份 `board.json.bak-fork-<时间>`，审计事件 `session/fork-backfill`。
- 新增仓库弹窗勾选候选仓库后列表跳回顶部：勾选只更新勾选状态和「已选」，候选列表不重画。
- 点「项目看板」长时间白屏：看板以前要等第一次 `/state` 回来才画任何东西。现在先用侧栏已有的快照立刻画出（第一次打开画骨架），后台同步超过 300ms 时标题旁显示「正在同步…」。`/state` 只读审计日志末尾 64KB；超过 1 秒在日志里记每一步耗时。

**新增 / 调整**

- 卡片「相关文件」新增「粘贴路径」：一次可贴多行，自动处理引号、`file://`、`~`、转义空格；每行由宿主检查「存在 / 是文件夹 / 不存在 / 已关联 / 重复 / 不是绝对路径」，只添加通过的，有问题的行留在输入框。⌘/Ctrl+Enter 添加，Esc 关闭。系统选文件框打不开时自动打开它。新路由 `card/files-check`（只读）。
- 相关说明编辑时输入框有内容，「重置」左边出现「清空」；清空后没保存，「重置」能找回。
- 卡片「新增仓库」：「全部加入已选（N）」只把本组共用仓库放进「已选」，可再取消勾选或改名，点保存才写入。
- 新增仓库弹窗布局：标题与搜索固定在顶；「候选仓库」与「已选 + 按钮」高度 2 : 1，各自只滚列表；「本组共用仓库」「其他候选仓库」标题滚动时吸顶（下一组把上一组顶走），「候选仓库」标题行右侧分组切换随滚动高亮、点击平滑跳转。

## 0.14.0 — 2026-10-12

**新增**

- 卡片有自己的仓库清单：卡片详情「仓库」区可以「新增仓库」、移除仓库，只影响这张卡片。
- 卡片组设置里的「仓库」改名「卡片共用仓库」（按钮「+添加卡片共用仓库」）：在组里新建卡片时复制一份；之后改组的共用仓库，已有卡片不变。
- 添加仓库弹窗去掉「dsh 已添加的工作区」，换成「候选仓库」：任意卡片组、卡片添加过的仓库（移除了也在），最近添加的在前。卡片的「新增仓库」里本组共用仓库单列一组，可「一键添加所在卡片组全部共用仓库」。
- 卡片资料注入新增「仓库」（名称、角色、repos/<名>/ → 绝对路径）和「子任务」（完成状态）两节。
- 在项目区里分叉已关联卡片的会话，新会话自动关联同一张卡片（带上源会话已读过的落盘项目）。
- 「管理类型」可拖动把手或 Alt+↑↓ 调整顺序，类型下拉按这个顺序；拖动时落点是两项之间的独立指示线。新路由 `linktype/move`。
- 相关链接重复检测：同一张卡片里同一个链接（域名大小写、末尾 /、有无 https:// 视为同一个）不能保存，显示已添加那条的显示文字、类型、完整链接，可直接编辑它；服务端同样拒绝（`DUP_URL`，点名第几条）。

**升级说明**

- 首次启动把每张已有卡片的仓库设成它所在组当前的仓库（表现与升级前一致），候选仓库从现有仓库起步。0.14 之前已移除的仓库不在候选里（旧事件没有记录路径）。
- 卡片组目录 repos/ 下挂「组共用仓库 + 本组卡片自己的仓库」；同名不同路径的后来者叫「名-2」，注入时写实际路径。
- 新路由：`card/repos-add`、`card/repos`、`linktype/move`。

## 0.13.0 — 2026-10-12

**新增**

- 删除还没对话的会话（数据层面）：侧栏项目区补画的「未开始」行悬停出现删除按钮（「未开始」标签让位），卡片详情「本卡片的会话」里未开始的会话也有删除按钮；确认后会话目录与登记一起删掉，卡片上的关联同步去掉，不能恢复。有对话的会话仍只能归档。
- 相关链接标题行「添加链接」左边加「管理类型」：小窗口列出全部类型和各自在用的链接数，可新增、改名；改名连带所有卡片（含已归档）里用这个类型的链接，全局生效。新路由 `linktype/rename`（重名 / 空 / 超 20 字点名报错，整批不写）。

**调整**

- 添加 / 编辑链接的类型下拉去掉「＋ 新增类型…」，新增统一在「管理类型」里做。
- 详情里还没对话的会话标「未开始」（原来标「活跃」），没有标题时显示「新会话」。

**实现说明**

- 删除调用 dsh-manage-sessions 的 `/dsh-manage-sessions/delete`（停空闲会话 → 写锁 → 会话目录移入回收区并记日志 → 官方 forgetSession 清工作区 / 归档 / 置顶登记 → 清回收区；中途失败回滚或启动时续做）。插件启动时读它的 capabilities，`delete: true` 才显示按钮；前端删除前再确认会话仍是 blank。

## 0.12.0 — 2026-10-11

**新增**

- 项目区与卡片组里「还没对话」的会话也显示出来（DSH 默认只显示当前打开的那个），排在最前，标「未开始」，点击打开。
- 卡片详情「本卡片的会话」「关联的落盘项目」默认显示 3 项，其余用「展示更多（还有 N 项）/ 折叠」切换；切换卡片回到 3 项。

## 0.11.0 — 2026-10-11

**新增**

- 侧栏卡片组行显示活跃会话数（该卡片组子工作区里没归档的会话，不含子代理）：蓝色小圆数字，0 为灰色；新建 / 归档 / 恢复会话后立即更新，变化时轻跳一下。悬停时数字仍在，宿主的操作按钮出现在它右侧。
- 从项目看板进入会话（详情「打开」、「新建会话」弹窗、以此卡片新建会话）后，会话所在的卡片组（以及「项目区」）在侧栏收起着就自动展开，并滚到这个会话。只作用于项目区里的会话。
- 卡片详情「关联的落盘项目」默认只显示标题；标题栏一个「展开详情 / 收起详情」按钮一次展开或收起全部，切换卡片时保持，重开看板回到收起。

**调整**

- 侧栏层级：卡片组下的会话整行缩进到一条竖向引导线右侧（选中 / 悬停底色、其他插件给会话行加的边框与填充一起缩进），展开的卡片组名加粗；「项目区」自己的会话在按工作区树分组时与卡片组同一级。

**修复**

- 「添加挂载仓库」的候选列表不再出现插件自己的卡片组子工作区（`hub/groups/…`，0.9.0 起会被列出）。

**实现说明**

- 数字与层级是一张按行 id 生成的样式表（`[data-row-key="workspace:<id>"]::after`），不改宿主节点；DSH 改版找不到行时不显示，功能不受影响。自动展开 = 对 `aria-expanded="false"` 的行模拟一次点击，与用户手动展开走同一路径。

## 0.10.0 — 2026-10-10

**新增**

- 卡片详情「相关链接」：位于「相关说明」和「相关文件」之间，完整列表不折叠。每条有「显示文字」「类型」「完整链接」，列表只显示文字 + 类型，点击用默认浏览器打开（dsh 桌面版把新窗口请求交给系统浏览器）。
  - 添加弹窗可一次加多条（「再加一条」，或在「完整链接」里粘贴多行网址自动拆分）；显示文字不填就用网址。
  - 网址简单校验：只收 http(s)，没写协议但像域名自动补 `https://`，空格 / 其他协议 / 不完整域名就地报错（服务端同口径校验，`BAD_URL` 点名第几条，整批不写）。
  - 「类型」下拉默认「文档」「代码」，可「＋ 新增类型…」；新类型存进看板（`board.linkTypes`），任意卡片都能选。
  - 每条悬停出现「编辑」「删除」（删除可撤销）；按住左侧手柄拖动排序，或聚焦手柄后 Alt+↑/↓。
- 卡片资料注入会话：卡片有相关说明 / 相关链接 / 相关文件时，关联会话的上下文在项目记忆后追加「卡片资料」一段：说明全文（放进文本围栏，超过 16KB 截断并注明）、链接列表（显示文字 + 网址 + 类型）、文件绝对路径列表。详情底部标签与会话记忆条会提示「+ 卡片资料」；没关联落盘项目时卡片资料也照常注入。
- HTTP：`card/weblinks {id, links}`（整表替换）、`linktype/add {name}`；`/session` 返回 `materials` 计数。

**调整**

- 「相关说明」过长时不再是固定高度内部滚动：超过阈值折叠（底部渐隐）+「展开全部 / 收起」。
- 在看板里归档会话后留在看板：dsh 归档「当前打开的会话」时会关掉主区面板并落到新建会话页，插件在归档期间把看板面板选回（只在看板是当前面板时生效）。
- 插件内所有下拉框改用自绘箭头，距右边 12px。

**兼容**

- 旧数据无 `webLinks` / `linkTypes` 字段时按空列表与默认两种类型处理，无需迁移。

## 0.9.0 — 2026-10-10

**新增**

- 卡片组 = 「项目区」的子工作区：每个卡片组登记一个子目录工作区（`hub/groups/<组 id>/`，标题 = 组名，按看板顺序紧跟「项目区」）。在 dsh 视图选项里选「按工作区树」分组时，卡片组嵌套在「项目区」下，可原生展开 / 收起。改组名同步工作区标题（目录不变）；删卡片组撤销它的工作区登记（目录与会话保留）。
- 子目录里只挂本组仓库（`repos/<仓库>` 软链接）和本组 AGENTS.md。
- 通过卡片新建的会话进卡片所在组的子工作区；分组方式是「按工作区树」时会话名只用卡片名（组名已在树上），其他分组方式仍是「组名 · 卡片名」。名字只在新建时决定，之后切换分组不改名。「新建会话」弹窗里预先显示位置与名称。
- 卡片组行悬停的「+」：先选卡片，浮层只列本组卡片；「项目区」行的「+」照旧列全部卡片。
- 「项目看板」全局面板主按钮：与「插件」同一组（官方 `sidebar.panellist`），整行渐变底 +「N 进行中」徽标（进行中 = 未归档、不在第一个也不在最后一个阶段的卡片）；悬停浮起、边框流光一周、光晕跟随鼠标、高光扫过；按下微缩 + 点击处波纹；打开看板时整行实心渐变、中间一列落下一张卡片。侧栏收成图标栏时是渐变方块 + 红色数字角标。动效只播一次、不循环；系统「减少动态效果」时全部关闭。

**调整**

- 去掉「项目区」行标题旁的看板按钮（入口统一为全局面板主按钮），也不再需要「找不到项目区行时」的降级入口。
- `hub/cleanup` 同时撤销卡片组子工作区登记（返回 `removedGroupWorkspaces`）。
- HTTP：`session/prepare` 返回卡片组子工作区（`workspaceId` + `workspaceTitle`）；`session/bind` 新增可选 `tree`（true = 会话名只用卡片名）；快照 `hub.groups`（卡片组 id → 子工作区 id）。

**兼容**

- 0.8.0 及以前建的项目会话目录是「项目区」根目录，dsh 不能给会话换目录，它们继续显示在「项目区」下（卡片组之后）；绑定关系、记忆注入不变。
- 主按钮整行样式靠 `button:has(.dpm-entry)` 选中宿主面板行（不依赖宿主哈希类名）；dsh 改版使之失效时退化为普通图标行，功能不丢。
- 分组方式读自 dsh 工作区浏览器的本地视图设置（非公开）；读不到时按「组名 · 卡片名」命名。

## 0.8.0 — 2026-10-10

**新增**

- 卡片归档：卡片右上角悬停出现归档图标（触屏常显），卡片详情标题旁也有；归档后卡片离开看板列，提示可「撤销」。卡片的会话保持原状，不跟着归档或恢复。
- 卡片组头部「已归档卡片 N」按钮，紧贴「新会话」右侧，默认收起；点开在头部下方就地展开列表（最近归档在上），再点或点 × 收起。列表展开时可把活跃卡片直接拖进来归档（只接收本卡片组的卡片）。
- 已归档列表每行：名称 + 灰字（原阶段 · 归档时间 · 会话数 · 落盘项目数）；点行打开只读详情，选中行与活跃卡片选中一样是蓝框；行尾图标「恢复活跃」，卡片回到原阶段末尾（原阶段已删除则回第一个阶段）。
- 已归档卡片详情只读：标题下一条状态栏「已归档 · N 天前，只能查看」+「恢复活跃」；改名、归档、关联、相关说明/文件、推进阶段、子任务、删除、新建会话都不显示。服务端同样拒绝修改已归档卡片（`CARD_ARCHIVED`）。
- 「本卡片的会话」里活跃会话加「归档会话」图标，与 dsh 侧栏「归档会话」同一调用（`workspaces.archiveSession`）：空闲直接归档，提示可撤销；会话还有进行中的工作时弹 dsh 原文确认「停止并归档此会话？」，列出将被停止的工作，确认后停止并归档。
- HTTP：`card/archive {id}`、`card/unarchive {id}`。

**调整**

- 卡片组头部不再折行：组名和统计过长时截断，右侧按钮始终一排。
- 「新会话」选卡片浮层只列活跃卡片。
- 删除阶段时只检查活跃卡片；已归档卡片不挡删阶段。

**兼容**

- board.json 的卡片新增可选字段 `archivedAt`（ISO 时间），旧数据无需迁移，版本号仍为 1。

## 0.7.0 — 2026-10-10

**新增**

- 卡片详情「相关说明」（在「关联的落盘项目」下面）：没保存过时直接是多行输入框（不限字数）；「重置」恢复成上次保存的内容（没保存过就是清空），「保存」后变成只读展示，网址可点击（在系统浏览器打开），「编辑」重新进入编辑。输入中会话推送不会打断。只给人看，不注入会话。HTTP：`card/notes {id, notes}`；请求体上限从 64KB 放宽到 2MB。
- 卡片详情「相关文件」（在「相关说明」下面）：「添加文件」弹出 macOS 系统选文件对话框（可多选，数量不限，已关联的自动跳过）；每项显示完整路径与状态（存在 / 已删除）；解除关联用图标按钮，只从列表移除、不删除文件。非 macOS 或对话框打不开时降级为手输绝对路径（点名失败原因）。HTTP：`card/files-pick {id}`、`card/files-add {id, paths}`、`card/files-remove {id, path}`；快照新增 `files`（路径 → 是否存在）。

**调整**

- 看板卡片不再显示子任务进度（在详情里看）。
- 卡片新增会话标志「气泡 + 数量」：有活跃会话 = 绿色，全部已归档 = 灰色，没有会话不显示（已删除的会话不计）；悬停显示活跃 / 已归档数量。
- 落盘项目标志改为有关联才显示，不再显示橙色「0」。

**兼容**

- board.json 的卡片新增可选字段 `notes`、`files`，旧数据无需迁移，版本号仍为 1。

## 0.6.0 — 2026-10-09

**新增**

- 「项目区」「+」→ 选卡片后弹出「新建会话」弹窗：单选「新建一个会话」（默认）或这张卡片已关联的会话（活跃在前、已归档在后，同类按更新时间新 → 旧）；已归档的不能选，可点「恢复活跃」就地恢复（弹窗不关，恢复后即可选）；「取消」不做任何事，「打开会话」新建并自动关联卡片 / 直接打开所选会话；双击一项直接打开。看板泳道里的「新会话」走同一流程。
- 同名落盘项目提示：卡片（含卡片组）没关联任何落盘项目、标题包含某落盘项目 slug（≥6 字符，取最长）时，弹窗与会话记忆提示条给「关联」按钮；HTTP `GET /session` 新增 `suggest`。

**调整**

- 选卡片浮层重做：两层信息（卡片名 + 阶段 / 记忆数 / 会话数）、卡片组标题吸顶并显示数量、悬停与上下键共用高亮（浅蓝底 + 左侧蓝条 + 右侧箭头）、搜索词高亮、空结果提示、键位提示。浮层背景为实色（宿主 token 缺失时也有显式回退色，不会透明）。
- 会话下方「已自动读取 N 个落盘项目的记忆」默认收起。

**说明**

- 「卡片已关联落盘项目仍提示没关联」未能复现：报告中的卡片在看板数据里确实没有关联（`links=[]`、卡片组也无关联），提示是准确的；同名落盘项目提示用于解决这类「会话里落盘了、卡片没关联」的情况。

## 0.5.0 — 2026-10-08

**新增**

- 卡片组排序：头部右侧新增拖动手柄（⠿），按住拖动、蓝线标落点、松开落位，其余卡片组平滑让位；拖动中 Esc 取消；键盘聚焦手柄后 Alt+↑/↓。HTTP：`group/move {id, beforeId}`（beforeId 缺省 = 放到最后），写入 events.jsonl。
- 卡片组头部左侧整块（箭头、组名、统计、空白）都能点击展开/收起；「组记忆」按钮保持原作用。

**调整**

- 卡片详情：「本卡片的会话」移到最上面；列表按 活跃 → 已归档 → 已删除 排序，同类按更新时间新 → 旧。

**修复**

- 卡片详情栏闪动：dsh 会话 / 工作区每次推送都会删掉详情栏重建并重放滑入动画（实测 60 秒 8 次）。现在同一张卡片的详情只在内容真正变化时原地更新，不重放动画，保留滚动位置、子任务草稿和焦点；仍然监听数据推送。拖动卡片组时暂停后台轮询重绘。

## 0.4.0 — 2026-09-29

**新增**

- 卡片详情「本卡片的会话」→「关联已有会话」弹窗：搜索（会话名 / 仓库名）、「活跃会话」「已归档会话」两列（按仓库分组，组内与组间都是新→旧），勾选即移入「已选会话」，「取消 / 保存关联」。已在别的卡片上的会话标「已关联在「X」」，保存后移到本卡片（一个会话只属于一张卡片）。
- 已关联会话列表：名字 + 状态（活跃 / 已归档）+ 仓库 + 更新时间；活跃的点名字打开，已归档的不能打开。
- 「恢复活跃」：已归档会话一键恢复，无确认，回到工作区归档前的位置（调用 `workspaceRegistry.unarchiveSession`，由 dsh-manage-sessions 核心补丁提供；缺失时按钮置灰并说明原因）。
- 「解除关联」：简单二次确认，只删绑定，不删会话。
- 记忆：手动关联的会话同样自动读取卡片记忆；关联时扫描会话记录，已读过（`read` 过对应 STATE.md，含 run_code 内调用）的落盘项目不再注入。
- HTTP：`session/link`、`session/unlink`、`session/unarchive`；快照新增 `caps.unarchive`；`SessionRef.readKeys`。

## 0.3.0 — 2026-09-29

**新增**

- 「卡片组设置」→ 仓库 → 「添加」打开「添加挂载仓库」弹窗：
  - 候选列表 = dsh 侧栏里已添加的工作区（不含「项目区」），可搜索、可多选；本组已挂载的锁定并标「已挂载」。
  - 「选择文件夹…」调用 dsh 的选文件夹对话框（与添加工作区同一个）；dsh 使用网页文件浏览器时降级为输入绝对路径。
  - 默认名称 = 文件夹名（与 dsh 默认工作区标题同一规则），名称与角色可改；空名、与本组已有或本批其他项重名时标红说明并禁用「保存」。
  - 「保存」一次追加全部（新 HTTP 动作 `group/repos-add`：任一名称/路径冲突整批不写，错误点名冲突对象）。
- 已挂载仓库行内改名称 / 角色，离开输入框即保存；移除立即生效。

**移除**

- 「保存仓库」按钮与手填名称 / 路径的空行。

## 0.2.0 — 2026-09-29

**BREAKING**

- 卡片组的「状态」改为「阶段」：只有名称，只用来给卡片分组。去掉 未开始 / 进行中 / 已完成 / 已取消 四个类别和「证据门」。
- `phase_move` 工具去掉 `evidence` 参数；`card_manage list` 不再给阶段标 🔒。旧调用多传的 `evidence` 会被忽略。
- HTTP `card/move` 不再接受 `evidence`；`card/create` 可以把卡片建在任意阶段。

**新增**

- 每个阶段底部常驻「添加卡片」：点开就地输入，回车添加并保留输入框（连续添加），Esc 或空着失焦收起。
- 卡片组设置里阶段只剩「序号上移 / 名称 / 删除」，「添加阶段」加到列表末尾。
- 详情栏「重命名」按钮换成铅笔图标。

**迁移**

- 自动完成，无需操作：旧 `board.json` 读入时丢掉阶段上的 `cat` / `gate` 和卡片上的 `ev`，阶段 id、名称、顺序和卡片位置都保留，下次写盘即为新格式。
- `events.jsonl` 里已有的证据记录不动。

## 0.1.0 — 2026-09-29

- 首个版本：项目看板、项目区工作区、项目会话（完全访问 + 自动读取落盘项目记忆）、4 个 agent 工具。
