dsh-tree-task-flow 0.3.14 → 0.3.15

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/README.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # dsh-tree-task-flow · 树形任务流
2
2
 
3
- 给 DeepSeek Harness 的**树形任务流**:把一件需要多步做完的事组织成
4
- **目标 → 任务 → 子任务**三级树,每个节点完成时由模型提交结果,插件随即把这个节点的
5
- **执行过程**从上下文里折叠掉,只留下那条结果。
3
+ 给 DeepSeek Harness 的**上下文管理**插件:把用户在这个会话里提的要求记成**需求**,
4
+ 需求下面挂**任务**与**步骤**;**完成[步骤/任务/需求]并折叠过程**——模型提交结果,
5
+ 插件随即把这段执行过程从上下文里折叠掉,只留下那条结果。
6
+
7
+ **这不是项目管理。** 需求记录的是"用户在这个会话里要什么",不是"项目长什么样"——
8
+ 一条需求可以对应毫无关联的目录,需求列表也不跨会话。模型定义见
9
+ [`docs/09-需求与任务模型.md`](docs/09-需求与任务模型.md)。
6
10
 
7
11
  **安装即启用**:`dsh plugin add` 之后就生效,不需要再改任何配置。
8
12
  不想用的时候,在 profile 里写一句 `enabled: false` 就能关掉,关掉后一个字节都不碰会话。
@@ -19,37 +23,41 @@
19
23
 
20
24
  | | 内容 | 去向 |
21
25
  |---|---|---|
22
- | 过程 | 读文件、试错、命令输出 | 节点完成时**整段折叠掉** |
26
+ | 过程 | 读文件、试错、命令输出、以及**已经写进需求的用户输入** | 节点完成时**整段折叠掉** |
23
27
  | 结果 | 模型在 `tree_task_done` 里提交的 `result` | 留下来,供后续节点引用 |
28
+ | 笔记 | 跟工作有关、但不属于任何一条需求的事实与偏好 | 跟会话走,折叠时随通告带出去 |
24
29
 
25
30
  ## 折叠按什么切
26
31
 
27
- 规则只有一条,**只看表层,与计划树无关**:
32
+ 规则只看表层,与计划树无关(计划树只用来认出"这次完成的是不是一条需求"):
28
33
 
29
34
  ```
30
- 从「上一次 tree_task_done 之后的第一条 tree_task_create 调用」之后
31
- → 到本次 tree_task_done 之前,这一段收走
35
+ tree_task_start → 收「上一次折叠成功之后」到这次调用之前
36
+ tree_task_done → 收「上一个 done 或 start 之后」到这次调用之前(尚未 start 时退到 create)
37
+ done 完成的是需求 → 收「这条需求开工那次 create 之后」到这次调用之前(全部)
32
38
  ```
33
39
 
34
- 起点是上一次 `tree_task_done` 之后的**第一条** `tree_task_create`;
35
- 会话里还没有过 `tree_task_done` 时,就是表层第一条 `tree_task_create`;
36
- 区间里一次 `tree_task_create` 都没有时,回退到上一次 `tree_task_done` 之后。
40
+ 边界只有三个**工具名**:`create` / `start` / `done`,按名字认、不看实参。
37
41
  **`tree_task_plan` 不是边界**——它的调用与返回跟普通过程一样,随这一段一起收走。
38
- 起点那次 `create` 的调用与返回留在上下文里,本次 `tree_task_done` 的调用与返回
39
- 同样留着(模型靠它们看"计划是什么、下一步干什么")。
42
+ 边界调用本身留在上下文里;触发这一次的 `done` / `start` 的调用与返回同样留着。
40
43
  折叠只收它们**之间**的过程,换成一条计数通告:
41
44
 
42
45
  ```
43
- [tree_task_create 调用] [返回:计划已建立 + 这个目标的树]
44
- [tree_task消息:隐藏了 12 条过程上下文。读取:… 写入:…]
45
- [tree_task_done 调用] [返回:接下来需要进行步骤:「二」(s-4)。]
46
+ [tree_task_create 调用] [返回:草稿编号]
47
+ [tree_task_start 调用] [返回:需求详情]
48
+ [tree_task消息:隐藏了 4 条过程上下文。读取:… 写入:…]
49
+ [tree_task_done 调用] [返回:接下来需要进行任务:「二」(t-4)。]
46
50
  ```
47
51
 
48
- > **`tree_task_create` 与 `tree_task_plan` 不能合并成一个工具。**
49
- > 起点取的是"上一次 `done` 之后最早的**开工**那一次",而 `plan` 每补一次步骤就调一次;
50
- > 并成一个工具之后,每次补步骤都会把起点往后推,`done` 与它之间那段过程就永远收不走。
51
- > 靠"实参里有没有 `parentId`"去区分,也只是把认错起点的机会交给模型。
52
- > 代价是两个工具的实参形状有点像,所以 `plan` 的说明里专门写了一句"建新目标不归它管"。
52
+ **为什么 `start` 认「上次折叠成功」而不是「上一个边界」**:折叠会被"用户的话还没写进
53
+ 需求"挡住;挡掉的那一段如果只按边界算,下一条边界一出现它就永远落在区间外——挡一次
54
+ 就永久丢一段上下文。插件给每个会话记一个"折到哪儿了"的游标,`start` 从那里补折。
55
+ `done` 反过来只认上一个边界:它收的就是前面这一小节,用游标会把早就收过的内容再卷一遍。
56
+
57
+ > **`tree_task_create` / `tree_task_start` / `tree_task_done` 不能合并成一个工具。**
58
+ > 边界是"上一次调用之后"这种位置判定,而 `plan` 每补一次步骤就调一次;并成一个工具之后,
59
+ > 每次补步骤都会把边界往后推,中间那段过程就永远收不走。靠"实参里有没有 `parentId`"
60
+ > 去区分,也只是把认错边界的机会交给模型——写漏一个字段,边界就悄悄挪走,还不报错。
53
61
 
54
62
  两条硬约束:
55
63
 
@@ -59,7 +67,8 @@
59
67
  不追加、不留空消息。
60
68
 
61
69
  每一次 `tree_task_done` 的调用与它的返回都**留在上下文里**,一轮轮累积;
62
- 模型下一轮还看得到"我刚做完了什么、接下来干什么"。
70
+ 模型下一轮还看得到"我刚做完了什么、接下来干什么"。`tree_task_start` 的调用与返回
71
+ 也留着——它的返回就是需求详情,是"这条需求要做什么"的最近一份摘要。
63
72
 
64
73
  折叠发生在 `agent/pre-step`——上一轮已结束、下一个请求还没构造的那一刻。
65
74
  工具执行中途不能折叠,那时 surface 还在增长,替换会把自己卷进去。
@@ -105,58 +114,59 @@ tree_task消息:接下来需要进行步骤:「步骤二」(s-4)。
105
114
  但插件**不会拦住任何工具**——"这一层到底做完了没有"由模型判断,插件既不替它定死,
106
115
  也不靠拒绝别的工具把它逼到墙角。
107
116
 
108
- ## 七个工具
117
+ ## 十个工具
109
118
 
110
- **写树分两个工具,不是可以合并的重复。** `tree_task_create` 与 `tree_task_done` 是折叠的
111
- 两个边界:`create` 是"开工"那一下,`done` 是"收工"那一下。`create` 只在新建目标时调一次,
112
- `plan` 却在任务中途反复调用——并成一个工具,折叠起点就只能靠实参去猜了(见上一节)。
119
+ **边界必须各有专门的名字,不是可以合并的重复。** `tree_task_create` / `tree_task_start` /
120
+ `tree_task_done` 是任务流的三个位置标记:`create` 是"记下这件事"(本身不折叠任何东西),
121
+ `start` 是"开工"(收走上一次 `done` 之后的过程),`done` 是"收工"(折叠就发生在这里)。
122
+ 它们各自只在特定时刻调一次,`plan` 却在任务中途反复调用——并成一个工具,
123
+ 折叠边界就只能靠实参去猜了(见上一节)。
113
124
 
114
125
  | 工具 | 用途 |
115
126
  |---|---|
116
- | `tree_task_status` | 查看计划树:默认只展开**还没结束**的目标,已完成的目标只留目标那一行;填 `id` 就返回那个目标(或该节点所在目标)的完整树 |
117
- | `tree_task_create` | 新建一个目标:这个目标 + 它下面的若干任务。可多次调用,多个目标并存,不替换已有计划。**它也是折叠的起点标记** |
118
- | `tree_task_plan` | 给一个节点追加子节点:父节点是目标加的是任务,父节点是任务加的是子任务。**建新目标不归它管** |
119
- | `tree_task_done` | 完成一个节点并提交它的结果,**`result` 必填**;返回的就是"下一步干什么",这次调用连同返回留在上下文里,被收走的只是它前面的执行过程 |
120
- | `tree_task_update` | 修改一个节点的标题或说明 |
121
- | `tree_task_drop` | 丢弃一个节点:留个记号说「这件事不做了」,节点**留在树里**可查(划掉)。丢弃目标会连同它下面的任务与子任务一起走,丢弃任务带上它的子任务 |
122
- | `tree_task_delete` | **删除**一个节点:把它连同下面的任务或子任务从树里**摘掉**、不留痕,**不看状态**(已完成、已丢弃的都删得掉)。清理写错 / 建重 / 结果记错的内容用它 |
123
-
124
- **丢与删是两件事**:丢弃回答"这件事还要不要做"(历史留着),删除是"这条内容本身就是错的"
127
+ | `tree_task_status` | **开工第一步先调它**:需求列表不常驻上下文。不填参数按「活跃 → 已归档 → 草稿」逐条列出,并展开当前那一条;填 `ids` 一次查多条全貌;`include` 选简介 / 版本历史 / 任务结果;`match` 按关键词找 |
128
+ | `tree_task_create` | 把用户提出的一件事记成**需求草稿**(标题 ≤50 字、简介 ≤200 字、详情不限长)。草稿不算真需求,不进活跃列表;草稿阶段用 `tree_task_requirement` 的 `update` 逐次补充正文,确认时用 `confirm` 生成版本 |
129
+ | `tree_task_requirement` | 需求的写操作:`confirm` 确认草稿并生成版本(第一次 v1,之后每次 +1,`title` 可不传)/ `update` 部分更新正文,只改给出的字段,更新后需求回到草稿,可多次调用 / `confirmChange` 确认用户提交的暂定版本 / `question` 有歧义退回 / `archive`、`unarchive`(可批量,给 `ids`)/ `prerequisites` 设前置(`id` 被设置者,`ids` 前置编号,整体替换) |
130
+ | `tree_task_start` | **开工**:把上一次折叠成功之后的过程收走,返回这条需求的详情。草稿要先确认;已完成的不能再开工。**调用前先读完所需的文件与文档** |
131
+ | `tree_task_plan` | 给一个节点追加子节点:给需求加任务,给任务加步骤。**建新需求不归它管**;**读资料不算任务**——那是开工前就该掌握的信息 |
132
+ | `tree_task_done` | **完成步骤、任务或需求,并折叠它的过程**:每完成一个步骤调用一次,多个节点完成时分别调用。`result` 必填,缺了直接拒;完成需求时它就是**总结**。这一次调用连同返回留在上下文里,被收走的是它前面那段执行过程 |
133
+ | `tree_task_update` | 改**任务或步骤**的标题与说明(改需求正文要走 `tree_task_requirement`,因为要留版本历史) |
134
+ | `tree_task_drop` | **放弃**:留个记号说「这件事不做了」,节点**留在树里**可查(划掉)。放弃需求会连同没做完的任务一起放弃,完成过的保持原样。可批量:给 `ids`,被父节点带走的子节点自动跳过 |
135
+ | `tree_task_delete` | **删除**:把它连同下面的东西**摘掉**、不留痕,**不看状态**。清理写错 / 建重 / 结果记错的内容用它。可批量:给 `ids` |
136
+ | `tree_task_note` | 笔记:给 `key` 与 `text` 就是写(当场返回,同名覆盖、修订号 +1);要查就只给 `query`,什么都不给就是全部 |
137
+
138
+ **放弃与删除是两件事**:放弃回答"这件事还要不要做"(历史留着),删除是"这条内容本身就是错的"
125
139
  (凭空摘掉)。一个节点做完之后再想让它消失,只能用删除。
126
140
 
127
- 层级固定三级,子任务是最低一级,不能再往下拆。
141
+ 层级固定三级,步骤是最低一级,不能再往下拆。
128
142
 
129
143
  **返回的三条规矩:**
130
144
 
131
- - 写树类工具只返回**本次动到的那个目标**的树,不再每次倾倒整棵树;
132
- - 树用**规范的 Markdown 嵌套任务清单**渲染(`- [ ]` 开头、每层两个空格缩进),
133
- 复制出去能正常预览,不会被当成代码块;
145
+ - 写树类工具只返回**本次动到的那个需求**,不再每次倾倒整份列表;
146
+ - 列表与树用**规范的 Markdown** 渲染,复制出去能正常预览,不会被当成代码块;
134
147
  - **结果全文给出,一个字都不截**。
135
148
 
136
149
  ```markdown
137
- - [x] **目标** `g-mv50h48v1` 安卓端播放
138
- - **结果**:手机连上 PC 并把声音收下来了。
139
- 验收:模拟器上跑通一次端到端。
140
- - [x] **任务** `t-mv50h48v2` 工程骨架
141
- - **结果**:交付物 android\settings.gradle;`cd android; powershell -File tools\build.ps1` 冷构建成功。
142
- - [ ] **子任务** `s-mv50h48v5` 写 build.gradle ← 当前
143
- - [ ] **目标** `g-mv50h48v6` 安卓端来源 ← 当前
144
- - [ ] **任务** `t-mv50h48v7` 采集层
150
+ - [ ] **R1** · 未完成 把菜单改成深色 ← 当前
151
+ 菜单太亮,改成深色
152
+ - [x] 任务一
153
+ - [ ] 任务二
145
154
  ```
146
155
 
147
156
  ### 三层怎么分
148
157
 
149
158
  | 层 | 是什么 | 怎么算分对了 |
150
159
  |---|---|---|
151
- | **L1 目标** | 最终要交付的东西 | 一个会话可以有多个,按创建顺序排;每个都写清要交付什么 |
152
- | **L2 任务** | **交付节点** | 一件能独立验收的交付内容——一个文件、一条能跑的命令、一份结论,也可以是件需要完成或验证的事、一个检查点;下面覆盖多个步骤,别拆到只剩一两个 |
153
- | **L3 子任务** | **步骤** | 任务内部一两次工具调用能做完的事 |
160
+ | **需求** | 用户在这个会话里要什么 | 标题一句话(≤50 字)、简介一段(≤200 字)、详情不限长;由 AI 与用户沟通后确认 |
161
+ | **任务** | **交付节点** | 一件能独立验收的交付内容——一个文件、一条能跑的命令、一份结论,也可以是一个检查点 |
162
+ | **步骤** | 任务内部的一下 | 一两次工具调用能做完的事 |
154
163
 
155
- **折叠次数跟着 `tree_task_done` 的次数走**:每完成一个节点就折一次,界面也会因此多一张
156
- 系统提示词卡片。所以任务别拆得太碎——够厚,done 的次数少,上下文前缀变动的次数也少。
164
+ **折叠次数跟着 `tree_task_done` 的次数走**:每完成一个任务折一次;完成需求时把它整条收成一条。
165
+ 所以任务别拆得太碎——够厚,done 的次数少,上下文前缀变动的次数也少。
157
166
 
158
167
  `result` 分两层写:任务的 result 写**交付物 + 怎么验收**(文件在哪、怎么跑、验出什么、
159
- 已知限制),子任务的 result 一句话说清这步做了什么就够。
168
+ 已知限制),步骤的 result 一句话说清这步做了什么就够;**需求的 result 就是它的总结**,
169
+ 别的需求靠它快速查阅。
160
170
 
161
171
  ## 安装
162
172
 
@@ -210,40 +220,40 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
210
220
  外观照内置条目做——用的是同一套 UI 基座(`@deepseek-ai/dsh-client-ui-primitives`
211
221
  的图标、Tooltip 与 CSS 变量),所以它看起来就是内置的一部分:
212
222
 
213
- - **折叠时**是目标条那样的 36px 单行条:左边清单图标,中间「阶段标签 + 目标标题 + 进度」,
214
- 右边一排圆形图标按钮——**暂停/继续**、清空计划、展开。
215
- 阶段标签四种:进行中 / 已暂停 / 检查点 / 已全部完成。
216
- - **展开后**是待办清单那样的卡片:三级树之间有竖线与拐角连线,层级一眼看得出来;
217
- 同一层的节点之间、节点内部的各个内容块之间,各有一条分界线。
218
- **默认只摊开正在走的那条路径**——目标一路展开到当前子任务,其余节点收起,
219
- 一打开就能看见正在跑的那一个,不用在一堆已经收尾的节点里翻;检查点所在的节点
220
- 也一样默认摊开。想细看哪个就点它行尾的箭头,逐层摊开或收起。
221
- 当前节点的虚线圈会匀速转,已完成打勾、丢弃的划掉。
222
- - 节点标题**不缩略**:有多长写多长,多了自动换行。
223
- - 提交的结果**默认只占一行**,点一下摊开看全文。
224
- - 节点上可以直接完成、**丢弃**(划掉,历史留着)、**删除**(垃圾桶,连子节点一起摘掉),
225
- 不用敲命令。删除对**任何状态**的节点都开着——已完成的那个也在,清理错内容正是它的用途。
226
- - 进度只数**还在做的事**:被丢弃的节点分子分母都不算,所以丢过几个之后进度照样能满。
227
- - 数据每 4 秒自动拉一次,模型在后台改计划时界面会自己跟上。
228
-
229
- **没有计划的会话一个像素都不占**——读不到计划就返回 `null`,不会平白挤掉内置的
223
+ - **收起时**是一条 36px 的单行条:左边清单图标,中间「状态 + 当前需求标题 + 进度」,
224
+ 右边两个按钮——**暂停 / 继续**与展开。状态三种:进行中 / 已暂停 / 待开始;
225
+ **没有进行中的需求时照最近的那一条显**(标题与它自己的状态,多半是「已完成」),
226
+ 不拿「待开始」去描述一条已经做完的需求。
227
+ - **展开后**是需求面板,分三段:
228
+ - **活跃需求**:一行一条(状态、编号、标题、简介、进度),当前进行中的那条打「当前」;
229
+ - **待确认**:还没跟 AI 沟通确认的草稿,不占上下文;
230
+ - **已归档**:用户归档掉的需求,同样一行一条,可随时取消归档;
231
+ - 每行三个动作:**开始**(叫醒 AI 去做这条)、**归档 / 取消归档**、**展开看详情**。
232
+ - **点开一条**看只读详情:简介、详情全文、缺哪个前置、待确认变动、任务与步骤、总结。
233
+ 点「改需求」进编辑态:标题、简介、详情三个输入框 + 「确认变更」。
234
+ **提交之后只是暂定版本**,AI 确认之前仍按旧版本走。
235
+ - **归档有一个刻意的延迟**:点了之后这一行**不动**,按钮变成「取消归档」,反悔点一下就回去了;
236
+ 下次打开面板才按新状态重新分列表。防误点优先于即时一致。
237
+ - 数据每 4 秒自动拉一次,模型在后台改需求时界面会自己跟上。
238
+
239
+ **一条需求都没有的会话一个像素都不占**——面板直接返回 `null`,不会平白挤掉内置的
230
240
  待办与目标条目。
231
241
 
232
- 开关不在界面上,在 profile 的 `cordis.patch.yml` 里(见上面的「关闭」一节)。
233
-
234
242
  ## 命令
235
243
 
236
244
  `/task-tree` **不经过模型**,直接执行:
237
245
 
238
246
  | 命令 | 作用 |
239
247
  |---|---|
240
- | `/task-tree` | 查看本会话的任务树与检查点状态 |
241
- | `/task-tree done <id> <结果>` | 提交某个节点的结果并完成它 |
242
- | `/task-tree drop <id>` | 丢弃某个节点:留着可查,标记为不做了 |
243
- | `/task-tree delete <id>` | 删除某个节点:连子节点一起从树里摘掉,不看状态 |
248
+ | `/task-tree` | 查看本会话的需求列表与当前进度 |
249
+ | `/task-tree done <id> <结果>` | 提交某个节点(需求 / 任务 / 步骤)的结果并完成它 |
250
+ | `/task-tree drop <id>` | 放弃:留着可查,标记为不做了 |
251
+ | `/task-tree delete <id>` | 删除:连下面的一起摘掉,不看状态 |
244
252
  | `/task-tree pause` | 暂停:正在跑的工具跑完就停住,不再往下推进 |
245
253
  | `/task-tree resume` | 继续:从停住的地方接着跑,不往会话里插消息 |
246
- | `/task-tree reset` | 清掉本会话的计划树 |
254
+ | `/task-tree reset` | 清掉本会话的计划(需求、任务全没) |
255
+
256
+ 开关不在界面上,在 profile 的 `cordis.patch.yml` 里(见上面的「关闭」一节)。
247
257
 
248
258
  ## 配置
249
259
 
@@ -252,19 +262,20 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
252
262
  | 字段 | 默认 | 说明 |
253
263
  |---|---|---|
254
264
  | `enabled` | `true` | 总开关;**装上即启用**,写 `false` 关掉 |
255
- | `autoContinue` | `false` | 模型停下时是否自动续行(见下节;**在 DSH 设置面板里能改**) |
265
+ | `autoContinue` | `false` | 模型停下时是否自动续行(见下节;**在插件管理里本插件那一页能改**) |
256
266
  | `maxAutoRounds` | `5` | 连续自动续行的轮次上限 |
257
- | `interruptRecovery` | `true` | 意外中断后是否自动拉起(见下节;**在 DSH 设置面板里能改**) |
267
+ | `interruptRecovery` | `true` | 意外中断后是否自动拉起(见下节;**在插件管理里本插件那一页能改**) |
258
268
  | `interruptDelaysMs` | `null` | 网络类中断的拉起时刻,`null` = 1/5/10/30 分钟 |
259
269
  | `promptOrder` | `1800` | 工具说明段落的排序 |
260
270
  | `rootDir` | `null` | 状态目录,默认 `$DSH_HOME/dsh-task-tree` |
261
271
 
262
272
  ## 设置
263
273
 
264
- 设置**在 DSH 自己的设置面板里**:打开侧边栏的设置,导航里有一页叫「树形任务流」
265
- (跟「通用」「市场」并排),点开就是这两个开关。**改完立刻生效,不用重启。**
274
+ 设置**在插件管理里、这个插件自己的那一页**:打开侧边栏的「插件」页,在「已安装」里点
275
+ `dsh-tree-task-flow` 这张卡,页面上描述下面就是这两个开关。**改完立刻生效,不用重启。**
266
276
 
267
- > 它不在任务条上。任务条只干两件事:看进度、按暂停 / 继续;偏好属于设置,就该待在设置里。
277
+ > 它不在 DSH 的设置面板里,也不在任务条上。设置属于这个插件,就该长在插件自己身上;
278
+ > 任务条只干两件事:看进度、按暂停 / 继续。
268
279
 
269
280
  | 设置 | 默认 | 做什么 |
270
281
  |---|---|---|
@@ -276,9 +287,9 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
276
287
  结束"时动手,正常停下它一步都不动。
277
288
 
278
289
  设置写在状态目录的 `settings.json` 里(**不按会话分**,整个插件一份),重启后还在。
279
- 优先级是 **设置面板里改过的 > profile 里的 config > `DEFAULT_CONFIG`**:在面板里点过就以
280
- 面板为准,免得界面对不上 YAML。`enabled`、`maxAutoRounds`、`interruptDelaysMs` 这类
281
- "装插件时就该定好"的项不在面板上,仍然只认 profile 配置。
290
+ 优先级是 **在插件页里改过的 > profile 里的 config > `DEFAULT_CONFIG`**:在页里点过就以
291
+ 页为准,免得界面对不上 YAML。`enabled`、`maxAutoRounds`、`interruptDelaysMs` 这类
292
+ "装插件时就该定好"的项不在开关名单里,仍然只认 profile 配置。
282
293
 
283
294
  ## 意外中断自动拉起
284
295
 
@@ -315,7 +326,7 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
315
326
  自己改道,本来也没中断这一轮。
316
327
  - 只在**这个会话的计划树还没走完**时才动手。等待时刻写在状态目录的 `revive/` 下,
317
328
  重启 `dsh web` 不会丢。
318
- - **能在设置面板里关掉。** DSH 设置里的「树形任务流」那一页中,"工具出错自动拉起"就是
329
+ - **能在插件页里关掉。** 插件管理里本插件那一页的"工具出错自动拉起"就是
319
330
  这个开关,改完立刻生效(关掉之后插件连 `revive/` 都不再写)。
320
331
 
321
332
  ## 暂停与继续
@@ -363,8 +374,8 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
363
374
  **模型自己停下、计划树却没跑完,插件就推一条"接下来要做 X"把它唤醒。** 这只是**兜底**:
364
375
  `tree_task_done` 的返回文本里已经带了"请继续执行下一个子任务",模型通常会在同一轮里接着做。
365
376
 
366
- `autoContinue` **默认关闭**——它会自己往下跑,所以默认由人来点。要开就在 DSH 设置面板的
367
- 「树形任务流」那一页里打开(**改完立刻生效**,不用重启),或者在 profile 里写 `autoContinue: true`。
377
+ `autoContinue` **默认关闭**——它会自己往下跑,所以默认由人来点。要开就在插件管理里
378
+ 本插件那一页打开(**改完立刻生效**,不用重启),或者在 profile 里写 `autoContinue: true`。
368
379
 
369
380
  开着也不会脱缰,有四道闸门:
370
381
 
@@ -391,13 +402,17 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
391
402
 
392
403
  | 文件 | 内容 |
393
404
  |---|---|
394
- | `plans/<sessionId>.json` | 计划树(每个会话一棵) |
405
+ | `plans/<sessionId>.json` | 需求与任务(每个会话一份,需求住在里面的 `goals` 键上——历史键名) |
406
+ | `notes/<sessionId>.json` | 笔记(跟会话走,不跨会话带) |
395
407
  | `surfaces/<sessionId>.json` | 三层的进度游标 `{ key, cursor }`(只给界面看,不参与折叠) |
396
408
  | `held/<sessionId>.json` | 暂停 / 停止状态(跨重启保留) |
397
409
  | `revive/<sessionId>.json` | 意外中断的拉起时刻表(跨重启保留) |
398
- | `settings.json` | 设置面板里改过的设置(**整个插件一份,不按会话分**) |
410
+ | `settings.json` | 在插件页里改过的设置(**整个插件一份,不按会话分**) |
399
411
 
400
412
  > 目录名沿用插件改名前的标识,为的是不让既有的计划文件失联;插件名与它无关。
413
+ >
414
+ > 旧版的文件里没有需求那一层的字段(`versions` / `archived` / `prerequisites` 等)。
415
+ > 读的时候**在内存里补齐**,不改写磁盘上的老文件——老会话照常能读。
401
416
 
402
417
  计划属于建立它的那个会话。放到会话无关的位置,任何一个会话的计划都会被
403
418
  所有会话读到——那等于把不相干的节点指派塞进别人的上下文。
@@ -411,30 +426,36 @@ dsh --profile web --dump-config # 输出里应出现 task-tree 这一
411
426
  空 `result` 会被拒绝。所以要写清"产出了什么",写成能独立看懂的样子——
412
427
  过程会丢,别把过程写进去。
413
428
 
414
- 2. **折叠只看表层。** 起点是上一次 `done` 之后的第一条 `tree_task_create`;
415
- `tree_task_plan` 不是边界,它的调用与返回跟过程一样会被收走;区间里没有过程时
416
- 什么都不注入,夹着你的消息时整段不折——那一段原样留着(往前折丢需求、
417
- 往后折丢回应),代价是上下文不收缩。
429
+ 2. **每完成一个步骤就报一次完成,不要合并。** 折叠只发生在完成的那一刻:四个任务全部做完
430
+ 再连续补四次 `done`,中间那两百多条过程会一直留在上下文里。实测过一轮对照——合并补报
431
+ 的会话,每步平均输入 174.7k token,不用插件的对照组是 167.0k,插件反而更贵。
432
+ 这条插件无法代替模型决定,所以写进了系统提示词与工具说明里。
433
+
434
+ 3. **折叠只看表层。** `start` 从上次折叠成功的位置起折,`done` 从上一个
435
+ `done` 或 `start` 之后折(尚未 start 时退到 `create`),完成需求时折整条;`tree_task_plan` 不是边界,
436
+ 它的调用与返回跟过程一样会被收走。区间里没有过程时什么都不注入,夹着你的消息时
437
+ 整段不折——那一段原样留着(往前折丢需求、往后折丢回应),代价是上下文不收缩;
438
+ 下一次 `start` 会把它补折回来。
418
439
 
419
- 3. **模型看到的工具说明不随计划变化,也不复述工具清单。** 那一段只讲什么时候用
440
+ 4. **模型看到的工具说明不随计划变化,也不复述工具清单。** 那一段只讲什么时候用
420
441
  这组工具、完成时守什么规矩;每个工具的用法由它自己的 `description` 承担。
421
442
  要了解计划就让模型调 `tree_task_status`。
422
443
 
423
- 4. **折叠几次,界面就多几张「系统提示词」卡片,但上下文里的系统提示词始终只有一条。**
444
+ 5. **折叠几次,界面就多几张「系统提示词」卡片,但上下文里的系统提示词始终只有一条。**
424
445
  DSH 把"上下文被替换过"记成一次请求序列的边界(下一次请求带 `reason=series`),
425
446
  界面在 `reason` 不是 `change` 的请求上都会画一张系统提示词卡片;锚点跟着那一轮 step 走,
426
447
  卡片于是一张张堆起来。**上下文里 `system/message` 自始至终只有一条**,折叠没有伪造
427
448
  任何系统消息。已实测:3 次折叠 → 3 次 `series` → 界面 3 张卡片。
428
449
 
429
- 5. **改需求用「丢弃 + 追加」,不要重建整棵树。** 丢掉的节点留在树里可查,
450
+ 6. **改需求用「丢弃 + 追加」,不要重建整棵树。** 丢掉的节点留在树里可查,
430
451
  它和完成的节点会一起被那一段折叠收走(通告只报条数,不区分完成还是丢弃)。
431
452
  **内容写错了才用删除**——删除是摘掉,摘掉的东西查不回来,也没有任何通告替它留痕。
432
453
 
433
- 6. **暂停不留痕迹。** 暂停后模型看到的是"没有下一条请求",看不到任何"你被暂停了"
454
+ 7. **暂停不留痕迹。** 暂停后模型看到的是"没有下一条请求",看不到任何"你被暂停了"
434
455
  之类的提示;继续之后也不会有"继续"消息进上下文。想让模型知道中间发生过什么,
435
456
  得自己发消息说。
436
457
 
437
- 7. **内置压缩之后会有一条提醒。** DSH 自己的压缩把一大段历史收成一条检查点之后,
458
+ 8. **内置压缩之后会有一条提醒。** DSH 自己的压缩把一大段历史收成一条检查点之后,
438
459
  如果这个会话里有计划树,插件会注入一条
439
460
  `tree_task消息:上下文刚被压缩过,计划树没有被压缩。用 tree_task_status 取回当前进度…`。
440
461
  计划树本身不在压缩范围内——它存在磁盘上;但模型会忘掉它,所以补这一句。