DSHarness 系统拆解 固定基线 47f943859b · 36 已复核 / 0 撰写中 / 36 章
English
导论·第 02 章

设计哲学总论

Everything is a plugin 背后的运行时观

已复核上游 47f943859b范围: 分析可替换核心、可逆副作用、组合优先、显式边界和事件溯源。

结论:可替换性来自更严格的交互规则

“一切皆插件”并不意味着任何组件都可以随意行动。DeepSeek Harness 把约束集中到少数协议——具名 service、typed event mode、effect 所有权、scope 路由、append-only 事实、显式提交点和包自有运行时不变量——以此换取具体实现的可替换性。

它把固定中心从具体类迁移到了交互规则。启动组合、Agent 生命周期、Turn / Step Loop、工具、prompt contributor、provider、持久化和 UI projection 都围绕这一选择展开。

1. “没有特权核心”不等于“没有架构骨架”

官方架构

模型 adapter、工具 registry、session log 和 Agent Loop 都作为 Cordis 插件挂载;相邻插件无需修改某个特权 Application 对象即可贡献或替换行为,其注册项也会随插件卸载而撤销。ARCH-PLUGIN-CORE

但系统仍然有骨架:公共 service key、interface、event 名称和 mode、session event 词汇、scope 规则,以及配置 entry identity。替换 provider 并不会消除这些义务。

可替换实现仍需遵守的协议这一区分为何重要
LLM providerAdapter 注册、请求/流式词汇、错误和 usage 归一化Loop 必须通过同一稳定 seam 消费所有 provider
ToolDefinition、schema、受控执行、耐久 call/result event策略和 replay 不能依赖工具私有实现
Agent driverAgent interface、registry 生命周期、inbox 与 session 事实产品 surface 无需导入默认 Loop 就能驱动 Agent
Persistence backendSession header 与 event-log 语义重载历史必须与 live 历史表达同一事实
设计评价

“无特权核心”描述的是实现权力,而非不存在宪法。真正的核心是协议;只有替代实现继续满足消费者依赖的义务,插件替换才成立。

2. 五种组合原语取代中央 Application 类

框架语义

Cordis 提供五种反复出现的机制:plugin 实现 Service 生命周期;context 通过稳定 key 暴露 service;inject 声明可用性依赖;typed event 选择观察或拦截语义;effect/on 把贡献与 teardown 绑定。DESIGN-CORDIS-SEMANTICS

原语架构职责误用后的失败
Service key把能力定义和 provider 分开消费者直接导入具体 provider,使配置替换沦为表面形式
inject不依赖 YAML row 顺序地表达所需拓扑插件看到缺失服务,或发明静默 fallback
Typed event让策略、adapter 和 observer 无需导入 orchestrator 即可挂接事件 mode 与调用方期望分裂
Waterfall以显式 next() 委托形成 around middleware观察者意外短路决策链
Effect让注册与撤销成为同一条受管生命周期HMR 或 session disposal 泄漏陈旧 provider、tool 或 listener

emitparallelserialwaterfall 不是风格差异。等待方式、顺序、返回值与短路语义各不相同;选择 mode 就是在规定谁能够影响该操作。

3. 注册项是有所有者的资源,不是全局变更

仓库规则

Prompt section、tool definition、adapter、provider 与 event listener 都以可逆 effect 注册;registry 的 register() 返回精确 disposer,HMR safety 测试还必须证明 owner fiber dispose 后贡献确实消失。ROOT-EFFECTSPKG-INVARIANTS

生产实现

ScopedLayers 让注册 context 同时承载两层含义:哪一个 scope 可以看到该贡献,以及哪个 effect 对其生命周期负责。全局项依次被祖先与最近 scope 叠加;undo 只删除这一笔注册,并回收已经为空的 layer。DESIGN-SCOPED-LAYERS

行为测试

Scope 测试验证同步可用性、重复 dispose 的共享 quiescence、反向清理顺序、按 key 路由的事件可见性,以及单向继承:后代 dispatch 可以到达祖先 scope listener,祖先 dispatch 不会向后代泄漏。DESIGN-SCOPE-TEST

机制推导

这既是依赖注入,也是资源账本。插件从哪个 context 做出贡献,就同时记录了该贡献的可达范围和清理责任;正是这种耦合,让在线配置和 per-Agent composition 无需另建一份全局清理 registry。

4. 耐久事实与 live 决策分处两个平面

平面例子生命周期用途
Durable session eventsturn/start、message、request header、chunk、tool call/result、turn/end跨 reload 与 persistence 存活对话事实、重建、replay、projection
Live Agent eventsagent/pre-stepagent/request、request-error recovery、stopping单个活跃进程与 scoped runtime拦截、策略、路由、控制
Capability eventsTool、filesystem、telemetry 与 provider hooksProvider/plugin 生命周期无需耦合 Loop 即可附加策略
事实源规则

Session log 是模型历史的事实源。任何进入模型请求的内容都必须可以从日志重建,因此 model-visible input 需要 session event,不能只存在于短命 callback mutation 中。ARCH-LOGROOT-MODEL-LOGGED

可执行校验

默认 Loop 会标记自己的 request,并安装运行时不变量:从 session log 独立派生 messages 和折叠 request header,再与即将 dispatch 的 request 比较。LOOP-REQUEST-INVARIANT

设计评价

这里是选择性事件溯源。耐久流记录具有对话语义的事实,而不是把每个 live callback、registry mutation 或进程细节都写入日志;系统避免把 event log 变成整个 runtime 的转储,同时保住必须可复现的投影——模型究竟看到了什么。

5. 提交点把准备态与发布态分开

全包设计纪律

仓库规则要求一个异步操作只有一个生命周期 owner;成功之前不能发布 derived state;限制必须在完整值已经确定的位置执行;每个 runtime invariant 由拥有该关系的 package 负责。DESIGN-PACKAGE-RULES

已经核实的运行时章节在不同尺度上重复同一种结构:

1

Boot

组合并准备候选树;只有 Loader settle 与 activation audit 通过才返回。

2

Agent creation

在不可见状态构建 Session、Agent 与 scoped world;同步 commit setup;再按固定顺序 enter/announce registry。

3

Inbox mutation

先 append durable splice,再改变 live queue projection。

4

Turn execution

dispatch 前写入边界与 request input;下一次 derived request 前提交 assistant 与 tool outcome。

机制推导

反复出现的状态机是 prepare → validate → commit → publish → dispose。提交产物可以是 Loader tree、registry entry 或 session event,但下游消费者都被刻意隔离在仍可能失败的候选状态之外。

6. 一项能力必须形成三角色 seam

官方架构

完整 capability seam 包含 Service Definition、至少一个 Service Provider 和 Consumer。只有 provider 不是产品能力;只有 tool 或 UI consumer 也不是可替换抽象。ARCH-LOG

角色应该知道什么不应该拥有
Definition全部当前 consumer 共同需要的操作与义务某个 provider 的部署细节或某个 UI 的词汇
Provider外部 API/process/storage 细节和 provider-local config替换 provider 后仍需存在的 model-facing 产品策略
Consumer能力如何呈现给 model、user、API 或 orchestrator对单一 provider 实现的隐含假设
设计评价

这种拆分避免最常见的伪模块化:先写一个接口,却让字段完全照搬第一个 backend。代价是更多 package 与显式 wiring,收益则是 provider replacement 真能成为配置操作,而不是重写每个 caller。

7. 行为应当挂在 Loop 旁边,而不是塞进 Loop

控制流事实

默认 Loop 只拥有最小 orchestrating skeleton:打开 Turn、认领输入、组装 step、派生 request、流式调用模型、执行工具,并判断是否还欠下一步。Prompt contributor、request rewrite、retry decision、tool policy、context injection 与 stopping behavior 都通过 service/event 挂接。ARCH-TURNLOOP-TURN-STATE

机制推导

保持 Loop 小并非追求代码行数,而是为了稳定唯一 orchestrating path,让不同 owner 的行为可以独立演进。代价是语义分布:理解一次 request 必须沿多个插件注册点追踪,而不能只读一个大函数。

8. 显式边界决定信任在哪停止

仓库策略

同进程内已经由 TypeScript interface 保证的值直接信任;parser/config、model/tool JSON、durable storage、worker、process 与 wire 边界必须做运行时验证。随部署变化的数值进入 validated config;缺失 referent 在最早可判定点失败;跨边界 identity 使用 branded type。ROOT-BOUNDARIES

边界优先做法拒绝的模式
同进程 typed call信任 interface,保持路径直接重复防御解析与静默 fallback
Config/parser/wire验证完整输入,并带 owner 上下文快速失败部分接受畸形值
Model/tool JSON解析、归一化、snapshot,并保留可机器路由的失败把概率性输出当作静态可信值
Persistence/replay验证格式、identity、连续性和 JSON losslessness加载 live code 永远不可能生成的历史
Policy decision在实际执行位置强制约束把 schema omission 或 UI filtering 当成授权

9. 不变量把局部所有权变成运行时证据

生产实现

Invariant registry 为每个 package 保留唯一注册,应用 allow/block selection,在 service 自有 child fiber 中安装被启用的检查,并把违反行为包装成带 INVARIANT code 与 package 归属的错误;setup 失败和 dispose 都会释放 reservation。DESIGN-INVARIANT-REGISTRY

Invariant 应检查 package 自己拥有的关系,例如 request reconstruction、scope routing 或 event pairing,而不是只证明某个方法存在。插件系统即使类型全部通过,也无法仅靠静态类型证明最终组合仍然遵守跨插件顺序与 identity。

设计评价

这一机制承认了配置驱动架构的现实:一组单独合法的 package,仍可能组合成关系非法的 runtime。Package attribution 改善诊断;可选择启用的 live check 则让 invariant 不只停留在测试期。

10. Developer Preview 改变了兼容性承诺

仓库状态

在本研究固定的基线上,项目明确声明首个 tag 前优先修正基础设计,而非保留 compatibility shim。SQLite schema version 单调前进;session format 仍为 0 且没有兼容承诺,旧磁盘格式可能被拒绝。ROOT-PREVIEW

解读约束

当前设计的完整性不能被误读为稳定公共合同。系统确实在投资显式协议,但名称、package 边界、配置 row 与持久格式仍可能快速变化。因此本站将每条结论固定到同一 commit;后续 upstream 改动应形成新基线,而不是被悄悄改写进旧研究。

11. 这套哲学带来什么,又让什么更困难

选择收益结构性代价
一切作为 plugin 挂载产品 surface 与 provider 可按配置组合仅看 import 无法理解 effective runtime
Registration 是 effectHMR 与 scoped teardown 能可预测地撤回贡献每项贡献都需要正确 owner 与 quiescence
Event 是扩展点策略无需导入 Loop 即可挂接Mode、顺序、短路与 scope 都成为公共语义
Model-visible 等价于 loggedRequest、replay 与 projection 可以一致短命 context 也需要耐久表示和 retention 语义
显式 commit pointObserver 只看到已提交状态准备与 rollback 路径更复杂
Definition/provider/consumer seamProvider replacement 真正成立Package 数量和 composition surface 增长
Package-owned invariant跨插件错误在语义 owner 附近失败协议扩展时 invariant coverage 必须同步演进
本章评价

这套架构没有消灭核心,而是把核心迁移到协议和生命周期规则中。对于需要让 provider、tool、policy 与产品 surface 独立变化的 Agent harness,这是高度匹配的选择;但它的成功依赖严格 owner、生成式地图、runtime invariant 和可重建 log。缺少这些护栏,同样的间接层会变成分布式、配置敏感且更难理解的控制流。

本章复核清单

  • 已区分可替换实现与替换后仍必须遵守的协议。
  • 已核实 Cordis service、inject、event mode、waterfall 与 effect 语义。
  • 已从生产 store 和行为测试追踪 scope 可见性与 effect 所有权。
  • 已把 model-visible/logged 原则连接到 Loop 的可执行 request 重建不变量。
  • 已用 Boot、Agent、Inbox 与 Turn 机制交叉检查提交点和所有权规则。
  • 已核实带 package 归属的 invariant 安装与 teardown。
  • 所有设计评价均保留 Developer Preview 的兼容性限制。

我的学习体会

内容仅自动保存到当前浏览器,不上传、不进入仓库。你可以导出 Markdown 自行归档。