Measured while implementing #5692 (the two plugin-dashboard copies). Out of that card's fence, which is the two plugin-dashboard files plus their tests — filed rather than widened into a cross-package diff.
What is there
@object-ui/core's EXPANDABLE_FIELD_TYPES (packages/core/src/utils/expand-fields.ts) is the published reference-bearing field family. Four MORE faces restate it inline, none deriving from it and none pinned against it:
| file | the restatement |
|---|
packages/plugin-kanban/src/ObjectKanban.tsx:346 | def?.type === 'lookup' || def?.type === 'master_detail' || def?.type === 'reference' |
packages/plugin-detail/src/RecordDetailDrawer.tsx:227 | def.type === 'lookup' || def.type === 'master_detail' || def.type === 'reference' |
packages/plugin-detail/src/HeaderHighlight.tsx:147 | resolvedType === 'reference' || resolvedType === 'lookup' || resolvedType === 'master_detail' (inside a wider isWide disjunction) |
packages/app-shell/src/utils/resolveActionParams.ts:489 | resolvedType === 'lookup' || resolvedType === 'reference' |
Why it is not merely duplication — every one of them diverges in BOTH directions
| core | these four |
|---|
lookup | yes | yes |
master_detail | yes | yes (3 of 4; resolveActionParams omits it) |
user | yes | no |
tree | yes | no |
reference | no | yes |
Two concrete consequences, same shape #4790 recorded for the form layer:
Deliberately NOT this issue
Direction
Same treatment as #4770 / #4790 / #4815 / #5312 / #5692: read EXPANDABLE_FIELD_TYPES and carry an identity pin (a spy on its .has) so a member-identical private copy fails rather than quietly re-forking. Each face needs its own call on whether gaining user / tree is the intended behaviour there — on the four above it looks like restoration rather than widening, but that is a per-face judgement and this card does not pre-empt it. Do NOT copy the set.
Related: #4770, #4790, #4815, #5312, #5692, #5654, #4914.
Generated by Claude Code
Measured while implementing #5692 (the two
plugin-dashboardcopies). Out of that card's fence, which is the twoplugin-dashboardfiles plus their tests — filed rather than widened into a cross-package diff.What is there
@object-ui/core'sEXPANDABLE_FIELD_TYPES(packages/core/src/utils/expand-fields.ts) is the published reference-bearing field family. Four MORE faces restate it inline, none deriving from it and none pinned against it:packages/plugin-kanban/src/ObjectKanban.tsx:346def?.type === 'lookup' || def?.type === 'master_detail' || def?.type === 'reference'packages/plugin-detail/src/RecordDetailDrawer.tsx:227def.type === 'lookup' || def.type === 'master_detail' || def.type === 'reference'packages/plugin-detail/src/HeaderHighlight.tsx:147resolvedType === 'reference' || resolvedType === 'lookup' || resolvedType === 'master_detail'(inside a widerisWidedisjunction)packages/app-shell/src/utils/resolveActionParams.ts:489resolvedType === 'lookup' || resolvedType === 'reference'Why it is not merely duplication — every one of them diverges in BOTH directions
lookupmaster_detailresolveActionParamsomits it)usertreereferenceTwo concrete consequences, same shape #4790 recorded for the form layer:
useris missing from all four. Ausercolumn carries the same foreign-key storage aslookupand resolves through the same expand path (the reason fix(core): $expand user/tree reference columns in list & grid views (not just lookup/master_detail) #2032 put it in the family). On these faces it is not treated as a relation.referenceis present in all four, and no producer can emit it. Measured on finding(plugin-dashboard): two more private copies of the reference-bearing field family — #5312's "LAST private copy" claim is false #5692's branch against@objectstack/spec's closedFieldTypevocabulary, withlookup/master_detail/user/treeas live controls and the retiredownerplus a nonsense spelling as dead ones:referenceis absent from the vocabulary andFieldSchema.safeParse({ type: 'reference' })is refused. It sits at exactly the levelownersat at beforeownerwidget 拿不到表单下发的 dataSource,而 plugin-grid 认为它需要 —— 且owner根本不在 spec 的 FieldType 里(enforce-or-remove 待判) #4814 retired it. So these four branches are dead weight that reads as live capability.Deliberately NOT this issue
packages/app-shell/src/views/ActionParamDialog.tsx:351— a different rule (degraded-hint, not reference-bearing) and already filed as finding(app-shell):ActionParamDialog'sisLookupParamrestates the picker family over RAW param spellings, so a degradedmaster_detailparam loses the #3405 affordances #5654.plugin-dashboardcopies — finding(plugin-dashboard): two more private copies of the reference-bearing field family — #5312's "LAST private copy" claim is false #5692.Direction
Same treatment as #4770 / #4790 / #4815 / #5312 / #5692: read
EXPANDABLE_FIELD_TYPESand carry an identity pin (a spy on its.has) so a member-identical private copy fails rather than quietly re-forking. Each face needs its own call on whether gaininguser/treeis the intended behaviour there — on the four above it looks like restoration rather than widening, but that is a per-face judgement and this card does not pre-empt it. Do NOT copy the set.Related: #4770, #4790, #4815, #5312, #5692, #5654, #4914.
Generated by Claude Code