Context
test:pr (the canonical pre-PR gate, mirrored by the PR CI workflow) runs:
nx affected --targets=test:sherif,test:knip,test:docs,test:eslint,test:lib,test:types,test:build,build --exclude=examples/**,testing/**
The --exclude=examples/**,testing/** carve-out means test:types never typechecks the example apps or the testing/ packages (testing/e2e, testing/panel). This leaves a real hole: a type regression that only manifests at a call site is invisible to CI when the only call sites live in the excluded folders.
Motivating repro (real bug, found by hand during a rebase, not by CI)
grokSummarize(...) is not assignable to summarize()'s adapter param for any current Grok model (grok-4.3, grok-build-0.1):
Type 'ChatStreamSummarizeAdapter<"grok-4.3", GrokTextProviderOptions>' is not assignable to
'SummarizeAdapter<string, object>'.
Types of property 'summarize' are incompatible.
... Type 'SummarizationOptions<object>' is not assignable to 'SummarizationOptions<GrokTextProviderOptions>'.
Type 'object' is not assignable to type 'GrokTextProviderOptions'.
Root cause: SummarizeAdapter.summarize is declared as a property (arrow type), so under strictFunctionTypes its parameter is checked contravariantly. Assignability to the constraint SummarizeAdapter<string, object> therefore reduces to "is object assignable to TProviderOptions?". GrokTextProviderOptions extends Record<string, unknown> (it carries an index signature), and object is not assignable to Record<string, unknown> — so it fails. OpenAI's options are all-optional with no index signature, so object is assignable and it passes. (Separate fix tracked for the Grok options shape; this issue is about the CI gap.)
Why test:pr doesn't catch it
Two factors compound:
- The error only exists at a
summarize({ adapter }) call site. The constraint TAdapter extends SummarizeAdapter<string, object> is only instantiated when summarize() is actually called with a concrete adapter. Merely constructing the adapter typechecks fine — which is all packages/ai-grok/tests/grok-adapter.test.ts does (asserts .kind, never calls summarize()). So the ai-grok package's own test:types stays green.
- The only real call sites are in excluded folders.
testing/e2e/src/routes/api.summarize.ts and testing/panel/src/routes/api.summarize.ts pass a Grok summarize adapter into summarize() — but testing/** is excluded from test:types. (testing/panel also casts grokSummarize(model as any), which would mask it there regardless.)
Net result: nothing in the affected + included set ever instantiates the constraint, so the regression sails through CI.
Proposal
Extend type-checking to the currently-excluded surfaces so call-site regressions are caught:
Acceptance
- CI fails if an example or
testing/ package has a type error.
- The Grok summarize call-site regression above is caught by CI (via example/testing coverage and/or the in-package call-site assertion).
Related
Context
test:pr(the canonical pre-PR gate, mirrored by thePRCI workflow) runs:The
--exclude=examples/**,testing/**carve-out meanstest:typesnever typechecks the example apps or thetesting/packages (testing/e2e,testing/panel). This leaves a real hole: a type regression that only manifests at a call site is invisible to CI when the only call sites live in the excluded folders.Motivating repro (real bug, found by hand during a rebase, not by CI)
grokSummarize(...)is not assignable tosummarize()'sadapterparam for any current Grok model (grok-4.3,grok-build-0.1):Root cause:
SummarizeAdapter.summarizeis declared as a property (arrow type), so understrictFunctionTypesits parameter is checked contravariantly. Assignability to the constraintSummarizeAdapter<string, object>therefore reduces to "isobjectassignable toTProviderOptions?".GrokTextProviderOptions extends Record<string, unknown>(it carries an index signature), andobjectis not assignable toRecord<string, unknown>— so it fails. OpenAI's options are all-optional with no index signature, soobjectis assignable and it passes. (Separate fix tracked for the Grok options shape; this issue is about the CI gap.)Why
test:prdoesn't catch itTwo factors compound:
summarize({ adapter })call site. The constraintTAdapter extends SummarizeAdapter<string, object>is only instantiated whensummarize()is actually called with a concrete adapter. Merely constructing the adapter typechecks fine — which is allpackages/ai-grok/tests/grok-adapter.test.tsdoes (asserts.kind, never callssummarize()). So theai-grokpackage's owntest:typesstays green.testing/e2e/src/routes/api.summarize.tsandtesting/panel/src/routes/api.summarize.tspass a Grok summarize adapter intosummarize()— buttesting/**is excluded fromtest:types. (testing/panelalso castsgrokSummarize(model as any), which would mask it there regardless.)Net result: nothing in the affected + included set ever instantiates the constraint, so the regression sails through CI.
Proposal
Extend type-checking to the currently-excluded surfaces so call-site regressions are caught:
test:typesoverexamples/**andtesting/**in CI (either drop them from the--excludefor thetest:typestarget specifically, or add a dedicatedtest:types:integrationtarget/job that covers them). Examples aren't built by Nx today, so this likely needs project-leveltest:typeswiring for the example apps.test:build,build,test:lib) excluded for examples if desired — the gap here is specifically types, which are cheap to check and high-value for a library that sells type safety.packages/ai-grok/tests/:Acceptance
testing/package has a type error.Related
…/srcand skipped examples/tests — this issue closes that complementary gap).