fix(spec)!: dashboard widget compareTo 收敛为执行器契约 { kind, dimension? } (#5011) - #5147
Merged
Merged
Conversation
…ract (#5011) WIP: schema + contract + executor resolution rule + ADR-0087 D2/D3.
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Contributor
📓 Docs Drift CheckThis PR changes 2 package(s): 108 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5011
按 2026-08-04 维护者裁决执行:方案 1 + 执行器决议规则。⛔ 不重议。
问题
widget 声明了三个对比分支,TSDoc 写得很具体;分析执行器实现的是另一份契约,而且从来不是同一份。于是在 ADR-0021 dataset 路径(spec 自称「唯一面向作者的分析形态」)上三个分支全废,而且是两种不同的废法:
compareTo: 'previousPeriod'/'previousYear'—— 被 dataset 渲染器静默丢弃。基础数值照常渲染,作者要的对比列不存在。compareTo: { offset: '7d' }—— 被原样转发进DatasetSelection.compareTo,而那个契约是{ kind, dimension },里面根本没有offset这个概念,于是执行器抛compareTo requires a timeDimension "undefined",整块 widget 报错。三个分支只在遗留内联图表路径上真的能跑。同一个键两种命运,失败的那条恰是 spec 自己推荐的规范路径 —— 这比普通的「declared but unread」更靠后一档:文档在自信地教一个会崩的形状。
改法
compareTo变成已实现的那份契约的薄投影:即
DatasetSelection.compareTo。widget 侧不再有第二套词表可以漂移,declared = enforced由构造保证,而不是靠人盯。DashboardWidgetOptionsSchema(有意的 passthrough)与responsive墓碑均未触碰。dimension可省略 —— 决议规则在执行器,不在渲染器省略时由
dataset-executor.ts的resolveCompareDimension决议,判据沿用执行器自己一直在用的那条(timeDimensions条目带dateRange):最后一条是最要紧的:作者想比
close_date而系统挑了created_at,得到的对比列是错的而不是缺的 —— 后者会被发现,前者不会。这是生产端决议规则,不是 PD#12 反对的消费端宽容映射:dashboard widget、report、裸queryDataset三个调用方拿到同一个维度或同一个报错,没有任何渲染器处在「自己猜一个」的位置上。offset退休(ADR-0087)先实测存量(裁决要求):全仓 4 处
compareTo作者实例,全部是字符串形态,全在examples/app-crm;两个仓库里{ offset }实例为 0。符合预期 —— 规范路径上用过{ offset }的早就崩了,它根本无法在那里沉淀。compareTo: 'previousPeriod'{ kind: 'previousPeriod' }compareTo: 'previousYear'{ kind: 'previousYear' }compareTo: { offset: '1y' }{ kind: 'previousYear' }1y就是 previousYearcompareTo: { offset: '7d' / '1M' / … }dashboard-widget-compareto-offset语义迁移最后一行是刻意不改写:
previousPeriod按 filter 解析出的窗口自身长度位移,只有当那个窗口恰好是 7 天时才等于7d。机械改写会悄悄改变对比列统计的是哪些行 —— 把一个响亮的失败换成一个错误的数字,正是本次收敛要终结的失败类。retiredFromLoadPath: true:旧拼法不给接受窗口。自动转换的 loader 会让compareTo: 'previousPeriod'继续解析通过,那就是 PD#12 禁止的宽容消费者,也正是让两套词表悄悄漂移一整个大版本的那个动力学。存量sys_metadata行仍被覆盖 —— 每个再水化缝都会通过applyConversionsToStoredItem重放已退休条目(#3903)。三个值得单说的点
1. 新形状不含联合,这不是外观问题。 zod 把失败的联合塌缩成一条裸
Invalid input,zodIssuesToFields只映射顶层 issue —— 所以本战役写进联合 arm 里的每一条精心措辞的处方,都是写给一个收不到它的读者的(#5014)。批 14 的台账行为compareTo记下了这个限制;本 PR 消解了它(而不是绕过),处方现在就在顶层。#5014 对其他所有联合 arm 仍然成立—— 台账行改成了「一个槽位的更正」,不是该 finding 的撤回。2. 字符串形态的处方按
issue.input分派(HookBodyCapability/object.managedBy: 'system'先例):只有真的合法过的两个拼法拿到「was removed」文案;写previosPeriod的人被告知的是拼错,而不是被告知一个他从没用过的东西「被移除了」。为此给strictObject加了一个窄的retiredForms钩子 ——guidance到不了这个 case,因为输入根本不是对象时unrecognized_keys不会触发。3. 台账更正而非重写。 liveness 的
compareTo判定仍是live,这点值得停一下:它从来就不是「declared but unread」—— 消费者一直都在,缺的是对它消费什么的共识。这是台账此前没有词汇描述的一类失败,它自己的compareTo行不得不用一整段散文来记录。_note里写清楚了。跨分片交接(#4876 式)
objectui 遗留内联图表路径不在本 PR 内,已按裁决未认领开单:objectstack-ai/objectui#3337,映射逐条写明:
CompareToConfig改型、shiftFilterByCompareTo按.kind分派、compareToTrendLabelKey、以及功能性的那一半 ——DatasetWidget需要把已解析的日期窗口降成selection.timeDimensions[].dateRange,否则执行器无窗口可移。该 issue 也记明:DatasetWidget.tsx:163-168的字符串丢弃 workaround 在新形状下不再需要,应一并删除。验证
check:generated8/8 up to date;十条 source-audit gate(check:liveness/check:empty-state/check:strictness-ledger/check:skill-examples/check:skill-refs/check:skill-docs/check:react-declaration-parity/check:variant-docs/check:exported-any/check:dual-source-exports)全 PASS。@objectstack/spec7745 tests、service-analytics538 tests、example-crm20 tests、CLImigrate-meta.e2e12 tests 全绿;全仓pnpm typecheck124/124。objectstack validate通过(残留 warning 均为既有、与本改动无关)。getMetadataTypeSchema('dashboard')),负控先证绿再断言退休形态不过关 —— dashboards 确实被 validate 覆盖,仍照objectstack build/validate从不按 PageSchema 解析页面元数据:ADR-0089 D3a 早就该拒绝的键一路通过,#4001 的「三个示例应用 validate 全过」对 page 面是空证 #5000 的纪律探一遍。git merge origin/main(⛔ 未 rebase / 未 force-push)→ 把 os-regen 路径 checkout 回 origin/main → 整体重生成 → 实测 sibling 条目全部存活(spec-changes.json相对 origin/main 的增量恰好只有我这两条;dashboard-widget-responsive-removed/view-inert-keys-removed/hook-body-crypto-hash-removed等各 2 处均在)。changeset:
major(spec + service-analytics),含 FROM → TO 映射与一行修法。🤖 Generated with Claude Code
https://claude.ai/code/session_01Ehu85kbvMcrNTUJjwxvLJ9
Generated by Claude Code