一场 8.6 小时的会话结束时,留给你的通常只有最后那段回答。你想知道第 47 步那次 bash 为什么标红、失败之后它到底改了参数还是换了工具、上下文是在哪一轮被压掉的——回答里都不会有。dsh-maze 做的事,是把这场会话的每一步按真实起止摊平到一根时间轴上,主干、失败支路、折返点画在同一张图里,再把工具密度、Token 脉冲、上下文压力三条轨道压在下面。
它最重要的一个设计决定不是画得好不好看,而是把「解释执行过程」这件事从模型手里拿走:所有数字都是对判定数据的确定性聚合,不调 LLM。下面讲这个决定是怎么落到具体规则上的,以及它付出了什么代价。
让模型总结执行过程,缺的到底是什么
把 session log 丢给模型,让它写一段「本次执行回顾」,通常能得到通顺的答案。问题在三个结构性的地方。
第一是不可复核。「在第 12 步调整了策略后成功」这句话里,第 12 步是哪一次调用、原始命令长什么样、返回了什么,全在总结中蒸发了。你想反驳它,得自己回去翻 jsonl。
第二是不稳定。同一份日志换一次采样,措辞会变,归因会变,连「这次算不算成功」都可能变,你没法拿它去对齐三个人的记忆。
第三是它会替失败找台阶。「经过若干次尝试后完成」这句话,可能对应 11 次原样重试。模型没有说谎,它只是把 11 次压缩成了一个副词。
确定性聚合不解决「解释」,它解决「指认」。
判定:先分清「病历」和「发病」
一条工具调用算成功还是失败,听起来是最简单的问题,实际上是整个工具最容易出错的地方。dsh-maze 的做法是三层:先看错误标志,再看失败特征,最后按工具分类兜底——写入类没有错误就算成功,检索类只有空结果才算扑空,bash 和未知工具有输出就算成功。
中间那层「失败特征」有一个刻意的限制:只扫开头与末尾窗口。原因是真实报错要么从头就开始说,要么是追加在末尾的 stderr 段;而你在 git log、读文件、转储日志时引用到的报错字样,往往悬在长文本中部。这是「病历」不是「发病」。实测中有一条提交信息写了 "upstream returns HTTP 400",如果全文扫描,这条 commit 就会被判成失败命令。
避免误判的代价是可能漏判——一条把错误埋在输出正中间的命令会被当成成功。这个取舍是有意的:在一个复盘工具里,误报比漏报更伤害信任,因为你一旦发现它把正常命令标红,后面所有红点你都会怀疑。
规则和阈值集中在 verdict.js 的常量里,可以按自己项目的语料调整;页面和实时页签两条渲染链路共用同一份实现。
失败恢复链:失败之后发生了什么才是信息
失败本身的信息量其实很低,失败之后的行为才有信息量。执行分析区把每个失败调用之后的动作用四种口径归类:原样重试、换参数、换工具、未恢复,恢复耗时如实标注。点任意一条,视图缩放到那次失败并打开详情,完整命令、报错返回、判定依据都在。
这里有两个容易含糊的口径,插件做了明确切分:链只统计失败(红 ✗),检索扑空(灰 ·)和盲目重试(灰 ↻)各自进矩阵的列,不单独进链;盲重试也不作为「已恢复」的证据。因为一次盲目重试碰巧成功,和一次有意识的换策略,是两件完全不同的事。
「盲目重试」本身是行为学判定,不是文本判定:时间序上连续的「同工具 + 参数相似」调用簇,且簇内至少有一次失败,才标为无效重试。这一思路借鉴了 AgentLens 对 SWE-agent 轨迹中「浪费」的确定性检测——它看的是行为形状,不是模型怎么描述自己。
行为信号:阈值为什么必须在本机语料上校准
执行分析区旁边有一块行为信号,列出失败后原样重试、同轮重复调用、循环、慢调用(≥120 秒)、工具集中度、上下文骤升骤降、上下文峰值、压缩发生、待办陈旧、换策略恢复这些模式,每条带严重度、一句含具体数字的依据、以及涉及的调用数。
阈值不是拍脑袋定的:按本机 202 份会话校准,「中」落在最差的 15%~20% 会话,「高」落在最差的 3%~5%。这个做法值得单独说一句,因为「慢调用超过 60 秒算异常」这种通用阈值在实际语料里几乎必然失效——有人一场会话两小时,有人二十分钟,同一个绝对秒数在两个人身上的含义完全不同。用分位数校准,信号才有可比性。
工具集中度用的是赫芬达尔指数,衡量调用是不是全压在某一两个工具上;上下文骤降如果落在压缩事件附近,会额外标注「压缩」,避免把一次正常的上下文压缩读成异常。没有触发任何信号时,它会直说「本场没有触发任何信号」,而不是留一块空白让你猜。
证据六格:不信 Agent 自述
模型说「测试通过了」,这句话在复盘里几乎没有权重。结果与证据区把验证拆成六格:任务完成、测试、构建、Lint、产物、人工确认,再加一个综合徽标(已完成 / 部分成功 / 未验证),全部来自日志证据。
口径细到有点较真:通过 = 该调用没有错误标志,且返回的末行没有非零退出码;每个类别以最后一次运行的结果为准,此前别的命令最后一次失败的条数用小字注明;测试、构建、Lint 按命令正则在命令位置识别,cat vitest.config.ts、grep pytest 这种只是「提到」的命令不算;后台任务按之后 job_output 末行的退出码计,取不到就不计并标注。
产物是写入、编辑、补丁类调用成功触及的文件去重;任务完成看最后一轮 turn/end 不是 error/aborted/interrupted/blocked,且最后一步是回答;人工确认只看最终回答之后有没有真人消息,不解读内容——它不做语义判断,只回答「有没有人回过话」。
一条验证命令都没有时,它显示中性的「未验证」,而不是猜一个「大概完成」。code 模式会话里脚本内部派发的真实命令这一版暂不识别,块里如实标注,不假装看见了。
确定性聚合买到了什么,又付出了什么
买到的是一句话:每个结论都能点回原始命令与返回。这句话在复盘场景里几乎决定了一切——你不需要相信这张图,你只需要能验证它。
付出的代价也很具体。它只认日志里有的东西:日志没报 usage,Token 轨道就不画、不占高度,标签退成「推理 N 段(日志未报 token 用量)」,中转站日志与原厂日志并排时单位不同,标签自带原因。模型窗口未知或表值过时时,上下文轨道退回绝对 token 数,绝不显示超过 100% 的占用。实时页签只画对话已加载的事件窗口,更早的轮次会被丢弃并标注「⏮ 另有 N 步更早历史未加载」,要看全场得走「Session log 下载 → 上传」。
八小时的密集会话也不是天然可读的:整图先给「×N」聚合徽标,点开才逐级补齐标签,空闲超过 60 秒的区间压成 ⏸ 细缝并标明省略时长。轴被压缩了,但步骤时长、工具耗时、总耗时仍是墙钟真值。
还有一层是数据边界:上传与可视化页面是一份自包含 HTML,跑在沙箱化的 iframe 里,解析和渲染全部在浏览器端完成,上传的日志内容不会到达宿主。安全档位上,本站对它做过静态扫描,结论是 🟢 未发现敏感能力;但尚无人工评估,本站也尚未做风险分级——这两句不是免责套话,是你在决定要不要把日志放进去之前应该知道的事实。
一个不调 LLM 的复盘工具,注定不会告诉你「这次为什么绕了远路」。它只会把绕路的那七步、每一步的命令、每一次的返回,按时间顺序摆在你面前。剩下那句解释,仍然得你自己下。
总结
把执行过程交给确定性聚合而不是模型总结,换来的是可复核、可对齐、可点回原文的证据链,代价是它只肯说日志里写着的事;更多同类插件的中文清单见 DeepSeek Harness Hub 插件清单。
适合与不适合
适合:需要复盘长会话里失败与恢复过程的工程师;要对比同一任务在不同模型上多次跑法差异的团队;想按证据核对「测试到底跑没跑过」的人;习惯把执行过程导出成 SVG 放进周报或事故复盘的人。
不适合:宿主还停在 0.1.0-rc.6~0.1.1-rc.2 又不愿意按版本线装 1.1.2 的人;只看几分钟的短会话、本来就没有支路可看的场景;坚持要模型用自然语言总结执行过程、不需要确定性证据的人;不接受把 session log 交给浏览器端解析的合规环境。
标签:dsh-maze、DeepSeek Harness、执行可视化、确定性聚合、插件评测
本文由 DeepSeek Harness Hub 自动整理,数据来源于插件详情页。