Uh oh!
There was an error while loading. Please reload this page.
fix(metadata-protocol): title global-search hits from the canonical nameField, not only the deprecated alias - #8809
Conversation
…8786) `searchAll`'s `renderTitle` opened its candidate list with `obj.displayNameField` alone — the ADR-0079 DEPRECATED alias. The canonical pointer is `nameField`, and `provisionPrimary` (the designation seat the SchemaRegistry runs on every object at registration) stamps `nameField` only, never the alias. So an object that declared its primary title canonically fell through the candidate list to `String(row.id)` and the palette showed a raw id. Reads `obj.nameField ?? obj.displayNameField` instead — the spelling `resolveDisplayField`, the #4254 ingress gate, and this same function's search-field resolution 44 lines below already use. Presentation only: #7643's recall half is untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XeQRiAa7vYRVX5Fog7Zby8
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XeQRiAa7vYRVX5Fog7Zby8
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 3 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also reference the affected code. These are read-only:
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#8786
searchAll— the global-search (⌘K) palette — resolved a hit's title from a candidate list that opened withobj.displayNameFieldalone. Under ADR-0079nameFieldis the canonical primary-title pointer anddisplayNameFieldis the deprecated alias, so this was the one consumer a canonical designation could not reach.Why it was reachable, not theoretical
provisionPrimary— the ADR-0079 designation seat the SchemaRegistry runs on every object at registration — stampsnameFieldonly, never the alias:So an object that declared its primary title canonically, without also carrying the deprecated alias, produced
undefinedfor that entry, the entry was filtered out of the candidate list, and the title fell through toreturn String(row.id)— the palette showing a raw record id where the object's own declared, populated title existed.Impact was bounded to objects whose primary title is outside
name/full_name/title/subject/label/company; anything in that conventional list already resolved through the later entries, which is why this stayed invisible.The change
One line, plus the doc comment directly above it that described the old order:
That is the spelling the rest of the platform already uses —
resolveDisplayFieldin@objectstack/spec, the #4254 ingress gate, and this same function's own search-field resolution 44 lines below (displayField: obj.nameField ?? obj.displayNameField). A fourth spelling here would have re-split what those merged.Precedence, measured rather than assumed
If an object carries both pointers naming different fields, this flips which one wins — so I measured the repo before calling it safe. Scanning every
displayNameFielddeclaration inpackages,examplesandapps(52 files, 38 declarations with a co-locatednameField):[ADR-0079] canonical primary-title pointer (mirrors deprecated displayNameField)comment.nameFieldas the winner.resolveDisplayField({ nameField: 'a', displayNameField: 'b' })returns'a', pinned indisplay-name.test.tsas "prefers nameField over displayNameField over derivation".No real object is in the disagreeing state, and the precedence landed on is the platform's existing answer rather than a new one. It is now pinned here too.
Tests
New file
packages/metadata-protocol/src/protocol.search-title-namefield.test.ts— 6 cases. The fixtures use non-conventional title fields (company_name,ref_no,ref_code), since a conventional one would pass identically before and after.nameField: 'company_name', no alias, populated row, title isAcme Industrialand notacc_1;name, with no pointer at all, still titles correctly (a short-circuit rewrite would pass the pin and break this);nameFieldwins;titleFormatstill outranks the pointer.Reverse verification, direction predicted before running and observed as predicted: restoring
obj.displayNameField,alone turns exactly 2 of 6 red, with the defect's own signature —The 4 that stay green are the controls, which by design do not discriminate this fix. The fix was committed before the ablation and restored with
git checkoutfrom that commit (git statusclean afterwards).Verification
All at HEAD
cd974da6e(after the merge oforigin/main, which is the final commit):pnpm --filter @objectstack/metadata-protocol test— 92 files, 1375 tests, all passingnode scripts/pm/dispatch-gates.mjs, all green:check:nul-bytes,check:cross-package-test-inputs,check:durability-log-level,check:filter-alias-parity,check:changeset-gate-self-tests,check:objectui-changeset,check:query-options-erasure,check:engine-double-contract,check:type-check-coverage,check:type-check-debt.changesetfamilies pluscheck:query-options-erasure/ the type-check pair, triggered by adding a test file).check:type-check-debt --re-measurewas run over the built workspace closure —@objectstack/metadata-protocolsits in the DEBT ledger, so a new test file genuinely moves it: "33 ledger entries re-measured, 1926 raw tsc errors total, none above its recorded number."Scope
Presentation only. #7643 addressed recall (which rows come back) and deliberately left titling alone; that contract stays untouched here, and its pins in
protocol.search-case-fold.test.tsstill pass. Search-field resolution, the object sweep, caps and ordering are unmodified. Region held:renderTitleinsidesearchAll. No other region ofprotocol.tswas touched, so the concurrent work inauditMetaItemanddiffMetaItemis unaffected.Generated by Claude Code