DeepSeek × 北大的 92 页 PL 论文(arXiv:2608.25512,2026-08-26 提交):为动态组合(运行时增删/替换组件)给出形式化基础。把经典 effect/coeffect 从编译期静态分析提升为运行时机制——可逆 effect 解决时间维度(卸载即完全回滚),响应式 coeffect 解决空间维度(依赖声明+反应式生命周期),统一为 context paradigm,再给出动态组合演算与五条元定理,实现即 cordis,生产验证是 Koishi 的 4000+ 社区插件。

维度事实
作者Yifan Shi(北大 / DeepSeek-AI,即 Koishi 作者 Shigma)、Wei Zhang(北大)、Tianyi Cui(DeepSeek-AI)
分类cs.PL / cs.SE,92 页,1 图 2 表
实现Cordis(cordiverse/cordis,~7.8k stars,MIT),DeepSeek Harness 的理论底座
前身理论来自已在 Koishi 生产运行 4 年的插件内核,论文是”先有代码后有形式化”

1. 问题:动态组合缺形式化基础

传统组合是静态的(函数调用/模块导入/继承,编译期定死)。现代软件需要运行时加载、卸载、重配置组件,但实践只能退回到粗粒度机制。

两个正交维度:

  • 时间可组合性(Temporal):组件移除时,它对共享环境做的所有修改必须被完全、安全地逆转——要追踪每一次资源分配、事件注册、状态变更并保证有序回收
  • 空间可组合性(Spatial):组件能以结构化、可验证的方式声明、发现、解析彼此依赖——要管理依赖拓扑并在依赖变化时协调生命周期

静态设定下这两者分别退化为词法作用域(RAII/bracket)和模块导入解析;动态设定下显著变难:副作用不再受词法边界约束,依赖会在执行中出现/消失/换身份。

动机案例(论文用数据说话):

  1. 插件系统(VSCode):所有扩展跑在共享 extension host,无法运行时卸载单个扩展——禁用必须重启整个 host。Top 100 扩展中 87 个含可执行代码,卸载都要重启;deactivate 钩子只是进程终止时的优雅关停,且把清理逻辑与注册逻辑分离,违反 locality of concern。空间侧:extensionDependencies 几乎没人用(Top 100 中仅 7 个声明),跨扩展 API 返回无类型 any,无结构化契约。
  2. 自进化 Agent Harness:未来 harness 会在持续服务请求的同时生成并部署对自身组件的修改(模型合成工具是组件级自修改的窄前驱)。每次修改都是一次动态组合。没有时间可组合性,每次自修改都要全进程重启、丢弃累积状态,坏修改甚至能瘫痪恢复进程本身;没有空间可组合性,每个模块得自己 ad hoc 地探测依赖变化,朴素代码替换会悄悄弄坏依赖方。
  3. 粗粒度替代方案的代价:OS 以进程粒度提供时间可组合性、容器编排以服务粒度提供空间可组合性,但每次重启丢弃缓存/连接/中间状态(重建要秒到分钟级),冗余副本浪费资源,容器编排表达不了同地址空间内的组件依赖。粒度错配正是本文要填的坑。

2. 核心形式化:把 effect / coeffect 提升为运行时机制

理论支柱是类型论中经典的 effect(程序如何改变环境)与 coeffect(程序需要环境什么):

  • effect system:Γ ⊢ t : T_effect——结果类型带上效应代数标注(Lucassen-Gifford → Moggi 单子 → Plotkin-Power 代数效应/处理器)
  • coeffect system:Γ_coeffect ⊢ t : T——上下文带上余效应代数标注(comonad、graded coeffects)

关键洞察:经典系统都是静态工具(词法固定作用域、编译期解析),而动态组合要求这些保证对运行时到达/离开的组件、对持续演化的上下文成立。本文的转向:不加更多类型标注,而是把 effect/coeffect 的概念结构 reify 成运行时可直接操作的一等实体。

2.1 Revertible Effects(时间)

把不纯函数纯化:f : X ⇝ Y 变成 f : Γ × X → Γ × Y,所有副作用都是对上下文 Γ 的变换。可撤销的效应建模为 Γ → Γ × (Γ → Γ):返回新上下文外加一个显式逆变换。逆变换交回运行时,就是”可追踪”。

核心构造:

  • 扭合成幺半群 𝔗Γ:变换对 (f, g) 的乘法 (f₁,g₁) ∘ (f₂,g₂) = (f₁∘f₂, g₂∘g₁)——逆变换按相反顺序累积(LIFO 回卷的代数本质)。撤销是单边的:只要求 g ∘ f,不要求 f ∘ g
  • effect context ∂Γ = Γ × (Γ → Γ):状态 + 累加器(到目前为止所有已执行效应的逆的复合,即可把上下文恢复到初始态的函数);迭代 ∂ 得到塔 Γ, ∂Γ, ∂²Γ, …(对应层级化组合)
  • track / recover:track(f,g)(γ,φ) = (f(γ), φ∘g) 把一次效应记入账本;recover 施加累加器恢复上下文。有定理保证 recover ∘ track = id(观测等价意义下)
  • effect 迭代器:激活过程是多步序列,每步 yield(新上下文、逆变换、续体);续体依赖前步结果。实现里对应回调的四种形态:普通函数 / 返回 disposer / 生成器 / 异步生成器

2.2 Reactive Coeffects(空间)

依赖表形式化为依赖部分函数 Σ = (k : K) ⇀ 𝒱ₖ(每个 key 带自己的值类型——比 IoC 容器的 key-value map 多了类型安全):

  • get(k) / set(k, v):set 返回新表 + 逆(删除该绑定)——set 本身就是 effect function,因此直接复用 2.1 的全部追踪/恢复机器。“coeffect 操作是 effect,effect 是可逆的”——两个维度的协同点
  • 满足谓词 σ ⊧ d ≔ ∀k ∈ d. k ∈ dom(σ),可判定
  • 通知分类 notify_d(σ, σ′) ∈ {activating, deactivating, neutral}:按组件的依赖规格对每次上下文变化三分类,驱动激活/去激活。这是响应式的代数基础
  • 隔离(isolation):Σiso 双层映射 k → ρ(k) realm → σ(ρ(k)) 值,同一逻辑依赖在不同上下文绑定不同值(多租户/测试/沙箱),本质是运行时 ad-hoc 多态
  • 拦截(interception):Σinter 给依赖访问挂横切元数据 ℳₖ(每 key 一个幺半群),组件声明的元数据与上下文携带的元数据合并(右偏向,上下文优先)——外层上下文可以不改组件代码就约束它如何使用某个依赖(权限控制的基础)

2.3 Context Paradigm(统一)

  • 统一上下文类型 Γ∞ = μΓ. Γ × (Γ → Γ) × Σ:递归结构 + 依赖表,自相似地统一了 ∂ 塔。任何需要跨组件共享的状态都可编码为依赖——Σ 囊括全部共享可变状态。组件与环境的一切交互都经过这唯一实体
  • 每个 key 携带 (𝒱ₖ, 𝒜ₖ):值类型 + 允许的操作集,操作本身是 𝒱ₖ 上的 effect function;上下文中介迭代器 ℑ 限制组件只能做”在声明的 key 上执行操作”或”在 provision 的 key 上安装绑定”两种 stage——形式化了”一切经过 context 中介”的纪律
  • 观测等价 ≃:物理状态不可能原样恢复(free 不会恢复堆布局、生成式名字不会复原),所以所有相等都在”任何操作序列都无法区分”的观测等价下读。≃ₖ 由 key 自己的操作生成,是最粗的相容等价
  • effect 独立性 + coeffect 交换性:不同 key 上的效应天然交换;同 key 上的操作要求组件提供”成对独立”的见证(witness)——由 key 的表示选择来履行

3. 动态组合演算与五条元定理

把系统分解为 component = (d, p, e) 三元组:依赖规格(读什么)、provision(可能提供什么)、带见证的 effect 迭代器(做什么)。组件的实例化叫 fiber,携带生命周期状态:

∅ ⇄ Inactive ⇄ Loading ⇄ Active ⇄ Unloading
         (+ 退休标志 τ;O-Remove 移除空条目)

9 条规则:3 条编排规则(O-Insert / O-Retire / O-Remove,外部唯一输入,编排者只请求存在/不存在,从不直接设生命周期状态)+ 6 条生命周期规则(L-Begin / L-Iter / L-Finish / L-Divert / L-Leave / L-Unload,前提成立时系统自发执行)。驱动机制是 target view(应该按哪个依赖解析运行)与 committed view(实际按哪个解析激活的)的比较——两者一致则静默,不一致则触发转换。卸载守卫(L-Unload 的 ¬relied 前提)保证提供方只在所有依赖方都卸载后才撤绑定。

五条元定理(论文最有价值的部分):

定理内容工程含义
Preservation任何 load/unload/reload 步骤保持注册表良构系统始终满足自身规则
Recovery exactness(时间全局)运行累加器后,系统状态 ≃ “该组件从未运行过、其余步骤照常” 的状态撤销是精确的,即使其他组件期间交错运行
Ordering + Resolution coherence(空间全局)组件只在依赖全部就绪时激活;提供方在依赖方全部退出后才撤绑定;转换期间读到的依赖解析不会在脚下移动不会半运行、不会抽走正在使用的依赖
Progress依赖图无环时,系统不死锁且必然终止于静默态变更不会卡在半途
Confluence无论中间经历多少次加载/卸载/替换/回滚,只要最终期望配置相同,静默态 ≃ 从零按依赖顺序一次性装配的态热改 50 次的系统 ≠ 状态脏,行为等价于干净安装

Confluence 是王冠:它让编排者可以像推理静态装配一样推理被反复热改的系统。

四个扩展(实现均已落地且不破坏元理论):

  1. 异步/惯性(inertia):异步宿主中迭代/逆返回 future,一旦进入转换就跑完(L-Divert 只取 landing 分支),步边界仍可中断
  2. 失败:迭代可抛错,走 aborting L-Divert 路由——回卷已装效应、回到 Inactive 且什么都没装(Cor 69),错误记录在 fiber 上阻止盲目重试;失败不外溢,兄弟组件照跑。实现的 FAILED 态即此
  3. 隔离:多 realm 读法 = 把 key 集扩成 K × R,规则原样适用
  4. 配置修订:禁用 = O-Retire;其他修订 = 退休→去激活→移除→同名重插。依赖方无需人工干预自动跟随

4. 实现:Cordis 逐符号对应

论文第 5 节给出理论↔实现对照(Table 2 摘录):

理论Cordis 实现
Γ∞ctx(一等上下文)
effectΓctx.effect(callback)——一切上下文变更的唯一原语,LIFO 复合逆
Σ / Σiso / Σinterctx[@@store] / ctx[@@isolate] / ctx[@@intercept] 三个 symbol 槽
set / getctx.set(key, value) / ctx.get(key);set 就是带 notify 的 ctx.effect
fiber ⟨d,p,e,π,σ,τ,θ⟩fiber:fiber.inject(d)、fiber.apply(绑定配置后的 e)、fiber.state、fiber.committed(ω)、fiber.target、fiber.inertia
O-Insert/O-Retirectx.use(component, config) 及其回调的逆——实例化本身是父纤维的普通 effect,卸载父自动级联卸载子
L-规则refresh/reload/unload 互递归状态机(Algorithm 5):refresh 重算 target,变了且无在途转换就发起 reload/unload;reload 完成时 target 仍匹配则 ACTIVE 并 notify,否则链式转 unload(惯性)
L-Unload 守卫unload 第一行:await all(notify(...).map(f => f.await()))——先等所有依赖方排空,再跑自己的逆

运行时不校验见证:回调提供的逆是否真的能撤销、同 key 操作是否真的交换,是组件作者的义务而非运行时检查——这是形式模型与实现之间诚实标注的缝隙。

三层架构:核心库(effect 追踪 + coeffect 解析)→ 组件加载器(声明式配置协调 + HMR)→ 应用框架(Koishi / DeepSeek Harness)。

  • 声明式配置:条目 = {id, url, isolate, intercept, config, disabled},恰是 support set(τ, π, d, p)的忠实规格。协调按字段分派最小扰动操作:id/url 变 → 重建;intercept → 原地更新(读时生效);config → 交给组件自己 diff;disabled → 卸载/重载。元理论保证协调只需发出请求、不必排序加载顺序(依赖只约束何时激活,不约束何时取模块,所以可并发加载)
  • HMR 三阶段:模块分类(accepted/declined 不动点,环上模块默认 declined)→ 陈旧条目探测(依赖树与 accepted 相交)→ 事务性重载(备份缓存,任何模块导入失败则全量回滚,绝不出现半重载态)。因为 fiber 已界定组件全部效应,HMR 不需要 webpack/Vite 那种开发者标注的接受边界

5. 案例研究与有效性边界

Koishi:4 年 4000+ 社区插件,服务端与 Web 控制台两个独立 Cordis 应用(证明表达力与运行时无关性)。三个实证点:控制台禁用插件即原地回卷效应(无需重启);HMR 保存即热替换且保住其他插件的连接/缓存;依赖不可用的插件安静停留 Inactive 而非报错,跨独立作者的依赖拓扑在运行时保持自洽。

论文明确的 threats to validity:单一生态、单一宿主语言、观察性而非对照实验——是存在性与采纳性结论,不是量化结论。

6. 讨论要点(工程价值密度最高的部分)

  • 系统边界:逆的语义由边界划定。边界内 = 系统能独占修改并恢复 → 可追踪可逆;边界外 = 操作视作 id,不追踪。获取(acquisition)在内、发射(emission)在外:open/malloc/fork 装的记录可逆,write/send 推出去的数据不可逆。跨越边界的恢复只有两条路:withhold(延迟发射直到状态确定持久,即 rollback-recovery 的输出提交问题)或 compensation(应用自定义的更粗等价下的补偿动作,如删文件、退款,同样 LIFO 复合)
  • 服务多路复用:exclusive binding(换实现要扰动全部消费方)vs service broker(broker 本身是注入点,后端提供方更换不触发消费方重载)——由此派生负载均衡、应用层滚动更新(provider transition 取代蓝绿部署)、跨进程调用(需按异步契约设计接口)
  • 访问控制:inject 声明 = 能力请求,context proxy = 能力中介——结构上就是 capability-based security;interception 元数据可做细粒度策略(如只读数据库授权),运行时可调且不触发重载。沙箱仍需外部机制(SFI/独立运行时/容器),桥接后对组件透明
  • 循环依赖:不产生死锁,而是相关组件永久 Inactive——可从声明静态预测并报错。任何双向交互都可拆成单向绑定(server-core + access-control-core + 两个集成组件),代价是集成组件数可能随 n 二次增长,靠打包/约定布线/脚手架缓解
  • 依赖类型与版本:key 身份是纯名义链接,独立开发场景下有 interface drift 与 key collision 两病。三条路:key 命名空间化(K × P)、peer dependencies(Cordis 现状,依赖语义化版本约定)、结构兼容性(理想但行为契约层面不可判定)
  • 语言/OS 协同设计:隐式上下文(免传参 + 防止误持他人 ctx)、编译器可见的效应迭代器(单个状态机替代每步闭包分配)、类型系统接纳依赖规格(编译期报环、行类型做结构兼容);OS 侧把资源作为 coeffect 发放并归属记账,事务性持久写/CoW 存储可让部分 emission 也可回滚

7. 相关工作定位

对照系区别
ZIO / Effect-TS需要单子嵌入(代码必须写在效应类型里);需求被”解释”而非反应式重解析,服务撤走其操作后果仍留在原地
Effekt(代数效应即能力)静态类型级、能力是二等的受词法作用域约束;Cordis 是运行时纪律、目标移除时完全恢复
Heunen 等可逆效应语义(dagger arrows)最接近的形式化对照:都是”效应配对逆”。但那是全局可逆、双侧逆、从范畴结构导出;Cordis 只要每个原子效应带单边逆、调用点提供、复合推出整体
Granule / graded types统一 effect+coeffect 但全在类型层;本文与之正交:同一对概念提升到运行时
COP / AOPCOP 的”context”是环境情境、层不追踪效应;Cordis 的激活由依赖满足驱动且去激活完全回卷。AOP pointcut 是 oblivious 的;Cordis 横切面被限制在组件声明的 coeffect 上,可审计可治理
DSU(Kitsune/Erlang OTP/webpack HMR)状态前向迁移更优雅但需手写迁移函数;Cordis 零迁移函数、支持彻底卸载。组件内存态不跨重载存活(除非放进更长寿命的依赖)——叠加前向迁移是 future work
OSGi服务模型呼应,但清理靠开发者回调

8. 评价

为什么重要(对 agent 工程师):这是第一份给”自进化 agent 的插件运行时”写形式语义的工作。自进化场景是这套理论最尖锐的应用——组件替换频率高、无人监督、坏修改必须能被完全撤销且依赖方自动跟随,正是 temporal+spatial 保证的直接翻译。DeepSeek Harness “一切皆插件、无特权核心”的架构主张,由这 5 条定理背书:热改收敛到干净安装态(Confluence)、不卡死(Progress)、卸载零残留(Recovery exactness)。

局限要清醒:

  1. 见证(逆真的可逆、操作真的交换)不被运行时校验,全靠组件作者纪律——形式保证是条件性的
  2. emission 不可回滚是原理性边界:发出去的消息、写出去的外部状态只能 withhold/compensate,agent 的工具调用副作用大多在这条边界外
  3. 验证只有 Koishi 单一生态的观察性证据;且 Koishi 还在 Cordis v3,论文写的是 v4
  4. 论文形式化了组合脚手架,不保证组件本身的正确性——插件内部逻辑错了,系统照样”正确地”装载它

与本知识库的连接:工程侧的五概念(插件/上下文/inject/事件/effect)、fiber 状态机、HMR 实操,见 cordis 与 README 系列教程;本文是其理论层的补全。对照 agent-harness-anatomy 的 harness 组件观,以及 2605.18747_code-as-agent-harness 的 harness 综述——本篇提供了”agent 如何安全地修改自己”这一子问题的最严格现有答案。

资源