You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while censusing bind producers and consumers for #6357 (PR #6574). Not that card's defect — filed separately per its dispatch.
The fact
bind is the data-scope binding vocabulary: a path string resolved by useDataScope(). Ten production sites read it. data-table is not one of them — it reads its rows from an inline data array on the node and never calls the hook.
So a bind on a data-table node is accepted by every gate and does nothing:
the TS side accepts it (BaseSchema's [key: string]: any);
the zod side accepts it (BaseSchema is .passthrough(), and DataTableSchema is BaseSchema.extend(…), which inherits that);
nothing reads it at render.
The result is a table that draws its header over an empty body — no error, no warning, no diagnostic.
This is already documented and already pinned — it just has no card
skills/objectui/rules/protocol.md:162 states it verbatim: "data-table does NOT: it reads its rows from an inline data array on the node, so a bind on it is ignored and the table renders its header over an empty body — no error, no warning."
packages/components/src/__tests__/skill-guide-data-table-binding.test.tsx pins the behaviour, including the measured detail that "the bound array never reaches the renderer at all" — the body is one row, the empty state spanning the table.
So the behaviour is known and asserted. What is missing is a decision about whether it should stay.
Why declaring bind centrally did not change this
PR #6574 declares bind on BaseSchema (the #6357 census concluded it belongs there). That does not touch this: the key was accepted on every node before the declaration existed, via the index signature and .passthrough(). The declaration narrows the key's value to a string; it cannot refuse the key on a node that ignores it. Recording that explicitly so this is not read as a regression from that PR.
What needs deciding
Three shapes, not obviously one answer:
Make data-table a reader — call useDataScope(schema.bind) like the other nine. Consistent with the vocabulary the protocol teaches, but it is a behaviour change on a published component: a node carrying both data and bind would need a stated precedence.
Diagnose it at render — the repo already has a diagnostic channel for exactly this shape of silent failure (packages/plugin-grid's column-spelling diagnostic, visibilityDiagnostic.ts).
Leaning 3 then 1, but this is a published-surface behaviour question rather than a mechanical fix, which is why this is a finding and not a patch.
Found while censusing
bindproducers and consumers for #6357 (PR #6574). Not that card's defect — filed separately per its dispatch.The fact
bindis the data-scope binding vocabulary: a path string resolved byuseDataScope(). Ten production sites read it.data-tableis not one of them — it reads its rows from an inlinedataarray on the node and never calls the hook.So a
bindon adata-tablenode is accepted by every gate and does nothing:BaseSchema's[key: string]: any);BaseSchemais.passthrough(), andDataTableSchemaisBaseSchema.extend(…), which inherits that);The result is a table that draws its header over an empty body — no error, no warning, no diagnostic.
This is already documented and already pinned — it just has no card
skills/objectui/rules/protocol.md:162states it verbatim: "data-tabledoes NOT: it reads its rows from an inlinedataarray on the node, so abindon it is ignored and the table renders its header over an empty body — no error, no warning."packages/components/src/__tests__/skill-guide-data-table-binding.test.tsxpins the behaviour, including the measured detail that "the bound array never reaches the renderer at all" — the body is one row, the empty state spanning the table.So the behaviour is known and asserted. What is missing is a decision about whether it should stay.
Why declaring
bindcentrally did not change thisPR #6574 declares
bindonBaseSchema(the #6357 census concluded it belongs there). That does not touch this: the key was accepted on every node before the declaration existed, via the index signature and.passthrough(). The declaration narrows the key's value to a string; it cannot refuse the key on a node that ignores it. Recording that explicitly so this is not read as a regression from that PR.What needs deciding
Three shapes, not obviously one answer:
data-tablea reader — calluseDataScope(schema.bind)like the other nine. Consistent with the vocabulary the protocol teaches, but it is a behaviour change on a published component: a node carrying bothdataandbindwould need a stated precedence.bindondata-tableat parse time. Blocked on the same ceiling as everything else in this class:.passthrough()means a per-node strict shape is needed first (finding(types): BaseSchema's[key: string]: anyleaves every component schema open, so a "declare the surface" fix can never reject a misspelled TOP-LEVEL key #5155 / finding(types): ObjectViewSchema'stableandformslots declare ZERO properties — the same Omit-under-index-signature collapse as #6151, in property position #6269).packages/plugin-grid's column-spelling diagnostic,visibilityDiagnostic.ts).Leaning 3 then 1, but this is a published-surface behaviour question rather than a mechanical fix, which is why this is a finding and not a patch.
Reproduce
Refs: #6357, PR #6574. Adjacent ceiling: #5155 / #6269.