<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>DeepSeek Harness on Trevor's Blog</title><link>http://hitrevor.com/tags/deepseek-harness/</link><description>Recent content in DeepSeek Harness on Trevor's Blog</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Thu, 12 Nov 2026 09:20:00 +0800</lastBuildDate><atom:link href="http://hitrevor.com/tags/deepseek-harness/index.xml" rel="self" type="application/rss+xml"/><item><title>DeepSeek Harness 的代码审阅：瓶颈根本不在 git</title><link>http://hitrevor.com/posts/dsh-worktree-review/</link><pubDate>Thu, 12 Nov 2026 09:20:00 +0800</pubDate><guid>http://hitrevor.com/posts/dsh-worktree-review/</guid><description>DeepSeek Harness 0.2.2-rc.2 加了按分支、提交、文件类型审阅。我在 21,711 个文件的仓库上把每一环量了一遍：建工作树 1.5 秒，28,458 行 diff 只要 75 毫秒，真正装不下的是三十万 token 的上下文。</description><content:encoded><![CDATA[<p>DeepSeek Harness 发了 0.2.2-rc.2，其中一条写着「Git Worktree 支持按分支、提交和文件类型审阅改动」。</p>
<p>我当晚就去升，结果 npm 上根本没有这个版本。</p>
<h2 id="三个地方三个版本号">三个地方三个版本号</h2>
<p>GitHub Releases 上是 dsh-v0.2.2-rc.2，11 日 11:33 发的。我去装，npm 报 notarget。</p>
<p>查了一下 dist-tags，latest 和 next 都还指着 0.2.2-rc.1。</p>
<p><img alt="三个位置，三个版本号" loading="lazy" src="/images/dsh-worktree-review/fig1.png"></p>
<p>桌面端更早，还停在 0.2.1-rc.2。也就是说我机器上同时躺着三个版本号，一个都没到 rc.2。</p>
<p>这不是 DeepSeek Harness 的毛病，发版流程都这样。但它决定了你什么时候能真的用上新功能：要么等 npm 追上，要么去桌面端切开发版渠道，而那个渠道本身就是 rc.2 里新加的。</p>
<h2 id="换个路子自己测">换个路子自己测</h2>
<p>装不上，我就把 DeepSeek Harness 这次要做的事在本机复刻一遍。</p>
<p>工作树、按分支比、按文件类型切，这些底层动作全是 git 命令，跟客户端无关。我用自己那个 21,711 个文件、60,037 次提交的仓库当靶子，旁边配一个 50 个文件的小仓库做对照。</p>
<p>先测最费时间的那一步：建工作树。</p>
<p><img alt="建工作树的耗时" loading="lazy" src="/images/dsh-worktree-review/fig2.png"></p>
<p>小仓库 32 毫秒，跑三次是 31、32、32。</p>
<p>大仓库 1.5 秒，三次 1.47、1.49、1.51，很稳。差了 46 倍。</p>
<p>工作树 checkout 出来占 275 MB，但 .git 是共享的，840 MB 那个仓库没被复制一遍。这点设计省了不少磁盘。</p>
<p>1.5 秒不算长，可如果 agent 每改一次代码就建一个工作树，中间还夹着网络往返、磁盘抖动和一堆看不见的等待，这个 1.5 秒就会变成一个随时可能超时的赌注。release notes 写道「放宽大型仓库创建工作树的等待时间」，说的就是这个 1.5 秒。</p>
<h2 id="三种审阅维度全是毫秒">三种审阅维度，全是毫秒</h2>
<p>我在工作树里造了两轮改动，模拟 agent 干活：40 个文件一轮，240 个文件一轮，累计对主分支 311 个文件、28,458 行。</p>
<p>然后按它说的三个维度各比一遍。</p>
<p><img alt="三种审阅维度的耗时" loading="lazy" src="/images/dsh-worktree-review/fig3.png"></p>
<p>按分支看统计，65 毫秒。全量正文，75 毫秒。按文件类型聚合，29 毫秒。按提交看日志，26 毫秒。</p>
<p>四个维度全在百毫秒以内，git 层面没有一处是慢的。</p>
<p>这里有个反直觉的地方。28,458 行、1.27 MB 的 diff，git 算出来只要 75 毫秒，我原本以为它会是大头，结果它是全场最快的那个。</p>
<h2 id="基线选错审的是空气">基线选错，审的是空气</h2>
<p>这里我踩了个坑，值得写出来。</p>
<p>第一次跑对比，我用的是 <code>git diff main...HEAD</code>。三个点，意思是拿两个分支的共同祖先比。结果输出 0 个文件。</p>
<p>原因很简单：我那个仓库的本地 main 早就落后，HEAD 本身就是 main 的一个祖先。共同祖先算出来是 HEAD 自己，自己跟自己比，当然是空的。</p>
<p>换成 <code>origin/main...HEAD</code>，立刻变成 311 个文件。</p>
<p>同一个仓库，同一个分支，只换基线，从 0 变成 311 个文件。</p>
<p>所以「按分支审阅」这件事，真正需要小心的不是 diff 慢不慢，是它到底在跟谁比。agent 的分支如果是从一个旧基线上拉出来的，你审出来的东西会少一大截，而且不会有任何提示。</p>
<p>三个点比共同祖先，两个点比两个端点。这个区别平时不重要，一旦交给 agent 自动审阅，就变成了能不能看见改动的分水岭。</p>
<h2 id="那-28458-行怎么读">那 28,458 行怎么读</h2>
<p>既然 git 不慢，慢的必然是别处。把 diff 按扩展名拆开，答案就浮出来了。</p>
<p><img alt="改动按文件类型的分布" loading="lazy" src="/images/dsh-worktree-review/fig4.png"></p>
<p>Python 187 个文件、12,468 行，占 43%。JSON 52 个文件、5,690 行，占 20%。TypeScript 46 个文件、2,647 行。TSX 12 个文件、1,526 行。</p>
<p>有意思的是 JSON 那 5,690 行。锁文件、契约快照、配置导出，占了五分之一的行数，但真正要逐行读的不到百分之五。</p>
<p>按文件类型审阅这件事，价值不在于分类好看，在于它让你有理由跳过一整个 5,690 行的文件夹。</p>
<h2 id="工作树省的不是磁盘">工作树省的不是磁盘</h2>
<p>我原本以为工作树会占很多盘，实测下来这个担心多余。</p>
<p>21,711 个文件、840 MB 的 .git，建出来的工作树只占 275 MB。因为 .git 是共享的，复制出去的只有工作区文件。</p>
<p>这 275 MB 买到的是一份隔离：同一个仓库里可以有多个工作树，各自挂在不同的分支上，互不干扰。agent A 在 feat-a 上改代码，agent B 在 feat-b 上改另一处，两边的工作区和索引都是各自独立的。</p>
<p>换成沙盒或者整个仓库副本，你要付的是 840 MB 的磁盘加几十秒的拷贝时间，而工作树付的只是 1.5 秒，还顺带把分支隔离这件事免费送给了你。</p>
<p>这也是它把审阅做在工作树上的原因。分支在那儿，提交在那儿，文件也在那儿，按哪个维度切都是现成的原料。</p>
<h2 id="瓶颈在上下文不在工具">瓶颈在上下文，不在工具</h2>
<p>把每一环的数字摆在一起，结论就很清楚。</p>
<p><img alt="每一环的量级" loading="lazy" src="/images/dsh-worktree-review/fig5.png"></p>
<p>建工作树 1.5 秒。产出 diff 75 毫秒。</p>
<p>把这份 diff 交给模型，1,268,059 个字符，粗算三十万 token。</p>
<p>三十万 token 是什么概念？现在主流模型的上下文窗口在二十万上下，这一个改动的 diff 就装不下，还没算上仓库结构、任务描述和你的提问。</p>
<p>所以 rc.2 那句「减少查看大型改动时的卡顿」，官方描述指出卡的不是 git，是把这堆东西渲染出来、送进模型、再让人读的那一层。前面几个毫秒级的数字再怎么优化都没用，因为真正的天花板在这里。</p>
<p>按文件类型、按提交、按分支，这三条路径本质上是三种切法。切得动，模型才读得完。</p>
<h2 id="另一条我还没试的">另一条我还没试的</h2>
<p>rc.2 还加了两件事：SubAgent 支持具名与多层协作，AgentTeam 可以按会话开启，共用成员和任务面板。</p>
<p>这个我没法在本机复刻，因为它不是 git 层面的事，是编排层的事。而且 npm 上装不到 rc.2，我手上只有 rc.1，跑出来也不是 rc.2 的行为。</p>
<p>所以我只写我验过的部分。这条留给能用上的人。</p>
<h2 id="你现在可以做的">你现在可以做的</h2>
<p>如果你的 agent 已经开始在分支上干活，有两件事现在就能改。一是给工作树准备一块快的盘，1.5 秒里大半是磁盘 IO，放在机械盘或者网络盘上会更慢。</p>
<p>二是先看统计再看正文。312 行和 28,458 行之间差 90 倍，先读前者，能过滤掉一半不需要看的文件。</p>
<p>至于 DeepSeek Harness 的 rc.2，等 npm 追上就行。装上之后第一件事建议是拿自己最大的那个仓库跑一遍建工作树，看看你那台机器上是 1.5 秒还是 15 秒。</p>
<p>这个数字决定了你以后要不要让它频繁开分支，也决定了你的流水线里能不能跑多个 agent 并行改同一份代码。一台机器上 1.5 秒和 15 秒的差别，最终会变成流水线里「三个 agent 一起跑」还是「老实一个一个来」这样两种完全不同的架构选择。</p>
]]></content:encoded></item><item><title>升级 DeepSeek Harness 后，插件全被禁用</title><link>http://hitrevor.com/posts/dsh-022/</link><pubDate>Thu, 29 Oct 2026 07:52:35 +0800</pubDate><guid>http://hitrevor.com/posts/dsh-022/</guid><description>npm 上还没更新的版本，得把版本号写死才装得到。装完三个插件当场被拒载，不是 bug，是精确版本锁在起作用。</description><content:encoded><![CDATA[<p>昨晚把本机的 DeepSeek Harness 从 0.2.1-rc.2 升到 0.2.2-alpha.2，16 秒装完。</p>
<p>有个前提得先说清楚。这个版本 npm 上还没更新到最新，直接装装出来的还是 0.2.1-rc.2，得手动把版本号写死才行。</p>
<pre tabindex="0"><code>npm install -g @deepseek-ai/dsh@0.2.2-alpha.2
</code></pre><p>少写这一段版本号，后面说的所有东西你都看不到。</p>
<p>启动之后，问题来了。日志里连着刷了三行 <code>disabling profile plugin row</code>，我装的东西被拿掉了三个。</p>
<p>装的时候 npm 还提了个醒，五个包的 install scripts 被拦了，包括 node-pty 和 koffi 这两个原生模块。我盯着看了会儿，还是先启动试了，web 界面能开，模型列表能拉，暂时没看出影响。这条先记着，后面要是哪里不对再回头查。</p>
<h2 id="升级完第一眼就撞上这三行">升级完第一眼就撞上这三行</h2>
<p>日志原文是这样的。</p>
<pre tabindex="0"><code>dsh: disabling profile plugin row &#34;plugin-market&#34;:
  Plugin @deepseek-ai/dsh-plugin-market@0.2.1-rc.2
  is incompatible with dsh 0.2.2-alpha.2:
  requirements {&#34;@deepseek-ai/dsh-plugin-manager&#34;:&#34;0.2.1-rc.2&#34;,
                &#34;@deepseek-ai/dsh-settings&#34;:&#34;0.2.1-rc.2&#34;,
                &#34;@deepseek-ai/dsh-tools&#34;:&#34;0.2.1-rc.2&#34;,
                &#34;@deepseek-ai/dsh-typert-protocol&#34;:&#34;0.2.1-rc.2&#34;}
</code></pre><p>被禁的三个是 <code>ui-agent-team</code>、<code>plugin-market</code>、<code>tool-plugin-market</code>。后两个其实是同一个包，被两行不同的配置引用了。</p>
<p>关键在 requirements 那一串。它写的是 <code>&quot;0.2.1-rc.2&quot;</code>，没有脱字符，没有波浪号，就是精确的四个版本号。而运行时的那四个内部包已经升到 0.2.2-alpha.2 了。</p>
<p>精确匹配失败，插件被拒载。DeepSeek Harness 的处理很干脆，不加载也不报错，只打一行警告继续跑下去。</p>
<p>这个设计其实是对的。让一个声明「我只在这些版本上测过」的插件硬跑在新 runtime 上，崩起来更难查。拒载比带病加载好。</p>
<p>只是对用户来说，代价是升个版本，装的东西消失，而且只是警告不是错误，很容易漏看。</p>
<h2 id="连带塌方插件市场读不到索引">连带塌方，插件市场读不到索引</h2>
<p>我装过自定义插件索引，配置在 <code>~/.dsh/profiles/web/cordis.patch.yml</code> 第 12 行，指向本地一个静态服务。</p>
<p>升级后点进 Plugins → Discover，红字一行：</p>
<blockquote>
<p>Could not read the index sources.</p>
</blockquote>
<p>旁边挂着个 Retry，点了还是这行。</p>
<p><img loading="lazy" src="/images/dsh-022/05-discover-failed.png"></p>
<p>排查时我先看的是那个静态服务，<code>lsof -iTCP:3489</code> 果然是空的，服务早就挂了。我以为这就是全部原因，把服务拉起来，<code>curl</code> 返回 200，3764 字节的 index.json 躺在那儿。</p>
<p>回浏览器点 Retry，同一行红字。</p>
<p>回浏览器点 Retry 还是那行红字，这才反应过来读索引这个动作本身就是 plugin-market 干的。索引源通了，读的人不在，页面照样空。</p>
<p>所以这里其实压着两层，表面是索引源没起，根因是读索引的插件被禁用了。</p>
<p>顺手踩到一个自己的坑，记一下。那个复现用的 <code>serve.py</code> 把访问日志硬编码到 <code>/tmp/market/access.log</code>，目录被我清过，不存在。每个请求一进来就抛异常，<code>curl</code> 返回的是 exit 52，空回复。把目录建出来，请求才恢复正常。</p>
<h2 id="修它有官方开关藏在报错文案里">修它有官方开关，藏在报错文案里</h2>
<p>那三行警告的末尾其实给了办法，说可以用 <code>dsh plugin allow-version</code> 这个命令，或者走插件管理器，给一个精确版本豁免。</p>
<p>我先敲了一遍帮助，DeepSeek Harness 的插件子命令说明里根本没提这个用法，只说剩余参数会转发给 pnpm。</p>
<p>直接试，用法自己跳出来了：</p>
<pre tabindex="0"><code>dsh: Error: usage: dsh plugin allow-version &lt;package@version&gt;
                   --dsh-version &lt;exact&gt; --accept-risk
</code></pre><p>按这个补全，两个插件各豁免一次：</p>
<pre tabindex="0"><code>$ dsh plugin --profile web allow-version \
    &#34;@deepseek-ai/dsh-plugin-market@0.2.1-rc.2&#34; \
    --dsh-version 0.2.2-alpha.2 --accept-risk
dsh: allowed @deepseek-ai/dsh-plugin-market@0.2.1-rc.2 for DSH 0.2.2-alpha.2
</code></pre><p>豁免精确到包和版本，换个版本得重新给一次。重启 DeepSeek Harness 之后，那三行警告从日志里消失了，Discover 立刻能读到索引，两个插件正常列出来，分类和标签筛选也都在。</p>
<p><img loading="lazy" src="/images/dsh-022/06-discover-fixed.png"></p>
<p>补一句，<code>--accept-risk</code> 这四个字是认真的。我这次运气好，插件跑起来没出事，但不保证。</p>
<h2 id="新界面长什么样">新界面长什么样</h2>
<p><img loading="lazy" src="/images/dsh-022/02-plugins-page.png"></p>
<p>插件页现在是 Installed 和 Discover 两栏。Installed 里分成上下两段。</p>
<p>上面一段叫 Built-in plugin settings，四条。Subagent 管递归深度、数量和模型。Web search 管 DeepSeek 搜索源的配置。Agent loop 控制 agent 怎么派发工具调用。Shell 限制单条命令能跑多久、能吐多少输出。</p>
<p>下面一段叫 Experimental plugins，五条，各带一个开关：</p>
<p>Agent teams 让 agent 把活拆给具名队友，共享一块任务板，再把结果报回来。</p>
<p>Voice input 用 SenseVoice 在本机转录，首次使用要先装依赖。</p>
<p>Custom plugin indexes 就是给 Plugins 加 Discover 那一栏的，从你加的索引源里浏览和安装。</p>
<p>Auto authorization review 是新增的审核模式，每次工具调用前先让模型对着你原本的要求过一遍，合规的批量放行。</p>
<p>Change requests &amp; worktrees 追踪每个会话的变更请求和它的检查、评审结果，还能让新会话直接在 Git worktree 里起。</p>
<p>这五条里前两条默认开着，后三条默认关。</p>
<h2 id="插件页上真变了的两处">插件页上真变了的两处</h2>
<p>绕完这一圈，回头看清这次升级到底给了什么。</p>
<p>插件详情页现在直接渲染包自带的 README。点进某个实验性插件，看到的是完整的文档，带 English 和中文切换、Summary、目录，往下还有一段叫 Use this package。</p>
<p>更有意思的是同一个页面把那个 bundle 拆成了 5 个 component 逐个列出来，每个一行，带图标、一句话说明、短名、完整包名，右边一个独立的开关。</p>
<p>比如 Change requests &amp; worktrees 这个包，展开是五个部分。</p>
<p>Change requests、GitHub change requests、Session change requests、Worktree service、Change request panel。页面顶部写着 <code>Components 5 total · 5 off</code>。</p>
<p>底部还标了来源，Code source 是 Built in，当前版本 0.2.2-alpha.2。</p>
<p><img loading="lazy" src="/images/dsh-022/04-plugin-components.png"></p>
<p>这比过去那种「一个插件一个开关」清楚太多。一个 bundle 里各部分能查、能单独开关，装了什么不用去翻配置文件。</p>
<h2 id="我的一点看法">我的一点看法</h2>
<p>这次经历最有意思的地方不是那个坑，而是它暴露的设计取舍。</p>
<p>精确版本锁让插件生态安全，代价是每次 runtime 升级都可能批量失效。alpha 和 rc 之间尤其明显，几个内部包一升，所有声明依赖它们的插件全部掉线。</p>
<p>DeepSeek Harness 给了豁免开关，但默认路径是拒载。它赌的是「宁可少加载，不要带病跑」。</p>
<p>对做插件的人，这意味着每跟一次 runtime 版本，都要重新发一次版本声明。对用插件的人，这意味着升级前得知道自己装了什么，不然升级后连哪里少了都未必看得出来。</p>
<p>DeepSeek 官方在 0.2.2-alpha.2 的发布说明里还写了一条，说插件热更新失败会尝试恢复旧版本。这个机制救的是运行中的更新，救不了启动前的版本检查，两套逻辑互不相干。</p>
<p>这版还列了几个我没验的：subagent_oar 能把独立任务交给本机的 Codex 或 Claude CLI 去跑，开发者工具那个统计插件能按轮次看上下文、缓存、模型和工具耗时。前者听着最有意思，但界面上没找到入口，估计要单独装，我没动。热更新失败回滚那条也一样，官方口径，我没构造出失败场景。</p>
<p>你升级工具链之前会先看一眼自己装了哪些插件吗？还是跟我一样，升完才发现东西没了。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li>DeepSeek Harness v0.2.2-alpha.2 发布说明：https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.2.2-alpha.2</li>
<li>本机实测环境：macOS arm64，DeepSeek Harness 由 0.2.1-rc.2 直升 0.2.2-alpha.2，npm 全局安装</li>
</ul>
]]></content:encoded></item></channel></rss>