Skip to content

06 · 架构防线

所有权、注册与单一事实源 ​

关键文件docs/defensive-patterns/README.mddocs/defensive-patterns/general.mdpackages/AGENTS.mddocs/architecture.md.agents/skills/cordis-styling-nitpicking/

docs/defensive-patterns/ 里每条规则都写明了必须成立的条件、评审者据以判断的标准、适用边界和谁能批准例外,并附正反两个例子。README 总结了贯穿所有规则的五个习惯:

习惯含义
正确性写进结构用具名调用点、显式生命周期、显式条件和类型保证正确,不靠时序事后补救
单一事实源一份数据只有一条读取路径,一个事实只有一个家,共享状态只有一个 owner
通过注册扩展新能力自己注册;已有的承载层不再接收新逻辑
改动面等于评审面改动只包含行为变化需要的行;迁移是移动代码而不是重写;性能敏感的改动附测量数据
要求证据断言必须可证伪、可重算:前后实测,或由门禁检查,不靠手工同步
拒绝:中心层写业务分支要求:业务包自己注册Manager / Gatewayif (name === 'attachment') {…}if (name === 'todo') {…}if (name === 'plan') {…}attachmenttodoplan调用中心层认识每个业务,每加一个能力都要改它注册表只持有结构与 dispose 生命周期条目条目条目attachmenttodoplan注册每个包在自己的 apply 里经 ctx.effect() 注册,dispose 时条目自动移除
箭头方向就是区别。左边中心层调用业务,新能力都要修改它,它会变成冲突热点。右边业务包向注册表注册,中心层只管结构和生命周期。规则原文:"A new branch in a center layer must explain why it cannot live in the owning package."

packages/AGENTS.md 里的设计规则 ​

  • 要有当前的 owner 和需求:每个抽象、状态机、选项、防御性拷贝和兼容路径都对应一个当前契约或生产消费者。
  • 公共选择要有证据:"可以配置"不能成为不受支持的默认值或公共操作集的理由。没有当前消费者的证据或先例,就要求显式值,或推迟决定。
  • 服务契约为所有消费者设计:反过来,一个只有一个内部调用方的公共服务方法属于不必要的 API 扩张,应改为构造时传入的私有闭包。
  • 共享状态要有 owner:挂在服务或实例上。模块级缓存、单例、全局 WeakMap、Symbol.for / globalThis 都会隐藏 owner,不再新增全局的 current / active / selection。
  • 在做决定的操作里强制执行:schema 省略、prompt 过滤、外观层、包装器和监听器顺序都可能被直接调用者绕过,不算强制执行。拒绝路径要通过执行器测试。
  • 只在提交点发布状态:操作成功后才发通知、更新派生状态;缓存、prompt、UI 回显、回放和查询视图都从同一个权威源派生。
  • 边界作用于完整结果:字节、token、条数、时间限制在完整的输出值(含包装和元数据)已知的位置执行,测试极小值、恰好等于上限、超大单块和多字节文本。
  • 一个异步操作只有一个生命周期控制器:就绪、取消、销毁、预留各自需要独立的 owner;否则合并到一个控制器。

Cordis 插件的三条 P0 ​

插件框架里最容易出错的是生命周期。根 AGENTS.md 要求所有注册都经过 ctx.effect() / ctx.on(),register() 返回销毁函数;waterfall 监听器必须调用 next()。cordis-styling-nitpicking 在评审时检查三类 P0 问题:单例状态、没有撤销的副作用、清理依赖先于消费者完成就被释放。每个注册表贡献都要有"销毁后条目被移除"的测试。

其他 general.md 规则(节选) ​

  • 时序不承载正确性:不靠 queueMicrotask、setTimeout(…, 0) 或 React effect 的时机保证正确,因为这类代码轻负载下成立、重负载下静默失败。
  • 正交结果分别报告:进程可能既超时又以 0 退出。timedOut、signal、exitCode 各自独立暴露。
  • 迁移保持行为不变:移动代码优于重写;迁移中发现的缺陷单独修。
  • 销毁要等到静止:kill 或 abort 之后要等子进程真正退出。
  • 改动附性能证据:同一环境、同一输入下,测运行时间、峰值内存、稳态内存。"整体没变慢"不算证据。

依据 deepseek-harness 仓库 master 分支及其 git 历史整理