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
Five more consumer-side reads of the undeclared object-level titleField survive #6531 — in ObjectView view-config fallbacks and a useRecordSearch memo key #6557
Filed unassigned by the dev seat working objectui#6531 (session session_011SfZeFWrhGLHmfq61xbz4q), out of a file face that did not include either file. Duplicate scan before filing: 244 open objectui issues enumerated via the REST list endpoint (3 pages, page 3 short — full population, not a truncated read) and grepped for titleField / record-title / nameField / displayNameField / getRecordDisplayName / display name; the only hit is #6531 itself (positive control), and a path-level grep for ObjectView.tsx / useRecordSearch surfaced only #6482, #6460, #4730 and #2890, none of which is about this key.
What #6531 settled, and what it deliberately left standing
#6531 removed getRecordDisplayName's step-0 read of objectDef.titleField after a producer census found nothing that can produce the key. The measurement it turned on is stronger than "undeclared": @objectstack/spec's object schema is a strictObject, so
ObjectSchema.safeParse({ name: 'account', fields: {…}, titleField: 'name' })
→ REJECTED unrecognized_keys: Unrecognized key(s) on this object: `titleField`
— the same issue code a nonsense key gets — while nameField, displayNameField and titleFormat all parse and survive (measured against @objectstack/spec@17.2.0, the dist this repo installs).
That card's file face was packages/core/src/utils/record-title.ts only. The same undeclared key is read in six more places, and they were left untouched because each one needs a decision the record-title card did not carry.
The remaining reads
packages/app-shell/src/views/ObjectView.tsx — five sites, all of the form view's own declared key, else the object's undeclared one, else the literal 'name':
o is an object definition from the app's metadata, so the titleField half of every entry is permanently ''. Not a wrong answer, but a key in a cache signature that can never vary — and it is the last thing in the repo that reads like evidence some producer supplies the key.
packages/react/src/hooks/__tests__/useRecordSearch.test.ts:11 — the fixture { name: 'account', label: 'Account', titleField: 'name' }. Same phantom shape #6531 retired inside record-title.test.ts: the assertion it feeds resolves identically with the key deleted, so it pins nothing while reading as a producer.
The ObjectView sites are not the same edit. Deleting the middle leg changes what a view is configured with, and the honest replacement is a judgement the record-title census does not settle:
Re-point it at the declared pointer.viewDef.<type>.titleField || objectDef?.nameField || 'name'. Arguably what the code always meant: nameField is ADR-0079's canonical record-title pointer and is what getRecordDisplayName now reads at the top of its object ladder. But this widens what these five sites consult, and the 'name' literal underneath is itself a forge of the kind objectui#5953 removed from ObjectMap — worth deciding deliberately rather than by analogy.
Hand the whole decision to the resolver, as ObjectMap already does, and stop binding a field name at this seam at all (the shape objectui#6343 restored one seam up).
Options 1 and 2 differ observably; option 3 is a larger refactor. Someone should pick, not infer.
The useRecordSearch signature line and its fixture are mechanical once that choice is made, and belong in the same PR so the key leaves the repo in one move.
Verification notes for whoever takes this
packages/app-shell and packages/react both resolve @object-ui/core through the root vitest.config.mts alias table (→ packages/core/src), so consumer tests exercise resolver source directly; no dist build is needed to see a precedence change.
Refs: objectui#6531 (the census and the resolver-side removal) · ADR-0079 · AGENTS.md Commandment #0.1.
Filed unassigned by the dev seat working objectui#6531 (session
session_011SfZeFWrhGLHmfq61xbz4q), out of a file face that did not include either file. Duplicate scan before filing: 244 open objectui issues enumerated via the REST list endpoint (3 pages, page 3 short — full population, not a truncated read) and grepped fortitleField/record-title/nameField/displayNameField/getRecordDisplayName/display name; the only hit is #6531 itself (positive control), and a path-level grep forObjectView.tsx/useRecordSearchsurfaced only #6482, #6460, #4730 and #2890, none of which is about this key.What #6531 settled, and what it deliberately left standing
#6531 removed
getRecordDisplayName's step-0 read ofobjectDef.titleFieldafter a producer census found nothing that can produce the key. The measurement it turned on is stronger than "undeclared":@objectstack/spec's object schema is astrictObject, so— the same issue code a nonsense key gets — while
nameField,displayNameFieldandtitleFormatall parse and survive (measured against@objectstack/spec@17.2.0, the dist this repo installs).That card's file face was
packages/core/src/utils/record-title.tsonly. The same undeclared key is read in six more places, and they were left untouched because each one needs a decision the record-title card did not carry.The remaining reads
packages/app-shell/src/views/ObjectView.tsx— five sites, all of the form view's own declared key, else the object's undeclared one, else the literal'name':titleField: viewDef?.timeline?.titleField || objectDef?.titleField || 'name'titleField: viewDef.kanban?.titleField || objectDef.titleField || 'name'titleField: viewDef.map?.titleField || objectDef.titleField || 'name'titleField: viewDef.gallery?.titleField || objectDef.titleField || 'name'labelField: (viewDef as any).tree?.labelField || (viewDef as any).tree?.titleField || objectDef.titleField || 'name'packages/react/src/hooks/useRecordSearch.ts:191— the memo signature that decides when the search fanout re-runs:ois an object definition from the app's metadata, so thetitleFieldhalf of every entry is permanently''. Not a wrong answer, but a key in a cache signature that can never vary — and it is the last thing in the repo that reads like evidence some producer supplies the key.packages/react/src/hooks/__tests__/useRecordSearch.test.ts:11— the fixture{ name: 'account', label: 'Account', titleField: 'name' }. Same phantom shape #6531 retired insiderecord-title.test.ts: the assertion it feeds resolves identically with the key deleted, so it pins nothing while reading as a producer.Why this is a card and not a rider on #6531
The
ObjectViewsites are not the same edit. Deleting the middle leg changes what a view is configured with, and the honest replacement is a judgement the record-title census does not settle:viewDef.<type>.titleField || 'name'. Simplest, and consistent withgetRecordDisplayNamestep 0 readsobjectDef.titleField— a key@objectstack/spec's object schema does not declare — and ranks it ABOVE the canonicalnameField#6531 — but it changes the literal fallback for any object that (illegally) carried the key.viewDef.<type>.titleField || objectDef?.nameField || 'name'. Arguably what the code always meant:nameFieldis ADR-0079's canonical record-title pointer and is whatgetRecordDisplayNamenow reads at the top of its object ladder. But this widens what these five sites consult, and the'name'literal underneath is itself a forge of the kind objectui#5953 removed fromObjectMap— worth deciding deliberately rather than by analogy.ObjectMapalready does, and stop binding a field name at this seam at all (the shape objectui#6343 restored one seam up).Options 1 and 2 differ observably; option 3 is a larger refactor. Someone should pick, not infer.
The
useRecordSearchsignature line and its fixture are mechanical once that choice is made, and belong in the same PR so the key leaves the repo in one move.Verification notes for whoever takes this
packages/app-shellandpackages/reactboth resolve@object-ui/corethrough the rootvitest.config.mtsalias table (→packages/core/src), so consumer tests exercise resolver source directly; nodistbuild is needed to see a precedence change.Refs: objectui#6531 (the census and the resolver-side removal) · ADR-0079 · AGENTS.md Commandment #0.1.
Generated by Claude Code
Generated by Claude Code