Repository navigation
Closed
Labels
domain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch loopprotocol:breakingtarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Description
从 #4001 批 15 中分离出来,未指派。批 15 已就地修正了错误的处方文本(否则会把它提升成一条带平台权威的报错),但底下的缺口是独立的一件事。
发现
packages/spec/src/ui/chart.zod.ts 里 #3752 写下的迁移说明是:
clickAction— … Migration:drillDown, or handle it in React.
批 15 要把这句话提升进 ChartInteractionSchema 的 strict 拒绝信息时,先按惯例核了处方指向的键是否存在。不存在:
grep -rn "drillDown" packages/spec/src/ui/*.zod.ts→ 只有这段注释本身;DashboardWidgetSchema没有任何 drill 相关键;ReportSchema有的是drilldown(全小写,ADR-0021 D2,布尔,默认 true);- objectui 侧则是
packages/plugin-charts/src/ObjectChart.tsx:602的const drillDown = (schema as any).drillDown;—— 一个未类型化的读取,后面真的驱动了 drill drawer、computeDrillFilter、drillDown.target/.maxRows/.columns。
即:渲染器实现了一套 drill 配置,协议里没有它的声明,而 spec 的注释在教作者写它。
为什么这是个问题,而不只是注释错字
如果批 15 照抄那句话,一个把 clickAction 改对的作者会被告知写 drillDown,然后被同一个刚加上的闸门再拒一次 —— 账本记过两次的 finding 7(「本战役自己的修复,给人指向了它本要消灭的失效模式」)的第三次。批 15 因此把处方改成只点名确实存在的东西(onSegmentClick / ReportSchema.drilldown / dashboard widget 的 options 袋),并留了一条测试钉死「永不出现 drillDown」。
但那只是让错误信息不再说谎。真实缺口仍在:
drillDown走的是options(DashboardWidgetOptionsSchema,故意passthrough)还是别处?今天没有声明,所以两种写法都「能跑」,取决于渲染器拿到的扁平化 schema 长什么样 —— 这是 Prime Directive chore: version packages #10 的 declared ≠ delivered,方向相反的一种:delivered 但 never declared。ReportSchema.drilldown与 objectui 的drillDown拼写不同、语义不同(前者是布尔开关,后者是{ target, maxRows, columns, mode }配置对象),名字却几乎一样。这正是本战役反复付学费的那类近似键。
建议
按 contract-first 择一:
- 声明它 —— 给 chart drill 配置一个 Zod 形状(
{ enabled, mode, target, maxRows, columns },从ObjectChart.tsx的实际读取点反推),挂在 widgetoptions或 chart config 上,再让渲染器读声明后的键;顺便决定与ReportSchema.drilldown的关系(是否统一拼写)。 - 或明确它是渲染器私有 —— 那就在
DashboardWidgetOptionsSchema的文档里点名drillDown属于「渲染器自有、协议不建模」的那一类(该 schema 已有这段话,只是没列它),并保持(schema as any)的读取方式,但不要在 spec 注释里把它当作可授权键推荐。
参考
- ChartConfig 剩余的 declared ≠ delivered 属性:stepSize / clickAction / zoom / description / height(#3729 收尾) #3752(移除
zoom/clickAction的那次改动,处方文本的来源) - 未知键静默剥离仍是全仓默认:把 #3405 的 strict 收紧从一个 schema 推广到整个可授权面(ADR-0078 完整性闸门) #4001 批 15(修正处方 + 测试钉;账本
ui/chart.zod.ts行记录了这条更正) - ADR-0021 D2(
ReportSchema.drilldown) packages/spec/src/ui/dashboard.zod.tsDashboardWidgetOptionsSchema(声明的渲染器逃生口)
Metadata
Metadata
Assignees
Labels
domain:specDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch loopReady for the PM dispatch loopprotocol:breakingtarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Activity
xuyushun441-sys commentedon Aug 4, 2026
维护者裁决(2026-08-04):A,且改动不大就整件进 v17(含拼写关系收口,不再拆两步)
执行定调:
ObjectChart.tsx实际读取点反推({ enabled?, mode?, target, maxRows?, columns? }以实测为准),strict(战役标准)。落点与拼写的最小改动路径:直接声明渲染器已在读的drillDown(objectui 零改动),挂 chart config(可发现性优于 options 袋)。ReportSchema.drilldown(布尔开关)与 chartdrillDown(配置对象)是两个概念,强行统一命名反而合并语义——默认走双向点名消歧:两个 schema 的 strict 门各带对方拼写的 guidance(在 report 上写drillDown→ 点名「这是 chart 的配置对象,报表开关是drilldown」,反向同理)。若 dev 实测重命名的爆炸半径确实微小且语义可清晰分离,可提议重命名方案,量大即回落双向消歧,不阻塞。.changeset/pre.json。needs-user-decision摘除,target:v18→target:v17,入队(T2 序,量小顺手)。Generated by Claude Code
xuyushun441-sys commentedon Aug 4, 2026
CLAIM
session_01Ehu85kbvMcrNTUJjwxvLJ9(spec 车道 PM,派发给 os-dev 实施)claude/issue-5022-drilldown-declareObjectChart.tsx实际读取点反推 Zod 形状,drill 配置成为声明键;与ReportSchema.drilldown的近似键关系按实测定,不猜。Generated by Claude Code
xuyushun441-sys commentedon Aug 4, 2026
实测结果与裁决前提冲突 —— 回
needs_decision,未写任何 spec 代码会话
session_01Ehu85kbvMcrNTUJjwxvLJ9派发的 os-dev。分支claude/issue-5022-drilldown-declare已 push(一个空提交,只承载证据,便于恢复),没有开 PR。裁决(2026-08-04)第 1 条的落点理由是:
这句话的前提在 chart config 上不成立。逐条量给你看(objectui @91757a7,objectstack @41e605ec70)。
一、
ObjectChart.tsx的真实读取词汇(反推,不用 issue 里的猜测)packages/plugin-charts/src/ObjectChart.tsx:602起,经@object-ui/core的drill-down.ts:enabledbooleanisDrillEnabled{}= 开;enabled: false= 关filterRecordcomputeDrillFilter${event.*}插值;缺省时按groupBy/xAxisKey推导titlestringresolveDrillTitle${event.*}插值target'drawer' | 'dialog':755'dialog',其余一律 Sheetcolumnsstring[]:762accessorKey/headermaxRowsnumber:761pageSizeObjectChart 不读:
mode、view、report、sort;并且不实现target: 'navigate'(那是DrillDownDrawer.tsx:84的实现,chart 自绘抽屉不走它,'navigate'静默落回 Sheet)。所以 issue 正文猜的
{ enabled?, mode, target, maxRows, columns }里,mode是别的 widget 的键,漏了filter/title。objectui 侧已经有一个共享 TS 接口
DrillDownConfig(packages/types/src/data-display.ts:897),是 5 个 widget 的并集:{ enabled, mode, target(含 navigate), filter, title, view, report, columns, sort, maxRows }。其中view/sort全仓无消费者 —— 已另立 objectui#3354。二、载体测量 —— 两个候选都不在 dashboard 元数据面交付
1.
widget.chartConfig.drillDown→ 无人读。DashboardRenderer.tsx全文 0 处chartConfig;DatasetWidget.tsx:595-605只取showLegend一个键,注释自陈 "the rest ofchartConfigstays unforwarded";:632构造的 chart schema 里没有drillDown。2.
widget.options.drillDown→ 只在一条 v17 作者走不到的分支上被读。DashboardRenderer.tsx:494/:570/:531确实读它,但全部在isObjectProvider(widgetData)的 legacy inline 分支内;DashboardWidgetSchema.dataset是必填(dashboard.zod.ts:427,无.optional()),于是datasetBound恒真,DashboardRenderer.tsx:691/:720恒渲染DatasetWidget,那份带drillDown的componentSchema被整个丢弃。options.drillDown永不被读。3. ADR-0021 正路的 drill 是派生的、不可配置的。
DatasetWidget的canDrill由dimensionFields/drillRanges决定,openDrill从 dataset 行构 filter,DrillDownDrawer只收{ objectName, filter, title, dataSource }—— 上面那 6 个键一个都不认。4. 唯一真活的面是 react tier。
react-blocks.ts:226-247把ChartConfigSchema的键作为扁平 prop 发布给ObjectChart块,而ObjectChart读的正是扁平schema.drillDown—— 所以 react 页面上写drillDown今天就生效。但它既不在 spec 的dataProps/interactions里,也不在 objectui registry 的inputs里(ObjectChart.tsx:822-830),SDUI save gate 会报unknown-prop(warning,不拦)。三、我们自己的文档已经写下了相反的结论
content/docs/ui/dashboards.mdx:273:skills/objectstack-ui/SKILL.md:1484:也就是说:已发布的文档和 skill 已经采用了本 issue 的第二臂(渲染器私有),只是没写进 spec schema 的 JSDoc。裁决选的是第一臂。两者今天是矛盾的。
四、需要你裁的两个问题
Q1 —— 载体(架构分叉,必须先定)
ChartDrillDownSchema+ObjectChart的interactions覆盖层),dashboard 面不声明,并在DashboardWidgetSchema的 strictguidance里点名「dataset 形态的 drill 是派生的,不可配置」drillDown会被 strict 门响亮拒绝并被告知去处;react 上写则有正式契约ChartConfigSchema(裁决原文)compareTo记过的 "same key, two fates"。注意这不是我新造的:chartConfig的 12 个键里已经有 11 个是这个形状(见 #5175),所以 B 是「加入一个既有的系统性缺陷」,不是「制造一个新的」chartConfig.drillDown会 parse 通过、渲染无效果、无任何提示 —— 正是本战役要消灭的静默options(或 chart config)并在 objectuiDatasetWidget真正落地compareTo的做法DatasetWidget要实现enabled/target/columns/maxRows/title/filter,且 dataset 聚合行的 drill 语义与mode: 'record'天然不匹配。裁决的前置条件「改动不大」不成立我的建议:A。 两个轴都指向它 —— 长期正确性上它是唯一让 declared = delivered 成立的选项(B 明知故犯,C 超出本单预算);防 AI 写错上它最强,因为它把 dashboard 面的错写从「静默无效」变成「strict 门带处方的拒绝」。B 的长期代价要说白:一旦写进公共参考页,下一次 ADR-0049 清扫要把它当死键处理时,它已经有协议权威了,退休成本比现在声明的收益高。
如果你更看重「dashboard 作者能配 drill」这个能力本身,那答案是 C,并且应该按 #5011 的规格另开一单做跨仓收口,而不是塞进本单。
Q2 —— 声明的形状(取决于 Q1)
{ enabled?, filter?, title?, target?: 'drawer' | 'dialog', columns?, maxRows? }—— 每一个键都有ObjectChart的读取点。mode/view/report/sort/target: 'navigate'—— 但 chart 一个都不读,view/sort更是任何 widget 都不读(objectui#3354)。建议:诚实子集,并在 JSDoc 里点明这是 chart 面的 drill,
mode/report是 table/pivot/metric 面的键。代价是 spec 类型不能直接被 objectui 的其余 4 个 widget 复用 —— 但那 4 个 widget 本来就不是 react tier 的发布块,让它们继续用 objectui 自己的DrillDownConfig是正确的分层,不是重复定义。五、近似键(按要求核过,未发现冲突,可照裁决第 2 条做双向消歧)
ReportSchema.drilldown(全小写,布尔,默认 true,ADR-0021 D2)与 chart 的drillDown(驼峰,配置对象)没有任何面重叠:前者在ReportSchema上、由plugin-report的DatasetReportRenderer.tsx:51,136读;后者在 chart/widget 的扁平 SDUI schema 上。两者不共享任何 schema、任何渲染器、任何存储行。所以不需要 STOP,双向guidance点名消歧是可做的 —— 等 Q1 定了落点之后一并写。六、顺带发现(已按 Prime Directive #10 立单,均未指派)
DashboardWidget.chartConfig在 dashboard 元数据面只有showLegend落地 —— 12 个已声明键里 11 个惰性,liveness 台账那一行高估了证据 #5175 ——widget.chartConfig在 dashboard 面只有showLegend落地,12 个已声明键里 11 个惰性;liveness/dashboard.json的chartConfig行证据写成 "chart-config bag forwarded",高估。这条直接影响 Q1 的 B 选项怎么读。DrillDownConfig.view/.sort无任何渲染器读取;target: 'navigate'在 ObjectChart 上静默降级。应先于本单的声明落地,否则协议会照着一份含死键的接口成形。Generated by Claude Code
xuyushun441-sys commentedon Aug 4, 2026
维护者裁决(2026-08-04,第二轮,基于上楼实测):Q1 = A,Q2 = 诚实子集
前一轮裁决(05:45)的「挂 chart config」落点前提被实测推翻,维护者改裁 A:
ChartDrillDownSchema+ObjectChart块的interactions覆盖层(进 registryinputs,让 SDUI save gate 从 unknown-prop 变成正式契约);dashboard 面不声明,DashboardWidgetSchema的 strict guidance 点名「dataset 形态的 drill 是派生的、不可配置的」—— 与已发布文档(dashboards.mdx:273 / SKILL.md:1484)一致。{ enabled?, filter?, title?, target?: 'drawer' | 'dialog', columns?, maxRows? },每键有 ObjectChart 读取点;JSDoc 点明mode/report是 table/pivot/metric 面的键,不抄 objectuiDrillDownConfig全集。ReportSchema.drilldown的双向点名消歧 guidance 照做(在新落点上);additive → minor changeset;target:v17(T2 序)不变。DrillDownConfig死键)宜先于或并行于本单落地,避免协议照含死键的接口成形;dashboard 作者可配 drill 若成真需求,按 dashboard widgetcompareTo:三个声明分支在 ADR-0021 dataset 路径上全部无效(两个静默丢弃,一个抛错) #5011 规格另立跨仓单(C 臂),本单不做。执行:恢复原 dev 会话(测量上下文在手)实施,配额重置后进行。
Generated by Claude Code
feat(spec,lint): declare the chart segment drill as ChartDrillDownSch…
yinlianghui commentedon Aug 5, 2026
知会:objectui 侧
DrillDownConfig已清理,spec 声明请以清理后的形状为准objectui#3354 已落地(draft PR:objectstack-ai/objectui#3382),即本单第三轮实测里点名的那两条前置。清理后的形状与本单已声明的
ChartDrillDownSchema对照:DrillDownConfigviewsorttarget: 'navigate''drawer' | 'dialog'前两条正是本单实测建议的方向,现在事实上成立了:第三轮实测里写的「
view/sort全仓无消费者」已不再需要靠注释提醒后人,类型上就没有这两个键了。一处需要 spec 车道回看的地方
本单第二轮裁决把
target定为'drawer' | 'dialog',理由是「每键有 ObjectChart 读取点」—— 一条测量。objectui#3354 的另一半正是把这条测量改掉:ObjectChart现在兑现target: 'navigate'(对齐DrillDownDrawer.navigateOnly,含 host 缺失时回落 drawer)。于是渲染器交付 3 个 target,协议声明 2 个,而validate-react-page-props会 parse strict schema 拒掉作者写的'navigate'。objectui 侧刻意没有把
'navigate'加进object-chart的 registryinputs描述 —— 那等于让面板推荐一个发布闸门随后拒绝的值,正是本单要消灭的失效模式。协议联合先动,面板再跟。已按 Prime Directive #10 另立 #5435(未指派)记录这条,不在本单里改。
Generated by Claude Code
feat(spec,lint): 声明 chart segment drill —— `ChartDrillDownSchema`,挂在真…
feat(spec): drillDown.target 补上 'navigate' —— 渲染器已兑现的第三个 arm (objects…
feat(lint): the react-page publish gate PARSES ChartAggregateSchema (o…
fix(spec): 三个手写 unrecognized_keys error map 把处方排到说明句之前 (objectstack-a…
test(spec): the first ui/ file group's test titles state each cited d…
test(spec): the second ui/ file group's test titles state each cited …