Found while implementing #4971 (the declared-arm ⊆ spec-accepted gate). Filed unassigned, not claiming. Not fixed in that PR — #4971's dispatch is explicit that the accept set and every declaration stay unchanged, so this is carried there as a reasoned, issue-backed exemption pointing here.
Two entries of the same contract, opposite kinds
Both are @objectstack/spec@17.2.0, both describe object-grid's data:
| spec authority | kind | its own description |
|---|
ViewDataSchema — what ObjectGridSchema.data?: ViewData (packages/types/src/objectql.ts:556) resolves to | object, discriminated on provider (object / api / value / schema), each arm strict | inline rows live at { provider: 'value', items: [...] } |
ComponentPropsMap['object-grid'].data | array (z.array(z.unknown()).optional()) | 'Static inline rows — bypasses the object query' |
Measured on the installed pin:
ComponentPropsMap['object-grid'].safeParse({ data: [{ id: 1 }] }) → success
ComponentPropsMap['object-grid'].safeParse({ data: { provider: 'value', items: [] } })
→ [{"expected":"array","code":"invalid_type","path":["data"],
"message":"Invalid input: expected array, received object"}]
The declaration (plugin-grid/src/index.tsx:225, type: 'object') matches the first authority — deliberately, and it is pinned there: #5090 / PR #5108 changed it from 'array' to 'object' against ViewDataSchema's own verdicts, and packages/plugin-grid/src/__tests__/gridDataInputContract.test.ts holds it. So it is the ComponentPropsMap entry that now refuses the published arm.
Why this is not a re-file of #5090
#5090 was declaration-vs-contract with ONE contract. This is contract-vs-contract: the fix #5090 landed is what makes the second authority's disagreement visible, and no change to the declaration can satisfy both — 'object' is refused by ComponentPropsMap, 'array' is refused by ViewDataSchema and by tsc (TS2322, measured on #5090). Flipping the declaration back would re-open #5090 exactly.
Why it matters
ComponentPropsMap is the authority the repo-wide parity gates read (apps/console/src/__tests__/registry-inputs-spec-parity.test.ts — both key-name directions and, since #4971, the arm direction). While the two disagree, one of them is teaching authors a shape the other refuses, and the gate that would notice has to be told to look away on this key.
Resolution is upstream, not here
This repo does not edit @objectstack/spec (AGENTS.md #0 / #0.1) — the two entries have to converge on one kind upstream. The likely shape (not a decision this card can take): ComponentPropsMap['object-grid'].data becomes ViewDataSchema, which is what ObjectGridSchema already resolves to and what the designer publishes; the array form is the deprecated staticData shortcut the #4648 carve-out already refuses to publish.
How to re-derive
sed -n '225p' packages/plugin-grid/src/index.tsx
grep -n 'data?: ViewData' packages/types/src/objectql.ts
pnpm exec vitest run apps/console/src/__tests__/registry-inputs-spec-parity.test.ts # the #4971 arm gate; entry `object-grid.data:object`
pnpm exec vitest run packages/plugin-grid/src/__tests__/gridDataInputContract.test.ts # the #5090 pin, against ViewDataSchema
Deleting the exemption entry in registry-inputs-spec-parity.test.ts is what closes this card — the gate's stale-exemption test demands it the moment the two authorities converge.
Found while implementing #4971 (the declared-arm ⊆ spec-accepted gate). Filed unassigned, not claiming. Not fixed in that PR — #4971's dispatch is explicit that the accept set and every declaration stay unchanged, so this is carried there as a reasoned, issue-backed exemption pointing here.
Two entries of the same contract, opposite kinds
Both are
@objectstack/spec@17.2.0, both describeobject-grid'sdata:ViewDataSchema— whatObjectGridSchema.data?: ViewData(packages/types/src/objectql.ts:556) resolves toprovider(object/api/value/schema), each arm strict{ provider: 'value', items: [...] }ComponentPropsMap['object-grid'].dataz.array(z.unknown()).optional())'Static inline rows — bypasses the object query'Measured on the installed pin:
The declaration (
plugin-grid/src/index.tsx:225,type: 'object') matches the first authority — deliberately, and it is pinned there: #5090 / PR #5108 changed it from'array'to'object'againstViewDataSchema's own verdicts, andpackages/plugin-grid/src/__tests__/gridDataInputContract.test.tsholds it. So it is theComponentPropsMapentry that now refuses the published arm.Why this is not a re-file of #5090
#5090 was declaration-vs-contract with ONE contract. This is contract-vs-contract: the fix #5090 landed is what makes the second authority's disagreement visible, and no change to the declaration can satisfy both —
'object'is refused byComponentPropsMap,'array'is refused byViewDataSchemaand bytsc(TS2322, measured on #5090). Flipping the declaration back would re-open #5090 exactly.Why it matters
ComponentPropsMapis the authority the repo-wide parity gates read (apps/console/src/__tests__/registry-inputs-spec-parity.test.ts— both key-name directions and, since #4971, the arm direction). While the two disagree, one of them is teaching authors a shape the other refuses, and the gate that would notice has to be told to look away on this key.Resolution is upstream, not here
This repo does not edit
@objectstack/spec(AGENTS.md #0 / #0.1) — the two entries have to converge on one kind upstream. The likely shape (not a decision this card can take):ComponentPropsMap['object-grid'].databecomesViewDataSchema, which is whatObjectGridSchemaalready resolves to and what the designer publishes; the array form is the deprecatedstaticDatashortcut the #4648 carve-out already refuses to publish.How to re-derive
Deleting the exemption entry in
registry-inputs-spec-parity.test.tsis what closes this card — the gate's stale-exemption test demands it the moment the two authorities converge.