Repository navigation
finding(plugin-dashboard): dataProvider is declared on two widget schema types and written by two producers, and no renderer reads it #7353
Description
Activity
- addeddomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Sep 5, 2026 分诊 —
domain:ui/priority:p3/pm:queue/finding锚定 (anchoring):三个写入点全在
packages/plugin-dashboard,一处声明也在那里 ⇒domain:ui。⚠️ 另一处声明ObjectDataTableSchema.dataProvider在packages/types/src/objectql.ts(domain:spec)—— 若裁决是"移除",收尾时需要一次domain:spec的交接,PR 里注明即可,不必拆卡。在
origin/maina472b07上复核 —— 写入点与零读取都成立packages/plugin-dashboard/src/DashboardGridLayout.tsx:308 dataProvider: widgetData, packages/plugin-dashboard/src/DashboardGridLayout.tsx:347 dataProvider: widgetData, packages/plugin-dashboard/src/DashboardRenderer.tsx:737 dataProvider: widgetData, packages/plugin-dashboard/src/ObjectPivotTable.tsx:44 dataProvider?: { provider: string; object?: string };三写一声明,行号与卡片一字不差。在
packages/plugin-dashboard里没有任何读取点 —— 与卡片的普查一致。⚠️ 给复核这张卡的人:这个名字有两个同名陷阱,我都踩了卡片的普查方法("one query over
packages/*/srcexcluding__tests__,every spelling of a read")是对的,但结果很容易被两类假阳性推翻,所以把它们记下来,免得下一个人误以为卡片错了:陷阱一 —— 子串。 朴素
git grep dataProvider会大量命中MetadataProvider(app-shell里几十处)。这是 objectui#6973 记过的那类子串假阳性,必须用词边界(git grep -E "(^|[^A-Za-z])dataProvider")。陷阱二 —— 同名局部变量。 即使加了词边界,仍会命中一批与本键无关的东西:
packages/plugin-calendar/src/ObjectCalendar.tsx:292 const dataProvider = dataConfig?.provider; packages/plugin-gantt/src/ObjectGantt.tsx (同形) packages/plugin-map/src/ObjectMap.tsx (同形) packages/plugin-tree/src/ObjectTree.tsx (同形)那是四个渲染器各自的局部变量,从
dataConfig.provider取值,与schema.dataProvider这个键毫无关系。⛔ 不要把它们当成"这个键其实到处在用"的证据 —— 那正是这张卡最容易被错误关闭的方式。排除这两类之后,读取点确实为 0。
定级理由
priority:p3:- 卡片自己划定的伤害就是 declared-but-unread 的标准形状:作者(或写元数据的 AI)把声明读成可授权输入、写下去、什么也不发生。真实但温和。
- 没有静默错答(不会算出错的数),没有数据损坏。
- 卡片诚实标注了一处未测:spread 之后这个对象会不会作为 DOM 属性泄漏(
MetricWidget/MetricCardspread...propsonto the DOM, emitting aschema="[object Object]"attribute on every KPI card #4357 那一类)。⚠️ 这一点没测,所以定级里不计入它 —— 若测出来真泄漏,本卡应重评为 p2。
定型:ADR-0049 enforce-or-remove —— 两个方向的型不同
方向 型 manual floor 移除(两处声明 + 三处写入一起删) 收窄,恢复 declared = enforced ⇒ Bug/tidy 不踩 接上(让某个渲染器真的消费它) 新增被消费的授权语义 ⇒ Feature 踩 ⛔ 本席不裁决方向。但把一条对判断有用的证据留下:卡片指出生产者已经在它旁边写
objectName: widgetData.object,而那才是 widget 真正读的键。也就是说dataProvider不是"还没接上的新能力",是"同一份信息的第二种拼写,且第二种没人读"。这让"移除"成为默认方向 —— 而移除不需要人工底线,"接上"需要。⛔ 给执行席的边界
- 动手前先把那处未测补上:spread 之后
dataProvider会不会落到 DOM 元素上(MetricWidget/MetricCardspread...propsonto the DOM, emitting aschema="[object Object]"attribute on every KPI card #4357 类)。这既影响定级,也影响移除的验收(若它今天在泄漏,移除顺带修了一个真缺陷,值得在 PR 里说)。 - 若移除,四处一起(
objectql.ts的声明、ObjectPivotTable.tsx:44的声明、三处写入),⛔ 不要只删声明留下写入 —— 那会让一个无人声明的键继续被写进节点。 ObjectDataTable会把节点 spread 进它渲染的data-table,所以移除后跑一次 dashboard 的渲染测试确认没有别的东西在靠这个 spread 过日子。- ⛔ 不要顺手清理
packages/plugin-*/src/Object*.tsx里那四个同名局部变量 —— 见上,它们无关。
⛔ 分诊席不认领、不派单、不写码、不裁定 enforce/remove。
Generated by Claude Code
objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsRuling: UI closure batch 1 item 10 · letter remove (ADR-0049 enforce-or-remove, remove arm) · maintainer 「同意」 2026-09-24T06:32Z
Director seat, summon #29 (
session_01EcrTi7s5oDYPHS4Pi7h31d). Presented in chat from the business angle; the maintainer answered 「同意」. Thread re-read to its last comment (5548497098) in this act.Ruled: remove, all at once. Readings on objectui
origin/main62597c5:- Writes:
packages/plugin-dashboard/src/DashboardGridLayout.tsx:386and:425, andDashboardRenderer.tsx:787, eachdataProvider: widgetData. - Declarations:
ObjectPivotTable.tsx:44;ObjectDataTableSchema.dataProvideratpackages/types/src/objectql.ts:4546; and its zod mirror atpackages/types/src/zod/objectql.zod.ts:2462. - Readers: none. The widgets read the
objectNamewritten beside it.
Delete the three writes and every declaration in one change. ⛔ No reader is added to keep the key alive.
ObjectPivotTableis exported frompackages/plugin-dashboard/src/index.tsx:29, so the removal narrows a published prop type; the changeset follows objectui AGENTS.md §9. Thepackages/typeshalf rides the same PR with the spec-lane hand-off named in the PR body (triage's note, 5548497098), ⛔ not a split card. The dev first measures the one gap the card left open: whether the spread value reaches a DOM attribute today (objectui#4357 class). If it does, say so in the PR; the removal ends it either way.Execution:
pm:queue·priority:p3·domain:uistand.
Generated by Claude Code
- Writes:
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsClaim: PM loop round 4 —
domain:uiexecution seat 2
Session:session_014mXUNuFomfj24w7s1pZzhN
Branch:claude/issue-7353-retire-widget-dataprovider
Worktree:objectui-issue-7353
Domain:domain:ui
Seat:domain:ui#2
File surface: the threedataProvider: widgetDatawrites inpackages/plugin-dashboard/src/DashboardGridLayout.tsxandDashboardRenderer.tsx; the declarations inpackages/plugin-dashboard/src/ObjectPivotTable.tsx(theschema.dataProvidermember),packages/types/src/objectql.ts(ObjectDataTableSchema.dataProvideronly) and its zod mirror inpackages/types/src/zod/objectql.zod.ts(theObjectDataTableSchemaregion only); tests beside them; one.changeset/7353-…md(stop on breach; explain in the report)
Container & model:S,mode:subagent,model: opus—dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; executes ruling5809008870(remove)
Clause-②: yes
Thread-read: 5809008870
Serial constraints cleared: open-PR file lists read 2026-09-25T05:42Z. Draft PR objectui#8941 (lucide bump) editspackages/types/src/objectql.tselsewhere, far fromObjectDataTableSchema, and is hunk-disjoint. No open PR touchesplugin-dashboard/src/orobjectql.zod.ts. Inobjectql.zod.ts, this seat's objectui#5157 is stopped atneeds_decisionwith no code and holds only theObjectMapConfigSchemaregion, which is region-disjoint; whichever lands later merges. Livepm:dispatchedclaims of seats 1, 3 and 4 name none of these files.Clause-②: yes— the ruling removes a declared member from a published prop type (ObjectPivotTableis exported from@object-ui/plugin-dashboard) and fromObjectDataTableSchemaon both faces.
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsos-dev-report
{ "issue": 7353, "status": "done", "branch": "claude/issue-7353-retire-widget-dataprovider", "pr": "https://github.com/objectstack-ai/objectui/pull/10522", "session": "session_014mXUNuFomfj24w7s1pZzhN", "premise_still_valid": true, "summary": "Carried out ruling 5809008870 (remove, all at once): deleted the three dataProvider: widgetData writes (DashboardRenderer object-data-table arm; DashboardGridLayout data-table and pivot arms) and every declaration (ObjectDataTableSchema.dataProvider on the TS interface and zod mirror in @object-ui/types; schema.dataProvider on ObjectPivotTableProps in @object-ui/plugin-dashboard). No reader added; one changeset declares both packages minor with the narrowing stated. H1 held exactly at base 660d31185 (the six sites the order named, zero readers). H2 measured with a real render: the key never reached a DOM attribute, so no objectui#4357-class leak existed. H3 measured: the mirror extends a passthrough BaseSchema, so an authored dataProvider now parses green and is kept unchecked; a malformed one that used to fail at dataProvider.provider now passes. Authored dataProvider does not start failing validation. No tombstone was added, per the ruling's wording. The card assignee (os-elon-musk) was present at start; I did not write it.", "tests": "BASE 660d31185 (new pin run against the unmodified tree): `pnpm exec vitest run packages/plugin-dashboard/src/__tests__/widgetDataProviderRetired-7353.test.tsx` gave `Tests 3 failed | 4 passed`, each failure `AssertionError: expected [ 'type', 'objectName', …(6) ] to not include 'dataProvider'` (renderer table, grid table, grid pivot). HEAD 35624634f: vitest over packages/plugin-dashboard/ packages/types/ plus the two out-of-package importers of ObjectDataTableSchema gave `Test Files 363 passed (363)`, `Tests 6439 passed (6439)`, lock VERDICT command-exit 0. `pnpm --filter @object-ui/types --filter @object-ui/plugin-dashboard run type-check` ran both full chains including tsc -p tsconfig.test.json (both new pins confirmed program inputs via tsc --listFilesOnly), lock VERDICT command-exit 0, after building the 13-package plugin-dashboard dependency closure. REVERSE VERIFICATION at 35624634f (trap-guarded script, committed state): git checkout 660d31185 on the five source files, then on-disk dataProvider hits 2/1/2/1/1 and a rebuild of @object-ui/types (dist/objectql.d.ts hits 1). Results: vitest `Tests 5 failed | 11 passed` (zod shape leg `expected [ Array(29) ] to not include 'dataProvider'`, passthrough leg `expected false to be true`, three node cases; controls and the union-arms file green); types type-check exit 2 with TS2322 on the TS-face probe line; plugin-dashboard type-check exit 2 with TS2322 on the pivot probe line and on the ObjectDataTableProps probe line (proof that the rebuilt .d.ts was read). RESTORE: git checkout HEAD on absolute paths, all 5 files hash-equal to their HEAD blobs, git diff HEAD 0 bytes, status clean, types rebuilt (dist hits 0). H2 probe (one-off, not committed) on base: renderer-table 68 elements / 0 dataprovider attributes / 0 React warnings; grid-table 31/0/0; grid-pivot 23/0/0; positive control (div with the object spread) found attribute dataprovider plus 1 React warning.", "mcp_calls": "0", "api_writes": "3, each one repository_dispatch through the fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, 204) that objectstack-fleet[bot] executed: (1) pr_create, POST /repos/objectstack-ai/objectui/pulls (draft, gave #10522, body read back byte-identical, 11951 chars); (2) label-write --assign os-elon-musk, POST /repos/objectstack-ai/objectui/issues/10522/assignees (read back MATCHES; zero label writes, and the labels present come from labeler.yml); (3) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/7353/comments via post-stamped. Also 3 git pushes (not REST).", "open_questions": [ { "question": "The PR body's `Clause-②: yes` line is copied verbatim from the claim. The measured shape fits `yes (narrowing)`: the declarations narrow on both packages, while the zod accept set widens for a malformed dataProvider. Should the seat add the arm?", "options": [ "A: seat edits the PR body line to `Clause-②: yes (narrowing)`", "B: keep `Clause-②: yes` as claimed" ], "recommendation": "A, because the diff narrows a published prop type and interface (a breaking change stated in the changeset). The arm exists to make that visible to readers that do not parse prose. The dev writes the PR body only once, so the seat makes this edit." } ], "out_of_scope_findings": [ "class: a · DashboardGridLayout's provider:'object' table and pivot widgets never fetch. getComponentSchema emits `data-table` / `pivot` nodes with `data: []` and objectName, and neither DataTableRenderer nor PivotTable reads objectName. The H2 probe on base 660d31185 measured adapter.find called 0 times and the row text absent for both, while DashboardRenderer fetched and rendered the same provider widget. DashboardRenderer's pivot-arm comment calls these grid branches live. Reachable through the registered `dashboard-grid` node. · dedupe words: DashboardGridLayout provider object table empty; dashboard-grid pivot never fetches; grid layout data-table objectName data empty; object provider widget blank editable grid", "carrier: none · the PR's Acceptance notes also record that no tombstone was added for dataProvider, per the ruling's wording (noted, not filed)" ], "files_changed": [ "packages/plugin-dashboard/src/DashboardRenderer.tsx (one write removed)", "packages/plugin-dashboard/src/DashboardGridLayout.tsx (two writes removed)", "packages/plugin-dashboard/src/ObjectPivotTable.tsx (declaration removed; the comment that counted it updated)", "packages/types/src/objectql.ts (ObjectDataTableSchema.dataProvider only; objectui#8941's hunk untouched)", "packages/types/src/zod/objectql.zod.ts (ObjectDataTableSchema region only)", "packages/types/src/__tests__/objectql-union-arms-7363.test.ts (fixture triage: dataProvider dropped from the 'with its keys' fixture; the dataProvider.provider rejection row removed with the declaration it pinned)", "packages/plugin-dashboard/src/__tests__/widgetDataProviderRetired-7353.test.tsx (new pin)", "packages/types/src/__tests__/object-data-table-dataprovider-retired-7353.test.ts (new pin)", ".changeset/7353-retire-widget-dataprovider.md (plugin-dashboard minor, types minor)" ], "gates": [ "All gates ran at head 35624634f and exited 0.", "Tests: vitest (both packages + 2 importers) `Test Files 363 passed (363)` / `Tests 6439 passed (6439)`; type-check types + plugin-dashboard `VERDICT command-exit 0`.", "Changeset gates: check-changeset-presence `8 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)`; check-changeset-no-major `No changeset declares a major bump`; check-changeset-overwrite `No pre-existing changeset was modified or deleted`; check-changeset-fixed OK; check:pending-changeset-literals OK; check:changeset-claims report-only (28 pending changesets listed, none claims dataProvider).", "Citation and byte gates: check:new-line-citations `VERDICT new-cross-file-line-citations: 0 new citation(s)`; check:control-bytes OK.", "Mock and test-root gates: check-vi-mock-specifiers, check-vi-mock-inherit, check-vi-mock-override-shape and check-test-path-roots all OK.", "Types-surface and doc gates, all OK: check:spec-symbols, check:designer-field-key-parity, check:handler-key-reads, check:element-data-source-declaration, check:unreferenced-sources, check:doc-types, check:doc-example-readers, check:prompt-keys, check:action-forward-parity, check:metadata-write-doors, check-type-check-coverage (43/43), check-lint-coverage (46/46). check:component-surface-parity is report-only and has no dataProvider row.", "Lint, proven narrowing: eslint --no-inline-config --format json over the 8 touched TS files gave 8 entries, 0 errors, 63 warnings. The population comes from eslint --print-config (all 8 in config). The config is not type-aware (no parserOptions.project or projectService in eslint.config.js), so the diff cannot move a verdict on an untouched file.", "NOT MEASURED: check:readme-exports, check:doc-examples, check-skill-examples. Reason: each needs the whole package set built and refused with a collapsed population or missing dist. The diff touches no README or doc, and no tracked file outside the diff names dataProvider.", "NOT MEASURED: check:sdui-registration-pins. Reason: needs a console build; the diff changes no registration.", "Governed surface: check-governed-queue-guard --test gave NOT GOVERNED (9 paths).", "CI: not awaited, per the order." ], "deviations": [ "The first lock acquisition returned queue-timeout exit 99 (holder: another seat's full app-shell vitest run). The run was retried with the same slot and measured; it is not reported as a failure.", "The first pre-edit grep used pathspec `packages/*/src` and returned 1 hit, a zero-match artefact of git pathspec semantics. The control word MetadataProvider exposed it. I re-ran the grep over the whole tracked tree, and every reading above comes from that run.", "The H2 DOM probe was a one-off test file, run on base and deleted uncommitted; readings are in the PR body.", "Attribution follows the role file, not the harness reminder: commits carry the model-free trailer pair, and the PR body ends with the session-URL footer." ], "cleanup": "Remote head equals local head 35624634f. node_modules removed; git worktree remove /home/user/objectui-issue-7353 exit 0 (no --force). No background process or server started." }
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actionsos-dev-report
{ "issue": 7353, "status": "done", "branch": "claude/issue-7353-retire-widget-dataprovider", "pr": "https://github.com/objectstack-ai/objectui/pull/10522", "head": "511316a02ac151a8ca90dabcaf1e4f180afeac7b", "session": "session_014mXUNuFomfj24w7s1pZzhN", "premise_still_valid": true, "summary": "Rework round for contract review 5828182277 (FAIL at 35624634f). Both items are done on commit 511316a02. (1) Tombstones replace the typed declarations: `dataProvider?: never` with a retirement JSDoc (objectui#7353, ruling 5809008870, write objectName) on ObjectDataTableSchema and on ObjectPivotTableProps['schema'], plus `retirementTombstone(...)` on the zod mirror, whose message points at objectName. ObjectPivotTable has NO zod face: git grep finds no PivotTable or object-pivot schema in any zod module, and data-display.zod.ts states that PivotTableSchema has no mirror of its own. The control hit was ObjectDataTableSchema = BaseSchema.extend. The discriminator applies as the PM read it: both carriers survive and prong 1 (objectName) holds. The three writes stay deleted and no reader was added. (2) The changeset is rewritten against released 17.6.0. I measured this with npm pack: types 17.6.0 has 0 word-bounded dataProvider and 0 ObjectDataTableSchema (control DashboardSchema 4; an unbounded grep's single hit is the MetadataProvider substring). plugin-dashboard 17.6.0 dist declares dataProvider? in ObjectDataTable.d.ts and ObjectPivotTable.d.ts and carries 3 writes. The published narrowing is therefore stated as plugin-dashboard's (BREAKING, minor), and the types half says no released validator changes verdict. Clause-② stays `yes`. The PR body was NOT patched: see deviations. A full replacement body is in pr_body_replacement for the seat to apply.", "tests": "HEAD 511316a02: vitest over packages/plugin-dashboard/ packages/types/ plus the two out-of-package importers of ObjectDataTableSchema gave `Test Files 363 passed (363)`, `Tests 6442 passed (6442)`, lock VERDICT command-exit 0. `pnpm --filter @object-ui/types --filter @object-ui/plugin-dashboard run type-check` ran both full chains including tsc -p tsconfig.test.json, VERDICT command-exit 0, after a closure rebuild (12 build: Done; types dist carries 1 `dataProvider?: never`). REVERSE VERIFICATION at 511316a02 (trap-guarded; pins kept; five source files restored from an earlier tree; types rebuilt per leg). LEG A, 35624634f (bare deletion): on-disk tombstones 0, writes 0. vitest `Tests 3 failed | 16 passed (19)` (zod well-formed, malformed and safeValidateSchema cases: `expected true to be false`); types type-check exit 2 (TS2344 on the Equal tombstone line, TS2578 unused directive on both authoring lines); plugin-dashboard type-check exit 2 (TS2344 on both Equal lines, TS2578 on both authoring lines); controls and node pins green. LEG B, 660d31185 (original base): writes 3. vitest `Tests 6 failed | 13 passed (19)` (3 node pins; zod well-formed accepted; malformed refused at dataProvider.provider, not the key: `expected [] to have a length of 1`; safeValidateSchema case); types type-check exit 2 (TS2344 plus TS2578 on the well-formed line only, since the typed member already refused the malformed value); plugin-dashboard type-check exit 2 (4 errors); controls green. RESTORE after each leg and at exit: 5 files hash-equal to HEAD, git diff HEAD 0 bytes, status clean, types rebuilt (dist tombstone 1). Pins at head: 3 files, 19 tests green.", "mcp_calls": "0", "api_writes": "1 this round: this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/7353/comments via post-stamped over the fleet-write relay (one repository_dispatch to objectstack-ai/objectstack). No PR body PATCH, no label or assignee write this round. Plus 1 git push (35624634f..511316a02), not REST. Round 1 writes (pr_create, PR-assignee label-write, round-1 report) are unchanged. Reads this round: REST GET of the PR comments, the PR, and check-runs for 511316a02; npm pack of both 17.6.0 tarballs.", "open_questions": [], "out_of_scope_findings": [ "class: a · (carried from round 1, unchanged; the contract review confirmed it at source) DashboardGridLayout's provider:'object' table and pivot widgets never fetch. They emit `data-table` / `pivot` nodes with `data: []` and objectName, and neither renderer reads objectName. The H2 probe on base 660d31185 measured find called 0 times and the row text absent, while DashboardRenderer fetched the same widget. Reachable through the registered `dashboard-grid` node. · dedupe words: DashboardGridLayout provider object table empty; dashboard-grid pivot never fetches; grid layout data-table objectName data empty; object provider widget blank editable grid" ], "files_changed": [ "packages/types/src/objectql.ts (ObjectDataTableSchema: typed dataProvider replaced by a `dataProvider?: never` tombstone with retirement JSDoc; objectui#8941's hunk untouched)", "packages/types/src/zod/objectql.zod.ts (ObjectDataTableSchema region only: `dataProvider: retirementTombstone(...)` naming objectName, and one docblock bullet)", "packages/plugin-dashboard/src/ObjectPivotTable.tsx (`dataProvider?: never` tombstone with retirement JSDoc that states there is no zod face; the members comment updated)", "packages/plugin-dashboard/src/DashboardRenderer.tsx and DashboardGridLayout.tsx (the three writes stay deleted; unchanged this round)", "packages/plugin-dashboard/src/__tests__/widgetDataProviderRetired-7353.test.tsx (node pins unchanged; the declared-key probes are replaced by tombstone Equal pins and @ts-expect-error on both prop types, with an undeclared-key control)", "packages/types/src/__tests__/object-data-table-dataprovider-retired-7353.test.ts (rewritten: TS tombstone and @ts-expect-error for well-formed and malformed values; zod refuses both by name, including via safeValidateSchema; undeclared key accepted and kept; a plain node validates)", "packages/types/src/__tests__/objectql-union-arms-7363.test.ts (comments only, aligned with the tombstone)", ".changeset/7353-retire-widget-dataprovider.md (rewritten against released 17.6.0; plugin-dashboard BREAKING minor; types minor with no released verdict change)" ], "gates": [ "All gates ran at head 511316a02 and exited 0.", "Tests and type-check: see tests. Lint: eslint --no-inline-config --format json over the 8 touched TS files gave 8 entries, 0 errors, 63 warnings. All 8 are accepted by eslint --print-config, and the config is not type-aware (no parserOptions.project or projectService).", "Changeset gates: check-changeset-presence `8 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)`; check-changeset-no-major, check-changeset-overwrite, check-changeset-fixed and check:pending-changeset-literals OK; check:changeset-claims report-only.", "Citation and byte gates: check:new-line-citations `VERDICT new-cross-file-line-citations: 0 new citation(s)`; check:control-bytes OK.", "Mock and test-root gates: check-vi-mock-specifiers, check-vi-mock-inherit, check-vi-mock-override-shape and check-test-path-roots OK.", "Types-surface and doc gates: check:spec-symbols, check:designer-field-key-parity, check:handler-key-reads, check:element-data-source-declaration, check:unreferenced-sources, check:doc-types, check:doc-example-readers, check:prompt-keys, check:action-forward-parity, check:metadata-write-doors, check-type-check-coverage (43/43) and check-lint-coverage (46/46) OK. check:component-surface-parity is report-only, with read-of-tombstoned-key 0.", "NOT MEASURED: check:readme-exports, check:doc-examples, check-skill-examples. Reason: each needs the whole package set built. The diff touches no README or doc. CI ran them.", "NOT MEASURED: check:sdui-registration-pins. Reason: needs a console build; the diff changes no registration.", "CI started on the new head: GET check-runs for 511316a02 returned total_count 43, all completed (40 success, 3 skipped, 0 non-green). PR #10522 head is 511316a02, draft, assignee os-elon-musk." ], "deviations": [ "CONFLICT, flagged and not silently resolved: the coordinator asked me to update the PR body, but the role file says the dev writes the PR body once, at pr_create, never PATCHes it, and hands any later edit to the seat. The role file also says it wins on conflict. objectui AGENTS.md records that a PATCH downgrades the session-URL footer. So I made no PR body write. The full replacement body is in pr_body_replacement. It rewrites the H3 section, removes the 'a named refusal is a declaration' inference, restates the released column against 17.6.0, and updates the pins, reverse verification, gates and CI to 511316a02. Apply it verbatim.", "The worktree had been removed after round 1, so I recreated it with `git worktree add` on the existing branch at 35624634f (remote head matched). I rebuilt the dependency closure and removed the worktree again at the end (git worktree remove exit 0, no --force).", "Two lock acquisitions returned queue-timeout exit 99 while other seats held the lock. Both were retried with the same slot and measured; neither is reported as a failure.", "My first npm-tarball grep was unbounded and read 1 types file naming dataProvider; the hit was the MetadataProvider substring. The word-bounded re-read gave 0, and that is the reading used." ], "cleanup": "Remote head equals local head 511316a02. node_modules removed and git worktree remove /home/user/objectui-issue-7353 exit 0 (no --force). No background process or server left running.", "pr_body_replacement": "Fixes #7353\n\nClause-②: yes — the ruling removes a declared member from a published prop type (`ObjectPivotTable` is exported from `@object-ui/plugin-dashboard`) and from `ObjectDataTableSchema` on both faces.\n\nThis carries out ruling 5809008870 (ADR-0049 enforce-or-remove, remove arm):\n\n- The three `dataProvider: widgetData` writes are deleted.\n- The two typed declarations are replaced by **retirement tombstones**, which refuse the key and point at `objectName`.\n- No reader is added.\n\nRound 2 applies contract review 5828182277 (FAIL at `35624634f`). That review found that the bare deletion left an authored `dataProvider` absorbed silently. It also found that the changeset described an unreleased `@object-ui/types` member as if it were published.\n\n## What changed\n\n| Site | Released 17.6.0 | This PR |\n|---|---|---|\n| `DashboardRenderer`, table arm (`object-data-table` node) | writes `objectName` and `dataProvider` | writes `objectName` only |\n| `DashboardGridLayout`, table arm (`data-table` node) | writes `objectName` and `dataProvider` | writes `objectName` only |\n| `DashboardGridLayout`, pivot arm (`pivot` node) | writes `objectName` and `dataProvider` | writes `objectName` only |\n| `ObjectPivotTableProps['schema']` (prop type of the exported `ObjectPivotTable`) | `dataProvider?: { provider: string; object?: string }` | `dataProvider?: never`, a tombstone. There is no zod face: neither `object-pivot` nor `PivotTableSchema` has a mirror. |\n| `ObjectDataTableSchema`, TS interface (`@object-ui/types`) | not released (enters with objectui#6576, changeset still pending) | `dataProvider?: never`, a tombstone |\n| `ObjectDataTableSchema`, zod mirror (`@object-ui/types/zod`) | not released | `dataProvider: retirementTombstone(...)`, which refuses the key by name. Its message says to write `objectName`. |\n\nI measured the released column with `npm pack` of `@object-ui/types@17.6.0` and `@object-ui/plugin-dashboard@17.6.0` (both are `latest`), using a word-bounded grep:\n\n- **types 17.6.0**: 0 files name `dataProvider` and 0 name `ObjectDataTableSchema`. The control, `DashboardSchema`, is found in 4 files. An unbounded grep also finds one `CHANGELOG.md` line, but that is the `MetadataProvider` substring trap.\n- **plugin-dashboard 17.6.0**: `dist/ObjectDataTable.d.ts` and `dist/ObjectPivotTable.d.ts` both declare `dataProvider?`, and `dist/index.js` carries 3 `dataProvider: ` writes.\n\nThe changeset is `.changeset/7353-retire-widget-dataprovider.md`. It declares `@object-ui/plugin-dashboard` minor with a BREAKING body, and `@object-ui/types` minor, per AGENTS.md §9. It is written against released 17.6.0: the published narrowing is plugin-dashboard's, and no released `@object-ui/types` validator changes verdict.\n\n**Pre-edit re-grep (H1).** I ran a word-bounded `dataProvider` grep over every tracked file at base `660d31185`. It left out the `const dataProvider = ...provider` locals in calendar, gantt, map, tree and core's `record-source` test, which triage ruled unrelated, and the `apps/console` comment about them. It found:\n\n- the three writes and the three declarations at the sites the dispatch named;\n- one comment in `ObjectPivotTable`;\n- two fixtures in `objectql-union-arms-7363.test.ts`.\n\nIt found no reader, no doc and no README that uses the key. `@objectstack/spec` declares neither `object-data-table` nor `dataProvider`.\n\n## objectui#4357 question (H2): the key never reached a DOM attribute\n\nA one-off probe, not committed, rendered all three producer paths for real on base `660d31185`. It listed every attribute on every element and spied on `console.error`:\n\n| Render | Elements | `dataprovider` / `data-provider` attributes | React unknown-prop warnings naming it |\n|---|---|---|---|\n| renderer, table | 68 | 0 | 0 |\n| grid, table | 31 | 0 | 0 |\n| grid, pivot | 23 | 0 | 0 |\n| positive control: a div with the same object spread onto it | 2 | 1 (`dataprovider`) | 1 |\n\nThis change does not close any objectui#4357-class leak.\n\n## What the zod mirror does with an authored `dataProvider` (H3)\n\n- **Bare deletion, measured at `35624634f` (round 1).** `ObjectDataTableSchema` extends the `.passthrough()` `BaseSchema`, so an authored `dataProvider` was kept on the parsed value and checked by nothing, whether well-formed or malformed. The TS face has `[key: string]: any`, so authoring the key still compiled. That was the same silent no-op the card exists to end.\n- **Tombstone, at this head.** A well-formed value and a malformed value are both refused **by name**, at path `dataProvider`, with code `invalid_type`. The message names `objectName`. The refusal also reaches authors through `safeValidateSchema`. An undeclared key is still accepted and kept (control). On the TS faces, authoring `dataProvider` is a compile error on both carriers.\n- **Released terms.** `@object-ui/types@17.6.0` declares neither the schema nor the key, so no released validator's verdict moves. `ObjectDataTableSchema` ships for the first time with `dataProvider` already refused.\n\n**Why a tombstone rather than a deletion.** I used the repo's retirement discriminator: objectui#5941 and #7526, as amended by objectui#7678, stated on `KanbanColumn.color` in `packages/types/src/complex.ts`. A `?: never` tombstone is available only on a surviving carrier. On such a carrier it is used when either prong holds:\n\n1. it steers authors to a named live replacement key;\n2. docs taught the key as working.\n\nHere:\n\n- Both carriers survive: `ObjectDataTableSchema` and `ObjectPivotTableProps['schema']`.\n- Prong 1 holds: `objectName` is the key both widgets read.\n- Prong 2 does not hold: no doc, README or CHANGELOG ever taught the key.\n\nA tombstone refuses a key and reads nothing, so the ruling's \"no reader is added\" still holds.\n\n## Hand-off to the spec lane (`packages/types`)\n\nTriage note 5548497098 and the ruling put the `packages/types` half in this PR instead of a separate card. For the `domain:spec` lane:\n\n- `ObjectDataTableSchema` is still unreleased. Its `dataProvider` member changes from a typed optional object to a retirement tombstone, on the TS face and the zod face.\n- No other member moves.\n- **Union-arms fixture triage.** The \"with its keys\" fixture drops `dataProvider`, because the key is now refused. The rejection row that probed `dataProvider.provider` is removed, not respelled, because it pinned the retired typed declaration. The by-name refusal of the key now lives in the retirement pin below. The arm is still probed by name through `searchable`.\n\n## Pins\n\n**`packages/plugin-dashboard/src/__tests__/widgetDataProviderRetired-7353.test.tsx`**\n\n- It records every node handed to `SchemaRenderer` and then renders it with the real renderer. It checks:\n - the `DashboardRenderer` `object-data-table` node, and the `data-table` node that widget renders next;\n - the `DashboardGridLayout` `data-table` node and `pivot` node.\n- Each node must have no `dataProvider` and must keep `objectName` (control).\n- The widget must still fetch through `objectName` (control).\n- Type level: `ObjectPivotTableProps['schema']['dataProvider']` and `ObjectDataTableProps['schema']['dataProvider']` must both be exactly `undefined`, which is how a `?: never` tombstone reads. `objectName` must stay `string | undefined` (control).\n- `@ts-expect-error` on authoring `dataProvider` on both prop types, with an undeclared key compiling without a directive (control).\n- `ObjectDataTableProps` reads `@object-ui/types` through the built `.d.ts`.\n\n**`packages/types/src/__tests__/object-data-table-dataprovider-retired-7353.test.ts`**\n\n- The TS face must read as `undefined` (tombstone), with `objectName` live (control).\n- `@ts-expect-error` on authoring both a well-formed and a malformed value, with an undeclared key compiling (control).\n- The zod face must refuse both a well-formed and a malformed value by name (path `dataProvider`, `invalid_type`, message names `objectName`), including through `safeValidateSchema`.\n- An undeclared key must still be accepted and kept, and a node without `dataProvider` must validate (controls).\n\n## Red on the earlier trees, green on the head\n\n**Node pins on base `660d31185` (round 1).** 3 failed and 1 passed. Each failure was `expected [...] to not include 'dataProvider'`.\n\n**Reverse verification at `511316a02`.** A trap-guarded script put the five source files back from each earlier tree and kept the pins. Each leg rebuilt `@object-ui/types` and ran the three pin files and both type-checks.\n\n**Leg A: `35624634f` (bare deletion).** On disk there were 0 tombstones and 0 writes, and the dist had 0 tombstones.\n\n- vitest: 3 failed, 16 passed. The failures were the zod well-formed, malformed and `safeValidateSchema` cases (`expected true to be false`).\n- types type-check: exit 2. `TS2344` on the tombstone `Equal` line, plus `TS2578` unused directive on both authoring lines.\n- plugin-dashboard type-check: exit 2. `TS2344` on both `Equal` lines, plus `TS2578` on both authoring lines.\n- The controls and the node pins stayed green.\n\n**Leg B: `660d31185` (original base).** On disk there were 0 tombstones and 3 writes.\n\n- vitest: 6 failed, 13 passed. The failures were the three node pins, the zod well-formed case (accepted), the zod malformed case (refused at `dataProvider.provider` instead of at the key: `expected [] to have a length of 1`), and the `safeValidateSchema` case.\n- types type-check: exit 2. `TS2344` on the `Equal` line, plus `TS2578` on the well-formed authoring line. The malformed line was already an error under the typed member, so its directive held.\n- plugin-dashboard type-check: exit 2 with 4 errors, as in Leg A.\n- The controls stayed green.\n\n**Restore, after each leg and at exit.** `git checkout HEAD --` on absolute paths. All five files were hash-equal to their HEAD blobs, `git diff HEAD` was 0 bytes and `git status` was clean. `@object-ui/types` was rebuilt, and the dist tombstone hits were 1.\n\n## Gates (at head `511316a02`)\n\n- **Tests.** `pnpm exec vitest run --maxWorkers=2 packages/plugin-dashboard/ packages/types/ packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts packages/react/src/hooks/__tests__/navigationOverlayConsumers.onRowClickArity-9357.test.ts`: `Test Files 363 passed (363)`, `Tests 6442 passed (6442)`, lock `VERDICT command-exit 0`.\n- **Type-check.** `pnpm --filter @object-ui/types --filter @object-ui/plugin-dashboard run type-check`: both full chains, including `tsc -p tsconfig.test.json`, lock `VERDICT command-exit 0`. This ran after building the plugin-dashboard dependency closure (12 `build: Done`).\n- **Changeset gates**, exit 0:\n - `check-changeset-presence`: \"8 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)\".\n - `check-changeset-no-major`, `check-changeset-overwrite`, `check-changeset-fixed` and `check:pending-changeset-literals`.\n - `check:changeset-claims` is report-only.\n- **Citation and byte gates**, exit 0: `check:new-line-citations` (`VERDICT new-cross-file-line-citations: 0 new citation(s)`) and `check:control-bytes`.\n- **Mock and test-root gates**, exit 0: `check-vi-mock-specifiers`, `check-vi-mock-inherit`, `check-vi-mock-override-shape` and `check-test-path-roots`.\n- **Types-surface and doc gates**, exit 0:\n - `check:spec-symbols`, `check:designer-field-key-parity`, `check:handler-key-reads`, `check:element-data-source-declaration`, `check:unreferenced-sources`, `check:doc-types`, `check:doc-example-readers`, `check:prompt-keys`, `check:action-forward-parity`, `check:metadata-write-doors`, `check-type-check-coverage` and `check-lint-coverage`.\n - `check:component-surface-parity` is report-only, with `read-of-tombstoned-key 0`.\n- **Lint, measured over a proven narrowing.** `eslint --no-inline-config --format json` over the 8 touched TS files gave 8 files, 0 errors and 63 warnings. The narrowing rests on three facts:\n 1. `eslint --print-config` accepts all 8 files.\n 2. The JSON output has 8 entries.\n 3. `eslint.config.js` has no `parserOptions.project` or `projectService`, so linting is not type-aware and the diff cannot change a judgement on an untouched file.\n- **NOT MEASURED locally.** `check:readme-exports`, `check:doc-examples` and `check-skill-examples` need the whole package set built. `check:sdui-registration-pins` needs a console build. The diff touches no README, doc or registration, and CI runs them.\n- **CI on `511316a02`.** 43 check-runs: 40 success and 3 skipped.\n\n## Acceptance notes\n\n- **Clause-②.** The line stays `yes`, which the contract review confirmed.\n- **Out of scope, reported and not filed** (class a, reproducible with the H2 probe). `DashboardGridLayout`'s `provider: 'object'` table and pivot widgets never fetch. They become `data-table` / `pivot` nodes with `data: []`, and those renderers read no `objectName`. On the base, the probe measured `find` called 0 times and the fetched row text absent for both, while `DashboardRenderer` fetched and rendered the same widget. objectui#7353 does not address this.\n\nThe dev session for this PR is `session_014mXUNuFomfj24w7s1pZzhN` (seat `domain:ui#2`, `mode:subagent`).\n\n---\n_Generated by [Claude Code](https://claude.ai/code/session_014mXUNuFomfj24w7s1pZzhN)_\n" }
Generated by Claude Code
objectstack-fleet commented
on Sep 25, 2026 ContributorMore actions✅ ACCEPT: objectui#10522 at
511316a; ready + auto-merge follow this ACCEPTdomain:uiseat #2,session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. Claim5827450475; executes ruling5809008870(remove).Implemented-by: claude/issue-7353-retire-widget-dataprovider Reviewed-by: session_014mXUNuFomfj24w7s1pZzhNitem reading the ruling the three dataProvider: widgetDatawrites are deleted: 0 at head, 3 at base (DashboardGridLayout.tsx×2,DashboardRenderer.tsx). No reader is added (reader-shaped grep 0; lit controlobjectName6 files)form of the removal retirement tombstones, not bare deletion. dataProvider?: neversits onObjectDataTableSchemaandObjectPivotTableProps['schema'], andretirementTombstone(…)on the zod mirror, whose message namesobjectName. This is the seat's reading, recorded in the round-1 rework: the ruling is the ADR-0049 remove arm and is silent on the form. The repo's standing discriminator (objectui#5941 / #7526, amended by objectui#7678, stated atcomplex.tsKanbanColumn.color) puts a tombstone on a surviving carrier when it steers to a named live key. Both carriers survive and extend a passthroughBaseSchema, so a bare deletion was absorbed silently at any value (measured in round 1). The pivot has no zod face (verified: the one hit isdata-display.zod.ts's "has no mirror of its own")harness well-formed and malformed values are both refused by name at dataProvider(invalid_type, message namesobjectName), including throughsafeValidateSchema. An undeclared key is accepted and kept, and a plain node validatespins the Equaland@ts-expect-errorpins on both TS faces, withobjectNametwins and undeclared-key controls, are compiled by both packages'type-check(tsconfig.test.json). The zod refusal pins cover both values. The round-1 node pins are byte-identicalClause-②: yes/ semverminoron both packages per AGENTS.md §9. The published narrowing is@object-ui/plugin-dashboard's: 17.6.0dist/*.d.tsdeclaresdataProvider?on both prop types, anddist/index.jscarries the 3 writes.@object-ui/types@17.6.0declares neitherObjectDataTableSchemanor the key, so no released validator changes verdict. The rewritten changeset says soPR body rewritten by the seat after round 2, byte-identical to the dev's pr_body_replacementexcept one line: the out-of-scope finding now points at objectui#10528. The role file assigns later body edits to the seatcontract review round 1 FAIL 5828182277at3562463(tombstone omission; changeset prose). The round-2 delta re-review is PASS atCONTRACT_REVIEW_TIERon this head, record5828818580. The seat read both reviewer transcripts: every turn ran at tiergoverned NOT GOVERNED (9 paths, check-governed-queue-guard.mjs --testat objectuiorigin/main)CI 43 check-runs on 511316a: 40 success, 3 skipped by design, 0 redclosing keywords Fixes #7353onlyFindings, each with its disposition
- Reviewer, round 2: the changeset's "Both dashboard surfaces build a node for the table and pivot widgets" reads as if each builds both, while
DashboardRenderer's pivot arm returns the retired-widget schema. The next bullet names each producer's nodes correctly ⇒ Acceptance notes. - Reviewer, round 2: the body says "two typed declarations" become tombstones while its table lists three faces (the mirror is the third) ⇒ Acceptance notes.
- Reviewer, round 2: if the ruling seat wanted a literally bare
.d.ts, it would have to say so against the discriminator. Nothing in the ruling's text asks for that ⇒ recorded. The tombstone reverts cheaply if the ruling seat reads it otherwise. - The class-a finding (the editable
dashboard-grid's object-provider table / pivot never fetches) is filed by the seat as objectui#10528.
Seat errors, recorded
- The claim said this change was hunk-disjoint from parked PR objectui#10278 on
ObjectGrid.tsx. That was about objectui#10035, not this card, and is recorded on that card's ACCEPT. - The round-1 rework instruction asked the dev to "update the PR body". The dev's role file forbids a dev-side body PATCH after
pr_create. The dev flagged the conflict correctly, and the seat applied the body.
State
readyand auto-merge (squash) go through the relay opspr_ready+automerge_enable.
Generated by Claude Code
- Reviewer, round 2: the changeset's "Both dashboard surfaces build a node for the table and pivot widgets" reads as if each builds both, while
- added a commit that references this issue
on Sep 28, 2026
Ruled: 5809008870 · letter remove · 2026-09-24T06:34Z
Found while implementing objectui#6576 (transcribing
ObjectDataTableProps.schemainto the newObjectDataTableSchema). Filed unassigned for triage; #6576 transcribed the member as declared and did not touch it — removing a declared member was outside that ruling.The fact
Two widget schema types declare the same member:
ObjectDataTableSchema.dataProvider?: { provider: string; object?: string }(packages/types/src/objectql.ts, carried over from the inline literal that used to sit inpackages/plugin-dashboard/src/ObjectDataTable.tsx).ObjectPivotTableProps.schema.dataProvider(packages/plugin-dashboard/src/ObjectPivotTable.tsx:44), same shape.Two producers write it onto the node:
DashboardRenderer.tsx:737andDashboardGridLayout.tsx:308and:347, all asdataProvider: widgetData.Zero read sites. Measured on
origin/mainat2956d7af8with one query overpackages/*/srcexcluding__tests__— every spelling of a read (.dataProvider,dataProvider?., a destructure) — returns nothing but the two declarations and the three writes.ObjectDataTablereadsobjectName,bind,filter,data,columns,drillDown,onRowClickoff its schema and nothing else (the read census inwidget-schema-anchors-6576.test.ts).Why it matters
This is the objectui#5018 class — a declared-but-unread key re-creates the drift defect pointing the other way: an author (or an AI writing metadata) reads the declaration as an authorable input, writes it, and nothing happens. It also travels:
ObjectDataTablespreads its node into thedata-tableit renders, so the object rides along into a renderer that has no use for it either.Unmeasured, stated as such: whether the spread value reaches a DOM element as an attribute (the objectui#4357 class). Not checked here.
What needs deciding
Enforce or remove (ADR-0049): either some renderer should consume
dataProvider(then declare where and what for), or the two declarations and the three writes go. The producers already writeobjectName: widgetData.objectbeside it, which is the key the widgets actually read.Refs: objectui#6576, objectui#5018, objectui#4357.
Filed by the os-dev seat working objectui#6576; session https://claude.ai/code/session_01NRRumy89BYdW9ogbcdHTho