Found while implementing #5068 (retiring ObjectGrid's undeclared accessorKey / header tolerance branch, and migrating its one in-repo producer bridgeListView). Filed unassigned, not claiming. Observation class — nothing is broken today by this alone.
The fact
packages/app-shell/src/views/metadata-admin/inspectors/ViewColumnInspector.tsx is the designer's scoped editor for a selected view column. It reads column identity through both spellings and, on write, preserves whichever one the stored document already used:
// :64
function colFieldKey(c: ViewColumn): string {
return c.field ?? c.accessorKey ?? '';
}
// :155
const patchIdentity = (updates: Partial<ViewColumn>) => {
const targetField = 'field' in col || !('accessorKey' in col) ? 'field' : 'accessorKey';
const targetLabel = 'label' in col || !('header' in col) ? 'label' : 'header';
Its own header comment names the intent: "the column IDENTITY (field key + label) … round-trip through two shapes: the ObjectStack canonical { field, label } and the legacy TanStack { accessorKey, header }."
Why it is worth recording now
#5068 removes the runtime that made the second shape work. After that PR:
- creating a column in the designer is already canonical and unaffected —
makeColumn (previews/view-column-io.ts:60) emits { field } plus label only when the author's label differs from the machine name; - editing a column of a stored view that already carries
{ accessorKey, header } re-saves it in that spelling. The inspector shows the value (it reads both), the author changes the field key, saves — and the column still does not render in an object-grid, because the spec refuses those keys by name (ListColumnSchema is strict: unrecognized_keys ["accessorKey","header"]) and the renderer no longer tolerates them.
So the editor keeps a dialect alive one layer above the renderer that just gave it up. That is the same declared-vs-read divergence #5068 is about, relocated into the authoring tool — where it is arguably worse, since the tool is the surface that is supposed to teach the correct shape.
Note this is a round-trip only: the inspector never invents the undeclared spelling, it only preserves one it was handed. Whether such documents exist in a real tenant is unmeasured here (the in-repo census for #5068 found zero authored accessorKey-shaped object-grid columns across examples/, content/docs/, apps, skills, e2e and package READMEs; every in-repo occurrence belongs to the table / data-table component, which legitimately owns the key).
The fork, unruled
- Normalize on write —
patchIdentity always writes { field, label } and drops accessorKey / header when it rewrites the column. The designer then migrates legacy documents by the act of editing them, which is the producer-side unification AGENTS.md #0.1 asks for. - Read both, write canonical, and say so — same as (1) plus a visible note in the inspector that the column was migrated.
- Leave it — the round trip is harmless as long as nothing renders those columns, and the spelling dies out with the documents.
(1) matches the disposition #5068 inherited from #3951; (3) is defensible only if no such documents exist, which nobody has measured on real data.
Scope note
Out of scope for #5068, whose granted file surface is packages/plugin-grid + packages/react (packages/app-shell/** explicitly excluded). Same family as #5120 (col.accessorKey || col.name in packages/components / plugin-dashboard) and #5340 (bridgeListView, resolved by #5068's PR). This is the fifth site in that family and the only one that is an editor rather than a renderer or a producer.
Reproduce
sed -n '1,20p;60,70p;150,170p' packages/app-shell/src/views/metadata-admin/inspectors/ViewColumnInspector.tsx
sed -n '60,70p' packages/app-shell/src/views/metadata-admin/previews/view-column-io.ts # create path: canonical
Generated by Claude Code
Found while implementing #5068 (retiring
ObjectGrid's undeclaredaccessorKey/headertolerance branch, and migrating its one in-repo producerbridgeListView). Filed unassigned, not claiming. Observation class — nothing is broken today by this alone.The fact
packages/app-shell/src/views/metadata-admin/inspectors/ViewColumnInspector.tsxis the designer's scoped editor for a selected view column. It reads column identity through both spellings and, on write, preserves whichever one the stored document already used:Its own header comment names the intent: "the column IDENTITY (field key + label) … round-trip through two shapes: the ObjectStack canonical
{ field, label }and the legacy TanStack{ accessorKey, header }."Why it is worth recording now
#5068 removes the runtime that made the second shape work. After that PR:
makeColumn(previews/view-column-io.ts:60) emits{ field }pluslabelonly when the author's label differs from the machine name;{ accessorKey, header }re-saves it in that spelling. The inspector shows the value (it reads both), the author changes the field key, saves — and the column still does not render in anobject-grid, because the spec refuses those keys by name (ListColumnSchemais strict:unrecognized_keys ["accessorKey","header"]) and the renderer no longer tolerates them.So the editor keeps a dialect alive one layer above the renderer that just gave it up. That is the same declared-vs-read divergence #5068 is about, relocated into the authoring tool — where it is arguably worse, since the tool is the surface that is supposed to teach the correct shape.
Note this is a round-trip only: the inspector never invents the undeclared spelling, it only preserves one it was handed. Whether such documents exist in a real tenant is unmeasured here (the in-repo census for #5068 found zero authored
accessorKey-shapedobject-gridcolumns acrossexamples/,content/docs/, apps, skills, e2e and package READMEs; every in-repo occurrence belongs to thetable/data-tablecomponent, which legitimately owns the key).The fork, unruled
patchIdentityalways writes{ field, label }and dropsaccessorKey/headerwhen it rewrites the column. The designer then migrates legacy documents by the act of editing them, which is the producer-side unification AGENTS.md #0.1 asks for.(1) matches the disposition #5068 inherited from #3951; (3) is defensible only if no such documents exist, which nobody has measured on real data.
Scope note
Out of scope for #5068, whose granted file surface is
packages/plugin-grid+packages/react(packages/app-shell/**explicitly excluded). Same family as #5120 (col.accessorKey || col.nameinpackages/components/plugin-dashboard) and #5340 (bridgeListView, resolved by #5068's PR). This is the fifth site in that family and the only one that is an editor rather than a renderer or a producer.Reproduce
Generated by Claude Code