Repository navigation
Closed
Labels
domain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchtarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GAtoolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surfaceFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
Description
由 #5483 的过渡看守(路线 1)落地后拆出的后续(未指派,记录测量与边界,不认领)。
现状
#5483 按路线 1 落地:strictUnknownKeyError 自己把 { surface, knownKeys, aliases, guidance } 登记进一张内部登记表,packages/spec/src/shared/alias-integrity.test.ts 因此把这 44 个直调点也判了 —— 零调用点改动。
实测规模:44 个源码调用点,运行时 52 张表(ui/app.zod.ts 的导航项工厂一个调用点跑九次,每个 type 变体一张)。
关键在于这批表被判到的强度不均,闸门自己也是这么写的:
| 判据 | strictObject 那 235 张 |
这 44 个直调点 |
|---|---|---|
| 别名 key 不得是已知键 | 对 .shape 判 |
对手抄数组判 |
| 别名 target 必须是已知键 | 对 .shape 判(含墓碑检查) |
对手抄数组判(墓碑不可见) |
表内 aliasProbe 不得撞车 |
判 | 判 —— 完全等价 |
第三条不依赖 shape,所以路线 1 就把它开满了(首测 52 张表 0 撞车)。前两条继承手抄数组与 shape 之间的漂移 —— 数组说 x 是已知键,而 schema 里早就没有了,闸门会照着数组给出绿灯。那正是 strictObject 存在的理由(见其 docblock:"the array is a second copy of the truth"),也正是路线 1 消不掉的那一半。
该做什么
把 44 个调用点分批迁到 strictObject(options, shape):
- 手抄的
*_KEYS数组连同它的漂移探针测试一起删除; - 这批表自动进入 shape 判据(含"别名 target 不得是墓碑"这条路线 1 看不见的);
alias-integrity.test.ts里toBeLessThanOrEqual(44)的只减不增棘轮随之降到 0;- 路线 1 的登记表(
packages/spec/src/shared/alias-table-registry.ts)与闸门里"直调点"那一整段随最后一个调用点一起删除。
分布(实测,基线见下):
ui/app.zod.ts 9 data/datasource.zod.ts 6
automation/approval.zod.ts 4 automation/flow.zod.ts 4
security/permission.zod.ts 4 data/driver/*.zod.ts 6
data/hook.zod.ts 2 data/hook-body.zod.ts 2
security/sharing.zod.ts 2 data/driver/sqlite.zod.ts (含在上面 6 里)
data/object.zod.ts 1 identity/position.zod.ts 1
security/rls.zod.ts 1 ui/action.zod.ts 1
ui/bulk-action.zod.ts 1
迁移时已知的三个坑
data/object.zod.ts的表是延迟构建的(objectUnknownKeyErrorImpl ??= …),为的是绕开一个 temporal dead zone ——UNKNOWN_KEY_GUIDANCE和 shape 都声明在它下面。改成strictObject需要先解决这个顺序问题,不是纯机械替换。ui/app.zod.ts的导航项是一个按变体拼装的工厂,九张表共用一段拼装逻辑,knownKeys是[...BASE, ...NAV_VARIANT_KEYS[variant]]。迁移意味着九个变体 schema 各自成为strictObject,extraKeys可能用得上。同一族还有ui/app.zod.ts导航项:4 条expanded别名在另外 8 个变体上把作者指向该变体同样拒绝的键(二次拒绝) #5555 那条待修缺陷,顺序上建议先修ui/app.zod.ts导航项:4 条expanded别名在另外 8 个变体上把作者指向该变体同样拒绝的键(二次拒绝) #5555 再迁,否则修法要写两遍。data/hook.zod.ts/data/hook-body.zod.ts当时在 [spec] 退役 HookContext session.roles —— #4839 双删后零消费方零生产方(ADR-0049) #5050 手里,分批时避开在飞的文件。
基线
分支 claude/issue-5483-strict-unknown-registry,origin/main 5acb93a。测量复现:pnpm --filter @objectstack/spec exec vitest run src/shared/alias-integrity.test.ts。
Metadata
Metadata
Assignees
Labels
domain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchtarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GAtoolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surfaceFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
Activity
os-zhuang commentedon Aug 5, 2026
补:路线 1 的过渡看守已落地为 PR #5609(draft),本 issue 描述的基线以那个 PR 为准。
实测数字定稿:44 个源码调用点 → 运行时 52 张表,
strictObject那边 235 张。三条判据的首测结果:probe 撞车 0 条、别名 key 不得是已知键 0 条、别名 target 必须是已知键 32 条(全部是 #5555 那一个根因)。对迁移有直接影响的一条:PR #5609 在闸门里加了两处带陈旧检查的显式豁免(
PROSE_ALIAS_TARGETS六条散文式 target、VARIANT_LEGAL_GUIDANCE两条),以及 #5555 的结构化容差。迁移ui/app.zod.ts导航项一族时,这三处会同时失去依据而转红 —— 那是预期行为,不是回归:它们的存在前提就是那批表还在直调登记表里。届时应当删除,而不是改写成新形式。Generated by Claude Code
os-zhuang commentedon Aug 5, 2026
发现分诊(#4949 纪律):晋级
pm:queue+pm:blocked(域已在domain:spec,摘finding)。strictUnknownKeyError直接调用点的别名表在 #5013 闸门覆盖之外(实测干净,但无人看守) #5483(在飞,其路线 1 看守 PR test(spec): 别名一致性闸门收编 44 个 strictUnknownKeyError 直调点 —— probe 撞车维度首测 (#5483) #5609 尚为 draft,本单基线以它为准;先落它)。ui/app.zod.ts导航族前先修ui/app.zod.ts导航项:4 条expanded别名在另外 8 个变体上把作者指向该变体同样拒绝的键(二次拒绝) #5555;避开 [spec] 退役 HookContext session.roles —— #4839 双删后零消费方零生产方(ADR-0049) #5050 在飞的data/hook*.zod.ts;PR test(spec): 别名一致性闸门收编 44 个 strictUnknownKeyError 直调点 —— probe 撞车维度首测 (#5483) #5609 的三处显式豁免届时应删除而非改写。分批节奏由 spec 座位排。本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
test(spec): 别名一致性闸门收编 44 个 strictUnknownKeyError 直调点 —— probe 撞车维度首测 (o…
os-zhuang commentedon Aug 6, 2026
打包建议(致 spec 座位):本单与 #5583 同为 strictObject 机械迁移族,建议同一接力棒内派发(一名 dev 一次落地、一 PR 多
Fixes或紧邻两棒),摊薄四步重建 + CI 圈的每单固定成本。背景:维护者 2026-08-06 拍板 spec 车道缩盘方案,见 #5837。Generated by Claude Code
hotlong commentedon Aug 7, 2026
Release-board audit (maintainer-directed re-audit of non-board
domain:specitems, 2026-08-07): addingtarget:v17— metadata-protocol change, size M, low-risk: mechanical migration of 44strictUnknownKeyErrorcall sites tostrictObject; pure strictness tightening backed by the alias-integrity gate/ratchet; batch with #5583. (pm:blockedon #5483/PR #5609 retained — board membership is independent of dispatchability.) Maintainer directive: protocol changes land in v17 unless large/risky. Triage seat may veto.Generated by Claude Code
fix(spec): 三个手写 unrecognized_keys error map 把处方排到说明句之前 (objectstack-a…
test(spec): give the strictness ledger's older-spelling case an owned…
test(spec): shared test titles state each cited decision in words ins…