Fix catalog/base/skills/openrouter search returning zero results#5388
Fix catalog/base/skills/openrouter search returning zero results#5388richardhjtan wants to merge 2 commits into
Conversation
The `item` resource in a search-entry response inherited its id directly from the stored pristine_doc, which realms with a registered alias prefix (catalog, base, skills, openrouter) store in unresolved alias form (e.g. @cardstack/catalog/...) for storage portability. The item's search-entry relationship, however, always points at the row's resolved absolute URL. The mismatched ids meant a strict JSON:API (type, id) lookup on the consuming side never found the included item, so searches against these realms silently returned zero results. Set the item's id/links.self to the same resolved URL the relationship already uses.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ab5c18f742
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| id: cardUrl as RealmResourceIdentifier, | ||
| links: { self: cardUrl }, |
There was a problem hiding this comment.
Normalize loadLinks root identities consistently
When this path is used through Realm.searchEntries, loadLinks is enabled by default (packages/runtime-common/realm.ts:5393-5395). For registered-prefix realms, this new resolved id means the roots are placed in loadLinks's visited/omit sets as resolved URLs, while fetched linked resources and relationshipIdStr are still compared in unresolved alias form (visited.has(linkResource.id), omitSet.has(entry.relationshipIdStr)). If a full item links to itself or to another card that is already a search result, loadLinks no longer recognizes that root and can add the same logical card again under the alias id and rewrite the relationship to that alias, leaving duplicate/mismatched identities in the search-entry document. Normalize both the root ids and the loadLinks comparison keys to the same form when overriding the item id here.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
[Claude Code 🤖] Good catch, confirmed and fixed in 95f05d3. The item's id override left loadLinks's visited/omitSet comparing resolved-URL roots against alias-form ids elsewhere in the same pass. Fixed by indexing both spellings of each root via VirtualNetwork.equivalentURLForms so either form matches.
There was a problem hiding this comment.
Pull request overview
Fixes a JSON:API identity mismatch in search-entry results for realms that store pristine_doc.id in registered-alias form (e.g. @cardstack/catalog/...). The projection engine now ensures the included item resource uses the same resolved URL (cardUrl) as the search-entry id and the item relationship, allowing consumers that hydrate via strict (type, id) matching on included to find the item.
Changes:
- Set included
item.idanditem.links.selfto the resolvedcardUrlinstead of the storedpristine_doc.id. - Add a regression test that simulates an alias-form stored
pristine_doc.idand asserts the included item is still keyed by the resolved id.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/runtime-common/realm-index-query-engine.ts | Forces included item resources to use cardUrl for id/links.self so JSON:API relationship hydration matches. |
| packages/realm-server/tests/search-entries-engine-test.ts | Adds coverage for the alias-stored-pristine_doc.id case to prevent regressions in search-entry item hydration. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Overriding the search-entry item's id to the resolved cardUrl (previous commit) left loadLinks comparing that against alias-form ids elsewhere in the same pass: a fetched linked resource's own id, and relationshipIdStr, both stay in registered-alias form for storage portability. A root that links to itself, or to another card already present as a search result, was no longer recognized as visited/omitted under its alias spelling, risking a duplicate included entry under a mismatched id. Index both the resolved and alias spellings of each omitted/visited root via VirtualNetwork.equivalentURLForms so either form matches.
Summary
itemresource inherited its id straight from the storedpristine_doc, which realms with a registered alias prefix (catalog, base, skills, openrouter) store in unresolved alias form (e.g.@cardstack/catalog/...) for storage portability across environments.(type, id)lookup onincluded(e.g. the host's search hydration) silently found nothing, so any search requestingfields[search-entry]=itemagainst these realms returned zero hydrated results despite the backend having correct, fully-indexed data.boxel_indexand found the same id mismatch present across a majority of instance rows in the catalog/base/skills/openrouter realms there.id/links.selfto the same resolved URL its relationship already uses, instead of trusting whatever form happened to be in storage.Test plan
pristine_doc.idand asserts the served item's id still matches its relationshiptsc --noEmitclean on the changed filesearch-entries-engine-test.ts(blocked locally by sandbox disk space; needs a clean re-run)🤖 Generated with Claude Code