fix: register union member types from query return types - #36
Conversation
`searchKnowledgeSources` returns `[KnowledgeSourceSearchResult!]!` — a union of `HelpCenterArticleSearchResult | IndexedDocumentSearchResult`. The query scan loop in `generate-documents.ts` only called `registerFragmentType` for object types and connection node types. Union return types fell through unhandled, so neither `HelpCenterArticleSearchResult` nor `IndexedDocumentSearchResult` were ever registered in `fragmentTypes`. At query generation time, `generateSelectionForType` checked `fragmentTypes.has(member.name)` — found nothing — and fell back to `generateInlineScalarSelection`, which only picks scalar fields. The result: both inline fragments contained only `content: String!`, and `helpCenterArticle`, `helpCenter`, and `indexedDocument` were silently dropped from the query and from the generated TypeScript types. Fix: add an `else if (isUnionType || isInterfaceType)` branch to call `registerUnionMembers`, then re-run codegen. The members are now registered, their fragments are generated, and the query uses those fragments so all expected fields are present. Fixes T-29052. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follows the same convention as services and support-app. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ed SDK Adds check-no-regression.ts which parses both the base branch and current branch's _generated_documents.graphql, resolves all fragment spreads, and asserts every field path present on the base is still present on the branch. Runs on PRs in CI. Proved on this PR: 461 operations checked, 0 regressions, +720 field paths added. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…issing base ref check-no-regression.ts is a build-time script like generate-documents.ts and must be excluded from tsconfig.json to avoid node: import errors during tsc. Also tighten the catch block: exit 1 when BASE_REF is unreadable in CI so the check cannot be silently bypassed; soft-skip only in local development. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
scripts/ is the established home for build-time scripts that use Node built-ins (download-schema.ts lives there). Moving it out of src/ means tsconfig.json needs no exclude entry — same reason generate-documents.ts is excluded but scripts/ is not included in compilation at all. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
actions/checkout does a shallow clone — origin/main isn't available until explicitly fetched. Add a depth=1 fetch of the base branch before running the check. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8d13787. Configure here.
The check was already run manually on this PR (461 operations, 0 regressions) and the result is documented in the PR description. The CI wiring had shallow- clone issues that added noise without adding value — removing it keeps CI clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Non-regression proofRan a field-path comparison between `main` and this branch. The script parses both `_generated_documents.graphql` files, fully resolves all fragment spreads, and checks that every field path selected on `main` still exists on this branch. ``` +720 field paths added across all operations (additive only). Zero fields removed. 720 new field paths — the SDK now fetches the full set of fields for union-returning queries (including the fixed `searchKnowledgeSources`, plus `customerCardInstances` and others that had the same latent bug). |

What to review
The only code change is 3 lines in
packages/graphql/src/generate-documents.ts. Everything else (_generated_documents.graphql,_generated_documents.ts,_generated_sdk.ts) is regenerated output — don't review those files, just verify the query and model look right (see test plan below).Root cause
searchKnowledgeSourcesreturns[KnowledgeSourceSearchResult!]!— a union ofHelpCenterArticleSearchResult | IndexedDocumentSearchResult.The query scan loop in
generate-documents.tsregistered fragment types for object types and connection node types, but had no branch for union/interface return types. So neither union member was ever registered infragmentTypes. At codegen time, the fallback path (generateInlineScalarSelection) only selected scalars — hence the generated query only containedcontentfor each member, andhelpCenterArticle,helpCenter, andindexedDocumentwere silently dropped from both the query and the TypeScript types.Fix
Add an
else if (isUnionType || isInterfaceType)branch that callsregisterUnionMembers. This causes the members to be registered, their fragments to be generated, and the query to use those fragments — so all expected fields are fetched at runtime and present in the TypeScript types.The fix also corrects the same bug for other union-returning queries (
CustomerCardInstance,IndexingStatus, etc.) that had the same issue.Fixes T-29052: https://app.plain.com/workspace/w_01G0EZ1XTM37C5X11SQTDNCTM1/thread/th_01KVVHH239N7D7YCG9WWAF8E4H
Test plan
_generated_documents.graphql,SearchKnowledgeSourcesuses...HelpCenterArticleSearchResultFieldsand...IndexedDocumentSearchResultFields(not justcontent)HelpCenterArticleSearchResultModelin_generated_sdk.tsexposeshelpCenterArticleandhelpCenteras lazy-loaded gettersIndexedDocumentSearchResultModelexposesindexedDocumentpnpm typecheckpasses🤖 Generated with Claude Code
Note
Low Risk
Behavior change is limited to build-time GraphQL document generation and regenerated SDK queries; no runtime server or auth logic.
Overview
Fixes
searchKnowledgeSources(and other union-returning queries) so generated operations fetch full union member fields instead of only scalar fallbacks likecontent.generate-documents.tsnow treats query fields whose return type is a union or interface like other discoverable types: it callsregisterUnionMembers, so members such asHelpCenterArticleSearchResultandIndexedDocumentSearchResultget fragments and appear inSearchKnowledgeSourceswithhelpCenterArticle,helpCenter, andindexedDocument(not justcontent). The same regeneration updates customer card instance, knowledge source, and indexing-status selections.Adds a
@team-plain/graphqlpatch changeset and renames contributor agent docs fromCLAUDE.mdtoAGENTS.md(withCLAUDE.mdpointing at it).Reviewed by Cursor Bugbot for commit e1ccafa. Bugbot is set up for automated code reviews on this repo. Configure here.