#4535 的 C8 簇,v17 收口四簇之一 。基线行:
RetryPolicy — [./automation (type)] ≠ [./system (type)]
RetryPolicySchema — [./automation (const)] ≠ [./system (const)]
⚠️ 本簇与 C5 / C6 的关键区别:它真的在作者面上
C5 / C6 的两侧都不从 BUILTIN_METADATA_TYPE_SCHEMAS 可达 ,所以它们的可作者化 key 是过度收集产物,vanish 只是形式上的。C8 不是 —— 静态引用图复算确认 RetryPolicySchema 从元数据根集合可达 (automation 侧经 control-flow.zod.ts 的 retry: 进 FlowSchema)。
后果:本簇任何可作者化 key 消失都是真的会静默剥离作者写的值 (schema 非 .strict(),Zod 直接吞)。tombstone 要求是实打实的,不是形式主义。可作者化 key:automation 5 / system 3(自行复核)。
已知线索(开工请自行验证,不要采信)
automation/control-flow.zod.ts:179 export type RetryPolicy = z.input<typeof RetryPolicySchema>;:194 retry: RetryPolicySchema.optional()(try 区域)。
system/worker.zod.ts:94 另有一个同名不同物 的 TaskRetryPolicySchema(:152 retryPolicy:)—— 注意别把它和 system 侧真正的 RetryPolicySchema 搞混,后者声明点要自己找。
两侧 key 数不同(5 vs 3)说明形状不是简单同构,收敛方向要选得让并集 存活,或对被丢的键走完整 ADR-0087。
纪律(#4535 §1–§4,开工前必读)
默认路线:收敛 + re-export。 优先选让两侧 key 并集 存活的方向 —— 不删 key 就不需要 tombstone。
若必须丢键 ⇒ 完整 ADR-0087 :retiredKey() + src/conversions/registry.ts 的 D2 conversion + D3 chain step + major changeset。本簇可达,所以这条会真的被触发,别指望绕过。
⛔ 禁止手编 packages/spec/authorable-surface.json (authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650 )。删基线行 = 删证据,门禁不拦但这是明令禁止的。gen:schema 只允许因新增 key 而重写它。
⚠️ 注意 build-schemas.ts 检查 (b) 用叶名匹配 conversion surface —— 无关簇的 .type 就能让一个 tombstone 冒充「已登记迁移」 #4659 :检查 (b) 按 leaf name 匹配 conversion surface,无关 conversion 也能满足它。也就是说门禁绿不等于你的 conversion 真的对上了 —— 自己核对 surface 是否真指向你 retire 的那个 def,别让门禁替你判断。
改名成本取决于改哪侧 :key 记作 ${defKey}:${name},改名 ⇒ 旧 defKey 全部 key vanish。两侧都有 key,所以本簇没有零成本改名侧 。
回归 pin 用运行时模块命名空间断言 ,不要用编译期条件类型(packages/spec 的「编译期 pin」是失效的:tsconfig 排除了 *.test.ts,vitest 也不做类型检查 #4642 已证空转);必须 sabotage 验证 并在 PR 贴输出。
判不出来就升级,不要猜 (spec 双源清账 C5:ActivationEventSchema(./kernel ≠ ./studio)—— 1 条 #4653 / spec 双源清账 C6:EventSchema(./automation ≠ ./kernel)—— 1 条 #4658 先例)。分析本身就是交付物。
⛔ 不要碰 content/docs/releases/。
验收
基线删掉上面 2 行,22 → 20 (若 C5 先落则顺延),只减不增。
全绿:build、check:dual-source-exports、check:generated、test,加源码审计组(check:liveness / check:strictness-ledger / check:empty-state / check:variant-docs / check:exported-any / check:skill-examples),以及全仓 pnpm typecheck。
删 zod 形状则同步 docs/audits/2026-07-unknown-key-strictness-ledger.md。
changeset 一份,@objectstack/spec major,含 FROM → TO 与迁移指引。
关联:#4535 (主单)、#4650 / #4659 (门禁漏洞)、#4642 (pin 空转)、ADR-0049、ADR-0087、ADR-0104
#4535 的 C8 簇,v17 收口四簇之一。基线行:
C5 / C6 的两侧都不从
BUILTIN_METADATA_TYPE_SCHEMAS可达,所以它们的可作者化 key 是过度收集产物,vanish 只是形式上的。C8 不是 —— 静态引用图复算确认RetryPolicySchema从元数据根集合可达(automation 侧经control-flow.zod.ts的retry:进FlowSchema)。后果:本簇任何可作者化 key 消失都是真的会静默剥离作者写的值(schema 非
.strict(),Zod 直接吞)。tombstone 要求是实打实的,不是形式主义。可作者化 key:automation 5 / system 3(自行复核)。已知线索(开工请自行验证,不要采信)
automation/control-flow.zod.ts:179export type RetryPolicy = z.input<typeof RetryPolicySchema>;:194retry: RetryPolicySchema.optional()(try 区域)。system/worker.zod.ts:94另有一个同名不同物的TaskRetryPolicySchema(:152retryPolicy:)—— 注意别把它和system侧真正的RetryPolicySchema搞混,后者声明点要自己找。纪律(#4535 §1–§4,开工前必读)
retiredKey()+src/conversions/registry.ts的 D2 conversion + D3 chain step + major changeset。本簇可达,所以这条会真的被触发,别指望绕过。packages/spec/authorable-surface.json(authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650)。删基线行 = 删证据,门禁不拦但这是明令禁止的。gen:schema只允许因新增 key 而重写它。.type就能让一个 tombstone 冒充「已登记迁移」 #4659:检查 (b) 按 leaf name 匹配 conversion surface,无关 conversion 也能满足它。也就是说门禁绿不等于你的 conversion 真的对上了 —— 自己核对 surface 是否真指向你 retire 的那个 def,别让门禁替你判断。${defKey}:${name},改名 ⇒ 旧defKey全部 key vanish。两侧都有 key,所以本簇没有零成本改名侧。content/docs/releases/。验收
build、check:dual-source-exports、check:generated、test,加源码审计组(check:liveness/check:strictness-ledger/check:empty-state/check:variant-docs/check:exported-any/check:skill-examples),以及全仓pnpm typecheck。docs/audits/2026-07-unknown-key-strictness-ledger.md。@objectstack/specmajor,含 FROM → TO 与迁移指引。关联:#4535(主单)、#4650 / #4659(门禁漏洞)、#4642(pin 空转)、ADR-0049、ADR-0087、ADR-0104