Skip to content

finding(objectui): ~20 more relationship-target readers still run a legacy-first reference_to chain the ingestion normalizer already made redundant #6837

Description

@claude

Surfaced while implementing objectui#6719 (PR #6836), and deliberately left out of that PR's fence: that card names one file.

What was measured

objectui#6528 narrowed two relationship-target resolvers to the spec spelling reference; objectui#6648 narrowed the same two to the string carrier; objectui#6719 did both for a third reader, app-shell's auditHistoryDisplay.ts. A grep of the whole tree for the legacy-first chain shape (reference_to ?? reference, reference_to || reference, referenceTo ||), excluding tests, turns up roughly twenty MORE readers of the same value, spread over nine packages:

  • packages/plugin-detail/src/RecordDetailDrawer.tsx:267 — the widest of them, a four-spelling chain: def.reference_to ?? def.reference ?? def.referenceTo ?? def.target. referenceTo is in RETIRED_FIELD_KEYS (objectui#6519), so the read door already strips it; target is not one of the three spellings finding(app-shell): resolveReferenceTos referenceTo branch is unreachable now that the read door strips the key #6528 measured at all, and is not in the spec's alias table either.
  • packages/plugin-detail/src/RelatedList.tsx:666,939, RecordMetaFooter.tsx:88, fieldEnrichment.ts:238, synth/buildDefaultPageSchema.ts:598
  • packages/plugin-gantt/src/ObjectGantt.tsx:1128 (three spellings)
  • packages/plugin-tree/src/ObjectTree.tsx:132 (three spellings, canonical-first)
  • packages/plugin-charts/src/ObjectChart.tsx:177
  • packages/plugin-list/src/ListView.tsx:2454,2465, UserFilters.tsx:291, ObjectGallery.tsx:272
  • packages/fields/src/widgets/LookupField.tsx:256, UserField.tsx:48 (canonical-first), FilterConditionField.tsx:111, packages/fields/src/index.tsx:1937
  • packages/app-shell/src/views/RecordDetailView.tsx:1841, utils/deriveRelatedLists.ts:194, utils/resolveActionParams.ts:532

Most read the LEGACY spelling first, ahead of the one ObjectSchema.safeParse actually accepts.

Why this is observation-class, not a live defect

None of these produces a wrong answer today, and the reason is the same one measured on objectui#6719: normalizeSchemaReferenceKeys (packages/core/src/utils/reference-keys.ts) runs at the two ingestion choke points — MetadataProvider's type cache for metadata type object, and ObjectStackAdapter.getObjectSchema — and stamps BOTH snake_case keys from whichever spelling arrived. So by the time any of these readers sees a def, the two keys are present and equal, and the chain is redundant rather than load-bearing.

That is exactly the tension worth recording. reference-keys.ts states its own purpose as running at the choke point "so per-consumer dual-key fallbacks can't drift" — and then twenty per-consumer dual-key fallbacks were written anyway. Each one is a place where a producer emitting only the refused spelling would be silently absorbed rather than failing visibly (AGENTS.md #0.1), and each one has to be reasoned about again the next time someone audits this value.

What a fix would be

Not one PR. The useful next step is a measurement, not a sweep: for each reader, establish which contract its caller feeds it — an object metadata document (canonicalized upstream, so the chain is dead weight) or ObjectUI's own view/field contract (DetailViewFieldSchema in @object-ui/typesviews.zod.ts, where reference_to is the live key and plugin-detail translates INTO it from reference). objectui#6719's PR shows the shape that answer takes, and the refusal-pin shape both axes are pinned with.

RecordDetailDrawer.tsx:267 is the one worth doing first regardless of the wider sweep: two of its four arms (referenceTo, target) are refused by name and have no producer on any of the contracts involved.

Filed unassigned, for triage.

Generated by Claude Code


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

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

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions