A9. Cordis 论文精读:时空可组合性范式与 dsh 源码对照

A9. Cordis 论文精读:时空可组合性范式与 dsh 源码对照

developer preview,API 可能变更。 本文基于 Cordis 论文《A Programming Paradigm for Spatiotemporal Composability》(Yifan Shi¹·², Wei Zhang¹, Tianyi Cui²,¹北京大学 ²DeepSeek-AI,cordiverse/paper)与 dsh 仓库 vendored 源码 vendor/cordis/@deepseek-ai/cordis@4.0.1)逐节对照写作。论文 88 页,含形式化演算、元理论证明与 Koishi 案例;vendored 版本正是论文所呈现的 v4 血统

配套阅读:A2 Cordis 核心框架(五概念入门)、S2 dsh-baseE1 HMR 热更新


1. 论文要解决什么问题

论文标题中的 Spatiotemporal Composability(时空可组合性) 拆开是两个正交维度:

维度 论文术语 通俗表述 失败后果
时间 temporal composability 组件卸载时,其对共享环境的全部副作用可完全、安全地逆置 卸载即重启,丢失进程内累积状态(缓存、连接、进行中的计算)
空间 spatial composability 组件能声明、发现、响应式解析彼此的依赖 组件只能自行轮询感知依赖变化;换实现时静默破坏依赖方

论文用 VSCode 做反面教材(2026-06-09 Marketplace 数据):

  • 时间维度失败 :top 100 扩展中 87 个含可执行代码 ,卸载任何一个都必须重启整个 extension host;deactivate 钩子只是进程终止时的优雅关闭回调,且把「效果创建」(activate)与「效果清理」(deactivate)分离两处,违反 locality of concern(关注点局部性)。
  • 空间维度失败 :top 100 扩展中仅 7 个 声明 extensionDependenciesgetExtension(...).exports 返回 any,依赖方无从获得受检接口。

而操作系统的进程粒度、容器编排器的服务粒度只是粗粒度替代品(coarse-grained workaround)------重启丢状态(重建需秒到分钟级),跨地址空间组件无法表达依赖,本可局部函数调用的交互被网络化。

2. 核心主张:把 effect / coeffect 提升为运行时机制

论文的理论起点是程序语言学界两个经典对偶概念:

  • Effect(效应)Γ ⊢ t : T^effect------类型标注描述计算对环境做什么(Moggi 单子效应 → Plotkin & Power 代数效应 → effect handler)。
  • Coeffect(协效应)Γ^coeffect ⊢ t : T------上下文标注描述计算需要环境提供什么(comonad、graded coeffect 半环)。

但经典体系都是编译期静态工具 :effect 在词法固定作用域内追踪、由编译期 handler 清算;coeffect 在执行前对既定上下文校验。动态组合恰恰相反------组件在运行时到来与离去,上下文持续演化。部署后才加载的插件没有词法作用域能框住它;运行时配置涌现的依赖没有编译期上下文能预判它。

论文的答案不是给静态类型系统加更多标注,而是把 effect / coeffect 的概念结构具象化(reify)为运行时可直接操作的一等实体
#mermaid-svg-2Z649YT4MPs3xf9B{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-2Z649YT4MPs3xf9B .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-2Z649YT4MPs3xf9B .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-2Z649YT4MPs3xf9B .error-icon{fill:#552222;}#mermaid-svg-2Z649YT4MPs3xf9B .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-2Z649YT4MPs3xf9B .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-2Z649YT4MPs3xf9B .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-2Z649YT4MPs3xf9B .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-2Z649YT4MPs3xf9B .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-2Z649YT4MPs3xf9B .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-2Z649YT4MPs3xf9B .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-2Z649YT4MPs3xf9B .marker{fill:#333333;stroke:#333333;}#mermaid-svg-2Z649YT4MPs3xf9B .marker.cross{stroke:#333333;}#mermaid-svg-2Z649YT4MPs3xf9B svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-2Z649YT4MPs3xf9B p{margin:0;}#mermaid-svg-2Z649YT4MPs3xf9B .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-2Z649YT4MPs3xf9B .cluster-label text{fill:#333;}#mermaid-svg-2Z649YT4MPs3xf9B .cluster-label span{color:#333;}#mermaid-svg-2Z649YT4MPs3xf9B .cluster-label span p{background-color:transparent;}#mermaid-svg-2Z649YT4MPs3xf9B .label text,#mermaid-svg-2Z649YT4MPs3xf9B span{fill:#333;color:#333;}#mermaid-svg-2Z649YT4MPs3xf9B .node rect,#mermaid-svg-2Z649YT4MPs3xf9B .node circle,#mermaid-svg-2Z649YT4MPs3xf9B .node ellipse,#mermaid-svg-2Z649YT4MPs3xf9B .node polygon,#mermaid-svg-2Z649YT4MPs3xf9B .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-2Z649YT4MPs3xf9B .rough-node .label text,#mermaid-svg-2Z649YT4MPs3xf9B .node .label text,#mermaid-svg-2Z649YT4MPs3xf9B .image-shape .label,#mermaid-svg-2Z649YT4MPs3xf9B .icon-shape .label{text-anchor:middle;}#mermaid-svg-2Z649YT4MPs3xf9B .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-2Z649YT4MPs3xf9B .rough-node .label,#mermaid-svg-2Z649YT4MPs3xf9B .node .label,#mermaid-svg-2Z649YT4MPs3xf9B .image-shape .label,#mermaid-svg-2Z649YT4MPs3xf9B .icon-shape .label{text-align:center;}#mermaid-svg-2Z649YT4MPs3xf9B .node.clickable{cursor:pointer;}#mermaid-svg-2Z649YT4MPs3xf9B .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-2Z649YT4MPs3xf9B .arrowheadPath{fill:#333333;}#mermaid-svg-2Z649YT4MPs3xf9B .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-2Z649YT4MPs3xf9B .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-2Z649YT4MPs3xf9B .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Z649YT4MPs3xf9B .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-2Z649YT4MPs3xf9B .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Z649YT4MPs3xf9B .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-2Z649YT4MPs3xf9B .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-2Z649YT4MPs3xf9B .cluster text{fill:#333;}#mermaid-svg-2Z649YT4MPs3xf9B .cluster span{color:#333;}#mermaid-svg-2Z649YT4MPs3xf9B div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-2Z649YT4MPs3xf9B .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-2Z649YT4MPs3xf9B rect.text{fill:none;stroke-width:0;}#mermaid-svg-2Z649YT4MPs3xf9B .icon-shape,#mermaid-svg-2Z649YT4MPs3xf9B .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-2Z649YT4MPs3xf9B .icon-shape p,#mermaid-svg-2Z649YT4MPs3xf9B .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-2Z649YT4MPs3xf9B .icon-shape .label rect,#mermaid-svg-2Z649YT4MPs3xf9B .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-2Z649YT4MPs3xf9B .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-2Z649YT4MPs3xf9B .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-2Z649YT4MPs3xf9B :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 统一范式
提升(reify)
经典静态体系(PL 学界)
vendored 为
Effect 系统

Γ ⊢ t : T^effect

编译期追踪 + handler
Coeffect 系统

Γ^coeffect ⊢ t : T

编译期上下文校验
可逆效应 Revertible Effects

每个 Γ→Γ 变换携带显式逆

运行时跟踪复合逆
响应式协效应 Reactive Coeffects

依赖以规约声明

上下文变更按规约通知组件
统一 Context 类型 Γ∞

效应上下文 + 协效应上下文

= 一种编程范式
动态组合演算

component (d,p,e) / fiber

  • 操作语义 + 元理论
    Cordis 实现

核心库 + 声明式 loader + HMR
dsh

@deepseek-ai/cordis@4.0.1

中文术语对照:Spatiotemporal Composability(时空可组合性)|Temporal Composability(时间可组合性)|Spatial Composability(空间可组合性)|Revertible Effect(可逆效应)|Reactive Coeffect(响应式协效应)|Context(上下文)|Component(组件)|Fiber(纤维/组件实例)|Registry(注册表)|Realm(领域/隔离域)|Inverse(逆/逆置函数)|Accumulator(累积器)|Committed View(已提交视图)|Inertial Transition(惯性迁移)|Locality of Concern(关注点局部性)。

3. 可逆效应:理论 → Algorithm 1 → fiber.ts

3.1 理论

论文把效应建模为类型 Γ → Γ × (Γ → Γ) 的函数:作用于当前上下文,返回修改后的上下文 连同一个显式逆。逆交还给运行时------这就是「可跟踪」;逆可复合------这就是「可完全恢复」:

By tracking and composing these inverses during execution, complete environment recovery becomes a structural guarantee.(论文 §3.1)

3.2 论文 Algorithm 1(效应跟踪)

复制代码
async function execute(callback, guard)
  iter ← callback();  inverse ← id
  while guard()
    (value, done) ← await iter.next()
    if value then inverse ← value ∘ inverse
    if done then break
  return inverse
function effect(ctx, callback)
  armed ← true
  task ← execute(callback, () ↦ armed)
  async function dispose() ...   // 翻转 armed → 停止迭代 → 至多恢复一次
  ctx.dispose ← dispose ∘ ctx.dispose   // 前插父级 → LIFO
  return dispose

两个关键设计:自处置 (armed 守卫使恢复至多触发一次------同一逆作用于两个不同状态不再有回退保证);父复合(子效应的逆本身是父上的效应,即 ∂²Γ 的递归结构)。

3.3 dsh 源码对照

ctx.effect 实为 Fiber.prototype.effect,经 mixin 暴露到 context(vendor/cordis/src/reflect.ts:220this.mixin('fiber', ['runtime', 'effect'])):

ts 复制代码
// vendor/cordis/src/fiber.ts:415-422
effect(execute: () => Effect, label = 'anonymous'): any {
  this.assertActive()
  if (this.state === FiberState.UNLOADING) {
    throw new CordisError('INACTIVE_EFFECT')
  }

dispose 的 LIFO 逆序不再用「前插数组」而是 DisposableList------清空时统一反转(vendor/cordis/src/utils.ts:27-31):

ts 复制代码
clear() {
  const values = [...this.map.values()]
  this.map.clear()
  return values.reverse()   // LIFO:后注册的先撤销
}

wrapper 注册进 _disposables 后立即执行(vendor/cordis/src/fiber.ts:520-522removeWrapper = this._disposables.push(wrapper); try { task = this._execute(runner) }),_unload()this._disposables.clear()(fiber.ts:676)。

可运行示例------用迭代器形式多次产出逆,观察 LIFO 撤销顺序(在 dsh 插件或独立 cordis 程序中运行):

ts 复制代码
import { Context } from 'cordis'

const app = new Context()

app.effect(function* () {
  console.log('1: 建立数据库连接')
  yield () => console.log('逆1: 关闭数据库连接')
  console.log('2: 注册事件监听')
  yield () => console.log('逆2: 移除事件监听')
  console.log('3: 启动定时器')
  return () => console.log('逆3: 停止定时器')   // 最终返回值也是逆
})

await app.dispose()
// 输出顺序:1 → 2 → 3 → 逆3 → 逆2 → 逆1(严格 LIFO)

4. 响应式协效应:理论 → Algorithm 2/3 → reflect.ts

4.1 理论

协效应侧,组件声明一个规约(specification) d;上下文每次变化,运行时按规约把该变化分类为 activating / deactivating / neutral,并通知组件。解析是两层 的:k → ρ(k) → σ(ρ(k))------协效应键先经 realm 表 ρ 映射到领域符号,再从值存储 σ 取绑定值。ρ 这层间接性让 **isolation(隔离)**能把一个键重定向到独立绑定;**interception(拦截)**表 ι 则在访问时调整「如何使用」而非「解析到什么」。

论文 Algorithm 2(get/set)与 Algorithm 3(notify):set(k,v) 本身是一个 ctx.effect 调用(安装与移除都触发 notify,向所有声明了 k 且 realm 一致的 fiber 传播变更,令其 refresh)。

4.2 dsh 源码对照

get 的两层解析(vendor/cordis/src/reflect.ts:233-243):

ts 复制代码
get(name: string, strict = true) {
  return getTraceable(this.ctx, this._getImpl(name, strict)?.value)
}
_getImpl(name: string, strict = true) {
  const key = this.ctx[symbols.isolate][name]   // 第一层:realm 表 ρ(k)
  const impl = key && this.store[key]            // 第二层:值存储 σ(ρ(k))
  if (!impl) return
  if (strict && impl.fiber.state !== FiberState.ACTIVE) return

set 要求「只有提供者 fiber 自己能覆写」(vendor/cordis/src/reflect.ts:254-264if (impl.fiber !== this.ctx.fiber) throw ...,无 provide 时抛 cannot set property "${name}" without provide)。notify 遍历 registry 中所有 fiber、重算依赖并触发 _refresh() 状态机(vendor/cordis/src/reflect.ts:314-333)。

isolate / intercept(论文 v4 特性,vendored 版均已实现):

ts 复制代码
// vendor/cordis/src/context.ts:121-125
isolate(name: string, label?: symbol) {
  const shadow = Object.create(this[symbols.isolate])
  shadow[name] = label ?? Symbol(name)
  return this.extend({ [symbols.isolate]: shadow })
}
// vendor/cordis/src/context.ts:141-145
intercept(name: string, config: any) {
  const intercept = Object.create(this[symbols.intercept])
  intercept[name] = config
  return this.extend({ [symbols.intercept]: intercept })
}

5. 统一 Context 与 Proxy 访问(Algorithm 6)

论文的统一 Context 类型把效应上下文与协效应上下文合一;组件访问 ctx[key] 时经 Proxy get trap 沿 fiber 链向上 走 committed view:第一站绑定即返回;走到「声明了 k 却未提交」的 fiber 抛未激活错;走到根仍无声明抛未声明错。这使协效应规约 d 在使用点被强制执行 ------比裸 ctx.get(查 store、从不失败)多了一层视图纪律。

源码对应 vendor/cordis/src/reflect.ts:153-166

ts 复制代码
return ctx.events.waterfall('internal/get', ctx, prop, error, () => {
  const key = target[symbols.isolate][prop]
  let fiber = (ctx[symbols.shadow] as Context ?? ctx).fiber
  while (true) {
    const impl = fiber.store?.[prop]           // committed 快照
    if (impl) return getTraceable(ctx, impl.value)
    if (prop in fiber.inject) {
      error.message = `cannot get required service "${prop}" in inactive context`
      throw error
    }
    if (!fiber.runtime) throw error
    if (fiber.parent[symbols.isolate][prop] !== key) throw error
    fiber = fiber.parent.fiber                  // 沿父链上行

6. 演算:component / fiber / registry → 源码字段级对照

论文 Definition 43/44 把组件形式化为三元组 ℭ ≔ (d, p, e) ------依赖规约 d(从环境读什么)、提供 p(可向环境写哪些键,不同 fiber 的 provision 两两不相交,故每个键提供者唯一)、效应函数 e(激活时贡献什么 + 撤回其全部效应的逆)。fiber 是组件的一次实例化:⟨d, p, e, π, σ, τ, θ⟩------父指针 π、自身协效应表 σ、退休标志 τ、生命周期状态 θ(携带累积器 g 与已提交视图 ω)。registry 是 fiber 的偏函数,父指针构成以 root 为根的树。
#mermaid-svg-N0D8FjApAZJcPSG5{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-N0D8FjApAZJcPSG5 .error-icon{fill:#552222;}#mermaid-svg-N0D8FjApAZJcPSG5 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-N0D8FjApAZJcPSG5 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-N0D8FjApAZJcPSG5 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-N0D8FjApAZJcPSG5 .marker.cross{stroke:#333333;}#mermaid-svg-N0D8FjApAZJcPSG5 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-N0D8FjApAZJcPSG5 p{margin:0;}#mermaid-svg-N0D8FjApAZJcPSG5 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-N0D8FjApAZJcPSG5 .cluster-label text{fill:#333;}#mermaid-svg-N0D8FjApAZJcPSG5 .cluster-label span{color:#333;}#mermaid-svg-N0D8FjApAZJcPSG5 .cluster-label span p{background-color:transparent;}#mermaid-svg-N0D8FjApAZJcPSG5 .label text,#mermaid-svg-N0D8FjApAZJcPSG5 span{fill:#333;color:#333;}#mermaid-svg-N0D8FjApAZJcPSG5 .node rect,#mermaid-svg-N0D8FjApAZJcPSG5 .node circle,#mermaid-svg-N0D8FjApAZJcPSG5 .node ellipse,#mermaid-svg-N0D8FjApAZJcPSG5 .node polygon,#mermaid-svg-N0D8FjApAZJcPSG5 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-N0D8FjApAZJcPSG5 .rough-node .label text,#mermaid-svg-N0D8FjApAZJcPSG5 .node .label text,#mermaid-svg-N0D8FjApAZJcPSG5 .image-shape .label,#mermaid-svg-N0D8FjApAZJcPSG5 .icon-shape .label{text-anchor:middle;}#mermaid-svg-N0D8FjApAZJcPSG5 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-N0D8FjApAZJcPSG5 .rough-node .label,#mermaid-svg-N0D8FjApAZJcPSG5 .node .label,#mermaid-svg-N0D8FjApAZJcPSG5 .image-shape .label,#mermaid-svg-N0D8FjApAZJcPSG5 .icon-shape .label{text-align:center;}#mermaid-svg-N0D8FjApAZJcPSG5 .node.clickable{cursor:pointer;}#mermaid-svg-N0D8FjApAZJcPSG5 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-N0D8FjApAZJcPSG5 .arrowheadPath{fill:#333333;}#mermaid-svg-N0D8FjApAZJcPSG5 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-N0D8FjApAZJcPSG5 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-N0D8FjApAZJcPSG5 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N0D8FjApAZJcPSG5 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-N0D8FjApAZJcPSG5 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N0D8FjApAZJcPSG5 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-N0D8FjApAZJcPSG5 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-N0D8FjApAZJcPSG5 .cluster text{fill:#333;}#mermaid-svg-N0D8FjApAZJcPSG5 .cluster span{color:#333;}#mermaid-svg-N0D8FjApAZJcPSG5 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-N0D8FjApAZJcPSG5 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-N0D8FjApAZJcPSG5 rect.text{fill:none;stroke-width:0;}#mermaid-svg-N0D8FjApAZJcPSG5 .icon-shape,#mermaid-svg-N0D8FjApAZJcPSG5 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-N0D8FjApAZJcPSG5 .icon-shape p,#mermaid-svg-N0D8FjApAZJcPSG5 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-N0D8FjApAZJcPSG5 .icon-shape .label rect,#mermaid-svg-N0D8FjApAZJcPSG5 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-N0D8FjApAZJcPSG5 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-N0D8FjApAZJcPSG5 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-N0D8FjApAZJcPSG5 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} vendored cordis v4 源码
论文形式化
d
p
e
Component ℭ = (d, p, e)

依赖规约·提供·效应函数
Fiber ⟨d,p,e,π,σ,τ,θ⟩

父·表·退休·生命周期
Registry 𝐹𝛾: 𝔑 ⇀ 𝔉

fiber 树 + 派生协效应上下文
Plugin 元数据 inject/provide

registry.ts:100-111
Service 构造器 provide

service.ts:57
Fiber.effect

fiber.ts:415
Fiber 字段 uid/parent/inject/

state/store/inertia

fiber.ts:184-226
RegistryService

Map<callback, Runtime>

registry.ts:195

关键源码锚点:

  • Fiber 字段(vendor/cordis/src/fiber.ts:184-226):uid(registry counter 单调分配,根 fiber 为 0)、parentinjectstatedisposestoreinertia 全部存在 ;论文的 committed/target 字段未按此命名------对应物是 fiber.store 快照(激活时 this.store = { ...this._store },fiber.ts:647;卸载时置 undefined,fiber.ts:687)。
  • 生命周期枚举(vendor/cordis/src/fiber.ts:147-154):PENDING / LOADING / ACTIVE / FAILED / DISPOSED / UNLOADING 六态------论文二态模型 + 迁移中状态的超集;论文的 LOADING ↔ LOADING、FAILED ↔ INACTIVE(ξ)
  • 组件实例化:论文 Algorithm 4 的 ctx.use,源码中名为 ctx.plugin()vendor/cordis/src/registry.ts:316const fiber = new Fiber(this.ctx, config, Inject.resolve(plugin.inject), runtime, getOuterStack))。

7. 生命周期状态机(Algorithm 5):惯性迁移与协效应定序

论文的 refresh/reload/unload 互递归实现了惯性(inertia):迁移一旦开始即运行至完成,才响应新的目标变更。reload 完成时核对目标------匹配则 ACTIVE,不匹配(无论 ⊥ 还是提供者变了)链入 unload;对称地,unload 恢复全部逆后按目标链入 reload 或入 INACTIVE。

论文特别指出三行代码承担了定理 63 的协效应定序 :① reload 在开头提交已解析视图、unload 在全部逆跑完才丢弃------fiber 加载多久、读的绑定就稳定多久(含自身卸载期间);② refresh 在创建迁移任务之前把 fiber 标记 UNLOADING(L-Leave)------fiber 先停止提供、依赖者据此先重算,才轮到任何逆被调度;③ unload 先等所有被通知的依赖者到达 INACTIVE(guard on L-Unload)再跑恢复。这一「先停供、依赖者先撤、最后清效应」的次序正是 dsh 中「换 Provider,依赖它的工具链有序重载而不出错」的形式化根基。

源码对应:FiberState.UNLOADING 检查(fiber.ts:418-420 即「INACTIVE_EFFECT」守卫)、_unload()this._disposables.clear()(fiber.ts:676)与 this.store = undefined(fiber.ts:687),以及 notify → fiber._refresh() 的传播链(reflect.ts:314-333)。

8. 声明式 loader 与 HMR(Algorithm 7--10)→ dsh 的 vendor/hmr

论文 §5.2 的 loader 把「系统该加载什么」表达为声明式配置条目(id/url/isolate/intercept/config/disabled 六字段),增量调和(reconciliation)而非整体重建------其正确性由元理论背书:静息态只是最终配置的函数(Theorem 73)、系统必然静息(Theorem 66)、离场 fiber 对状态贡献为零(Corollary 62)、条目可并发实例化无须编排加载顺序(Theorem 63)。

HMR 三阶段 (论文 Algorithm 8--10):① 模块分类(stashed 变更集沿 import 子图定点扩散:一旦有 import 被接受即接受、全部 import 被拒绝即拒绝、循环 import 默认拒绝);② 陈旧条目检测(条目依赖树 ∩ 接受集 ≠ ∅ 即陈旧);③ 事务性重载 (备份缓存 → 换 fiber → 任一失败则恢复缓存并全部回滚)------系统永不进入半重载态。与 Webpack/Vite 需要 import.meta.hot 注解接受边界不同,Cordis HMR 无需开发者注解:fiber 本就界定了组件全部效应与协效应,dispose 旧 fiber 即恢复一切、新模块再实例化即重装一切。

dsh 对应实现为 vendored 的 @deepseek-ai/cordis-plugin-hmrvendor/hmr/src/index.ts,Chokidar 监视 + ES/CJS 双模块缓存清除 + fiber 交换),由 packages/bundle/base/cordis.patch.yml:20 挂载------详见本系列 E1 HMR 热更新

可运行示例------体验 dsh 的 HMR(无注解、保存即换、事务回滚):

sh 复制代码
# 1. 写一个最小 dsh 插件
mkdir -p my-plugin && cat > my-plugin/index.ts <<'EOF'
import { Context } from 'cordis'
export function apply(ctx: Context) {
  console.log('v1 已加载')
  ctx.effect(() => () => console.log('v1 已卸载(逆)'))
}
EOF

# 2. 以 --patch 挂载并启动 web(默认 127.0.0.1:3080)
npx @deepseek-ai/dsh web --patch ./my-plugin

# 3. 修改 my-plugin/index.ts 的输出为 'v2 已加载' 并保存
#    观察控制台:v1 已卸载(逆) → v2 已加载(fiber 交换,进程不重启)

# 4. 故意引入语法错误保存 → 事务回滚:缓存恢复,v1 继续服务,永不半重载

9. dsh:论文动机的直接落地 + 生态验证

论文 §1.2.2 明确把 **self-evolving agent harness(自进化智能体运行时)**列为第二动因:未来 harness 可在持续服务的同时生成并部署对自身组件的修改------每次修改都是一次动态组合。没有时间可组合性,每次自改都是全量重启、进行中任务反复中断,更糟的是一次故障自改可能废掉恢复所需的进程本身;没有空间可组合性,每个模块只能自行 ad hoc 感知依赖变化。

dsh 正是这一动机的产品化 :Everything is a Plugin、无特权内核、--dump-config 可审视的 Profile 组装(见 A1A4)。而 Koishi 案例验证的「跨开放生态的空间可组合性」(4000+ 独立作者插件仅靠协效应契约协作、IM 适配器/数据库驱动即插即换、提供者重配只重激活解析结果变化的依赖者),正在 dsh-plugin 话题下复现:20+ 活跃仓库(2026-08 快照)涵盖设计插件(open-design 87.6k★)、桌面端(deepseek-harness-desktop 9.2k★)、Web UI 合集(dsh-web-ui)、Agent VFS(mirage)、awesome 清单等------多数同时兼容 Claude Code / Codex,TypeScript 占 9/20。
#mermaid-svg-u5FAiZns3pLkunCA{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-u5FAiZns3pLkunCA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-u5FAiZns3pLkunCA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-u5FAiZns3pLkunCA .error-icon{fill:#552222;}#mermaid-svg-u5FAiZns3pLkunCA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-u5FAiZns3pLkunCA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-u5FAiZns3pLkunCA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-u5FAiZns3pLkunCA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-u5FAiZns3pLkunCA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-u5FAiZns3pLkunCA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-u5FAiZns3pLkunCA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-u5FAiZns3pLkunCA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-u5FAiZns3pLkunCA .marker.cross{stroke:#333333;}#mermaid-svg-u5FAiZns3pLkunCA svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-u5FAiZns3pLkunCA p{margin:0;}#mermaid-svg-u5FAiZns3pLkunCA .edge{stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .section--1 rect,#mermaid-svg-u5FAiZns3pLkunCA .section--1 path,#mermaid-svg-u5FAiZns3pLkunCA .section--1 circle,#mermaid-svg-u5FAiZns3pLkunCA .section--1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section--1 text{fill:#ffffff;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon--1{font-size:40px;color:#ffffff;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge--1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth--1{stroke-width:17;}#mermaid-svg-u5FAiZns3pLkunCA .section--1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:#ffffff;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-0 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-0 path,#mermaid-svg-u5FAiZns3pLkunCA .section-0 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-u5FAiZns3pLkunCA .section-0 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-0{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-0{stroke-width:14;}#mermaid-svg-u5FAiZns3pLkunCA .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-1 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-1 path,#mermaid-svg-u5FAiZns3pLkunCA .section-1 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-1 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-1{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-1{stroke-width:11;}#mermaid-svg-u5FAiZns3pLkunCA .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-2 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-2 path,#mermaid-svg-u5FAiZns3pLkunCA .section-2 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-2 text{fill:#ffffff;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-2{stroke-width:8;}#mermaid-svg-u5FAiZns3pLkunCA .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:#ffffff;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-3 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-3 path,#mermaid-svg-u5FAiZns3pLkunCA .section-3 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-3 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-3{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-3{stroke-width:5;}#mermaid-svg-u5FAiZns3pLkunCA .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-4 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-4 path,#mermaid-svg-u5FAiZns3pLkunCA .section-4 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-4 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-4{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-4{stroke-width:2;}#mermaid-svg-u5FAiZns3pLkunCA .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-5 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-5 path,#mermaid-svg-u5FAiZns3pLkunCA .section-5 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-5 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-5{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-5{stroke-width:-1;}#mermaid-svg-u5FAiZns3pLkunCA .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-6 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-6 path,#mermaid-svg-u5FAiZns3pLkunCA .section-6 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-6 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-6{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-6{stroke-width:-4;}#mermaid-svg-u5FAiZns3pLkunCA .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-7 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-7 path,#mermaid-svg-u5FAiZns3pLkunCA .section-7 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-7 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-7{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-7{stroke-width:-7;}#mermaid-svg-u5FAiZns3pLkunCA .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-8 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-8 path,#mermaid-svg-u5FAiZns3pLkunCA .section-8 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-8 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-8{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-8{stroke-width:-10;}#mermaid-svg-u5FAiZns3pLkunCA .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-9 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-9 path,#mermaid-svg-u5FAiZns3pLkunCA .section-9 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-9 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-9{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-9{stroke-width:-13;}#mermaid-svg-u5FAiZns3pLkunCA .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-10 rect,#mermaid-svg-u5FAiZns3pLkunCA .section-10 path,#mermaid-svg-u5FAiZns3pLkunCA .section-10 circle,#mermaid-svg-u5FAiZns3pLkunCA .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-10 text{fill:black;}#mermaid-svg-u5FAiZns3pLkunCA .node-icon-10{font-size:40px;color:black;}#mermaid-svg-u5FAiZns3pLkunCA .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .edge-depth-10{stroke-width:-16;}#mermaid-svg-u5FAiZns3pLkunCA .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-u5FAiZns3pLkunCA .lineWrapper line{stroke:black;}#mermaid-svg-u5FAiZns3pLkunCA .disabled,#mermaid-svg-u5FAiZns3pLkunCA .disabled circle,#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:lightgray;}#mermaid-svg-u5FAiZns3pLkunCA .disabled text{fill:#efefef;}#mermaid-svg-u5FAiZns3pLkunCA .section-root rect,#mermaid-svg-u5FAiZns3pLkunCA .section-root path,#mermaid-svg-u5FAiZns3pLkunCA .section-root circle{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-u5FAiZns3pLkunCA .section-root text{fill:#ffffff;}#mermaid-svg-u5FAiZns3pLkunCA .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-u5FAiZns3pLkunCA .edge{fill:none;}#mermaid-svg-u5FAiZns3pLkunCA .eventWrapper{filter:brightness(120%);}#mermaid-svg-u5FAiZns3pLkunCA :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 2020 Koishi 聊天机器人框架上线(cordis v3,4000+ 插件生态) 2026 论文《Spatiotemporal Composability》定稿(v4 形式化 + 演算 + 元理论) 2026 DeepSeek fork 为 @deepseek-ai/cordis@4.0.1 vendor 进 dsh 2026 dsh 开源,Everything is a Plugin,134k★ 2026 dsh-plugin 话题生态起步:20+ 仓库,Koishi 模式复现 Cordis 理论到 dsh 生态的时间线

10. 官方文档 vs 论文 vs 源码 对照表

# 论文主张(Table 2 / 正文) vendored 源码实况 判定
1 ctx.effect(callback) = Algorithm 1,逆前插 ctx.dispose Fiber.effect(fiber.ts:415);LIFO 由 DisposableList.clear() 统一 reverse(utils.ts:27-31) ✅ 一致(机制细节不同)
2 get/set 两层解析 k→ρ(k)→σ(ρ(k)) ReflectService.get/set(reflect.ts:233/254),[symbols.isolate][name]store[key] ✅ 一致
3 ctx.isolate(key, realm) / ctx.intercept(key, metadata) context.ts:121 / context.ts:141,完整实现 ✅ 一致
4 fiber 含 committed/target 字段 未按此命名;对应物为 fiber.store 快照(fiber.ts:647/687) ⚠️ 语义等价、命名不同
5 生命周期二态 + 迁移中状态 FiberState 六态(fiber.ts:147),多出 PENDING/DISPOSED ⚠️ 超集
6 ctx.use(component, config) 实例化 API 名为 ctx.plugin()(registry.ts:316) ⚠️ 名称不一致
7 错误码 INACTIVE_ACCESS / UNDECLARED_ACCESS 无具名错误码;对应字符串消息(reflect.ts:144/160),唯一结构化码是 INACTIVE_EFFECT(fiber.ts:171) ⚠️ 部分实现
8 HMR 无需开发者注解接受边界 vendor/hmr/src/index.ts,挂载于 packages/bundle/base/cordis.patch.yml:20 ✅ 一致
9 Koishi 用 cordis v3,论文呈现 v4 vendored 为 @deepseek-ai/cordis@4.0.1(package.json:4),即论文 v4 血统 ✅ 一致
10 registry = fiber 偏函数、父指针成树 RegistryService(registry.ts:195)Map<callback, Runtime>Runtime.fibers 持 fiber;counter 分配 uid(根=0) ✅ 一致

11. 一句话小结

Cordis 论文把 PL 学界的 effect/coeffect 对偶提升为运行时可操作的统一 Context 范式,以 (d,p,e) 组件演算严格化了「插件即插即拔且副作用完全可逆」;dsh vendored 的 @deepseek-ai/cordis@4.0.1 与论文 Algorithm 1--10 在语义上高度吻合(差异集中在 ctx.use→ctx.plugincommitted→store 等命名层),使 dsh 成为该理论在智能体运行时上的首个大规模产品化落地。


上一篇:A8 日志即 Seam · 本篇为架构篇增补(论文精读)· 下一篇:S1 仓库构建与环境

相关推荐
头茬韭菜3 天前
A6 · 事件体系与扩展点分类(会话 / Agent / 能力事件)
herness
头茬韭菜7 天前
A2 · Cordis 内核五概念:Context / Service / Event / Effect / Inject
herness
头茬韭菜10 天前
DeepSeek Harness 技术文档系列
herness
无心水1 个月前
【全域智能营销实战】10、三大引擎协同工作流:从用户消息到智能决策的完整链路
人工智能·springai·openclaw·顶尖架构师·全域智能营销·harmess·herness