Skip to content

把 #4632 词表扩到「启动期对注册表的终局判断」—— 一次冷启抓出 3 例,当前零防线 #4777

Description

@os-zhuang

Blocked-by: #4769
Blocked-by: #4771
Blocked-by: #4772

背景

2026-08-03 一次 showcase 冷启日志暴露了三个同形缺陷,分别落在三个互不相干的子系统(#4769 objectql 的 ADR-0104 自证、#4771 service-automation 的 flow 节点校验、#4772 plugin-auth 的 cache 探测)。三处代码此前互不知情,由三拨人在三个时期写下。

共同形状:启动期问注册表「有没有 X」,把得到的「没有」当成终局事实并记账下来 —— 缓存进进程内变量、打成断言式告警、或者(最坏的 #4769)写进数据库。提供方随后注册好了,记账却不会撤销。

完整的两轴分析和「是否要更进一步收紧 kernel 契约」的裁定请求在 #4776(needs-user-decision)。本 issue 是那份分析里不需要维护者拍板的第一步,PM 已裁定直接派发。

要做什么

沿 #4632 已经建立的机制(静默降级词表 + 门禁),把词表扩到这一类。#4632 的词表已经证明这条路能自己找活:#4669 引用它落地,#4755 的 dev 实测把 saveMetaItem 加进词表,当场抓出 8 处全静默 catch(→ #4754)。

要抓的模式,大致是这三者的组合(单独出现都可能是合法的,组合起来才是违规):

  1. 在插件 start() / 构造期 / kernel:ready 之前,读服务注册表或能力注册表(getService(...)、节点执行器表、driver 表、capability 表等);
  2. 对「读不到」这个结果做出终局判断;
  3. 把该判断记账 —— 赋值给实例字段 / 模块级变量(缓存)、logger.warn 断言式措辞、或写入持久层。

第 3 点是判定的关键,请在实现时守住:只读不记账的调用是完全合法的,不要误报。三个已知实例分别命中三种记账方式,可以拿来当测试夹具:

实例 记账方式 修复后应当不再违规
#4772 plugin-auth 缓存进实例字段 ✅ 惰性解析后不再有启动期终局判断
#4771 service-automation 断言式 warn(“will fail at execution time”) ✅ 校验推迟到 kernel:ready
#4769 objectql 写进数据库(sys_migrationattested) ✅ attestation 推迟到首启 seed 之后

为什么要等三个 PR 先落地(Blocked-by)

词表要抓的正是这三处现存代码。若门禁先于修复进 main,main 会立刻变红。三个修复都已在第 3 轮派发中,合并后再落这条门禁,可以顺带用它们验证词表:门禁在修复前的 commit 上必须报出这三处,在修复后的 commit 上必须干净。请把这个双向验证做进 PR 的证据里 —— 一个只在当前 main 上绿的门禁,无法证明它抓得到东西(参见 #4690:check:react-declaration-parity 无 MANIFEST 时静默 skip 退出 0,永远不可能红)。

已知的覆盖边界(请在 PR 里如实写明,不要粉饰)

这是文本模式匹配,覆盖面天然有限:

换句话说:这条门禁能止血,不能根治。根治与否是 #4776 要裁定的事。请不要为了让门禁看起来更强而放宽匹配 —— 误报会比漏报更快地让人关掉它。

顺带

#4773(SQL driver 注册两次)尚未定性,可能是同族第四例(若第二次注册的调用方也在做「我没看到 X,所以我来注册」这类过早判断)。该 issue 独立派发,定性后如果确属同族,回到本 issue 补进夹具表。

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions