fix(sql-orm-client): selectIncludeStrategy reads namespaced capability flags#425
fix(sql-orm-client): selectIncludeStrategy reads namespaced capability flags#425
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughRefactors include-strategy capability detection to use a new capabilityFlag(contract, flag) helper that reads boolean flags from contract.capabilities[targetFamily] and contract.capabilities[target]. Tests and fixtures were updated to provide namespaced boolean capability shapes and to exercise the revised lookup semantics. ChangesNamespace-Aware Capability Detection & Test Adaptation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/middleware-telemetry
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/emitter
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/3-extensions/sql-orm-client/src/include-strategy.ts (1)
50-55: 💤 Low valueOptional: tighten
flagto a literal union.
flag: stringis loose — only'lateral'and'jsonAgg'are ever passed today. Constraining it would document the supported flag set and prevent accidental drift if someone adds a third flag.♻️ Suggested signature
-function capabilityFlag(contract: Contract<SqlStorage>, flag: string): boolean { +function capabilityFlag(contract: Contract<SqlStorage>, flag: 'lateral' | 'jsonAgg'): boolean {🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/3-extensions/sql-orm-client/src/include-strategy.ts` around lines 50 - 55, The capabilityFlag function accepts a loose flag: string; tighten it to a literal union of the supported flags (e.g., 'lateral' | 'jsonAgg') so callers cannot pass arbitrary strings. Update the function signature (capabilityFlag) to use the literal union type for the flag parameter and adjust any callers or tests that pass flags to use one of 'lateral' or 'jsonAgg'; ensure the property lookups contract.capabilities[...][flag] still type-check with the new narrower type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/3-extensions/sql-orm-client/src/include-strategy.ts`:
- Around line 50-55: The capabilityFlag function accepts a loose flag: string;
tighten it to a literal union of the supported flags (e.g., 'lateral' |
'jsonAgg') so callers cannot pass arbitrary strings. Update the function
signature (capabilityFlag) to use the literal union type for the flag parameter
and adjust any callers or tests that pass flags to use one of 'lateral' or
'jsonAgg'; ensure the property lookups contract.capabilities[...][flag] still
type-check with the new narrower type.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 3c29ce1b-2d33-43a4-b1dd-e051877fb1e9
📒 Files selected for processing (4)
packages/3-extensions/sql-orm-client/src/include-strategy.tspackages/3-extensions/sql-orm-client/test/collection-dispatch.test.tspackages/3-extensions/sql-orm-client/test/include-strategy.test.tspackages/3-extensions/sql-orm-client/test/integration/include.test.ts
3530713 to
c600e7f
Compare
b7ac2c6 to
ca015a3
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/3-extensions/sql-orm-client/test/integration/include.test.ts (1)
45-58: ⚡ Quick winReuse
withCapabilities()here instead of a loose local override helper.This helper accepts
Record<string, unknown>and then casts the result back to the base contract, so a future test can quietly drift back to stale capability fixtures while still looking valid. Reusing the sharedwithCapabilities()helper here would keep the integration tests locked to the emitted boolean-map shape this PR is guarding.As per coding guidelines, "Try to minimize type casts. Instead, prefer explicit types that would make type casts unnecessary."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/3-extensions/sql-orm-client/test/integration/include.test.ts` around lines 45 - 58, Replace the local loose capability override in createUsersCollectionWithCapabilities with the shared withCapabilities helper: change the capabilities parameter from Record<string, unknown> to the exact shape produced by withCapabilities (use ReturnType<typeof withCapabilities>), call withCapabilities(...) to produce the capability map, and construct the contract using { ...base, capabilities: withCapabilities(capabilities) } (or simply assign the returned boolean-map) instead of casting to typeof base; update usages of createUsersCollectionWithCapabilities accordingly and remove the unnecessary type cast and comment about merging. Ensure you reference getTestContract, createUsersCollectionWithCapabilities, and withCapabilities while making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/3-extensions/sql-orm-client/test/integration/include.test.ts`:
- Around line 45-58: Replace the local loose capability override in
createUsersCollectionWithCapabilities with the shared withCapabilities helper:
change the capabilities parameter from Record<string, unknown> to the exact
shape produced by withCapabilities (use ReturnType<typeof withCapabilities>),
call withCapabilities(...) to produce the capability map, and construct the
contract using { ...base, capabilities: withCapabilities(capabilities) } (or
simply assign the returned boolean-map) instead of casting to typeof base;
update usages of createUsersCollectionWithCapabilities accordingly and remove
the unnecessary type cast and comment about merging. Ensure you reference
getTestContract, createUsersCollectionWithCapabilities, and withCapabilities
while making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: bc885ef3-04c2-414c-851d-3b5d6156860b
📒 Files selected for processing (6)
packages/3-extensions/sql-orm-client/src/include-strategy.tspackages/3-extensions/sql-orm-client/test/collection-dispatch.test.tspackages/3-extensions/sql-orm-client/test/collection-fixtures.tspackages/3-extensions/sql-orm-client/test/helpers.tspackages/3-extensions/sql-orm-client/test/include-strategy.test.tspackages/3-extensions/sql-orm-client/test/integration/include.test.ts
ca015a3 to
8c98e73
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/3-extensions/sql-orm-client/test/integration/include.test.ts (1)
47-58: ⚡ Quick winTighten capability fixture typing to avoid cast-masked test mistakes.
Record<string, unknown>plusas typeof basecan silently accept malformed capability shapes. Narrowing this to the contract capability type (or usingwithCapabilities) makes fixture mistakes fail fast.Proposed refactor
-import { getTestContext, getTestContract, isSelectAst } from '../helpers'; +import { getTestContext, getTestContract, isSelectAst, withCapabilities } from '../helpers'; function createUsersCollectionWithCapabilities( runtime: Parameters<typeof createUsersCollection>[0], - capabilities: Record<string, unknown>, + capabilities: ReturnType<typeof getTestContract>['capabilities'], ) { const base = getTestContract(); - const contract = { - ...base, - capabilities, - } as typeof base; + const contract = withCapabilities(base, capabilities); const context = { ...getTestContext(), contract }; return new Collection({ runtime, context }, 'User'); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/3-extensions/sql-orm-client/test/integration/include.test.ts` around lines 47 - 58, The test fixture accepts capabilities as Record<string, unknown> and then force-casts the merged object to typeof base, which can mask malformed capability shapes; change the parameter type from Record<string, unknown> to the concrete capability type (e.g., typeof getTestContract().capabilities or the exported ContractCapabilities type) and remove the unsafe `as typeof base` cast when creating `contract`; alternatively call the helper `withCapabilities` (or equivalent test factory) to produce a properly-typed contract so that malformed capability shapes fail at compile time instead of being silenced by a cast (refer to getTestContract, contract, and withCapabilities in the diff).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/3-extensions/sql-orm-client/test/integration/include.test.ts`:
- Around line 47-58: The test fixture accepts capabilities as Record<string,
unknown> and then force-casts the merged object to typeof base, which can mask
malformed capability shapes; change the parameter type from Record<string,
unknown> to the concrete capability type (e.g., typeof
getTestContract().capabilities or the exported ContractCapabilities type) and
remove the unsafe `as typeof base` cast when creating `contract`; alternatively
call the helper `withCapabilities` (or equivalent test factory) to produce a
properly-typed contract so that malformed capability shapes fail at compile time
instead of being silenced by a cast (refer to getTestContract, contract, and
withCapabilities in the diff).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 046ed3d7-0ff8-4344-b247-6b9bb1764891
📒 Files selected for processing (6)
packages/3-extensions/sql-orm-client/src/include-strategy.tspackages/3-extensions/sql-orm-client/test/collection-dispatch.test.tspackages/3-extensions/sql-orm-client/test/collection-fixtures.tspackages/3-extensions/sql-orm-client/test/helpers.tspackages/3-extensions/sql-orm-client/test/include-strategy.test.tspackages/3-extensions/sql-orm-client/test/integration/include.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/3-extensions/sql-orm-client/src/include-strategy.ts
- packages/3-extensions/sql-orm-client/test/helpers.ts
- packages/3-extensions/sql-orm-client/test/collection-dispatch.test.ts
- packages/3-extensions/sql-orm-client/test/include-strategy.test.ts
the contract's target/family namespaces
`selectIncludeStrategy` previously checked `contract.capabilities['lateral']`
and `contract.capabilities['jsonAgg']` at the top level only. The
`Contract` type declares capabilities as
`Record<string, Record<string, boolean>>` — a namespaced map — and the
contract emitter populates the flags one level deeper, under the
contract's `targetFamily` (e.g. `'sql'`) and `target` (e.g. `'postgres'`)
namespaces. Top-level access never found them, so every nested include
fell back to the multi-query strategy on emitted contracts even when
the runtime supported single-query lateral / correlated emission.
Concrete impact: a 2-level include like `db.User.include('comments').all()`
fired 2 SQL statements instead of the expected 1.
Why CI didn't catch it: the strategy unit tests and the integration
tests that exercised the lateral path all populated capabilities at the
top level (`{ lateral: { enabled: true }, jsonAgg: { enabled: true } }`),
a shape the buggy detection happened to match but that no real emitted
contract produces. The lateral / correlated branches of the dispatcher
were dead code in practice, but tests appeared to cover them.
The fix uses the contract's own declared identity:
contract.capabilities[contract.targetFamily]?.[flag] === true ||
contract.capabilities[contract.target]?.[flag] === true
Universal SQL flags like `jsonAgg` declared by the SQL family at
`capabilities.sql.jsonAgg` are picked up; target-specific flags like
`lateral` declared at `capabilities.postgres.lateral` are picked up;
flags split across both namespaces compose correctly. Cross-namespace
false positives ("`postgres.lateral` found while running SQLite") are
impossible because we only inspect the running target's namespaces.
Tests:
- `include-strategy.test.ts` rewritten to use the principled shape:
`{ sql: { jsonAgg: true } }`, `{ postgres: { jsonAgg: true, lateral:
true } }`, split namespaces, unrelated namespaces, explicit false,
non-boolean values. The previous suite tested the buggy top-level
shape; those scenarios were never reachable from an emitted contract
and have been replaced.
- `collection-dispatch.test.ts` `withSingleQueryCapabilities` helper
updated to populate capabilities under the contract's actual
target/family namespaces rather than at the top level. Same logical
intent, now matching the type's shape.
- `integration/include.test.ts` `createUsersCollectionWithCapabilities`
helper now replaces capabilities entirely (instead of merging with
the base contract's `postgres` namespace), so passing
`{ sql: { jsonAgg: true } }` truly tests the correlated path. Four
call sites updated to use the namespaced shape.
All 479 sql-orm-client tests pass.
lookup; centralize the structural cast in a `withCapabilities` helper
Adds two tests that assert depth-1 includes against an emitted-shape
contract (capabilities under `targetFamily` and `target` namespaces)
fire exactly one SQL execution. Either fails fast if
`selectIncludeStrategy`'s namespace-aware lookup regresses.
Verified the unit-level guard fails when the strategy detection
reverts to top-level-only access.
Test ergonomics:
- Adds `withCapabilities(contract, capabilities)` to `helpers.ts`.
The narrow `TestContract` type fixes capabilities to the exact
shape from `contract.json` (e.g. the `postgres` namespace's specific
readonly fields). Tests need to construct contracts with arbitrary
capability shapes, which don't fit the narrow type. The helper
centralizes the structural cast in one named, documented place.
- Removes per-test `as unknown as ReturnType<typeof getTestContract>`
/ `as unknown as TestContract` casts from `include-strategy.test.ts`
(was 7) and `collection-dispatch.test.ts` (was 3) by routing through
`withCapabilities`.
- The pre-existing `withSingleQueryCapabilities` and the new
`withEmittedSqlCapabilities` helpers in `collection-dispatch.test.ts`
delegate to `withCapabilities`.
Regression guards:
- `collection-dispatch.test.ts` — `withEmittedSqlCapabilities` produces
`{ sql: { jsonAgg: true }, postgres: { jsonAgg: true, lateral: true } }`.
Asserts on MockRuntime's `executions.length`.
- `integration/include.test.ts` — uses `getTestContract()` directly
(whose capabilities are already in the emitted shape via the
`postgres` namespace) against the dev Postgres. Asserts
`runtime.executions.length === 1`.
All 481 sql-orm-client tests pass.
…lities
Replace the `as unknown as TestContract` cast with a generic over
`TCaps extends Record<string, Record<string, boolean>>`, returning
`Omit<TestContract, 'capabilities'> & { readonly capabilities: TCaps }`.
Capability-dependent type checks now see the caller's literal
capability shape instead of the narrow `TestContract` slot.
Addresses @aqrln's review note: "I'd make this helper produce an
accurate contract types from day one if it's not too complex."
Widens `contextForContract` and `createCollectionFor` in
`collection-fixtures.ts` to accept `Contract<SqlStorage>` so the more
precise return type flows through; the existing internal cast inside
`contextForContract` already absorbs the structural gap. Drops the
explicit `: TestContract` return annotations on the two thin
`with…Capabilities` wrappers in `collection-dispatch.test.ts` so the
inferred result keeps its literal capability shape.
All 481 sql-orm-client tests pass.
8c98e73 to
5e32fab
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/3-extensions/sql-orm-client/test/integration/include.test.ts (1)
55-58: 💤 Low valueUse a double cast (
as unknown as typeof base) instead of the single direct cast.The coding guidelines require
as unknown as Xfor mocks in tests to make the unsafe boundary explicit; a directas typeof basemay also be rejected by the TypeScript compiler ifRecord<string, unknown>doesn't overlap with the actualcapabilitiesfield type on the contract.🔧 Proposed fix
const contract = { ...base, capabilities, -} as typeof base; +} as unknown as typeof base;As per coding guidelines: "Use double casts (
as unknown as X) for mocks and dynamic proxies in tests instead of direct casts."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/3-extensions/sql-orm-client/test/integration/include.test.ts` around lines 55 - 58, The test creates `contract` by casting a mock object directly to `typeof base` which violates the guideline; change the cast on the constructed object (the `contract` assignment that spreads `base` and `capabilities`) to use a double cast (`as unknown as typeof base`) so the unsafe mock boundary is explicit; update the expression that currently uses `as typeof base` to `as unknown as typeof base` referring to the `contract`, `base`, and `capabilities` symbols.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@packages/3-extensions/sql-orm-client/test/integration/include.test.ts`:
- Around line 55-58: The test creates `contract` by casting a mock object
directly to `typeof base` which violates the guideline; change the cast on the
constructed object (the `contract` assignment that spreads `base` and
`capabilities`) to use a double cast (`as unknown as typeof base`) so the unsafe
mock boundary is explicit; update the expression that currently uses `as typeof
base` to `as unknown as typeof base` referring to the `contract`, `base`, and
`capabilities` symbols.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: fe7145ae-7462-4885-9831-7376e8b75479
📒 Files selected for processing (6)
packages/3-extensions/sql-orm-client/src/include-strategy.tspackages/3-extensions/sql-orm-client/test/collection-dispatch.test.tspackages/3-extensions/sql-orm-client/test/collection-fixtures.tspackages/3-extensions/sql-orm-client/test/helpers.tspackages/3-extensions/sql-orm-client/test/include-strategy.test.tspackages/3-extensions/sql-orm-client/test/integration/include.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
- packages/3-extensions/sql-orm-client/test/helpers.ts
- packages/3-extensions/sql-orm-client/src/include-strategy.ts
- packages/3-extensions/sql-orm-client/test/collection-dispatch.test.ts
- packages/3-extensions/sql-orm-client/test/include-strategy.test.ts
`multi-query path handles empty parent result sets` was using the bare
`getTestContract()`. That contract has `postgres.lateral` and
`postgres.jsonAgg` set in the emitted shape, so post-fix the test
routes through the single-query lateral path instead of multi-query
— leaving the empty-parent early return at `collection-dispatch.ts:209`
unhit and dropping package branch coverage just under the 93% gate.
Pre-fix this never showed up because `selectIncludeStrategy` could
not read namespaced capabilities and silently fell back to multi-query
for every emitted contract — so this test was hitting the multi-query
empty-parent branch by accident.
Use the same `withCapabilities(getTestContract(), {})` trick the
sibling test on line 245 already uses to force the multi-query path.
The test now actually exercises what its name describes.
wmadden
left a comment
There was a problem hiding this comment.
Your fix is more correct than the current implementation but the root cause of this problem is that capabilities shouldn't be namespaced at all
| contract.capabilities[contract.targetFamily]?.[flag] === true || | ||
| contract.capabilities[contract.target]?.[flag] === true |
There was a problem hiding this comment.
This is an old mistake in the emission process: capability flags should not be namespaced, they're either present or not, and we don't care which framework component contributes them. Your fix is more correct than the current implementation, but still working around this core mistake.
Walkthrough —
selectIncludeStrategyreads namespaced capability flagsSources
origin/main...fix/orm-client-include-strategyKey snippet (Before / After)
Intent
Make
selectIncludeStrategyread capability flags from the namespaces the contract emitter actually populates (capabilities[targetFamily]andcapabilities[target]) instead of from the top level. Without this, every emitted SQL contract silently falls back to the multi-query strategy for nested includes — even on adapters that support single-query lateral / correlated emission.Change map
withEmittedSqlCapabilitieshelper + new regression test asserting one SQL execution;withSingleQueryCapabilitiesand one inline test rebuilt to usewithCapabilitieswithCapabilities(contract, capabilities)so tests don't need per-call structural castsThe story
Contracttype declarescapabilities: Record<string, Record<string, boolean>>— namespaced — and the contract emitter populates it undertargetFamily(e.g.'sql') andtarget(e.g.'postgres'). The previous detector looked atcapabilities['lateral']directly, never finding anything. The new lookup uses the contract's own declaredtargetFamilyandtargetto find the right namespaces, so cross-target false positives ("postgres.lateralfound while running SQLite") are impossible by construction.{ lateral: { enabled: true } }) that no real emitted contract produces; those scenarios were never reachable from real usage. They're replaced by tests against the principled shape: family-only, target-only, split-namespace, unrelated-namespace, explicitfalse, non-boolean values.'multiQuery'for the default test contract) that were only true because the buggy detector failed to see the test contract's nestedpostgres.{lateral,jsonAgg}flags. They're rewritten to express their intent independently of the bug — clearing capabilities, replacing rather than merging, etc.expected 2 to be 1.withCapabilitieshelper. The narrowTestContracttype fixes the postgres namespace's shape to specific readonly fields. Tests that override capabilities for a scenario don't fit that narrow shape and previously needed per-callas unknown as TestContractcasts. ThewithCapabilitieshelper centralizes that structural cast in one place; call sites are clean.Behavior changes & evidence
Capability lookup is namespace-aware. Adds a principled lookup that reads
contract.capabilities[contract.targetFamily]?.[flag]andcontract.capabilities[contract.target]?.[flag]only.false, and non-boolean valuesSingle-query include path is now reached on emitted contracts. Before → after: a depth-1
db.User.include('comments').all()against an emitted contract fired 2 SQL statements (parent + child stitched in JS); now it fires 1 (correlated subquery +json_group_array).runtime.executions.length === 1Test ergonomics:
withCapabilitieshelper. Adds a single function that owns the structural cast tests need when overriding capabilities away from the narrowTestContractshape. No behavior change.as unknown as TestContractcasts in seven test cases; the helper is one named, documented place that makes the cast intentional rather than incidental.withCapabilitiesCompatibility / migration / risk
selectIncludeStrategy(onlydispatchWithIncludeStrategytoday) are unaffected at the API level.targetFamilyandtargetnamespaces are consulted, so a hand-crafted contract carrying flags for a different target is ignored.Follow-ups / open questions
compileSelectWithIncludeStrategystill throws onscalar/combinedescriptors, andhasComplexIncludeDescriptorsshort-circuits to multi-query. That's a separate, larger fix with codec-semantics implications (SQLSUMvs JS-side reducer for parameterized codecs); not in scope here.hasNestedIncludesshort-circuits the dispatcher; the lateral / correlated emission paths are depth-1 only today. Also separate.Non-goals
Summary by CodeRabbit
Tests
Refactor