Skip to content

feat(runtime): unify runtime executor and query-plan interfaces across SQL and Mongo (TML-2242)#381

Merged
wmadden merged 41 commits intomainfrom
tml-2242-unified-runtime-executor-and-query-plan-interfaces-across
Apr 28, 2026
Merged

feat(runtime): unify runtime executor and query-plan interfaces across SQL and Mongo (TML-2242)#381
wmadden merged 41 commits intomainfrom
tml-2242-unified-runtime-executor-and-query-plan-interfaces-across

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented Apr 27, 2026

Summary

Unifies the runtime executor and query-plan interfaces across SQL and Mongo families. Introduces an abstract RuntimeCore<TPlan, TExec, TMiddleware> in @prisma-next/framework-components that both families extend directly, deletes the separate runtime-executor package, and consolidates plan-marker types and middleware-orchestration plumbing.

Behavior changes

  • Single abstract runtime base (M2): RuntimeCore template orchestrates runBeforeCompile → lower → runWithMiddleware(beforeExecute → driver loop → onRow → afterExecute). Family runtimes implement only the abstract seams (lower, runDriver, close).
  • SqlRuntimeImpl and MongoRuntimeImpl extend RuntimeCore (M3, M4) — no composition wrapper, no second middleware orchestrator. The runtime-executor package is deleted.
  • runWithMiddleware is the single source of truth for the beforeExecute / onRow / afterExecute lifecycle. Deleting it would break both runtime suites (AC-LU2).
  • ExecutionPlan moves out of the framework contract types (M1). SqlExecutionPlan lives in @prisma-next/sql-relational-core (lanes layer); MongoExecutionPlan lives in @prisma-next/mongo-runtime. The framework-level marker is content-free.
  • RuntimeQueryable is canonicalized (M5 + Close-out PF-3): both RuntimeQueryable declarations (in sql-runtime and sql-orm-client) now extends RuntimeScope from @prisma-next/sql-relational-core. No second execute method shape survives anywhere in the SQL stack.

Architecture docs (durable artifacts)

  • ADR 204 — Single-tier runtime: docs/architecture docs/adrs/ADR 204 - Single-tier runtime.md
  • Subsystem 4 — Runtime & Middleware Framework (rewritten): docs/architecture docs/subsystems/4. Runtime & Middleware Framework.md
  • Package Layering (collapsed Mermaid layer diagram): docs/architecture docs/Package-Layering.md
  • Package Naming Conventions (single-tier tree): docs/reference/Package Naming Conventions.md
  • Architecture Overview, Error Handling — runtime-executor references retargeted.

Acceptance criteria

13 PASS / 0 PARTIAL / 0 FAIL / 0 NOT VERIFIED. Reviewer-validated at Close-out R1 (HEAD 8d8163b5a).

Test plan

  • pnpm typecheck — 118/118 (local)
  • pnpm test:packages — 109/109 (local)
  • pnpm test:integration — 104 files / 520 tests (local)
  • pnpm lint:deps — 633 modules / 1249 deps, 0 violations (local)
  • CI checks pass (driven to green in this PR)

Refs: TML-2242

Summary by CodeRabbit

  • New Features

    • Unified runtime architecture consolidates execution orchestration into core framework layer with streamlined middleware lifecycle support.
  • Documentation

    • Architecture documentation updated to reflect single-tier runtime model (ADR 204).
    • Runtime and middleware framework subsystem documentation reworked with explicit execution pipeline and lifecycle definitions.
  • Refactoring

    • @prisma-next/runtime-executor package removed; runtime execution now extends unified RuntimeCore base class.
    • SQL and Mongo runtimes refactored to inherit common execution patterns from framework core.
    • Middleware orchestration centralized via runWithMiddleware function.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request restructures the runtime architecture by removing the intermediate runtime-executor package and promoting core runtime abstractions (RuntimeCore, runWithMiddleware, plan markers) into @prisma-next/framework-components. SQL and Mongo runtimes now extend the new RuntimeCore base class, and middleware is refactored to accept plan objects instead of metadata, enabling type-safe, family-specific middleware implementations.

Changes

Cohort / File(s) Summary
Architecture & Documentation
architecture.config.json, docs/Architecture Overview.md, docs/Error Handling.md, docs/architecture docs/*
Removes runtime-executor layer from architecture model; collapses runtime plane from dual-layer to single ring; updates dependency chain and documentation to reflect new RuntimeCore-based design and ADR 204 for single-tier runtime.
Framework Components Core
packages/1-framework/1-core/framework-components/src/query-plan.ts, packages/1-framework/1-core/framework-components/src/run-with-middleware.ts, packages/1-framework/1-core/framework-components/src/runtime-core.ts, packages/1-framework/1-core/framework-components/src/runtime-middleware.ts, packages/1-framework/1-core/framework-components/src/exports/runtime.ts
Introduces plan marker interfaces (QueryPlan/ExecutionPlan), RuntimeCore abstract base class for orchestrating family runtime execution, runWithMiddleware middleware lifecycle orchestrator, and refactored RuntimeMiddleware SPI parameterized over plan types. Exports these new abstractions from the public API.
Framework Components Tests
packages/1-framework/1-core/framework-components/test/*.ts, packages/1-framework/1-core/framework-components/test/*.test-d.ts
Comprehensive test coverage for new RuntimeCore, runWithMiddleware, plan markers, and middleware SPI with both runtime and type-level tests.
Contract Layer Updates
packages/1-framework/0-foundation/contract/src/types.ts, packages/1-framework/0-foundation/contract/src/exports/types.ts, packages/1-framework/0-foundation/contract/README.md
Removes ExecutionPlan and ResultType from contract layer (moved to framework-components) and updates documentation to reflect plan metadata relocation.
Runtime Executor Deletion
packages/1-framework/4-runtime/runtime-executor/*
Entire @prisma-next/runtime-executor package deleted, including all source files, configuration, tests, and documentation.
SQL Runtime Refactor
packages/2-sql/4-lanes/relational-core/src/plan.ts, packages/2-sql/4-lanes/relational-core/src/sql-execution-plan.ts, packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts, packages/2-sql/4-lanes/relational-core/src/types.ts
Introduces SqlExecutionPlan extending framework ExecutionPlan marker; refactors SqlQueryPlan to extend QueryPlan; defines RuntimeScope as shared SQL ORM execution interface.
SQL Runtime Implementation
packages/2-sql/5-runtime/src/sql-runtime.ts, packages/2-sql/5-runtime/src/runtime-spi.ts, packages/2-sql/5-runtime/src/middleware/*, packages/2-sql/5-runtime/README.md
Refactors SqlRuntimeImpl to extend RuntimeCore with lower/runDriver/runBeforeCompile lifecycle methods; creates new runtime-spi.ts with marker/adapter/telemetry types; updates middleware to use SqlExecutionPlan and extends RuntimeMiddleware<SqlExecutionPlan>.
SQL Runtime Tests
packages/2-sql/5-runtime/test/*.ts, packages/2-sql/5-runtime/vitest.config.ts
Updates SQL runtime tests to use SqlExecutionPlan typing and new imports from framework-components; adds coverage exclusions for relocated modules.
Mongo Runtime Refactor
packages/2-mongo-family/4-query/query-ast/src/query-plan.ts, packages/2-mongo-family/7-runtime/src/mongo-execution-plan.ts, packages/2-mongo-family/7-runtime/src/mongo-runtime.ts, packages/2-mongo-family/7-runtime/src/mongo-middleware.ts, packages/2-mongo-family/7-runtime/README.md
Introduces MongoExecutionPlan extending framework marker; refactors MongoRuntimeImpl to extend RuntimeCore; updates MongoMiddleware to extend RuntimeMiddleware<MongoExecutionPlan>.
Mongo Runtime Tests
packages/2-mongo-family/7-runtime/test/*.ts
Adds type-level tests for Mongo execution plan and updates middleware tests to use new plan typing.
ORM Client Updates
packages/3-extensions/sql-orm-client/src/*.ts, packages/3-extensions/sql-orm-client/test/*.ts
Updates ORM client to import AsyncIterableResult and RuntimeScope from new sources (framework-components, sql-relational-core); removes local RuntimeScope definition; updates plan typing to use SqlExecutionPlan.
Integration & Package Updates
packages/1-framework/1-core/operations/README.md, packages/2-sql/9-family/package.json, packages/2-mongo-family/5-query-builders/orm/README.md, packages/3-extensions/postgres/src/runtime/postgres.ts, test/integration/*
Removes @prisma-next/runtime-executor from package dependencies; updates integration tests to use new import sources and RuntimeCore; updates dependency documentation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant RuntimeCore
    participant Middleware
    participant Driver as DriverImpl
    
    Client->>RuntimeCore: execute(plan)
    activate RuntimeCore
    
    RuntimeCore->>RuntimeCore: runBeforeCompile(plan)
    RuntimeCore->>RuntimeCore: lower(plan) → ExecutionPlan
    
    RuntimeCore->>Middleware: beforeExecute(exec, ctx)
    activate Middleware
    Middleware->>Middleware: hook processing
    deactivate Middleware
    
    RuntimeCore->>Driver: runDriver() → AsyncIterable<Row>
    activate Driver
    
    loop For each row
        Driver->>RuntimeCore: yield row
        RuntimeCore->>Middleware: onRow(row, exec, ctx)
        activate Middleware
        Middleware->>Middleware: hook processing
        deactivate Middleware
        RuntimeCore->>Client: yield processed row
    end
    
    Driver->>RuntimeCore: completion
    deactivate Driver
    
    RuntimeCore->>Middleware: afterExecute(exec, result, ctx)
    activate Middleware
    Middleware->>Middleware: hook processing (errors swallowed)
    deactivate Middleware
    
    deactivate RuntimeCore
    Client->>Client: consume results
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • PR #373: Introduces SQL-family beforeCompile middleware hook and corresponding runtime changes to RuntimeCore and SqlMiddleware typing, directly related to the middleware/runtime execution flow refactoring in this PR.
  • PR #338: Extracts and migrates runtime/middleware SPIs (RuntimeCore, runWithMiddleware, AsyncIterableResult, runtimeError) into @prisma-next/framework-components, which is the same core abstraction movement performed by this PR.

Poem

🐰 The runtime hops with newfound grace,
One layer stands in execution's place,
Core and middleware dance in sync,
No executor need—just plans that link!
From families bound to frameworks free,
The architecture springs with glee!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.92% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: unifying runtime executor and query-plan interfaces across SQL and Mongo families by centralizing lifecycle in RuntimeCore.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2242-unified-runtime-executor-and-query-plan-interfaces-across

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 27, 2026

Open in StackBlitz

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-runtime@381

@prisma-next/family-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-mongo@381

@prisma-next/sql-runtime

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-runtime@381

@prisma-next/family-sql

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/family-sql@381

@prisma-next/middleware-telemetry

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/middleware-telemetry@381

@prisma-next/mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo@381

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-paradedb@381

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/extension-pgvector@381

@prisma-next/postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/postgres@381

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-orm-client@381

@prisma-next/sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sqlite@381

@prisma-next/target-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-mongo@381

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-mongo@381

@prisma-next/driver-mongo

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-mongo@381

@prisma-next/contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract@381

@prisma-next/utils

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/utils@381

@prisma-next/config

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/config@381

@prisma-next/errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/errors@381

@prisma-next/framework-components

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/framework-components@381

@prisma-next/operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/operations@381

@prisma-next/ts-render

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/ts-render@381

@prisma-next/contract-authoring

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/contract-authoring@381

@prisma-next/ids

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/ids@381

@prisma-next/psl-parser

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-parser@381

@prisma-next/psl-printer

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/psl-printer@381

@prisma-next/cli

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/cli@381

@prisma-next/emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/emitter@381

@prisma-next/migration-tools

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/migration-tools@381

prisma-next

npm i https://pkg.pr.new/prisma/prisma-next@381

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/vite-plugin-contract-emit@381

@prisma-next/mongo-codec

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-codec@381

@prisma-next/mongo-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract@381

@prisma-next/mongo-value

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-value@381

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-psl@381

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-contract-ts@381

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-emitter@381

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-schema-ir@381

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-query-ast@381

@prisma-next/mongo-orm

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-orm@381

@prisma-next/mongo-query-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-query-builder@381

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-lowering@381

@prisma-next/mongo-wire

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/mongo-wire@381

@prisma-next/sql-contract

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract@381

@prisma-next/sql-errors

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-errors@381

@prisma-next/sql-operations

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-operations@381

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-schema-ir@381

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-psl@381

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-ts@381

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-contract-emitter@381

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-lane-query-builder@381

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-relational-core@381

@prisma-next/sql-builder

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/sql-builder@381

@prisma-next/target-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-postgres@381

@prisma-next/target-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/target-sqlite@381

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-postgres@381

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/adapter-sqlite@381

@prisma-next/driver-postgres

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-postgres@381

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/prisma/prisma-next/@prisma-next/driver-sqlite@381

commit: 85c3430

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/architecture docs/Package-Layering.md (1)

529-533: ⚠️ Potential issue | 🟡 Minor

Remove the brief link from this architecture doc.

Brief 12 - Package Layering reads like planning material, so linking it from durable architecture documentation will rot faster than the ADR/package docs and keeps this page coupled to transient project artifacts. Based on learnings: Project planning docs, specs, and milestones are ephemeral and should not be linked from durable documentation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/architecture` docs/Package-Layering.md around lines 529 - 533, Remove
the transient planning doc link under the "## References" section by deleting
the bullet that contains "Brief 12 - Package Layering" (the markdown line "-
[Brief 12 - Package Layering](../../briefs/12-Package-Layering.md)"); ensure the
remaining reference bullets (e.g., "ADR 140 - Package Layering & Target-Family
Namespacing" and "ADR 005 - Thin Core, Fat Targets") remain unchanged and the
list spacing stays consistent after removal.
🧹 Nitpick comments (6)
packages/1-framework/1-core/framework-components/src/query-plan.ts (1)

44-44: Clarify ResultType behavior when _row is absent.

The JSDoc states that ResultType returns never when _row is absent, but the conditional P extends { readonly _row?: infer R } will match any object (since _row? is optional) and infer unknown for R when the property doesn't exist. If you want never for plans without _row, consider:

-export type ResultType<P> = P extends { readonly _row?: infer R } ? R : never;
+export type ResultType<P> = P extends { readonly _row: infer R } ? R : never;

However, if inferring unknown for absent _row is acceptable, update the JSDoc to reflect this.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/1-framework/1-core/framework-components/src/query-plan.ts` at line
44, The conditional type ResultType currently uses an optional check "P extends
{ readonly _row?: infer R }" which will match any object and yield unknown when
_row is absent; update ResultType to "P extends { readonly _row: infer R } ? R :
never" if you want absent _row to produce never, or alternatively update the
JSDoc for ResultType to state that absent _row yields unknown (current behavior)
so the intent is clear; ensure the change is applied to the ResultType
definition in query-plan.ts.
packages/1-framework/1-core/framework-components/test/mock-family.test.ts (1)

145-147: Prefer a single object matcher for related hook flags.

Line 145–147 checks one logical state with three separate toBe(true) assertions. Grouping them into one object matcher is more consistent with repo test conventions.

♻️ Suggested refactor
-    expect(beforeExecuteCalled).toBe(true);
-    expect(onRowCalled).toBe(true);
-    expect(afterExecuteCalled).toBe(true);
+    expect({
+      beforeExecuteCalled,
+      onRowCalled,
+      afterExecuteCalled,
+    }).toMatchObject({
+      beforeExecuteCalled: true,
+      onRowCalled: true,
+      afterExecuteCalled: true,
+    });

As per coding guidelines, "**/*.test.ts: Prefer object matchers (toMatchObject) over multiple individual expect().toBe() calls when checking 2 or more related values in tests."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/1-framework/1-core/framework-components/test/mock-family.test.ts`
around lines 145 - 147, Replace the three separate assertions that check
beforeExecuteCalled, onRowCalled, and afterExecuteCalled with a single object
matcher; construct an object with those three flags (beforeExecuteCalled,
onRowCalled, afterExecuteCalled) and assert it with toMatchObject (or toEqual)
against { beforeExecuteCalled: true, onRowCalled: true, afterExecuteCalled: true
} so the related hook flags are verified in one concise expectation.
packages/2-sql/4-lanes/relational-core/src/plan.ts (1)

10-16: Refresh the JSDoc to drop the old runtime executor term.

This PR removes that abstraction, so the comment now points readers at the old architecture instead of the runtime/RuntimeCore flow that actually performs lowering. As per coding guidelines "**/*.{md,ts,tsx}: Keep docs current (READMEs, rules, links) and prefer links to canonical docs over long comments`."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-sql/4-lanes/relational-core/src/plan.ts` around lines 10 - 16,
Update the JSDoc in plan.ts to remove the outdated "runtime executor" wording
and instead reference the current lowering flow performed by RuntimeCore; keep
the rest of the description about the absent `sql` field and that it produces a
`SqlExecutionPlan`, retain the `QueryPlan<Row>` marker and the `_Row`/`_row`
phantom properties for compatibility, and ensure `ast` and `params` are still
documented—replace the old architecture mention with a concise note that
lowering happens via `RuntimeCore` (or link to canonical docs) so readers are
pointed at the current flow.
packages/2-sql/5-runtime/src/runtime-spi.ts (1)

24-28: Consider explicit TContract constraint or removing default.

The TContract = unknown default on RuntimeFamilyAdapter<TContract> may be intentional for SPI flexibility, but per coding guidelines: "Don't add generic defaults unless the type is meaningfully usable with the default."

If callers always provide a concrete TContract, consider removing the default to enforce explicit typing. If unknown is a valid use case (e.g., for middleware that doesn't inspect the contract), the current default is acceptable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-sql/5-runtime/src/runtime-spi.ts` around lines 24 - 28, The
generic default on RuntimeFamilyAdapter<TContract = unknown> should be removed
to force explicit typing; update the interface declaration for
RuntimeFamilyAdapter todeclare the generic without a default
(RuntimeFamilyAdapter<TContract>) so callers must supply a concrete TContract,
and update any callers/tests that relied on the default to pass an explicit
contract type; alternatively, if leaving a default is required for valid
use-cases, replace the permissive unknown default with a meaningful constraint
(e.g., TContract extends object or a specific contract shape) and add a brief
comment on why the default is kept.
packages/3-extensions/postgres/src/runtime/postgres.ts (1)

198-204: Prefer ifDefined() for conditional middleware spread.

Per coding guidelines, use ifDefined() from @prisma-next/utils/defined instead of inline conditional spread patterns.

♻️ Proposed fix
+import { ifDefined } from '@prisma-next/utils/defined';

Then at line 198-204:

     runtimeInstance = createRuntime({
       stackInstance,
       context,
       driver,
       verify: options.verify ?? { mode: 'onFirstUse', requireMarker: false },
-      ...(options.middleware ? { middleware: options.middleware } : {}),
+      ...ifDefined('middleware', options.middleware),
     });

As per coding guidelines: "Use ifDefined() from @prisma-next/utils/defined for conditional object spreads instead of inline conditional spread patterns".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/3-extensions/postgres/src/runtime/postgres.ts` around lines 198 -
204, The createRuntime call uses an inline conditional spread for middleware;
replace that with ifDefined() from `@prisma-next/utils/defined` so the middleware
property is only added when present. Import ifDefined and change the options
spread in the createRuntime argument (where runtimeInstance =
createRuntime({...})) to use middleware: ifDefined(options.middleware) (or the
appropriate object shape) instead of ...(options.middleware ? { middleware:
options.middleware } : {}), ensuring the middleware key is omitted when
undefined.
packages/2-sql/5-runtime/src/sql-runtime.ts (1)

251-265: Consider guarding onFirstUse verification with verified flag.

The onFirstUse branch calls verifyMarker() on every execution, relying on the internal verified flag to early-return. While correct, checking the flag before the async call would avoid the function call overhead after first verification.

♻️ Optional optimization
-      if (self.verify.mode === 'onFirstUse') {
+      if (self.verify.mode === 'onFirstUse' && !self.verified) {
         await self.verifyMarker();
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-sql/5-runtime/src/sql-runtime.ts` around lines 251 - 265, The
onFirstUse branch currently calls self.verifyMarker() every time even though
verifyMarker() early-returns once verification is done; change the branch to
first check the internal verified flag to avoid unnecessary async calls — i.e.,
in the block where you check self.verify.mode === 'onFirstUse', only call
self.verifyMarker() if !self.verified (similar to how startupVerified is used),
referencing the verify.mode, verifyMarker(), and verified symbols.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/Error` Handling.md:
- Around line 144-146: Update the "See:" list in docs/Error Handling.md so it
matches the text that mentions "budgets/lints": add the lints middleware path
`packages/2-sql/5-runtime/src/middleware/lints.ts` alongside the existing
`packages/2-sql/5-runtime/src/middleware/budgets.ts` entry (the text around
"budgets/lints" should now have corresponding links), keeping the format
consistent with other entries and following the docs linting guideline for
README/link upkeep.

In
`@packages/1-framework/1-core/framework-components/test/query-plan.types.test-d.ts`:
- Around line 91-94: The test "ResultType returns never for objects without
_row" uses expectTypeOf<Row>().toEqualTypeOf<never>() which can fail with the
current Vitest; update the assertion to use the approved workaround by comparing
against undefined as never instead (replace the toEqualTypeOf<never>() call with
toEqualTypeOf(undefined as never)) so the type-level assertion for ResultType<{
meta: PlanMeta }> (Row) correctly asserts never; locate this in the test block
that defines type Row = ResultType<{ meta: PlanMeta }> and adjust the
expectTypeOf call accordingly.

In `@packages/2-mongo-family/7-runtime/src/mongo-runtime.ts`:
- Around line 13-19: The public options type narrows middleware to
MongoMiddleware[] which prevents passing shared RuntimeMiddleware values; change
the middleware property on MongoRuntimeOptions from readonly MongoMiddleware[] |
undefined to readonly RuntimeMiddleware[] | undefined (or a union allowing both
RuntimeMiddleware and MongoMiddleware) so callers can supply cross-family
middleware; update any related type imports and ensure
checkMiddlewareCompatibility(...) is still invoked where middleware is validated
(e.g., in the constructor/initializer that reads MongoRuntimeOptions) so
incompatible middleware are rejected at runtime.

In `@packages/2-mongo-family/7-runtime/test/mongo-execution-plan.types.test-d.ts`:
- Around line 52-55: Replace the deprecated matcher call on the type assertion
for plan.command: change the call site using
expectTypeOf(plan.command).toMatchTypeOf<{ readonly collection: string; readonly
kind: string; }>() to use the current Vitest API
expectTypeOf(plan.command).toExtend<{ readonly collection: string; readonly
kind: string; }>() so the test verifies type compatibility with the supported
toExtend() matcher (locate the assertion referencing plan.command and replace
toMatchTypeOf with toExtend).

---

Outside diff comments:
In `@docs/architecture` docs/Package-Layering.md:
- Around line 529-533: Remove the transient planning doc link under the "##
References" section by deleting the bullet that contains "Brief 12 - Package
Layering" (the markdown line "- [Brief 12 - Package
Layering](../../briefs/12-Package-Layering.md)"); ensure the remaining reference
bullets (e.g., "ADR 140 - Package Layering & Target-Family Namespacing" and "ADR
005 - Thin Core, Fat Targets") remain unchanged and the list spacing stays
consistent after removal.

---

Nitpick comments:
In `@packages/1-framework/1-core/framework-components/src/query-plan.ts`:
- Line 44: The conditional type ResultType currently uses an optional check "P
extends { readonly _row?: infer R }" which will match any object and yield
unknown when _row is absent; update ResultType to "P extends { readonly _row:
infer R } ? R : never" if you want absent _row to produce never, or
alternatively update the JSDoc for ResultType to state that absent _row yields
unknown (current behavior) so the intent is clear; ensure the change is applied
to the ResultType definition in query-plan.ts.

In `@packages/1-framework/1-core/framework-components/test/mock-family.test.ts`:
- Around line 145-147: Replace the three separate assertions that check
beforeExecuteCalled, onRowCalled, and afterExecuteCalled with a single object
matcher; construct an object with those three flags (beforeExecuteCalled,
onRowCalled, afterExecuteCalled) and assert it with toMatchObject (or toEqual)
against { beforeExecuteCalled: true, onRowCalled: true, afterExecuteCalled: true
} so the related hook flags are verified in one concise expectation.

In `@packages/2-sql/4-lanes/relational-core/src/plan.ts`:
- Around line 10-16: Update the JSDoc in plan.ts to remove the outdated "runtime
executor" wording and instead reference the current lowering flow performed by
RuntimeCore; keep the rest of the description about the absent `sql` field and
that it produces a `SqlExecutionPlan`, retain the `QueryPlan<Row>` marker and
the `_Row`/`_row` phantom properties for compatibility, and ensure `ast` and
`params` are still documented—replace the old architecture mention with a
concise note that lowering happens via `RuntimeCore` (or link to canonical docs)
so readers are pointed at the current flow.

In `@packages/2-sql/5-runtime/src/runtime-spi.ts`:
- Around line 24-28: The generic default on RuntimeFamilyAdapter<TContract =
unknown> should be removed to force explicit typing; update the interface
declaration for RuntimeFamilyAdapter todeclare the generic without a default
(RuntimeFamilyAdapter<TContract>) so callers must supply a concrete TContract,
and update any callers/tests that relied on the default to pass an explicit
contract type; alternatively, if leaving a default is required for valid
use-cases, replace the permissive unknown default with a meaningful constraint
(e.g., TContract extends object or a specific contract shape) and add a brief
comment on why the default is kept.

In `@packages/2-sql/5-runtime/src/sql-runtime.ts`:
- Around line 251-265: The onFirstUse branch currently calls self.verifyMarker()
every time even though verifyMarker() early-returns once verification is done;
change the branch to first check the internal verified flag to avoid unnecessary
async calls — i.e., in the block where you check self.verify.mode ===
'onFirstUse', only call self.verifyMarker() if !self.verified (similar to how
startupVerified is used), referencing the verify.mode, verifyMarker(), and
verified symbols.

In `@packages/3-extensions/postgres/src/runtime/postgres.ts`:
- Around line 198-204: The createRuntime call uses an inline conditional spread
for middleware; replace that with ifDefined() from `@prisma-next/utils/defined` so
the middleware property is only added when present. Import ifDefined and change
the options spread in the createRuntime argument (where runtimeInstance =
createRuntime({...})) to use middleware: ifDefined(options.middleware) (or the
appropriate object shape) instead of ...(options.middleware ? { middleware:
options.middleware } : {}), ensuring the middleware key is omitted when
undefined.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: bcb24b5b-f767-484e-a8d1-cf692323bcc1

📥 Commits

Reviewing files that changed from the base of the PR and between cd17e07 and 4dd2ddc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (107)
  • architecture.config.json
  • docs/Architecture Overview.md
  • docs/Error Handling.md
  • docs/architecture docs/Package-Layering.md
  • docs/architecture docs/adrs/ADR 204 - Single-tier runtime.md
  • docs/architecture docs/subsystems/4. Runtime & Middleware Framework.md
  • docs/reference/Package Naming Conventions.md
  • examples/prisma-next-demo/src/prisma-no-emit/runtime.ts
  • packages/1-framework/0-foundation/contract/README.md
  • packages/1-framework/0-foundation/contract/src/exports/types.ts
  • packages/1-framework/0-foundation/contract/src/types.ts
  • packages/1-framework/1-core/framework-components/src/exports/runtime.ts
  • packages/1-framework/1-core/framework-components/src/query-plan.ts
  • packages/1-framework/1-core/framework-components/src/run-with-middleware.ts
  • packages/1-framework/1-core/framework-components/src/runtime-core.ts
  • packages/1-framework/1-core/framework-components/src/runtime-middleware.ts
  • packages/1-framework/1-core/framework-components/test/mock-family.test.ts
  • packages/1-framework/1-core/framework-components/test/query-plan.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/run-with-middleware.test.ts
  • packages/1-framework/1-core/framework-components/test/runtime-core.test.ts
  • packages/1-framework/1-core/framework-components/test/runtime-core.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/runtime-middleware.types.test-d.ts
  • packages/1-framework/1-core/operations/README.md
  • packages/1-framework/4-runtime/runtime-executor/README.md
  • packages/1-framework/4-runtime/runtime-executor/biome.jsonc
  • packages/1-framework/4-runtime/runtime-executor/package.json
  • packages/1-framework/4-runtime/runtime-executor/src/exports/index.ts
  • packages/1-framework/4-runtime/runtime-executor/src/index.ts
  • packages/1-framework/4-runtime/runtime-executor/src/middleware/types.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-core.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-spi.ts
  • packages/1-framework/4-runtime/runtime-executor/test/mock-family.test.ts
  • packages/1-framework/4-runtime/runtime-executor/test/runtime-core.types.test-d.ts
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.json
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.prod.json
  • packages/1-framework/4-runtime/runtime-executor/tsdown.config.ts
  • packages/1-framework/4-runtime/runtime-executor/vitest.config.ts
  • packages/2-mongo-family/4-query/query-ast/src/query-plan.ts
  • packages/2-mongo-family/4-query/query-ast/test/query-plan.types.test-d.ts
  • packages/2-mongo-family/5-query-builders/orm/README.md
  • packages/2-mongo-family/7-runtime/README.md
  • packages/2-mongo-family/7-runtime/package.json
  • packages/2-mongo-family/7-runtime/src/exports/index.ts
  • packages/2-mongo-family/7-runtime/src/mongo-execution-plan.ts
  • packages/2-mongo-family/7-runtime/src/mongo-middleware.ts
  • packages/2-mongo-family/7-runtime/src/mongo-runtime.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-plan.types.test-d.ts
  • packages/2-mongo-family/7-runtime/test/mongo-middleware.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/plan.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/types.ts
  • packages/2-sql/4-lanes/relational-core/src/plan.ts
  • packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts
  • packages/2-sql/4-lanes/relational-core/src/sql-execution-plan.ts
  • packages/2-sql/4-lanes/relational-core/src/types.ts
  • packages/2-sql/4-lanes/relational-core/test/sql-execution-plan.types.test-d.ts
  • packages/2-sql/5-runtime/README.md
  • packages/2-sql/5-runtime/package.json
  • packages/2-sql/5-runtime/src/codecs/decoding.ts
  • packages/2-sql/5-runtime/src/codecs/encoding.ts
  • packages/2-sql/5-runtime/src/exports/index.ts
  • packages/2-sql/5-runtime/src/fingerprint.ts
  • packages/2-sql/5-runtime/src/guardrails/raw.ts
  • packages/2-sql/5-runtime/src/lower-sql-plan.ts
  • packages/2-sql/5-runtime/src/marker.ts
  • packages/2-sql/5-runtime/src/middleware/before-compile-chain.ts
  • packages/2-sql/5-runtime/src/middleware/budgets.ts
  • packages/2-sql/5-runtime/src/middleware/lints.ts
  • packages/2-sql/5-runtime/src/middleware/sql-middleware.ts
  • packages/2-sql/5-runtime/src/runtime-spi.ts
  • packages/2-sql/5-runtime/src/sql-family-adapter.ts
  • packages/2-sql/5-runtime/src/sql-marker.ts
  • packages/2-sql/5-runtime/src/sql-runtime.ts
  • packages/2-sql/5-runtime/test/async-iterable-result.test.ts
  • packages/2-sql/5-runtime/test/before-compile-chain.test.ts
  • packages/2-sql/5-runtime/test/budgets.test.ts
  • packages/2-sql/5-runtime/test/json-schema-validation.test.ts
  • packages/2-sql/5-runtime/test/lints.test.ts
  • packages/2-sql/5-runtime/test/sql-family-adapter.test.ts
  • packages/2-sql/5-runtime/test/sql-runtime.test.ts
  • packages/2-sql/5-runtime/test/utils.ts
  • packages/2-sql/9-family/package.json
  • packages/3-extensions/middleware-telemetry/src/telemetry-middleware.ts
  • packages/3-extensions/postgres/src/runtime/postgres.ts
  • packages/3-extensions/sql-orm-client/README.md
  • packages/3-extensions/sql-orm-client/package.json
  • packages/3-extensions/sql-orm-client/src/collection-dispatch.ts
  • packages/3-extensions/sql-orm-client/src/collection-mutation-dispatch.ts
  • packages/3-extensions/sql-orm-client/src/collection-runtime.ts
  • packages/3-extensions/sql-orm-client/src/collection.ts
  • packages/3-extensions/sql-orm-client/src/execute-query-plan.ts
  • packages/3-extensions/sql-orm-client/src/mutation-executor.ts
  • packages/3-extensions/sql-orm-client/src/types.ts
  • packages/3-extensions/sql-orm-client/test/collection-dispatch.test.ts
  • packages/3-extensions/sql-orm-client/test/collection-runtime.test.ts
  • packages/3-extensions/sql-orm-client/test/helpers.ts
  • packages/3-extensions/sql-orm-client/test/integration/runtime-helpers.ts
  • packages/3-extensions/sql-orm-client/test/raw-compiled-query.test.ts
  • packages/3-extensions/sql-orm-client/test/runtime-queryable.types.test-d.ts
  • packages/3-extensions/sqlite/src/runtime/sqlite.ts
  • test/integration/package.json
  • test/integration/test/contract-builder.test.ts
  • test/integration/test/contract-builder.types.test-d.ts
  • test/integration/test/cross-package/cross-family-middleware.test.ts
  • test/integration/test/dsl-type-inference.test-d.ts
  • test/integration/test/rewriting-middleware.integration.test.ts
  • test/integration/test/utils.ts
💤 Files with no reviewable changes (19)
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.json
  • packages/1-framework/4-runtime/runtime-executor/biome.jsonc
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.prod.json
  • packages/1-framework/4-runtime/runtime-executor/tsdown.config.ts
  • packages/1-framework/4-runtime/runtime-executor/src/index.ts
  • packages/1-framework/4-runtime/runtime-executor/package.json
  • test/integration/package.json
  • packages/2-sql/9-family/package.json
  • packages/1-framework/4-runtime/runtime-executor/vitest.config.ts
  • packages/2-sql/5-runtime/package.json
  • packages/1-framework/4-runtime/runtime-executor/test/runtime-core.types.test-d.ts
  • packages/1-framework/4-runtime/runtime-executor/README.md
  • packages/1-framework/4-runtime/runtime-executor/src/middleware/types.ts
  • packages/1-framework/0-foundation/contract/src/types.ts
  • packages/1-framework/0-foundation/contract/src/exports/types.ts
  • packages/1-framework/4-runtime/runtime-executor/test/mock-family.test.ts
  • packages/1-framework/4-runtime/runtime-executor/src/exports/index.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-spi.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-core.ts

Comment thread docs/Error Handling.md
Comment thread packages/2-mongo-family/7-runtime/src/mongo-runtime.ts
Comment thread packages/2-mongo-family/7-runtime/test/mongo-execution-plan.types.test-d.ts Outdated
@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented Apr 27, 2026

@coderabbitai — addressing the review at #pullrequestreview-4178305734. Per-finding response:

Will address (5):

  • docs/architecture docs/Package-Layering.md — dangling Brief link: Done in 0957eaf3f. Removed the briefs/12-Package-Layering.md reference; durable architecture docs should not link to transient project material.
  • packages/2-sql/4-lanes/relational-core/src/plan.ts — "runtime executor" terminology: Done in 0957eaf3f. Refreshed the SqlQueryPlan JSDoc to name RuntimeCore (the runtime base class in @prisma-next/framework-components/runtime) as the entity that lowers query plans.
  • packages/1-framework/1-core/framework-components/src/query-plan.tsResultType infers unknown: Done in 2aea90ad6. Guarded the conditional with _row extends keyof P so plans whose static type lacks _row resolve to never. Also updated the type test to toEqualTypeOf(undefined as never) so a regression to unknown would actually fail.
  • packages/3-extensions/postgres/src/runtime/postgres.ts — inline conditional spread: Done in 4bc8ad9a8. Switched to ifDefined('middleware', options.middleware) from @prisma-next/utils/defined, matching the established pattern.
  • packages/2-sql/5-runtime/src/sql-runtime.ts — missing !verified guard on onFirstUse: Done in d03bd0f50. Mirrored the startup branch's guard so we no longer await a guaranteed-no-op promise on the hot execute path after first verification.

Won't address in this PR (2):

  • packages/2-sql/5-runtime/src/runtime-spi.ts — default TContract = unknown on RuntimeFamilyAdapter: Keeping the default. It is intentional and called out in the JSDoc — test mocks of RuntimeFamilyAdapter rely on it; production callsites already pass an explicit Contract<SqlStorage>. Satisfies the "meaningfully usable" criterion for generic defaults.
  • packages/1-framework/1-core/framework-components/test/mock-family.test.ts — three toBe(true) assertions: Keeping three separate assertions. Granular per-hook failure messages (beforeExecute / onRow / afterExecute) are more diagnostic than a single toMatchObject, and the cited "object matchers when checking 2+ values" guideline is not a documented rule in this repo.

The CodeRabbit review-body itself (4 sub-threads) was decomposed into A05a–A05g during triage rather than blanket-dismissed; per-finding decisions are recorded in wip/reviews/prisma_prisma-next_pr-381/review-actions.json.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Tip

For best results, initiate chat on the files or code changes.

@wmadden Thanks for the thorough triage and the commit-level detail.

Confirmed fixed ✓

  • Dangling Brief link (0957eaf3f) — noted.
  • SqlQueryPlan JSDoc / "runtime executor" terminology (0957eaf3f) — noted.
  • ResultType unknownnever guard + regression-proof type test (2aea90ad6) — the _row extends keyof P guard is the right fix; glad the type test was tightened alongside it.
  • Postgres ifDefined('middleware', ...) spread (4bc8ad9a8) — noted.
  • !verified guard on onFirstUse hot path (d03bd0f50) — good catch to fix; that was a real correctness issue.

Won't address — acknowledged

  • TContract = unknown default: the JSDoc-documented intent plus the test-mock reliance is a reasonable justification; no objection.
  • Three separate toBe(true) assertions: per-hook failure messages are a legitimate diagnostic preference and the cited guideline isn't a repo convention; no objection.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/architecture docs/Package-Layering.md (1)

285-290: Unify the framework-components import path wording in runtime docs.

Line 285/288 says @prisma-next/framework-components/runtime, while Line 290 says @prisma-next/framework-components. Pick one canonical specifier and use it consistently here to avoid contradictory architecture guidance.

Proposed doc fix
- - `packages/2-sql/5-runtime/` → `@prisma-next/sql-runtime` – SQL family runtime that extends `RuntimeCore` from `@prisma-next/framework-components/runtime` with SQL adapters (future document runtimes will mirror this)
+ - `packages/2-sql/5-runtime/` → `@prisma-next/sql-runtime` – SQL family runtime that extends `RuntimeCore` from `@prisma-next/framework-components` with SQL adapters (future document runtimes will mirror this)

- - `packages/2-mongo-family/7-runtime/` → `@prisma-next/mongo-runtime` – Mongo family runtime that extends `RuntimeCore` from `@prisma-next/framework-components/runtime` with the Mongo adapter
+ - `packages/2-mongo-family/7-runtime/` → `@prisma-next/mongo-runtime` – Mongo family runtime that extends `RuntimeCore` from `@prisma-next/framework-components` with the Mongo adapter

As per coding guidelines: “Keep docs current (READMEs, rules, links) and prefer links to canonical docs over long comments.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/architecture` docs/Package-Layering.md around lines 285 - 290, The doc
uses two import specifiers for the runtime SPI; unify them to a single canonical
import (choose and use '@prisma-next/framework-components' everywhere) and
update the two occurrences of '@prisma-next/framework-components/runtime' so
that the text consistently states that RuntimeCore, RuntimeMiddleware,
RuntimeExecutor and runWithMiddleware are imported from
'@prisma-next/framework-components'. Ensure the `@prisma-next/sql-runtime` and
`@prisma-next/mongo-runtime` descriptions also reference the same canonical
specifier and keep the ADR link intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/2-sql/4-lanes/relational-core/src/plan.ts`:
- Line 22: Remove the unused transitional phantom property `_Row` from the
`SqlQueryPlan` type declaration: locate the `readonly _Row?: Row;` member on
`SqlQueryPlan` and delete it so the type only uses the canonical `_row` property
that `ResultType<P>` inspects; no other code paths should be changed, but run
type-checks to ensure nothing else referenced `_Row` remains.

---

Nitpick comments:
In `@docs/architecture` docs/Package-Layering.md:
- Around line 285-290: The doc uses two import specifiers for the runtime SPI;
unify them to a single canonical import (choose and use
'@prisma-next/framework-components' everywhere) and update the two occurrences
of '@prisma-next/framework-components/runtime' so that the text consistently
states that RuntimeCore, RuntimeMiddleware, RuntimeExecutor and
runWithMiddleware are imported from '@prisma-next/framework-components'. Ensure
the `@prisma-next/sql-runtime` and `@prisma-next/mongo-runtime` descriptions
also reference the same canonical specifier and keep the ADR link intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: b08d791b-942f-4c5b-96a2-1399ff812bc0

📥 Commits

Reviewing files that changed from the base of the PR and between 9baa590 and d03bd0f.

📒 Files selected for processing (8)
  • docs/Error Handling.md
  • docs/architecture docs/Package-Layering.md
  • packages/1-framework/1-core/framework-components/src/query-plan.ts
  • packages/1-framework/1-core/framework-components/test/query-plan.types.test-d.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-plan.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/plan.ts
  • packages/2-sql/5-runtime/src/sql-runtime.ts
  • packages/3-extensions/postgres/src/runtime/postgres.ts
✅ Files skipped from review due to trivial changes (3)
  • packages/1-framework/1-core/framework-components/src/query-plan.ts
  • packages/1-framework/1-core/framework-components/test/query-plan.types.test-d.ts
  • packages/2-sql/5-runtime/src/sql-runtime.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/Error Handling.md

Comment thread packages/2-sql/4-lanes/relational-core/src/plan.ts Outdated
@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented Apr 27, 2026

@coderabbitai — addressing the review at #pullrequestreview-4178503981.

Will address (2):

  • SqlQueryPlan._Row phantom removal (actionable, 1): Done in da7e0d4e3 — removed readonly _Row?: Row; from SqlQueryPlan, refreshed the JSDoc to describe the canonical _row (inherited from QueryPlan<Row>) that ResultType<P> actually inspects, and dropped the matching field from the SqlQueryPlanShape test fixture. The thread on packages/2-sql/4-lanes/relational-core/src/plan.ts:22 is auto-resolved by the deletion; replied + resolved explicitly.
  • docs/architecture docs/Package-Layering.md 285–290 — unify framework-components specifier (nitpick): Done in 086cc757f. Picked the subpath form @prisma-next/framework-components/runtime (the one already used on lines 285 and 288 for the SQL/Mongo runtime entries) and switched the immediately-following Dependency Rules sentence to match, so the section is internally consistent. The opposite direction proposed in the diff would have required editing 285 and 288 too; the chosen direction is the smaller patch and matches how the runtime SPI is exported (@prisma-next/framework-components/runtime).

pnpm typecheck clean across sql-relational-core, framework-components, sql-runtime, and postgres after both commits.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Tip

For best results, initiate chat on the files or code changes.

@wmadden Thanks for the follow-up and the commit-level detail.

Confirmed fixed ✓

  • SqlQueryPlan._Row phantom removal (da7e0d4e3) — the cleanup is correct: dropping the uppercase _Row field and relying solely on the _row phantom inherited from QueryPlan<Row> keeps the ResultType<P> inspection surface consistent across all plan types. Good call to also trim it from the SqlQueryPlanShape test fixture so the type test stays authoritative.
  • Package-Layering.md specifier unification (086cc757f) — the chosen direction (standardising on the subpath @prisma-next/framework-components/runtime) is the right call; it matches the actual export entrypoint and required the smallest diff.

pnpm typecheck clean across all four packages is a solid signal. Nothing further to raise on either item.

@wmadden wmadden force-pushed the tml-2242-unified-runtime-executor-and-query-plan-interfaces-across branch from 086cc75 to 23698f7 Compare April 27, 2026 11:32
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
packages/2-sql/5-runtime/README.md (1)

44-71: ⚠️ Potential issue | 🟡 Minor

Add the missing budgets import to the usage example.

The snippet now calls budgets() on Line 71, but it never imports it, so the example fails as written.

Suggested doc fix
-import { createExecutionContext, createRuntime, createSqlExecutionStack } from '@prisma-next/sql-runtime';
+import {
+  budgets,
+  createExecutionContext,
+  createRuntime,
+  createSqlExecutionStack,
+} from '@prisma-next/sql-runtime';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-sql/5-runtime/README.md` around lines 44 - 71, The example calls
budgets() but doesn't import it; add an import for the budgets middleware at the
top of the snippet (e.g., import budgets from
'@prisma-next/framework-components/budgets') so the budgets() symbol used in the
createRuntime({ middleware: [budgets()] }) call is defined; update the top
imports alongside
instantiateExecutionStack/createExecutionContext/createRuntime/createSqlExecutionStack
to include budgets.
packages/2-sql/5-runtime/src/sql-runtime.ts (1)

438-439: ⚠️ Potential issue | 🔴 Critical

Clean up the acquired connection when beginTransaction() fails.

runtime.connection() runs before the outer try/finally is established, so a rejection from connection.transaction() exits withTransaction() without releasing or destroying the acquired connection. Repeated BEGIN failures will leak pool slots.

Suggested fix
 export async function withTransaction<R>(
   runtime: Runtime,
   fn: (tx: TransactionContext) => PromiseLike<R>,
 ): Promise<R> {
   const connection = await runtime.connection();
-  const transaction = await connection.transaction();
+  let transaction: RuntimeTransaction;
+  try {
+    transaction = await connection.transaction();
+  } catch (error) {
+    await connection.destroy(error).catch(() => undefined);
+    throw error;
+  }
 
   let invalidated = false;
   const txContext: TransactionContext = {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/2-sql/5-runtime/src/sql-runtime.ts` around lines 438 - 439, Acquired
connection from runtime.connection() is not cleaned up if
connection.transaction() (beginTransaction) throws; either move the await
runtime.connection() call inside the try/finally that cleans up the connection
or add a small try/catch around connection.transaction() that calls the
connection cleanup method (e.g. connection.release() or connection.destroy()
depending on your pool API) before rethrowing the error; update the
withTransaction / beginTransaction flow to ensure that when
connection.transaction() fails the previously acquired connection is
released/destroyed so pool slots are not leaked.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/architecture` docs/Package-Layering.md:
- Around line 172-173: Replace inconsistent references to the runtime SPI so all
mentions of RuntimeCore and related runtime types point to the dedicated
entrypoint; e.g., change references from `@prisma-next/framework-components` to
`@prisma-next/framework-components/runtime` wherever RuntimeCore or "runtime SPI"
is mentioned (including the early Runtime description and any other paragraphs
that reference the runtime implementation or SPI), and ensure the explanatory
sentence that already uses the /runtime subpath is the canonical form for these
types.

In `@docs/architecture` docs/subsystems/4. Runtime & Middleware Framework.md:
- Around line 278-279: Change the inconsistent sentence that currently claims
marker verification happens “before any work” so it matches the actual lifecycle
used in code: verification occurs after runBeforeCompile and lowering (as
implemented in SqlRuntimeImpl.executeAgainstQueryable()). Update the sequence
text and the related paragraphs (also around lines referenced 343–355) to state
that the runtime performs runBeforeCompile and lowering first, then verifies the
loaded contract against the database marker, and then proceeds to middleware
policy/budget application and driver streaming.

In `@packages/2-sql/5-runtime/src/sql-runtime.ts`:
- Around line 301-317: The connection and transaction wrappers (e.g.,
wrappedConnection returned by transaction()/release()/destroy() and the
transaction wrapper returned by self.wrapTransaction/commit/rollback) must track
a closed flag and fail-fast: add an internal boolean like "closed" on the
wrappedConnection and on the RuntimeTransaction wrapper, set closed = true in
release(), destroy(), and in transaction commit()/rollback() handlers, and
update wrapper methods (transaction(), release(), destroy(), execute(), and any
lifecycle methods on the transaction wrapper) to check the flag and throw a
clear error if invoked after closed; ensure executeAgainstQueryable and
wrapTransaction are updated to respect and set this invalidation so callers can
no longer use wrappers after teardown.

---

Outside diff comments:
In `@packages/2-sql/5-runtime/README.md`:
- Around line 44-71: The example calls budgets() but doesn't import it; add an
import for the budgets middleware at the top of the snippet (e.g., import
budgets from '@prisma-next/framework-components/budgets') so the budgets()
symbol used in the createRuntime({ middleware: [budgets()] }) call is defined;
update the top imports alongside
instantiateExecutionStack/createExecutionContext/createRuntime/createSqlExecutionStack
to include budgets.

In `@packages/2-sql/5-runtime/src/sql-runtime.ts`:
- Around line 438-439: Acquired connection from runtime.connection() is not
cleaned up if connection.transaction() (beginTransaction) throws; either move
the await runtime.connection() call inside the try/finally that cleans up the
connection or add a small try/catch around connection.transaction() that calls
the connection cleanup method (e.g. connection.release() or connection.destroy()
depending on your pool API) before rethrowing the error; update the
withTransaction / beginTransaction flow to ensure that when
connection.transaction() fails the previously acquired connection is
released/destroyed so pool slots are not leaked.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: c6f22d87-7ff5-4c32-a435-bbf724ba8b23

📥 Commits

Reviewing files that changed from the base of the PR and between 086cc75 and 23698f7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (101)
  • architecture.config.json
  • docs/Architecture Overview.md
  • docs/Error Handling.md
  • docs/architecture docs/Package-Layering.md
  • docs/architecture docs/adrs/ADR 204 - Single-tier runtime.md
  • docs/architecture docs/subsystems/4. Runtime & Middleware Framework.md
  • docs/reference/Package Naming Conventions.md
  • packages/1-framework/0-foundation/contract/README.md
  • packages/1-framework/0-foundation/contract/src/exports/types.ts
  • packages/1-framework/0-foundation/contract/src/types.ts
  • packages/1-framework/1-core/framework-components/src/exports/runtime.ts
  • packages/1-framework/1-core/framework-components/src/query-plan.ts
  • packages/1-framework/1-core/framework-components/src/run-with-middleware.ts
  • packages/1-framework/1-core/framework-components/src/runtime-core.ts
  • packages/1-framework/1-core/framework-components/src/runtime-middleware.ts
  • packages/1-framework/1-core/framework-components/test/mock-family.test.ts
  • packages/1-framework/1-core/framework-components/test/query-plan.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/run-with-middleware.test.ts
  • packages/1-framework/1-core/framework-components/test/runtime-core.test.ts
  • packages/1-framework/1-core/framework-components/test/runtime-core.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/runtime-middleware.types.test-d.ts
  • packages/1-framework/1-core/operations/README.md
  • packages/1-framework/4-runtime/runtime-executor/README.md
  • packages/1-framework/4-runtime/runtime-executor/biome.jsonc
  • packages/1-framework/4-runtime/runtime-executor/package.json
  • packages/1-framework/4-runtime/runtime-executor/src/exports/index.ts
  • packages/1-framework/4-runtime/runtime-executor/src/index.ts
  • packages/1-framework/4-runtime/runtime-executor/src/middleware/types.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-core.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-spi.ts
  • packages/1-framework/4-runtime/runtime-executor/test/mock-family.test.ts
  • packages/1-framework/4-runtime/runtime-executor/test/runtime-core.types.test-d.ts
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.json
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.prod.json
  • packages/1-framework/4-runtime/runtime-executor/tsdown.config.ts
  • packages/1-framework/4-runtime/runtime-executor/vitest.config.ts
  • packages/2-mongo-family/4-query/query-ast/src/query-plan.ts
  • packages/2-mongo-family/4-query/query-ast/test/query-plan.types.test-d.ts
  • packages/2-mongo-family/5-query-builders/orm/README.md
  • packages/2-mongo-family/7-runtime/README.md
  • packages/2-mongo-family/7-runtime/package.json
  • packages/2-mongo-family/7-runtime/src/exports/index.ts
  • packages/2-mongo-family/7-runtime/src/mongo-execution-plan.ts
  • packages/2-mongo-family/7-runtime/src/mongo-middleware.ts
  • packages/2-mongo-family/7-runtime/src/mongo-runtime.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-plan.types.test-d.ts
  • packages/2-mongo-family/7-runtime/test/mongo-middleware.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/plan.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/types.ts
  • packages/2-sql/4-lanes/relational-core/src/plan.ts
  • packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts
  • packages/2-sql/4-lanes/relational-core/src/sql-execution-plan.ts
  • packages/2-sql/4-lanes/relational-core/src/types.ts
  • packages/2-sql/4-lanes/relational-core/test/sql-execution-plan.types.test-d.ts
  • packages/2-sql/5-runtime/README.md
  • packages/2-sql/5-runtime/package.json
  • packages/2-sql/5-runtime/src/codecs/decoding.ts
  • packages/2-sql/5-runtime/src/codecs/encoding.ts
  • packages/2-sql/5-runtime/src/exports/index.ts
  • packages/2-sql/5-runtime/src/fingerprint.ts
  • packages/2-sql/5-runtime/src/guardrails/raw.ts
  • packages/2-sql/5-runtime/src/lower-sql-plan.ts
  • packages/2-sql/5-runtime/src/marker.ts
  • packages/2-sql/5-runtime/src/middleware/budgets.ts
  • packages/2-sql/5-runtime/src/middleware/lints.ts
  • packages/2-sql/5-runtime/src/middleware/sql-middleware.ts
  • packages/2-sql/5-runtime/src/runtime-spi.ts
  • packages/2-sql/5-runtime/src/sql-family-adapter.ts
  • packages/2-sql/5-runtime/src/sql-marker.ts
  • packages/2-sql/5-runtime/src/sql-runtime.ts
  • packages/2-sql/5-runtime/test/async-iterable-result.test.ts
  • packages/2-sql/5-runtime/test/budgets.test.ts
  • packages/2-sql/5-runtime/test/json-schema-validation.test.ts
  • packages/2-sql/5-runtime/test/lints.test.ts
  • packages/2-sql/5-runtime/test/sql-family-adapter.test.ts
  • packages/2-sql/5-runtime/test/sql-runtime.test.ts
  • packages/2-sql/5-runtime/test/utils.ts
  • packages/2-sql/5-runtime/vitest.config.ts
  • packages/2-sql/9-family/package.json
  • packages/3-extensions/postgres/src/runtime/postgres.ts
  • packages/3-extensions/sql-orm-client/README.md
  • packages/3-extensions/sql-orm-client/package.json
  • packages/3-extensions/sql-orm-client/src/collection-dispatch.ts
  • packages/3-extensions/sql-orm-client/src/collection-mutation-dispatch.ts
  • packages/3-extensions/sql-orm-client/src/collection-runtime.ts
  • packages/3-extensions/sql-orm-client/src/collection.ts
  • packages/3-extensions/sql-orm-client/src/execute-query-plan.ts
  • packages/3-extensions/sql-orm-client/src/mutation-executor.ts
  • packages/3-extensions/sql-orm-client/src/types.ts
  • packages/3-extensions/sql-orm-client/test/collection-dispatch.test.ts
  • packages/3-extensions/sql-orm-client/test/collection-runtime.test.ts
  • packages/3-extensions/sql-orm-client/test/helpers.ts
  • packages/3-extensions/sql-orm-client/test/integration/runtime-helpers.ts
  • packages/3-extensions/sql-orm-client/test/raw-compiled-query.test.ts
  • packages/3-extensions/sql-orm-client/test/runtime-queryable.types.test-d.ts
  • test/integration/package.json
  • test/integration/test/contract-builder.test.ts
  • test/integration/test/contract-builder.types.test-d.ts
  • test/integration/test/cross-package/cross-family-middleware.test.ts
  • test/integration/test/dsl-type-inference.test-d.ts
💤 Files with no reviewable changes (19)
  • packages/2-sql/9-family/package.json
  • packages/2-sql/5-runtime/package.json
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.json
  • packages/1-framework/4-runtime/runtime-executor/tsdown.config.ts
  • packages/1-framework/4-runtime/runtime-executor/vitest.config.ts
  • packages/1-framework/4-runtime/runtime-executor/tsconfig.prod.json
  • packages/1-framework/4-runtime/runtime-executor/test/runtime-core.types.test-d.ts
  • test/integration/package.json
  • packages/1-framework/4-runtime/runtime-executor/biome.jsonc
  • packages/1-framework/4-runtime/runtime-executor/src/index.ts
  • packages/1-framework/0-foundation/contract/src/types.ts
  • packages/1-framework/4-runtime/runtime-executor/README.md
  • packages/1-framework/4-runtime/runtime-executor/test/mock-family.test.ts
  • packages/1-framework/0-foundation/contract/src/exports/types.ts
  • packages/1-framework/4-runtime/runtime-executor/src/middleware/types.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-spi.ts
  • packages/1-framework/4-runtime/runtime-executor/src/runtime-core.ts
  • packages/1-framework/4-runtime/runtime-executor/package.json
  • packages/1-framework/4-runtime/runtime-executor/src/exports/index.ts
✅ Files skipped from review due to trivial changes (33)
  • packages/3-extensions/sql-orm-client/src/mutation-executor.ts
  • packages/3-extensions/sql-orm-client/test/collection-runtime.test.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/plan.ts
  • packages/2-sql/5-runtime/src/sql-marker.ts
  • test/integration/test/contract-builder.test.ts
  • test/integration/test/contract-builder.types.test-d.ts
  • packages/3-extensions/postgres/src/runtime/postgres.ts
  • architecture.config.json
  • test/integration/test/dsl-type-inference.test-d.ts
  • packages/2-mongo-family/5-query-builders/orm/README.md
  • packages/3-extensions/sql-orm-client/package.json
  • docs/Error Handling.md
  • packages/2-sql/4-lanes/relational-core/src/runtime-scope.ts
  • packages/2-sql/5-runtime/test/json-schema-validation.test.ts
  • packages/3-extensions/sql-orm-client/src/collection.ts
  • packages/1-framework/1-core/operations/README.md
  • packages/2-sql/5-runtime/src/fingerprint.ts
  • packages/3-extensions/sql-orm-client/test/raw-compiled-query.test.ts
  • packages/1-framework/1-core/framework-components/src/exports/runtime.ts
  • packages/2-sql/5-runtime/src/sql-family-adapter.ts
  • packages/3-extensions/sql-orm-client/src/collection-runtime.ts
  • packages/1-framework/1-core/framework-components/test/query-plan.types.test-d.ts
  • packages/2-sql/5-runtime/src/codecs/encoding.ts
  • packages/2-mongo-family/7-runtime/src/exports/index.ts
  • packages/2-sql/5-runtime/test/sql-runtime.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-plan.types.test-d.ts
  • packages/2-sql/5-runtime/test/sql-family-adapter.test.ts
  • packages/3-extensions/sql-orm-client/test/runtime-queryable.types.test-d.ts
  • packages/2-sql/5-runtime/src/runtime-spi.ts
  • packages/3-extensions/sql-orm-client/test/collection-dispatch.test.ts
  • packages/1-framework/1-core/framework-components/src/query-plan.ts
  • packages/1-framework/0-foundation/contract/README.md
  • packages/2-sql/5-runtime/src/exports/index.ts
🚧 Files skipped from review as they are similar to previous changes (24)
  • packages/2-mongo-family/7-runtime/src/mongo-execution-plan.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/types.ts
  • packages/2-sql/5-runtime/vitest.config.ts
  • packages/2-mongo-family/7-runtime/package.json
  • packages/3-extensions/sql-orm-client/src/collection-dispatch.ts
  • packages/2-sql/4-lanes/relational-core/test/sql-execution-plan.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/sql-execution-plan.ts
  • packages/2-mongo-family/4-query/query-ast/src/query-plan.ts
  • packages/2-sql/5-runtime/src/lower-sql-plan.ts
  • packages/2-mongo-family/4-query/query-ast/test/query-plan.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/mock-family.test.ts
  • packages/1-framework/1-core/framework-components/test/runtime-core.types.test-d.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/runtime-core.test.ts
  • packages/3-extensions/sql-orm-client/src/execute-query-plan.ts
  • packages/2-sql/5-runtime/src/codecs/decoding.ts
  • packages/2-mongo-family/7-runtime/README.md
  • packages/2-sql/4-lanes/relational-core/src/types.ts
  • packages/1-framework/1-core/framework-components/src/run-with-middleware.ts
  • packages/2-sql/5-runtime/test/budgets.test.ts
  • packages/3-extensions/sql-orm-client/README.md
  • test/integration/test/cross-package/cross-family-middleware.test.ts
  • packages/1-framework/1-core/framework-components/test/runtime-middleware.types.test-d.ts
  • packages/2-sql/5-runtime/test/utils.ts

Comment thread docs/architecture docs/Package-Layering.md Outdated
Comment thread docs/architecture docs/subsystems/4. Runtime &amp; Middleware Framework.md Outdated
Comment thread packages/2-sql/5-runtime/src/sql-runtime.ts
wmadden added a commit that referenced this pull request Apr 27, 2026
…fication ordering

- Package-Layering.md: align all RuntimeCore / runtime SPI mentions on
  the @prisma-next/framework-components/runtime subpath (per ADR 204),
  removing the inconsistency CodeRabbit flagged at L172/L209/L282 where
  some references used the bare /framework-components path.
- subsystems/4. Runtime & Middleware Framework.md: rewrite the
  Sequence (high level) prose at L278 so it describes the same lifecycle
  as the Execution Pipeline section and SqlRuntimeImpl.executeAgainstQueryable():
  runBeforeCompile + lower run first, then contract verification (timing
  controlled by verify.mode = startup | onFirstUse | always), then
  middleware policy/budget application around the driver stream.

Refs PR #381 review threads PRRT_kwDOQM0QJc590M2b and PRRT_kwDOQM0QJc590M2g.
wmadden added a commit that referenced this pull request Apr 27, 2026
… 140

- ADR-INDEX.md: add ADR 204 (Single-tier runtime) under Runtime &
  Execution following the table style used for neighboring entries.
- ADR 140: add a top-of-file blockquote callout noting partial
  supersession by ADR 204 — specifically the "Runtime Separation"
  two-tier-runtime portion. Package-layering, plane-boundary, and
  naming guidance in ADR 140 is unchanged. Style follows the existing
  precedent at the top of ADR 167 and ADR 044.

Closes a close-out gap surfaced by the project audit ahead of merging
the cross-family runtime unification PR (#381).
wmadden added a commit that referenced this pull request Apr 27, 2026
Add the ./runtime subpath export to the "What this package provides"
list and the "Subpath exports" code sample. The export is in active use
across @prisma-next/sql-runtime, @prisma-next/sql-orm-client, and
@prisma-next/mongo-runtime; per ADR 204 it is the canonical location
for the runtime SPI (RuntimeCore, runWithMiddleware, RuntimeMiddleware)
and the README should reflect that.

Closes a close-out gap surfaced by the project audit ahead of merging
PR #381.
wmadden added a commit that referenced this pull request Apr 27, 2026
…fication ordering

- Package-Layering.md: align all RuntimeCore / runtime SPI mentions on
  the @prisma-next/framework-components/runtime subpath (per ADR 204),
  removing the inconsistency CodeRabbit flagged at L172/L209/L282 where
  some references used the bare /framework-components path.
- subsystems/4. Runtime & Middleware Framework.md: rewrite the
  Sequence (high level) prose at L278 so it describes the same lifecycle
  as the Execution Pipeline section and SqlRuntimeImpl.executeAgainstQueryable():
  runBeforeCompile + lower run first, then contract verification (timing
  controlled by verify.mode = startup | onFirstUse | always), then
  middleware policy/budget application around the driver stream.

Refs PR #381 review threads PRRT_kwDOQM0QJc590M2b and PRRT_kwDOQM0QJc590M2g.
wmadden added a commit that referenced this pull request Apr 27, 2026
… 140

- ADR-INDEX.md: add ADR 204 (Single-tier runtime) under Runtime &
  Execution following the table style used for neighboring entries.
- ADR 140: add a top-of-file blockquote callout noting partial
  supersession by ADR 204 — specifically the "Runtime Separation"
  two-tier-runtime portion. Package-layering, plane-boundary, and
  naming guidance in ADR 140 is unchanged. Style follows the existing
  precedent at the top of ADR 167 and ADR 044.

Closes a close-out gap surfaced by the project audit ahead of merging
the cross-family runtime unification PR (#381).
wmadden added a commit that referenced this pull request Apr 27, 2026
Add the ./runtime subpath export to the "What this package provides"
list and the "Subpath exports" code sample. The export is in active use
across @prisma-next/sql-runtime, @prisma-next/sql-orm-client, and
@prisma-next/mongo-runtime; per ADR 204 it is the canonical location
for the runtime SPI (RuntimeCore, runWithMiddleware, RuntimeMiddleware)
and the README should reflect that.

Closes a close-out gap surfaced by the project audit ahead of merging
PR #381.
@wmadden wmadden force-pushed the tml-2242-unified-runtime-executor-and-query-plan-interfaces-across branch from 1c2eb55 to b40f102 Compare April 27, 2026 13:07
wmadden added 13 commits April 27, 2026 17:50
Decision: introduce an abstract RuntimeCore base class in
@prisma-next/framework-components/runtime that owns the full middleware
lifecycle (runBeforeCompile -> lower -> runWithMiddleware). SqlRuntime and
MongoRuntime extend it, providing two abstract overrides each (lower,
runDriver) plus an optional runBeforeCompile override. The duplicated
middleware orchestrator collapses into a single runWithMiddleware helper.

QueryPlan<Row> and ExecutionPlan<Row> become content-free nominal markers
in framework-components; the SQL-shaped ExecutionPlan leaves
@prisma-next/contract/types and lives in the SQL domain as
SqlExecutionPlan. Mongo gains a typed MongoExecutionPlan wrapping the
inline wire command.

Plan: five milestones (markers + ExecutionPlan relocation; abstract base
+ helper; SQL migration; Mongo migration; SQL ORM RuntimeQueryable
reconciliation). Project branch is rooted on PR #373
(origin/writeable-middleware) so M3 lifts the existing beforeCompile chain
rather than reinventing it; PRs target writeable-middleware until #373
merges, then re-target to main.

Linear: TML-2242.
…ighten middleware/executor constraints

Introduce family-agnostic plan markers in
@prisma-next/framework-components/runtime: QueryPlan<Row> carries the
phantom Row parameter alongside meta, and ExecutionPlan<Row> extends
QueryPlan as a nominal marker for executable plans. ResultType<P>
extracts the Row type from the phantom _row property and works for any
plan that extends QueryPlan, so SQL- and Mongo-shaped plans alike feed
into one type-level utility.

Tighten the cross-family SPI to use the marker:
RuntimeExecutor<TPlan extends QueryPlan> and
RuntimeMiddleware<TPlan extends QueryPlan = QueryPlan> replace the prior
inline { meta: PlanMeta } constraint. The default on RuntimeMiddleware
keeps existing untyped middleware (telemetry, etc.) compiling without
churn while letting family-specific middleware narrow TPlan to their
concrete plan type.

Type tests (runtime-middleware.types.test-d.ts,
query-plan.types.test-d.ts) cover positive assignability for SQL-,
SqlQueryPlan-, and MongoQueryPlan-shaped values, plus negative tests
for objects without meta. ResultType extraction is exercised on a
plan-shaped value with a typed _row.

Phase M1 (T1.1, T1.2, T1.3).
TML-2242. Project: cross-family-runtime-unification.
…meMiddleware<ExecutionPlan>

Spell out the structural relationship the legacy contract-typed
middleware already had: Middleware<TContract> extends
RuntimeMiddleware<ExecutionPlan> rather than relying on the default
TPlan = QueryPlan. The override still narrows the context type to
MiddlewareContext<TContract> and adds the beforeCompile? hook for AST
rewriting; the plan parameter shape is unchanged at this point (still
the SQL-shaped ExecutionPlan re-exported from @prisma-next/contract,
relocated to SqlExecutionPlan in T1.6).

T1.4 outcome (option a): Middleware<TContract> is structurally a
RuntimeMiddleware. SqlMiddleware and MongoMiddleware extend
RuntimeMiddleware directly — Middleware<TContract> survives only to
carry the contract-typed context for RuntimeCoreImpl callers. M3 will
delete RuntimeCoreImpl and fold this type away with it, so no
reshaping is needed at M1.

Phase M1 (T1.4).
TML-2242. Project: cross-family-runtime-unification.
Add SqlExecutionPlan<Row> alongside SqlMiddleware in
@prisma-next/sql-runtime. The type extends the framework
ExecutionPlan<Row> marker and carries the SQL-specific shape that the
driver actually runs: rendered sql + bound params + optional source ast +
plan meta + phantom _row. This is the type that lowerSqlPlan will return
once the migration in T1.6 lands.

Home decision: @prisma-next/sql-runtime (default per the M1 plan). No
downstream package gains a runtime dependency that it lacked before —
sql-runtime is already on the runtime plane and is the natural neighbor
of SqlMiddleware. A thinner @prisma-next/sql-execution-plan package
would add a workspace boundary without separating any consumer.

Type tests verify SqlExecutionPlan is assignable to both ExecutionPlan
and QueryPlan, that ResultType extracts the row type, and that values
missing sql or params are rejected.

Phase M1 (T1.5).
TML-2242. Project: cross-family-runtime-unification.
…rate to SqlExecutionPlan

Phase M1 (T1.6, T1.7).

Atomically remove the SQL-shaped ExecutionPlan and ResultType<P> from
@prisma-next/contract/types and migrate every in-repo usage to either
the framework markers (QueryPlan/ExecutionPlan/ResultType in
@prisma-next/framework-components/runtime) or the SQL-domain
SqlExecutionPlan.

Decisions:

- SqlExecutionPlan home (T1.5/T1.6): relocated from @prisma-next/sql-runtime
  to @prisma-next/sql-relational-core/plan. The default home in the plan was
  sql-runtime, but lane-level utilities (SqlPlan, RawTemplateFactory,
  RawFactory) compose against the executable shape and the lanes layer
  cannot depend on the runtime layer. sql-runtime now re-exports
  SqlExecutionPlan from sql-relational-core.

- ResultType<P> home: framework alongside QueryPlan
  (@prisma-next/framework-components/runtime), keyed off the _row phantom.
  This is the smaller import-graph diff than co-locating with
  SqlExecutionPlan because runtime-executor and the cross-family middleware
  SPI already pull from framework-components; SQL packages re-export the
  framework ResultType from sql-relational-core/types.

- SqlQueryPlan now extends QueryPlan<Row> (T1.7) and retains its _Row
  phantom alongside the inherited _row for backwards-compatible type
  extraction.

- RuntimeCoreImpl and evaluateRawGuardrails live in the framework but
  consume SQL-shaped wire fields (sql, params). To avoid framework→SQL
  layering violations, both define inline views (WirePlanView,
  RawGuardrailPlan) and use a single scoped `as unknown as WirePlanView`
  cast at the access sites. RuntimeCoreImpl is slated for deletion in M3,
  at which point these casts disappear.

- lowerSqlPlan now returns SqlExecutionPlan<Row>.

No runtime behavior change.
…end QueryPlan

Phase M1 (T1.8, T1.9).

Introduce MongoExecutionPlan<Row> in @prisma-next/mongo-runtime as the
Mongo-domain executable plan: it extends the framework
ExecutionPlan<Row> marker (meta + _row) and carries the wire-command
shape (AnyMongoWireCommand) that MongoAdapter.lower(plan) produces and
MongoDriver.execute consumes.

Update MongoQueryPlan in @prisma-next/mongo-query-ast to extend the
framework QueryPlan<Row>; meta is now inherited from the marker. The
existing unique-symbol phantom is retained alongside the inherited _row
for backwards compatibility with anything that may have relied on it.

Decisions:

- MongoExecutionPlan home: @prisma-next/mongo-runtime (the spec default).
  Co-locating with MongoQueryPlan in @prisma-next/mongo-query-ast was
  considered but rejected: the wire-command type lives in the transport
  layer (@prisma-next/mongo-wire), and the lanes layer hosting
  mongo-query-ast cannot depend on transport. Adopting the type as
  MongoRuntime.execute input is deferred to M4 per spec.

- mongo-runtime now declares a direct dep on @prisma-next/mongo-wire
  (previously transitive via mongo-lowering).

No runtime behavior change.
- Drops the `SqlExecutionPlan` re-export from @prisma-next/sql-runtime
  (no in-repo consumers).
- Drops the `ResultType` re-export from
  @prisma-next/sql-relational-core/types and migrates the three
  remaining integration-test imports to the canonical home,
  @prisma-next/framework-components/runtime.
- Completes T1.6 atomic-migration cleanup: fixes the inline
  `{ sql, params, meta }` literal in cross-family-middleware.test.ts
  that escaped df176a9 (mirrors line 121s typed-local pattern).

Both deletions align with AGENTS.md: "Don't add exports for backwards
compatibility unless requested to do so."

M1 R2 — addresses F1 and resolves F2.
M2 R1 — adds the canonical middleware orchestration helper extracted from
RuntimeCoreImpl.#executeWith. Lifecycle and error path are byte-equivalent
to the SQL-flavored RuntimeCoreImpl.#executeWith body (modulo the parameter
substitution: this.middleware → middleware, this.middlewareContext → ctx,
queryable.execute({ sql, params }) → runDriver()), so M3/M4 adoption can
proceed without observable behavior changes.

Unit tests cover all five behavioral cases from the M2 spec AC: zero
middleware passthrough, single middleware lifecycle order, multiple
middleware registration order at every hook, error path with
afterExecute(completed: false) + rethrow, and afterExecute errors
swallowed during the error path.

No production runtime adopts the helper yet — that is M3/M4 work.
M2 R1 — adds abstract RuntimeCore<TPlan, TExec, TMiddleware> to
framework-components/runtime alongside type tests and a behavioral
mock-family test. The base templates execute(plan):

  exec = await runBeforeCompile(plan)   # identity by default
  exec = await lower(exec)              # abstract
  yield* runWithMiddleware(exec, this.middleware, this.ctx,
                           () => this.runDriver(exec))

Abstract methods: lower, runDriver, close. Concrete identity default
for runBeforeCompile (SQL will override in M3 to run the beforeCompile
chain). Constructor accepts { middleware, ctx }.

No production runtime adopts the base in M2; SQL adoption lands in M3
and Mongo in M4.

Implementation notes:
- TMiddleware is constrained to RuntimeMiddleware<TExec> rather than
  RuntimeMiddleware<TPlan> from the plan wording, because runWithMiddleware
  invokes hooks (beforeExecute / onRow / afterExecute) on the lowered
  TExec. TPlan and TExec are siblings under QueryPlan, so the helper
  call site cannot accept RuntimeMiddleware<TPlan>. Middleware still
  sees the post-lowering plan, which matches every concrete family.
- runDriver returns AsyncIterable<Record<string, unknown>>; execute<Row>
  applies an as-cast for parity with RuntimeCoreImpl.#executeWith
  (`yield row as Row`). Caller-side Row typing flows through plan._row.

Behavioral test verifies the lifecycle order across one and multiple
middlewares; type tests assert the TPlan/TExec/Row constraints flow,
including a negative test for lower returning a non-TExec type.
M2 R1 — adapts the cross-family middleware-SPI mock-family test to
extend the new abstract `RuntimeCore` from
`@prisma-next/framework-components/runtime` instead of the legacy
`createRuntimeCore` factory. Demonstrates that the new base is
family-agnostic by plugging in a fictional "mock" family with no SQL
dependency.

Preserves the intent of the original four tests:
- Plans flow end-to-end through the lifecycle without SQL plumbing.
- A `lower()` that throws on a misrouted plan rejects the iteration
  (the family-agnostic equivalent of contract validation).
- Middleware lifecycle hooks fire across `beforeExecute / onRow /
  afterExecute`.
- `close()` is wired through for resource teardown.

Decision flagged: this drops direct unit-test coverage of
`RuntimeCoreImpl.#executeWith` in M2. `RuntimeCoreImpl` itself remains
in place — and is still exercised indirectly by the SQL runtime suite
(which uses `createRuntimeCore`). M3 owns the cleanup: it deletes
`RuntimeCoreImpl` outright when `SqlRuntime` adopts the new base, at
which point this file likely moves into `framework-components/test/`.
M3 R1 — SQL family adopts RuntimeCore.

`SqlRuntimeImpl` now extends the abstract `RuntimeCore<SqlQueryPlan,
SqlExecutionPlan, SqlMiddleware>` introduced in M2. The two-layer
composition (SqlRuntime-around-RuntimeCoreImpl) collapses to a single
class that overrides `lower()`, `runDriver()`, and `runBeforeCompile()`.

Responsibility map (RuntimeCoreImpl -> post-M3 home):

- middleware orchestration (beforeExecute / onRow / afterExecute) ->
  `runWithMiddleware` in `framework-components` (sole iterator)
- driver invocation -> `SqlRuntime.runDriver()` (calls Queryable.execute)
- AST -> SqlExecutionPlan lowering -> `SqlRuntime.lower()` (delegates to
  `lowerSqlPlan`, with raw-SQL bypass preserved)
- beforeCompile chain -> `SqlRuntime.runBeforeCompile()` (delegates to
  `runBeforeCompileChain`, semantics preserved including rewrite logging
  and error propagation)
- marker verification -> `SqlRuntime.executeAgainstQueryable` (post-
  lowering, pre-driver: same insertion point as today)
- SQL telemetry fingerprint -> `SqlRuntime.recordTelemetry()` via
  `computeSqlFingerprint` (now in `sql-runtime/src/fingerprint.ts`)
- codec encode/decode -> wrapped around `super.execute()` in
  `SqlRuntime.execute()`: encodeParams during lowering, decodeRow on the
  row stream emitted by the framework lifecycle
- RuntimeFamilyAdapter / MarkerReader / MarkerStatement -> moved to
  `sql-runtime/src/runtime-spi.ts` (SQL is the only consumer)

Decisions:

1. `@prisma-next/runtime-executor` package removed entirely. Its
   remaining contents post-`RuntimeCoreImpl` deletion (marker reader,
   SQL fingerprint, raw-SQL guardrails, `RuntimeFamilyAdapter` SPI) are
   all SQL-domain concerns; no framework-level reuse remains.

2. `RuntimeFamilyAdapter` lives in `@prisma-next/sql-runtime` (only SQL
   uses it). Verified: zero hits in `packages/1-framework/`.

3. Marker verification happens inside `executeAgainstQueryable`, after
   `runBeforeCompile`+`lower` but before middleware orchestration kicks
   off. Same observable position as `RuntimeCoreImpl.verifyPlanIfNeeded`
   today; existing verify-mode tests pass without modification.

After this round, `runWithMiddleware` is the only file in the repo that
iterates middleware around a driver loop. The SQL `beforeCompile` chain
iterates middleware for AST rewriting (pre-lowering, family-specific) —
not a lifecycle loop. Mongo still has its own loops; that is M4 scope.

Test changes are import-only: `cross-family-middleware.test.ts` now
constructs a mock `RuntimeCore` subclass directly instead of going
through the deleted `createRuntimeCore` factory. `mock-family.test.ts`
relocated to `framework-components/test/` alongside the abstract base.
M3 deleted the @prisma-next/runtime-executor package and relocated its
SQL-specific responsibilities into @prisma-next/sql-runtime, but five
package READMEs still described the deleted package as a dependency or
composed collaborator.

- sql-runtime: rewrite Overview, Responsibilities, Dependencies, Plugins
  exports list, and Architecture section + mermaid to describe the
  current shape (SqlRuntime extends RuntimeCore<SqlQueryPlan,
  SqlExecutionPlan, SqlMiddleware> from @prisma-next/framework-components/runtime;
  marker.ts, fingerprint.ts, runtime-spi.ts, guardrails/raw.ts,
  middleware/before-compile-chain.ts now own the four SQL-specific
  responsibilities).
- mongo-runtime: drop the runtime-executor dependency line; AsyncIterableResult
  and the RuntimeMiddleware SPI now come from @prisma-next/framework-components/runtime.
- sql-orm-client: redirect AsyncIterableResult to its current home in
  @prisma-next/framework-components/runtime.
- mongo-orm: redirect AsyncIterableResult similarly.
- operations: drop the runtime-executor entry from the depended-on-by
  list; surface sql-runtime / framework-components as current consumers.

M3 R2 — addresses F3.
…are loops (TML-2242 M4)

Mirror the M3 SQL migration on the Mongo side: MongoRuntimeImpl now
extends RuntimeCore<MongoQueryPlan, MongoExecutionPlan, MongoMiddleware>
and overrides only the family-specific seams.

- lower(plan): wraps adapter.lower(plan) into a MongoExecutionPlan.
- runDriver(exec): dispatches the wire command via driver.execute.
- close(): closes the underlying driver.

The four inline `for ... of middleware` lifecycle loops (beforeExecute,
onRow, afterExecute, error-path afterExecute) that previously lived in
MongoRuntimeImpl.execute are gone; the lifecycle is inherited from the
base via runWithMiddleware. Mongo does not override runBeforeCompile —
Mongo middleware has no beforeCompile hook today.

To make the middleware contract align with the inherited template,
MongoMiddleware now extends RuntimeMiddleware<MongoExecutionPlan> and
its hooks observe the post-lowering plan. familyId is narrowed to
optional `mongo` so generic cross-family middleware (e.g. telemetry)
without a familyId remain assignable; mismatches are caught at
construction by checkMiddlewareCompatibility.

Tests are updated to use MongoMiddleware as the type annotation. The
SQL-rejection test casts through unknown to exercise the runtime
compatibility check despite the narrower static type. The type-d test
asserts the new optional familyId shape.

Behaviour parity is preserved 1:1: all 56 mongo-runtime unit tests
pass, and the cross-family middleware integration test continues to
observe equivalent telemetry events from both runtimes.
wmadden added 12 commits April 27, 2026 17:56
- Add `lints.ts` next to `budgets.ts` under the Error Handling guardrails
  references, matching the surrounding text that calls out budgets/lints.
- Drop the dangling link to the deleted `briefs/12-Package-Layering.md`
  from `Package-Layering.md`; durable docs should not point at transient
  project artifacts.
- Refresh `SqlQueryPlan` JSDoc to name `RuntimeCore` (the new runtime base
  class) as the entity that lowers query plans, instead of the retired
  "runtime executor" terminology.
…hout _row

`ResultType<P>` previously matched `P extends { readonly _row?: infer R }`,
which trivially holds for any object type. When `P` had no `_row` property
in its static type, `R` silently inferred as `unknown` instead of `never`,
contradicting the JSDoc and producing incorrect row types when callers
forgot to thread the phantom marker through their plans.

Guard the inference with `_row extends keyof P` so the conditional only
binds `R` when the property is actually declared. Plans whose static
shape lacks `_row` now resolve to `never`.

Update the corresponding type test to use `toEqualTypeOf(undefined as never)`
so the assertion fails loudly if the result drifts back to `unknown` —
plain `toEqualTypeOf<never>()` is structurally permissive in that case.
`expectTypeOf().toMatchTypeOf()` is deprecated in vitest 4.0; the
non-deprecated equivalent is `toExtend()`. Swap it in the
MongoExecutionPlan command-shape assertion to silence the warning and
keep the type tests on the supported API.
The repository already standardises conditional optional-property spreads
on `ifDefined("key", value)` from `@prisma-next/utils/defined` (see callers
in `framework-components`, the CLI, the postgres adapter, etc.). The new
postgres runtime entry point was still using an inline
`...(options.middleware ? { middleware: options.middleware } : {})` spread.
Swap it for `ifDefined` so the call site reads consistently with the rest
of the codebase and benefits from the utility's sharper return type.
`verifyMarker()` already short-circuits when `this.verified` is true, but
the call site for `onFirstUse` still entered the async function on every
execute, paying a microtask for nothing once the runtime had been verified.
The `startup` branch above already gates on `!self.startupVerified` to
avoid that overhead — mirror it for `onFirstUse` by guarding on
`!self.verified`. Behaviour is unchanged; we just stop awaiting a
guaranteed no-op promise on the hot execute path.
…Plan

After the runtime-unification work canonicalised on `_row` (lowercase) as
the phantom property `ResultType<P>` inspects, the capital-R `_Row?` field
on `SqlQueryPlan` is just transitional cruft: no production code reads it,
and `ResultType` already extracts via the inherited `_row` from
`QueryPlan<Row>`.

Remove the unused property and the matching field in the
`SqlQueryPlanShape` test fixture, and refresh the JSDoc to point at the
canonical `_row` instead of describing the retired backwards-compat path.
…ayer section

Lines 285/288 already cite the runtime SPI with the subpath specifier
`@prisma-next/framework-components/runtime`, but the immediately-following
"Dependency Rules" paragraph used the bare `@prisma-next/framework-components`
specifier when describing the same imports, contradicting the surrounding
guidance. Switch the dependency-rules sentence to the same subpath
specifier so a reader copying the import path from this section gets the
canonical one.
…fication ordering

- Package-Layering.md: align all RuntimeCore / runtime SPI mentions on
  the @prisma-next/framework-components/runtime subpath (per ADR 204),
  removing the inconsistency CodeRabbit flagged at L172/L209/L282 where
  some references used the bare /framework-components path.
- subsystems/4. Runtime & Middleware Framework.md: rewrite the
  Sequence (high level) prose at L278 so it describes the same lifecycle
  as the Execution Pipeline section and SqlRuntimeImpl.executeAgainstQueryable():
  runBeforeCompile + lower run first, then contract verification (timing
  controlled by verify.mode = startup | onFirstUse | always), then
  middleware policy/budget application around the driver stream.

Refs PR #381 review threads PRRT_kwDOQM0QJc590M2b and PRRT_kwDOQM0QJc590M2g.
… 140

- ADR-INDEX.md: add ADR 204 (Single-tier runtime) under Runtime &
  Execution following the table style used for neighboring entries.
- ADR 140: add a top-of-file blockquote callout noting partial
  supersession by ADR 204 — specifically the "Runtime Separation"
  two-tier-runtime portion. Package-layering, plane-boundary, and
  naming guidance in ADR 140 is unchanged. Style follows the existing
  precedent at the top of ADR 167 and ADR 044.

Closes a close-out gap surfaced by the project audit ahead of merging
the cross-family runtime unification PR (#381).
Add the ./runtime subpath export to the "What this package provides"
list and the "Subpath exports" code sample. The export is in active use
across @prisma-next/sql-runtime, @prisma-next/sql-orm-client, and
@prisma-next/mongo-runtime; per ADR 204 it is the canonical location
for the runtime SPI (RuntimeCore, runWithMiddleware, RuntimeMiddleware)
and the README should reflect that.

Closes a close-out gap surfaced by the project audit ahead of merging
PR #381.
…s on PR merge

Make explicit in the drive-project-workflow rule and the drive-generate-plan
skill that close-out tasks must not include manual Linear issue closure.
Linear auto-transitions a linked issue to the team completed state when its
PR merges, provided the PR or branch references the issue identifier.

Manual closure is redundant and risks landing the issue in the wrong
completed state (e.g. Done while the team convention is Ready to be merged),
and adds noise to the Linear activity log.

In-progress / in-review state transitions during execution remain fine and
useful for visibility.
…rename

Conflict-resolution follow-up to rebase onto origin/main: PR #379
(`feat(codec): single-path async codec runtime`) added
`test/codec-async.test.ts` referencing `ExecutionPlan` from
`@prisma-next/contract/types`, which TML-2242 removed when migrating
the SQL family to `SqlExecutionPlan` from `@prisma-next/sql-relational-
core/plan`. Update the test to import `SqlExecutionPlan` so it lines up
with the post-rebase types.

Pure conflict-resolution; no behavior change.
@wmadden wmadden force-pushed the tml-2242-unified-runtime-executor-and-query-plan-interfaces-across branch from d7b05f5 to 24ccd18 Compare April 27, 2026 16:00
The Usage example in `packages/2-sql/5-runtime/README.md` references
`budgets()` in the `createRuntime({ middleware: [budgets()] })` call but
never imports it, so a copy/paste of the snippet would not type-check or
run as written. Adding `budgets` to the existing named import from
`@prisma-next/sql-runtime` (where it is re-exported from
`./middleware/budgets`) makes the example self-contained.

Addresses CodeRabbit finding from
#381 (review)
("Add the missing `budgets` import to the usage example", outside diff
range).
@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented Apr 27, 2026

@coderabbitai — addressing the review at #pullrequestreview-4180591712. Per-finding response:

Will address (1):

  • `packages/2-sql/5-runtime/README.md` — missing `budgets` import in Usage example (outside diff range): Done in `9f4ce75dc`. `budgets` is now part of the named import from `@prisma-next/sql-runtime` so the snippet is self-contained.

Defer (1):

  • `packages/2-sql/5-runtime/src/sql-runtime.ts` 438–439 — `withTransaction()` leaks the connection if `connection.transaction()` rejects (outside diff range): Acknowledging the finding — this is real but pre-existing, not introduced by TML-2242. `git blame -L 439,444 packages/2-sql/5-runtime/src/sql-runtime.ts` resolves to commit `a21bf7134` (Apr 23, 2026 — feat(sql-runtime): add callback-based transaction API feat(sql-runtime): add callback-based transaction API #346), which is already on `origin/main` and predates this branch. Fixing it would change observable behavior on transaction-begin failures (currently the connection is implicitly leaked; the suggested fix releases/destroys it), which conflicts with the project's R6 invariant ("observable behavior is bit-equivalent before/after the refactor"). It's the same SQL connection / transaction wrapper safety family as the closed-flag / fail-fast finding from #pullrequestreview-4180591712 that we deferred earlier today, so I'm folding it into the same follow-up: TML-2333 — SQL RuntimeConnection/RuntimeTransaction: invalidate wrappers on teardown. I've left a note on TML-2333 to expand its scope to cover the `withTransaction` connection-leak case alongside the wrapper closed-flag work.

Already fixed (1):

  • `packages/2-sql/5-runtime/src/sql-runtime.ts` 301–317 / 322–337 — connection / transaction wrappers should track a closed flag and fail-fast (re-mentioned in the autofix prompt): This is the same finding that was raised on thread #pullrequestreview-4180591712 (`PRRT_kwDOQM0QJc590M2j`), triaged earlier today, and resolved with a deferral to TML-2333. No new action.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

Tip

For best results, initiate chat on the files or code changes.

@wmadden Thanks for the thorough triage.

Confirmed fixed ✓

  • packages/2-sql/5-runtime/README.md — missing budgets import (9f4ce75dc) — noted; the snippet is now self-contained.

Deferred — acknowledged

  • withTransaction() connection-leak on connection.transaction() rejection — the pre-existence attribution (a21bf7134 / #346, already on main) and the R6 bit-equivalence invariant are valid grounds to defer. Folding it into TML-2333 alongside the wrapper closed-flag work is the right grouping.

Already handled — no new action

  • Connection / transaction wrapper closed-flag / fail-fast — confirmed same finding, same TML-2333 deferral; nothing further needed here.

wmadden added 2 commits April 28, 2026 06:25
…ily-runtime example

Restructure ADR 204 so a fresh-eyes reader gets the decision and a
concrete shape first, before the history of the world being replaced.

- Lead with Decision (no longer buried under context).
- Add "What this looks like" section with a SqlRuntimeImpl extends
  RuntimeCore snippet and a text-art lifecycle diagram of the inherited
  execute() template.
- Frame why RuntimeCore belongs in the framework layer: it owns
  behavior (when/how/which lifecycle steps), not plan shape; QueryPlan
  and ExecutionPlan are generic parameters narrowed by each family.
- Compress the two-tier history into a shorter Background section.
- Collapse the rationale list into a 3-item narrative (one lifecycle
  template / one orchestrator / one SPI surface).
- Tighten Trade-offs to two honest costs without re-pleading rationale.
- Drop the file-level "Affected source" enumeration (changelog detail
  recoverable from git) and the redundant "Decision record" footer.
- Keep all three Alternatives Considered and the dependency-direction
  enforcement chain intact.
`SqlRuntimeImpl.runBeforeCompile` only spread the rewritten AST onto the
returned plan, dropping the rewritten `meta.paramDescriptors` that
`runBeforeCompileChain` derives from the new AST. When a beforeCompile
middleware injected new ParamRefs (e.g. a `WHERE id = ?` filter), the
adapter would emit lowered params for those refs while `encodeParams`
still saw the stale, pre-rewrite descriptor count, throwing
`RUNTIME.MISSING_PARAM_DESCRIPTOR`.

Propagate `rewrittenDraft.meta` alongside `rewrittenDraft.ast` so the
descriptors stay in lockstep with the params the adapter emits.

Restores the integration tests:
- test/rewriting-middleware.integration.test.ts > single middleware rewrite
- test/rewriting-middleware.integration.test.ts > chains multiple middlewares
@wmadden wmadden force-pushed the tml-2242-unified-runtime-executor-and-query-plan-interfaces-across branch from af84bf2 to 85c3430 Compare April 28, 2026 04:40
@wmadden wmadden merged commit 77f65f6 into main Apr 28, 2026
18 checks passed
wmadden added a commit that referenced this pull request Apr 28, 2026
…fication ordering

- Package-Layering.md: align all RuntimeCore / runtime SPI mentions on
  the @prisma-next/framework-components/runtime subpath (per ADR 204),
  removing the inconsistency CodeRabbit flagged at L172/L209/L282 where
  some references used the bare /framework-components path.
- subsystems/4. Runtime & Middleware Framework.md: rewrite the
  Sequence (high level) prose at L278 so it describes the same lifecycle
  as the Execution Pipeline section and SqlRuntimeImpl.executeAgainstQueryable():
  runBeforeCompile + lower run first, then contract verification (timing
  controlled by verify.mode = startup | onFirstUse | always), then
  middleware policy/budget application around the driver stream.

Refs PR #381 review threads PRRT_kwDOQM0QJc590M2b and PRRT_kwDOQM0QJc590M2g.
wmadden added a commit that referenced this pull request Apr 28, 2026
… 140

- ADR-INDEX.md: add ADR 204 (Single-tier runtime) under Runtime &
  Execution following the table style used for neighboring entries.
- ADR 140: add a top-of-file blockquote callout noting partial
  supersession by ADR 204 — specifically the "Runtime Separation"
  two-tier-runtime portion. Package-layering, plane-boundary, and
  naming guidance in ADR 140 is unchanged. Style follows the existing
  precedent at the top of ADR 167 and ADR 044.

Closes a close-out gap surfaced by the project audit ahead of merging
the cross-family runtime unification PR (#381).
wmadden added a commit that referenced this pull request Apr 28, 2026
Add the ./runtime subpath export to the "What this package provides"
list and the "Subpath exports" code sample. The export is in active use
across @prisma-next/sql-runtime, @prisma-next/sql-orm-client, and
@prisma-next/mongo-runtime; per ADR 204 it is the canonical location
for the runtime SPI (RuntimeCore, runWithMiddleware, RuntimeMiddleware)
and the README should reflect that.

Closes a close-out gap surfaced by the project audit ahead of merging
PR #381.
wmadden added a commit that referenced this pull request Apr 28, 2026
The Usage example in `packages/2-sql/5-runtime/README.md` references
`budgets()` in the `createRuntime({ middleware: [budgets()] })` call but
never imports it, so a copy/paste of the snippet would not type-check or
run as written. Adding `budgets` to the existing named import from
`@prisma-next/sql-runtime` (where it is re-exported from
`./middleware/budgets`) makes the example self-contained.

Addresses CodeRabbit finding from
#381 (review)
("Add the missing `budgets` import to the usage example", outside diff
range).
@wmadden wmadden deleted the tml-2242-unified-runtime-executor-and-query-plan-interfaces-across branch April 28, 2026 04:40
wmadden added a commit that referenced this pull request May 4, 2026
…fication ordering

- Package-Layering.md: align all RuntimeCore / runtime SPI mentions on
  the @prisma-next/framework-components/runtime subpath (per ADR 204),
  removing the inconsistency CodeRabbit flagged at L172/L209/L282 where
  some references used the bare /framework-components path.
- subsystems/4. Runtime & Middleware Framework.md: rewrite the
  Sequence (high level) prose at L278 so it describes the same lifecycle
  as the Execution Pipeline section and SqlRuntimeImpl.executeAgainstQueryable():
  runBeforeCompile + lower run first, then contract verification (timing
  controlled by verify.mode = startup | onFirstUse | always), then
  middleware policy/budget application around the driver stream.

Refs PR #381 review threads PRRT_kwDOQM0QJc590M2b and PRRT_kwDOQM0QJc590M2g.
wmadden added a commit that referenced this pull request May 4, 2026
… 140

- ADR-INDEX.md: add ADR 204 (Single-tier runtime) under Runtime &
  Execution following the table style used for neighboring entries.
- ADR 140: add a top-of-file blockquote callout noting partial
  supersession by ADR 204 — specifically the "Runtime Separation"
  two-tier-runtime portion. Package-layering, plane-boundary, and
  naming guidance in ADR 140 is unchanged. Style follows the existing
  precedent at the top of ADR 167 and ADR 044.

Closes a close-out gap surfaced by the project audit ahead of merging
the cross-family runtime unification PR (#381).
wmadden added a commit that referenced this pull request May 4, 2026
Add the ./runtime subpath export to the "What this package provides"
list and the "Subpath exports" code sample. The export is in active use
across @prisma-next/sql-runtime, @prisma-next/sql-orm-client, and
@prisma-next/mongo-runtime; per ADR 204 it is the canonical location
for the runtime SPI (RuntimeCore, runWithMiddleware, RuntimeMiddleware)
and the README should reflect that.

Closes a close-out gap surfaced by the project audit ahead of merging
PR #381.
wmadden added a commit that referenced this pull request May 4, 2026
The Usage example in `packages/2-sql/5-runtime/README.md` references
`budgets()` in the `createRuntime({ middleware: [budgets()] })` call but
never imports it, so a copy/paste of the snippet would not type-check or
run as written. Adding `budgets` to the existing named import from
`@prisma-next/sql-runtime` (where it is re-exported from
`./middleware/budgets`) makes the example self-contained.

Addresses CodeRabbit finding from
#381 (review)
("Add the missing `budgets` import to the usage example", outside diff
range).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant