Skip to content

ui/app.zod.ts 导航项:4 条 expanded 别名在另外 8 个变体上把作者指向该变体同样拒绝的键(二次拒绝) #5555

Closed

Description

@os-zhuang

由 #5483 的过渡看守新装的判据实测发现(范围外,未指派)。具体缺陷:错误信息把作者指向一个下一步同样会被拒的键。

现状

packages/spec/src/ui/app.zod.ts 的 NAV_ITEM_ALIASES 是九个导航项变体共用的一张别名表,其中四条指向 expanded:

defaultopen: 'expanded',
open: 'expanded',
collapsed: 'expanded',
isopen: 'expanded',

但 expanded 只声明在 group 变体上(NAV_VARIANT_KEYS.group = ['expanded', 'children'])。其余八个变体(object / dashboard / page / url / report / action / component / separator)的 knownKeys 里根本没有 expanded。

于是在这八个变体上,作者的路径是:

  1. 写 { type: 'url', url: '/x', defaultOpen: true }
  2. 得到 Unrecognized key(s) on this urlnavigation item:defaultOpen. … Did you mean defaultOpen→expanded?
  3. 照做写成 expanded: true
  4. 再次被拒,而且第二次没有任何建议

这正是 #5013 立案时那条 ReportSchema 的 filter → filters、以及 ledger finding 7 的形状:#4001 战役自己的修复,把作者指进它要消灭的失败模式。

证据

新判据(别名 target 必须是本表的已知键)在 44 个直调点上跑出 32 条,全部是这一个根因 —— 4 个别名 × 8 个变体:

"this `url` navigation item": `collapsed`   -> `expanded` — `expanded` is not a known key here
"this `url` navigation item": `defaultopen` -> `expanded` — `expanded` is not a known key here
"this `url` navigation item": `isopen`      -> `expanded` — `expanded` is not a known key here
"this `url` navigation item": `open`        -> `expanded` — `expanded` is not a known key here
…(其余 7 个变体同形)

同一批测量里另外两条判据(别名 key 不得是已知键、表内 aliasProbe 不得撞车)在这 44 张表上是干净的,所以这 32 条不是噪声底噪,是唯一的信号。

为什么会写成这样(机制,不是粗心)

同一个文件里紧接着的六条跨变体别名已经解决了同一个问题,用的是散文式 target:

...(variant !== 'object' ? { objectname: "type: 'object' (with objectName)" } : {}),
...(variant !== 'url'    ? { url: "type: 'url' (with url)" } : {}),

作者显然知道"键名对、变体错"不能用裸键名回答。区别只在于:那六条写在按变体拼装的那一段里,变体差异就在眼前;这四条写在 NAV_ITEM_ALIASES —— 一张名字就叫"每个变体共有"的共享表里,而 expanded 并不是每个变体都有。

建议的修法(未在此擅自决定)

把这四条从共享表挪到按变体拼装的那一段,给非 group 变体一个散文 target,与既有六条同形:

...(variant !== 'group' ? {
  defaultopen: "type: 'group' (with expanded)",
  open: "type: 'group' (with expanded)",
  collapsed: "type: 'group' (with expanded)",
  isopen: "type: 'group' (with expanded)",
} : { defaultopen: 'expanded', open: 'expanded', collapsed: 'expanded', isopen: 'expanded' }),

这会改动面向作者的报错文案,所以没有在 #5483 的 PR 里顺手改:那张单子的硬约束是不动 44 个调用点本身。散文 target 一旦增加,#5483 闸门里的 PROSE_ALIAS_TARGETS 白名单需要同步扩充(白名单带陈旧检查,漏改会红)。

当前缓解

#5483 的闸门把这 32 条钉成只减不增的已知债(toBeLessThanOrEqual(32)),并且判定规则是结构化的 —— 只放过"nav 变体表 + 这四个别名 key + target 恰为 expanded"这一种组合,别的破损 target(包括这张表上第五种"展开"拼法)一律直接红。所以这条债只会缩,不会悄悄长。

复现:pnpm --filter @objectstack/spec exec vitest run src/shared/alias-integrity.test.ts,把 isPinnedExpandedDefect 的调用去掉即可看到 32 条。

Activity

  1. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    on Aug 5, 2026
  2. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    补:过渡看守已落地为 PR #5609(draft),本 issue 的 32 条即该 PR 里那条结构化只减不增容差(toBeLessThanOrEqual(32))所钉住的债。

    反向验证里有一次注入专门证明这条容差不会被滥用:在 NAV_ITEM_ALIASES 里加第五种「展开」拼法(expand: 'expanded'),闸门立刻转红 —— 容差只放过「nav 变体表 + 那四个既有 key + target 恰为 expanded」这一种组合,新拼法落在 broken 里。所以本 issue 修完之后,把 32 改小(直至删除整条容差)是安全的,不会连带放松别的东西。

    修复顺序上的一个提示:#5593(44 个直调点迁 strictObject)会重写 ui/app.zod.ts 的导航项一族,建议先修本 issue、再迁,否则同一个修法要写两遍。


    Generated by Claude Code

  3. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    on Aug 5, 2026
  4. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    PM 分诊(spec 车道,session_018fxLGQdatPbBUvCgiVxg6D):入队(pm:queue)。具体缺陷、定位明确、修法已勾勒(挪出共享表 + 非 group 变体散文 target,与既有六条同形)。

    落地序约束(选批时执行,非阻塞标签):必须排在 PR #5609(#5483)合并之后 —— 修复需同步做两件闸门侧动作,均落在 #5609 新增/修改的 alias-integrity.test.ts 里:① toBeLessThanOrEqual(32) 容差收到 0(或删除该容差段);② PROSE_ALIAS_TARGETS 白名单扩入新增的散文 target(白名单带陈旧检查,漏改会红)。同批不得与其它 ui/app.zod.ts 单并行。


    Generated by Claude Code

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

    @os-zhuang
    ContributorAuthor

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


    Generated by Claude Code

  8. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    已实现,draft PR #5664(分支 claude/issue-5555-nav-expanded-aliases)。

    前提复核(对 origin/main,已含 #5609 闸门):全部成立 —— 四条别名确在 NAV_ITEM_ALIASES 共享表;expanded 只在 NAV_VARIANT_KEYS.group;闸门持有 isPinnedExpandedDefect ≤32 结构化容差与带陈旧检查的 PROSE_ALIAS_TARGETS。#5593 仍 open/pm:blocked,导航项工厂未被迁走,按建议的「先修本 issue 再迁」顺序执行。

    修法:四条挪进按变体拼装段 —— group 保留裸键名,另外八个用散文 target type: 'group' (with expanded),与既有六条同形。

    闸门联动两处:① isPinnedExpandedDefect 容差整段删除(非收到 0),判据 2 现在零容差;② PROSE_ALIAS_TARGETS 扩入第七条。

    先证红(方向事先预测):未改 schema、仅让容差失效 → 恰好 32 条,4 别名 × 8 个非 group 变体,group 正确缺席。修复后全绿(spec 全量 317 files / 8072 tests)。两次反向注入证明清理后判据仍咬得住:加第五种拼法 expand: 'expanded' → 判据 2 红 8 条;把散文 target 打错一字母 → 判据 2 红 32 条且白名单陈旧检查同时红。

    解析期行为已单独立测(app-nav-expanded-alias.test.ts,12 例):url 上写 defaultOpen 现在得到散文指引而非死的 expanded 重定向,group 上仍重定向到 expanded;可达性按值判据写成 full-parse-green。

    Changeset:@objectstack/spec patch(纯报错文案改进,无形状变更)。


    Generated by Claude Code

  9. os-zhuang commented on Aug 5, 2026

    @os-zhuang
    ContributorAuthor

    验收通过(spec 车道 PM,session_018fxLGQdatPbBUvCgiVxg6D,2026-08-05)—— PR #5664。

    • 四条 expanded 别名挪入按变体拼装段:group 保留真重定向,其余八变体散文 target 与既有六条同形;两张字面表(散文串是契约面,不派生)。
    • 闸门联动两处均落地且均经注入实测为活:isPinnedExpandedDefect 容差整段删除(双桶收敛回单桶,原位留债务去向注释——比留恒空容差干净);PROSE_ALIAS_TARGETS 第七条,surface 家族正则未放宽。
    • 先证红恰 32 条、注入 A 证明删容差后判据无吸收缓冲、注入 B 证明白名单陈旧检查活性;全量 317 文件 / 8072 测试绿。
    • patch changeset 理由充分(纯报错文案,零形状变更);把 44 个 strictUnknownKeyError 直调点批量迁到 strictObject,棘轮降到 0(路线 1 消不掉手抄数组与 shape 的漂移) #5593 迁移提示已记录(两张表可原样带走,判据 2 已零容差)。

    转 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

bugSomething isn't workingdomain:specDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions