#4535 的 C9 簇,v17 收口三簇之一 。基线行:
RateLimitConfig — [./integration (type)] ≠ [./shared (type)]
RateLimitConfigSchema — [./integration (const)] ≠ [./shared (const)]
基线现为 19 条 ,本簇目标 19 → 17 。
本簇在作者面上 —— tombstone 风险是真的
静态引用图确认 RateLimitConfigSchema 从 BUILTIN_METADATA_TYPE_SCHEMAS 可达 。已知嵌入点(开工请自行复核):
侧
嵌入点
可作者化 key
./shared
shared/http.zod.ts:144 声明;api/endpoint.zod.ts:47 与 api/registry.zod.ts:379 的 rateLimit:
3
./integration
integration/connector.zod.ts:336 声明
6
任何可作者化 key 消失都会真的静默剥离作者写的值 (schema 非 .strict(),Zod 直接吞)。
C8 是最接近的先例 (RetryPolicy,同样两侧都活、都可达):它把单一声明放进 shared/retry-policy.zod.ts、由两个入口 re-export,利用「发布的 def key 由入口命名空间 决定」这一点,让两个 def key 都存活且 key 集相同 —— 因此只付了 1 个 key 的代价而不是 8 个。本簇很可能适用同一手法 (注意 ./shared 侧的声明已经在 shared/http.zod.ts,情况可能更简单)。
纪律(#4535 §1–§4 + 手册 6/7/8,开工前必读)
默认路线:收敛 + re-export,优先选让两侧 key 并集存活的方向。 不删 key 就不需要 tombstone。若两侧存在「同一概念两种拼法」(C8 的 retryDelayMs vs backoffMs),并集保全不可行 —— 同时声明两者是 alias 反模式,必须选一个并对被丢的键走完整 ADR-0087。
⛔ 禁止手编 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 也能满足。自己枚举 ALL_CONVERSIONS 的 clause,确认以你 retire 的那个叶名结尾的全仓只有 1 条且就是你的 (C8 的做法)。
⚠️ 默认值 / 约束的变更不被任何门禁记录(spec 门禁盲区:可作者化 key 的「默认值 / 约束」变更不被任何 gate、tombstone 或 conversion 记录(#4650 / #4659 同族) #4666 )。 若收敛导致某个 .default() 或 .min()/.max() 改变,必须 用手写运行时测试钉住,并在 changeset 里显式写明;若存量文档会因此改变行为,用 conversion 显式物化 旧值(C8 的做法:把 pre-17 默认值写进每个省略了它的存量文档,已部署栈行为不变)。
回归 pin 用运行时模块命名空间断言 (packages/spec 的「编译期 pin」是失效的:tsconfig 排除了 *.test.ts,vitest 也不做类型检查 #4642 已证编译期 pin 空转),必须 sabotage 验证 并贴输出。
判不出来就升级,不要猜 (spec 双源清账 C5:ActivationEventSchema(./kernel ≠ ./studio)—— 1 条 #4653 / spec 双源清账 C6:EventSchema(./automation ≠ ./kernel)—— 1 条 #4658 / spec 双源清账 C8:RetryPolicy / RetryPolicySchema(./automation ≠ ./system)—— 2 条 #4661 先例)。分析本身就是交付物。
⚠️ 生成物冲突只能靠重新生成 (手册第 7 条,2026-08-02 实测教训)。main 在 v17 收尾期前进很快,你跑完门禁大概率已落后。推之前重新 git fetch origin main 判一次 ;要合并时:字符串数组可集合合并,spec-changes.json 是对象数组,必须跑 gen:spec-changes (集合合并会丢条目,已把 CI 打红过)。pnpm install --filter @objectstack/spec... 走缓存约 2.5 秒,生成器秒级。解完冲突务必本地跑对应 check:* 再推。
⛔ 不要碰 content/docs/releases/ 。
验收
基线删掉上面 2 行,19 → 17 ,只减不增。
全绿: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 与迁移指引。
注意 spec 现为 17.0.0-rc.1、pre-mode 仍开;major 通道在 changeset pre exit 关闭。
关联:#4535 (主单)、#4661 / PR #4670 (最接近的先例)、#4650 / #4659 / #4666 (门禁洞)、#4642 (pin 空转)、#4675 (生成物冲突)、ADR-0049、ADR-0087、ADR-0104
#4535 的 C9 簇,v17 收口三簇之一。基线行:
基线现为 19 条,本簇目标 19 → 17。
本簇在作者面上 —— tombstone 风险是真的
静态引用图确认
RateLimitConfigSchema从BUILTIN_METADATA_TYPE_SCHEMAS可达。已知嵌入点(开工请自行复核):./sharedshared/http.zod.ts:144声明;api/endpoint.zod.ts:47与api/registry.zod.ts:379的rateLimit:./integrationintegration/connector.zod.ts:336声明任何可作者化 key 消失都会真的静默剥离作者写的值(schema 非
.strict(),Zod 直接吞)。C8 是最接近的先例(
RetryPolicy,同样两侧都活、都可达):它把单一声明放进shared/retry-policy.zod.ts、由两个入口 re-export,利用「发布的 def key 由入口命名空间决定」这一点,让两个 def key 都存活且 key 集相同 —— 因此只付了 1 个 key 的代价而不是 8 个。本簇很可能适用同一手法(注意./shared侧的声明已经在shared/http.zod.ts,情况可能更简单)。纪律(#4535 §1–§4 + 手册 6/7/8,开工前必读)
retryDelayMsvsbackoffMs),并集保全不可行 —— 同时声明两者是 alias 反模式,必须选一个并对被丢的键走完整 ADR-0087。packages/spec/authorable-surface.json(authorable-surface 的 tombstone 门禁可被手编基线绕过 —— 删掉基线行就删掉了证据(#4638 / #4643 已两次这样过绿) #4650)。gen:schema只允许因新增 key 而重写它。.type就能让一个 tombstone 冒充「已登记迁移」 #4659):检查 (b) 按 leaf name 匹配 conversion surface,无关 conversion 也能满足。自己枚举ALL_CONVERSIONS的 clause,确认以你 retire 的那个叶名结尾的全仓只有 1 条且就是你的(C8 的做法)。.default()或.min()/.max()改变,必须用手写运行时测试钉住,并在 changeset 里显式写明;若存量文档会因此改变行为,用 conversion 显式物化旧值(C8 的做法:把 pre-17 默认值写进每个省略了它的存量文档,已部署栈行为不变)。git fetch origin main判一次;要合并时:字符串数组可集合合并,spec-changes.json是对象数组,必须跑gen:spec-changes(集合合并会丢条目,已把 CI 打红过)。pnpm install --filter @objectstack/spec...走缓存约 2.5 秒,生成器秒级。解完冲突务必本地跑对应check:*再推。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 与迁移指引。17.0.0-rc.1、pre-mode 仍开;major 通道在changeset pre exit关闭。关联:#4535(主单)、#4661 / PR #4670(最接近的先例)、#4650 / #4659 / #4666(门禁洞)、#4642(pin 空转)、#4675(生成物冲突)、ADR-0049、ADR-0087、ADR-0104