在 #4956 给 dashboard.widgets 做逐键分类时实测发现,与该单裁决无关,独立存在。
声明
DashboardWidgetSchema.compareTo(packages/spec/src/ui/dashboard.zod.ts)声明三个分支,TSDoc 写得很具体:
'previousPeriod' —— 从 widget 的 filter 日期宏自动推导对比窗口
'previousYear' —— 整体回移一个日历年
{ offset: '7d' | '1M' | '1y' } —— 按显式时长回移
实测
内联 object-provider 图表路径(遗留形态)—— 正常。 DashboardRenderer 把 widget.compareTo 传进 object-chart schema,objectui packages/core/src/utils/compare-to.ts 的 CompareToConfig 恰好就是这三个分支,shiftFilterByCompareTo 全部实现。
ADR-0021 dataset 绑定路径(spec 自称「唯一面向作者的分析形态」)—— 三个分支全废:
两个字符串分支被显式丢弃 。DatasetWidget.tsx:163-168 只在 typeof widget.compareTo === 'object' 时才转发,注释写明理由是「forwarding it makes the executor throw "compareTo requires a timeDimension"」。作者写 compareTo: 'previousPeriod',基础数值照常渲染,对比列静默消失。
{ offset } 分支被转发进 DatasetSelection.compareTo —— 而那个契约(packages/spec/src/contracts/analytics-service.ts:104-109)要求的是 { kind, dimension }。packages/services/service-analytics/src/dataset-executor.ts:870-876 拿 cmp.dimension(此时是 undefined)去找 timeDimension,找不到就抛:
[dataset-executor] compareTo requires a timeDimension "undefined" with a dateRange.
执行器里根本没有 offset 这个概念 —— 它只认 kind: 'previousPeriod' | 'previousYear' 加一个具名时间维度。也就是说 widget 侧的词表和 dataset 侧的词表从来没有对齐过,只是没人被要求去看。
为什么值得单开一单
这不是「declared but unread」,而是更靠后的一档:同一个键在两条路径上有两种命运 ,而且失败的那条恰恰是 spec 自己推荐的规范路径。一个照着 TSDoc 写 { offset: '7d' } 的作者(或 AI)在 dataset 看板上拿到的是整块 widget 报错,在遗留内联图表上却工作正常。
可选方向(需要维护者裁决,别猜)
在 widget 侧收敛词表 :把 compareTo 改成 dataset 侧真正支持的 { kind, dimension },offset 走 ADR-0087 conversion 退休 —— 契约优先,但会动 authorable 面。
在 dataset 执行器里实现 offset + 自动推导维度 ,让三个分支都真的可用 —— 保住已声明的能力,成本在分析服务侧。
objectui 侧翻译 :DatasetWidget 把 widget 形态映射成 { kind, dimension } —— 最快,但这是消费者侧的宽容映射,Prime Directive Add comprehensive test suite for Zod schema validation #12 明确反对。
台账现状:packages/spec/liveness/dashboard.json → props.widgets.children.compareTo 记为 live(遗留路径确有消费者),并在 note 里完整记录了这条路径分裂 —— 照 action.disabled 的先例,「一个 surface 成立就记 live」必须把边界写清楚,否则就是下一次误读的种子。
Generated by Claude Code
在 #4956 给
dashboard.widgets做逐键分类时实测发现,与该单裁决无关,独立存在。声明
DashboardWidgetSchema.compareTo(packages/spec/src/ui/dashboard.zod.ts)声明三个分支,TSDoc 写得很具体:'previousPeriod'—— 从 widget 的filter日期宏自动推导对比窗口'previousYear'—— 整体回移一个日历年{ offset: '7d' | '1M' | '1y' }—— 按显式时长回移实测
内联 object-provider 图表路径(遗留形态)—— 正常。 DashboardRenderer 把
widget.compareTo传进 object-chart schema,objectuipackages/core/src/utils/compare-to.ts的CompareToConfig恰好就是这三个分支,shiftFilterByCompareTo全部实现。ADR-0021 dataset 绑定路径(spec 自称「唯一面向作者的分析形态」)—— 三个分支全废:
DatasetWidget.tsx:163-168只在typeof widget.compareTo === 'object'时才转发,注释写明理由是「forwarding it makes the executor throw "compareTo requires a timeDimension"」。作者写compareTo: 'previousPeriod',基础数值照常渲染,对比列静默消失。{ offset }分支被转发进DatasetSelection.compareTo—— 而那个契约(packages/spec/src/contracts/analytics-service.ts:104-109)要求的是{ kind, dimension }。packages/services/service-analytics/src/dataset-executor.ts:870-876拿cmp.dimension(此时是undefined)去找 timeDimension,找不到就抛:执行器里根本没有
offset这个概念 —— 它只认kind: 'previousPeriod' | 'previousYear'加一个具名时间维度。也就是说 widget 侧的词表和 dataset 侧的词表从来没有对齐过,只是没人被要求去看。为什么值得单开一单
这不是「declared but unread」,而是更靠后的一档:同一个键在两条路径上有两种命运,而且失败的那条恰恰是 spec 自己推荐的规范路径。一个照着 TSDoc 写
{ offset: '7d' }的作者(或 AI)在 dataset 看板上拿到的是整块 widget 报错,在遗留内联图表上却工作正常。可选方向(需要维护者裁决,别猜)
compareTo改成 dataset 侧真正支持的{ kind, dimension },offset走 ADR-0087 conversion 退休 —— 契约优先,但会动 authorable 面。{ kind, dimension }—— 最快,但这是消费者侧的宽容映射,Prime Directive Add comprehensive test suite for Zod schema validation #12 明确反对。台账现状:
packages/spec/liveness/dashboard.json→props.widgets.children.compareTo记为live(遗留路径确有消费者),并在note里完整记录了这条路径分裂 —— 照action.disabled的先例,「一个 surface 成立就记 live」必须把边界写清楚,否则就是下一次误读的种子。Generated by Claude Code