ΓDocsInteractiveNet

08 · 架构决策记录(ADR)

格式:Context → Decision → Alternatives → Consequences。 状态:accepted / proposed / superseded。新决策追加编号,不删除旧记录。


ADR-001 · 双轨 monorepo,共享交互网内核

Status: accepted

Context:教材与生产运行时如果各写一套引擎,语义会漂移;教材演示的规则可能在生产里不成立,调试器也无法复用。

Decision:单 monorepo;ain-core 同时编译到 native 与 WASM;Netbook 与 aind 都依赖它;trace 格式共享。

Alternatives:

  • 两个独立仓库:迭代快,但语义漂移风险高。
  • 教材用 JS 重写解释器:前端简单,但无法保证一致。

Consequences:

  • 需要维护 WASM 边界与 API 兼容。
  • 核心 crate 不能依赖 tokio/OS,必须 no_std + alloc 友好。
  • 教材的 golden trace 直接成为运行时的测试用例(优点)。

ADR-002 · AIN = 标准交互网 + 受控扩展

Status: accepted

Context:标准交互网无法表达同步、效果、位置、失败、成本;完整 multiport IN 表达力强但实现/类型复杂。

Decision:纯核保持标准二元交互网(γ/δ/ε + 构造子)。在此之上分层加: L1 状态(state-indexed agents)、L2 同步(Join/Select/Gate/Barrier)、L3 Effects、L4 Locations、L5 Supervision、L6 Cost。

Alternatives:

  • 直接实现完整 multiport IN:理论优雅,但 v1 工程风险高。
  • 直接用 actor 模型:工程成熟,但失去图重写/合流/共享的差异化。
  • 只用标准 IN + 外部编排:核心干净,但无法表达 Agent 的关键需求。

Consequences:

  • 需要证明/测试每层扩展不破坏纯子集的性质。
  • 用户 agent 是单 principal(v1),同步原语是独立的 multiport cell;语义边界清晰。
  • 未来可升级到完整 multiport,不影响表面语言。

ADR-003 · 运行时用 Rust,前端用 WASM

Status: accepted

Context:需要接近 HVM 的性能、无 GC 的确定性、可嵌入 Web。

Decision:核心与运行时用 Rust;ain-wasm 用 wasm-bindgen;前端不重写引擎。

Alternatives:

  • C/C++:性能好,但内存安全/工具链/包管理差。
  • Zig:有潜力,但生态/招聘/库不足。
  • TypeScript:前端快,但性能与并行不够。

Consequences:

  • 需要处理 WASM 内存/线程(SharedArrayBuffer)限制;v1 WASM 单线程足够。
  • Rust 编译时间/学习曲线;用 workspace + 增量构建缓解。

ADR-004 · 自研运行时,不直接依赖 HVM

Status: accepted

Context:HVM2/3/4 是优秀的纯 IC 运行时,但没有 Agent 状态、effects、分布式、能力安全、成本调度。

Decision:自研 ain-core/ain-runtime,借鉴 HVM 的内存布局与原子链接;HVM 作为基准与可选后端,不是依赖。

Alternatives:

  • Fork HVM:起步快,但会被其架构/路线绑定;effects/分布式改动大。
  • 只做 HVM 上的 DSL:最省力,但无法控制调度/持久化/安全。

Consequences:

  • 需要自己实现/验证原子链接、GC、work stealing;工作量大。
  • 保持 IR 兼容,未来可把纯子网卸载到 HVM/GPU。

ADR-005 · 状态用 state-indexed agents 编码

Status: accepted

Context:IN 规则按 agent 类型匹配,每对至多一条;Agent 需要多阶段状态。

Decision:Agent<S> 编译为多个 agent 符号(Agent_Idle, Agent_Working, …);规则按状态对生成。运行时 cell 状态不可变(纯子集)。

Alternatives:

  • 运行时可变状态:实现简单,但破坏纯合流/重放。
  • 用消息携带状态:可行,但每次交互复制状态,成本高。

Consequences:

  • 规则表规模 = 状态数 × 消息类型数;用索引/特化控制。
  • 状态转移 = cell 替换;旧 cell 被回收(线性)。
  • 调试器能直接看到状态名(优点)。

ADR-006 · Effects 作为显式 cell + 确定性日志

Status: accepted

Context:LLM/工具/人工调用是非确定性、高延迟、有成本的;纯网无法表达。

Decision:Effect<Op> cell + 异步 job;结果注入为 Result/Error cell;所有 effect 记录到不可变日志;重放时注入而非重调。

Alternatives:

  • 把 effect 当普通 host function(同步阻塞):简单,但阻塞 worker、无法重放。
  • 把 effect 结果当外部状态,不做日志:轻量,但无法确定性重放/审计。

Consequences:

  • 需要幂等键/去重表;LLM 无法真正 exactly-once,只能记账 + 去重。
  • 日志可能含敏感数据;需要加密/脱敏/保留策略。
  • 重放速度远高于实时(优点)。

ADR-007 · 分布 = cell 归属 + 远程通道,不共享堆

Status: accepted

Context:跨机共享图/锁的代价高、故障复杂;Agent 工作负载是消息/IO 密集。

Decision:每个 cell 有唯一 owner;只有 owner 点火;跨节点 wire 编译为有序远程通道;活跃对永远本地;迁移是显式的 lease + 序列化。

Alternatives:

  • 分布式共享内存/全局图:编程简单,但一致性/故障/性能都难。
  • 纯 actor(无图):成熟,但失去图级 trace/共享/合流。

Consequences:

  • 放置/迁移/路由成为核心组件;跨节点消息有延迟。
  • 无分布式锁(优点);故障恢复靠检查点/重放。
  • v1 静态 3 节点;动态成员 v2。

ADR-008 · 语言双层:Core + Flow

Status: accepted

Context:研究者要精确控制网/规则;Agent 工程师要写流水线,不想学 λ 演算。

Decision:Core 暴露 agent/port/rule/net;Flow 提供 agent/stage/->/par/race/supervise/budget;两者编译到同一 IR,可互相下探。

Alternatives:

  • 只做 Core:语义干净,但采用门槛高。
  • 只做 Flow:易用,但无法表达自定义规则/研究。
  • 两门独立语言:灵活,但语义漂移/工具重复。

Consequences:

  • 需要维护两套语法/诊断,但共享 AST/类型/IR。
  • Flow 的每个构造必须有明确的 Core lowering(文档 + 测试)。
  • SDK 可以直接生成 Core AST(绕过文本)。

ADR-009 · Netbook 技术栈:Astro + Svelte 5 + PixiJS + WASM

Status: accepted

Context:内容是主体、交互是核心;需要静态部署、离线、几千节点的 60fps。

Decision:Astro 7 静态站点 + Svelte 5 islands + PixiJS 8 画布 + Rust/WASM 引擎 + MDX + KaTeX。

Alternatives:

  • Next.js + React Flow:生态好,但端口级交互/性能不匹配。
  • 纯 SVG/DOM:可访问性好,但几千节点动画会卡。
  • Unity/WebGL 游戏引擎:性能好,但包体/内容集成差。

Consequences:

  • 需要自研布局/交互/动画(可控,但工作量大)。
  • SVG 覆盖层保证可访问性;PixiJS 负责性能。
  • WASM 包体需控制在 600KB gzip 内。

ADR-010 · 端口即能力(capability security)

Status: accepted

Context:Agent 框架普遍给全局工具注册表;prompt injection 可越权。

Decision:没有全局名字/工具表;Agent 只能沿已连接的端口通信;工具 capability 由宿主显式注入,可撤销;WASM 沙箱执行用户规则。

Alternatives:

  • RBAC/ABAC:表达力强,但运行时检查复杂,且默认权限容易过宽。
  • 仅靠 prompt 约束:不可靠。
  • 进程级隔离:必要但不充分(Agent 仍可调用全局工具)。

Consequences:

  • 网构造时必须显式接线;动态发现/市场需要额外的 capability 分发机制。
  • 审计简单:一条消息的路径就是权限路径(优点)。
  • 需要 threat model + 渗透测试。

ADR-011 · Trace 是一等公民,格式共享

Status: accepted

Context:可观测性通常是事后拼日志;教材动画与生产调试各写一套。

Decision:运行时输出结构化 trace(step/effect/remote);Netbook、ain trace view、重放、测试都用同一格式;trace 带版本与 hash 链。

Alternatives:

  • 只输出日志/OTel span:通用,但缺少图结构。
  • 只存快照:简单,但体积大、无法看过程。

Consequences:

  • 需要设计 delta 编码/压缩;大网 trace 可能很大。
  • 每步 hash 校验增加开销(可采样)。
  • 教材/调试器/测试共享(优点)。

ADR-012 · 确定性分级,默认 at-least-once + 幂等

Status: accepted

Context:不同场景对一致性/性能要求不同;LLM 调用无法真正 exactly-once。

Decision:提供 ephemeral / at-least-once / exactly-once-effects / strict 四档;默认 at-least-once + 幂等键;文档明确语义。

Alternatives:

  • 默认 strict:安全但慢,且 LLM 仍无法 exactly-once。
  • 默认 ephemeral:快,但事故无法复现。

Consequences:

  • 用户必须理解幂等键/去重;SDK 提供默认实现。
  • 预算/账本需要处理重复调用(按 job_id 去重)。
  • 重放保证的是"记录的结果",不是"重新调用得到相同结果"。

ADR-013 · 许可与治理

Status: proposed

Context:核心要可嵌入/商业化;教材要可复用。

Decision(建议):

  • 代码:MIT 或 Apache-2.0(双许可,跟 Rust 生态一致)。
  • 文档/课程:CC BY 4.0。
  • 规范:CC0 或 Apache-2.0(鼓励实现)。
  • 贡献:DCO(不用 CLA),保持开放。
  • 商标:项目名/logo 单独保护(若商业化)。

Alternatives:

  • AGPL:保护开源,但阻碍商业采用。
  • 纯 MIT:最宽松,但缺少专利授权。

Consequences:

  • 需要在 M0 做 license audit(HVM/Inpla/Vine 的许可)。
  • 商业版(托管/支持)与开源核心分离。

ADR-014 · v1 不追求完整 multiport / π 演算

Status: accepted

Context:完整 multiport 表达力强,但规则匹配、类型、调度、调试都复杂。

Decision:v1 只实现 Join/Select/Gate/Barrier 四种同步 cell;用户 agent 单 principal;不实现通道名传递/移动。

Alternatives:

  • 完整 π/multiport:研究价值高,但产品风险大。
  • 完全不做同步:无法表达 Agent 协作。

Consequences:

  • 动态拓扑(Agent 运行时创建新连接)受限;v1 用预连接 + 路由器。
  • 未来可在 L2 增加 New/Send name,升级到 π 子集。
  • 类型/死锁检查先保守,运行时超时兜底。

ADR-015 · 先做 Netbook MVP,再做运行时

Status: accepted

Context:两者都大;Netbook 能更早获得用户/反馈,并为运行时积累测试/可视化。

Decision:M1 先发布第 1–3 章 + sandbox;M2 再做 Ainet 单机;共用核心。

Alternatives:

  • 先做运行时:技术风险先解决,但 6 个月没有可见成果。
  • 并行做:资源够可以,但单人/小团队容易两头不讨好。

Consequences:

  • 核心 IR 必须先稳定(M0),否则 Netbook 返工。
  • Netbook 的用户反馈会影响语言/运行时设计(好事)。
  • 发布节奏:先教学、后基础设施。

在 GitHub 编辑本文