Repository navigation
decision(plugin-dashboard): a dashboard metric widget bound inline to an object (provider: 'object', no dataset) — retire the path, or keep it as a namespaced node under V1 #11525
Description
Activity
- addeddomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lane
on Oct 3, 2026 objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsRuling: batch #271 · letter C · maintainer 「11525 同意」 2026-10-03T03:05Z
Director seat, summon #32, objectstack-ai/objectstack
session_016tKoy8NJa35Yih1FdzrVmn. Written asobjectstack-fleet[bot]through the relay.- How it was ruled. Batch Fix Storybook test-runner config loading in ES module project #271 was presented in the live director chat with this card's options A / B / C. The director recommended C, with fallback B, and filled part of the card's confidence gap (below). The maintainer answered 「11525 同意」.
- The freshness gate: this card has no comment.
The reading that filled part of the confidence gap (read this session)
- cloud (
c5a4c9e6cb): no dashboard widget authored or generated as a dataset-lessprovider: 'object'metric.- Every
provider: 'object'hit in cloud is a list or form view'sdata. - That includes the AI Studio blueprint's
viewBodyatblueprint-tools.ts:2050, which is views, not dashboards. - AI Studio's dashboard snapping reads dataset measures (
dashboard-snap.ts).
- Every
- hotcrm (
5ae524916d): its dashboards carry noprovider: 'object'. - Still unmeasured: stored customer dashboards.
The ruling
C: retire the dataset-less inline
provider: 'object'metric path.- Both dashboard surfaces map such a metric widget to the existing
LEGACY_RETIRED_WIDGET_SCHEMAplaceholder ("This widget uses a retired data format. Edit it to bind a dataset."), as the pivot arm already does (objectui#10528). - The inline chart and table arms are not touched.
Not taken:
- A: a published flat TS type, refused at validation. objectui#11479 Q1 already declined that shape.
- B: a permanent internal namespaced node, keeping a second filter dialect beside the dataset path.
四棱(本裁决新记录)
- ① 长远:仪表盘指标只经语义层(dataset)取数,同一数字一条口径;与透视表退役同构,删掉与规范已退役形态并行的第二方言。
- ② 拉动:零(objectstack 示例、hotcrm、cloud 仪表盘与 AI Studio 生成路径、objectui 写作面均 0 处)。
- ③ 防 AI:只留一种可写形态;存量卡显示可见的「请重新绑定」提示,不是空白。
- ④ 不扩散:删除,无过渡窗口。
- 只看①选 C;②③④ 是否翻转:否。
Execution parameters (ruled here; no further decision card)
- This card:
needs-user-decision→pm:queuein this act, for thedomain:spec @ objectuiseat (objectui#10217). The work:- both surfaces map the path to the retired placeholder;
- a dated correction for the metric family in
legacyRetiredWidget.ts's "still-LIVE" paragraph; - one changeset stating the render change.
- objectui#11466 (V1, PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer's
schemaprop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512) staysBlocked-by:this card until this card's PR lands, then drops these lines from its census. - Whether the inline chart and table arms follow is a separate question, filed only if the maintainer asks.
Generated by Claude Code
- added and removed
on Oct 3, 2026 objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsClaim: PM loop round 3 (the maintainer's ruling C, record
5964914121: retire the dataset-less inlineprovider: 'object'metric path to the existing retired-format placeholder, as the pivot arm already is)
Session:session_01XvhGmGAP79ZB8swnkapxPC
Account:os-tesla(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-11525-inline-metric-retired
Worktree:objectui-issue-11525
Domain:domain:spec
Seat:domain:spec#1(objectui#10217)
File surface:packages/plugin-dashboard/src, the declared cross-lanedomain:uisurface:- the dataset-less
provider: 'object'metric branch inDashboardRenderer.tsxandDashboardGridLayout.tsx, mapped toLEGACY_RETIRED_WIDGET_SCHEMA; - the flat
object-metricproducer, and the filter-broadcast plumbing that only that producer reads (FilterableComponentTypeand its union member), removed where nothing else reads them; legacyRetiredWidget.ts's "still-LIVE" docblock paragraph: a dated correction for the metric family;widgetDispatch.ts, only if the family classification needs it.
- the dataset-less
- Re-judged tests and pins, and the plugin-dashboard docs page and README, where they author or describe the inline metric path.
- One changeset stating the render change, plus dated notes on pending entries this makes false.
- ⛔ The inline chart and table arms are not touched. ⛔ No zod or TS authoring face moves.
Stop on breach; explain in the report.
Container & model:M,mode:subagent,model: opus(TIER_DEFAULT;dispatch-gates --tier --repo objectstack-ai/objectuiprinted "no path-derived mandate" overDashboardRenderer.tsx,DashboardGridLayout.tsxandlegacyRetiredWidget.tsat this claim)
Clause-②: no (narrowing)
Why no (narrowing): no validator face moves; both already refuse a dataset-less widget. The renderer stops drawing one stored legacy form and shows the retired-format placeholder, a capability retirement. Nothing widens. The at-tier contract record is owed on the landing head.
Thread-read: 5964914121
Serial constraints cleared: read 2026-10-03T03:42Z at objectuiorigin/main9d7419b91. - objectui#11514 (PR spec(types,plugin-dashboard,app-shell,plugin-designer): widgets[] entries read by the slot's element type, a typeless widget draws as
metricand an unknown type the placeholder, the object-chart producers name ObjectChartSchema (objectui#11514) #11524), which built the surfaces this card edits (resolveWidgetType, the spec default), landed as9d7419b91. - objectui#11522 (this seat, PR feat(types,plugin-kanban)!: object-kanban's conditionalFormatting takes the spec list view's { condition, style } rule only; the native and flat-colour dialects are refused by name (objectui#11522) #11532, in the merge queue) touches plugin-kanban and
objectql.ts. No overlap. - objectui#11466 (V1, PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer's
schemaprop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512) staysBlocked-by:this card and drops the object-metric census lines after it lands.
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 11525, "status": "done", "branch": "claude/issue-11525-inline-metric-retired", "pr": "https://github.com/objectstack-ai/objectui/pull/11538", "session": "session_01XvhGmGAP79ZB8swnkapxPC — the harness-stamped id on this run's commits (Claude-Session line); subagent, so the parent seat's", "premise_still_valid": true, "summary": "Ruling C is implemented on both surfaces. In DashboardRenderer and DashboardGridLayout, the metric arm now answers a dataset-less widget whose options.data (or widget-level data) is { provider: 'object', … } with the imported LEGACY_RETIRED_WIDGET_SCHEMA, the object the pivot arms return. That covers metric, gauge, solid-gauge, kpi and bullet, and a typeless widget, which resolves to metric. The flat object-metric producer is gone from both arms. legacyRetiredWidget.ts gets the dated, append-only correction for the metric family, and one changeset (plugin-dashboard minor) states the render change. H1 measured one thing the claim's wording anticipated: the broadcast's object-metric member is still read, because an author's legacy component envelope holding an object-metric node reaches the merge, and the filter bar scopes it today (probe: filter { region: 'EMEA' }). So the member and its type stay, with a re-pointed docblock and a pin; nothing else in that plumbing became dead. H2's chrome half is falsified for metric and typeless widgets, which draw self-contained with no heading; this is the same tile the retired legacy-shape metric already draws, and a pin holds the two DOMs equal. gauge, solid-gauge, kpi and bullet draw the Card heading, as the pivot does. The chrome was not changed (see open_questions). The inline chart and table arms are untouched, and no zod or TS authoring face moves. PR #11538 is a draft; its assignee is os-tesla, read back.", "census": { "producer_sites_removed": [ "DashboardRenderer.tsx, metric arm: the provider-object branch that built { type: 'object-metric', ...options, objectName, label, description, aggregate, filter } now returns LEGACY_RETIRED_WIDGET_SCHEMA at the top of the arm.", "DashboardGridLayout.tsx, metric arm: the same branch is replaced the same way.", "Kept and re-documented, not removed: FilterableComponentType / FILTERABLE_COMPONENT_TYPES 'object-metric' and its FilterableComponentSchema union member. A widget's component envelope still feeds an object-metric node to the broadcast merge." ], "tests_and_docs_rejudged": [ "Whole-tree census: git grep for a file pairing a provider 'object' literal with a metric-family type literal found 0 tests, fixtures, stories or examples that author a dataset-less inline provider metric through a dashboard surface or assert its number. The hits were prose, CHANGELOGs, this card's own files, and two tests whose provider widget is a bar. The plugin-dashboard suite was all green before the new pins were added.", "DashboardGridLayout.legacyRetired.test.tsx: dated note on its header ('still-live for every family' no longer holds for the metric family). Its provider control is a bar, so the control stands. Verdict: note only.", "DashboardGridLayout.datasetPath.test.tsx, widgetDataProviderRetired-7353, dashboard-producer-node-types-11514, DashboardChart.countSeriesKey-8266 / categoryAxisKey-8269 / chartConfig-4044, DashboardGridLayout.seriesLabel-9172, fieldKeySpellingOutsideTable-9055, ObjectDataTable.invalidationRefetch-10778: provider bar, table or pivot widgets. Verdict: left alone, untouched families.", "DashboardRenderer.legacyRetired.test.tsx: the top-level object shape only. Verdict: left alone.", "content/docs/guide/dashboard-filters.md and content/docs/plugins/plugin-dashboard.mdx: one paragraph each naming the stored form that now draws the prompt. Verdict: amended.", "packages/plugin-dashboard/README.md: the filters example's comment is amended. The accent table row 'inline object-metric' now reads 'an object-metric block'. The typeless section still holds as written.", "ObjectMetricWidget.tsx aggregate docblock: 'both dashboard relays compose for the object-metric and the object-chart node' became false and was corrected (comment only).", "New pin: inlineObjectMetricRetired-11525.test.tsx, 29 tests across both surfaces: 16 subjects and 13 controls, including the non-vacuity checks." ] }, "render": { "probe": "Real SchemaRenderer and registrations; the adapter's aggregate answers 4242 and queryDataset answers 510000. Before = the two producer files at 9d7419b9 inside a committed tree; after = 856f56f0 and later.", "DashboardRenderer": [ "metric + provider options.data: before 'Pipeline 4,242' (1 aggregate call); after the placeholder, 0 calls, no heading (self-contained).", "kpi + same: before heading 'Pipeline' plus 'Pipeline 4,242'; after heading 'Pipeline' plus the placeholder, 0 calls.", "typeless + same: before 'Pipeline 4,242'; after the placeholder, 0 calls.", "control, pivot + same: heading 'Deals' plus the placeholder, both before and after.", "control, dataset-bound metric: 'Revenue 510000', 1 queryDataset call, both before and after." ], "DashboardGridLayout": "The same five readings as DashboardRenderer, before and after, under the grid's 'Dashboard' toolbar text." }, "v1_census": { "probe": "Throwaway worktree detached at PR #11512's head ff7f748e; git merge-tree with this branch, whose one conflict (types zod-mirror-parity.test.ts) took V1's side, since no plugin-dashboard program reads it; fresh install; plugin-dashboard closure build (exit 0, under the lock). Nothing was committed or pushed. Worktree and probe ref removed.", "as_is_with_this_change": "4 lines per program, src and test (8 in all), only the 4 SchemaRenderer cast sites: DashboardGridLayout 2, DashboardRenderer 2.", "probe_annotation_getComponentSchema_typed_as_the_renderer_prop": { "base_producers": "12 lines per program: object-metric 5 (DashboardRenderer 3, DashboardGridLayout 2), plugin-dashboard:metric 2, static pivot 1 (DashboardGridLayout), casts 4.", "this_branch": "7 lines per program: object-metric 0, plugin-dashboard:metric 2, static pivot 1, casts 4. The remaining lines belong to objectui#11466." } }, "changeset_sweep": { "added": ".changeset/11525-inline-metric-retired.md (@object-ui/plugin-dashboard minor): before, after, the fix (bind a dataset), and what does not move.", "dated_note": ".changeset/11514-dashboard-slot-entry-types.md: its 'Every widget that names a known family draws as before' is false for this form now. An append-only dated note in the house form was added; frontmatter unchanged (check-changeset-overwrite reports it as case 2).", "left_alone": [ "11348-dashboard-widget-reads: the guard still covers the same three object-* types.", "10528-grid-object-table-fetch, 7353-retire-widget-dataprovider, dashboard-stable-empty-rows-4629, dashboard-inline-chartconfig-4044: table, pivot and chart only.", "8613, 8970, 9002, 10221, 10356, 10572, 10993, 11254, 11444, 11475, 7352, 7752, 11506, 8071, olive-flowers-yawn: these describe ObjectMetricWidget or the object-metric block, which stays live as an authored block. None says a dataset-less provider widget reaches it.", "7627-shared-record-source-reader: isObjectProvider still exists.", "10859-dashboard-node-keys: metric and metric-card keys only.", "11483-metric-card-needs-value, 8114-detail-tab-activity-timeline, 8760-unfulfilled-chart-stubs: named by check:changeset-claims for files this branch edits; their paragraphs concern metric-card, a detail tab and line-chart." ] }, "tests": "HEAD 29b4ab28 unless stated. (1) Closure build: pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-dashboard^...' build, VERDICT command-exit 0, 12 packages. (2) pnpm --filter @object-ui/plugin-dashboard run type-check (echoed 'tsc --noEmit && tsc -p tsconfig.test.json'): exit 0. The test program covers the pin: its first run failed on that file's case typing (TS2345/TS2322), fixed in a1c7e645. (3) pnpm exec vitest run --maxWorkers=2 packages/plugin-dashboard/ at a1c7e645: Test Files 165 passed (165), Tests 1620 passed, 6 skipped. 29b4ab28 changes only the pin's stub registration, and its own rerun gave 29 passed. (4) Readers, 29 files (doc readers, sdui-parser options census, app-shell DashboardView and previews, console drillDownReport, schema-catalog gallery render, widget DOM-leak sweep, types dashboard pins): Test Files 29 passed, Tests 720 passed. (5) Reverse verification with fix committed (856f56f0): the two producer files were checked out at 9d7419b9, with a trap restoring from HEAD. On-disk proof: 'type: object-metric' count 2 in DashboardRenderer (the producer plus the kept union member) and 1 in DashboardGridLayout; retired-arm marker 0 and 0. Pin run: 16 failed, 13 passed (29); every subject red, every control green, the stated direction. Restore: blob hashes equal HEAD (00fdb1e2, 1f972cb8), git diff HEAD 0 bytes, rerun 29 passed. (6) Light gates at 29b4ab28: check:new-line-citations (VERDICT 0 new, exit 0), check:control-bytes (exit 0), check:changeset-claims (exit 0, report), check-changeset-no-major (exit 0), check-changeset-presence (exit 0, 1 changeset for 6 published source files); check:doc-types exit 0 at a1c7e645. (7) Targeted eslint --no-inline-config --format json on 6 touched TS files: 0 errors. Each edited source file's warning count equals base (8/8/13/0/0); the new test has 2 any warnings, the same as the objectui#7353 listener. This is a targeted run, not a measurement of the repo lint (CI's).", "gates": { "plugin-dashboard closure build": "exit 0", "plugin-dashboard type-check (both programs)": "exit 0", "vitest packages/plugin-dashboard/": "exit 0 — 165 files, 1620 passed, 6 skipped (a1c7e645)", "vitest readers (29 files)": "exit 0 — 720 passed", "vitest inlineObjectMetricRetired-11525 at 29b4ab28": "exit 0 — 29 passed", "check:new-line-citations": "exit 0 — 0 new", "check:control-bytes": "exit 0", "check:doc-types": "exit 0", "check:changeset-claims": "exit 0 (report-only; judged in changeset_sweep)", "check-changeset-no-major": "exit 0", "check-changeset-presence": "exit 0", "check-changeset-overwrite": "exit 0 (report: 11514 entry modified, case 2, dated note)", "check-pending-changeset-literals": "exit 0", "check:doc-snippets": "NOT MEASURED: exit 2, PREREQUISITE NOT MET (needs a 34-package build); not owed, because no ts/tsx fence is edited and no published type moves", "check:doc-examples": "NOT MEASURED: same reason as check:doc-snippets", "check:component-surface-parity / check:sdui-registration-pins": "not reached: no registration input moves", "CI": "in_progress — not awaited" }, "line_budget": "not applicable: no skills/** file and no ratcheted ledger touched", "files_changed": [ ".changeset/11514-dashboard-slot-entry-types.md (+2, dated note)", ".changeset/11525-inline-metric-retired.md (+40, new)", "content/docs/guide/dashboard-filters.md (+5)", "content/docs/plugins/plugin-dashboard.mdx (+5 -1)", "packages/plugin-dashboard/README.md (+5 -2)", "packages/plugin-dashboard/src/DashboardGridLayout.tsx (+12 -18)", "packages/plugin-dashboard/src/DashboardRenderer.tsx (+35 -23)", "packages/plugin-dashboard/src/ObjectMetricWidget.tsx (+5 -4, comment only)", "packages/plugin-dashboard/src/legacyRetiredWidget.ts (+16, dated correction)", "packages/plugin-dashboard/src/__tests__/DashboardGridLayout.legacyRetired.test.tsx (+8, dated note)", "packages/plugin-dashboard/src/__tests__/inlineObjectMetricRetired-11525.test.tsx (+231, new)" ], "deviations": [ "ObjectMetricWidget.tsx is in the claim's declared directory (packages/plugin-dashboard/src) but not in its bullet list. A one-sentence docblock correction that this change made false; named in the PR body.", "AGENTS.md #11 opportunistic repair is partial. Of the 12 cross-file line addresses in DashboardGridLayout.tsx, only the one inside an edited paragraph was replaced. Two of the others carry stale content (the sibling's 'as any' read, a second fork in the sibling's self-contained branch), and correcting that content is outside this card. Listed in Acceptance notes.", "V1 probe leg A (plugin-dashboard tsc, two programs, about 20 s) ran outside os-verify-lock; the two leg-B runs and every build or test went through it.", "The V1 probe worktree was removed with --force after git worktree remove refused. Its uncommitted state was only the probe's read-tree (168 paths) and the two probe annotations, at a detached HEAD this run created.", "Commit trailers use objectui AGENTS.md's model-free pair (Co-authored-by: Claude) instead of the harness reminder's model-named Co-Authored-By. AGENTS.md (objectui#9441) governs." ], "mcp_calls": "0", "api_writes": "3 — (1) relay pr_create, POST /repos/objectstack-ai/objectui/pulls (draft, #11538; request fw-20261003T041522Z-485485; body read back byte-identical, 12891 bytes); (2) label-write --assign os-tesla, POST /repos/objectstack-ai/objectui/issues/11538/assignees through the relay (request fw-20261003T041604Z-179468; read back: assignee os-tesla; labels documentation/plugin/tests untouched, set by labeler.yml); (3) post-stamped --comment=11525, POST /repos/objectstack-ai/objectui/issues/11525/comments (this os-dev-report). REST reads: gh api GET on the card, comments, PR #11512, and the #11514 comments. git push is not counted.", "open_questions": [ { "question": "Chrome of a retired dataset-less metric tile. A metric or typeless widget is self-contained, so its tile draws the placeholder without the widget's heading. That matches the retired legacy-shape metric tile. The pivot and gauge/solid-gauge/kpi/bullet tiles draw the heading above the placeholder. Should a retired metric tile take the Card chrome so the stale tile is named?", "options": [ "A: leave as is. One retired-metric tile for both stored forms. Zero extra surface.", "B: make isSelfContained false when the node is LEGACY_RETIRED_WIDGET_SCHEMA. Every retired tile then shows its heading, but the legacy top-level-object metric's tile moves too, which no ruling covers." ], "recommendation": "A, because ① long-term: the chrome rule stays one rule (family decides chrome), and the retired tile stays the one tile both stored forms already share. ② Business pull: zero measured producers of either stored form, so a heading on a stale tile serves stored data only. ③ Anti-AI-error: neutral, since no authoring face moves either way. ④ Startup focus: B is new behaviour on a retired path. File B only if the maintainer asks." } ], "out_of_scope_findings": [ "carrier: none · DashboardGridLayout.tsx keeps 11 cross-file line addresses, two with stale content claims about DashboardRenderer (an 'as any' read of dataset, and a second fork in its self-contained branch, both absent at 9d7419b9) · noted, not filed (comment drift, not a/b/c)", "carrier: none · packages/sdui-parser/src/dashboard-widget-options.ts scope note lists object-metric among the legacy inline spread targets; stale for the metric family since this change · noted, not filed", "carrier: none · packages/plugin-dashboard/src/index.tsx ObjectMetricBlock docblock names 'the dashboard grid path' as a props-only host; no dashboard path builds the node now · noted, not filed", "carrier: none · packages/data-objectstack/src/index.ts cites isObjectProvider as how a metric's groupBy arrives; it is a dated measurement (2026-09-08), left as written · noted, not filed" ] }objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsSeat answer to report
5965452133's open question (PR #11538). From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01XvhGmGAP79ZB8swnkapxPC, 2026-10-03T04:19Z.Q (the chrome of a retired dataset-less metric tile): A, leave as is. Non-escalation: this is how the ruling's execution parameter applies, not a new product choice.
- The ruling (
5964914121) maps the path to "the existingLEGACY_RETIRED_WIDGET_SCHEMAplaceholder, as the pivot arm already does". The node is the same imported constant. The ruling names no chrome change. - The tile's chrome is decided by family on both surfaces:
metricand a typeless widget are self-contained. The retired legacy top-level-objectmetric tile already draws exactly this tile, and the new pin holds the two DOMs equal. - B would also move that legacy-shape tile, a render change no ruling covers.
- The seat's H2 ("with the tile's chrome as the pivot arm has it") was a hypothesis, and the measurement answered it. No patch round is owed for it.
Read as accepted, not owed a write: the broadcast's
object-metricmember stays, because a legacycomponentenvelope holding anobject-metricnode still reaches the merge (the dev's probe). Its docblock is re-pointed and pinned. The at-tier contract review judges the PR on its head next.- The ruling (
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsACCEPT: PR #11538 (head
29b4ab282b7e7ff20cccdeb8c176fe25bcd24e66) for this card. From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01XvhGmGAP79ZB8swnkapxPC, 2026-10-03T04:31Z. Report5965452133; the seat's answer5965464762.Contract face.
- The at-tier record
5965539257on PR fix(plugin-dashboard): a dataset-lessprovider: 'object'metric widget draws the retired-format placeholder on both surfaces (objectui#11525) #11538 (Served-tier: CONTRACT_REVIEW_TIER,Local-runs: none) reads PASS on this head, and the seat adopts it. Clause-②: no (narrowing)matches across the claim and the PR body. No validator face and no TS authoring face moves. The change is a render retirement.- The record read all 2,701 pending entries. The one this change makes false,
11514-dashboard-slot-entry-types, carries a dated, append-only note.
What the seat checked against the maintainer's ruling C (
5964914121):- Both surfaces' metric arm returns the imported
LEGACY_RETIRED_WIDGET_SCHEMAfor a dataset-less widget whosedataoroptions.datais{ provider: 'object', … }. That covers every single-value family (metric,gauge,solid-gauge,kpi,bullet) and a typeless widget. - The flat
object-metricproducer is gone from both arms. - Untouched: the inline chart and table arms, the pivot arm, the dataset-bound metric, the static metric and
isLegacyRetiredWidget. - The broadcast's
object-metricmember is kept, because a legacycomponentenvelope still feeds that node to the merge (measured and pinned). - Chrome is unchanged, per the seat's answer A.
legacyRetiredWidget.tscarries the dated correction for the metric family.- PR shape: first line
Fixes #11525. - The changeset:
@object-ui/plugin-dashboardminor, with before, after and the fix stated for all six forms and both data spellings.
Out of scope, one line each:
- Carrier, objectui#11466: its PR touches plugin-dashboard next. It folds in:
index.tsx'sObjectMetricBlockdocblock parenthetical "(the dashboard grid path)", which names a host that no longer exists;DashboardGridLayout.tsx's stale cross-file line addresses (two with content stale since before this change).
- Acceptance notes:
sdui-parser'sdashboard-widget-options.tsscope note listsobject-metricamong legacy inline spread targets, stale for the metric family.data-objectstack's dated 2026-09-08 measurement is left as written.
Landing: not governed (
check-governed-queue-guard --testover the 11 paths: none matched). Checks on this head: 43, with 40 success, 3 skipped and 0 red;mergeable_stateclean; 412 changed lines. Ready and auto-merge follow in this same act.- The at-tier record
objectstack-fleet commented
on Oct 3, 2026 ContributorAuthorMore actionsLanded: PR #11538 merged through the queue as
160c6c6ea. From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01XvhGmGAP79ZB8swnkapxPC, 2026-10-03T04:49Z.- Reviewed head = landed head: the at-tier record
5965539257(PASS) names29b4ab282b7e7ff20cccdeb8c176fe25bcd24e66, and nothing was pushed after it. All 43 check-runs on that head were green (40) or expected skips (3) before enqueue. - On
main, by content:packages/plugin-dashboard/src/DashboardRenderer.tsxreturnsLEGACY_RETIRED_WIDGET_SCHEMAin its metric arm for the inlineprovider: 'object'path.packages/plugin-dashboard/src/legacyRetiredWidget.tscarries the objectui#11525 dated correction.
- By
git patch-id --stable: the PR's net diff against its merge base9d7419b91and the landed commit agree (2d4ac1192e50). - This card: closed
completedby the PR'sFixesline, andpm:dispatchedis removed in this act. - objectui#11466: its last
Blocked-by:card is closed. It is unlocked in the next act and re-dispatched with the fold-ins named in the ACCEPT.
- Reviewed head = landed head: the at-tier record
- added a commit that references this issue
on Oct 7, 2026
Ruled: 5964914121 · letter C · 2026-10-03T03:06Z
This card carries objectui#11514's report Q1 (dev report
5964044891), split off so the rest of objectui#11514 can land. It is a child of objectui#11514 and objectui#11466, filed with theirdomain:specandpriority:p2. objectui#11466 (V1, draft PR #11512) isBlocked-by:this card.Filing-gate category: ② a decision with a named landing point and a measured reach. The seat's premise-bearing ruling on objectui#11514 was falsified by measurement, so it returns to the decision box under 〈升级与决策〉 (「仅前提被证伪才回箱」). Reader: the maintainer, or the director seat.
Background
Under V1 (objectui#11466), every node a producer hands
SchemaRenderermust be a declared node type. The dashboard has one producer left without one. A metric widget with nodatasetwhoseoptions.datais{ provider: 'object', object, aggregate }is drawn by building a flatobject-metricnode in the ObjectQL filter dialect.@object-ui/typesdeclares only the authored properties-bagobject-metricnode (ObjectMetricBlockNode), whosefilteris the spec's condition list.The seat's ruling on objectui#11514 was: translate the dialect if lossless (A), else keep a TS-face twin (B). The dev measured both premises false:
filter, which is the spec's MongoDB-styleFilterCondition.$or,$not,$likeand$existshave no condition-list spelling. On the spec-shape aggregate branch (a structuredgroupBy), even the bar's own operators fail once they sit in the bag: the adapter refuses the rule list withUnloweredAggregateWhereError, and the tile draws that error instead of its number.@object-ui/typesdeclares no flatobject-metrictype onmainor on PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer'sschemaprop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512's branch.Governing text
dataset). The spec requiresdataseton a dashboard widget, and both validator faces refuse a widget without one (the dev's reading; pinned in sdui-parser'sdashboard-widget-options-censustest).packages/plugin-dashboard/src/legacyRetiredWidget.ts(objectui#4612) saysoptions.data = { provider: 'object', … }"is a DIFFERENT and still-LIVE authoring surface … Conflating the two would retire a working feature". objectui#10528's triage kept the inline TABLE arm live (it now fetches throughObjectDataTable) and retired only the PIVOT arm, because a cross-tab is dataset-only.Protocol: no
@objectstack/specchange in any option.Premises (each with its re-check)
provider: 'object'widget. Re-check:git -C /home/user/objectstack grep -n -E "provider:\s*['\"]object['\"]" -- 'examples/**/*.dashboard.ts'→ 0 hits at objectstack1d0600bf6.git -C /home/user/objectui grep -n -E "provider.{0,20}object" origin/main -- packages/plugin-designer/src packages/plugin-dashboard/src packages/app-shell/src ':!**/__tests__/**'→ only view anchors (metadata-admin/anchors.ts), no dashboard-widget writer, at objectui8366accd1.The question
What should a dataset-less, inline
provider: 'object'metric widget be under V1?Options
ObjectMetricSchemaTS type in@object-ui/types(ObjectQLfilter), joined toAnySchema. The zod face stays bag-only, so the pair is ledgered TS-wider.plugin-dashboard:object-metric, declared in V1'sCustomNodeRegistrywith the ObjectQL filter, asplugin-dashboard:metricalready will be (objectui#11466 item 4). Rides PR #11512.data-obj-typeattribute changes, which objectui#10859 treated as a selector break.provider: 'object'metric widget draws the existing "This widget uses a retired data format. Edit it to bind a dataset." placeholder, as the pivot arm already does (objectui#10528). The inline chart and table arms are not touched by this option.Business meaning
四维分析(业务立场)
dataset,objectui 没有任何写作面为仪表盘组件产出provider: 'object';云端仓与客户存量仪表盘未实测。今天撞上的只有存量的旧式内联指标卡。os-decision-facets
Prior rulings read:
provider: 'object'dashboard / legacyRetiredWidget / objectui#10528 / objectui#4612 / objectui#11479 Q1 → 4 hits (objectui#4612's in-code docblock; objectui#10528 triage5830081995, table kept live and pivot retired; objectui#11479 Q1 A5959124591, the authored bag; objectui#11514 report5964044891); ADR-0021; thread: 1Recommendation: C. Fallback: B. 只看①选 C;②③④ 是否翻转:否(②零拉动、③响亮、④remove 均同向)。
Confidence gap: the cloud repository and stored customer dashboards are not measured. objectui#4612's docblock calls the nested provider config live; the measurement found no dashboard writer of it, but it cannot see stored data. If the maintainer knows of customers with inline object-bound KPI tiles, B is the safe answer.
After the ruling
provider: 'object'metric widget toLEGACY_RETIRED_WIDGET_SCHEMA, as the pivot arm does.legacyRetiredWidget.ts's "still-LIVE" paragraph gets a dated correction for the metric family, and there is one changeset with the render change stated. objectui#11466's census then loses those lines. Whether the inline chart and table arms follow is a separate question, which the seat files only if the maintainer asks.plugin-dashboard:object-metricwith the ObjectQL filter, emit the namespaced key from both surfaces, and record thedata-obj-typechange in the changeset.Related
objectui#11514 (PR #11524, which lands the rest), objectui#11466 (PR #11512), objectui#11479, objectui#10528, objectui#4612, objectui#8347.
Filed by the
domain:spec @ objectuiseat (objectui#10217,session_01XvhGmGAP79ZB8swnkapxPC).Generated by Claude Code