Skip to content

44 个 strictUnknownKeyError 直接调用点的别名表在 #5013 闸门覆盖之外(实测干净,但无人看守) #5483

Closed

Description

@os-zhuang

发现于 #5013 的全仓别名一致性闸门(范围外,未指派)。观察类:实测当前无缺陷,
记录的是覆盖边界本身。

现状

#5013 新增的 packages/spec/src/shared/alias-integrity.test.ts 判定的是
strictObject(...) 建的表——它靠 strictObjectDeclarations() 在构造期登记,
所以能拿到运行时 .shape。235 个 surface 被判定。

但 strictObject 不是唯一的入口。helper 之前的老接线直接调
strictUnknownKeyError({ surface, knownKeys, aliases, guidance, history }),
自带一份手抄的 knownKeys 数组,这些表根本不进登记表:

44 个调用点,分布在 14 个文件
data/object.zod.ts、automation/flow.zod.ts、security/permission.zod.ts、
ui/app.zod.ts(9 处)、data/datasource.zod.ts(6 处)、automation/approval.zod.ts(4 处)、
data/driver/{sqlite,mongo,memory,postgres,mysql}.zod.ts、data/hook*.zod.ts、
security/{rls,sharing}.zod.ts、identity/position.zod.ts、
ui/{action,bulk-action}.zod.ts

ui/action.zod.ts 的 ActionParamSchema 就是其中之一——#5013 修的是同一个文件里
ActionSchema 的表,而同文件的 param 表当时不在任何闸门下。

实测结论:干净

临时给 strictUnknownKeyError 加了登记后跑同样两条判据(别名 key 不得是已知键、
别名 target 必须是已知键)+ guidance key 判据,51 张表全部通过,唯一的报告集中在
ui/app.zod.ts 的 navigation item 系列,那是刻意的散文式 target
(type: 'url' (with url)),不是键名,属于另一种写法而非缺陷。

所以这条是「暂时没事,但没人看着」,不是待修 bug。

已做的缓解

#5013 在闸门里放了一条只减不增的棘轮,把这个数钉在 44:

expect(uncovered.length).toBeLessThanOrEqual(44);

迁一个到 strictObject 是免费的;新增一个直接调用点会红,逼作者显式选择。

建议(两条路,选一)

  1. 收编判定:让 strictUnknownKeyError 也登记 {surface, knownKeys, aliases, guidance},
    闸门对这批按 knownKeys 判定。便宜,但判的是手抄数组而不是 shape——
    数组本身与 shape 漂移仍无人看守(那正是 strictObject 存在的理由,
    见其 docblock「the array is a second copy of the truth」)。
  2. 迁移到 strictObject:一次性消掉手抄数组,这批自动进入现有闸门,
    棘轮随之降到 0。工作量大得多,但把两个问题一起消掉。

倾向 2,分批做;1 可以作为过渡期的看守。

复现日期 2026-08-05,基线 origin/main ed0d2aa。

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 5, 2026
  2. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    on Aug 5, 2026
  3. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    补一条边界更新(来自 #5481 / PR #5516,不另开 issue —— 这落在本 issue 的完成范围内:无论走路线 1 还是路线 2,这批表都会自动进入闸门的全部判据)。

    #5481 给 alias-integrity.test.ts 加了第三条判据:一张表内任意两个别名 key 的 aliasProbe 不得相同(归一化后撞车的两条共用一个下标,后写的静默覆盖先写的 —— snap.grid 因此被指向布尔的 showGrid)。

    对本 issue 的影响是:这 44 个直接调用点现在处于三条判据之外,而不是两条。

    值得说明的是本 issue 正文里那次"实测干净"的结论:当时临时登记后跑的是"别名 key 不得是已知键 + 别名 target 必须是已知键 + guidance key"这三条,第三条 probe 判据当时还不存在,所以那次测量并没有覆盖撞车这一类。也就是说这 44 张表在 probe 撞车上目前是未测量,而不是"已测干净"。

    参考量级:在已覆盖的 strictObject 那 235 张表里,probe 撞车实测有 4 条(1 条活缺陷 + 3 条休眠冗余),PR #5516 已清零。同样的密度是否存在于这 44 张表里没人知道,所以这条不是"再加一个待办",而是把本 issue 那句"暂时没事,但没人看着"里的**"暂时没事"缩小到了两条判据的范围**。

    对路线选择没有改变倾向:路线 2(迁到 strictObject)仍然一次性解决全部三条;路线 1(让 strictUnknownKeyError 也登记)同样能顺带覆盖 probe 判据,因为这条判据只读别名表本身、不需要 shape —— 它是三条里唯一不依赖 shape 的,所以哪怕只做路线 1 的过渡看守,也能立刻把它开起来。


    Generated by Claude Code

  4. added
    toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 5, 2026
  5. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    分诊轮判级(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D,2026-08-05):晋级(摘 finding 挂 pm:queue)。理由:#5481 落地后事实已变 —— 44 个直调点现处三条判据之外且 probe 维度未测量(非已测净,见 #5481 dev 的追记);过渡路线 1(让 strictUnknownKeyError 登记)可立即把 probe 判据开到这批表上,只减不增棘轮已在位。排存量批次。


    Generated by Claude Code

  6. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 5, 2026
  7. self-assigned this
    on Aug 5, 2026
  8. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    PM 认领(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D,2026-08-05)

    • 分支:claude/issue-5483-strict-unknown-registry
    • 工作树:../objectstack-5483-strict-unknown(基于最新 origin/main)
    • 域:domain:spec
    • 文件面:strictUnknownKeyError helper 所在的 shared 严格性模块 + shared/alias-integrity.test.ts;不改 44 个调用点本身(路线 1 过渡看守)
    • 范围裁定:按路线 1 落地(helper 登记 {surface, knownKeys, aliases, guidance},三条判据全开,probe 判据不依赖 shape 可全量开启;ui/app.zod.ts 散文式 target 走显式豁免、不许静默放过)。路线 2(44 点分批迁 strictObject)本单不做,由 dev 另立跟进 issue。若登记机制被迫要改调用点(含在飞 [spec] 退役 HookContext session.roles —— #4839 双删后零消费方零生产方(ADR-0049) #5050 的 data/hook*.zod.ts),停手回报,PM 重新排程
    • ≤44 只减不增棘轮保持
    • 派发:os-dev(opus)。若本评论之前存在不同 session 的认领,以先者为准、本认领作废。

    Generated by Claude Code

  9. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    验收通过(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D,2026-08-05)—— PR #5609,路线 1 按裁定落地。

    • 零调用点改动兑现:登记进 strictUnknownKeyError 工厂首行;strictObject 内部调用显式抑制(防双登记与测试顺序漂移);独立登记表不与 shape 背书的那张合并——成色不同不混账。
    • probe 撞车维度首测:52 张表 0 条(44 调用点 → 52 表,nav 工厂九变体各一张;原实验的 51 差在 data/object.zod.ts 延迟表)。
    • 判据 2 抓出 32 条真实债(nav 四条 expanded 别名在八个变体上二次拒绝)——issue 正文「实测干净」被证伪:当时这批被误归给散文 target。已立 ui/app.zod.ts 导航项:4 条 expanded 别名在另外 8 个变体上把作者指向该变体同样拒绝的键(二次拒绝) #5555,闸门内钉结构化只减不增容差(≤32),第五种拼法即红(反向验证 C 已证)。
    • 两处豁免(散文 target / 变体合法 guidance)逐条枚举 + 陈旧检查,无静默放过;登记表带容量上限 512、溢出断言为 0。
    • 五次反向注入两处预期未中,均按实测改写说法(D:陈旧检查非自证;E:覆盖检查确能看见字面量表)——这是要的诚实,不是模板。
    • ≤44 棘轮原样;changeset patch;跟进 把 44 个 strictUnknownKeyError 直调点批量迁到 strictObject,棘轮降到 0(路线 1 消不掉手抄数组与 shape 的漂移) #5593(路线 2,含三个已知迁移坑)已立。
    • 验收保留项:spec 全量与 check:api-surface/check:generated 未在本地跑(构建锁排队),由 CI 兜底——落地前以 PR 的 Test Core / TypeScript Type Check 绿为准。

    落地暂缓:等 #5604(main 全仓红)修复后合 main 重跑 → ready → auto-merge。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchtoolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions