dsh-session-mng 0.1.4 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.1 — 2026-11-02
4
+
5
+ ### Added
6
+
7
+ - **整枝移动(移动会话时连同子代理会话)**:根会话的子代理会话此前会阻止移动(`has-descendants`),现在它们跟随根会话一起迁移——先整体校验(任一会话已打开/运行中就整体拒绝,不留半移动状态),再逐个改写 header `cwd`、迁移目录、对账账本,任一步失败按逆序整体回滚;普通分支(fork)仍是独立会话,不跟随。移动成功的提示会写明「连同 N 个子代理会话一起移动」。
8
+ - **批量失败显示原因**:批量操作返回 200 但有条目失败时,toast 直接列出每个失败会话的 `code` 与消息(此前只显示「成功 0,失败 1」,看不出原因)。
9
+ - **「刷新页面」按钮**:设置页头部新增按钮,点击执行 `location.reload()` 重新加载整个 DSH 页面(与插件市场刷新同一个调用)。宿主侧栏的会话列表只在页面加载时拉取并按工作区分组,所以跨工作区移动会话后侧栏仍显示旧分组;点这个按钮即可让侧栏按最新归属重新分组。只重载客户端,不改变宿主进程里已打开的会话状态。
10
+ - **成功提示自动消失**:带操作按钮的成功提示(tone `ok`)现在也会自动隐藏(8 秒;不带按钮 5 秒),此前只要挂了按钮就永不消失;错误/警告提示仍保留到用户手动关闭。
11
+
12
+ ## 0.2.0 — 2026-10-29
13
+
14
+ ### Added
15
+
16
+ - **Host 侧会话 catalog(零会话日志 IO)**:新增 `lib/catalog.js`,从宿主的 `workspaceRegistry.headers`(启动时已建好的全量 header 索引)与 `sessionProjectionCache`(title / `sessionListMetadata`)组装会话行,不再为总览调用 `sessionController.list()`、`sessionPersistence.list()` 或批量 `readTitleSnapshots()`。内部 seam 全部特性检测;缺失时自动回退到 0.1.x 的 `buildState` 慢路径(30 s TTL),接口形状不变。
17
+ - **`GET /overview`**:首屏只返回工作区计数/归档计数/空会话计数、totals、orphans、capabilities、limits,**不含任何会话行**;10000 条会话的合成基准约 10 ms、payload 约 1.3 KB。
18
+ - **`GET /sessions`**:按 `workspaceId` + `tab` + `query` + `sort` + `offset/limit`(≤50)分页;Host 端 branch-aware 排序(父行优先)+ `id` tie-break 保证分页稳定;对不在本页的分支返回 `parentStub`;页内只对 ≤50 条日志做一次 readdir+stat 取大小。
19
+ - **`GET /search`**:跨工作区的标题/路径/id/父标题搜索(与 0.1.3 的搜索口径一致),一次请求返回每个命中工作区的 `total` 与首屏一页,供客户端自动展开。
20
+ - **`GET /session` / `GET /blanks` / `GET /sizes`**:详情单行、空会话 id 列表、按工作区/全局大小统计;大小统计复用一次 `sessionPersistence.list()` 并做 60 s 进程内缓存。
21
+ - **客户端两段式加载**:首屏 `overview` → 展开工作区时取第一页 → 「加载更多」按 offset 追加;每工作区页缓存 + 行缓存,请求并发上限 3,切换筛选/排序/搜索时按 scope 失效。
22
+ - **老 Host 回退**:`GET /overview` 404 时一次性探测并回退到 `GET /state`(0.1.4 行为),旧 Host + 新 Client 仍可用;`GET /state` 本身保持不变。
23
+ - **配置项**:`sizesTtlMs`(默认 60000)、`sizeScanMax`(默认 20000)、`pageLimitMax`(默认 50)。
24
+
25
+ ### Changed
26
+
27
+ - **列表默认每工作区 50 条改由 Host 分页**:客户端不再持有全量行;组头计数与「剩余 N 条」来自 Host 的 `total`,组大小异步取自 `/sizes`(未到达时显示「—」)。
28
+ - **搜索改为宿主搜索**:输入防抖 250 ms 后请求 `/search`,命中工作区自动展开;搜索期间仍锁定折叠与「展开全部/收起全部」。
29
+ - **选择语义收紧**:只允许选择已加载且已展开的行;切换 tab/工作区/搜索/排序/开关会清空选择;「全选当前列表」只作用于已加载可见行,并提示另有 N 条未加载;批量提交前再次过滤未加载 id(数据安全)。
30
+ - **分支跨页展示**:父会话不在本页时不再误报「来源父会话已不存在」——有 `parentStub` 时显示「↳ 来自:父标题」,仅 Host 确认父不存在时才显示原提示;`forkCount` 始终是全域名额。
31
+ - **详情页独立取数**:进入详情先用行缓存立即渲染,再由 `GET /session` 补齐;刷新不会再因为「不在当前列表数据里」把详情踢回列表。
32
+ - **刷新策略**:写操作与「刷新」按钮改为刷新 overview + 按已加载深度重取当前展开工作区的页,保留选择与滚动位置;窗口重新获得焦点时只静默刷新 overview,不再全量重取。
33
+
34
+ ### Fixed
35
+
36
+ - **排序键相同时行序不稳定**:`updated/created/size/title` 四种排序全部补 `id` 升序 tie-break,分页切片不再重复/漏行。
37
+ - **切换排序不重置分页与选择裁剪**:`sort` 纳入分页 limit 重置与选择裁剪的依赖键,修掉 0.1.x 遗留的失效漏项。
38
+ - **空会话 / orphan / 计数在分页后失真**:tabs 计数、hiddenBlankCount、hiddenSubagents、orphan 横幅与两个空会话按钮全部改为读 overview / `/blanks`,不再由「已加载行」推算。
39
+ - **老 Host 回退丢失每工作区分页**:回退 `/state` 时仍按每组 50 条渲染 + 「加载更多」,不一次性铺满整组。
40
+
41
+ ### Compatibility
42
+
43
+ - 实测宿主 DSH `0.2.1-rc.2` / `0.2.1-rc.3`;`GET /state` 保留,0.1.x 客户端不受影响。
44
+ - 快速路径依赖的两个宿主内存 seam(`workspaceRegistry.headers`、`sessionProjectionCache`)仍属版本敏感点,已全部特性检测并保留慢路径兜底。
45
+
3
46
  ## 0.1.4 — 2026-10-28
4
47
 
5
48
  ### Fixed
package/README.md CHANGED
@@ -17,14 +17,16 @@
17
17
  ## 功能
18
18
 
19
19
  - **统一会话总览**:按工作区分组列出当前 profile 的全部会话(活跃 + 已归档)。显示标题、路径、会话 id、大小、最后活动时间、运行/已打开/已归档/已置顶/分支/子代理标记;支持搜索、工作区筛选、排序、刷新、批量选择。
20
+ - **「刷新页面」按钮**:头部一键 `location.reload()` 重载整个 DSH 页面(与插件市场刷新同一个调用)。宿主侧栏只在页面加载时拉取会话列表并按工作区分组,跨工作区移动会话后侧栏不会自己重新分组,点它即可让侧栏按最新归属刷新(只重载客户端,不动宿主进程里已打开的会话)。
20
21
  - **分支会话默认显示**:从某条会话分出来的会话(fork)和主会话一样可见、可管理——缩进挂在父会话下方,父行显示「N 分支」,分支行标注「↳ 来自:父标题」;搜索父标题也能找到它。由委派产生的**子代理会话**仍默认隐藏(勾选「显示子代理会话」查看),总览行会提示「已隐藏 N 个子代理会话」。
21
- - **工作区优先 + 分页**:会话数 >100 时默认折叠工作区;每个工作区默认 50 条,「加载更多」继续展开;搜索自动展开命中工作区。过滤工具栏和批量条整体吸顶。
22
+ - **按工作区分页(Host 侧)**:首屏只取工作区概览(会话数/归档数/空会话数/大小占位),展开工作区才按 50 条一页向宿主取行,「加载更多」继续追加;会话数 >100 时默认折叠工作区;搜索自动展开命中工作区。过滤工具栏和批量条整体吸顶。
23
+ - **万级会话可用**:Host 新增零会话日志 IO 的 catalog(复用宿主的 header 索引与投影缓存),10000 条会话首屏 overview 约 10 ms / 约 1.3 KB,单页 50 行约 9 ms;`GET /state` 保留给 0.1.x 客户端与回退路径。
22
24
  - **选择跟随可见集**:切换筛选/折叠/搜索/刷新后,隐藏会话自动取消选择;`全选当前列表` 只作用于当前筛选与已展开的工作区。
23
25
  - **空会话默认隐藏**:侧栏本来就不显示的 `blank` 会话,会话管理默认也不显示;勾选「显示空会话」才出现。提供「清理空会话(N)」快速清理已归档空会话。
24
26
  - **删除范围模态确认**:范围内容在弹窗内独立滚动,底部勾选与确认/取消按钮固定可见;支持遮罩点击/Esc 取消。
25
27
  - **生成标题**:选中任意会话(**包括已归档的冷会话**),让模型总结整段对话,给出可编辑的标题提案;**确认后才写入**。活跃会话走官方 `sessionTitle.rename`,冷会话按官方 `session/title` 事件形状追加,不需要恢复会话。
26
28
  - **归档 / 恢复**:调用官方 `workspaceRegistry.archiveSession` / `unarchiveSession`。运行中的会话先提示,用户二次确认后才停止并归档;恢复后回到原工作区原位置。
27
- - **跨工作区移动**:把冷会话真正迁移到目标工作区——改写会话日志 header 的 `cwd`、把日志目录迁到目标项目目录、同步 workspace 账本。SessionId、归档状态、pin 状态不变,事件字节不变。
29
+ - **跨工作区移动(整枝)**:把冷会话真正迁移到目标工作区——改写会话日志 header 的 `cwd`、把日志目录迁到目标项目目录、同步 workspace 账本。**根会话的子代理会话会一起搬走**(它们的 `parentSession` 血缘保持不变),普通分支(fork)是独立会话,留在原工作区。整枝先整体校验(任一会话已打开/运行中就整体拒绝)、逐个迁移、失败按逆序整体回滚。SessionId、归档状态、pin 状态不变,事件字节不变。
28
30
  - **彻底删除已归档会话**:删除前先预览范围(根会话、子代理会话、目录、字节数);确认后把日志目录移出 store、清理归档集合与 workspace 账本,再删除。**不可恢复。** 子代理会话随父级联删除;**普通分支会话不会**(它们仍是独立会话,来源父会话删除后保留下来),如需一并删除请把分支也勾选进来。
29
31
  - **预览最近消息**:不恢复会话即可看最近 10 条用户/助手消息。
30
32
  - **失效归档标记清理**:归档集合里有、但磁盘上已无日志的 id,会以横幅提示并允许清理。
@@ -73,17 +75,23 @@ Host 半是进程内模块:装完如果看不到页面,重启一次 dsh/应
73
75
 
74
76
  ```
75
77
  Settings page (client.js)
76
- │ GET /session-mng/api/state
78
+ │ GET /session-mng/api/overview ← 首屏:只有计数,没有会话行
79
+ │ GET /session-mng/api/sessions?... ← 每个展开的工作区一页(≤50 行)
80
+ │ GET /session-mng/api/{search,session,blanks,sizes}
81
+ │ GET /session-mng/api/state ← 0.1.x 兼容 / 老 Host 回退
77
82
  │ POST /session-mng/api/{preview,title/propose,title/apply,archive,unarchive,delete/preview,delete,move}
78
83
  ▼
79
84
  Host route (lib/api.js) ──► service (lib/service.js)
80
- ├─ state : sessionController/sessionQuery + workspaceRegistry + sessionPersistence
85
+ ├─ catalog : workspaceRegistry.headers + sessionProjectionCache(零会话日志 IO;seam 缺失回退 buildState 慢路径)
86
+ ├─ state : buildState 慢路径 / sessionController + sessionQuery + workspaceRegistry + sessionPersistence
81
87
  ├─ title : sessionQuery.readSurface → ctx.llm.stream → 确认后写 session/title 事件
82
88
  ├─ archive : workspaceRegistry.archiveSession / unarchiveSession
83
89
  ├─ move : 日志 header cwd 重写 + 目录迁移 + workspace 缓存对账(失败全回滚)
84
90
  └─ delete : 删除范围预览 → 目录移入临时区 → 清理账本 → 删除(失败回滚)
85
91
  ```
86
92
 
93
+ - **首屏是概览、行是分页**:`overview` 只聚合内存索引;`sessions` 每页最多 50 行,排序/分支嵌套在 Host 完成后再切片,`id` tie-break 保证翻页稳定。
94
+ - **catalog 不落盘、不缓存会话**:行从宿主已有的 header 索引与投影缓存读取;归档/移动/删除/改标题后只失效大小快照与慢路径缓存,下一次请求自然重建。
87
95
  - **标题是日志事件**:`session/title` 的 `source` 为 `user`,与官方重命名一致;已归档会话不需要恢复 Agent。
88
96
  - **工作区归属是派生的**:由会话 header 的 `cwd` 决定。移动必须改写 header,只改账本无效。
89
97
  - **不碰事件正文**:移动只重写日志第一个 frame(header),其余字节原样保留;移动后重新完整 replay 校验一次。
@@ -98,8 +106,8 @@ Host route (lib/api.js) ──► service (lib/service.js)
98
106
  | Node | `>=20.3` 可运行总览/标题/归档/删除;**移动** 需要 `node:zlib` 的 Zstandard 支持(Node `>=22.15`,当前 Desktop 运行时为 Node 24.21) |
99
107
  | 会话后端 | 移动/删除只支持本地 JSONL 后端(`sessionPersistence.locate`);其他后端仍可用总览/标题/归档/恢复 |
100
108
  | 官方依赖 | 无 runtime 依赖;只使用 `ctx` 服务 |
101
- | 已知限制 | 已打开(live)会话不能移动或彻底删除,重启 DSH 后重试;有子代理后代的会话不能单独移动;子代理会话默认隐藏(可勾选「显示子代理会话」查看);分支会话默认显示,但暂不能单独移动(需与父会话留在同一工作区);删除父会话不级联普通分支,分支会失去来源标识(显示「来源父会话已不存在」) |
102
- | 规模限制 | 0.1.1 的折叠/分页只在客户端压 DOM,`state` 仍一次拉全量(202 条约 103 KB;10000 条约 5 MB)。Host 侧 overview + paged sessions 是 0.2.0 的主任务 |
109
+ | 已知限制 | 已打开(live)会话不能移动或彻底删除,重启 DSH 后重试;移动会连同子代理会话整枝迁移,普通分支不跟随;子代理会话默认隐藏(可勾选「显示子代理会话」查看);分支会话默认显示,但暂不能单独移动(需与父会话留在同一工作区);删除父会话不级联普通分支,分支会失去来源标识(显示「来源父会话已不存在」) |
110
+ | 规模限制 | 首屏与分页行走 Host catalog,不拉全量行;单页上限 50。**大小**按需异步统计(`/sizes` 复用一次 `sessionPersistence.list()`,10000 条约数秒),首屏/分页不依赖它。依赖宿主的两个内存 seam(`workspaceRegistry.headers`、`sessionProjectionCache`),缺失时自动退回 0.1.x 的 `buildState` 慢路径 |
103
111
 
104
112
  ### 版本敏感点(请读)
105
113
 
@@ -125,6 +133,9 @@ Host route (lib/api.js) ──► service (lib/service.js)
125
133
  titleMaxBytes: 120
126
134
  allowRemote: false # 默认只接受 loopback / webRuntime.trustedHosts
127
135
  sessionsRoot: '' # 仅在 sessionPersistence.locate 缺失时作为定位兜底
136
+ pageLimitMax: 50 # /sessions 单页上限(1–200)
137
+ sizesTtlMs: 60000 # /sizes 全量大小快照的进程内 TTL(1s–1h)
138
+ sizeScanMax: 20000 # /sizes 最多统计的会话数,超出返回 sizes-pending 降级
128
139
  ```
129
140
 
130
141
  ## 安全边界
@@ -137,25 +148,34 @@ Host route (lib/api.js) ──► service (lib/service.js)
137
148
  ## 开发
138
149
 
139
150
  ```sh
140
- npm test # node --test,29 个单元/集成测试
151
+ npm test # node --test,Host 单测 + 客户端 vm 测试
141
152
  node --check index.js client.js lib/*.js
142
153
  npm --cache /tmp/dsh-npm-cache pack --dry-run
143
154
  ```
144
155
 
156
+ > **改了 `client.js` 之后请重启应用,不要只刷新页面。** 宿主在启动时把每个插件的客户端产物(bundle + `rev`,`rev` 由文件的 mtime/ctime/size 算出)读进内存并组好图;本插件用 `link:` 安装时源文件是活的,运行中被改写后内存里的产物与磁盘不一致,此时页面重载会让 boot 审计把该条目判成「未激活」(桌面版弹「应用无法启动」,日志 `/Users/<you>/Library/Logs/DeepSeek Harness/crash-*-web-boot.log`)。重启应用会重新读盘组图,立刻恢复。这也是应用内插件管理器那条「1 项变更需重启后生效」的同一个道理。
157
+
145
158
  实机验收:安装到 `desktop` profile → 确认 `settings.section` 出现 `session-mng-section` → 用**一次性测试会话**验证标题/归档/恢复/移动/删除 → 清理测试数据。0.1.3 的验收与实机记录见 `docs/RELEASE-CHECKLIST-0.1.3.md`。
146
159
 
147
160
  ## 当前状态与下一步
148
161
 
162
+ - `0.2.1` 已发布到 npm / GitHub / Release(2026-11-02):**整枝移动**(根会话的子代理会话随根会话一起迁移,先整体校验、逐个迁移、失败逆序回滚;普通分支仍不跟随)、批量失败 toast 显示每条原因、头部「刷新页面」按钮(整页重载)、带操作按钮的成功提示也会自动消失。131 个测试全绿。
163
+ - `0.2.0` 已发布到 npm / GitHub / Release(2026-10-29):Host 侧新增零会话日志 IO 的会话 catalog 与 7 条只读路由(`/overview`、`/sessions`、`/search`、`/session`、`/blanks`、`/sizes`,`/state` 保留);首屏只取概览,工作区展开才按 50 条一页取行;搜索改由宿主完成;选择只作用于已加载行;详情独立取数不再被刷新踢出;分支跨页不再误报父会话已删除。10000 条合成基准:overview ≈ 10 ms / 1.3 KB,单页 50 行 ≈ 9 ms。129 个测试全绿(Host 72 + 客户端 vm 57)。
149
164
  - `0.1.4` 已发布到 npm / GitHub / Release:详情页标题行吸顶;操作结果改为浮动 toast(成功 5 秒自动消失);头部按钮移到标题右侧;新增「归档空会话(N)」,「清理空会话(N)」只要有已归档空会话就显示,且超过 50 条自动分批预览/删除。
150
165
  - `0.1.3` 已发布到 npm / GitHub / Release:三态会话模型(根/分支/子代理),分支默认显示并缩进在父会话下;删除父会话不再级联删掉普通分支;父会话有历史分支时也能移动;兼容声明增加 DSH `0.2.1-rc.3`。
151
166
  - `0.1.2` 已发布:空会话默认隐藏、清理空会话、删除范围模态确认。
152
- - 29 个测试全绿;0.1.4 包 37 个文件 / 583.2 kB(unpacked 834.8 kB)。
153
- - 市场条目已收录:PR [#9672](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/9672) 已于 2026-10-27 合并(`check` 与仓库年龄 gate 均通过);卡片版本随 npm 自动更新,当前 0.1.4。
154
- - 下一项主任务:**0.2.0 Host 侧 overview + 分页 sessions**,为 1000–10000 条会话设计;详细任务、验收标准、环境坑见 [接手说明](docs/HANDOVER-2026-10-27.md)。
167
+ - 131 个测试全绿;0.2.1 包内容见 `docs/RELEASE-CHECKLIST-0.2.1.md`。
168
+ - 市场条目已收录:PR [#9672](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/9672) 已于 2026-10-27 合并(`check` 与仓库年龄 gate 均通过);卡片版本随 npm 自动更新,当前 0.2.1。
169
+ - 下一项主任务见 [接手说明(0.2.0 之后)](docs/HANDOVER-2026-10-29.md):先完成 0.2.0 的实机只读验收与发版,再安排全文内容搜索、导出、置顶等候选。
155
170
 
156
171
  ## 文档索引
157
172
 
158
- - [接手说明(下一步任务)](docs/HANDOVER-2026-10-27.md)
173
+ - [接手说明(2026-10-27)](docs/HANDOVER-2026-10-27.md)
174
+ - [接手说明(0.2.0 之后)](docs/HANDOVER-2026-10-29.md)
175
+ - [0.2.1 发布检查清单](docs/RELEASE-CHECKLIST-0.2.1.md)
176
+ - [整枝移动实施计划(父会话 + 子代理后代)](docs/PLAN-2026-11-02-family-move.md)
177
+ - [0.2.0 实施计划(overview + 分页 sessions)](docs/PLAN-2026-10-29.md)
178
+ - [0.2.0 发布检查清单](docs/RELEASE-CHECKLIST-0.2.0.md)
159
179
  - [实施计划(批准时原样归档)](docs/PLAN-2026-10-26.md)
160
180
  - [0.1.0 发布检查清单](docs/RELEASE-CHECKLIST-0.1.0.md)
161
181
  - [0.1.1 实施计划](docs/PLAN-2026-10-27.md)
package/ROADMAP.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Roadmap
2
2
 
3
- > 当前:`0.1.4` 已发布(npm latest / tag `v0.1.4` / Release):详情页吸顶、结果 toast、空会话归档/清理与分批删除。市场条目已收录(PR [#9672](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/9672) 于 2026-10-27 合并)。下一项主任务是 0.2.0 的 Host 分页;详细接手任务见 [docs/HANDOVER-2026-10-27.md](docs/HANDOVER-2026-10-27.md)。
3
+ > 当前:`0.2.0` 已发布(npm latest / tag `v0.2.0` / Release,2026-10-29):Host 侧 overview + 分页 sessions(1000–10000 条会话)+ 客户端两段式加载。0.2.0 计划与验收见 [docs/PLAN-2026-10-29.md](docs/PLAN-2026-10-29.md) 与 [docs/RELEASE-CHECKLIST-0.2.0.md](docs/RELEASE-CHECKLIST-0.2.0.md)。下一项候选见本文件 Later candidates 与 [docs/HANDOVER-2026-10-29.md](docs/HANDOVER-2026-10-29.md)。
4
4
 
5
5
  ## 0.1.0 — delivered
6
6
 
@@ -40,25 +40,26 @@
40
40
  - 头部三个按钮移到会话管理标题右侧;副标题与统计信息独占下方整行。
41
41
  - 空会话:「归档空会话(N)」一键分批归档;「清理空会话(N)」只要有已归档空会话就显示;删除范围预览与删除按 `maxBatch` 分批,超过 50 条也能一次确认完成。
42
42
 
43
- ## 0.2.0 — next (planned)
43
+ ## 0.2.0 — delivered (published)
44
44
 
45
- 首要目标:真正支撑 1000–10000 条会话,不再首屏拉全量 `state`。实施前先写 `docs/PLAN-2026-10-28.md` 并获批准。
45
+ 首要目标:真正支撑 1000–10000 条会话,不再首屏拉全量 `state`。计划与实施记录见 [docs/PLAN-2026-10-29.md](docs/PLAN-2026-10-29.md)。
46
46
 
47
- - `GET /session-mng/api/overview`:只返回工作区计数/大小/归档数、totals、capabilities、orphans;不读全部标题/日志。
48
- - `GET /session-mng/api/sessions`:按 `workspaceId/tab/offset/limit/query/sort` 分页;只对当前页 id 读标题/大小;返回 `hasMore`。
49
- - 未分组会话懒加载 + 短 TTL 缓存;全局搜索先只读验证宿主 search 是否覆盖标题。
50
- - Client:overview 首屏 → 工作区展开时取第一页 → 加载更多;保留 sticky、选择裁剪、搜索自动展开。
51
- - 兼容:保留 `/state` 给 0.1.x 客户端;Host 同时提供新旧接口。
52
- - 验收:合成 10k 数据首屏不返回 session rows;单页 ≤50 行;不触发全量 `sessionController.list`;现有 26 测试 + 新增分页/overview/search 测试。
53
- - 详细接口建议、验收与坑:[docs/HANDOVER-2026-10-27.md](docs/HANDOVER-2026-10-27.md)。
47
+ - **零 IO catalog**:`lib/catalog.js` 从 `workspaceRegistry.headers` + `sessionProjectionCache` 组装行;两个内部 seam 特性检测,缺失回退 `buildState` 慢路径。
48
+ - `GET /overview`:工作区计数/归档数/空会话/totals/capabilities/orphans,无会话行;10k 合成约 9.5 ms / 1.3 KB。
49
+ - `GET /sessions`:按 `workspaceId/tab/query/sort/offset/limit` 分页(≤50 行),branch-aware 排序 + `id` tie-break + `parentStub`;10k 单页约 8.8 ms / 25 KB,不触发全量扫描。
50
+ - `GET /search` / `/session` / `/blanks` / `/sizes`:跨工作区标题搜索、详情单行、空会话 id、按工作区/全局大小(一次 `persistence.list()` + 60 s TTL,只聚合可见行)。
51
+ - Client 两段式加载:overview → 展开取页 → 加载更多;搜索防抖走宿主;选择只作用于已加载行;详情独立取数;老 Host 回退 `/state` 并保留每组 50 条本地分页。
52
+ - 兼容:`GET /state` 保留;0.1.x 客户端不受影响。
53
+ - 验收:129 测试全绿(Host 72 + 客户端 vm 57);10k 基准不调用 `persistence.list` / `sessionController.list` / 批量 `readTitleSnapshots`。实机验收与发版待执行,见 [docs/RELEASE-CHECKLIST-0.2.0.md](docs/RELEASE-CHECKLIST-0.2.0.md)。
54
54
 
55
55
  ## Later candidates
56
56
 
57
57
  - 侧栏会话「...」菜单快捷入口(生成标题 / 会话管理详情),复用同一套 Host 操作。
58
- - 内容全文搜索(复用 `sessionQuery.searchSessions` / `searchEvents`),不只按标题/路径/id。
58
+ - 内容全文搜索(本部署宿主 FTS 默认关闭且索引不含标题;接入前先确认 composition 与结果模型)。
59
+ - `(sortValue,id)` keyset 游标,替换 0.2.0 的裸 offset 分页,进一步抗数据变化。
59
60
  - 导出所选会话为 Markdown / JSON(删除前的安全网;批量)。
60
61
  - 置顶 / 取消置顶(`workspaceRegistry.pinSession` / `unpinSession`)。
61
- - 整枝移动(父会话 + 分支会话 + 子代理后代一起迁移),或在移动时保留父链接。
62
+ - ~~整枝移动(父会话 + 子代理后代一起迁移)~~ 已实现(2026-11-02,见 [docs/PLAN-2026-11-02-family-move.md](docs/PLAN-2026-11-02-family-move.md));普通分支(fork)仍按独立会话处理,不跟随。
62
63
  - 会话体检 / 修复:重复目录、幽灵归档、workspace 账本与 header cwd 不一致、损坏日志报告。
63
64
  - 可选回收站(与「彻底删除」并存,默认关闭)。
64
65
  - 移动的增量实现(rename 而不是整目录复制),大日志更快。