Skip to content

liveness: DashboardWidgetSchema 的 ~22 个 widget 级键从未被台账分类,而 dashboard.json 的 _note 声称它们已分类 #4956

Description

@xuyushun441-sys

在 #4876 的实测过程中发现,与该单的裁决无关,独立存在。

现象

packages/spec/liveness/dashboard.json 的 _note 写明:

Widget-level props are classified in the DashboardWidgetSchema subtree, not drilled here.

但不存在这个 subtree。packages/spec/liveness/ 下 28 个台账文件里,提到 DashboardWidget 的只有 dashboard.json 自己和 README.md。

而 check-liveness.mts 只按显式 children 下钻一层(:375-387):

if (led?.children) {
  // drill one level

dashboard.json 的 widgets 条目是:

{ "status": "live",
  "note": "objectui: the widget grid — DashboardRenderer maps each to DatasetWidget/metric/etc. Per-widget props live in the DashboardWidgetSchema subtree (strict, ADR-0021)." }

没有 children。所以检查器把整个 widgets 记作一个 live 属性就收工,DashboardWidgetSchema 的 ~22 个可授权键(dataset / values / dimensions / filterBindings / responsive / aria / compareTo / colorVariant / actionUrl / suppressWarnings / …)一个都没进过分类,unclassified 计数也不会报——因为没声明 children 就根本不走那条分支。

为什么这是「声明 ≠ 强制」

台账的 _note 是一句断言:这些键在别处分类了。检查器不校验这句断言,读台账的人(和 agent)会据此认为覆盖完整。这正是 Prime Directive #10 的形状,只不过发生在审计系统自身身上。

实际后果(已经发生了一次)

2026-07-30 的 #3896 close-out sweep 按审计文档移除了 dashboard.aria / dashboard.performance / widgets[].performance,却把 widgets[].responsive 留下了。台账说不出为什么——因为它对这两个键都没有裁决记录。同一个 sweep 在 view 侧移除 list.responsive 时,理由是「authorable and inert — no renderer in either repo read them」;widgets[].responsive 的实测状态与之相同(objectui@91757a7 全仓 grep 无任何读取点),只是没人被要求去看。

换句话说:这个键躲过审计靠的是台账覆盖缺口,不是任何 liveness 证据。

建议

二选一,都不大:

  1. 给 dashboard.json 的 widgets 补 children,把 22 个 widget 级键逐个分类(与 view.json 对 list/form 的做法一致——那边正是靠 children 下钻才让 list.responsive 被判 dead 的)。
  2. 若确实想要独立 subtree 文件,那就让 check-liveness.mts 能解析这种引用,并在引用悬空时报错;在那之前 _note 里不该写一句检查器兑现不了的话。

倾向 1——它复用已有机制,且立刻能给 widgets[].responsive 一个有据可查的裁决(#4876 正卡在这个问题上)。

同类排查值得顺带做一遍:其它台账文件里是否还有「声称在别处分类」但无下钻的容器条目。


Generated by Claude Code

Activity

  1. xuyushun441-sys commented on Aug 3, 2026

    @xuyushun441-sys
    CollaboratorAuthor

    🔒 认领:PM 循环补位(#4876 dev 完成腾位;批 14 因与 #4995 同文件须串行,本单顶上)
    会话:session_01Ehu85kbvMcrNTUJjwxvLJ9
    分支:claude/issue-4956-liveness-widget-drill
    Worktree:objectstack-issue-4956
    域:domain:spec(仪器/门禁)
    文件面:packages/spec/scripts/liveness/check-liveness.mts(或按实测的钻取实现位置)、packages/spec/liveness/dashboard.json、新增的 widget 键分类行

    ⚠️ 已知共享面:#4995(在队)也动了 liveness/dashboard.json 两行——合并时双边保留,重跑 check:liveness 为准。仪器修复必须先证红(用一个确知存在且未分类的 widget 键作探针,证明修复前地图外、修复后被要求分类)。


    Generated by Claude Code

  2. xuyushun441-sys commented on Aug 4, 2026

    @xuyushun441-sys
    CollaboratorAuthor

    ✅ 验收通过 —— PR #5012(即刻挂轨;远端 Type Check / Test Core 分片交接时仍在跑,本地同树已绿,auto-merge 会等它们)

    复核要点:

    • 修法是结构性的(任务书第 1 条的高标准达成):台账容器属性此后必须三选一声明处置——children 钻取 / {container, to} 延迟(且门禁解析目标:必须存在、必须恰好分类该容器的子键集)/ 只减不增基线。悬空、漂移、双列、陈旧基线行全部各自证红。
    • 延迟解析器抓到本 PR 自己第一版基线的错:声称 64 容器全部「无处分类」,实际 6 个(248 键)已在别处——不修解析器就会带着与本单同款缺陷发货。仪器咬自己作者,本战役第 N 例,这正是要它存在的理由。
    • 22 个 widget 键闭合调用图分类(16 live / 8 dead 合计后 dashboard 20→41);CLI lint 注册补上,5 条 authorWarn 真能到作者面前;假 _note 修正。
    • RED/GREEN 对照完整:旧门对旧账绿(缺陷复现)→ 新门对旧账红(点名 22 键)→ 分类恢复后绿。

    衍生分诊:


    Generated by Claude Code

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

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions