fix(spec-parity): the Tier-3 spec values render instead of red-boxing (#2943) - #3011
Merged
Conversation
…#2943) This tier fails LOUDLY — `SchemaRenderer` renders a red `role="alert"` panel naming the missing type and dumping the schema JSON. Three rows: **Dashboard chart dispatch.** Three surfaces restated the chart vocabulary independently and disagreed: `DatasetWidget` covered all 19 `ChartTypeSchema` values, `DashboardRenderer` 15, `DashboardGridLayout` 8. A type a surface didn't name fell through to `{ ...widget }`, whose `type` no component registers. The sharpest part was already half-done: `METRIC_LIKE_TYPES` existed with a docstring saying gauge/solid-gauge/kpi/bullet "render as a metric card rather than a chart" — and was consulted only to pick a grid span, so the tile was sized correctly and the widget was never routed. One shared `widgetDispatch` module now classifies a widget type into its family (series / metric / table / pivot / custom / unsupported / passthrough) and both renderers consume it. The single-value families reach the metric card, the dropped families get a labelled placeholder in the grid layout too, and the `list` branch folds into `table` while keeping its lighter chrome. **`ai:chat_window` was offered by Studio with a config panel and has no renderer.** `placeholders.tsx` documents a deliberate decision to exclude it so it fails loudly; the palette was never told, so an author dragged a block Studio advertised and got the red box. Pruned from `block-types.ts` and `block-config.ts` per the audit's recommendation — the floating chat overlay (plugin-chatbot) stays canonical. **Placeholder coverage was host-dependent.** `registerPlaceholders()` is opt-in and only `apps/console` calls it, so four blocks the palette DOES offer (`nav:menu`, `nav:breadcrumb`, `global:search`, `ai:suggestion`) red-boxed in every other host. Those four now register eagerly through the `./renderers` barrel; the rest of the protocol vocabulary stays opt-in on purpose, because a genuinely missing renderer must keep failing loudly. **The guard is inverted, as the issue asked.** `block-config.test.ts` used to hand-assert a few palette EXCLUSIONS, which locks drift in — a new spec block type could land and never reach the palette with nothing failing. It now derives coverage from `PageComponentType` (34 values): every value must be offered or listed in the new `PALETTE_EXCLUSIONS` with a reason, no value can be both, no exclusion may name a non-spec type, and a block with a config panel must be authorable (the seam `ai:chat_window` hid in). Inverting it immediately caught four wrong entries in my own first exclusion list. Refs #2943, #2901 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
os-zhuang
added a commit
that referenced
this pull request
Jul 30, 2026
…e spec adopting one (#2945) (#3016) The parity guard added in #3011 asserted `dialect === ['combo']` — an exact match against the one name objectui draws that the resolved spec does not define. That is the wrong shape for a drift guard: framework#4070 has already promoted `combo` into `ChartTypeSchema`, so the moment objectui bumps to a spec version carrying it, `dialect` becomes `[]` and the test fails with "expected [] to deeply equal ['combo']" — a cryptic red for the good outcome, landing on whoever does the bump rather than on whoever adds dialect. Now the tracked set is an upper bound: only UNTRACKED dialect fails, so the list shrinks silently as the spec adopts a name, and an entry the spec has since defined is reported via console.info so it gets pruned instead of accumulating as a stale exception. No renderer change; the coverage assertions are untouched. Refs #2945, #2943 Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.
Closes #2943 (Tier 3 of the #2901 audit — spec values that fail loudly; audit doc). Follows #2993 (Tier 1) and #3008 (Tier 2).
This tier renders
SchemaRenderer's redrole="alert"panel naming the missing type and dumping the schema JSON. Cheaper to triage precisely because it cannot hide.Dashboard chart dispatch
Three surfaces restated the chart vocabulary independently and disagreed —
DatasetWidgetcovered all 19ChartTypeSchemavalues,DashboardRenderer15,DashboardGridLayout8. A type a surface didn't name fell through to{ ...widget }, whosetypeno component registers.The sharpest part was already half-done, exactly as the issue observed:
METRIC_LIKE_TYPESexisted with a docstring saying gauge/solid-gauge/kpi/bullet "render as a metric card rather than a chart" — and was consulted only to pick a grid span. The tile was sized correctly and the widget was never routed.New
widgetDispatch.tsis the single classification (series / metric / table / pivot / custom / unsupported / passthrough); both renderers consume it. Net effect:gauge/solid-gauge/kpi/bulletradar/treemap/sankeyheatmap/candlestick/ …listtable, lighter chrome preserved#3008 made this cheaper than filed:
AdvancedChartImplalready renders single-value families as a number card, so this is routing, not a new renderer.The trap:
ai:chat_windowOffered by the Studio palette with a config panel (
block-types.ts,block-config.ts) whileplaceholders.tsxdocuments a deliberate exclusion so it produces a loud unknown-type error. The reasoning was sound; the palette was never told. An author dragged a block Studio advertised and got a red box.Pruned from both palette artifacts per the audit's recommendation — the floating chat overlay (plugin-chatbot) stays canonical.
The soft gaps turned out to be one defect, not seven
The audit lists 7 types as "dashed placeholder, but only in hosts that call
registerPlaceholders()". Tracing it: registration is entirely opt-in and onlyapps/consolecalls it, so four blocks the palette does offer —nav:menu,nav:breadcrumb,global:search,ai:suggestion— red-boxed in every other host purely because that host skipped an optional bootstrap.Those four now register eagerly through the
./renderersbarrel. The rest of the protocol vocabulary stays opt-in on purpose: auto-registering everything would mask genuinely missing renderers, which is the same reasoning that keepsai:chat_windowloud. The three shell singletons (app:launcher,global:notifications,user:profile) are not page blocks at all — a page referencing one is a misconfiguration, so the red box is correct and they're recorded as palette exclusions instead.The guard is inverted, as the issue asked
block-config.test.tshand-asserted a few palette exclusions, which locks drift in — a new spec block type could land and never reach the palette with nothing failing. It now derives coverage fromPageComponentType(34 values) and asserts:PALETTE_EXCLUSIONSwith a reason;ai:chat_windowhid in.Inverting it immediately caught four wrong entries in my own first exclusion list (
page:sidebar,record:activity,record:chatter,record:reference_railare genuinely offered), which is the point.Verification
pnpm build43/43;tsc --noEmitclean on all 4; eslint 0 errors on every touched file.Refs #2901. With this, all three renderer-facing tiers are done. Remaining: #2944 (forks — already in progress elsewhere) and #2945 (vocabularies; Track C still blocked on objectstack#3948).
🤖 Generated with Claude Code