dsh-session-mng 0.1.1 → 0.1.3
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 +37 -0
- package/README.md +25 -6
- package/ROADMAP.md +30 -4
- package/client.js +272 -66
- package/docs/01-design.md +23 -13
- package/docs/02-open-source-and-marketplace.md +21 -0
- package/docs/HANDOVER-2026-10-27.md +133 -0
- package/docs/PLAN-2026-10-27.md +2 -0
- package/docs/PLAN-2026-10-28-branch-visibility.md +116 -0
- package/docs/PLAN-2026-10-28-legacy-fork-safety.md +62 -0
- package/docs/RELEASE-CHECKLIST-0.1.1.md +18 -5
- package/docs/RELEASE-CHECKLIST-0.1.2.md +31 -0
- package/docs/RELEASE-CHECKLIST-0.1.3.md +38 -0
- package/lib/service.js +64 -16
- package/lib/state.js +54 -9
- package/package.json +4 -3
package/docs/01-design.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# dsh-session-mng 设计与实现说明
|
|
2
2
|
|
|
3
|
-
> 对应版本 0.1.
|
|
3
|
+
> 对应版本 0.1.3,实测宿主 DSH 0.2.1-rc.3(Desktop `desktop` profile;0.2.1-rc.2 亦验证过)。本文面向代码评审与二次开发,记录可观察行为、事务边界、版本敏感点和已知限制。
|
|
4
4
|
|
|
5
5
|
## 1. 设计约束
|
|
6
6
|
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
|
|
44
44
|
| 路由 | 说明 |
|
|
45
45
|
|---|---|
|
|
46
|
-
| `GET /state?subagents=0\|1` |
|
|
46
|
+
| `GET /state?subagents=0\|1` | 总览;默认过滤子代理会话(分支会话始终返回) |
|
|
47
47
|
| `POST /preview` | 最近消息(最多 10 条) |
|
|
48
48
|
| `POST /title/propose` | 整段会话标题提案(只读) |
|
|
49
49
|
| `POST /title/apply` | 确认写入标题;live 或 cold |
|
|
50
50
|
| `POST /archive` | `{sessionIds, stopActivity?}` |
|
|
51
51
|
| `POST /unarchive` | `{sessionIds}` |
|
|
52
|
-
| `POST /delete/preview` | 删除范围预览(根 +
|
|
52
|
+
| `POST /delete/preview` | 删除范围预览(根 + 子代理后代 + 分支提示) |
|
|
53
53
|
| `POST /delete` | `{sessionIds, confirm:true}` |
|
|
54
54
|
| `POST /move` | `{sessionIds, workspaceId}` |
|
|
55
55
|
|
|
@@ -65,12 +65,20 @@
|
|
|
65
65
|
4. `sessionQuery.readTitleSnapshots(ids)`:只为缺失标题的行补读。
|
|
66
66
|
5. `archivedSessionIds` / `pinnedSessionIds`。
|
|
67
67
|
|
|
68
|
+
会话按三类打标(`kind`),这是 0.1.3 修正的核心:**不能用「有 `parentSession`」判定子会话**,因为分支会话(fork)也带 parent。
|
|
69
|
+
|
|
70
|
+
- `root`:无 parent;
|
|
71
|
+
- `fork`:非子代理且有 parent(`isSeeded:true`、`delegationDepth:0` 为辅证)。它是用户会话,默认可见、可改标题/归档/删除,但不可单独移动;
|
|
72
|
+
- `subagent`:`origin:'subagent'` 或 `delegationDepth≥1`(委派产生)。`subagents=0` 时过滤,并计入 `totals.hiddenSubagents` 供 UI 提示。
|
|
73
|
+
|
|
74
|
+
行字段:`kind` / `isFork` / `isSubagent`(兼容)/ `parentSessionId` / `parentTitle` / `parentPresent` / `forkCount`;`totals` 附带 `forks` / `hiddenSubagents`。
|
|
75
|
+
|
|
68
76
|
每个会话行带 `can`:
|
|
69
77
|
|
|
70
78
|
- `title`:有 `llm`;
|
|
71
79
|
- `archive`:未归档;
|
|
72
80
|
- `restore`:已归档;
|
|
73
|
-
- `move`:JSONL + zstd + workspace 缓存 seam 可用 + 非 live/running
|
|
81
|
+
- `move`:JSONL + zstd + workspace 缓存 seam 可用 + 非 live/running + `kind === 'root'`(分支要留在父会话工作区);
|
|
74
82
|
- `delete`:JSONL + 已归档 + 非 live;
|
|
75
83
|
- `open`:总是 true(客户端再判断 `uiWorkspace` 是否存在)。
|
|
76
84
|
|
|
@@ -110,8 +118,8 @@
|
|
|
110
118
|
1. `capabilities.move`:JSONL + zstd + `canReconcileMove(registry)`。
|
|
111
119
|
2. `stat(id)` 存在,header `cwd` 非空。
|
|
112
120
|
3. 非 live(`ctx.sessions.get(id) === undefined`);非 running。
|
|
113
|
-
4.
|
|
114
|
-
5. `traceSession(id)`
|
|
121
|
+
4. 子代理会话(`origin:'subagent'` 或 `delegationDepth≥1`)不能单独移动;普通分支(含历史 fork)是独立会话,不阻止移动。
|
|
122
|
+
5. `traceSession(id)` 无**子代理** descendants(普通分支会出现在谱系里,但不再阻止移动)。
|
|
115
123
|
6. 目标 workspace 存在且 `status() === 'ok'`;目标目录不存在。
|
|
116
124
|
7. 源目录唯一;目标目录由 `locate({id,cwd:target.path})` 推导。
|
|
117
125
|
8. `open(id,'write')` 成功后再 close,证明没有其他进程正在写。
|
|
@@ -159,19 +167,20 @@ targetDir = dirname(locate({id, cwd: target.path}))
|
|
|
159
167
|
### 9.1 预览
|
|
160
168
|
|
|
161
169
|
- 每个 root 必须已归档。
|
|
162
|
-
- `traceSession(root)` 递归收集 descendants
|
|
163
|
-
-
|
|
164
|
-
- 返回 roots、descendantCount
|
|
170
|
+
- `traceSession(root)` 递归收集 descendants,并按 header 拆成两类:**子代理**(`origin:'subagent'` / `delegationDepth≥1`,随 root 级联)与**普通分支**(历史 fork 仍带 `parentSession`)。遇到分支即停止下钻,分支的子代不随 root 删除。
|
|
171
|
+
- 每个待删 id:找目录、递归算字节、尝试 `readSession` 标记可读/损坏;分支只读标题,供「不会被删除」提示使用。
|
|
172
|
+
- 返回 roots、descendantCount(仅子代理)、sessions、forkChildren、totalBytes、errors。
|
|
165
173
|
|
|
166
174
|
### 9.2 执行
|
|
167
175
|
|
|
168
176
|
1. `confirm === true`;重新校验 root 仍已归档(防 TOCTOU)。
|
|
169
|
-
2. 重算 roots + descendants
|
|
177
|
+
2. 重算 roots + **子代理** descendants;普通分支不参与;总 id 数 > 500 拒绝。
|
|
170
178
|
3. 任一会话 live 或 running → 拒绝(live 会在内存留下幽灵行)。
|
|
171
179
|
4. 每个存在的目录 `rename` 到 `tempRoot/delete-<batch>-<id>-<rand>`;记录映射。
|
|
172
180
|
5. 清理 registry:`unarchiveSession`、所属 workspace `detachSession`、可选删除 headers/sessionPaths 缓存。
|
|
173
181
|
6. 成功 → `rm` 所有 trash 目录并验证;失败 → 把 trash 移回原位,并尽力 `attachSession` + `archiveSession` 恢复账本,返回错误。
|
|
174
182
|
7. 若最终 rm 失败 → `leftover-trash`,details 给出残留路径;不谎报成功。
|
|
183
|
+
8. 保留下来的分支 header 仍记录已删除的父 id;宿主 0.2.1-rc.3 把这类历史 fork 当独立会话,插件列表用 `parentPresent:false` 显示「来源父会话已不存在」。
|
|
175
184
|
|
|
176
185
|
## 10. 安全
|
|
177
186
|
|
|
@@ -187,16 +196,17 @@ targetDir = dirname(locate({id, cwd: target.path}))
|
|
|
187
196
|
|---|---|
|
|
188
197
|
| `test/title.test.js` | 清洗、UTF-8 截断、turn 抽取、预算收缩 |
|
|
189
198
|
| `test/store-jsonl.test.js` | header 解析、cwd 重写、后续字节不变、generation 选择、stage/rollback、删除 round-trip |
|
|
190
|
-
| `test/state.test.js` |
|
|
191
|
-
| `test/service.test.js` | 移动成功、workspace seam
|
|
199
|
+
| `test/state.test.js` | 工作区归属、归档/置顶、三态分类(根/分支/子代理)、`parentTitle`/`parentPresent`、orphans、capabilities |
|
|
200
|
+
| `test/service.test.js` | 移动成功、workspace seam 失败回滚、删除成功/拒绝、删除保留普通分支、分支不阻止移动、子代理仍阻止移动、冷标题事件形状 |
|
|
192
201
|
| `test/api.test.js` | fence、state 信封、未知 action、方法、坏 JSON、超大 body、错误码 |
|
|
193
202
|
|
|
194
|
-
`node --test`
|
|
203
|
+
`node --test` 29 个测试全绿。
|
|
195
204
|
|
|
196
205
|
## 12. 已知限制与 0.2.0 方向
|
|
197
206
|
|
|
198
207
|
- live 会话不能移动/删除(重启后重试)。
|
|
199
208
|
- 有子代理后代的会话不能单独移动(0.2.0 整枝移动)。
|
|
209
|
+
- 普通分支(含历史 fork)不随父会话删除,会失去来源标识。宿主「普通 fork 不再写 `parentSession`」的变更在 DSH 源码里已合入,但**尚未进入当前安装的 0.2.1-rc.3 构建**(2026-10-28 实测:新建 fork 仍带 `parentSession`,app.asar 里仍有旧写入代码),所以这类「历史分支」形态短期仍会持续出现;插件对两种形态一视同仁。
|
|
200
210
|
- 移动是整目录复制,大日志会慢;0.2.0 评估 rename/增量。
|
|
201
211
|
- 非 JSONL 后端不支持移动/删除。
|
|
202
212
|
- workspace 缓存 seam 是版本敏感点;升级 DSH 后先跑测试与实机验收。
|
|
@@ -118,3 +118,24 @@ curl -s https://awesome-dsh-plugin.com/plugins.json | grep -i session-mng
|
|
|
118
118
|
- [ ] PR 编号 / 合并状态 / CI 结果
|
|
119
119
|
- [ ] dshmarket 卡片截图或文本记录
|
|
120
120
|
- [ ] `docs/PLAN-2026-10-26.md` 末尾追加「事后差异(补记)」
|
|
121
|
+
|
|
122
|
+
## 7. 0.1.1 更新发布(2026-10-27)
|
|
123
|
+
|
|
124
|
+
0.1.1 是客户端可用性修复(工作区优先/分页、sticky、选择裁剪、控件视觉),Host API 未变,marketplace 条目不需要改 YAML。
|
|
125
|
+
|
|
126
|
+
- 本地提交:`cea99f9 fix: align sticky surface and enlarge list controls`(功能提交 `d36e725`)。
|
|
127
|
+
- `npm publish`:`dsh-session-mng@0.1.1`,31 个文件,tarball 560.7 kB / unpacked 767.4 kB;发布后约 90 秒 packument 出现 0.1.1,`latest` = 0.1.1,版本端点 200。
|
|
128
|
+
- Git:main 已 push;tag `v0.1.1`;GitHub Release 见仓库 Releases。
|
|
129
|
+
- marketplace:PR [#9672](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/9672) 不变;`check` 已通过,`Submission gate` 仅因仓库 0.0 天(需要 1 天)失败;该检查会自动重跑,约 24h 后转绿,不需要重新提交。
|
|
130
|
+
- Release:https://github.com/ZilongYang/dsh-session-mng/releases/tag/v0.1.1
|
|
131
|
+
|
|
132
|
+
## 8. 接手
|
|
133
|
+
|
|
134
|
+
下一步市场验证与 0.2.0 任务见 [HANDOVER-2026-10-27.md](HANDOVER-2026-10-27.md)。
|
|
135
|
+
|
|
136
|
+
## 9. 0.1.2 更新发布(2026-10-27)
|
|
137
|
+
|
|
138
|
+
- 客户端修复:空会话默认隐藏 + 清理已归档空会话 + 删除范围模态确认。
|
|
139
|
+
- `npm publish`:`dsh-session-mng@0.1.2`,33 个文件,568.3 kB / unpacked 789.1 kB;约 3 分钟后 packument 出现,`latest` = 0.1.2,版本端点 200。
|
|
140
|
+
- Git:main 已 push;tag `v0.1.2`;Release 见仓库 Releases。
|
|
141
|
+
- marketplace 条目不变;卡片版本随 npm 自动更新,PR gate 仍只差仓库满 1 天。
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# dsh-session-mng 接手说明(2026-10-27)
|
|
2
|
+
|
|
3
|
+
> 面向下一个接手的人/会话。先读这一页,再按链接进入详细文档。当前代码在 `main`,工作区干净。
|
|
4
|
+
|
|
5
|
+
## 1. 当前状态
|
|
6
|
+
|
|
7
|
+
| 项 | 值 |
|
|
8
|
+
|---|---|
|
|
9
|
+
| 版本 | `0.1.2`(npm `latest`) |
|
|
10
|
+
| npm | https://www.npmjs.com/package/dsh-session-mng |
|
|
11
|
+
| GitHub | https://github.com/ZilongYang/dsh-session-mng |
|
|
12
|
+
| Release | https://github.com/ZilongYang/dsh-session-mng/releases/tag/v0.1.2 |
|
|
13
|
+
| 当前 main | 0.1.2 代码提交 `8feaf3a`;交接后的文档提交以远端 `main` 为准 |
|
|
14
|
+
| Tag | `v0.1.2`(最新发布) |
|
|
15
|
+
| 测试 | `node --test` 26 个全绿 |
|
|
16
|
+
| 包内容 | `npm pack` 33 个文件 / 568.3 kB;unpacked 789.1 kB |
|
|
17
|
+
| 本地安装 | 已作为 symlink 安装到 Desktop `desktop` profile;改 client 后刷新页面即可,Host 改动需重启 DSH |
|
|
18
|
+
| 市场 PR | awesome-dsh-plugin [#9672](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/9672),open |
|
|
19
|
+
|
|
20
|
+
### 市场 PR 的真实状态
|
|
21
|
+
|
|
22
|
+
- 条目文件:`data/plugins/ZilongYang__dsh-session-mng.yml`,只新增 1 个文件;分支 `add-dsh-session-mng`(fork `ZilongYang/awesome-dsh-plugin`)。
|
|
23
|
+
- CI:`check` **已通过**;`Submission gate` 唯一失败项是**仓库 0.0 天,要求满 1 天**。
|
|
24
|
+
- Gate 原文:`repository is 0.0 days old (needs 1) — this check re-runs by itself and should clear in about 24h. No need to resubmit, push, or close and reopen.`
|
|
25
|
+
- 预计自动转绿:仓库创建于 `2026-10-26T16:44:42Z`,满 1 天约为 **2026-10-27T16:44Z / 2026-10-28 00:44 Asia/Shanghai**。
|
|
26
|
+
- **不要**重新提交 PR 或关闭重开;gate 自动重跑。转绿后等维护者合并。
|
|
27
|
+
- 合并后 dshmarket/awesome 目录才会出现;市场卡片读取 npm 版本,当前应显示 `0.1.1`。验证:`curl -s https://awesome-dsh-plugin.com/plugins.json | grep -i session-mng`,以及在 dshmarket 搜 `dsh-session-mng`。
|
|
28
|
+
|
|
29
|
+
## 2. 代码地图
|
|
30
|
+
|
|
31
|
+
| 文件 | 职责 / 接手要点 |
|
|
32
|
+
|---|---|
|
|
33
|
+
| `index.js` | Host 入口、inject、幂等挂载 `/session-mng/api` |
|
|
34
|
+
| `lib/api.js` | 路由、64 KiB body 上限、错误信封;**新增加分页接口从这里开始** |
|
|
35
|
+
| `lib/fence.js` | loopback / trustedHosts / Origin 围栏 |
|
|
36
|
+
| `lib/service.js` | 操作层;state / title / archive / delete / move |
|
|
37
|
+
| `lib/state.js` | 总览组装;0.2.0 的 overview/page 应从这里拆分 |
|
|
38
|
+
| `lib/title.js` | 整段会话标题、模型路由、清洗/截断 |
|
|
39
|
+
| `lib/store-jsonl.js` | header、zstd frame、目录复制/事务/回滚 |
|
|
40
|
+
| `lib/workspace-sync.js` | 移动后的 registry 缓存对账;删除后的账本清理 |
|
|
41
|
+
| `client.js` | 设置页单文件 UI;列表逻辑在 `computeView` / `SessionManagerPage` |
|
|
42
|
+
| `test/` | title / store-jsonl / state / service / api,共 26 个 |
|
|
43
|
+
|
|
44
|
+
### 0.1.1 列表逻辑(不要改坏)
|
|
45
|
+
|
|
46
|
+
- `computeView`:过滤 → 排序 → 分组 → 折叠 → 每组分页 → `visibleRows`;纯函数。
|
|
47
|
+
- 默认 `>100` 折叠;每工作区 50 条;`loadMore` 只改 `limits`,不改可见集。
|
|
48
|
+
- `viewKey` 变化(tab/工作区/搜索/展开集合/刷新)后 `selected = selected ∩ visibleIdSet`。
|
|
49
|
+
- 行 checkbox 的 `onSelect` 与工作区头 `onToggle` 必须分开;曾因此误折叠工作区。
|
|
50
|
+
- sticky 使用 `--dsw-alias-bg-layer-2`(与设置面板一致),不要改回 `bg-base` 黑色。
|
|
51
|
+
|
|
52
|
+
## 3. 下一步任务
|
|
53
|
+
|
|
54
|
+
### P0 — 等市场 gate / 合并(无代码)
|
|
55
|
+
|
|
56
|
+
1. 满 1 天后重新查看 `gh pr checks 9672 --repo awesome-dsh-plugin/awesome-dsh-plugin`。
|
|
57
|
+
2. gate 转绿后不要重复提交;等待维护者合并。
|
|
58
|
+
3. 合并后验证市场目录:`plugins.json` / dshmarket 搜索 / 卡片版本 `0.1.1` / 4 张截图 / `icon-180.png`。
|
|
59
|
+
4. 把结果回填到 `docs/02-open-source-and-marketplace.md` 第 7 节和 `docs/RELEASE-CHECKLIST-0.1.1.md` 的 E 节。
|
|
60
|
+
5. 如果维护者要求改描述/分类,只改 PR 里的那 1 个 YAML;代码仓库的发版不受影响。
|
|
61
|
+
|
|
62
|
+
### P1 — 0.2.0:Host 侧 overview + 分页 sessions(主任务)
|
|
63
|
+
|
|
64
|
+
目标:真正支撑 **1000–10000 条会话**,不再首屏拉全量 state。0.1.1 只是客户端折叠/分页,state payload 仍是全量(202 条约 103 KB;10000 条约 5 MB)。
|
|
65
|
+
|
|
66
|
+
建议(实现前先写 `docs/PLAN-2026-10-28.md` 并让子龙批准):
|
|
67
|
+
|
|
68
|
+
1. **`GET /session-mng/api/overview`**
|
|
69
|
+
- 只返回 `workspaces[]`(id/title/path/status/sessionIds.length/archivedCount/总大小)+ `totals` + `capabilities` + `orphans`。
|
|
70
|
+
- 计数优先用 `workspaceRegistry` 的内存 `sessionIds` / archived set;不要为计数读全部标题或日志。
|
|
71
|
+
- 未分组会话数量:需要一次 header 扫描;做成懒加载 + 短 TTL 缓存,不阻塞首屏。
|
|
72
|
+
2. **`GET /session-mng/api/sessions?workspaceId=&tab=&offset=&limit=&query=&sort=`**
|
|
73
|
+
- 只对当前页 id 做 `readTitleSnapshots` / `stat`;返回 `rows/total/offset/limit/hasMore`。
|
|
74
|
+
- 已归档:用 `archivedSessionIds` 过滤 workspace 账本;不要扫全量日志。
|
|
75
|
+
- 排序必须在 host 完成,保证分页稳定。
|
|
76
|
+
3. **全局搜索**
|
|
77
|
+
- 先只读验证 `sessionController.search` / `sessionQuery.searchSessions` 是否覆盖标题;不覆盖就限制为“当前工作区/已加载页标题搜索”,内容搜索走宿主索引。
|
|
78
|
+
- 搜索结果返回 id 列表后再按页补标题/大小,避免全量读标题。
|
|
79
|
+
4. **Client**
|
|
80
|
+
- `overview` 首屏 → 默认折叠;展开工作区时请求第一页;`加载更多` 请求下一页;缓存每工作区页。
|
|
81
|
+
- 保持 0.1.1 的 sticky、选择裁剪、搜索自动展开、视觉规范。
|
|
82
|
+
- 选择语义:优先保留“可见集”语义;跨页选择需要明确“已加载页”边界,避免隐藏页误操作。
|
|
83
|
+
5. **兼容**
|
|
84
|
+
- 保留 `GET /state` 给 0.1.x 客户端;Host 同时提供新旧接口,客户端 feature-detect.
|
|
85
|
+
- 版本 0.2.0;升级 README/CHANGELOG/ROADMAP;新增 `docs/RELEASE-CHECKLIST-0.2.0.md`.
|
|
86
|
+
6. **验收**
|
|
87
|
+
- 合成 10k 会话数据:首屏 overview 不带 session rows;单页 ≤50 行;不触发全量 `sessionController.list`。
|
|
88
|
+
- 现有 26 个测试 + 新增 overview/page/search/分页/空态/归档/未分组测试。
|
|
89
|
+
- 实机只读验证 202 条真实数据,再用手动合成数据验证 1000/10000;写操作仍只用一次性测试会话。
|
|
90
|
+
|
|
91
|
+
### P2 — 后续候选(不急)
|
|
92
|
+
|
|
93
|
+
侧栏会话菜单、全文搜索、导出、置顶、整枝移动、会话体检/修复、回收站、增量移动。按 `ROADMAP.md` 逐项排,不要一次全做。
|
|
94
|
+
|
|
95
|
+
## 4. 发布 / 开发命令
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
cd /Users/zilong/zWork/ai/zl-plugins/dsh-session-mng
|
|
99
|
+
|
|
100
|
+
npm test
|
|
101
|
+
node --check index.js client.js lib/*.js
|
|
102
|
+
npm --cache /tmp/dsh-npm-cache pack --dry-run
|
|
103
|
+
|
|
104
|
+
# npm 发布(0.1.x 均出现 202 + 0.0.0-stage 占位,约 90s 后 packument 出现新版本;以版本端点为准)
|
|
105
|
+
npm --cache /tmp/dsh-npm-cache publish
|
|
106
|
+
curl -s -o /dev/null -w "%{http_code}\n" https://registry.npmjs.org/dsh-session-mng/<version>
|
|
107
|
+
|
|
108
|
+
# GitHub
|
|
109
|
+
git push origin main
|
|
110
|
+
git tag v<version> && git push origin v<version>
|
|
111
|
+
gh release create v<version> --repo ZilongYang/dsh-session-mng --title "dsh-session-mng <version>" --notes-file /tmp/notes.md
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 5. 环境与坑
|
|
115
|
+
|
|
116
|
+
- DSH `0.2.1-rc.2`;Desktop `desktop` profile **由应用独占**,不要用 `dsh plugin --profile desktop …` 管理;用应用内插件管理器或 `plugin_manager`。
|
|
117
|
+
- Client 服务只能 `ctx.get('uiWorkspace')`;直接 `ctx.uiWorkspace` 在未 inject 时会抛错,且被 try/catch 吞掉会导致“恢复并打开”消失。
|
|
118
|
+
- 移动依赖 workspace registry 内部缓存 seam;已做特性检测和回滚,升级 DSH 先跑测试 + 实机验收。
|
|
119
|
+
- 移动/删除只支持本地 JSONL;live 会话拒绝移动/删除,重启后重试。
|
|
120
|
+
- 测试/截图只用一次性测试会话或 `/Users/demo/...` + `session-demo-*` 假数据;不要提交真实标题/路径/会话 id。
|
|
121
|
+
- 公开计划是脱敏版;逐字原文在 `private/raw-plans/`(gitignore,不进 npm)。
|
|
122
|
+
- 0.1.1 的 npm tarball 是在最终文档回填前打的,包内 checklist 可能显示 pending;功能/README 无影响。不值得为这个单独发 0.1.2。
|
|
123
|
+
- 0.1.2 的 npm 发布同样先返回 202,约 3 分钟后公开;tarball 33 个文件。
|
|
124
|
+
|
|
125
|
+
## 6. 关键文档
|
|
126
|
+
|
|
127
|
+
- [0.1.0 批准计划](PLAN-2026-10-26.md)
|
|
128
|
+
- [0.1.1 实施计划](PLAN-2026-10-27.md)
|
|
129
|
+
- [0.1.1 发布清单](RELEASE-CHECKLIST-0.1.1.md)
|
|
130
|
+
- [设计说明](01-design.md)
|
|
131
|
+
- [开源/市场记录](02-open-source-and-marketplace.md)
|
|
132
|
+
- [路线图](../ROADMAP.md)
|
|
133
|
+
- [变更记录](../CHANGELOG.md)
|
package/docs/PLAN-2026-10-27.md
CHANGED
|
@@ -67,3 +67,5 @@
|
|
|
67
67
|
5. **新增第 4 张截图** `screenshot-4-expanded.png`,展示工作区展开、选择 2 条活跃会话、sticky 过滤 + 批量条;市场可展示 4 张。
|
|
68
68
|
6. **实现中修了一个行选择事件绑定 bug**:Group 的行 checkbox 最初误调用工作区折叠函数(`toggleGroup`),已拆成 `onSelect` / `onToggle` 两个 prop;该 bug 只存在于工作区,未进入 0.1.0 发布。
|
|
69
69
|
7. **0.1.1 仍是客户端快修**:首屏继续拉全量 state(202 条约 103 KB;10000 条约 5 MB),真正按工作区懒加载/分页在 0.2.0 做。这一点在验收时明确,不把 0.1.1 当成 10000 条的解决方案。
|
|
70
|
+
|
|
71
|
+
8. **发布结果(2026-10-27)**:0.1.1 已发布;npm `latest` = 0.1.1(31 文件,560.7 kB),GitHub main / tag `v0.1.1` / Release 已更新;marketplace 条目不变,版本随 npm 自动更新。
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# 计划:分支会话(fork)默认可见 + 三态会话模型
|
|
2
|
+
|
|
3
|
+
> 提出:2026-10-28 · 批准:2026-10-28 · 对应版本:0.1.3
|
|
4
|
+
> 本文按批准内容原样归档;实施完成后差异另起一节补记(见文末)。
|
|
5
|
+
|
|
6
|
+
## 1. 问题
|
|
7
|
+
|
|
8
|
+
截图(2026-10-28,DSH 0.2.1-rc.2):
|
|
9
|
+
|
|
10
|
+
- 左侧工作区 `dsh-ml-input` 下有 2 条会话:`DSH 多行输入插件开发`(父,14 小时)和 `DSH 多行输入插件开发 (1)`(分支,2 小时)。
|
|
11
|
+
- 设置页「会话管理」的同一工作区只有 **1 个会话**,分支被隐藏;页面上「显示子会话」默认未勾选。
|
|
12
|
+
|
|
13
|
+
## 2. 根因
|
|
14
|
+
|
|
15
|
+
`lib/state.js` 只有一条二元判断:
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
function isSubagent(header, summary) {
|
|
19
|
+
if (header?.origin === 'subagent' || summary?.origin === 'subagent') return true
|
|
20
|
+
return Boolean(header?.parentSession ?? summary?.parentSessionId) // 有父就算子会话
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`buildState` 在 `includeSubagents=false`(默认)时直接丢弃这些行。
|
|
25
|
+
|
|
26
|
+
扫描 `~/.dsh/sessions` 全部 304 个会话 header:
|
|
27
|
+
|
|
28
|
+
| header 特征 | 数量 | 语义 |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| 无 origin / 无 parent / `isSeeded:false` | 165 | 普通根会话 |
|
|
31
|
+
| `origin:'subagent'` / `delegationDepth:1` / 有 parent | 137 | 子代理(委派,内部) |
|
|
32
|
+
| `isSeeded:true` / `delegationDepth:0` / 有 parent / 无 origin | 1 | **用户分支会话** |
|
|
33
|
+
| `isSeeded:true` / 无 parent | 1 | 无父种子会话 |
|
|
34
|
+
|
|
35
|
+
实测落盘的分支是 `session-a9fdeaf7…`(2026-10-28 14:04 从 `session-aa896e13…` 分出)。线上 API 返回 `{"origin":null,"parentSessionId":"session-aa896e13…","isSubagent":true}` —— 即只要挂 parent 就被当成子代理。
|
|
36
|
+
|
|
37
|
+
DSH 自身的语义:分支是挂在父会话下、标题带 `(1)` 后缀的**一等用户会话**(可继续对话、改标题、归档);子代理不进入侧栏。插件把两者混为一类,属于判错。
|
|
38
|
+
|
|
39
|
+
## 3. 决策
|
|
40
|
+
|
|
41
|
+
- **方案 B(三态 + 树形缩进 + 隐藏提示)**:修分类 + 分支默认显示并缩进挂在父行下 + 子代理仍默认隐藏但给出「已隐藏 N 个」提示。
|
|
42
|
+
- **分支会话暂不允许移动**:父会话留在原工作区时,分支跨区会让侧栏层级散架。
|
|
43
|
+
|
|
44
|
+
## 4. 设计
|
|
45
|
+
|
|
46
|
+
### 4.1 三态模型
|
|
47
|
+
|
|
48
|
+
| kind | 判定 | 默认可见 | 徽标 | 可管理动作 |
|
|
49
|
+
|---|---|---|---|---|
|
|
50
|
+
| `root` | 无 parent | 是 | — | 标题 / 归档 / 恢复 / 删除 / 移动 |
|
|
51
|
+
| `fork` | 非子代理且有 parent(`isSeeded:true` 为辅证) | **是** | 「分支」+ 父行「N 分支」计数 | 标题 / 归档 / 恢复 / 删除;**不可移动** |
|
|
52
|
+
| `subagent` | `origin:'subagent'` 或 `delegationDepth≥1` | 否(开关 + 「已隐藏 N 个子代理会话」提示) | 「子代理」 | 查看为主;删除随父级联 |
|
|
53
|
+
|
|
54
|
+
向后兼容:保留 `isSubagent` 字段(= kind==='subagent'),新增 `isFork`、`kind`、`parentTitle`、`totals.hiddenSubagents`、`totals.forks`。
|
|
55
|
+
|
|
56
|
+
### 4.2 列表呈现
|
|
57
|
+
|
|
58
|
+
- 同一工作区内,分支行**缩进**(每层 18px)紧跟父行;父行徽标区显示「N 分支」。
|
|
59
|
+
- 分支行标题前加 `↳`,副行显示「↳ 来自:父标题 · cwd · id」。
|
|
60
|
+
- 搜索命中父标题时,对应分支也命中。
|
|
61
|
+
- 详情页:分支徽标 + 「父会话」元数据行。
|
|
62
|
+
- 工具栏开关改名「显示子代理会话」;总览行在隐藏时提示「已隐藏 N 个子代理会话」。
|
|
63
|
+
- 移动不可用提示按原因区分:live / 子代理 / 分支 / 有后代。
|
|
64
|
+
|
|
65
|
+
### 4.3 删除
|
|
66
|
+
|
|
67
|
+
删除预览已列出根 + 子代理后代;本计划附带提示:若被删会话存在分支子项,预览里单独提示「分支会话不会随父删除,但会失去来源标识」。
|
|
68
|
+
|
|
69
|
+
## 5. 改动清单
|
|
70
|
+
|
|
71
|
+
| 文件 | 改动 |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `lib/state.js` | `classifyKind` 三态、`parentTitle` 回填、`totals.hiddenSubagents/forks`、`can.move` 仅 root |
|
|
74
|
+
| `lib/service.js` | 删除预览附带分支引用(可选);移动前置校验保持 |
|
|
75
|
+
| `client.js` | 块内父子排序、缩进 + 分支徽标、搜索含父标题、开关文案、隐藏提示、移动提示、详情页父会话行 |
|
|
76
|
+
| `test/state.test.js` | fork 用例:默认可见 / 可管理 / parentTitle / 不可移动;子代理隐藏计数 |
|
|
77
|
+
| `README.md` | 功能列表、已知限制 |
|
|
78
|
+
| `CHANGELOG.md` | 0.1.3 |
|
|
79
|
+
| `ROADMAP.md` | 0.1.3 delivered、后续候选整理 |
|
|
80
|
+
| `package.json` | 0.1.3 |
|
|
81
|
+
| `docs/RELEASE-CHECKLIST-0.1.3.md` | 发布检查清单 |
|
|
82
|
+
|
|
83
|
+
## 6. 验收
|
|
84
|
+
|
|
85
|
+
1. `npm test` 全绿(含新增 fork 用例)。
|
|
86
|
+
2. 用 `~/.dsh` 真实数据构建 state:`dsh-ml-input` 分组从 1 条变 2 条,分支默认出现且 `isFork:true`、`parentTitle:'DSH 多行输入插件开发'`。
|
|
87
|
+
3. GUI 刷新后:分支缩进显示、父行显示「1 分支」、总览行出现「已隐藏 N 个子代理会话」、勾选开关后子代理出现。
|
|
88
|
+
4. 搜索父标题能找到分支;分支行 `can.move=false` 且提示为分支原因。
|
|
89
|
+
5. 存量数据不需要迁移。
|
|
90
|
+
|
|
91
|
+
## 7. 不在本次范围
|
|
92
|
+
|
|
93
|
+
- 子树折叠三角、只看主会话视图(方案 C,后续版本)。
|
|
94
|
+
- 分支会话移动、「父 + 分支」整枝移动。
|
|
95
|
+
- 0.2.0 的 Host 分页(另有计划)。
|
|
96
|
+
|
|
97
|
+
## 8. 实施差异(事后补记,2026-10-28)
|
|
98
|
+
|
|
99
|
+
计划外的实现细节:
|
|
100
|
+
|
|
101
|
+
1. 状态行新增 `forkCount`(父行徽标「N 分支」),原计划打算只在客户端算。
|
|
102
|
+
2. 删除预览实际实现了 `forkChildren`(原计划里标为「可选」)。
|
|
103
|
+
3. `can.move` 直接写成 `row.kind === 'root'`(与「非子代理且无 parent」等价,读起来更直白)。
|
|
104
|
+
4. 分支缩进深度由客户端 `orderBranchRows()` 计算(`branchDepth`),分支徽标用 `brand` 色调,`↳` 字形放在标题前。
|
|
105
|
+
|
|
106
|
+
与原计划的差异:
|
|
107
|
+
|
|
108
|
+
- 计划文件名加了 `-branch-visibility` 后缀:ROADMAP 里已把 `docs/PLAN-2026-10-28.md` 预留给 0.2.0 的 Host 分页计划,避免撞名。
|
|
109
|
+
- 方案 C 的子树折叠、只看主会话视图按约定未做。
|
|
110
|
+
|
|
111
|
+
验证记录:
|
|
112
|
+
|
|
113
|
+
- `npm test` 26/26 通过;`node --check index.js client.js lib/*.js test/*.js` 全部通过。
|
|
114
|
+
- 真实数据冒烟(`~/.dsh/sessions` 304 个日志 header + 临时 ctx 调 `buildState`):`totals {all:167, hiddenSubagents:137, forks:1}`;`dsh-ml-input` 的分支 `session-a9fdeaf7…` 判定为 `kind:'fork'`、`parentTitle:'DSH 多行输入插件开发'`,父行 `forkCount:1`。
|
|
115
|
+
- GUI 实机验收待重载 Desktop 后进行(见 `docs/RELEASE-CHECKLIST-0.1.3.md` B 节)。
|
|
116
|
+
- 版本 0.1.3,未发布。
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 计划:历史分支(legacy fork)的删除与移动安全
|
|
2
|
+
|
|
3
|
+
> 提出:2026-10-28 · 批准:2026-10-28 · 归入 0.1.3(未发布)
|
|
4
|
+
> 本文按批准内容原样归档;实施完成后差异另起一节补记。
|
|
5
|
+
|
|
6
|
+
## 1. 背景
|
|
7
|
+
|
|
8
|
+
0.1.3 修复了「分支默认可见」,但删除/移动仍按宿主的 `sessionQuery.traceSession` 收集后代。宿主 0.2.1-rc.3 已把**新建** fork 改为独立会话(不写 `parentSession`),而**历史 fork**(rc.2 及更早创建,header 保留 `parentSession`)在 `traceSession` 里仍算父会话的 descendant。
|
|
9
|
+
|
|
10
|
+
实测(宿主同版本代码):
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
traceSession([p, fork1(parent=p), sub1(parent=p), grand(parent=fork1)], 'p')
|
|
14
|
+
→ descendants: [fork1 → [grand], sub1]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
插件现有行为因此有两个问题:
|
|
18
|
+
|
|
19
|
+
1. `POST /delete` 会**级联删除历史分支**,且不要求分支已归档,也不单独确认;`POST /delete/preview` 把它标成「子代理会话」。
|
|
20
|
+
2. `POST /move` 只要父会话有历史分支就 `has-descendants` 拒绝,属于误拦。
|
|
21
|
+
|
|
22
|
+
当前库里有 4 条历史分支(1 条 v4 + 3 条 v0 老格式,内容都是真实用户对话)。
|
|
23
|
+
|
|
24
|
+
## 2. 决策
|
|
25
|
+
|
|
26
|
+
- **删除:不级联历史分支。** 只级联 `origin:'subagent'` / `delegationDepth≥1` 的后代;历史分支保留,预览单独提示「不会被删除,但会失去来源标识;如需一起删请勾选」。
|
|
27
|
+
- **移动:解除误拦。** 只有子代理后代阻止移动;历史分支不再阻止,并在详情页提示「分支会留在原工作区」。
|
|
28
|
+
- 历史分支的父 id 悬空可以接受:rc.3 宿主把这类会话当独立根会话,打开/改名/归档不受影响;插件面板对这类行显示「来源父会话已不存在」。
|
|
29
|
+
|
|
30
|
+
## 3. 实现
|
|
31
|
+
|
|
32
|
+
| 文件 | 改动 |
|
|
33
|
+
|---|---|
|
|
34
|
+
| `lib/state.js` | 抽出并导出 `classifySession(fields)`;行上增加 `parentPresent`(父行是否在本列表) |
|
|
35
|
+
| `lib/service.js` | `descendantsOf()` 改为返回 `{ subagents, forks }`(遇到 fork 停止下钻);`delete/preview` 只列出根 + 子代理,`forkChildren` 由谱系直接得出(排除同批被选中的分支);`remove()` 只删根 + 子代理;`moveOne()` 只按子代理后代判断 |
|
|
36
|
+
| `client.js` | 删除预览:分支保留提示 + 子代理计数;分支行/详情:父会话缺失提示;移动详情:有分支时的说明 |
|
|
37
|
+
| 测试 | `test/service.test.js` 覆盖「预览不列分支」「删除不删分支目录」「移动不被分支阻止」;`test/state.test.js` 覆盖 `parentPresent` |
|
|
38
|
+
| 文档 | CHANGELOG 0.1.3、README、ROADMAP、`docs/01-design.md`、`docs/RELEASE-CHECKLIST-0.1.3.md` |
|
|
39
|
+
|
|
40
|
+
## 4. 验收
|
|
41
|
+
|
|
42
|
+
1. `npm test` 全绿。
|
|
43
|
+
2. 用假 ctx:`delete/preview` 返回的 `sessions` 不含历史分支、`forkChildren` 含它;`remove` 只删根 + 子代理目录,分支目录仍在。
|
|
44
|
+
3. 真实数据只读核对:4 条历史分支仍出现在列表,`parentPresent` 正确。
|
|
45
|
+
4. GUI 删除预览里出现「历史分支不会被删除」提示;父会话有分支时移动不再报 `has-descendants`。
|
|
46
|
+
|
|
47
|
+
## 5. 不在本次范围
|
|
48
|
+
|
|
49
|
+
- 给历史分支补写/清理 `parentSession`(不在插件侧改 header)。
|
|
50
|
+
- 「父 + 分支」整枝迁移(ROADMAP Later)。
|
|
51
|
+
- 宿主 `traceSession` 的谱系语义(属于 DSH,不在插件范围)。
|
|
52
|
+
|
|
53
|
+
## 6. 实施差异(事后补记,2026-10-28)
|
|
54
|
+
|
|
55
|
+
- `lib/state.js` 导出 `classifySession(fields)`,listing / delete / move 共用同一分类,避免三处各写一套 `origin/parentSession` 判断。
|
|
56
|
+
- 删除预览的 `forkChildren` 改为从同一次谱系遍历得到(原计划写的是沿用语料扫描),同批被勾选的分支不会重复出现在「保留」提示里。
|
|
57
|
+
- 行字段新增 `parentPresent`(父行是否还在本列表),客户端据此显示「来源父会话已不存在」;这是原计划「显示父缺失」的具体落点。
|
|
58
|
+
- 移动详情在 `movable && forkCount>0` 时多一条提示,说明分支留在原工作区;原计划只写了「解除误拦」。
|
|
59
|
+
- 测试从 26 个增加到 29 个;另跑了客户端无头渲染冒烟覆盖列表缩进、父缺失、移动提示与删除预览文案。
|
|
60
|
+
- 真实数据核对:当前库 4 条历史分支(`a9fdeaf7…`、`675ca5a4…`、`b9b7923d…`、`session-1`),第 2~4 条是 v0 老格式(`seedLength`、无 `isSeeded`),分类仍正确。
|
|
61
|
+
- 更正(2026-10-28 晚):本文第 1 节称「rc.3 已把新建 fork 改为独立会话」**不适用于当前安装的 0.2.1-rc.3 构建**。实测该构建的 app.asar 仍含 `parentSession: source.header.id` 写入路径,今天 17:42 新建的 fork 也带 `parentSession`;「独立 fork」变更只在 DSH 源码(master)里。因此「历史分支」形态仍会继续产生,本计划的保留/移动策略是长期需要,而非一次性兼容。
|
|
62
|
+
- 兼容声明按批准更新为 `0.2.1-rc.2` + `0.2.1-rc.3` 均 compatible。
|
|
@@ -35,8 +35,21 @@
|
|
|
35
35
|
|
|
36
36
|
## D. 发布
|
|
37
37
|
|
|
38
|
-
- [x] `npm --cache /tmp/dsh-npm-cache pack --dry-run`:31 个文件 / 560.8 kB / unpacked
|
|
39
|
-
- [
|
|
40
|
-
- [
|
|
41
|
-
- [
|
|
42
|
-
- [
|
|
38
|
+
- [x] `npm --cache /tmp/dsh-npm-cache pack --dry-run`:31 个文件 / 560.8 kB;npm 发布实际 tarball 560.7 kB / unpacked 767.4 kB;包含 4 张截图。
|
|
39
|
+
- [x] `npm publish` 0.1.1(`+ dsh-session-mng@0.1.1`);版本端点 HTTP 200,`latest` = 0.1.1,`dist.fileCount` = 31。发布后约 90 秒 packument 才出现 0.1.1(与 0.1.0 相同的 staged 处理)。
|
|
40
|
+
- [x] Git commit `cea99f9` + push main + tag `v0.1.1` + GitHub Release(https://github.com/ZilongYang/dsh-session-mng/releases/tag/v0.1.1)。
|
|
41
|
+
- [x] 确认 npm `latest` = 0.1.1;marketplace 条目无需改 YAML,市场卡片版本随 npm 自动更新。
|
|
42
|
+
- [x] 在 `docs/02-open-source-and-marketplace.md` 记录 0.1.1 发布结果。
|
|
43
|
+
|
|
44
|
+
## E. 市场收录(进行中)
|
|
45
|
+
|
|
46
|
+
- [x] PR [#9672](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin/pull/9672) 已提交,只新增 1 个 YAML;条目不需要随 0.1.1 改。
|
|
47
|
+
- [x] `check` 已通过。
|
|
48
|
+
- [ ] `Submission gate`:当前仅因仓库 0.0 天(需要 1 天)失败;约 2026-10-28 00:44 Asia/Shanghai 自动重跑,不要重新提交/关闭重开。
|
|
49
|
+
- [ ] gate 转绿后等待维护者合并。
|
|
50
|
+
- [ ] 合并后验证 `plugins.json` / dshmarket 搜索、卡片版本 `0.1.1`、4 张截图、icon。
|
|
51
|
+
- [ ] 结果回填 `docs/02-open-source-and-marketplace.md` 与本节。
|
|
52
|
+
|
|
53
|
+
## F. 接手
|
|
54
|
+
|
|
55
|
+
完整接手说明、0.2.0 任务、环境坑见 [HANDOVER-2026-10-27.md](HANDOVER-2026-10-27.md)。
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# dsh-session-mng 0.1.2 发布检查清单
|
|
2
|
+
|
|
3
|
+
> 记录时间:2026-10-27。0.1.2 是空会话清理 + 删除范围弹窗的客户端修复;Host API 未变。**当前未发布**,等子龙实机测试后再执行 npm/GitHub。
|
|
4
|
+
|
|
5
|
+
## A. 实现
|
|
6
|
+
|
|
7
|
+
- [x] 默认隐藏 `blank: true` 的空会话;新增「显示空会话」开关。
|
|
8
|
+
- [x] 全部/活跃/已归档 tab 计数与隐藏空会话后的可见列表一致。
|
|
9
|
+
- [x] 总览行显示「已隐藏 N 个空会话」;显示空会话时才显示“未归档空会话需先归档”提示。
|
|
10
|
+
- [x] 头部新增「清理空会话(N)」:只收集 `blank && archived && can.delete` 的会话,打开删除范围预览;未归档空会话不混入。
|
|
11
|
+
- [x] 删除范围确认改为模态:内容区独立滚动、底部勾选/确认/取消固定;支持遮罩点击与 Esc 取消。
|
|
12
|
+
- [x] 单条详情里的删除范围与批量删除共用同一模态。
|
|
13
|
+
|
|
14
|
+
## B. 验证
|
|
15
|
+
|
|
16
|
+
- [x] `node --check client.js`。
|
|
17
|
+
- [x] `node --test` 26 个测试全绿(Host/标题/移动/删除未改)。
|
|
18
|
+
- [x] React render smoke(4 条假会话、2 条空白归档):
|
|
19
|
+
- 默认只渲染 2 条非空会话;tab 全部/活跃/已归档 = 2/2/0;`清理空会话` 按钮存在。
|
|
20
|
+
- 打开清理 → `.dsm-scope-overlay` / `.dsm-scope-dialog` / `.dsm-scope-foot` 存在;确认按钮 disabled;取消后弹窗消失。
|
|
21
|
+
- 勾选「显示空会话」→ 行数 4;再取消。
|
|
22
|
+
- [x] 子龙实机测试通过:默认隐藏、显示空会话、清理空会话、删除范围弹窗滚动时底部按钮可见。
|
|
23
|
+
- [ ] 若确认文案/按钮位置需要微调,再改一轮。
|
|
24
|
+
|
|
25
|
+
## C. 发布(已完成)
|
|
26
|
+
|
|
27
|
+
- [x] `npm pack`:33 个文件 / 568.3 kB,unpacked 789.1 kB。
|
|
28
|
+
- [x] `npm publish` 0.1.2;版本端点 HTTP 200,`latest` = 0.1.2,`dist.fileCount` = 33(发布后约 3 分钟公开)。
|
|
29
|
+
- [x] Git commit / push / tag `v0.1.2` / GitHub Release(见仓库 Releases)。
|
|
30
|
+
- [x] 市场条目不需要改 YAML;版本随 npm 自动更新。
|
|
31
|
+
- [x] 更新 `CHANGELOG` 的 unreleased 标记、README 当前状态、ROADMAP、`docs/HANDOVER-2026-10-27.md`。
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# dsh-session-mng 0.1.3 发布检查清单
|
|
2
|
+
|
|
3
|
+
> 记录时间:2026-10-28。0.1.3 修复「分支会话被误判成子会话并默认隐藏」,并修正历史分支在删除/移动上的安全问题;Host 增加分类字段与计数,Client 增加缩进/徽标/提示。
|
|
4
|
+
|
|
5
|
+
## A. 实现
|
|
6
|
+
|
|
7
|
+
- [x] `lib/state.js`:三态分类 `root` / `fork` / `subagent`;分支不再因 `parentSession` 被隐藏。
|
|
8
|
+
- [x] `lib/state.js`:行新增 `kind` / `isFork` / `parentTitle` / `forkCount`;`totals` 新增 `forks` / `hiddenSubagents`;`isSubagent` 保留兼容。
|
|
9
|
+
- [x] `lib/state.js`:`can.move` 改为仅 `root` 可移动。
|
|
10
|
+
- [x] `lib/service.js`:`descendantsOf()` 拆成子代理 / 普通分支;`delete` 只级联子代理,普通分支保留;`move` 只被子代理阻止。
|
|
11
|
+
- [x] `lib/service.js`:`delete/preview` 的 `forkChildren` 改由谱系直接得出(同批勾选的分支不重复提示)。
|
|
12
|
+
- [x] `lib/state.js`:导出 `classifySession()` 供 service 复用;行新增 `parentPresent`。
|
|
13
|
+
- [x] `client.js`:同一工作区内分支缩进挂在父行下方,父行显示「N 分支」,分支行显示「↳ 来自:父标题」。
|
|
14
|
+
- [x] `client.js`:搜索命中父标题时返回分支;总览行显示「已隐藏 N 个子代理会话」;开关改名「显示子代理会话」。
|
|
15
|
+
- [x] `client.js`:移动不可用提示区分 live / 分支 / 子代理 / 有后代;移动有分支的父会话时提示「分支留在原工作区」。
|
|
16
|
+
- [x] `client.js`:详情页显示分支徽标与「父会话」元数据行;来源父会话已删除时显示「来源父会话已不存在」。
|
|
17
|
+
- [x] `package.json` 兼容声明:`0.2.1-rc.2` + `0.2.1-rc.3` 均 `compatible`。
|
|
18
|
+
- [x] 中英双语文案同步。
|
|
19
|
+
|
|
20
|
+
## B. 验证
|
|
21
|
+
|
|
22
|
+
- [x] `node --check index.js client.js lib/*.js test/*.js` 全部通过。
|
|
23
|
+
- [x] `npm test`:29 个测试全绿(fork 默认可见/`parentTitle`/`parentPresent`/`forkCount`/隐藏计数;删除级联子代理但保留普通分支;普通分支不阻止移动;子代理仍阻止移动)。
|
|
24
|
+
- [x] 真实数据冒烟(当时 `~/.dsh/sessions` 全量 420 个日志 header + 临时 ctx):库中 4 条历史分支(1 条 v4、3 条 v0 老格式);`dsh-ml-input` 的分支 `session-a9fdeaf7…` 判定 `kind:'fork'`、`parentTitle` 正确、父行 `forkCount:1`。(该分支随后在实机测试中被删除,见下条。)
|
|
25
|
+
- [x] 客户端无头渲染冒烟(最小 React shim + 假 state):
|
|
26
|
+
- 列表:分支缩进 18px、徽标「分支」、副行「↳ 来自:父标题」;父行「1 分支」;空会话默认隐藏;总览「已隐藏 N 个子代理会话」;勾选开关后以 `subagents=1` 重拉并显示子代理行。
|
|
27
|
+
- 详情:分支行显示「父会话」;来源父会话被删时行内显示「来源父会话已不存在」;父会话移动卡片提示「移动只迁移本会话,分支留在原工作区」。
|
|
28
|
+
- 删除预览:弹窗出现「N 个历史分支会话不会被删除…如需一起删除,请把它们也勾选进来」。
|
|
29
|
+
- [x] 现场旁证(应用已重载新 Host 代码,API 返回 `parentPresent`):`dsh-ml-input` 里父分支 `session-a9fdeaf7…` 已从列表消失,其分支 `session-64daeaa4…`(17:42 fork 出,标题「DSH 多行输入插件开发 (3)」)仍在,`parentPresent:false`、`parentTitle:''` —— 父被删后分支没有跟着消失。具体是否走插件删除流程待子龙确认。
|
|
30
|
+
- [ ] 子龙实机复核完整流程(重启/重载 Desktop 后):工作区从 1 条变 2 条,分支缩进在父会话下;勾选开关后子代理出现;搜索父标题命中分支;删除父会话的预览里出现分支保留提示;父会话移动不再报 `has-descendants`。
|
|
31
|
+
- [ ] 若缩进/徽标观感需要微调,再改一轮。
|
|
32
|
+
|
|
33
|
+
## C. 发布
|
|
34
|
+
|
|
35
|
+
- [ ] `npm --cache /tmp/dsh-npm-cache --logs-dir /tmp/dsh-npm-logs pack --dry-run` 检查文件清单。
|
|
36
|
+
- [ ] `npm publish` 0.1.3;确认版本端点 `latest` = 0.1.3。
|
|
37
|
+
- [ ] Git commit / push / tag `v0.1.3` / GitHub Release。
|
|
38
|
+
- [ ] 更新 CHANGELOG 的发布标记、README 当前状态、ROADMAP。
|