DeepSeek Harness Hub
← 返回列表

源码审计对照DylanMerigaud/dsh-internals

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

逐条核对文档与代码,标出不一致之处

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/8/19 · 已提供中文文档

DeepSeek Harness 的源码级审计:文档与代码不一致之处。270 条经机器验证的引用,固定于 v0.1.0-rc.7。

综合分
27.9
GitHub 分
27.9
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add DylanMerigaud/dsh-internals
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-internals

对 DeepSeek Harness(DSH)的源码级审计,
核对文档所声称的内容与代码实际行为是否一致。

固定于提交 99f6f02
(v0.1.0-rc.7,2026-08-17)。下文每一项论断都带有 path:line 引用。本仓库中的全部 270 条引用
均已机器校验:文件存在,且行号在范围内。

这不是又一篇“什么是 DeepSeek Harness”的说明文。那种文章已经存在。本文问的是一个更窄、
且需要阅读源码才能回答的问题:文档与代码在哪里不一致,哪些只是约定而非强制?

摘要

DSH 是一个严肃的代码库。它发布的测试代码多于源代码,其架构文档大体准确,其 vendor 日志
对自身分歧的坦诚程度也非同寻常。以下发现并非拆台。它们只是那些——若读者轻信宣传口径,
就会建立在代码并不支持的假设之上的地方。

| # | 常见表述 | 源码所显示的 |
|---|---|---|
| 1 | “一切皆插件”,“没有需要打补丁的特权核心” | 对产品层成立,对引导层不成立。五个核心服务和三个加载器插件是硬编码的。 |
| 2 | 运行时上下文快照会取代更早的快照 | 任何地方都未强制。这只是提示词中的一句话,请求模型遵守。 |
| 3 | Claude Code 和 Codex 作为子代理运行 | 真实、可用的代码。但默认以禁用状态发布,且未记录文档。 |
| 4 | “每次运行都可追踪” | 进程内成立。进程外子代理完全没有会话,其成本数据被明确丢弃。 |
| 5 | 委派深度有上限(maxDepth,默认 3) | 该上限无法在任何进程外提供者上设置。DSH 套 DSH 的链式调用每一跳都会把深度重置为 0。 |
| 6 | 沙箱模式约束代理 | 它们约束的是写入。读取、网络和进程可见性不受约束,这是明确的设计。 |
| 7 | 压缩释放上下文 | 它只是遮蔽,从不删除。原始内容仍留在日志中,且可按 seq 恢复。 |

1. 核心很小,但并非不存在

docs/architecture.md:13 称“没有需要打补丁的特权核心”。但确实有一个,而且它是结构性的,
而非偶然的。

Context 在其构造函数中直接构建五个服务,完全不涉及注册表:

// vendor/cordis/src/context.ts:77-81
this.fiber    = new Fiber(self, {}, Object.create(null), null, () => [])
this.reflect  = new ReflectService(self)
this.registry = new RegistryService(self)
this.events   = new EventsService(self)
this.logger   = new LoggerService(self)

使配置驱动加载成为可能的三个插件(Loader、Include、Group)在
packages/boot/app-boot/src/index.ts:15-16,492,510,771 处被静态导入并硬编码挂载。这是
一个先有鸡还是先有蛋的约束,而非疏忽:Loader 读取 cordis.yml,因此 Loader 自身无法
作为 cordis.yml 中的一行。

DSH 自身的内部文档比其公开文档更为准确。docs/i18n/style-samples.md:9
称其为“刻意精简的核心”,这是正确的。

该说法成立之处。 agent 循环确实可替换。core/agent 将
AgentFactory 定义为一个接口,通过 AgentRegistry.setFactory
(packages/core/agent/src/index.ts:176-181)填充,专门是为了让使用方永远不必导入具体的
包。经全面排查验证:唯一直接导入 @deepseek-ai/dsh-agent-loop
的已发布 TypeScript 源码是一个演示(packages/examples/agent-spine-demo/src/index.ts:36)。有四个包列出了它,
但仅作为 devDependencies。唯一真正的运行时耦合是 python/sdk-runtime,它
将其声明为生产依赖。

2. Cordis 是内嵌的,而非依赖的

根 package.json 有零个生产依赖。整个 Cordis 技术栈以源码形式内嵌
于 vendor/ 之下(cordis、cosmokit、hmr、loader、schemastery、timer、group、
logger-console、include),并以 @deepseek-ai/ 作用域重新发布,这在
vendor/README.md 中声明是为了让该 harness “完全拥有其框架层”。

vendor 日志记录了与上游 cordiverse/cordis 的 18 处明确分歧,包括
手工移植的可重入释放加固,以及一个手工回移的上游 PR(#41),该 PR 晚于
所固定的版本。

因此,“构建于 Cordis 之上”意味着构建于 Cordis 的一个受控分支之上。这一区别对任何
计划跟进上游的人来说都很重要。

3. 快照取代是文字说明,而非机制

类型词汇是真实存在的,并且确实比同类 harness 所记录的更多。两个独立的
维度存在于 packages/llm/llm/src/message.ts 中:MessageSource.kind 回答谁产生了一条消息
(user、plugin 加插件名、model、tool),而 ContextForm 回答它是什么
(instructions、catalog、snapshot、notice、relay、recall)。

文档注释指出,来自同一生产者的后续快照会取代先前的快照。该
行为并未实现。它只是一个字符串:

// packages/core/system-prompt/src/index.ts:239
return Current runtime context. This snapshot supersedes earlier
runtime-context snapshots.\n\n${body}

agent 循环发出的每个 surfaceOp 都是 'append'。replace 操作存在
(packages/core/session/src/surface.ts:64-68),并且可以强制执行取代,但它仅
连接到压缩和工具结果修剪。所有三个真实的快照生产者(核心 runtime-context、
time-context、tmux-context)都会针对自己最后发出的文本进行去重,以避免重新发送
未更改的内容。没有一个会移除、替换或隐藏先前的快照。

对同一模型的另外两个限制:

- 编译器仅对内置的 plugin 类型强制执行形式到字段的契约。其他七个
生产者类型(agent-instructions、session-reference、skill-catalog、coordinator、
subagent-settled 等)按约定复用 form 字符串来声明扁平接口。
TypeScript 无法对其中任何一个强制实施“快照需要 sections”。
- 压缩会抹平来源信息。其检查点消息携带
source: {kind:'plugin', plugin:'dsh-compaction-basic'},完全没有 form 字段
(packages/compaction/compaction-basic/src/summarizer.ts:150),而且替换会遮蔽整个
先前区域,无论其中包含哪些 form。

4. Claude Code 和 Codex:真实存在、被禁用、未记录

那个被广泛重复的说法——你可以把 Codex 或 Claude Code 作为子代理接入——在代码
层面是真的。这些是真实的包,带有真实的依赖(@anthropic-ai/claude-agent-sdk@0.3.220、
@openai/codex@0.147.0,见 packages/subagent/subagent-claude-code/package.json:29-33 和
subagent-codex/package.json:39),它们会启动实际的 SDK 和 CLI。

它们默认并不启用。它们被一项有记录的决策排除在 @deepseek-ai/dsh-base 包之外
(.agents/notes/implemented/simplification/2026-08-12-production-dsh-excludes-product-subagent-providers.md),
并且每个随附的 agent 预设都把这些行标记为 disabled: true,并附有注释“Production dsh
does not install these optional providers”
(apps/cli/config/agent-presets/standard/agent.cordis.yml:201-217)。

README 和面向用户的 provider 指南都没有提到这些。安装 dsh 的用户
得不到其中任何内容,也完全不会被告知。

相关且以同样方式定论的是:没有 Ollama 专属支持(grep -rn ollama 返回
零命中)。本地模型通过通用的 OpenAI 兼容路径工作
(packages/llm/llm-pi-ai/src/provider.ts:47-51),而若干第三方文章将其报道为
一项具名功能。MCP 仅限客户端,没有服务端(packages/mcp/README.md:7-9)。Token 核算
统计 token 并跟踪缓存 token,但从不转换为货币
(packages/llm/llm-pi-ai/src/catalog.ts:28-32)。

5. 可追溯性止步于进程边界

仅追加的事件日志才是这里真正的资产。44 种事件类型
(packages/core/session/src/known-event-types.ts),每个会话一个 JSONL 文件,一个头部携带
parentSession、origin: 'subagent'、delegationDepth 和 agentPreset。

进程内子级(fork、spawn)是真实会话,带有每步的 TokenUsage,因此调用方可以
汇总其成本。harness 本身不执行任何汇总:listChildren() 和 subagent/end
都不携带成本字段。

进程外子级则是另一回事。四个 provider(claude-code、codex、
acp、dsh-sdk)中没有一个曾调用 ctx.agents.create 或 resume,因此不存在可供读取的会话。具体到
claude-code,SDK 是以 persistSession: false 打开的,而 consumeClaudeQuery
(packages/subagent/subagent-claude-code/src/run.ts:112-124)只从
SDKResultMessage 读取最终文本,丢弃了 SDK 报告的成本和用量。

这些数据不仅仅是没有被聚合。它们是被读取后直接丢弃了。
6. 委托深度在 DSH 嵌套 DSH 的跳转中不受限制

tool-subagent 接受一个数值型 maxDepth(默认值为 3),但只有声明了 depthLimit 能力的提供方才能强制执行它。在不具备该能力的提供方上挂载数值上限会在配置时抛出异常:

tool-subagent: provider "X" cannot enforce maxDepth (no depthLimit capability),
set maxDepth: 'provider-managed' to leave the recursion budget to the provider
(packages/subagent/tool-subagent/src/index.ts:286-291)

packages/subagent/subagent/src/out-of-process.ts:27 将 depthLimit: false 设为所有进程外提供方的共享默认值。进程内的 fork 和 spawn 都将其设为 true。

subagent-dsh-sdk 会作为子进程启动一个完整的第二个 DSH 运行时,而 delegationDepth 在该包中从未出现,因此它不会跨进程传递。每个子会话的深度都从 0 开始。

这是一个有文档记录的设计选择,错误信息也坦率地表明将预算交给提供方。但其后果没有文档记录:DSH 嵌套 DSH 的委托链仅受操作系统限制约束,别无其他。

7. 沙箱意味着写入限制

这种限制是真实的操作系统级机制(bwrap、Landlock、Seatbelt、ACL),并且在不可用时默认拒绝。但它覆盖的范围比这个词所暗示的要窄。

// packages/fs/fs-sandbox/src/index.ts:8-9
Reads pass through untouched: every mode permits reading.

macOS Seatbelt 配置文件实际上就是 (allow default) (deny file-write) 加上可写根目录(packages/sandbox/sandbox-local/src/profiles.ts:47-54)。“只读模式”意味着任何地方都不能写入,而不是限制可见性。网络和进程可见性完全不在沙箱的语义范围内(packages/sandbox/sandbox/src/index.ts:26)。

源码明确指出,文件系统围栏是“在受信任代码中对模型控制的路径进行策略检查,而非内核边界”,并将不受信任代码的内核级隔离委托给 dsh-bash-sandbox。这是一个刻意的两层设计,将其报告为草率是错误的。发现仅在于此处的“沙箱”并不符合大多数读者的假设。

同一代码库中两个相反的失败默认值,且都是有意为之。 一个崩溃、缺失或超时(默认 10 分钟)的钩子会产生非阻塞错误,然后该轮次继续执行(packages/hooks/hook-protocol/src/runner.ts:82-96)。审批接缝则相反:任何缺失、抛出异常或格式错误的应答者都会被规范化为 'unavailable',调用方将其视为拒绝(packages/interaction/user-approval/src/index.ts:301-337)。在依赖钩子作为护栏之前,这一点值得了解。

一个已退役的安全基线。 packages/session/session-persistence-jsonl/src/format.ts:71-74 会对任何携带 sandboxMode 或 approvalPolicy 头字段的日志主动抛出异常,称它们为“已退役的策略基线字段”。这些字段曾是在会话开始时固定的不可变每会话限制级别,
创建。替换项,即 approval/policy 和 sandbox/mode 事件,在会话中途可被任何能够追加到日志的东西修改。

8. 压缩产生遮蔽,而非删除

压缩会追加一条携带 surfaceOp: {op:'replace', start, end} 的 user/message
(packages/compaction/compaction-basic/src/region.ts:462-465),该操作将被遮蔽的序列号从模型可见的排序中拼接移除。原始事件永久保留在仅追加日志中,并可按 seq 恢复。剪枝器自身的字段名为 originalSeq。

可见表面是日志之上的一个投影,而非日志本身。这颠覆了从那些压缩是有损的 harness 中沿袭而来的假设。

文档做对的地方

可信度要求如实说明。上下文溯源审计在 docs/ 中未发现文档与源码之间的矛盾:system-prompt.md、compaction.md 以及 agent-instructions 的 README 都与源码精确吻合。该领域的缺口是遗漏,而非错误陈述。崩溃恢复设计细致且分层,能容忍撕裂的尾部或序列缺口,但当 turn/end 出现在空洞之后时会硬性抛出,因为那会静默地重建出一个错误的会话。vendor/README.md 对其自身差异的坦诚程度,超过大多数 vendored 依赖所能做到的。

规模

| 指标 | 数值 |
|---|---|
| 工作区包 | 239 个,分属 47 个家族 |
| TypeScript 文件 | 2,589 个(1,508 个源码,1,081 个测试) |
| 测试与源码 LOC 之比 | 介于 1.0 与 1.2 之间,取决于共享的 test-support/ 是否计入测试 |
| 测试文件 | 697 个 .spec.ts,129 个 .e2e.ts,6 个 vitest 配置 |
| 文档 | 217 个文件,111 个英文和 106 个中文,所有包 README 均为双语 |
| 根依赖 | 0 个生产依赖,36 个开发依赖,9 个 vendored,1 个补丁(node-pty) |
| 标记 | 66 个 TODO / FIXME / HACK |

测试与源码之比被刻意给出为一个范围。它取决于分类器,给出单一精确数字会是虚假的精确。

未验证

公开保留而非丢弃:

- compaction/prune 和 compaction/summary 的“必须紧邻其替换事件之前”这一契约是否在运行时被强制执行。未找到断言。
- SQLite 后端的 commitRepair 是否会为撕裂的尾部发出物理 DELETE。
- 第三方 pi-ai 包的内部实现,该包未在克隆中 vendored。
- 调用 session-reference 的命令层和宿主层,未追踪。

方法

参见 METHOD.md。各领域的发现见 findings/。

许可证

发现与文字:CC BY 4.0。引用的代码摘录仍遵循 DeepSeek Harness 许可证(MIT)。

这是一份独立审计。它与 DeepSeek 无关联,也未获其认可。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入 DPharness 群聊

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群