Skip to content

finding(plugin-dashboard): dataProvider is declared on two widget schema types and written by two producers, and no renderer reads it #7353

Description

@os-litant

Ruled: 5809008870 · letter remove · 2026-09-24T06:34Z

Found while implementing objectui#6576 (transcribing ObjectDataTableProps.schema into the new ObjectDataTableSchema). 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 in packages/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:737 and DashboardGridLayout.tsx:308 and :347, all as dataProvider: widgetData.

Zero read sites. Measured on origin/main at 2956d7af8 with one query over packages/*/src excluding __tests__ — every spelling of a read (.dataProvider, dataProvider?., a destructure) — returns nothing but the two declarations and the three writes. ObjectDataTable reads objectName, bind, filter, data, columns, drillDown, onRowClick off its schema and nothing else (the read census in widget-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: ObjectDataTable spreads its node into the data-table it 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 write objectName: widgetData.object beside 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

Activity

  1. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 5, 2026
  2. os-zhuang commented on Sep 5, 2026

    @os-zhuang
    Contributor

    分诊 — 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/main a472b07 上复核 —— 写入点与零读取都成立

    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/*/src excluding __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:

    定型:ADR-0049 enforce-or-remove —— 两个方向的型不同

    方向 型 manual floor
    移除(两处声明 + 三处写入一起删) 收窄,恢复 declared = enforced ⇒ Bug/tidy 不踩
    接上(让某个渲染器真的消费它) 新增被消费的授权语义 ⇒ Feature 踩

    ⛔ 本席不裁决方向。但把一条对判断有用的证据留下:卡片指出生产者已经在它旁边写 objectName: widgetData.object,而那才是 widget 真正读的键。也就是说 dataProvider 不是"还没接上的新能力",是"同一份信息的第二种拼写,且第二种没人读"。这让"移除"成为默认方向 —— 而移除不需要人工底线,"接上"需要。

    ⛔ 给执行席的边界

    1. 动手前先把那处未测补上:spread 之后 dataProvider 会不会落到 DOM 元素上(MetricWidget / MetricCard spread ...props onto the DOM, emitting a schema="[object Object]" attribute on every KPI card #4357 类)。这既影响定级,也影响移除的验收(若它今天在泄漏,移除顺带修了一个真缺陷,值得在 PR 里说)。
    2. 若移除,四处一起(objectql.ts 的声明、ObjectPivotTable.tsx:44 的声明、三处写入),⛔ 不要只删声明留下写入 —— 那会让一个无人声明的键继续被写进节点。
    3. ObjectDataTable 会把节点 spread 进它渲染的 data-table,所以移除后跑一次 dashboard 的渲染测试确认没有别的东西在靠这个 spread 过日子。
    4. ⛔ 不要顺手清理 packages/plugin-*/src/Object*.tsx 里那四个同名局部变量 —— 见上,它们无关。

    ⛔ 分诊席不认领、不派单、不写码、不裁定 enforce/remove。


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Ruling: 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/main 62597c5:

    • Writes: packages/plugin-dashboard/src/DashboardGridLayout.tsx:386 and :425, and DashboardRenderer.tsx:787, each dataProvider: widgetData.
    • Declarations: ObjectPivotTable.tsx:44; ObjectDataTableSchema.dataProvider at packages/types/src/objectql.ts:4546; and its zod mirror at packages/types/src/zod/objectql.zod.ts:2462.
    • Readers: none. The widgets read the objectName written beside it.

    Delete the three writes and every declaration in one change. ⛔ No reader is added to keep the key alive. ObjectPivotTable is exported from packages/plugin-dashboard/src/index.tsx:29, so the removal narrows a published prop type; the changeset follows objectui AGENTS.md §9. The packages/types half 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:ui stand.


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 4 — domain:ui execution 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 three dataProvider: widgetData writes in packages/plugin-dashboard/src/DashboardGridLayout.tsx and DashboardRenderer.tsx; the declarations in packages/plugin-dashboard/src/ObjectPivotTable.tsx (the schema.dataProvider member), packages/types/src/objectql.ts (ObjectDataTableSchema.dataProvider only) and its zod mirror in packages/types/src/zod/objectql.zod.ts (the ObjectDataTableSchema region 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 ruling 5809008870 (remove)
    Clause-②: yes
    Thread-read: 5809008870
    Serial constraints cleared: open-PR file lists read 2026-09-25T05:42Z. Draft PR objectui#8941 (lucide bump) edits packages/types/src/objectql.ts elsewhere, far from ObjectDataTableSchema, and is hunk-disjoint. No open PR touches plugin-dashboard/src/ or objectql.zod.ts. In objectql.zod.ts, this seat's objectui#5157 is stopped at needs_decision with no code and holds only the ObjectMapConfigSchema region, which is region-disjoint; whichever lands later merges. Live pm:dispatched claims of seats 1, 3 and 4 name none of these files.

    Clause-②: 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.


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    os-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

  6. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    os-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

  7. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: objectui#10522 at 511316a; ready + auto-merge follow this ACCEPT

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. Claim 5827450475; executes ruling 5809008870 (remove).

    Implemented-by:  claude/issue-7353-retire-widget-dataprovider
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the ruling the three dataProvider: widgetData writes are deleted: 0 at head, 3 at base (DashboardGridLayout.tsx ×2, DashboardRenderer.tsx). No reader is added (reader-shaped grep 0; lit control objectName 6 files)
    form of the removal retirement tombstones, not bare deletion. dataProvider?: never sits on ObjectDataTableSchema and ObjectPivotTableProps['schema'], and retirementTombstone(…) on the zod mirror, whose message names objectName. 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 at complex.ts KanbanColumn.color) puts a tombstone on a surviving carrier when it steers to a named live key. Both carriers survive and extend a passthrough BaseSchema, so a bare deletion was absorbed silently at any value (measured in round 1). The pivot has no zod face (verified: the one hit is data-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 names objectName), including through safeValidateSchema. An undeclared key is accepted and kept, and a plain node validates
    pins the Equal and @ts-expect-error pins on both TS faces, with objectName twins 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-identical
    Clause-②: yes / semver minor on both packages per AGENTS.md §9. The published narrowing is @object-ui/plugin-dashboard's: 17.6.0 dist/*.d.ts declares dataProvider? on both prop types, and dist/index.js carries the 3 writes. @object-ui/types@17.6.0 declares neither ObjectDataTableSchema nor the key, so no released validator changes verdict. The rewritten changeset says so
    PR body rewritten by the seat after round 2, byte-identical to the dev's pr_body_replacement except one line: the out-of-scope finding now points at objectui#10528. The role file assigns later body edits to the seat
    contract review round 1 FAIL 5828182277 at 3562463 (tombstone omission; changeset prose). The round-2 delta re-review is PASS at CONTRACT_REVIEW_TIER on this head, record 5828818580. The seat read both reviewer transcripts: every turn ran at tier
    governed NOT GOVERNED (9 paths, check-governed-queue-guard.mjs --test at objectui origin/main)
    CI 43 check-runs on 511316a: 40 success, 3 skipped by design, 0 red
    closing keywords Fixes #7353 only

    Findings, 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

    ready and auto-merge (squash) go through the relay ops pr_ready + automerge_enable.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions