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
finding(objectui): ~20 more relationship-target readers still run a legacy-first reference_to chain the ingestion normalizer already made redundant #6837
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.
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.
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'sauditHistoryDisplay.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.referenceTois inRETIRED_FIELD_KEYS(objectui#6519), so the read door already strips it;targetis not one of the three spellings finding(app-shell):resolveReferenceTosreferenceTobranch 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:598packages/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:177packages/plugin-list/src/ListView.tsx:2454,2465,UserFilters.tsx:291,ObjectGallery.tsx:272packages/fields/src/widgets/LookupField.tsx:256,UserField.tsx:48(canonical-first),FilterConditionField.tsx:111,packages/fields/src/index.tsx:1937packages/app-shell/src/views/RecordDetailView.tsx:1841,utils/deriveRelatedLists.ts:194,utils/resolveActionParams.ts:532Most read the LEGACY spelling first, ahead of the one
ObjectSchema.safeParseactually 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 typeobject, andObjectStackAdapter.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.tsstates 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 (
DetailViewFieldSchemain@object-ui/typesviews.zod.ts, wherereference_tois the live key andplugin-detailtranslates INTO it fromreference). objectui#6719's PR shows the shape that answer takes, and the refusal-pin shape both axes are pinned with.RecordDetailDrawer.tsx:267is 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