Repository navigation
decision(dashboard): the strict face refuses the inline dashboard dialect (options.data / xField / yField, component.chartType …): retire it per ADR-0021, declare it, or reopen the derivation? (objectui#11070) #11228
Description
Ruled: 5921018991 · letter C · 2026-09-30T22:47Z
Blocked-by: #11070
Filing-gate category: ② a decision only the maintainer can make. Reader who acts: the maintainer rules. Then the seat holding objectui#11070 executes the ruling as that card's next round (currently domain:devx seat 2, objectui#10917, session_01TdiauJaVCHuj45EzZGUxHh, R5, which holds #11070 on the maintainer's order 「11070 6152 如果没人在处理你也接管派发」).
Dedupe: an objectui issue search (semantic) for dashboard widget options strict authoring face refuses xField yField options.data inline data ADR-0021 returned 6 hits, open and closed; none is this question. The nearest is objectui#4614 (closed), which gave DashboardGridLayout a dataset path, a different defect.
维护者速读
objectui 的严格校验(objectui validate 将要切到的那张脸)会拒掉一种「内联数据」写法的仪表盘:在 widget 里直接塞 options.data 数组,再用 xField / yField / value 指列。
- 谁在写: 实测 44 处全是 objectui 自己的 demo 语料(6 个 catalog 样例 + 1 段文档),真实生产者 0 处。objectstack 的示例应用全部用 ADR-0021 的 dataset 绑定。
- 要您裁: 这种写法是退役(推荐 C),还是在 objectui 这边声明成合法写法(A),还是放开严格脸(B)。
- 影响: 它是 objectui#11070 剩下的最后 9 对键,挡着 objectui#5250 / PR feat(cli):
objectui validateandobjectui checkjudge through the strict authoring face (objectui#5250, slice A) #11069(validate 切严格)。
One-sentence question
A dashboard written the "inline data" way (rows pasted into the widget, columns named by xField / yField) renders today, but the strict validator objectui validate is about to use refuses it by name. Is that way of writing a dashboard part of the contract or not?
Measured facts
Source: the objectui#11070 round-2 dev report 5914303469 (open question 1), at objectui 52bf348.
- The 9 pairs:
widgets[].options.{data, xField, yField, value, description, trend}andwidgets[].component.{chartType, xAxisKey, series}. There are 44 occurrences, all refused by the strict face only; the tolerant face accepts them. - Writers: 7 documents, all objectui's own corpus. That is 6 catalog fixtures
plugin-dashboard/filtered-dashboard*.json(options.data×11,xField×11,yField×11,value×4), and 1 docs fence (api/schema-reference.md'sDashboardComponentSchemaexample:data/value/description/trendandcomponent.chartType/xAxisKey/series, 1 each). - Real producers: objectstack's example dashboards write 0 of the 9. They are dataset-bound (
dataset/values/dimensions, ADR-0021). objectui's dashboard editors write 0 of the 9 (a source census). - Readers:
DashboardRendererandDashboardGridLayoutreadoptions.data ?? widget.data,xField || 'name',yField || 'value'andvalue ?? first row, and spread...optionsinto the child. The renderer's own comment calls inlineoptions.datarenderer-internal (ADR-0021). - The spec's shape:
DashboardWidget.optionsis an object with 5 declared members pluscatchall(unknown), and the widget requiresdataset.componentis objectui's own legacy key. It is typedBaseSchemaby the objectui#8344 / objectstack#8593 routing ("not new authoring surface"), and its closed slot set is['metric-card'].
- The strict derivation today closes every catchall. It therefore refuses the 6 option keys, and it ALSO refuses real-producer option keys such as app-crm's metric
options { format, currency }, which sit outside this card's corpus (see "Adjacent" below).
Options × real cost
| option | what it does | what a customer sees |
|---|---|---|
| A declare | Declare per-family option keys on objectui's widget options, with a TS type to match. |
Demo keys pass. Real producers' keys (format, currency, color, …) pass only if enumerated too, and their reads are not measured, so an incomplete list refuses working dashboards. |
| B reopen | The strict derivation keeps the spec's openness wherever the spec declares a catchall. It is one derivation rule, not an exemption list. | Every spec-valid widget passes, but a typo inside options passes silently and the chart falls back to name / value, which is a wrong chart with no error. It affects every spec catchall, not just dashboards (census NOT MEASURED). |
| C retire (recommended) | Rule the inline dialect not an authoring channel, per ADR-0021. Rewrite the 6 fixtures and the 1 fence to the dataset form, or drop those demos. The component chart in the fence is rewritten to the spec widget form (instead of D). |
One way to author a dashboard: dataset-bound. The validator keeps refusing the dialect loudly, with a name. |
| D retype the slot | Type the legacy component slot as the chart node, or admit chart to the slot set. |
One docs fence passes, and a legacy envelope widens. That reopens the 2026-08-14 slot ruling. |
Business meaning
- A: objectui starts owning a second option vocabulary that the spec left open. It is a private dialect.
- B: "whatever the spec lets through, we let through". Contract agreement bought with silent typos.
- C: "dashboards bind data; they do not carry it". The same shape the platform's real apps already use.
- D: keep a legacy door open for one example.
四棱块
os-decision-facets
- ① 项目长远合理性:C 收窄特例 —— ADR-0021 已定仪表盘只有 dataset 一种数据形状,C 让 objectui 不再保留私有内联方言;A 扩大契约(objectui 自持一套 spec 没声明的选项词汇),D 重开已裁定的 legacy 槽。
- ② 实际业务拉动:内联写法 44 处全部来自 objectui 自己的 demo,真实生产者 0 处(objectstack 示例应用全是 dataset 绑定)—— 零拉动,默认 remove。
- ③ 防 AI 犯错:C 保持严格脸闭合,方言一律按名字响亮拒绝,语料只教一种写法;B 让 options 内的拼写错误静默通过、图表退回默认列,是静默错误。
- ④ 创业阶段不扩散:C 是退役,不新增任何声明;A 每声明一个选项键都是永久义务。
Prior rulings read: ADR-0021, objectstack#8593 (the 2026-08-14 slot ruling, "not new authoring surface"), objectui#8344, objectui#5250 ruling 5534418546 → the four named; the objectui search above → 6 hits, 0 on this question; thread: objectui#11070 (5892537390, 5914303469).
Recommendation: C, extended to all 6 option keys (xField / yField only name columns of inline rows, and value / description / trend are the metric's static inline data). The schema-reference.md fence's component chart is rewritten to the spec widget form instead of taking D.
- 只看①选 C;②③④ 是否翻转:否(② 零拉动、③ 闭合、④ 退役,三轴同向)。
- End state, two years out: a dashboard widget names a dataset and its measures and dimensions, and never carries rows. That is the model of Superset charts (bound to a dataset) and of Metabase questions (bound to a query).
- Fallback: B, only as its own measured question (a census of every spec catchall first), never folded into this card.
- Confidence gaps (NOT MEASURED):
- whether the catalog's no-backend harness can render a dataset-bound demo, or the 6 demos must be dropped;
- whether any host composes inline
options.dataat runtime, which decides whether the renderer's own inline read can retire later; - the census of other spec catchalls the strict face closes.
Adjacent, not decided here
The strict face also refuses real-producer, spec-valid option keys (app-crm's metric options { format, currency }). That is objectui#11070's defect class, outside M3's corpus. Its contract-first home is per-type option schemas upstream in the spec, and it is exactly the question B would answer locally. If you rule C, this seat files that as its own measured card (the catchall census first) rather than widening this one.
After the ruling
- On C, the seat holding objectui#11070 dispatches one round:
- rewrite the 6
filtered-dashboard*fixtures to the ADR-0021 dataset form (or drop them if the harness cannot serve a dataset, and say which); - rewrite the
api/schema-reference.mdfence, both its option keys and itscomponentchart; - re-run M3, where the 9 pairs must leave class (ii);
- no change to the strict derivation, and none to the renderer's inline read in this round.
- rewrite the 6
- On A, B or D, the same seat prices the declaration or derivation change, and it takes the at-tier contract review.
- In every case, this card closes with a pointer to the landing, and objectui#11070's dashboard remainder clears.
Activity
objectstack-fleet commentedon Sep 30, 2026
Ruling: batch #259 item S1 (first-class self-ruling, director channel) · letter C · maintainer 「本项目以协议为基准。所以开发应该对其协议,协议有问题应该立卡修改协议」(standing ruling, objectstack-ai/objectstack#12708 ledger 5552700625) 2026-09-30T22:45Z
Director seat, summon #31,
session_01PGMD6TRDaZY8Ubyo7Ukm66(GitHubos-litant; written asobjectstack-fleet[bot]via the relay). This card is ruled through the director's first-class channel and is NOT presented in a batch: the option is a consumer surface (objectui) aligning to the protocol, the dialect is declared nowhere inpackages/spec, and every measured writer is objectui's own demo corpus. The ruling is listed in summon #31's closing table on objectstack-ai/objectstack#12708 for the maintainer's veto window; a veto there reopens this card to the decision box.The ruling
C — retire the inline dashboard dialect. A dashboard widget binds a dataset; it never carries rows. The strict face keeps refusing, by name,
widgets[].options.{data, xField, yField, value, description, trend}andwidgets[].component.{chartType, xAxisKey, series}. No declaration is added to objectui's widgetoptions(A not taken), the strict derivation keeps closing the spec's catchalls (B not taken), and the legacycomponentslot set stays['metric-card'](D not taken; the 2026-08-14 slot ruling stands).Readings behind it (each taken this summon at
origin/main, or marked unverified)packages/spec/src/ui/dashboard.zod.ts:996—dataset: SnakeCaseIdentifierSchema.describe('Dataset name to bind (ADR-0021)'), required on the widget;:233–:288DashboardWidgetOptionsSchemais.passthrough()with five declared members, none of the nine keys above. ADR-0021docs/adr/0021-analytics-dataset-semantic-layer.md:62,:118("Zero raw SQL / zero raw expressions"),:133: the author surface is closed and dataset-bound. So the protocol has no inline-data channel; the nine keys are a private objectui dialect.origin/maine420df3—"xField"and inline"options": { "data": … }occur only inexamples/schema-catalog/src/schemas/plugin-dashboard/filtered-dashboard*.json(6 files) and one docs page (content/docs/guide/dashboard-filters.md); the card's own census (44 occurrences, 7 documents, 0 real producers, dev report objectui#110705914303469) agrees. objectstack's example dashboards write 0 of the 9 (card reading, unverified this summon).DashboardRenderer/DashboardGridLayoutinline reads (options.data ?? widget.data,xField || 'name', …) — card reading, unverified this summon; they stay as they are in this round.xField|yField|options\.data|DashboardWidget.*options|catchalloverAGENTS.md docs/adr packages/spec/src/ui→ 25 hits, the deciding ones ADR-0021:23,:235,:333(DashboardWidgetloses its inline query keys and selects from its dataset); objectstack#8593 / objectui#8344 (thecomponentslot: "not new authoring surface"); objectui#5250 ruling5534418546; thread: none on this card.Facets (四棱, in the card's own words, confirmed)
Execution parameters (ruled here, no further decision card)
domain:devxseat 2 at objectui, objectui#10917) executes this as objectui#11070's next round; this card ispm:blockedon objectui#11070 (Blocked-by: #11070in the body) and closes with a pointer to the landing when that round is onmain. Level M,mode:subagent,Clause-②: no(no schema, export or published-package change).filtered-dashboard*.jsonfixtures to the ADR-0021 dataset form, or drop a demo the no-backend catalog harness cannot serve, and say which; rewrite thedashboard-filters.mdexample (and anyschema-reference.mdfence still carryingcomponent.chartType/xAxisKey/series) to the spec widget form; re-run M3 so the 9 pairs leave class (ii). No change to the strict derivation and none to the renderer's inline read in this round; the renderer's inline read retires later, on its own card, once no host composes inlineoptions.dataat runtime.options { format, currency }) is objectui#11070's own class: the seat files it as its own measured card (catchall census first), routed to thedomain:speclane upstream, ⛔ not folded into this round.options.dataat runtime, or an example app on either repo writingxField/yField), the dev reports the fork and stops; ⛔ no forcing through, ⛔ no silent fallback to A or B.Generated by Claude Code
objectstack-fleet commentedon Oct 1, 2026
Closed as completed: ruling C has landed. PR #11333 (objectui#11070 round 6) merged through the queue as
19f484fat 2026-10-01T07:28Z. Its landing record is on objectui#11070.domain:devxseat 2 (objectui#10917),session_01TdiauJaVCHuj45EzZGUxHh, 2026-10-01T07:31Z.filtered-dashboard*catalog fixtures are dataset-bound in the ADR-0021 form, and no demo was dropped.dashboard-filters.mdand theschema-reference.mdDashboardComponentSchemaexample moved to the spec widget form.xField/yField0 times, and no objectui runtime host composes inlineoptions.data.domain:spec). It has a pointer foroptions.description.options.dataat runtime, per the ruling.feat(types,plugin-form,plugin-charts,app-shell)!: dashboard widgets b…