Repository navigation
fix(plugin-dashboard): retire the metric sub-caption reads at both ends (objectui#11389) - #11957
Conversation
…ds (objectui#11389) Ruling C retires the metric sub-caption at both ends, objectstack first. @objectstack/spec 17.7.0 removed translateDashboard's options.description overlay and refuses a widgets.ID.subCaption translation entry by name; this is the reader half. - plugin-dashboard: DatasetWidget loses its subCaption prop and its read of the options bag's description; the useWidgetSubCaption module (both limbs) is deleted; both surfaces' inline metric arms drop the key from the options spread through one helper, withoutRetiredSubCaption. widget.description still draws as the card-header subtitle. - i18n: useObjectLabel() no longer returns widgetSubCaption. - sdui-parser: CONSUMED_WIDGET_OPTION_KEYS drops description, so an authored options.description draws the unconsumed-widget-option warning. - The sub-caption tests are reversed into absence pins, with lit controls; docs and README stop describing the sub-caption. Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw Co-authored-by: Claude <noreply@anthropic.com>
… retired (objectui#11389) The member-count pin anchors the hook's surface to an absolute; retiring widgetSubCaption with the metric sub-caption takes it from 28 to 27, and the pin now also names the retired member as absent. Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw Co-authored-by: Claude <noreply@anthropic.com>
…i#11389) The retirement edit dropped it; whitespace only, no behaviour change. Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw Co-authored-by: Claude <noreply@anthropic.com>
❌ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. Which half objected:
📦 Bundle Size Report
Size Limits
|
|
Generated by Claude Code |
…version literal (objectui#11389) doc-version-claims flagged the two `@objectstack/spec` 17.7.0 literals this branch added to plugin-dashboard.mdx. Following the gate's prescription, the literals are dropped and the facts kept: the spec no longer writes the key from a translation, and its translation schema refuses a `subCaption` bundle key by name. Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw Co-authored-by: Claude <noreply@anthropic.com>
❌ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. Which half objected:
📦 Bundle Size Report
Size Limits
|
…sk (objectui#11389) check-hand-rolled-comment-mask flagged the leg's private regex projection of comments. The leg reports file names only, never a line or an offset, so it now calls the shared scanner's stripComments, as the gate prescribes. No DEBT entry is added. Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Inputs read: card objectui#11389 (body; ruling ① Derived judgmentsEvery accept-set and public-surface change the diff implies, each judged against ruling C (「retire the metric sub-caption at both ends」; pins: a metric tile draws no sub-caption from
Judged wrong on the contract faces (accept sets, public surface, parser report): none. ② Semver level
③ Boundary flagsDeviations (dev report
Other flags in the report. Check-runs on
FAIL items (two):
Items ①, ② and ③ otherwise hold, and both fixes sit outside the contract faces (two prose sentences; one test instrument's import), so the record on the corrected head can be narrow: those two edits, and the gates' answer on the new head. Implemented-by: VERDICT: FAIL Generated by Claude Code |
…tire-subcaption-reads
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
1 similar comment
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Contract reviewServed-tier: Inputs read: card objectui#11389 (body; ruling Scope: NARROW, as ① Derived judgments
Judged wrong on the contract faces (accept sets, public surface, parser report): none. ② Semver levelUnchanged from ③ Boundary flagsThe base merge, Dev reports Carried from Check-runs on FAIL items: none. Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #11389
Clause-②: no
objectui#11070 remains open. This PR is the objectui reader half of ruling C on objectui#11389 (record
5942430353), after objectstack's half landed as99e1912afcand shipped in@objectstack/spec17.7.0, which objectuimaininstalls.What changes
@object-ui/plugin-dashboard. No metric tile draws a sub-caption any more, on either surface (DashboardRenderer,DashboardGridLayout), dataset-bound or stored inline.DatasetWidgetloses itssubCaptionprop, its read of the options bag'sdescription, and the caption row.widgetSubCaption.ts(useWidgetSubCaption, both limbs) is deleted, and both dispatch sites stop passing the prop....optionsonto the metric node, andMetricWidgetdraws the node'sdescriptionas its caption. So the spread alone kept drawingoptions.description. Both arms now spreadwithoutRetiredSubCaption(options), one helper inwidgetDispatch.ts, so the two surfaces cannot disagree.DashboardGridLayout's arm was not on the dispatch's list; it is the same read through the same spread.widget.descriptionstill draws as the card-header subtitle onDashboardRenderer, translated through the widget'sdescriptionbundle key.@object-ui/i18n.useObjectLabel()no longer returnswidgetSubCaption(limb 2's resolver).@object-ui/sdui-parser.CONSUMED_WIDGET_OPTION_KEYSdropsdescription; it is now exactly the five keys the spec declares.plugin-dashboard.mdx(the options table row and the translation-key list), the plugin-dashboard README'slocalizedsection, anddashboard-filters.md, whose sentence "the renderer still draws a stored widget that carries them" this change made false foroptions.description.Exports removed or narrowed
@object-ui/i18n: thewidgetSubCaptionmember ofuseObjectLabel()'s return value. Nothing in this repo read it.@object-ui/sdui-parser:CONSUMED_WIDGET_OPTION_KEYSloses'description'. The export stays.@object-ui/plugin-dashboard: nothing on the package entry.useWidgetSubCaption,SubCaptionWidgetandDatasetWidget'ssubCaptionprop were internal. The newwithoutRetiredSubCaptionis internal too.The changeset
.changeset/11389-retire-metric-subcaption.mddeclares the three packagesminorwith the BREAKING note and lists the same removals.The restart probe, run first on the install surface
The hold comment (
5947079886) ordered it before any edit:@objectstack/specresolves to 17.7.0 frompackages/types,packages/i18n,packages/plugin-dashboardandpackages/sdui-parser.TranslationDataSchemaandTranslationBundleSchemarefuse a bundle carryingdashboards.D.widgets.W.subCaption:invalid_typeat that path, with a message naming the key as removed in 17.7.0.widgets.W.titleparses on both schemas.@objectstack/sdui-parser@17.7.0(pulled in by@objectstack/lint) has five keys and nodescription. objectui's ownCONSUMED_WIDGET_OPTION_KEYSstill haddescriptionbefore this PR.The dispatch's mechanism assumptions, measured
H1 (read sites): confirmed, plus one. Re-measured on
19a7348(mainhad moved past the seat'sf1781be). The read sites:DatasetWidget's metric branch;useWidgetSubCaption's limb 1;DashboardRenderer's inline metric arm (description: subCaptionafter the spread);subCaption={tWidgetSubCaption(datasetWidget) ?? null});DashboardGridLayout's inline metric arm, whose bare...optionsspread carried the key intoMetricWidget.H2 (limb 2 has no live feed on 17.7.0): holds.
subCaptionbundle entry exists anywhere in objectui. On objectstackorigin/main(f4bed583) only the tombstone, the conversion, the migration entries and prose remain.subCaptionat load: the conversiontranslation-widget-sub-caption-removedisretiredFromLoadPath, and the schema tombstone does the refusing.I18nProviderconfig.resources;loadLanguage:transformSpecTranslationscopiesdashboardsthrough verbatim;useObjectLabelmember.H3 (the parser half): narrows. The accepted set goes from 6 keys to 5. For an authored
options.descriptionon a dataset-bound widget:expected [] to have a length of 1 but got +0.warning, codeunconsumed-widget-option. It is a warning, never an error, andsuppressWarningsstill applies.Pins: reversed, not deleted
DashboardRenderer.metricSubCaption.test.tsx(inline metric arm, both surfaces).subCaptiondraws nothing, while the same entry'stitletranslates (the lit control).kpi,widget.descriptiondraws as the header subtitle andoptions.descriptionbeside it does not.namedraws nothing either.DashboardSurfaces.datasetSubCaption.test.tsx(dataset tile, both surfaces).subCaptiongrows none, with or without an authored value.widget.descriptionheader subtitle is drawn.DatasetWidget.subCaption.test.tsx(direct mount). Every authored form renders the no-caption markup byte for byte.DashboardRenderer.servedLocalized-11295.test.tsxand app-shellDashboardView.servedLocalized-11295.test.tsx. The four live texts keep their pins. The retired sub-caption stays in the fixtures (on the served widget and in the bundle) and is pinned absent.dashboard-widget-options.test.ts. A new H3 block, with a control: a widget-leveldescriptionand a declared option draw nothing.dashboard-widget-options-census.test.ts.descriptionis refused by name.plugin-dashboardsource readsoptions.descriptionor resolves asubCaption, with a litoptions.limitcontrol on the same comment-stripped scan. The resolver module is gone and no surface calls its hook.widgetSubCaption.tsanduseObjectLabel.ts.useObjectLabel-identity-5564.test.tsx. The member-count pin goes from 28 to 27 and now nameswidgetSubCaptionas absent.Reverse verification
All three ablations ran from the committed
344f8cea. Each mutation went throughablation-replace.mjs, with the anchor count and the blob change verified on disk, and each restore was proven: blob equal toHEADandgit diff HEADempty. The tests resolve@object-ui/*tosrc/through the root vitest aliases and import their subjects relatively, so nodist/leg applies.descriptionback intoCONSUMED_WIDGET_OPTION_KEYS. Red as predicted: 4 failed and 27 passed. The failures are the two H3 cases, census leg 1 and census leg 2's "every accepted key has a read site". The H3 control stayed green.withoutRetiredSubCaptionreturnoptionsunchanged. Red as predicted: 18 failed and 19 passed. Every failure is an inline-arm pin:metricSubCaptionon both surfaces, and bothservedLocalizedfiles. The two dataset-tile files stayed green, so the pins discriminate by arm.options.descriptioncaption intoDatasetWidget's metric branch. Red as predicted: 11 failed and 29 passed.Tests and gates
The head is
0916a26d. The two commits after344f8ceatouch onlypackages/i18n: the count pin, and one restored space inuseObjectLabel.ts.Tests (
pnpm exec vitest runfrom the repo root):packages/plugin-dashboard/: 174 files, 1725 passed and 6 skipped, at344f8cea. The baseline at19a7348was 195 files and 2030 passed across plugin-dashboard and sdui-parser together.b8b7d515: 117 files, 2304 passed and 13 skipped. It covered:packages/sdui-parser/andpackages/i18n/;servedLocalizedtest;unconsumed-widget-option-claim-6186,one-authority-per-exported-name-6273,markdown-test-inputs,dollar-dialect-alias-census,check-doc-component-types,check-control-bytes,check-i18n-call-site-keys,check-i18n-dead-keys, the schema-catalog dashboard gallery render, the console and cliunfulfilled-chart-stubs-8760tests, and the typesdashboard-widget-slot-component-arm-7952andstrict-face-read-keys-11070tests.344f8cea, was red in exactly one test: the i18n member-count pin, 28 against 27.b8b7d515updates it.packages/i18n/andpackages/sdui-parser/again, at0916a26d: 103 files, 1617 passed and 13 skipped.Type-check:
pnpm --filter … run type-checkfor@object-ui/plugin-dashboard,@object-ui/sdui-parserand@object-ui/i18nis green at344f8cea, with the script name echoed for each.@object-ui/i18nis green again at0916a26d, and@object-ui/app-shellis green at344f8cea.tsconfig.test.json --listFilesOnlylists the 4 changed plugin-dashboard test files and the 2 changed sdui-parser test files.Gates:
0916a26d:check-changeset-presence(1 changeset, 4 released packages touched),check:changeset-claims,check:new-line-citations(0 new),check:control-bytes,check:i18n-keys.b8b7d515:check:pending-changeset-literals,check:i18n-drift,check:i18n-dead-keys,check:doc-fences,check:doc-types,check:doc-snippets(784 of 784 blocks judged, 0 failed),check:doc-examples,check:readme-exports,check:skill-examples.dist/). They ran after the scoped buildcheck-doc-snippet-types.mjs --build-filternames (35 tasks).pnpm lintis CI's. ESLint over the 14 changed TS/TSX files gives 0 errors and 34 warnings. One warning sits on a changed line: theDatasetWidgetsignature, rewritten to dropsubCaption; itswidget: anypredates this branch. This is a targeted run, not a proven narrowing.check-governed-queue-guard.mjs --testanswers NOT GOVERNED for all 18 paths.Acceptance notes
DatasetWidgetto drawoptions.description, was filed fromobjectstack-ai/duly(duly#109), which asked for a caption under a KPI value. The ruling's producer count covered objectui and objectstack. Whether duly authorsoptions.descriptiontoday is NOT MEASURED: this session could not read that repository (REST 403, and repository access was not granted). If it does, its tiles lose that caption silently on render, and the authoring validator now warnsunconsumed-widget-option. The ruling already names the way back: a declared widget-level key outsideoptions.DashboardGridLayout's card header draws the title only, neverwidget.description;DashboardRendererdraws both. This predates this PR and is dormant: no in-repo surface mountsDashboardGridLayout. Not filed.5946940099) says objectstack seat post finding: two follow-on questions record:path's one-classification fix deliberately did not settle — a declared mid-pathterminal: 'won', and whether the lost alt-group slice should be classification-driven #6017 carries them for the.objectui-shabump.The implementing session is
https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw.Generated by Claude Code