这是【DSH 工程哲学】系列的第五篇。我们在前面讨论了代码编写权让渡、决策记忆与分层门禁。但当进入复杂的工业级代码库时,开发者常会陷入另一种无力感:设计了优雅的分层架构与领域模型,Agent 却总能在数次迭代中,随手把裸字符串穿透到底层接口、随手跨层引入环状依赖、或者随意越权读写宿主文件。这一篇深入 DeepSeek Harness 架构设计的灵魂命题:为什么没有机械守卫的不变量不是架构,只是愿望?

在现代软件工程中,“架构设计”往往被误解为写在 Wiki 里漂亮的框线图和 UML 关系表。
许多技术 Leader 煞费苦心地向团队和 Agent 宣讲:
- “
SessionId和普通的string不能混用”; - “持久化存储格式只能单向向下兼容”;
- “子任务只能在授权的写域目录内修改文件,禁止越权污染其他代码”。
然而现实非常残酷。只要这些规则只存在于散文文档或口头警告中,大模型在面临复杂的上下文推理时,就会轻描淡写地破坏它们:在需要强类型的地方传入裸字符串、在没有迁移脚本的情况下偷偷修改持久化结构、或者为了“顺手修个小问题”直接把写操作渗透到了项目根目录之外。
在 DeepSeek Harness 源码库 的工程哲学中,“不变量(Invariant)”是系统的真正支柱,而任何愿望都必须被物理守卫铸造进代码本身。
一、建立心智:到底什么是“不变量”?
在深入复杂的工程实现前,我们必须先剥离掉“不变量(Invariant)”这个词的学术外壳。
用最平实的大白话讲:不变量就是系统演化与代码重构过程中,无论谁来改代码(人类还是 AI)、无论并发多高、无论上下文丢了多少次,都“绝对不可被打破的底层铁律与前提假设”。
在经典开发模式中,团队往往依赖资深工程师在脑子里“记住假设”;但 AI Agent 没有人类的默契与自觉,只要规则没有被物理拦截,假设在几轮会话后就必然失守:
- 业务身份不变量(不能把苹果当香蕉传):
如果把用户 ID 和订单 ID 都声明为普通的
string,Agent 在写getOrder(userId, orderId)时极易传反成getOrder(orderId, userId)。编译器默不作声,Bug 只有到了线上产生灾难数据时才会被发现。 - 持久化数据不变量(历史档案不可损毁): 存盘的历史会话 JSON 结构,如果不做版本锁定,Agent 在迭代新功能时顺手重命名了一个字段,成千上万老用户的历史记录当场无法解析。
- 权限边界不变量(改前台绝不能动后台): 给 Agent 交代“修复前台按钮样式”,它在顺手格式化代码时,把全局环境配置和测试断言也一并改了。
愿望 vs 不变量:
- 愿望(Wish):“希望模型不要把参数顺序搞反、不要动历史数据、不要乱改无关文件。”(写在提示词或文档里,脆弱不堪)
- 不变量(Invariant):“一旦参数传反,编译根本通不过;一旦格式不兼容,系统拒读并报警;一旦越权写入,操作系统内核直接强杀进程。”(由物理机制寸步不让地捍卫)
明确了这一心智,我们才能真正理解 DSH 整个架构设计的底层逻辑。
二、第一性原理:P8 不变量经济原理
在 DSH 的方法论体系中,衡量系统架构质量的尺度极为冷酷:
架构质量 ≈ Σ(不变量强度 × 捍卫者机械程度) ÷ 不变量数量。 没有机械捍卫者的不变量不是架构,只是一厢情愿。
这一定理揭示了两个反直觉的真相:
- 不变量不是越多越好:充斥着大量虚妄规则的系统,只会迅速腐烂为无法维护的泥潭;
- 规则的生命力取决于捍卫它的机械程度:一个仅靠 Code Review 人眼检查的不变量,其价值趋近于零;而一个被编译器静态类型、加载期拦截器或操作系统沙箱物理捍卫的不变量,才具备长久的抗熵增能力。
flowchart TD
subgraph Layers["DSH 捍卫层分布 (由轻到重)"]
L1["1. 编译期静态类型防御<br/>(Branded ID / 封闭联合体 / ts-expect-error 负样本)"]
L2["2. 依赖图与加载期拦截<br/>(单调 SCHEMA_VERSION / 禁止顶层 await / 跨包依赖门禁)"]
L3["3. 运行时系统级沙箱<br/>(Linux Landlock/bwrap / OS 级物理写域阻断)"]
L4["4. 语义层对抗 Review<br/>(正反校准样例 / ADR 决策记录)"]
end
Cost["验证与运行成本: 便宜 ────────────▶ 昂贵"]
Layers -.-> Cost
classDef guard fill:#2563eb,stroke:#1d4ed8,color:#ffffff
classDef bg fill:#f8fafc,stroke:#cbd5e1,color:#0f172a
class L1,L2,L3 guard
class L4 bg
三、四种铸造工艺:把愿望变成物理铁律
在支撑约 260 个 npm 包协同演化的代码库中,DSH 沉淀了四种标准的不变量铸造工艺:
1. 单一真源(Single Source of Truth)
“让状态产生分歧在结构上变得不可能(Divergence is structurally impossible)”。 在 DSH 的设计中,会话的事件日志(Session Event Log)是唯一的系统真源,界面的有序投影(Projection)、标题生成、乃至遥测数据,全部是从事件日志派生而来的只读纯函数视图。这一设计彻底消灭了“缓存状态与数据库状态不一致”的 Bug 类别,从源头上消除了 Bug 存在的物理空间。
2. 接缝三角色(Seam Triad)
任何核心能力接缝必须且只能由三个角色构成:
- 服务定义(Service Definition):公开的强类型契约;
- 提供者(Provider):实现该接口的具体后端;
- 消费者(Consumer):依赖该接口的业务代码。
关键约束:消费者绝对禁止直接 import 提供者包。通过包依赖门禁脚本(scripts/verify-package-dependencies.ts),任何跨过接缝直接依赖底层实现的引用,都会在编译与门禁阶段直接被退出码阻断。
3. 方向感知版本(Directional Schema Evolution)
在持久化状态层(packages/session),数据演进强制遵循单向递增的 SCHEMA_VERSION。
写入方定义主版本,读取方实现向后兼容。在 CI 门禁中,scripts/persistence-changes.ts 在每次提交前对所有导出的 TypeGraph 提取物理摘要,任何破坏单向版本兼容或未声明迁移的变更,直接中断编译并强行拒绝合入。
4. 类型印记(Branded ID):用编译器封死原始类型穿透
在前端或分布式系统中,开发者常习惯用裸 string 表达各类唯一标识符。然而在大模型生成代码时,极其容易把 ToolCallId 当作 SessionId 传给另一个函数,造成灾难性的串号事故。
在 DSH 源码包 packages/util/brand/src/index.ts 中,设计了一种零运行时开销的类型印记工具:
// DSH 真实的类型印记实现 (packages/util/brand/src/index.ts)
declare const BRAND: unique symbol
/** 携带编译期专属印记的强类型 string */
export type Branded<B extends string> = string & { readonly [BRAND]: B }
export function brandString<T extends Branded<string>>(value: string | T): T {
return value as T
}
定义了 type SessionId = Branded<'SessionId'> 后,任何裸字符串都无法直接赋值给该类型。大模型必须显式调用验证与转换函数;如果它试图胡乱传参,TypeScript 编译器会在第一时间直接报错,根本无需等待运行时爆炸。
四、系统级物理沙箱:机器维度的写域隔离
如果说类型系统是在代码层面设立守卫,那么**系统级沙箱(Sandbox Policy)**则是在操作系统底层架设防线。
在长链路 Agent 任务中,Agent 最致命的破坏是“越权文件修改”:原本只要求它修复某个前端组件,它却悄悄改动了全局的构建配置或破坏了测试断言。
DSH 在 packages/sandbox/sandbox-policy/ 与 packages/fs/fs-sandbox/ 中,推行了不可逾越的物理写域隔离(Write Scope Confinement):
- 任务执行前,声明式绑定当前步骤的授权目录前缀(
workspace-write); - 底层直接挂接 Linux 下的
bwrap/landlock以及 macOS 下的sandbox-exec; - 非零即一的硬阻断:任何越界的文件读取或写入,直接在系统内核层被操作系统当场下发
EPERM或SIGKILL掐断。
系统绝不把文件安全寄托在大模型对“请不要修改其他目录”这类提示词的自觉理解上,而是把防线筑在操作系统内核的物理调用点上。
五、从原理到实践:明天就能用上的落地动作
在日常中小型工程中,你无需立刻搭建复杂的操作系统沙箱,但可以通过以下三步铸造坚固的架构守卫:
- 废弃裸 String,引入最小 Branded ID:在项目的核心实体(如
UserId,OrderId,TaskId)中使用印记类型,消除由于大模型参数错位造成的无声隐患; - 给持久化数据打上单调 SCHEMA_VERSION:任何存盘 JSON 或数据库字段定义一个递增版本常量,加载时若版本不匹配立即抛出致命异常并拒绝读取,倒逼编写迁移脚本;
- 在根目录锁死跨层依赖:用简单的 ESLint 规则或自定义脚本,严格禁止业务层代码绕过接口层直接 import 底层数据库或网络提供方。
让架构有守卫,让愿望变铁律。 在 AI 全栈研发的新秩序中,顶级工程师的标志不再是能写多少代码,而是能在多大程度上用确定性的机械力量,将脆弱的架构不变量稳固地锁定在物理世界之中。
🛠️ 本课哲学的实证落地:作为 AI Coding 工程质量控制元框架,PonyGo 将不变量经济与机器守卫哲学作为核心支柱,通过标准化的架构不变量检查与自适应门禁(如
ponygo status与ponygo audit),帮助项目在演化中机械式捍卫系统底线。