Code Review 规约必须把架构判断转换成可执行约束。单独写“职责要清晰”或“生命周期顺序要正确”只是结论;完整规约还要说明何时适用、必须做什么、如何验收、产生什么收益,以及如何限制修复本身的副作用。

1. 规约条目的固定结构

本文每条规约都包含以下字段:

字段要回答的问题
触发场景出现什么代码形态、依赖或行为变化时应用本规约?
必须动作Author 和 Reviewer 必须建立或修改什么约束?
验收标准哪些可观察后置条件成立才算完成?
预期收益规约降低什么风险,或获得什么工程能力?
副作用边界为实现规约不得额外引入什么复杂度、耦合或行为变化?
验证证据用什么测试、类型约束或运行结果证明验收标准?

文中的“必须”对应合并前要求;“应”允许在 PR 中给出明确理由后偏离;“可以”表示不影响合并的实现选择。

2. 按改动场景选择规约

Reviewer 先按改动信号匹配规约,不要求所有 PR 机械套用全部条目。

改动信号主要适用规约
公共层开始访问内部字段,或资源在一个模块创建、另一个模块清理R1 职责与所有权、R4 可组合契约、R5 最小副作用修复
新增 close、后台任务、线程、进程、runtime 或嵌套 handleR2 依赖生命周期、R3 状态 authority
多个参与者共享 closed、event、lease 或 cleanup 状态R1 职责与所有权、R3 状态 authority
新增 adapter、替换 backend、父模块包装子模块R1 职责与所有权、R4 可组合契约、R5 最小副作用修复
close 与在途操作并发,或外层锁跨越内部阻塞调用R2 依赖生命周期、R3 状态 authority
源码、配置、文档、日志、截图、测试夹具或生成产物涉及认证材料或真实环境标识R6 敏感信息与环境脱敏
纯局部算法改动,不改变边界、资源或生命周期不强制建立完整生命周期模型;按正确性和局部测试 Review

3. 可执行规约

R1:跨模块状态和资源必须有唯一 owner

字段规约
触发场景改动跨越公共层、组合层和内部模块;新增共享资源;出现重复 close;或外层直接修改内部状态。
必须动作列出受影响状态和资源的创建者、借用者、共享者与最终释放者。每个资源指定唯一 final-release authority。公共层只表达稳定契约;组合层只安排模块顺序;内部模块维护自己的状态、不变量和 cleanup。
验收标准每个资源都能回答“谁最后释放”;借用方不会释放 owner 资源;外层不通过内部字段完成 cleanup;替换内部实现时,公共层和组合层的生命周期逻辑不变。
预期收益职责高内聚,避免重复释放和无人释放,缩小修改传播范围,使模块可独立测试和替换。
副作用边界不为形式上的分层拆出无状态薄模块;不扩大公共 API;不把原本局部的资源提升为全局共享;不顺带迁移无关职责。
验证证据ownership 表或类型关系、公共契约测试,以及证明 borrower close 不破坏 owner 资源、独占 owner close 完成释放、共享 authority 遵守约定释放条件的测试。

R2:有依赖关系的生命周期必须按偏序执行

字段规约
触发场景对象依赖其他 runtime、transport、存储、worker、线程、进程或 handle 才能工作;新增启动、关闭、重启或热替换流程。
必须动作写出依赖 DAG。若 A 依赖 B,初始化满足 B → A,销毁满足 A → B。关闭依次建立 admission barrier、传播 wake/cancel、收敛 in-flight、join 后台任务、逆依赖释放、发布完成。锁层级和 callback 方向必须与依赖方向兼容。
验收标准关闭开始后不再接收新操作;被依赖资源释放前,所有依赖方已经静默;close 返回后,该生命周期边界内不再有任务、callback 或 handle 使用其拥有的资源;重复 close 能到达同一终态。
预期收益获得确定性启停,避免 use-after-close、关闭死锁、悬挂后台任务和依赖提前释放。
副作用边界只排序真实依赖;互不依赖的分支可以并行关闭。不要为了统一顺序引入全局锁或全局 coordinator;wake/cancel 只作用于本次关闭拥有的范围。
验证证据真实生命周期测试、并发 close 与在途操作测试、超时测试,以及 close 返回后无后台活动的完成屏障测试。

R3:停止命令、进行状态和完成证明必须由明确 authority 管理

字段规约
触发场景一个布尔值或 event 同时被多个对象读写;停止请求与资源释放异步;close 可重试;或不同层都能发布 closed。
必须动作为每个状态标明作用域、唯一 writer 和语义。区分停止命令、Closing 过程与 Closed 完成证明。同一作用域优先使用单调状态机;不同作用域的信号和完成状态分别由各自 owner 管理。只发信号的接口命名为 request_shutdown() 或等价语义。
验收标准其他参与者发出 stop 不会让本模块跳过 cleanup;只有 owner 能发布本模块完成;状态只向终态推进;失败或重试不会重新开放入口,也不会永久跳过未完成步骤。
预期收益消除共享布尔值的语义歧义,使关闭可重试、可等待、可观测,并避免提前返回和资源泄漏。
副作用边界不为同一个事实增加多个 source of truth;简单同步对象不引入多余状态;能用有限 enum 表达时不扩散布尔组合;不保留旧状态别名形成兼容分支。
验证证据状态转换测试、多参与者先后发 stop 的测试、部分构造和部分 cleanup 失败后的重试测试。

R4:子模块生命周期契约必须能够被父模块直接组合

字段规约
触发场景父模块包装子模块、新增 adapter 或 backend、一个 close 需要调用多个子模块,或错误需要跨层传播。
必须动作为子模块定义生命周期前置条件、成功后置条件和失败后置条件。create / release、register / unregister、spawn / join、subscribe / cancel 必须成对。父模块只调用子模块契约并安排顺序,不复制其 cleanup 实现。独立 cleanup 即使部分失败也继续执行,并保留主错误和 teardown error。
验收标准父模块不检查子模块内部字段就能决定下一步;子模块 close 返回后满足父模块逆序释放所需条件;替换一个符合契约的实现不要求修改父模块;失败结果能说明哪些后置条件尚未满足。
预期收益局部正确性可以组合为系统正确性,backend 可替换,错误因果不丢失,模块可以独立演进。
副作用边界不为假设中的未来实现提前设计通用框架;只抽象已经稳定的共同语义;特化 fast path 留在模块内部;不把所有错误压成无信息的统一返回值。
验证证据contract test、替代实现或 test double 的一致性测试、部分子模块关闭失败时其余 cleanup 仍执行的测试。

R5:修复必须落在不变量的 authority 处,并限制改动半径

字段规约
触发场景修复方案准备在外层增加判断、直接置空内部字段、增加全局 flag、兼容分支或新的配置入口,以绕过内部职责或生命周期问题。
必须动作找到被破坏不变量的 owner,在 owner 内修复状态、cleanup 或契约;组合层只调整必要顺序。明确本次非目标,删除被新契约取代的 workaround,并只回归受影响边界。
验收标准修复后跨边界知识减少或不增加;没有新增重复入口、并行配置通道或第二套生命周期路径;无关公共行为保持不变。
预期收益修复根因而非症状,降低回归范围,避免兼容层和条件分支持续累积。
副作用边界不借机重写无关模块;不以“统一架构”为由扩大迁移范围;若公共契约必须变化,单独说明迁移和影响,不能夹带在内部修复中。
验证证据修复前反例、修复后不变量测试、受影响调用方回归,以及 diff 中没有新增旁路的检查。

R6:仓库和公开产物不得暴露敏感信息或私有环境标识

字段规约
触发场景改动包含源码、配置、示例、文档、CI、日志、堆栈、截图、录屏、测试夹具、报告或其他生成产物,并且其中可能带入真实个人环境、开发 / 测试 / 生产集群信息或认证材料。
必须动作识别并移除密码、Token、API key、访问密钥、私钥、cookie、session、带凭证的连接串等认证秘密。对未经明确批准公开的真实 IP 地址、域名、主机名、用户名、节点名、cluster ID、端口映射、存储路径和集群拓扑做脱敏。文档和示例使用 example.comexample-node-a 以及 RFC 5737 的 192.0.2.0/24198.51.100.0/24203.0.113.0/24 等保留占位符。运行时秘密通过项目已有的标准 secret / 配置机制提供;日志、截图和生成产物在纳入版本控制或上传前完成脱敏。
验收标准tracked diff、二进制资源和待发布产物中不存在有效或疑似有效的认证秘密,也不存在未经批准的真实私有环境标识;错误和日志输出会对敏感值做省略或掩码;同一示例中的占位符前后一致。若有效秘密曾进入提交或公开产物,必须先撤销或轮换,再按项目安全流程处理历史和缓存,才能批准合并。
预期收益防止凭证滥用、私有网络与集群拓扑泄露,并使文档、测试和诊断产物可以安全共享。
副作用边界不隐藏诊断所需的字段名、错误类别和因果关系;使用稳定且可关联的假值保留调试结构。已经明确授权公开的公共 endpoint 可以保留。不要为脱敏再增加平行配置通道,也不要把真实值换成看似虚构但实际可路由或可认证的值。
验证证据人工检查完整 diff 和所有图片 / 生成产物,运行仓库认可的 secret scanning,并针对 IP、主机名、路径和日志输出做定向检查;涉及 redaction 逻辑时补充测试,证明原始敏感值不会进入输出。

4. Review 输出与合并标准

Finding 应引用规约编号,并包含触发场景、违反的验收标准、影响和要求守住的副作用边界:

[R3][blocking] 共享 stop signal 被当成了当前模块 cleanup 的完成证明。
 
触发场景:另一个参与者先设置共享状态。
违反标准:当前资源 owner 的 cleanup 被跳过,close 不再是 completion barrier。
必须动作:分离共享停止命令与本模块完成状态,并由本模块发布完成。
副作用边界:不要新增第二套公共 close API,也不要让外层直接清理内部资源。
标记合并标准
[blocking]已有合理触发路径会破坏规约验收标准,修复后才能合并。
[major]关键场景缺少约束或证据,补齐实现或验证后合并。
[minor]不影响规约验收标准的局部维护性或诊断问题,可以明确接受后续处理。
[question]触发场景、authority 或契约不清楚,回答后再定级。

R6 使用更严格的定级:有效或疑似有效的凭证、私钥,以及未经批准公开的真实 IP、主机名或集群拓扑一律标记为 [blocking]。无法确认某项环境信息是否允许公开时先标记为 [question],确认前不得 Approve。

  • Request changes:存在未解决的 [blocking] / [major],或无法确定适用规约的 owner、依赖与验收标准。
  • Approve:所有匹配规约的必须动作已完成,验收标准有证据,预期收益成立且副作用保持在声明边界内。
  • Comment:仅剩澄清问题或不影响验收标准的建议。

文档类 PR 还应遵守文档写作规约技术文档审校