Skip to content

schema-catalog: all 9 plugin-dashboard examples are refused by the spec's DashboardSchema — the AI few-shot corpus teaches the pre-ADR-0021 widget shape #4600

Description

@yinlianghui

Found while implementing #4356 (Phases 0+1), measuring whether the guardrail that card asked for could be built as suggested. Not fixed there — that card's scope is the globalFilters[].options shorthand, and this is strictly larger.

What was measured

Parsing every examples/schema-catalog/src/schemas/plugin-dashboard/*.json entry with the real @objectstack/spec DashboardSchema, on origin/main at 92250d648:

REJECT  basic-dashboard.json                        (17 issues)
REJECT  e-commerce-dashboard.json                   (22 issues)
REJECT  filtered-dashboard.json
REJECT  filtered-dashboard-dataset-widgets.json
REJECT  filtered-dashboard-date-presets.json
REJECT  filtered-dashboard-dynamic-options.json
REJECT  filtered-dashboard-filter-types.json
REJECT  filtered-dashboard-target-widgets.json
REJECT  support-dashboard.json

9 of 9. Fixing #4356's bare-string options shorthand does not change this — those three entries stay refused for the reasons below, which is why #4356 pinned its guardrail at GlobalFilterSchema (the sub-schema that owns the property that regressed) rather than at DashboardSchema as the objectstack#7917 survey had suggested. That narrowing is deliberate and recorded in that PR; this issue is the remainder.

Two distinct causes, and they are not the same kind of problem:

1. Metadata identity keys — arguably by design. Every entry reports [name] Invalid input: expected string, received undefined and [label] Invalid input. These are objectui SDUI component schemas ({ "type": "dashboard", "title": …, "columns": … }), not stored platform metadata documents, so they legitimately carry no name / label identity. If that is the intended reading, then DashboardSchema is simply the wrong schema for an SDUI node and the interesting question is which schema is right.

2. The widget shape — this is the real finding. Most entries' widgets use the pre-ADR-0021 inline analytics form:

[widgets.0] Unrecognized key(s) on this dashboard widget: `object`, `categoryField`, `aggregate`.
  • The pre-ADR-0021 inline analytics shape (`object` + `categoryField` + `valueField` + `aggregate`,
    pivot `rowField`/`columnField`) was removed — bind a `dataset` and select `dimensions` + `values`
    by name. Renderer-only settings belong under `options`. Undeclared top-level keys were dropped
    silently before strict validation, shipping inert metadata; a stale or mis-layered key is now a
    loud parse error.

@objectstack/spec 17 removed that shape. And objectui's own DashboardWidgetSchema (packages/types/src/complex.ts) does not declare object / categoryField / aggregate either — it takes its keys from the spec through extends and adds only component, layout, type, options, chartConfig, filter, responsive. So these examples author keys that neither contract declares. Nothing catches it because the entries are imported as JSON and the catalog's only assertions are structural (smoke.test.tsx) and render-without-throw.

Why it matters

This is the same defect class as #4356, in the same corpus, with the same blast radius — and #4356's was judged worth a card. examples/schema-catalog/package.json describes itself as the "single source of truth for example schemas consumed by the docs site, smoke tests, and AI few-shot retrieval", and test/fields-form-hosted.test.tsx records the #3910 lesson verbatim: "these examples are the docs site's field demos and a few-shot retrieval source for AI authors, so what they show is what gets copied."

So an AI author retrieving filtered-dashboard.json today is taught a widget shape the platform refuses at publish, exactly as it was being taught the bare-string options shorthand until #4356. The objectstack#7917 survey's core point applies unchanged: the stored population of these documents is still growing, because the corpus is still producing them.

Uncertainty, stated plainly

Not measured here: whether objectui's renderer still supports the inline analytics form at runtime. It evidently renders (the catalog's render-without-throw tests pass), so this may be a live compat arm rather than dead metadata — in which case the finding is a documented-tolerance divergence of the #4356 shape (renderer accepts, spec refuses) and wants the same enforce-or-retire treatment, not a silent rewrite of the examples. Whoever picks this up should establish that before choosing between "migrate the 9 examples to dataset + dimensions + values" and "retire the renderer arm too".

Related, both closed and from an earlier era: #824 (examples' dashboard/widget metadata vs spec) and #3965 (48 catalog examples using the deprecated div component type) — same corpus, same failure mode, which suggests the catalog needs a standing spec-validation gate rather than another one-off sweep. #4356 added one for globalFilters only.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions