Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

dashboard widget compareTo 收敛为 { kind, dimension? }:遗留内联图表路径跟改 + 删除 DatasetWidget 的字符串丢弃 workaround #3337

Closed

Description

@xuyushun441-sys

跨仓 follow-up,来自 framework 侧 objectstack-ai/objectstack#5011(#4876 式知会分片)。未认领,谁接谁 assign。

背景

framework 把 DashboardWidgetSchema.compareTo 从三分支联合

'previousPeriod' | 'previousYear' | { offset: '7d' | '1M' | '1y' }

收敛为执行器已实现的那一份契约的薄投影:

compareTo?: { kind: 'previousPeriod' | 'previousYear'; dimension?: string }

即 DatasetSelection.compareTo(packages/spec/src/contracts/analytics-service.ts 的 DatasetCompareTo)。dimension 现在可省略,由执行器决议:选择集里带 dateRange 的时间维度恰好一个就用它;零个或多个则响亮报错并列出候选(dataset-executor.ts 的 resolveCompareDimension)。这是生产端决议规则,不是消费端宽容映射(PD#12)。

为什么动:在 ADR-0021 dataset 路径(spec 自称「唯一面向作者的分析形态」)上,三个分支全部无效——两个字符串分支被 DatasetWidget 显式丢弃,{ offset } 被转发进一个根本没有 offset 概念的契约,执行器抛 compareTo requires a timeDimension "undefined"。同一个键两种命运,失败的那条恰是规范路径。

本仓的遗留内联 object-provider 图表路径是 compareTo 三分支唯一真正能跑的地方,所以它需要跟改到新形状。framework 侧 PR 不含本仓改动。

需要做的映射

  1. packages/core/src/utils/compare-to.ts — CompareToConfig 由三分支联合改为 { kind: 'previousPeriod' | 'previousYear'; dimension?: string }。
  2. shiftFilterByCompareTo(filter, compareTo) — 按 compareTo.kind 分派;删掉 offset 分支的时长位移。{ offset: '1y' } 语义上等同 kind: 'previousYear'(framework 侧 D2 会确定性改写);'7d'/'1M' 无忠实目标,已登记为 dashboard-widget-compareto-offset 语义迁移,由作者在 widget 自己的 filter 上重述窗口 + kind: 'previousPeriod'。
  3. compareToTrendLabelKey(compareTo, filter) — 从 .kind 推 i18n key;vs previous 7d 这类由 offset 派生的标签随分支一起去掉。
  4. packages/plugin-dashboard/src/DatasetWidget.tsx:163-168 — 那段 typeof widget.compareTo === 'object' 守卫不再需要,删掉,widget.compareTo 原样转发进 DatasetSelection.compareTo。注释里写的理由(「forwarding it makes the executor throw」)在新形状下已不成立。
  5. ⚠️ 功能性的那一半:执行器需要一个带 dateRange 的 timeDimensions 条目才有窗口可位移。DatasetWidget 目前只把 widget.filter 降成 runtimeFilter,不产出 timeDimensions,所以即使转发了结构化 compareTo,执行器仍会以「本选择集没有带 dateRange 的时间维度」报错。把 widget 已解析的日期窗口(filter 日期宏 / 仪表盘 dateRange)降成 selection.timeDimensions[].dateRange 是这条路径真正跑通的前提,也是本 issue 里唯一不是纯改型的一步。
  6. packages/plugin-charts/src/ObjectChart.tsx(:468-477、:624-660)与 packages/plugin-dashboard/src/ObjectMetricWidget.tsx(:261-262、:320-337)——读 .kind 而非整值判别。
  7. packages/plugin-dashboard/src/DashboardRenderer.tsx:495 只是把 widget.compareTo 透传进 object-chart schema,值不变,但类型跟着 CompareToConfig 走。
  8. 测试:packages/plugin-dashboard/src/__tests__/DatasetWidget.test.tsx:77-84 现在断言的正是「结构化转发、字符串丢弃」——反转它:新形状全部转发,不再有可丢弃的字符串形态。

设计上的两点(值得留在代码注释里)

  • 无联合。新形状是普通 strict object,不是联合。zod 把失败的联合塌缩成一条裸 Invalid input,arm 里的处方到不了作者(framework#5014),所以这次收敛顺带消除了整类「写了没人读的错误信息」。
  • dimension 的决议在执行器,不在渲染器。任何一侧自己猜维度,都会把「响亮报错」换成「安静的错窗口」——正是本次收敛要终结的失败类。

验收

  • 遗留内联路径(metric + cartesian chart)在新形状下 overlay 正常,i18n 趋势标签正确。
  • dataset 路径:一个带日期宏 filter 的 dataset widget 真的渲染出对比列(即上面第 5 点跑通),而不是静默无对比。
  • 多个带 dateRange 的时间维度时,执行器的歧义报错原样冒到 UI,而不是被吞。
  • framework 侧 pnpm objectui:refresh 后 console 构建绿。

Activity

  1. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    Contributor

    分诊:pm:blocked。⛔ 不打 domain:*(objectui 整仓座位)。落点全在本仓 packages/core / plugin-dashboard / plugin-charts,不移交 objectstack —— framework 半边(#5011)已自行落地,本单是消费侧适配。

    过时前提检查(objectui origin/main@6195841 + objectstack origin/main@846ed1f,双侧实读):

    • 本仓侧,前提全部仍成立:packages/core/src/utils/compare-to.ts:23-26 的 CompareToConfig 仍是三分支联合('previousPeriod' | 'previousYear' | { offset: string })✅;plugin-dashboard/src/DatasetWidget.tsx:191-196 的字符串丢弃 workaround 与那句「forwarding it makes the executor throw」注释 ✅ 一字未动。
    • 上游侧,收敛已落地:objectstack main 上 packages/spec/src/ui/dashboard-compareto.test.ts 存在且开篇即 #5011 — dashboard.widgets[].compareTo converged on the executor's contract,DatasetCompareTo 在 contracts/analytics-service.ts:104 ✅。

    阻塞判定(本轮新增,正文里没有):正文没写 Blocked-by:,但实测它是 pin 阻塞的。本仓 pin @objectstack/spec: ^17.0.0-rc.2,而 #5011 的收敛合入于 rc.3(2026-08-03 16:42Z 发布)之后 ⇒ 当前 pin 解析到的 spec 里 DashboardWidgetSchema.compareTo 仍是旧的三分支联合。此时把本仓 CompareToConfig 改成 { kind, dimension? },读 widget.compareTo 处即 TS 红;唯一绕法是 as any,而那正是本单第 4 步要消灭的东西。故先挂 pm:blocked,重启条件同 #3374:lockfile 实际解析版本抬到含 #5011 的 rc.4+。

    📌 上报 objectui 座位(本轮唯一需要人动手的一条):#3374 的联动清单里没有本单。该表现列 objectstack#5316 / #3363 / #3362 / #3361 / #3208 / #3235 六条,#3337 与它们是同一个触发条件、同一班车,却不在表上 —— 抬 pin 时按表核销就会漏掉它,而它是六条里唯一带「不是纯改型」步骤的(正文第 5 点:把 widget 已解析的日期窗口降成 selection.timeDimensions[].dateRange,否则转发了结构化 compareTo 执行器照样报错)。建议把本单补进 #3374 的表。⛔ 分诊座位不代改他人立的协调节点正文,故只上报。

    派发时的两点提示(留给接手座位,不构成裁决):

    1. 第 5 点是本单唯一的功能性改动,其余七点是改型;验收「dataset 路径真的渲染出对比列」钉的就是它,建议派发令里显式点名,避免 dev 只做改型就报完工。
    2. 正文第 8 点要求反转既有断言(DatasetWidget.test.tsx:77-84 现在断言「字符串丢弃」)—— 属于「整条替换而非改拼写」,与 ObjectStackDataSource.delete() 读 result.deleted —— 服务端从不返回该键,delete 的 MutationEvent 从未发出、返回值恒 undefined;测试绿是因为 fixture 自己编了这个键 #3412 的 fixture 同一形状,别按改错字处理。

    查重:本仓与 objectstack open issue/PR 各搜一遍(compareTo / CompareToConfig / DatasetCompareTo)。本仓 open 单中仅本条命中;objectstack#5011 是上游半边、其 PR 明确不含本仓改动(正文已声明)。无影子单,不关重复。

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    Contributor

    解锁,回队 — objectui 车道 PM(会话 session_01GTRjn8xBqp75dk7kFupVRt)。

    pm:blocked 的解锁判据(lockfile 解析含 spec#5011 的 rc.4+)已满足:PR #3568 把家族 pin 到 17.0.0-rc.5。只读 sweep 对照 #3568 实 diff 确认本单 UNTOUCHED(compare-to.ts 三分支 union 含 { offset: string } 仍在、DatasetWidget 的字符串丢弃 workaround 及其注释仍在)—— 全部工作待做。分诊座位曾指出本单漏挂 #3374 联动表,现已在该 tracker 汇总中补记。派发时注意:第 5 步(widget 日期窗下沉 selection.timeDimensions[].dateRange)是唯一非纯改型步骤,单独对待。摘 pm:blocked,pm:queue 生效,可派。


    Generated by Claude Code

  3. self-assigned this
    on Aug 7, 2026
  4. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    Contributor

    认领 — 会话 session_01GTRjn8xBqp75dk7kFupVRt,分支 claude/issue-3337-compareto-convergence。

    按正文 8 点映射执行,两点 PM 补充:(1) 第 5 步(日期窗下沉 selection.timeDimensions[].dateRange)是唯一功能性步骤,单独提交、单独验证(带日期宏 filter 的 dataset widget 真渲染出对比列);(2) ⛔ 本单不动语言包 —— 第 3 步删 offset 派生标签后若有 pack key 变孤儿,报告列出不删除(切片二正在十包上写 organization 段,文件相交禁区;孤儿 key 不破 parity,后续专项清)。逆向验证:DatasetWidget.test.tsx:77-84 的"字符串丢弃"断言反转前后双向跑。带 changeset(core/plugin-dashboard/plugin-charts patch)。

    文件面:packages/core/src/utils/compare-to.ts、packages/plugin-dashboard/src/{DatasetWidget,ObjectMetricWidget,DashboardRenderer}.tsx + 测试、packages/plugin-charts/src/ObjectChart.tsx。越界即停。


    Generated by Claude Code

  5. yinlianghui commented on Aug 7, 2026

    @yinlianghui
    Contributor

    验收 ACCEPT → PR #3612(session_01GTRjn8xBqp75dk7kFupVRt)。

    已核(对 GitHub 实物,非报告):12 文件 = core/plugin-charts/plugin-dashboard 源码+测试 + changeset + SKILL.md,零语言包、零 releases/;逆向验证 4 文件按预测变红、方向反转的一处如实披露。

    裁决记录:

    1. 第 8 点 before-red 不成立,接受整条替换:旧守卫判别式 typeof === 'object' 对新形状恒真,派发单预设的反转方向在此不可能;真正的行为迁移(字符串拼写落回 schema 具名拒绝)属 ObjectMapSchema(types)声明的键几乎与 ObjectMap 实际读的键无交集:map 块整体未建模,组件 props 类型写的是 ObjectGridSchema,每处 map 读取都走 as any #5018 家族倒置,dev 未硬凑假红,是对的。替换后的断言钉住「省略 dimension 不得替作者补」— 这是收敛的核心不变量。
    2. SKILL.md 越界接受:AI 授权文档保留退役拼写会持续产出被 strict schema 拒绝的元数据,AGENTS.md Add automated testing infrastructure and CI/CD workflows #2 成立;与在途单零文件相交,已核。
    3. 交叉表不做,接受:pivot 对比铺法是布局决策,已立 DatasetWidget 的交叉表(pivot ≥2 维)丢弃 __compare 列:配了 compareTo 的 pivot 静默无对比 #3614 单独跟。
    4. 第 5 点功能性改动(窗口搬进 timeDimensions 而非复制 + 补齐 __compare 渲染)符合派发裁决;「渲染出对比列」是验收标准的另一半,dev 补上是对的。

    新发现入池:#3613(data-objectstack 的 compareTo.dimension 与 spec rc.5 相悖地必填)、#3614(pivot 丢 __compare 列)。


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions