DeepSeek Harness 插件 · 上下文管理
把过程折起来,把结果留下。
它把你在这个会话里提的要求记成需求,需求下面挂任务与步骤。 每完成一步,模型提交结果,插件随即把这段执行过程从上下文里折叠掉——只留下那条结果。
- read
src/menu.css - bash
grep -rn "--surface" src/ - edit
src/menu.css - result
3 处命中 - read
src/theme.css - bash
node verify.mjs - edit
src/theme.css - result
12 项通过
- C:\apps\x\src\menu.css
- C:\apps\x\src\theme.css
- done
t-4 · 任务已完成
读文件、试错、命令输出在完成时一起收走;通告里只列写入过的文件,读过的文件不列出。
而真正要留住的只有一句
长任务跑到后半程,
上下文里堆的都是过程。
读过哪些文件、试过哪些错、执行过哪些命令——它们对后面没有用,但会一直占着位置。 真正需要留给后面的只有一句话:这一步做完了,它产出了什么。
越滚越大
每一轮工具调用都追加到同一串消息里。任务跑得越久,这串消息越长——后半程要读的,是前半程的全部经过。
越读越贵
每多一轮,喂给模型的上下文就更长一分。被反复送进去的过程,与实际需要的结论之间,差得越来越远。
越走越忘事
上下文越长,关键信息越容易被稀释。模型得一遍遍回去找「当初到底要的是什么」,或者干脆记成了别的。
没有它的时候:整段过程一直留在表层,只有零星几句是结论。
三级固定
把要求记成需求,
需求下面挂任务与步骤。
需求记的是「用户在这个会话里要什么」,不是「项目长什么样」——一条需求可以对应毫无关联的目录, 需求列表也不跨会话。这不是项目管理。
-
R1 把菜单改成深色 进行中
-
t-1 取色板与对比度 已完成
-
s-1 读现有的颜色变量 已完成
-
s-2 逐个量对比度 已完成
-
-
t-2 改菜单样式 进行中
-
s-3 替换 --surface 未完成
-
-
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]
记下
需求先落成草稿,正文可以反复改,确认后才生成版本。
开工
开始一条已确认的需求;返回整棵树,不必重读旧过程。
收工并折叠
提交结果、完成节点。折叠就发生在这一刻。
边界只有三个工具名。补步骤的 tree_task_plan 不算边界——它跟普通过程一起被收走。
真正需要留给后面的,只有一句话:— README · 它解决什么
这一步做完了,它产出了什么。
过程从上下文里消失
收走的是一段区间,
换回来的是一行通告。
折叠按表层的位置切,与计划树无关(计划树只用来认出「这次完成的是不是一条需求」)。
边界调用本身留在上下文里;触发这一次的 done 调用与返回,同样留着。
- C:\apps\x\src\menu.css
- C:\apps\x\src\theme.css
t-4 任务已完成,结果:菜单与主题都改成深色,对比度逐条检查过。
收「上一个 done 或 start 之后」到这次调用之前
完成的是需求时,收「这条需求开工那次 create 之后」的全部。尚未 start 时,退到 create。
从「上一次折叠成功」的位置补折
折叠会被「用户的话还没写进需求」挡住。挡掉的那一段如果只按边界算,下一条边界一出现就永远落在区间外——挡一次就永久丢一段上下文。所以插件给每个会话记一个「折到哪儿了」的游标。
只讲折叠,不带别的提示
正文是 tree_task消息:此处隐藏了N条过程上下文。。有写入文件时接「其中修改或生成了文件:」与逐行路径;读取的文件不列出。
- 表层节点
- 23 个system/message 恰好 1 条
- 折叠 3 次
- 12 / 6 / 4 条经一次 headless 会话实测
- 请求 4 次
- initial 1 · series 3
- 口径
- 数据取自旧起点规则新规则下区间会更少、更大
数字来自仓库 docs/03-折叠上下文实测.md,连文档自己标注的口径问题一起照抄。
留下的是结果与笔记
凭什么成立:
收走的只是发出去的那份上下文。
收走的不是存档。需求全文、版本历史、任务结果都还在存储里,按需可查; 笔记不随折叠通告带出,需求树也不常驻上下文。
结果原样留下
模型在 tree_task_done 里提交的 result 留下来,供后续节点引用。折叠通告只讲折叠,不带任务、需求、笔记的提示。
笔记不跟着走
跟工作有关、但不属于任何一条需求的事实与偏好,写成笔记。它跟会话走,不随通告带出;要查就调 tree_task_note。
需求树在磁盘上
plans/<sessionId>.json,每个会话一份。树不常驻上下文,开工第一步用 tree_task_status 现取。
plans/<sessionId>.json;暂停与中断时刻表跨重启保留。也写在文档里
会算错账的地方,
照原样告诉你。
一支工具的宣传页最容易漏掉的,是它不划算的那些场合。下面这几条来自仓库文档,包括那条对自己不利的对照。
收益取决于完成时机:攒着补报,插件反而更贵 实测对照
每完成一个节点就报一次,折得越大越省。反过来,攒很久再补报一轮,折叠几乎追不上前面堆起来的过程。
实测过一次对照:攒着补报的那一轮,用插件的会话每步平均输入 174.7k token,不用插件的对照组 167.0k——插件反而贵了 11%。
这条留在仓库里,没有删。
它管的是上下文,不是项目管理 模型边界
需求记录的是「用户在这个会话里要什么」。不跨会话,一条需求可以横跨毫无关联的目录,它也不回答「项目长什么样」。
把需求列表当成项目看板来用,是误用。
两条硬约束:夹着真人消息不折,区间为空不注入 规则
区间里夹着还没写进需求的用户消息时,整段不折,宁可留着;区间为空时什么都不注入——不追加、不留空消息。
所以「折到哪儿了」需要游标来记:start 认「上一次折叠成功」,done 只认上一个边界。
折叠不是快照,也不是文件回退 别指望
收走的只是发出去的那份上下文。它不会替你保存工作区、不会把改动回滚,也不是记忆系统。
要留的东西,仍然要写在 result 里,或者写成笔记。
暂停是真暂停;自动续行默认关 行为
暂停之后,正在跑的工具跑完就停住,不再往下推进;继续时从停住的地方接着跑,不往会话里插消息。重启 dsh web 之后暂停依然有效。
自动续行默认关闭——它会自己往下跑,所以该由人来点。中途意外中断的拉起有 1 / 5 / 10 / 30 分钟的时刻表,你按下的停止永远不拉。
关掉之后,一个字节都不碰会话 开关
不想用时,在 profile 里写一句 enabled: false 就能关掉;关掉后只留一条 /task-tree 命令,让你确认它确实关着、以及怎么打开。
一条命令,
之后不用再改任何配置。
需要 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 不经过模型,直接执行。