树形任务流 dsh-tree-task-flow

DeepSeek Harness 插件 · 上下文管理

把过程折起来,把结果留下。

它把你在这个会话里提的要求记成需求,需求下面挂任务与步骤。 每完成一步,模型提交结果,插件随即把这段执行过程从上下文里折叠掉——只留下那条结果。

Node.js 22.19+ 安装即启用 MIT 不跨会话

surface 一次任务在上下文里的形状
  1. readsrc/menu.css
  2. bashgrep -rn "--surface" src/
  3. editsrc/menu.css
  4. result3 处命中
  5. readsrc/theme.css
  6. bashnode verify.mjs
  7. editsrc/theme.css
  8. result12 项通过
tree_task消息:此处隐藏了12条过程上下文。
其中修改或生成了文件:
  • C:\apps\x\src\menu.css
  • C:\apps\x\src\theme.css
  1. donet-4 · 任务已完成
结果:菜单与主题都改成深色,对比度由 verify.mjs 逐条检查。
折叠只发生在完成那一刻

读文件、试错、命令输出在完成时一起收走;通告里只列写入过的文件,读过的文件不列出。

01 — 症状 上下文只增不减,
而真正要留住的只有一句

长任务跑到后半程,
上下文里堆的都是过程。

读过哪些文件、试过哪些错、执行过哪些命令——它们对后面没有用,但会一直占着位置。 真正需要留给后面的只有一句话:这一步做完了,它产出了什么。

01

越滚越大

每一轮工具调用都追加到同一串消息里。任务跑得越久,这串消息越长——后半程要读的,是前半程的全部经过。

02

越读越贵

每多一轮,喂给模型的上下文就更长一分。被反复送进去的过程,与实际需要的结论之间,差得越来越远。

03

越走越忘事

上下文越长,关键信息越容易被稀释。模型得一遍遍回去找「当初到底要的是什么」,或者干脆记成了别的。

过程 读过的文件、试过的错、命令输出 结果 这一步做完了,它产出了什么

没有它的时候:整段过程一直留在表层,只有零星几句是结论。

02 — 结构 需求 / 任务 / 步骤,
三级固定

把要求记成需求,
需求下面挂任务与步骤。

需求记的是「用户在这个会话里要什么」,不是「项目长什么样」——一条需求可以对应毫无关联的目录, 需求列表也不跨会话。这不是项目管理。

tree_task_statusactive
  • R1 把菜单改成深色 进行中
    • t-1 取色板与对比度 已完成
      • s-1 读现有的颜色变量 已完成
      • s-2 逐个量对比度 已完成
    • t-2 改菜单样式 进行中
      • s-3 替换 --surface 未完成
存下来的样子YAML
active:
  - id: R1
    title: 把菜单改成深色
    status: 进行中
    version: 1
    tasks:
      - id: t-1
        title: 取色板与对比度
        status: 已完成
        result: 对比度 ≥ 4.5:1,逐条写在 verify 输出里
      - id: t-2
        title: 改菜单样式
        status: 进行中
        steps: [s-3]
create

记下

需求先落成草稿,正文可以反复改,确认后才生成版本。

start

开工

开始一条已确认的需求;返回整棵树,不必重读旧过程。

done

收工并折叠

提交结果、完成节点。折叠就发生在这一刻。

边界只有三个工具名。补步骤的 tree_task_plan 不算边界——它跟普通过程一起被收走。

真正需要留给后面的,只有一句话:
这一步做完了,它产出了什么。
— README · 它解决什么
03 — 折叠 完成的那一刻,
过程从上下文里消失

收走的是一段区间,
换回来的是一行通告。

折叠按表层的位置切,与计划树无关(计划树只用来认出「这次完成的是不是一条需求」)。 边界调用本身留在上下文里;触发这一次的 done 调用与返回,同样留着。

折叠前8 条过程
readsrc/menu.css
bashgrep --surface src/
editsrc/menu.css
result3 处命中
readsrc/theme.css
bashnode verify.mjs
editsrc/theme.css
result12 项通过
折叠后1 条通告 + 1 条结果
tree_task消息:此处隐藏了12条过程上下文。
其中修改或生成了文件:
  • C:\apps\x\src\menu.css
  • C:\apps\x\src\theme.css
t-4 任务已完成,结果:菜单与主题都改成深色,对比度逐条检查过。
done

收「上一个 done 或 start 之后」到这次调用之前

完成的是需求时,收「这条需求开工那次 create 之后」的全部。尚未 start 时,退到 create。

start

从「上一次折叠成功」的位置补折

折叠会被「用户的话还没写进需求」挡住。挡掉的那一段如果只按边界算,下一条边界一出现就永远落在区间外——挡一次就永久丢一段上下文。所以插件给每个会话记一个「折到哪儿了」的游标。

通告

只讲折叠,不带别的提示

正文是 tree_task消息:此处隐藏了N条过程上下文。。有写入文件时接「其中修改或生成了文件:」与逐行路径;读取的文件不列出。

表层节点
23 个system/message 恰好 1 条
折叠 3 次
12 / 6 / 4 条经一次 headless 会话实测
请求 4 次
initial 1 · series 3
口径
数据取自旧起点规则新规则下区间会更少、更大

数字来自仓库 docs/03-折叠上下文实测.md,连文档自己标注的口径问题一起照抄。

04 — 依据 折掉的是过程,
留下的是结果与笔记

凭什么成立:
收走的只是发出去的那份上下文。

收走的不是存档。需求全文、版本历史、任务结果都还在存储里,按需可查; 笔记不随折叠通告带出,需求树也不常驻上下文。

01

结果原样留下

模型在 tree_task_done 里提交的 result 留下来,供后续节点引用。折叠通告只讲折叠,不带任务、需求、笔记的提示。

02

笔记不跟着走

跟工作有关、但不属于任何一条需求的事实与偏好,写成笔记。它跟会话走,不随通告带出;要查就调 tree_task_note。

03

需求树在磁盘上

plans/<sessionId>.json,每个会话一份。树不常驻上下文,开工第一步用 tree_task_status 现取。

折叠按什么切
只看表层的三个工具名:create / start / done,按名字认、不看实参。
收走后剩下什么
一条计数通告 + 写入过的文件路径;读取不算。
两条硬约束
区间里夹着真人消息 → 整段不折;区间为空 → 什么都不注入。
存哪儿
状态目录里的 plans/<sessionId>.json;暂停与中断时刻表跨重启保留。
05 — 边界 它做不到什么,
也写在文档里

会算错账的地方,
照原样告诉你。

一支工具的宣传页最容易漏掉的,是它不划算的那些场合。下面这几条来自仓库文档,包括那条对自己不利的对照。

收益取决于完成时机:攒着补报,插件反而更贵 实测对照

每完成一个节点就报一次,折得越大越省。反过来,攒很久再补报一轮,折叠几乎追不上前面堆起来的过程。

实测过一次对照:攒着补报的那一轮,用插件的会话每步平均输入 174.7k token,不用插件的对照组 167.0k——插件反而贵了 11%。

这条留在仓库里,没有删。

它管的是上下文,不是项目管理 模型边界

需求记录的是「用户在这个会话里要什么」。不跨会话,一条需求可以横跨毫无关联的目录,它也不回答「项目长什么样」。

把需求列表当成项目看板来用,是误用。

两条硬约束:夹着真人消息不折,区间为空不注入 规则

区间里夹着还没写进需求的用户消息时,整段不折,宁可留着;区间为空时什么都不注入——不追加、不留空消息。

所以「折到哪儿了」需要游标来记:start 认「上一次折叠成功」,done 只认上一个边界。

折叠不是快照,也不是文件回退 别指望

收走的只是发出去的那份上下文。它不会替你保存工作区、不会把改动回滚,也不是记忆系统。

要留的东西,仍然要写在 result 里,或者写成笔记。

暂停是真暂停;自动续行默认关 行为

暂停之后,正在跑的工具跑完就停住,不再往下推进;继续时从停住的地方接着跑,不往会话里插消息。重启 dsh web 之后暂停依然有效。

自动续行默认关闭——它会自己往下跑,所以该由人来点。中途意外中断的拉起有 1 / 5 / 10 / 30 分钟的时刻表,你按下的停止永远不拉。

关掉之后,一个字节都不碰会话 开关

不想用时,在 profile 里写一句 enabled: false 就能关掉;关掉后只留一条 /task-tree 命令,让你确认它确实关着、以及怎么打开。

06 — 安装 装上就是全部配置

一条命令,
之后不用再改任何配置。

需要 Node.js 22.19 以上,以及能运行 dsh。装进 profile 之后必须重启 dsh web 才生效——新工具要在新会话里才会出现。

终端
# 从 npm 安装到 web 这个 profile
$ dsh plugin --profile web add dsh-tree-task-flow

# 从源码目录安装(装成 link:,改完源码重启即生效)
$ dsh plugin --profile web add <插件目录>

# 重启之后才会出现新工具
$ dsh web

# 不想要了
$ dsh plugin --profile web remove dsh-tree-task-flow

两个开关在插件管理里本插件那一页,改完立刻生效、不用重启: 自动续行默认关;连续续行上限 5 轮。设置写在状态目录的 settings.json 里,不按会话分,重启后还在。

/task-tree查看本会话的需求列表与当前进度
done <id> <结果>提交节点结果并完成它
drop <id>放弃:留着可查,标记为不做了
delete <id>删除:连下面的一起摘掉
pause暂停:工具跑完就停住
resume继续:从停住的地方接着跑
reset清掉本会话的计划

/task-tree 不经过模型,直接执行。