Found while implementing #5344 (retiring the READ tolerance in ViewColumnInspector). Filed unassigned, not claiming. Out of that card's granted file surface (ViewColumnInspector.tsx + its tests only), so recorded rather than fixed.
The fact
packages/app-shell/src/views/metadata-admin/previews/view-column-io.ts carries the same undeclared-alias read that #5344 just retired one file over:
// :29 — colLabel()
return String(o.label ?? o.header ?? o.field ?? o.accessorKey ?? `col ${i + 1}`);
// :39 — colFieldName()
const v = o.field ?? o.accessorKey;
Its sole importer is previews/FieldsListEditor.tsx, which supplies the row labels for the column manager — and FieldsListEditor renders inside ViewColumnInspector's own panel (it is rendered by both ViewVariantInspector and ViewColumnInspector; see that file's header docblock).
Why it is worth recording now
After #5344 the two surfaces disagree within one panel. Measured on the #5344 branch, mounting the real component with a stored column {accessorKey: 'name', header: 'Name'}:
- the inspector's Field key control shows
'' and its Header control shows '' — the ruled behaviour, since ListColumn refuses both keys by name (unrecognized_keys ["accessorKey","header"]); - the column list row one line above still reads
Name, because colLabel consults o.header.
So the ruling's observable requirement — "the inspector stops presenting a spec-refused spelling as a valid column identity" — is met by the identity controls and not by the list rendered beside them. A pin for exactly this is committed in ViewColumnInspector.identityRead.test.tsx (the test named "records the residue this card is fenced out of"), which asserts getAllByText('Name') has length 1 and carries a comment saying the expectation flips when this is fixed.
Two details worth having before triage
colLabel's precedence is not merely tolerant, it is inverted. The chain is label ?? header ?? field ?? accessorKey — header is preferred overfield. A perfectly canonical column that also happens to carry a stray header key displays header's value rather than its declared label/field. That is a different (and stronger) defect than the plain ?? accessorKey alias.colFieldName feeds more than a label. It backs usedFieldNames(), which is what the Add-field picker uses to decide which object fields are already taken. Reading accessorKey there means a spec-refused column still reserves a field name in the picker.
Scope note
Same family as #5068 (renderer), #5120 (packages/components / plugin-dashboard), #5340 (bridgeListView), and #5344 (the column inspector, now fixed). This is the sixth site and the second editor-side one. Whether it should be retired the same way #5344 was, or whether the list deliberately wants a best-effort human label for a column it cannot otherwise name, is a judgement this finding does not take — note the two surfaces are not symmetric: an empty field-key box invites re-authoring, an empty list row would leave the author with nothing to click.
Reproduce
sed -n '1,45p' packages/app-shell/src/views/metadata-admin/previews/view-column-io.ts
grep -rn "view-column-io" packages/app-shell/src --include=*.tsx # sole importer
Found while implementing #5344 (retiring the READ tolerance in
ViewColumnInspector). Filed unassigned, not claiming. Out of that card's granted file surface (ViewColumnInspector.tsx+ its tests only), so recorded rather than fixed.The fact
packages/app-shell/src/views/metadata-admin/previews/view-column-io.tscarries the same undeclared-alias read that #5344 just retired one file over:Its sole importer is
previews/FieldsListEditor.tsx, which supplies the row labels for the column manager — andFieldsListEditorrenders insideViewColumnInspector's own panel (it is rendered by bothViewVariantInspectorandViewColumnInspector; see that file's header docblock).Why it is worth recording now
After #5344 the two surfaces disagree within one panel. Measured on the #5344 branch, mounting the real component with a stored column
{accessorKey: 'name', header: 'Name'}:''and its Header control shows''— the ruled behaviour, sinceListColumnrefuses both keys by name (unrecognized_keys ["accessorKey","header"]);Name, becausecolLabelconsultso.header.So the ruling's observable requirement — "the inspector stops presenting a spec-refused spelling as a valid column identity" — is met by the identity controls and not by the list rendered beside them. A pin for exactly this is committed in
ViewColumnInspector.identityRead.test.tsx(the test named "records the residue this card is fenced out of"), which assertsgetAllByText('Name')has length 1 and carries a comment saying the expectation flips when this is fixed.Two details worth having before triage
colLabel's precedence is not merely tolerant, it is inverted. The chain islabel ?? header ?? field ?? accessorKey—headeris preferred overfield. A perfectly canonical column that also happens to carry a strayheaderkey displaysheader's value rather than its declaredlabel/field. That is a different (and stronger) defect than the plain?? accessorKeyalias.colFieldNamefeeds more than a label. It backsusedFieldNames(), which is what the Add-field picker uses to decide which object fields are already taken. ReadingaccessorKeythere means a spec-refused column still reserves a field name in the picker.Scope note
Same family as #5068 (renderer), #5120 (
packages/components/plugin-dashboard), #5340 (bridgeListView), and #5344 (the column inspector, now fixed). This is the sixth site and the second editor-side one. Whether it should be retired the same way #5344 was, or whether the list deliberately wants a best-effort human label for a column it cannot otherwise name, is a judgement this finding does not take — note the two surfaces are not symmetric: an empty field-key box invites re-authoring, an empty list row would leave the author with nothing to click.Reproduce