Skip to content

feat(codec-registration-completion): unify codec registration (TML-2357)#417

Merged
wmadden merged 156 commits intomainfrom
tml-2357-codec-registration-model-complete-the-unified
May 9, 2026
Merged

feat(codec-registration-completion): unify codec registration (TML-2357)#417
wmadden merged 156 commits intomainfrom
tml-2357-codec-registration-model-complete-the-unified

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented May 1, 2026

Status: ready for review. All milestones complete; all 14 acceptance criteria PASS or LANDED at HEAD; validation gates green workspace-wide. Post-implementation surface cleanup (F9 + F10) and post-feedback hygiene round (F11–F39) landed on top.

Completes the registration-side migration that the parent codec-registry-unification project (merged via ADR 208) deliberately deferred. (TML-2357)

Spec & plan

Milestones

# Goal Spec ACs Status
M0 Class-based codec migration + per-codec helpers + Strength 3 deletion sweep AC-0, AC-1, AC-CB-1..6 SATISFIED at a210fa1c5
M1 Narrow runtime Codec instance + descriptor-keyed metadata reads AC-3 LANDED at 1be7564c4; reverified through M4
M2 Native descriptor migration + bridge / aliasCodec / arktypeJsonEmitCodec deletion AC-2, AC-4 ABSORBED into M0 (Phase B + Phase C)
M3 ParamRef.refs plumbing + encode-side forColumn + forCodecId retirement AC-5 SATISFIED at 3f0ec224a
M4 Delete JsonSchemaValidatorRegistry; retire 'json-validator' trait AC-6 SATISFIED at e055c9455
F9 + F10 Public-API surface cleanup: registry-only public surface; drop transition vocabulary hygiene SATISFIED at c4d81ad1c
F11–F39 Post-feedback hygiene round: 27 findings closed; F38 rejected; SQL CodecRegistry consolidated into CodecDescriptorRegistry hygiene + correctness SATISFIED at 0e3aafc0b
AC-7 Validation gates green AC-7 PASS at every milestone close + every hygiene-round close

What landed

  • Class-based codec hierarchy. interface CodecDescriptor<P> + abstract class CodecDescriptorImpl<P>, paired with interface Codec<Id, Traits, Wire, Input> + abstract class CodecImpl<...>. Per-codec column helpers (e.g. vectorColumn(N)) directly invoke descriptor.factory(params) to preserve method-level generics; satisfies ColumnHelperFor<D> ties helpers to their descriptor without polymorphism. AnyCodecDescriptor (alias for CodecDescriptor<any>) is the canonical heterogeneous-storage type.
  • Strength 3 forcing-function deletion. Every legacy carrier deleted: mkCodec, defineCodec, defineCodecGroup, defineCodecBundle, CodecDefBuilder*, synthesizeNonParameterizedDescriptor, instance-keyed ExtractCodecTypes, byScalar maps, dataTypes exports, sqlCodecDefinitions, codecDescriptorDefinitions, pgVectorRepresentativeCodec placeholder, parameterizedCodecs: slot, CodecParamsDescriptor, arktypeJsonEmitCodec, aliasCodec, aliasDescriptor function form, the 'json-validator' trait, JsonSchemaValidatorRegistry infrastructure, arktypeParamsSchema helper, the SQL-family CodecRegistry interface (consolidated into CodecDescriptorRegistry). Closing-grep zero call-sites.
  • ParamRef + ProjectionItem carry refs?: { table; column }; validateParamRefRefs builder-pipeline pass enforces refs for parameterized codec ids; encode/decode dispatch consults metadata.refs first via contractCodecs.forColumn(table, column).
  • JSON validation lives in the resolved codec's decode body (arktype-json's inline pattern from TML-2229). Decode-error envelope equivalence verified via codec-async.test.ts:408-456.
  • ColumnTypeDescriptor relocated from @prisma-next/contract-authoring (layer 2) to @prisma-next/framework-components (layer 1) so codec base types live with the framework primitives.
  • F8 portability fix (fae3bd688): CodecTypes exposed at the public exports/codec-types.ts entry point with a Resolve<T> materializer to break tsdown's chunk-private path reference and restore consumer-side typecheck.
  • F9 + F10 surface cleanup (3d57f9ecd..c4d81ad1c): each codec-shipping package now exposes only column helpers + a <package>CodecRegistry instance + type re-exports of descriptor types. Internal codecDescriptorMap / codecDescriptorClassList no longer surface through public exports. Transition vocabulary (Class suffixes, class-form / class-based in comments, codecs-class.ts filenames) scrubbed.

Post-feedback hygiene round (F11–F39)

19 commits between c4d81ad1c..0e3aafc0b close 27 findings surfaced from orchestrator-principal review and 30 GitHub PR review threads. Highlights:

  • F11 (f725db1f8) — rename ast/sql-codecs-class.tsast/sql-codecs.ts, split helpers into ast/sql-codec-helpers.ts.
  • F12 (7d56a39b4) — move parameterization predicate onto CodecDescriptorImpl.isParameterized getter; retire the standalone IsParameterizedCodecId callback type.
  • F13 + F14 + F20 (cfa078a23) — align arktype params schemas with TParams optionality ('length?': '...'); delete arktypeParamsSchema helper; consumer sites direct-assign with : StandardSchemaV1<TParams>. The arktype runtime dep stays in @prisma-next/contract because validate-contract.ts consumes it directly for structural validation — that's by design, not a follow-up.
  • F15 (1051f24e8) — replace unique symbol trait phantom with a string-key phantom property (__codecTraits) to avoid Node bundling failure modes.
  • F16 + F17 (083fff350, a278bd034) — rewrite codec-authoring-guide alias section + fix self-referential JSDoc helper-source reference.
  • F18 (7ee52fae0) — assert leaf scalar type in no-emit-typed-flow.test-d.ts to make AC-CB-6's literal claim explicit.
  • F19 + F31 + F32 + F33 (81c55248f, bc4e8d716) — harden extractCodecLookup: lift inline imports, tighten id to non-optional string, refine the silent catch so non-parameterized codecs throw immediately while parameterized factories that tolerate empty params still materialise representatives.
  • F21 (f1be14d55) — createStubAdapter returns a stable codec registry instance (no per-call rebuild).
  • F22 + F26 + F29 (20f99bffd) — dispatch correctness: refsFromLeft walks via collectColumnRefs to preserve refs for wrapping expressions; encode-side forColumn fall-through is structurally safe (F19 + ambiguousCodecIds rejection + byCodecId column-correct materialisation); pgvector length threaded into PgVectorCodec constructor with assertVector validating the dimension at every ingress.
  • F23 + F24 + F25 (48ed1d135) — type predicate isArktypeSchemaLike replaces blind cast in rehydrateSchema; @ts-expect-error replaces as any + biome-ignore in tests; toExtend replaces deprecated toMatchTypeOf matcher.
  • F27 (21b4cbca7, 0e3aafc0b) — retire SQL-family CodecRegistry.register() mutation surface in favour of buildCodecRegistry(descriptors) builder; phase-2 deletes the CodecRegistry interface entirely. Single registry surface in the SQL family is now CodecDescriptorRegistry.
  • F28 (9881a7efe) — buildCodecDescriptorRegistry throws on duplicate codecId.
  • F30 (7a3faf20f) — codecDescriptorMap relocated to core/codec-type-map.ts; Resolve<T> materialisation kept at the exports/ boundary per F8.
  • F34 + F35 + F36 (4178072fa) — postgres render hygiene: scale validation in pgNumericRenderOutputType; ISO 8601 regex for timestamps; string validation for enum values.
  • F37 (182d10c88) — SqliteDatetimeCodec rejects Invalid Date in decode/decodeJson.
  • F38rejected. Default identity codecs on CodecImpl would constrain its type signature and obscure where real conversion work happens. Convention stays: explicit identity overrides at codec-author site.
  • F39 (80ba4fd60) — enumParamsSchema and EnumParams tightened to readonly string[].

Closure-mechanism note for F22: the implementer chose a structural argument over fail-fast on forColumn miss — F19's refinement makes extractCodecLookup skip parameterized descriptors that don't tolerate empty params; buildContractCodecRegistry's ambiguousCodecIds set throws RUNTIME.TYPE_PARAMS_INVALID on multi-instance ids; for the non-ambiguous parameterized case byCodecId stores the column-correct per-instance codec. Reviewer cross-checked all three legs and accepted.

Notable side effect: 16 pre-existing e2e failures resolved by M3

Before M3, the e2e suite ran 75/91 with 16 failures of the form Codec '...' resolves to multiple parameterized instances; column-aware dispatch is required. — top-level field shortcuts (select('vectorCol')) emitted IdentifierRef AST that didn't carry (table, column) context, so decode-side resolveProjectionCodec fell back to forCodecId and threw. M3's ProjectionItem.refs extension + decode-side parity in decoding.ts closed the path. e2e is now 91/91.

Validation gates at HEAD 0e3aafc0b

Gate Result
pnpm typecheck PASS — 123/123
pnpm lint:deps PASS — 727 modules / 1444 deps / 0 violations
pnpm fixtures:check PASS — zero drift (demo emit byte-identical against origin/main)
pnpm build PASS — 62/62
pnpm test:e2e PASS — 91/91 (16 pre-existing failures resolved by M3)
pnpm test:packages PASS in scope (residual: pre-existing 7 sql-orm-client pgvector wire-format + TML-2402 parallel-flake)

Review artifacts

projects/codec-registration-completion/reviews/ carries three review artifacts produced by the reviewer subagent during orchestration. After user feedback that the initial structure didn't match the canonical skill output, all three were rewritten to conform to /drive-pr-local-review (flat F-numbered findings + AC verification table) and /drive-pr-walkthrough (intent-first semantic narrative). Final reviewer verdict at HEAD 0e3aafc0b: SATISFIED with 12 PASS / 2 WEAK on the AC scoreboard. The two WEAKs are AC-7 (acknowledged baseline test failures in sql-orm-client pgvector wire format + TML-2402 parallel flake) and AC-CB-5 (a single internal descriptor as unknown as AnyDescriptor cast inside buildCodecDescriptorRegistry — purely a registry-internal heterogeneous-storage erasure, not a public surface concern).

Linear follow-ups filed during close-out

  • TML-2402pnpm test:packages parallel-execution flake (adapter-postgres / cli / sql-orm-client; passes cleanly in isolation). P3.
  • TML-2403 — Turbo cache-keying gap on transitive AST/type-system changes (worked around with pnpm build --force). P4.
  • TML-2405 — Codec dispatch follow-up: reference codec instances on the lowered Plan instead of carrying (table, column) lookup keys on the AST. The current shape's validator pass is a smell; instance-on-Plan would retire forColumn/forCodecId from the runtime dispatch surface entirely. Architectural successor to this work. P3.

Out of scope

  • Mongo codec registration migration — folded into TML-2324 (Mongo runtime forColumn plumbing).
  • Renaming Codec — type name stays; only the field set narrows.
  • Reshaping the async codec runtime (ADR 204) or CodecCallContext (ADR 207).
  • pgEnumCodec placeholder factory audit (already clean at HEAD; documented in ADR 208 § Future work).
  • Retiring CodecLookup.get(id) and ProjectionItem.refs / ParamRef.refs lookup-key carriers from the AST — TML-2405.

Note on project artifacts

Per the user's mid-flight directive at close-out, projects/codec-registration-completion/ is preserved in-tree (the standard transient-directory deletion was reverted at 5b0113a5a). The directory's review artifacts under reviews/ are gitignored and don't appear in the diff; they live in the working tree only as historical context.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features

    • Unified descriptor-driven codec system and class-based codec authoring; per-codec column helpers.
    • Codecs now receive per-call context (AbortSignal + column provenance).
  • Documentation

    • Added codec authoring reference and multiple ADR updates clarifying descriptor and async model.
  • Improvements

    • Stronger parameter validation and improved output-type rendering for parameterized codecs.
    • Query builder/runtime now propagate column refs into expressions and parameter encoding.
  • Tests

    • Expanded type and runtime tests covering descriptor-driven flows and helpers.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: caa93e7f-c0af-4199-99e6-b9b3e60790ce

📥 Commits

Reviewing files that changed from the base of the PR and between 1c6f0bf and d60ab77.

📒 Files selected for processing (2)
  • .agents/rules/jsdoc-line-width.mdc
  • docs/architecture docs/adrs/ADR 208 - Higher-order codecs for parameterized types.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • .agents/rules/jsdoc-line-width.mdc

📝 Walkthrough

Walkthrough

This change rearchitects all codec authoring, registration, lookup, parameterization, column helpers, and downstream registry usage across every part of the framework, targets, adapters, and extensions to use a unified class-based descriptor and registry pattern. Old factory, registry, and parameterized codec split logic is completely supplanted. All tests, typegen, docs, contract logic, and downstream wiring are rewritten to match the new unified infrastructure.

Changes

Unified Codec Descriptor Registry Migration

Layer / File(s) Summary
Core descriptor and codec types
framework-components/src/shared/codec-descriptor.ts, .../codec.ts, .../column-spec.ts
Defines foundational codec descriptor interfaces and classes, base Codec interface and implementation, and column spec shapes with coercions and helper typings for use in descriptor-based codec systems.
Descriptor registry and framework/adapter integration
framework-components/src/control/control-stack.ts, src/shared/codec-types.ts, registry build/plumbing, framework core and adapter runtime wiring
Overhauls the framework’s codec registry construction to build lookup from codecDescriptors; updates control stack, wiring for registration/lookup, and adapter/runtime interactions to use the new descriptor-driven registry and metadata APIs.
Codec descriptor, columns, and implementations
SQL, Mongo, Postgres, SQLite, and extension codec implementations and exports
Rewrites all core, target, and extension codecs to use the class-based codec descriptor/instance/column helper pattern, ditching prior registry and builder outputs in favor of descriptor-driven lists and explicit parameter schemas with output type renderers.
Runtime dispatch, AST metadata, and validation
Runtime encode/decode, SQL AST nodes, param/column ref propagation, validation logic
Updates runtime and AST layers to use unified descriptor-driven codec registries and per-column materializations; enhances ParamRef and ProjectionItem AST nodes to carry binding metadata; enforces refs validation for parameterized codecs; removes legacy JSON-schema validator plumbing and updates output render logic.
Documentation, authoring guides, and tests
Docs, ADRs, authoring materials, type/runtime tests and integrations
Expands documentation and architecture decisions for unified codec descriptors; rewrites and adds tests for runtime codec behavior, registry integration, refs propagation, type inference, and parameterized codecs; introduces helpers for test codec construction.

Sequence Diagram(s)

sequenceDiagram
  participant Author
  participant CodecDescriptor
  participant Registry
  participant Runtime
  participant Consumer
  Author->>CodecDescriptor: implements CodecImpl, DescriptorImpl
  CodecDescriptor->>Registry: descriptor registration (array)
  Runtime->>Registry: lookup(by id, type, meta, render)
  Registry->>CodecDescriptor: .factory(params)
  Runtime->>Codec: encode/decode/render via registry
  Consumer->>Registry: typegen or metadata lookup
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ minutes

Possibly related PRs

  • prisma/prisma-next#402: The main PR implements the unified CodecDescriptor/descriptor-driven codec registry, descriptor factories, and emitter resolveFieldTypeParams changes that are the same core design and code-level modifications described in PR #402 (ADR 208), so they are directly related.
  • prisma/prisma-next#312: The main PR and retrieved PR are directly related: both implement the shift to descriptor-driven codec registration and codec-dispatched output-type rendering (adding/using renderOutputType and a codec lookup/descriptor registry), so the changes are related.
  • prisma/prisma-next#400: Main PR continues and expands the same codec call-context/AbortSignal work (ADR 207, CodecCallContext/SqlCodecCallContext, runtimeAborted/raceAgainstAbort and threaded ctx changes) introduced in PR #400 — related.

Suggested reviewers

  • SevInf
  • aqrln

Poem

In a warren of types and code,
Rabbits gathered the codecs owed.
No more bumpy registry roads—
Descriptors hop in neat abode.
Helpers line with pointed ears,
Fields and params trust their peers.
A carrot cheers, for change appears! 🥕🐇

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2357-codec-registration-model-complete-the-unified

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 1, 2026

Open in StackBlitz

@prisma-next/mongo-runtime

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

@prisma-next/family-mongo

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

@prisma-next/sql-runtime

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

@prisma-next/family-sql

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

@prisma-next/extension-arktype-json

npm i https://pkg.pr.new/@prisma-next/extension-arktype-json@417

@prisma-next/middleware-telemetry

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

@prisma-next/mongo

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

@prisma-next/extension-paradedb

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

@prisma-next/extension-pgvector

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

@prisma-next/postgres

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

@prisma-next/sql-orm-client

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

@prisma-next/sqlite

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

@prisma-next/target-mongo

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

@prisma-next/adapter-mongo

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

@prisma-next/driver-mongo

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

@prisma-next/contract

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

@prisma-next/utils

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

@prisma-next/config

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

@prisma-next/errors

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

@prisma-next/framework-components

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

@prisma-next/operations

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

@prisma-next/ts-render

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

@prisma-next/contract-authoring

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

@prisma-next/ids

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

@prisma-next/psl-parser

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

@prisma-next/psl-printer

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

@prisma-next/cli

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

@prisma-next/emitter

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

@prisma-next/migration-tools

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

prisma-next

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

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

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

@prisma-next/mongo-codec

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

@prisma-next/mongo-contract

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

@prisma-next/mongo-value

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

@prisma-next/mongo-contract-psl

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

@prisma-next/mongo-contract-ts

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

@prisma-next/mongo-emitter

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

@prisma-next/mongo-schema-ir

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

@prisma-next/mongo-query-ast

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

@prisma-next/mongo-orm

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

@prisma-next/mongo-query-builder

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

@prisma-next/mongo-lowering

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

@prisma-next/mongo-wire

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

@prisma-next/sql-contract

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

@prisma-next/sql-errors

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

@prisma-next/sql-operations

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

@prisma-next/sql-schema-ir

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

@prisma-next/sql-contract-psl

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

@prisma-next/sql-contract-ts

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

@prisma-next/sql-contract-emitter

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

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

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

@prisma-next/sql-relational-core

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

@prisma-next/sql-builder

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

@prisma-next/target-postgres

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

@prisma-next/target-sqlite

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

@prisma-next/adapter-postgres

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

@prisma-next/adapter-sqlite

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

@prisma-next/driver-postgres

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

@prisma-next/driver-sqlite

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

commit: d60ab77

@wmadden wmadden force-pushed the tml-2357-codec-registration-model-complete-the-unified branch from 5e0dee5 to 692178c Compare May 1, 2026 18:12
@wmadden wmadden marked this pull request as ready for review May 8, 2026 05:58
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: 13

Caution

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

⚠️ Outside diff range comments (1)
packages/2-sql/5-runtime/src/sql-context.ts (1)

493-516: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don't collapse non-parameterized column codecs to one instance per codecId.

CodecInstanceContext is per materialization site, but this cache makes contractCodecs.forColumn() hand back the same codec instance for every column sharing a non-parameterized id. The first column wins the captured ctx.name / usedAt, so any non-parameterized codec that derives state from column context will behave incorrectly.

🛠️ Safer materialization shape
         } else if (!isParameterized) {
-          let cached = byCodecId.get(column.codecId);
-          if (!cached) {
-            const ctx: SqlCodecInstanceContext = {
-              name: `<shared:${column.codecId}>`,
-              usedAt: [{ table: tableName, column: columnName }],
-            };
-            const voidFactory = descriptor.factory as unknown as (
-              params: undefined,
-            ) => (ctx: SqlCodecInstanceContext) => Codec;
-            cached = voidFactory(undefined)(ctx);
-            byCodecId.set(column.codecId, cached);
-          }
-          resolvedCodec = cached;
+          const ctx: SqlCodecInstanceContext = {
+            name: `<anon:${tableName}.${columnName}>`,
+            usedAt: [{ table: tableName, column: columnName }],
+          };
+          const voidFactory = descriptor.factory as unknown as (
+            params: undefined,
+          ) => (ctx: SqlCodecInstanceContext) => Codec;
+          resolvedCodec = voidFactory(undefined)(ctx);
+          byCodecId.set(column.codecId, byCodecId.get(column.codecId) ?? resolvedCodec);
         }

If you still want a codec-id fallback, keep that representative instance separate from the per-column instances rather than reusing the column-scoped object for every site.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/2-sql/5-runtime/src/sql-context.ts` around lines 493 - 516, The code
currently caches the concrete Codec instance in byCodecId (via
voidFactory(undefined)(ctx)), causing every non-parameterized column to share
the same instance and captured ctx; instead cache the parameterless factory
function and invoke it per-column so each materialization site gets its own
Codec with its own SqlCodecInstanceContext. Concretely: in the branch that
handles non-parameterized codecs (where descriptor.factory is cast to
voidFactory), store the function returned by voidFactory(undefined) in byCodecId
(not the result of calling it with ctx), then for each column call that cached
factory with a fresh SqlCodecInstanceContext to produce resolvedCodec; update
uses of cached/voidFactory/byCodecId/resolvedCodec accordingly so
contractCodecs.forColumn() returns per-column instances.
🧹 Nitpick comments (7)
examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts (1)

20-22: ⚡ Quick win

Use package-export imports in this example test

Line 20 and Line 21 import internals via relative paths. For examples/**/test/**, this should validate the public API surface by importing from package exports (@prisma-next/...) instead.

As per coding guidelines, “Cross-package and integration tests: Import from package exports (@prisma-next/...) to verify the public API.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts` around lines 20
- 22, The test imports package internals via relative paths; update the imports
to use the package-export public API instead: replace the relative imports that
bring in the types/symbols "contract" and "sql" with their corresponding
exported package paths so the test validates the public surface (import the
"contract" type and the "sql" helper from the package exports for
prisma/prisma-no-emit rather than from ../prisma/contract and
../src/prisma-no-emit/context).
packages/2-sql/4-lanes/relational-core/test/utils.ts (1)

4-11: ⚡ Quick win

Avoid /exports/ barrel imports in this test utility.

Line 10 and Line 11 import through ../src/exports/*; switch these to direct module imports to keep dependency boundaries explicit.

As per coding guidelines: “Avoid barrel files for exports; use direct file imports instead” and “Import from shared plane packages using package name and export identifier … not /exports/ paths.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/2-sql/4-lanes/relational-core/test/utils.ts` around lines 4 - 11,
The test utility currently imports Adapter, Codec, CodecRegistry,
LoweredStatement, SelectAst and ExecutionContext from barrel paths
('../src/exports/*'); change these to import the same symbols directly from
their concrete modules (the specific source files that define Adapter, Codec,
CodecRegistry, LoweredStatement, SelectAst and ExecutionContext) so you avoid
`/exports/` barrel imports and keep dependency boundaries explicit; update the
import statements to reference the original modules that declare those types and
remove the barrel paths.
packages/3-targets/3-targets/postgres/src/core/codecs.ts (1)

55-72: 💤 Low value

Redundant undefined check for precision parameter.

The function parameter declares precision as readonly precision: number (required), but line 60 checks if (precision === undefined). This check is unreachable given the type signature.

If precision can actually be undefined at runtime (e.g., from untyped callers), consider changing the type to readonly precision?: number. Otherwise, remove the redundant check.

♻️ Suggested fix if precision is guaranteed
 export const pgNumericRenderOutputType = (typeParams: {
   readonly precision: number;
   readonly scale?: number;
 }): string | undefined => {
   const precision = typeParams.precision;
-  if (precision === undefined) return undefined;
   if (
     typeof precision !== 'number' ||
     !Number.isFinite(precision) ||
     !Number.isInteger(precision)
   ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-targets/3-targets/postgres/src/core/codecs.ts` around lines 55 -
72, The check for precision being undefined in pgNumericRenderOutputType is
unreachable because typeParams declares readonly precision: number; remove the
if (precision === undefined) return undefined; branch and any related
early-return logic; alternatively, if precision can be missing at runtime,
change the signature to readonly precision?: number and keep the check —
reference the function name pgNumericRenderOutputType and the property
typeParams.precision when making the change.
packages/2-sql/2-authoring/contract-psl/test/fixtures.ts (1)

160-164: ⚡ Quick win

Harden codec-id presence checks with Object.hasOwn.

Line 160 and Line 163 currently rely on plain index lookups, which can accidentally treat prototype keys (for example, "constructor") as valid codec ids.

Suggested patch
 export const postgresCodecLookup: CodecLookup = {
   get: (id: string) => {
-    if (!targetTypesByCodecId[id]) return undefined;
+    if (!Object.hasOwn(targetTypesByCodecId, id)) return undefined;
     return { id } as ReturnType<CodecLookup['get']>;
   },
-  targetTypesFor: (id: string) => targetTypesByCodecId[id],
+  targetTypesFor: (id: string) =>
+    Object.hasOwn(targetTypesByCodecId, id) ? targetTypesByCodecId[id] : undefined,
   metaFor: () => undefined,
   renderOutputTypeFor: () => undefined,
 };

As per coding guidelines "Always use Object.hasOwn() instead of hasOwnProperty() to check for own properties."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/2-sql/2-authoring/contract-psl/test/fixtures.ts` around lines 160 -
164, Replace plain property index checks on targetTypesByCodecId with
Object.hasOwn to avoid treating prototype keys as valid codec ids: in the
implementation returning ReturnType<CodecLookup['get']> change the existence
check from if (!targetTypesByCodecId[id]) to if
(!Object.hasOwn(targetTypesByCodecId, id)) and in the targetTypesFor method
ensure it only returns targetTypesByCodecId[id] when
Object.hasOwn(targetTypesByCodecId, id) (otherwise return undefined); leave
metaFor as-is.
packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts (1)

249-249: 💤 Low value

Use toExtend instead of deprecated toMatchTypeOf.

Per coding guidelines, toMatchTypeOf() is deprecated in Vitest's expectTypeOf API. Use toExtend<T>() instead.

♻️ Proposed fix
-  expectTypeOf<typeof reg>().toMatchTypeOf<Map<string, AnyCodecDescriptor>>();
+  expectTypeOf<typeof reg>().toExtend<Map<string, AnyCodecDescriptor>>();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts`
at line 249, Replace the deprecated expectTypeOf(...).toMatchTypeOf usage with
the supported generic toExtend form: locate the assertion using reg
(expectTypeOf<typeof reg>().toMatchTypeOf<Map<string, AnyCodecDescriptor>>())
and change it to use toExtend with the same generic type (expectTypeOf<typeof
reg>().toExtend<Map<string, AnyCodecDescriptor>>()); ensure the generic
parameter remains Map<string, AnyCodecDescriptor> and the assertion target
remains typeof reg.
packages/1-framework/1-core/framework-components/src/shared/column-spec.ts (1)

34-55: ⚡ Quick win

Thread the TCodecId generic through ColumnSpec to preserve codec ID literals in helper return types.

ColumnTypeDescriptor is generic in TCodecId, but ColumnSpec and the column() function drop this parameter. Codec ID literals widen to string at the helper boundary, losing type precision that downstream code (e.g., contract-dsl.ts) already extracts via Descriptor['codecId']. Threading the generic would maintain literal fidelity through the helper surface and align with the field-state pattern used in contract authoring.

♻️ Suggested type-surface fix
-export interface ColumnSpec<R, P extends Record<string, unknown> | undefined>
-  extends ColumnTypeDescriptor {
+export interface ColumnSpec<
+  TCodecId extends string,
+  R,
+  P extends Record<string, unknown> | undefined,
+> extends ColumnTypeDescriptor<TCodecId> {
   readonly codecFactory: (ctx: CodecInstanceContext) => R;
   readonly typeParams: P;
 }

-export function column<R, P extends Record<string, unknown> | undefined>(
+export function column<
+  TCodecId extends string,
+  R,
+  P extends Record<string, unknown> | undefined,
+>(
   codecFactory: (ctx: CodecInstanceContext) => R,
-  codecId: string,
+  codecId: TCodecId,
   typeParams: P,
   nativeType: string,
-): ColumnSpec<R, P> {
+): ColumnSpec<TCodecId, R, P> {
   return {
     codecFactory,
     codecId,
     typeParams,
     nativeType,
   };
 }

 export type ColumnHelperFor<D extends CodecDescriptor<any>> = (
   ...args: any[]
-) => ColumnSpec<unknown, ColumnHelperParams<D>>;
+) => ColumnSpec<D['codecId'], unknown, ColumnHelperParams<D>>;

 export type ColumnHelperForStrict<D extends CodecDescriptor<any>> = (
   ...args: any[]
-) => ColumnSpec<ReturnType<ReturnType<D['factory']>>, ColumnHelperParams<D>>;
+) => ColumnSpec<
+  D['codecId'],
+  ReturnType<ReturnType<D['factory']>>,
+  ColumnHelperParams<D>
+>;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/1-framework/1-core/framework-components/src/shared/column-spec.ts`
around lines 34 - 55, ColumnSpec currently drops the TCodecId generic from
ColumnTypeDescriptor which widens codecId literals to string; update ColumnSpec
to be generic in TCodecId and extend ColumnTypeDescriptor<TCodecId> (e.g. change
the declaration to something like interface ColumnSpec<TCodecId extends string,
R, P extends Record<string, unknown> | undefined> extends
ColumnTypeDescriptor<TCodecId>), keep the existing codecFactory and typeParams
members but use the P and R generics, and then propagate the TCodecId generic
through the column() helper signature so helper return types preserve codec ID
literals.
packages/3-extensions/sql-orm-client/src/types.ts (1)

302-305: ⚡ Quick win

Use ifDefined() instead of inline conditional object spreads in param().

Line 302-Line 305 currently uses inline spread conditionals; this codepath should use the shared helper for consistency with repo conventions.

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-extensions/sql-orm-client/src/types.ts` around lines 302 - 305,
The inline conditional spreads in param() should be replaced with the shared
helper ifDefined from `@prisma-next/utils/defined`: import ifDefined and pass
ParamRef.of(value, ifDefined({ codecId }, { refs })) (or a single ifDefined call
that combines the optional codecId and refs objects) instead of the current
...(codecId !== undefined ? { codecId } : {}), ...(refs !== undefined ? { refs }
: {}); update the param() return to use ifDefined and remove the inline
conditional spreads while keeping ParamRef.of and the same option shape.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/architecture` docs/adrs/ADR 184 - Codec-owned value serialization.md:
- Line 59: The paragraph claims "the defineCodec() factory provides these
defaults" but defineCodec() is retired; update the text that describes
encodeJson/decodeJson to either mark the defineCodec() statement as historical
("historically, defineCodec() provided these defaults") or reword it to the
current authoring surface (e.g., explain that the codec class/descriptor default
implementations make encodeJson/decodeJson identity for JSON-safe types and only
Date/binary codecs override them); do the same for the duplicate instance of
this sentence elsewhere so the ADR is internally consistent.

In `@docs/reference/codec-authoring-guide.md`:
- Around line 262-269: Update the docs' references that point to old filenames
so readers are directed to the new class-style implementations: change mentions
of the pre-migration files (e.g. "sql-codecs.ts" and "codecs.ts") to the
migrated filenames "sql-codecs-class.ts" and "codecs-class.ts" in the paragraphs
that describe the aliasCodec helper, CodecDescriptorImpl<P>, and the alias
factory pattern (around the aliasCodec/CodecDescriptorImpl example); ensure any
other occurrences (including the similar text at lines ~320-331) are updated
consistently so the guide links to the current implementations.

In `@examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts`:
- Around line 27-32: The test title claims the User.id is a string but current
assertions only check presence; update the test "field.id.uuidv4() produces a
string-typed id field on User" to actually assert the scalar type (or rename the
test to reflect presence-only checks). Specifically, in the test referencing
UserStorageFields and IdField (from (typeof
contract.models)['User']['storage']['fields']), add a type-level assertion that
IdField's column (or the appropriate scalar property on IdField) is string-typed
(e.g., assert IdField['column'] equals string) using expectTypeOf, or change the
test name to remove the "string-typed" claim.

In `@packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts`:
- Around line 67-76: lengthParamsSchema currently requires length but
LengthParams marks it optional and the sqlCharColumn/sqlVarcharColumn helpers
default params to {} which produces descriptors that validateTypeParams later
rejects; either relax lengthParamsSchema to make length optional (change to
'length?') so bare char/varchar is supported, or make LengthParams require
length and stop defaulting params to {} in the helper functions (sqlCharColumn,
sqlVarcharColumn and the other affected helpers mentioned) so callers must
provide length; update validateTypeParams usage accordingly to match the chosen
contract.

In `@packages/2-sql/4-lanes/relational-core/test/utils.ts`:
- Around line 39-41: profile.codecs() currently returns a new empty registry
every call (via emptyCodecRegistry()), causing registered codecs to be lost
between calls; fix by creating a single stable registry instance (e.g., const
codecRegistry = emptyCodecRegistry()) and have profile.codecs() return that same
codecRegistry so registrations persist; update the utils.ts factory that defines
profile.codecs() to initialize the registry once (module-scope or closure) and
return it on each call, leaving emptyCodecRegistry() usage but only invoked
once.

In `@packages/2-sql/5-runtime/src/codecs/encoding.ts`:
- Around line 56-62: When metadata.refs is present the resolution must use the
column path only and must not fall back to id-based resolution; in the block
that checks contractCodecs.forColumn(metadata.refs.table, metadata.refs.column)
(symbols: metadata.refs, contractCodecs, forColumn), change the logic so that if
byColumn is falsy you stop resolution immediately (e.g. return undefined or
throw a clear error) instead of continuing to
contractCodecs.forCodecId(metadata.codecId) or registry.get(metadata.codecId);
this ensures a missing column lookup fails fast rather than downgrading to
codec-id dispatch.

In `@packages/3-extensions/arktype-json/src/core/arktype-json-codec-class.ts`:
- Around line 144-154: Replace the blind cast in rehydrateSchema by adding a
type predicate (e.g. isArktypeSchemaLike) and use it to assert the return of
ark.schema(jsonIr) is an ArktypeSchemaLike before returning; if the predicate
fails throw the same runtimeError (preserving ARKTYPE_JSON_CODEC_ID and jsonIr)
so invalid shapes are rejected instead of being force-cast; keep the existing
try/catch and error message behavior around ark.schema and runtimeError.

In `@packages/3-extensions/arktype-json/test/arktype-json-codec-class.test.ts`:
- Around line 75-79: The test uses an explicit any cast and a biome-ignore;
replace that with a TypeScript compile-time suppression: remove the "as any" and
the biome lint suppression, and instead place a single-line "@ts-expect-error —
intentionally passing non-callable to test runtime guard" immediately above the
arktypeJsonColumn(notASchema) call (leaving notASchema typed as an object), so
the runtime negative-path assertion remains but the test follows the repo rule
against any/biome ignores; target the arktypeJsonColumn call in
arktype-json-codec-class.test.ts when making this change.

In
`@packages/3-extensions/arktype-json/test/arktype-json-codec-class.types.test-d.ts`:
- Around line 140-142: The type-test assertion for variable col uses the
deprecated matcher toMatchTypeOf; update the expectTypeOf(col) call to use
toExtend with the same generic target type ColumnSpec<ArktypeJsonCodecClass<{
name: string; price: number }>, ArktypeJsonTypeParams> so the assertion reads
expectTypeOf(col).toExtend<...>(), keeping the same generics (ColumnSpec,
ArktypeJsonCodecClass, ArktypeJsonTypeParams) and not changing the tested
variable name col.

In `@packages/3-extensions/sql-orm-client/src/types.ts`:
- Around line 292-294: refsFromLeft currently only handles kind === 'column-ref'
which drops refs for other AnyExpression shapes (so result.buildAst() loses refs
and breaks codec dispatch); update refsFromLeft (and the comparison factory
usage that passes result.buildAst()) to preserve/collect refs for any expression
by returning refs found on the expression (e.g., expression.refs if present) or
by recursively extracting column-ref nodes from
BinaryExpr/Unary/Identifier/Literal wrappers so column refs are not lost (keep
the return type { table: string; column: string } | undefined or adjust to
return refs array if needed and update callers accordingly); also replace the
inline conditional spreads in param() that do ...(codecId !== undefined ? {
codecId } : {}) and ...(refs !== undefined ? { refs } : {}) with the ifDefined()
helper from '@prisma-next/utils/defined' (add the import) to follow the
repository guideline.

In `@packages/3-targets/3-targets/postgres/src/core/codecs-class.ts`:
- Around line 110-126: The TypeScript type LengthParams marks length as optional
but lengthParamsSchema requires it, causing runtime validation failures when
helpers (e.g., pgBitColumn) pass {} as params; update lengthParamsSchema to make
length optional (change the schema key to 'length?' with the same constraint) so
the runtime arktype matches the LengthParams type and existing callers that
default params = {} continue to validate correctly.

In `@packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts`:
- Around line 250-264: The decode paths (async decode and decodeJson) and the
encoder path (encode and encodeJson) should validate Date objects: after
constructing a Date in decode/decodeJson, check that date.getTime() is not NaN
and throw a TypeError (same contract message) for malformed/invalid ISO strings;
in encode/encodeJson ensure the provided Date is valid (check
isFinite(date.getTime()) or !isNaN) and throw TypeError if it is an Invalid Date
before calling toISOString; update the functions named encode, decode,
encodeJson, and decodeJson in codecs-class.ts accordingly.

---

Outside diff comments:
In `@packages/2-sql/5-runtime/src/sql-context.ts`:
- Around line 493-516: The code currently caches the concrete Codec instance in
byCodecId (via voidFactory(undefined)(ctx)), causing every non-parameterized
column to share the same instance and captured ctx; instead cache the
parameterless factory function and invoke it per-column so each materialization
site gets its own Codec with its own SqlCodecInstanceContext. Concretely: in the
branch that handles non-parameterized codecs (where descriptor.factory is cast
to voidFactory), store the function returned by voidFactory(undefined) in
byCodecId (not the result of calling it with ctx), then for each column call
that cached factory with a fresh SqlCodecInstanceContext to produce
resolvedCodec; update uses of cached/voidFactory/byCodecId/resolvedCodec
accordingly so contractCodecs.forColumn() returns per-column instances.

---

Nitpick comments:
In `@examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts`:
- Around line 20-22: The test imports package internals via relative paths;
update the imports to use the package-export public API instead: replace the
relative imports that bring in the types/symbols "contract" and "sql" with their
corresponding exported package paths so the test validates the public surface
(import the "contract" type and the "sql" helper from the package exports for
prisma/prisma-no-emit rather than from ../prisma/contract and
../src/prisma-no-emit/context).

In `@packages/1-framework/1-core/framework-components/src/shared/column-spec.ts`:
- Around line 34-55: ColumnSpec currently drops the TCodecId generic from
ColumnTypeDescriptor which widens codecId literals to string; update ColumnSpec
to be generic in TCodecId and extend ColumnTypeDescriptor<TCodecId> (e.g. change
the declaration to something like interface ColumnSpec<TCodecId extends string,
R, P extends Record<string, unknown> | undefined> extends
ColumnTypeDescriptor<TCodecId>), keep the existing codecFactory and typeParams
members but use the P and R generics, and then propagate the TCodecId generic
through the column() helper signature so helper return types preserve codec ID
literals.

In `@packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts`:
- Line 249: Replace the deprecated expectTypeOf(...).toMatchTypeOf usage with
the supported generic toExtend form: locate the assertion using reg
(expectTypeOf<typeof reg>().toMatchTypeOf<Map<string, AnyCodecDescriptor>>())
and change it to use toExtend with the same generic type (expectTypeOf<typeof
reg>().toExtend<Map<string, AnyCodecDescriptor>>()); ensure the generic
parameter remains Map<string, AnyCodecDescriptor> and the assertion target
remains typeof reg.

In `@packages/2-sql/2-authoring/contract-psl/test/fixtures.ts`:
- Around line 160-164: Replace plain property index checks on
targetTypesByCodecId with Object.hasOwn to avoid treating prototype keys as
valid codec ids: in the implementation returning ReturnType<CodecLookup['get']>
change the existence check from if (!targetTypesByCodecId[id]) to if
(!Object.hasOwn(targetTypesByCodecId, id)) and in the targetTypesFor method
ensure it only returns targetTypesByCodecId[id] when
Object.hasOwn(targetTypesByCodecId, id) (otherwise return undefined); leave
metaFor as-is.

In `@packages/2-sql/4-lanes/relational-core/test/utils.ts`:
- Around line 4-11: The test utility currently imports Adapter, Codec,
CodecRegistry, LoweredStatement, SelectAst and ExecutionContext from barrel
paths ('../src/exports/*'); change these to import the same symbols directly
from their concrete modules (the specific source files that define Adapter,
Codec, CodecRegistry, LoweredStatement, SelectAst and ExecutionContext) so you
avoid `/exports/` barrel imports and keep dependency boundaries explicit; update
the import statements to reference the original modules that declare those types
and remove the barrel paths.

In `@packages/3-extensions/sql-orm-client/src/types.ts`:
- Around line 302-305: The inline conditional spreads in param() should be
replaced with the shared helper ifDefined from `@prisma-next/utils/defined`:
import ifDefined and pass ParamRef.of(value, ifDefined({ codecId }, { refs }))
(or a single ifDefined call that combines the optional codecId and refs objects)
instead of the current ...(codecId !== undefined ? { codecId } : {}), ...(refs
!== undefined ? { refs } : {}); update the param() return to use ifDefined and
remove the inline conditional spreads while keeping ParamRef.of and the same
option shape.

In `@packages/3-targets/3-targets/postgres/src/core/codecs.ts`:
- Around line 55-72: The check for precision being undefined in
pgNumericRenderOutputType is unreachable because typeParams declares readonly
precision: number; remove the if (precision === undefined) return undefined;
branch and any related early-return logic; alternatively, if precision can be
missing at runtime, change the signature to readonly precision?: number and keep
the check — reference the function name pgNumericRenderOutputType and the
property typeParams.precision when making the change.
🪄 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: 69fcb105-9c82-4733-9268-a3018eb3c54d

📥 Commits

Reviewing files that changed from the base of the PR and between 1d8b709 and 2d4eb3b.

⛔ Files ignored due to path filters (6)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • projects/codec-registration-completion/plan.md is excluded by !projects/**
  • projects/codec-registration-completion/spec.md is excluded by !projects/**
  • projects/codec-registration-completion/specs/class-based-codec-design.spec.md is excluded by !projects/**
  • projects/codec-registration-completion/specs/factory-defined-codec-types.spec.md is excluded by !projects/**
  • projects/codec-registration-completion/specs/typed-codec-flow.spec.md is excluded by !projects/**
📒 Files selected for processing (218)
  • docs/README.md
  • docs/Testing Guide.md
  • docs/architecture docs/adrs/ADR 152 - Execution Plane Descriptors and Instances.md
  • docs/architecture docs/adrs/ADR 184 - Codec-owned value serialization.md
  • docs/architecture docs/adrs/ADR 186 - Codec-dispatched type rendering.md
  • docs/architecture docs/adrs/ADR 202 - Codec trait system.md
  • docs/architecture docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md
  • docs/architecture docs/adrs/ADR 205 - SQL cast emission is adapter policy.md
  • docs/architecture docs/adrs/ADR 207 - Codec call context per-query AbortSignal and column metadata.md
  • docs/architecture docs/adrs/ADR 208 - Higher-order codecs for parameterized types.md
  • docs/architecture docs/adrs/ADR 209 - Mongo result-shape as a structural plan field.md
  • docs/architecture docs/subsystems/2. Contract Emitter & Types.md
  • docs/reference/codec-authoring-guide.md
  • docs/reference/community-generator-migration-analysis.md
  • docs/reference/framework-gaps.md
  • docs/reference/typescript-patterns.md
  • examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
  • packages/1-framework/0-foundation/contract/package.json
  • packages/1-framework/0-foundation/contract/src/exports/types.ts
  • packages/1-framework/0-foundation/contract/src/standard-schema-utils.ts
  • packages/1-framework/1-core/framework-components/README.md
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/1-framework/1-core/framework-components/src/exports/codec.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-types.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec.ts
  • packages/1-framework/1-core/framework-components/src/shared/column-spec.ts
  • packages/1-framework/1-core/framework-components/src/shared/framework-components.ts
  • packages/1-framework/1-core/framework-components/test/codec-call-context.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/codec-types.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/codec.test.ts
  • packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/control-stack.test.ts
  • packages/1-framework/2-authoring/contract/README.md
  • packages/1-framework/2-authoring/contract/src/descriptors.ts
  • packages/1-framework/2-authoring/contract/src/index.ts
  • packages/1-framework/2-authoring/contract/test/descriptors.test.ts
  • packages/1-framework/2-authoring/ids/package.json
  • packages/1-framework/2-authoring/ids/src/index.ts
  • packages/1-framework/3-tooling/cli/src/control-api/contract-enrichment.ts
  • packages/1-framework/3-tooling/cli/test/config-types.test.ts
  • packages/1-framework/3-tooling/cli/test/control-api/contract-enrichment.test.ts
  • packages/1-framework/3-tooling/emitter/src/domain-type-generation.ts
  • packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/README.md
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codec-registry.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codecs.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/exports/index.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/src/derive-json-schema.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/derive-json-schema.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.polymorphism.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.test.ts
  • packages/2-mongo-family/7-runtime/README.md
  • packages/2-mongo-family/7-runtime/src/mongo-execution-stack.ts
  • packages/2-mongo-family/7-runtime/test/codecs/decoding.test.ts
  • packages/2-mongo-family/7-runtime/test/decode.integration.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-stack.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-middleware.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime-abort.test.ts
  • packages/2-sql/2-authoring/contract-psl/src/provider.ts
  • packages/2-sql/2-authoring/contract-psl/test/fixtures.ts
  • packages/2-sql/2-authoring/contract-psl/test/provider.test.ts
  • packages/2-sql/2-authoring/contract-psl/test/ts-psl-parity.test.ts
  • packages/2-sql/2-authoring/contract-ts/src/contract-definition.ts
  • packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts
  • packages/2-sql/2-authoring/contract-ts/src/contract-lowering.ts
  • packages/2-sql/2-authoring/contract-ts/test/config-types.test.ts
  • packages/2-sql/2-authoring/contract-ts/test/contract-builder.contract-definition.test.ts
  • packages/2-sql/2-authoring/contract-ts/test/contract-builder.value-objects.test.ts
  • packages/2-sql/2-authoring/contract-ts/test/helpers/column-descriptor.ts
  • packages/2-sql/3-tooling/emitter/test/emitter-hook.typeref-resolver.test.ts
  • packages/2-sql/4-lanes/relational-core/README.md
  • packages/2-sql/4-lanes/relational-core/package.json
  • packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/validate-param-refs.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/ast.ts
  • packages/2-sql/4-lanes/relational-core/src/expression.ts
  • packages/2-sql/4-lanes/relational-core/src/query-lane-context.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory-ctx.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory-ctx.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-types.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/refs-propagation.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs-class.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs-class.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/test-codec.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/test-helpers.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/validate-param-refs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/expression.test.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/utils.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/builder-base.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/expression-impl.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/field-proxy.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/functions.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/mutation-impl.ts
  • packages/2-sql/4-lanes/sql-builder/test/runtime/field-proxy.test.ts
  • packages/2-sql/4-lanes/sql-builder/test/runtime/functions.test.ts
  • packages/2-sql/5-runtime/src/codecs/decoding.ts
  • packages/2-sql/5-runtime/src/codecs/encoding.ts
  • packages/2-sql/5-runtime/src/codecs/json-schema-validation.ts
  • packages/2-sql/5-runtime/src/sql-context.ts
  • packages/2-sql/5-runtime/src/sql-runtime.ts
  • packages/2-sql/5-runtime/test/before-compile-chain.test.ts
  • packages/2-sql/5-runtime/test/codec-async.test.ts
  • packages/2-sql/5-runtime/test/codec-decode-ctx.test.ts
  • packages/2-sql/5-runtime/test/codec-encode-ctx.test.ts
  • packages/2-sql/5-runtime/test/contract-codec-registry.test.ts
  • packages/2-sql/5-runtime/test/encoding-dispatch.test.ts
  • packages/2-sql/5-runtime/test/execution-stack.test.ts
  • packages/2-sql/5-runtime/test/json-schema-validation.test.ts
  • packages/2-sql/5-runtime/test/mutation-default-generators.test.ts
  • packages/2-sql/5-runtime/test/parameterized-types.test.ts
  • packages/2-sql/5-runtime/test/seeded-secret-codec.ts
  • packages/2-sql/5-runtime/test/sql-context.test.ts
  • packages/2-sql/5-runtime/test/sql-runtime-abort.test.ts
  • packages/2-sql/5-runtime/test/sql-runtime.test.ts
  • packages/2-sql/5-runtime/test/test-codec.ts
  • packages/2-sql/5-runtime/test/utils.ts
  • packages/3-extensions/arktype-json/README.md
  • packages/3-extensions/arktype-json/src/core/arktype-json-codec-class.ts
  • packages/3-extensions/arktype-json/src/core/arktype-json-codec.ts
  • packages/3-extensions/arktype-json/src/core/pack-meta.ts
  • packages/3-extensions/arktype-json/src/exports/codecs.ts
  • packages/3-extensions/arktype-json/src/exports/column-types.ts
  • packages/3-extensions/arktype-json/src/exports/control.ts
  • packages/3-extensions/arktype-json/src/exports/runtime.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec-class.test.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec-class.types.test-d.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.test-d.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts
  • packages/3-extensions/arktype-json/test/extension-descriptors.test.ts
  • packages/3-extensions/pgvector/src/core/codecs-class.ts
  • packages/3-extensions/pgvector/src/core/codecs.ts
  • packages/3-extensions/pgvector/src/core/descriptor-meta.ts
  • packages/3-extensions/pgvector/src/exports/column-types.ts
  • packages/3-extensions/pgvector/src/exports/runtime.ts
  • packages/3-extensions/pgvector/src/types/codec-types.ts
  • packages/3-extensions/pgvector/test/codec-render-output-type.test.ts
  • packages/3-extensions/pgvector/test/codecs-class.types.test-d.ts
  • packages/3-extensions/pgvector/test/codecs.test.ts
  • packages/3-extensions/pgvector/test/operations.test.ts
  • packages/3-extensions/pgvector/test/typed-descriptor-flow.test-d.ts
  • packages/3-extensions/sql-orm-client/src/query-plan-mutations.ts
  • packages/3-extensions/sql-orm-client/src/types.ts
  • packages/3-extensions/sql-orm-client/src/where-binding.ts
  • packages/3-extensions/sql-orm-client/test/codec-async.types.test-d.ts
  • packages/3-extensions/sql-orm-client/test/filters.test.ts
  • packages/3-extensions/sql-orm-client/test/integration/codec-async.test.ts
  • packages/3-extensions/sql-orm-client/test/integration/create.test.ts
  • packages/3-extensions/sql-orm-client/test/model-accessor.test.ts
  • packages/3-extensions/sql-orm-client/test/query-plan-mutations.test.ts
  • packages/3-extensions/sql-orm-client/test/repository.test.ts
  • packages/3-extensions/sql-orm-client/test/rich-filters-and-where.test.ts
  • packages/3-extensions/sql-orm-client/test/test-codec.ts
  • packages/3-mongo-target/1-mongo-target/src/exports/runtime.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/codecs.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/control.ts
  • packages/3-mongo-target/2-mongo-adapter/src/exports/runtime.ts
  • packages/3-mongo-target/2-mongo-adapter/test/codecs.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/lowering.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/mongo-adapter-ctx.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/mongo-adapter.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/resolve-value-ctx.test.ts
  • packages/3-mongo-target/2-mongo-adapter/test/resolve-value.test.ts
  • packages/3-targets/3-targets/postgres/package.json
  • packages/3-targets/3-targets/postgres/src/core/codecs-class.ts
  • packages/3-targets/3-targets/postgres/src/core/codecs.ts
  • packages/3-targets/3-targets/postgres/src/core/descriptor-meta.ts
  • packages/3-targets/3-targets/postgres/src/exports/codec-types.ts
  • packages/3-targets/3-targets/postgres/src/exports/codecs.ts
  • packages/3-targets/3-targets/postgres/src/exports/runtime.ts
  • packages/3-targets/3-targets/postgres/test/codec-render-output-type.test.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.test.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.types.test-d.ts
  • packages/3-targets/3-targets/postgres/test/codecs.test.ts
  • packages/3-targets/3-targets/postgres/test/typed-descriptor-flow.test-d.ts
  • packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts
  • packages/3-targets/3-targets/sqlite/src/core/codecs.ts
  • packages/3-targets/3-targets/sqlite/src/core/descriptor-meta.ts
  • packages/3-targets/3-targets/sqlite/src/core/runtime-target.ts
  • packages/3-targets/3-targets/sqlite/src/exports/codec-types.ts
  • packages/3-targets/3-targets/sqlite/src/exports/codecs.ts
  • packages/3-targets/3-targets/sqlite/test/codecs-class.types.test-d.ts
  • packages/3-targets/3-targets/sqlite/test/typed-descriptor-flow.test-d.ts
  • packages/3-targets/6-adapters/postgres/README.md
  • packages/3-targets/6-adapters/postgres/src/core/adapter.ts
  • packages/3-targets/6-adapters/postgres/src/core/codec-lookup.ts
  • packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts
  • packages/3-targets/6-adapters/postgres/src/core/sql-renderer.ts
  • packages/3-targets/6-adapters/postgres/src/exports/column-types.ts
  • packages/3-targets/6-adapters/postgres/src/exports/runtime.ts
  • packages/3-targets/6-adapters/postgres/test/adapter.test.ts
  • packages/3-targets/6-adapters/postgres/test/descriptor-parity.test.ts
  • packages/3-targets/6-adapters/postgres/test/sql-renderer.cast-policy.test.ts
  • packages/3-targets/6-adapters/postgres/test/test-codec.ts
  • packages/3-targets/6-adapters/sqlite/README.md
  • packages/3-targets/6-adapters/sqlite/src/core/adapter.ts
  • packages/3-targets/6-adapters/sqlite/src/core/runtime-adapter.ts
  • packages/3-targets/6-adapters/sqlite/src/exports/codec-types.ts
  • packages/3-targets/6-adapters/sqlite/test/codecs.test.ts
  • test/integration/test/authoring/parity/ts-psl-parity.real-packs.test.ts
  • test/integration/test/contract-builder.test.ts
  • test/integration/test/cross-package/cross-family-codec.test.ts
  • test/integration/test/cross-package/test-codec.ts
  • test/integration/test/mongo/migration-psl-authoring.test.ts
  • test/integration/test/pgvector.test.ts
  • test/utils/README.md
  • test/utils/src/column-descriptors.ts
💤 Files with no reviewable changes (11)
  • packages/2-mongo-family/7-runtime/test/decode.integration.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-types.test.ts
  • packages/3-extensions/pgvector/src/core/codecs.ts
  • packages/2-sql/5-runtime/src/codecs/json-schema-validation.ts
  • packages/3-extensions/arktype-json/src/core/arktype-json-codec.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.test-d.ts
  • packages/1-framework/2-authoring/contract/src/descriptors.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test-d.ts
  • packages/2-sql/5-runtime/test/json-schema-validation.test.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts

Comment thread docs/reference/codec-authoring-guide.md Outdated
Comment thread examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
Comment thread packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts Outdated
Comment thread packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts
Comment thread packages/3-extensions/arktype-json/test/arktype-json-codec.types.test-d.ts Outdated
Comment thread packages/3-extensions/sql-orm-client/src/types.ts
Comment thread packages/3-targets/3-targets/postgres/src/core/codecs-class.ts Outdated
Comment thread packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts Outdated
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

♻️ Duplicate comments (5)
packages/3-extensions/arktype-json/test/arktype-json-codec-class.types.test-d.ts (1)

140-142: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use the approved matcher for .test-d.ts type compatibility assertions.

Line 140 uses deprecated toMatchTypeOf; switch to toExtend for this subtype-style check.

♻️ Proposed fix
-  expectTypeOf(col).toMatchTypeOf<
+  expectTypeOf(col).toExtend<
     ColumnSpec<ArktypeJsonCodecClass<{ name: string; price: number }>, ArktypeJsonTypeParams>
   >();
#!/bin/bash
# Verify deprecated matcher usage in .test-d.ts files.
rg -n --glob '**/*.test-d.ts' '\.toMatchTypeOf\s*<'

As per coding guidelines, "**/*.test-d.ts: Do not use the deprecated toMatchTypeOf() matcher in Vitest's expectTypeOf API. Use toExtend() instead."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/3-extensions/arktype-json/test/arktype-json-codec-class.types.test-d.ts`
around lines 140 - 142, Replace the deprecated matcher usage: locate the
expectTypeOf assertion that references ColumnSpec<ArktypeJsonCodecClass<{ name:
string; price: number }>, ArktypeJsonTypeParams> (the expectTypeOf(col) line)
and change the matcher from toMatchTypeOf<...>() to toExtend<...>() so the
subtype-style compatibility check uses the approved Vitest matcher for
.test-d.ts files.
packages/3-extensions/arktype-json/src/core/arktype-json-codec-class.ts (1)

144-147: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Replace the double-cast in schema rehydration with a predicate-based narrow.

Line 146 force-casts ark.schema(jsonIr) with as unknown as ArktypeSchemaLike, which bypasses static safety and can mask shape drift.

♻️ Proposed fix
 function rehydrateSchema(jsonIr: object): ArktypeSchemaLike {
   try {
-    return ark.schema(jsonIr) as unknown as ArktypeSchemaLike;
+    const schema = ark.schema(jsonIr);
+    if (!isArktypeSchemaLike(schema)) {
+      throw new Error('Rehydrated schema is not callable with expression metadata');
+    }
+    return schema;
   } catch (error) {
     throw runtimeError(
       'RUNTIME.JSON_SCHEMA_VALIDATION_FAILED',
       `Failed to rehydrate arktype schema from contract IR: ${error instanceof Error ? error.message : String(error)}`,
       { codecId: ARKTYPE_JSON_CODEC_ID, jsonIr },
     );
   }
 }
In current Arktype docs/types, what does `ark.schema(jsonIr)` return, and is the return value guaranteed to be callable with an `expression: string` property?

As per coding guidelines, "packages/**/*.{ts,tsx}: No blind casts in production code: as unknown as X is forbidden outside tests. Prefer type predicates or fix the type surface."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-extensions/arktype-json/src/core/arktype-json-codec-class.ts`
around lines 144 - 147, The rehydrateSchema function silently force-casts
ark.schema(jsonIr) to ArktypeSchemaLike with "as unknown as", which violates the
no-blind-casts rule; replace the double-cast with a runtime type-narrow: call
ark.schema(jsonIr) into a local const (no cast), then implement and use a type
predicate/is-check (for example isArktypeSchemaLike) that verifies the returned
value is callable and has the expected shape (e.g., a function and the
"expression" property of type string or other required members), throw a clear
error if the check fails, and only then return the value typed as
ArktypeSchemaLike; reference rehydrateSchema and ark.schema when locating code
to change.
packages/3-extensions/arktype-json/test/arktype-json-codec-class.test.ts (1)

75-79: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Replace as any + lint suppression with @ts-expect-error in the guard test.

Lines 77-78 currently bypass both typing and lint policy; this negative-path test can express intent without any or biome-ignore.

♻️ Proposed fix
   it('rejects non-callable schema lookalikes at the call site', () => {
     const notASchema = { foo: 'bar' };
-    // biome-ignore lint/suspicious/noExplicitAny: deliberately malformed input for the call-site guard
-    expect(() => arktypeJsonColumn(notASchema as any)).toThrow(/callable arktype Type/);
+    // `@ts-expect-error` -- intentionally passing non-callable value to test runtime guard
+    expect(() => arktypeJsonColumn(notASchema)).toThrow(/callable arktype Type/);
   });
#!/bin/bash
# Verify explicit any and biome suppressions in this test file.
rg -n 'biome-ignore|as any|@ts-expect-error' packages/3-extensions/arktype-json/test/arktype-json-codec-class.test.ts -C2

As per coding guidelines, "Never use any type", "Never suppress biome lints", and "Use @ts-expect-error with a short reason in tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-extensions/arktype-json/test/arktype-json-codec-class.test.ts`
around lines 75 - 79, The test currently silences type + lint rules by using "as
any" and a "biome-ignore" comment; replace that with a TypeScript compile-time
suppression using `@ts-expect-error` plus a short reason above the offending call
to arktypeJsonColumn so the test still asserts the runtime guard without using
any/biome ignores. Locate the failing test in arktype-json-codec-class.test.ts
where arktypeJsonColumn(notASchema as any) is called and remove the "as any"
cast and the biome-ignore, adding a single-line "@ts-expect-error TS-EXPLAIN:
deliberate malformed input to exercise call-site guard" immediately above the
call.
packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts (1)

245-258: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject invalid Date values at the codec boundary.

new Date(wire) / new Date(json) can produce an Invalid Date, and toISOString() will also fail if callers hand this codec an invalid Date. Validating here keeps malformed storage values and contract JSON from escaping as poisoned Date instances.

🐛 Minimal validation
 export class SqliteDatetimeCodec extends CodecImpl<
@@
 > {
   async encode(value: Date, _ctx: CodecCallContext): Promise<string> {
+    if (Number.isNaN(value.getTime())) {
+      throw new TypeError('sqlite/datetime@1 input value must be a valid Date');
+    }
     return value.toISOString();
   }
   async decode(wire: string, _ctx: CodecCallContext): Promise<Date> {
-    return new Date(wire);
+    const date = new Date(wire);
+    if (Number.isNaN(date.getTime())) {
+      throw new TypeError('sqlite/datetime@1 wire value must be a valid ISO-8601 string');
+    }
+    return date;
   }
   encodeJson(value: Date): JsonValue {
+    if (Number.isNaN(value.getTime())) {
+      throw new TypeError('sqlite/datetime@1 contract value must be a valid Date');
+    }
     return value.toISOString();
   }
   decodeJson(json: JsonValue): Date {
     if (typeof json !== 'string') {
       throw new TypeError('sqlite/datetime@1 contract value must be an ISO-8601 string');
     }
-    return new Date(json);
+    const date = new Date(json);
+    if (Number.isNaN(date.getTime())) {
+      throw new TypeError('sqlite/datetime@1 contract value must be a valid ISO-8601 string');
+    }
+    return date;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts` around lines
245 - 258, The codec must reject invalid Date instances and non-strings: in
encode and encodeJson (functions encode(value: Date, _ctx: CodecCallContext) and
encodeJson(value: Date)) check that value is a Date (instanceof Date) and that
Number.isFinite(value.getTime())/!Number.isNaN(value.getTime()) before calling
toISOString(), and throw a TypeError if not; in decode and decodeJson
(decode(wire: string, _ctx: CodecCallContext) and decodeJson(json: JsonValue))
ensure the input is a string, construct the Date, then validate the produced
Date with Number.isFinite(date.getTime())/!Number.isNaN(...) and throw a
TypeError for invalid dates instead of returning them.
packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts (1)

67-76: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

sqlCharColumn() / sqlVarcharColumn() still expose an impossible params shape.

lengthParamsSchema requires length, but LengthParams makes it optional and both helpers default to {}. That lets callers build column specs that this same descriptor later rejects during params validation. Either require length end-to-end, or relax the schema if bare char / varchar is intentionally supported.

🐛 Minimal fix
-type LengthParams = { readonly length?: number };
+type LengthParams = { readonly length: number };

-export const sqlCharColumn = (params: LengthParams = {}) =>
+export const sqlCharColumn = (params: LengthParams) =>
   column(sqlCharDescriptor.factory(params), sqlCharDescriptor.codecId, params, 'char');

-export const sqlVarcharColumn = (params: LengthParams = {}) =>
+export const sqlVarcharColumn = (params: LengthParams) =>
   column(sqlVarcharDescriptor.factory(params), sqlVarcharDescriptor.codecId, params, 'varchar');

Also applies to: 245-246, 290-291

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts` around
lines 67 - 76, The params shape is inconsistent: lengthParamsSchema currently
requires length but the TypeScript type LengthParams and the
sqlCharColumn/sqlVarcharColumn helpers treat length as optional and default to
{}. Fix by making the contract consistent — either (A) relax lengthParamsSchema
to allow an optional length (e.g., make the length rule accept undefined or mark
it optional) so it matches LengthParams and the default {} behavior, or (B) make
LengthParams require length and update sqlCharColumn/sqlVarcharColumn to require
callers to supply length (and remove the default {}). Locate and update
lengthParamsSchema, the LengthParams type, and the
sqlCharColumn/sqlVarcharColumn call sites to implement the chosen option so
params validation no longer rejects valid inputs.
🧹 Nitpick comments (4)
packages/3-targets/6-adapters/postgres/src/core/adapter.ts (1)

44-60: ⚡ Quick win

Don’t leave the factory(undefined) invariant implicit.

This block now depends on every descriptor in postgresCodecRegistry being safely materializable without params. That may be true for current builtins, but it is only enforced by comments right now. Please move this through a small helper owned next to postgresCodecRegistry or add a fail-fast assertion here so a future param-sensitive descriptor does not silently instantiate the wrong runtime codec.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-targets/6-adapters/postgres/src/core/adapter.ts` around lines 44 -
60, The code silently calls factory(undefined) for each descriptor from
postgresCodecRegistry when constructing codecRegistry, which assumes every
descriptor is paramless; add a fail-fast check or helper next to
postgresCodecRegistry to enforce/verify that a descriptor is materializable
without params before calling factory(undefined). Concretely, introduce a small
predicate/helper (e.g., isParamlessDescriptor) or add an assertion in the
codecRegistry initializer that inspects the descriptor shape and throws a clear
error if params are required, and then only call (descriptor.factory)(undefined)
(or use the helper) to produce the codec instance; reference codecRegistry,
postgresCodecRegistry, CodecInstanceContext and the current factory(undefined)
usage when making the change.
packages/3-targets/6-adapters/sqlite/src/core/adapter.ts (1)

55-70: 🏗️ Heavy lift

Don't materialize every descriptor with factory(undefined).

sqliteCodecRegistry now includes parameterized SQL descriptors, but this loop hard-casts every factory to accept unknown and instantiates it with undefined. The adapter registry therefore only works for descriptors whose runtime instances happen to ignore params; the first param-sensitive codec added here will be mis-materialized. Please keep this surface descriptor-based, or restrict this fallback registry to descriptors whose params are truly void.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-targets/6-adapters/sqlite/src/core/adapter.ts` around lines 55 -
70, The current codecRegistry eagerly materializes every descriptor by calling
descriptor.factory(undefined), which mis-instantiates parameterized descriptors
from sqliteCodecRegistry; change this to preserve descriptor-based entries and
only instantiate codecs when they are truly parameterless: in the codecRegistry
initialization (and related logic around codecRegistry, sqliteCodecRegistry,
CodecInstanceContext and factory), avoid calling factory(undefined) for all
descriptors—instead detect parameterized descriptors (e.g., via a param-type
flag or factory arity) and either keep the original descriptor in the registry
or only call factory() for descriptors known to accept no params; ensure the
fallback registry only materializes codecs whose params are void so
parameterized codecs remain descriptor-based.
packages/3-targets/3-targets/postgres/test/codecs.test.ts (1)

75-82: ⚡ Quick win

Don't bypass parameterized descriptor factories here.

descriptor.factory(undefined as never) sidesteps the public params contract for character, numeric, timestamp, enum, and the other parameterized descriptors in this table. The suite still checks encode/decode behavior, but it no longer proves those codecs can be constructed through their supported API shape. A small paramsByScalar map, or separate helpers for parameterized vs non-parameterized codecs, would keep these tests aligned with the descriptor-first surface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-targets/3-targets/postgres/test/codecs.test.ts` around lines 75 -
82, The helper codecForScalar currently calls descriptor.factory(undefined as
never) which bypasses the public params contract for parameterized descriptors;
change codecForScalar to supply real params for parameterized descriptors (e.g.
via a small paramsByScalar map or conditional helpers) and call
descriptor.factory(params) for those scalars, falling back to
descriptor.factory() or descriptor.factory(undefined) only for true
non-parameterized descriptors so that descriptorByScalar/descriptor.factory and
SYNTH_CTX are exercised via the intended public API shape.
packages/3-targets/3-targets/sqlite/src/exports/codec-types.ts (1)

11-45: ⚡ Quick win

Keep src/exports/codec-types.ts as a thin re-export surface.

codecDescriptorMap and Resolve make this export file a second source of truth for SQLite codec membership. That raises the odds of CodecTypes drifting from the core registry/list when the next codec is added or removed. Please move the map/type derivation into ../core/... and re-export the final alias from here so the public entrypoint stays aligned with the package’s single descriptor source.

♻️ Suggested shape
-import type { ExtractCodecTypes } from '@prisma-next/sql-relational-core/ast';
-import {
-  sqlCharDescriptor,
-  sqlFloatDescriptor,
-  sqlIntDescriptor,
-  sqlVarcharDescriptor,
-} from '@prisma-next/sql-relational-core/ast';
 import type { JsonValue } from '../core/codecs';
-import {
-  sqliteBigintDescriptor,
-  sqliteBlobDescriptor,
-  sqliteDatetimeDescriptor,
-  sqliteIntegerDescriptor,
-  sqliteJsonDescriptor,
-  sqliteRealDescriptor,
-  sqliteTextDescriptor,
-} from '../core/codecs-class';
-
-const codecDescriptorMap = {
-  char: sqlCharDescriptor,
-  varchar: sqlVarcharDescriptor,
-  int: sqlIntDescriptor,
-  float: sqlFloatDescriptor,
-  text: sqliteTextDescriptor,
-  integer: sqliteIntegerDescriptor,
-  real: sqliteRealDescriptor,
-  blob: sqliteBlobDescriptor,
-  datetime: sqliteDatetimeDescriptor,
-  json: sqliteJsonDescriptor,
-  bigint: sqliteBigintDescriptor,
-} as const;
-
-type Resolve<T> = { readonly [K in keyof T]: { readonly [P in keyof T[K]]: T[K][P] } };
-
-export type CodecTypes = Resolve<ExtractCodecTypes<typeof codecDescriptorMap>>;
+export type { CodecTypes } from '../core/codec-types';
 export type { JsonValue };

As per coding guidelines, packages/**/src/exports/{adapter,codec-types,types}.ts re-export files must re-export from core without adding additional logic.

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/2-sql/4-lanes/relational-core/src/codec-descriptor-registry.ts`:
- Around line 31-39: The registry currently overwrites duplicate codecId entries
causing inconsistent state; before calling byId.set(descriptor.codecId, widened)
in the loop over allDescriptors (where widened is cast to AnyDescriptor), check
if byId.has(descriptor.codecId) and throw a clear error (including the
conflicting codecId and descriptor identity) to fail-fast on duplicates; only
proceed to add to byTargetType when the codecId is not already present (so byId
and byTargetType remain consistent and descriptorFor(id) will match target-type
lists).

In `@packages/3-extensions/pgvector/src/core/codecs-class.ts`:
- Around line 82-118: The PgVectorCodec produced by factory() must retain
params.length (the declared dimension) and validate input across all ingress
paths: modify factory() to store the expected length on the PgVectorCodec
instance, add a single reused validator function (used by encode, decode, and
decodeJson) that checks the value is an array of numbers and that its length
equals the stored dimension, and update encodeJson/decodeJson/decode/encode to
call that validator and throw descriptive errors for wrong-dimension or
non-numeric entries; ensure contractCodecs.forColumn(table, column) returns a
codec that enforces the declared vector length rather than ignoring
params.length.

In `@packages/3-targets/3-targets/postgres/src/exports/codec-types.ts`:
- Around line 19-86: The file defines codecDescriptorMap, Resolve, and
CodecTypes inline which violates the export-only rule; move the
codecDescriptorMap, Resolve type helper, and the ExtractCodecTypes processing
into a new or existing module under src/core (e.g., export the computed type
there) and then change src/exports/codec-types.ts to only re-export the public
type (export type { CodecTypes } from '../core/...') so the exports file
contains no computation or logic and only exposes the type symbol CodecTypes.

In `@packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts`:
- Around line 204-211: The encodeJson and decodeJson methods currently use
Node-only Buffer; replace that with a runtime-neutral base64 utility so src/core
stays platform-agnostic: implement or import cross-platform helpers (e.g.,
uint8ArrayToBase64 and base64ToUint8Array) that use Web APIs (atob/btoa or
TextEncoder/TextDecoder) and fall back to Buffer only when necessary, then
update encodeJson(value: Uint8Array) to return uint8ArrayToBase64(value) and
decodeJson(json: JsonValue) to validate string and return
base64ToUint8Array(json); keep the function names encodeJson and decodeJson
unchanged.

---

Duplicate comments:
In `@packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts`:
- Around line 67-76: The params shape is inconsistent: lengthParamsSchema
currently requires length but the TypeScript type LengthParams and the
sqlCharColumn/sqlVarcharColumn helpers treat length as optional and default to
{}. Fix by making the contract consistent — either (A) relax lengthParamsSchema
to allow an optional length (e.g., make the length rule accept undefined or mark
it optional) so it matches LengthParams and the default {} behavior, or (B) make
LengthParams require length and update sqlCharColumn/sqlVarcharColumn to require
callers to supply length (and remove the default {}). Locate and update
lengthParamsSchema, the LengthParams type, and the
sqlCharColumn/sqlVarcharColumn call sites to implement the chosen option so
params validation no longer rejects valid inputs.

In `@packages/3-extensions/arktype-json/src/core/arktype-json-codec-class.ts`:
- Around line 144-147: The rehydrateSchema function silently force-casts
ark.schema(jsonIr) to ArktypeSchemaLike with "as unknown as", which violates the
no-blind-casts rule; replace the double-cast with a runtime type-narrow: call
ark.schema(jsonIr) into a local const (no cast), then implement and use a type
predicate/is-check (for example isArktypeSchemaLike) that verifies the returned
value is callable and has the expected shape (e.g., a function and the
"expression" property of type string or other required members), throw a clear
error if the check fails, and only then return the value typed as
ArktypeSchemaLike; reference rehydrateSchema and ark.schema when locating code
to change.

In `@packages/3-extensions/arktype-json/test/arktype-json-codec-class.test.ts`:
- Around line 75-79: The test currently silences type + lint rules by using "as
any" and a "biome-ignore" comment; replace that with a TypeScript compile-time
suppression using `@ts-expect-error` plus a short reason above the offending call
to arktypeJsonColumn so the test still asserts the runtime guard without using
any/biome ignores. Locate the failing test in arktype-json-codec-class.test.ts
where arktypeJsonColumn(notASchema as any) is called and remove the "as any"
cast and the biome-ignore, adding a single-line "@ts-expect-error TS-EXPLAIN:
deliberate malformed input to exercise call-site guard" immediately above the
call.

In
`@packages/3-extensions/arktype-json/test/arktype-json-codec-class.types.test-d.ts`:
- Around line 140-142: Replace the deprecated matcher usage: locate the
expectTypeOf assertion that references ColumnSpec<ArktypeJsonCodecClass<{ name:
string; price: number }>, ArktypeJsonTypeParams> (the expectTypeOf(col) line)
and change the matcher from toMatchTypeOf<...>() to toExtend<...>() so the
subtype-style compatibility check uses the approved Vitest matcher for
.test-d.ts files.

In `@packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts`:
- Around line 245-258: The codec must reject invalid Date instances and
non-strings: in encode and encodeJson (functions encode(value: Date, _ctx:
CodecCallContext) and encodeJson(value: Date)) check that value is a Date
(instanceof Date) and that
Number.isFinite(value.getTime())/!Number.isNaN(value.getTime()) before calling
toISOString(), and throw a TypeError if not; in decode and decodeJson
(decode(wire: string, _ctx: CodecCallContext) and decodeJson(json: JsonValue))
ensure the input is a string, construct the Date, then validate the produced
Date with Number.isFinite(date.getTime())/!Number.isNaN(...) and throw a
TypeError for invalid dates instead of returning them.

---

Nitpick comments:
In `@packages/3-targets/3-targets/postgres/test/codecs.test.ts`:
- Around line 75-82: The helper codecForScalar currently calls
descriptor.factory(undefined as never) which bypasses the public params contract
for parameterized descriptors; change codecForScalar to supply real params for
parameterized descriptors (e.g. via a small paramsByScalar map or conditional
helpers) and call descriptor.factory(params) for those scalars, falling back to
descriptor.factory() or descriptor.factory(undefined) only for true
non-parameterized descriptors so that descriptorByScalar/descriptor.factory and
SYNTH_CTX are exercised via the intended public API shape.

In `@packages/3-targets/6-adapters/postgres/src/core/adapter.ts`:
- Around line 44-60: The code silently calls factory(undefined) for each
descriptor from postgresCodecRegistry when constructing codecRegistry, which
assumes every descriptor is paramless; add a fail-fast check or helper next to
postgresCodecRegistry to enforce/verify that a descriptor is materializable
without params before calling factory(undefined). Concretely, introduce a small
predicate/helper (e.g., isParamlessDescriptor) or add an assertion in the
codecRegistry initializer that inspects the descriptor shape and throws a clear
error if params are required, and then only call (descriptor.factory)(undefined)
(or use the helper) to produce the codec instance; reference codecRegistry,
postgresCodecRegistry, CodecInstanceContext and the current factory(undefined)
usage when making the change.

In `@packages/3-targets/6-adapters/sqlite/src/core/adapter.ts`:
- Around line 55-70: The current codecRegistry eagerly materializes every
descriptor by calling descriptor.factory(undefined), which mis-instantiates
parameterized descriptors from sqliteCodecRegistry; change this to preserve
descriptor-based entries and only instantiate codecs when they are truly
parameterless: in the codecRegistry initialization (and related logic around
codecRegistry, sqliteCodecRegistry, CodecInstanceContext and factory), avoid
calling factory(undefined) for all descriptors—instead detect parameterized
descriptors (e.g., via a param-type flag or factory arity) and either keep the
original descriptor in the registry or only call factory() for descriptors known
to accept no params; ensure the fallback registry only materializes codecs whose
params are void so parameterized codecs remain descriptor-based.
🪄 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: 395e4d68-7371-4142-b775-7022bfe445bb

📥 Commits

Reviewing files that changed from the base of the PR and between 2d4eb3b and 583a8e9.

📒 Files selected for processing (46)
  • packages/2-sql/4-lanes/relational-core/package.json
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts
  • packages/2-sql/4-lanes/relational-core/src/codec-descriptor-registry.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/codec-descriptor-registry.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs-class.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs-class.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • packages/2-sql/4-lanes/relational-core/tsdown.config.ts
  • packages/2-sql/5-runtime/src/sql-context.ts
  • packages/3-extensions/arktype-json/src/core/arktype-json-codec-class.ts
  • packages/3-extensions/arktype-json/src/core/pack-meta.ts
  • packages/3-extensions/arktype-json/src/exports/codecs.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec-class.test.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec-class.types.test-d.ts
  • packages/3-extensions/arktype-json/test/extension-descriptors.test.ts
  • packages/3-extensions/pgvector/src/core/codecs-class.ts
  • packages/3-extensions/pgvector/src/core/descriptor-meta.ts
  • packages/3-extensions/pgvector/src/core/registry.ts
  • packages/3-extensions/pgvector/src/exports/runtime.ts
  • packages/3-extensions/pgvector/test/codec-render-output-type.test.ts
  • packages/3-extensions/pgvector/test/codecs-class.types.test-d.ts
  • packages/3-extensions/pgvector/test/codecs.test.ts
  • packages/3-extensions/pgvector/test/typed-descriptor-flow.test-d.ts
  • packages/3-targets/3-targets/postgres/src/core/codecs-class.ts
  • packages/3-targets/3-targets/postgres/src/core/registry.ts
  • packages/3-targets/3-targets/postgres/src/exports/codec-types.ts
  • packages/3-targets/3-targets/postgres/src/exports/codecs.ts
  • packages/3-targets/3-targets/postgres/test/codec-render-output-type.test.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.test.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.types.test-d.ts
  • packages/3-targets/3-targets/postgres/test/codecs.test.ts
  • packages/3-targets/3-targets/postgres/test/typed-descriptor-flow.test-d.ts
  • packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts
  • packages/3-targets/3-targets/sqlite/src/core/registry.ts
  • packages/3-targets/3-targets/sqlite/src/exports/codec-types.ts
  • packages/3-targets/3-targets/sqlite/src/exports/codecs.ts
  • packages/3-targets/3-targets/sqlite/test/codecs-class.types.test-d.ts
  • packages/3-targets/3-targets/sqlite/test/typed-descriptor-flow.test-d.ts
  • packages/3-targets/6-adapters/postgres/src/core/adapter.ts
  • packages/3-targets/6-adapters/postgres/src/core/codec-lookup.ts
  • packages/3-targets/6-adapters/postgres/src/core/descriptor-meta.ts
  • packages/3-targets/6-adapters/postgres/src/exports/runtime.ts
  • packages/3-targets/6-adapters/sqlite/src/core/adapter.ts
  • packages/3-targets/6-adapters/sqlite/src/core/runtime-adapter.ts
  • packages/3-targets/6-adapters/sqlite/test/codecs.test.ts
✅ Files skipped from review due to trivial changes (9)
  • packages/2-sql/4-lanes/relational-core/package.json
  • packages/2-sql/4-lanes/relational-core/src/exports/codec-descriptor-registry.ts
  • packages/3-targets/3-targets/postgres/src/core/registry.ts
  • packages/3-extensions/pgvector/src/core/registry.ts
  • packages/3-targets/3-targets/sqlite/src/core/registry.ts
  • packages/2-sql/4-lanes/relational-core/tsdown.config.ts
  • packages/3-extensions/arktype-json/src/exports/codecs.ts
  • packages/3-extensions/arktype-json/src/core/pack-meta.ts
  • packages/3-targets/3-targets/sqlite/src/exports/codecs.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/3-targets/3-targets/postgres/src/exports/codecs.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.types.test-d.ts
  • packages/2-sql/5-runtime/src/sql-context.ts
  • packages/3-targets/3-targets/postgres/src/core/codecs-class.ts

Comment thread packages/3-extensions/pgvector/src/core/codecs.ts Outdated
Comment thread packages/3-targets/3-targets/postgres/src/exports/codec-types.ts Outdated
Comment thread packages/3-targets/3-targets/sqlite/src/core/codecs-class.ts Outdated
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)
packages/3-targets/3-targets/postgres/src/core/codecs.ts (1)

110-124: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

The length-parameter helpers can emit params their descriptors reject.

lengthParamsSchema requires length, but LengthParams is optional and these helpers default to {}. That means pgBitColumn(), pgVarbitColumn(), pgCharColumn(), and pgVarcharColumn() can author column specs that fail descriptor validation later.

Either make length required at the helper boundary, or relax the relevant schemas if bare forms are intentionally supported. Right now the API surface and validator contract disagree.

Also applies to: 733-735, 779-780, 1008-1035

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-targets/3-targets/postgres/src/core/codecs.ts` around lines 110 -
124, The helper functions (e.g., pgBitColumn, pgVarbitColumn, pgCharColumn,
pgVarcharColumn) are producing param objects that the validator
lengthParamsSchema rejects because lengthParamsSchema requires length while the
Type LengthParams and helpers allow an empty {}; fix by reconciling the
contract: either relax lengthParamsSchema to accept an optional length (change
length to 'number.integer > 0' -> 'number.integer > 0?') so bare forms validate,
or make the helpers enforce/require length at their boundary (update the helper
implementations to validate and throw or return an error when length is missing)
and change LengthParams to require length; apply the same reconciliation for the
related numeric/precision schemas and their helper functions referenced in the
comment (numericParamsSchema, precisionParamsSchema and their callers).
♻️ Duplicate comments (3)
packages/3-extensions/pgvector/src/core/codecs.ts (1)

76-118: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Carry length into PgVectorCodec and validate every ingress path.

factory() still materializes the same codec for vector(3) and vector(1536), and decodeJson() still force-casts JSON to number[]. That means wrong-dimension or non-numeric vectors can get past the codec boundary until much later.

Suggested direction
 export class PgVectorCodec extends CodecImpl<
   typeof VECTOR_CODEC_ID,
   readonly ['equality'],
   string,
   number[]
 > {
+  constructor(
+    descriptor: PgVectorDescriptor,
+    private readonly length: number,
+  ) {
+    super(descriptor);
+  }
+
+  private assertVector(value: JsonValue | number[]): asserts value is number[] {
+    if (!Array.isArray(value)) {
+      throw new Error('Vector value must be an array of numbers');
+    }
+    if (!value.every((v) => typeof v === 'number')) {
+      throw new Error('Vector value must contain only numbers');
+    }
+    if (value.length !== this.length) {
+      throw new Error(`Vector length mismatch: expected ${this.length}, got ${value.length}`);
+    }
+  }
+
   async encode(value: number[], _ctx: CodecCallContext): Promise<string> {
-    if (!Array.isArray(value)) {
-      throw new Error('Vector value must be an array of numbers');
-    }
-    if (!value.every((v) => typeof v === 'number')) {
-      throw new Error('Vector value must contain only numbers');
-    }
+    this.assertVector(value);
     return `[${value.join(',')}]`;
   }

   async decode(wire: string, _ctx: CodecCallContext): Promise<number[]> {
@@
-    return content.split(',').map((v) => {
+    const value = content.split(',').map((v) => {
       const num = Number.parseFloat(v.trim());
       if (Number.isNaN(num)) {
         throw new Error(`Invalid vector value: "${v}" is not a number`);
       }
       return num;
     });
+    this.assertVector(value);
+    return value;
   }

   encodeJson(value: number[]): JsonValue {
+    this.assertVector(value);
     return value;
   }

   decodeJson(json: JsonValue): number[] {
-    return json as number[];
+    this.assertVector(json);
+    return json;
   }
 }
@@
-  override factory(_params: VectorParams): (ctx: CodecInstanceContext) => PgVectorCodec {
-    return () => new PgVectorCodec(this);
+  override factory(params: VectorParams): (ctx: CodecInstanceContext) => PgVectorCodec {
+    return () => new PgVectorCodec(this, params.length);
   }
 }

Also applies to: 130-132

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-extensions/pgvector/src/core/codecs.ts` around lines 76 - 118,
PgVectorCodec currently ignores the declared vector dimension so invalid-length
or non-numeric vectors slip through; modify the factory() that constructs
PgVectorCodec to accept and store the vector length into the codec instance,
then validate that length in all ingress/egress paths: in encode(value), ensure
value is an array of numbers of the expected length; in decode(wire) after
parsing, ensure the resulting number[] has the expected length; in
encodeJson(value) validate the array contents and length before returning; in
decodeJson(json) validate that json is an array of numbers and the correct
length (don’t force-cast). Update the PgVectorCodec class signature to carry a
length field and use it in these methods to throw descriptive errors on mismatch
or non-numeric entries.
packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts (1)

67-76: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make the char/varchar helper contract match the descriptor schema.

Lines 75-76, 245-246, and 290-291 make length optional and default helper params to {}, but lengthParamsSchema on Lines 67-69 still requires it. That lets sqlCharColumn() / sqlVarcharColumn() produce type params that their own descriptors later reject.

One fix if bare forms are not intended
-type LengthParams = { readonly length?: number };
+type LengthParams = { readonly length: number };
@@
-export const sqlCharColumn = (params: LengthParams = {}) =>
+export const sqlCharColumn = (params: LengthParams) =>
   column(sqlCharDescriptor.factory(params), sqlCharDescriptor.codecId, params, 'char');
@@
-export const sqlVarcharColumn = (params: LengthParams = {}) =>
+export const sqlVarcharColumn = (params: LengthParams) =>
   column(sqlVarcharDescriptor.factory(params), sqlVarcharDescriptor.codecId, params, 'varchar');

If bare char / varchar is intentional, relax lengthParamsSchema instead so validation matches the helper API.

Also applies to: 245-246, 290-291

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts` around
lines 67 - 76, The length validation in lengthParamsSchema conflicts with the
helper defaults used by sqlCharColumn and sqlVarcharColumn—lengthParamsSchema
currently requires length but the helpers make length optional and default to
{}—so relax the schema to allow an optional length (e.g. change the key to
'length?' with the same numeric constraint) so the descriptor validation matches
the helper API; alternatively, if you intend bare forms to be disallowed, make
sqlCharColumn/sqlVarcharColumn require and pass a length instead, but the
simpler fix is to update lengthParamsSchema to accept an optional length to
align with LengthParams and the helpers.
packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts (1)

74-77: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Drop the any cast and Biome suppression in this negative-path test.

This still violates the repo’s test rules. A single @ts-expect-error on Line 77 keeps the runtime-guard coverage without suppressing lint or widening to any.

Suggested cleanup
   it('rejects non-callable schema lookalikes at the call site', () => {
     const notASchema = { foo: 'bar' };
-    // biome-ignore lint/suspicious/noExplicitAny: deliberately malformed input for the call-site guard
-    expect(() => arktypeJsonColumn(notASchema as any)).toThrow(/callable arktype Type/);
+    // `@ts-expect-error` -- intentionally passing a non-callable to exercise the runtime guard
+    expect(() => arktypeJsonColumn(notASchema)).toThrow(/callable arktype Type/);
   });

As per coding guidelines, "Never use any type", "Never suppress biome lints", and "Use @ts-expect-error with a short reason in tests instead of blanket @ts-ignore."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts` around
lines 74 - 77, The test currently uses an any cast and a biome-ignore to pass a
malformed value into arktypeJsonColumn (variable notASchema) which violates
project rules; remove the "as any" cast and the biome-ignore comment and instead
put a single line with `@ts-expect-error` and a short reason immediately above the
expect(() => arktypeJsonColumn(notASchema)).toThrow(...) call so the TypeScript
compile-time error is expected while preserving the runtime negative-path
assertion for arktypeJsonColumn.
🧹 Nitpick comments (2)
packages/3-targets/3-targets/sqlite/src/exports/codec-types.ts (1)

11-45: ⚡ Quick win

Keep src/exports/codec-types.ts as a pure re-export surface.

This entrypoint now computes codecDescriptorMap, Resolve, and CodecTypes inline. That breaks the repo’s src/exports/* rule; move the implementation into a core module and re-export the finished type from here.

♻️ Suggested shape
-import type { ExtractCodecTypes } from '@prisma-next/sql-relational-core/ast';
-import {
-  sqlCharDescriptor,
-  sqlFloatDescriptor,
-  sqlIntDescriptor,
-  sqlVarcharDescriptor,
-} from '@prisma-next/sql-relational-core/ast';
 import type { JsonValue } from '../core/codec-helpers';
-import {
-  sqliteBigintDescriptor,
-  sqliteBlobDescriptor,
-  sqliteDatetimeDescriptor,
-  sqliteIntegerDescriptor,
-  sqliteJsonDescriptor,
-  sqliteRealDescriptor,
-  sqliteTextDescriptor,
-} from '../core/codecs';
-
-const codecDescriptorMap = {
-  char: sqlCharDescriptor,
-  varchar: sqlVarcharDescriptor,
-  int: sqlIntDescriptor,
-  float: sqlFloatDescriptor,
-  text: sqliteTextDescriptor,
-  integer: sqliteIntegerDescriptor,
-  real: sqliteRealDescriptor,
-  blob: sqliteBlobDescriptor,
-  datetime: sqliteDatetimeDescriptor,
-  json: sqliteJsonDescriptor,
-  bigint: sqliteBigintDescriptor,
-} as const;
-
-type Resolve<T> = { readonly [K in keyof T]: { readonly [P in keyof T[K]]: T[K][P] } };
-
-export type CodecTypes = Resolve<ExtractCodecTypes<typeof codecDescriptorMap>>;
+export type { CodecTypes } from '../core/codec-types';

As per coding guidelines, "Re-export files in src/exports/ (adapter.ts, codec-types.ts, types.ts) must re-export from core (../core/...) without adding additional logic."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/3-targets/3-targets/sqlite/src/exports/codec-types.ts` around lines
11 - 45, The file currently computes codecDescriptorMap, Resolve and CodecTypes
inline; move that logic into a new core module (e.g. ../core/codec-types.ts)
where you export the const codecDescriptorMap, the helper Resolve type and the
resulting export type CodecTypes (using ExtractCodecTypes and the existing codec
descriptors like sqliteTextDescriptor, sqliteIntegerDescriptor, etc.), then
change this src/exports/codec-types.ts to be a pure re-export that only
re-exports the finished type (e.g. export type { CodecTypes } from
'../core/codec-types';) and any needed descriptor re-exports—remove all inline
computation from the exports file.
packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts (1)

238-248: 💤 Low value

Both input and output correctly use DescriptorCodecInput — no issue found.

The current implementation is semantically correct. Both input and output represent the application-facing type (TInput) per codec contract semantics: codecs encode application values to wire format and decode wire format back to application values. Tests confirm this: ContractCodecTypes['pg/int4@1']['output'] correctly infers number.

The naming could benefit from a brief inline comment clarifying that input and output both refer to the application-side type (as opposed to wire format), but this is a minor optional clarity improvement, not a functional issue.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts` around lines
238 - 248, Add a brief inline comment in the ExtractCodecTypes type to clarify
that both properties named input and output use DescriptorCodecInput and
therefore represent the application-facing type (TInput) rather than the wire
format; update the area around the ExtractCodecTypes declaration (reference the
type name ExtractCodecTypes and the properties input/output that use
DescriptorCodecInput and DescriptorCodecTraits) to include a one-line comment
explaining this semantic choice for future readers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/3-targets/3-targets/postgres/src/core/codec-helpers.ts`:
- Around line 55-72: The pgNumericRenderOutputType function currently allows any
JS number for typeParams.scale (including NaN/Infinity/floats) which can produce
invalid output like "Numeric<10, NaN>"; update pgNumericRenderOutputType to
validate typeParams.scale the same way precision is validated: check typeof
scale === 'number', Number.isFinite(scale), and Number.isInteger(scale) (and
throw a similar Error mentioning "scale" when invalid), and only render
`Numeric<precision, scale>` when the validated scale is present; otherwise fall
back to `Numeric<precision>`.
- Around line 103-114: The function pgEnumRenderOutputType currently coerces all
enum values with String(value); instead, validate that typeParams.values is an
array of strings and throw a descriptive Error if any element is not a string
before rendering. In pgEnumRenderOutputType inspect values (e.g. values.forEach
or values.some) and if an element's typeof !== 'string' throw an Error naming
the offending index/type (or a clear message) so only string literals are
processed, then proceed to escape and join the strings as before.
- Around line 75-96: Both pgTimestampDecodeJson and pgTimestamptzDecodeJson
currently accept any format the Date constructor parses; change them to first
validate the input string against a strict ISO 8601 regex (e.g., RFC3339-like
pattern) before constructing a Date, and remove the round-trip toISOString()
equality check (use the regex + Number.isNaN(date.getTime()) checks only) so
inputs like "2024-01-15T10:30:00Z" are accepted while non-ISO inputs are
rejected; update the error messages in pgTimestampDecodeJson and
pgTimestamptzDecodeJson to reflect the ISO-only requirement.

In `@packages/3-targets/3-targets/sqlite/src/core/codecs.ts`:
- Around line 245-259: The decode methods currently create Date objects from
strings but don't validate them, allowing invalid Dates to propagate; update
both decode(wire: string) and decodeJson(json: JsonValue) to parse the string
into a Date (using new Date(...)) and then check validity with
isNaN(date.getTime()) (or Number.isNaN(date.getTime())); if invalid, throw a
TypeError with the same contract message used now ('sqlite/datetime@1 contract
value must be an ISO-8601 string'); otherwise return the valid Date. Apply this
change to the decode and decodeJson functions to reject malformed datetime
strings early.

---

Outside diff comments:
In `@packages/3-targets/3-targets/postgres/src/core/codecs.ts`:
- Around line 110-124: The helper functions (e.g., pgBitColumn, pgVarbitColumn,
pgCharColumn, pgVarcharColumn) are producing param objects that the validator
lengthParamsSchema rejects because lengthParamsSchema requires length while the
Type LengthParams and helpers allow an empty {}; fix by reconciling the
contract: either relax lengthParamsSchema to accept an optional length (change
length to 'number.integer > 0' -> 'number.integer > 0?') so bare forms validate,
or make the helpers enforce/require length at their boundary (update the helper
implementations to validate and throw or return an error when length is missing)
and change LengthParams to require length; apply the same reconciliation for the
related numeric/precision schemas and their helper functions referenced in the
comment (numericParamsSchema, precisionParamsSchema and their callers).

---

Duplicate comments:
In `@packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts`:
- Around line 67-76: The length validation in lengthParamsSchema conflicts with
the helper defaults used by sqlCharColumn and
sqlVarcharColumn—lengthParamsSchema currently requires length but the helpers
make length optional and default to {}—so relax the schema to allow an optional
length (e.g. change the key to 'length?' with the same numeric constraint) so
the descriptor validation matches the helper API; alternatively, if you intend
bare forms to be disallowed, make sqlCharColumn/sqlVarcharColumn require and
pass a length instead, but the simpler fix is to update lengthParamsSchema to
accept an optional length to align with LengthParams and the helpers.

In `@packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts`:
- Around line 74-77: The test currently uses an any cast and a biome-ignore to
pass a malformed value into arktypeJsonColumn (variable notASchema) which
violates project rules; remove the "as any" cast and the biome-ignore comment
and instead put a single line with `@ts-expect-error` and a short reason
immediately above the expect(() => arktypeJsonColumn(notASchema)).toThrow(...)
call so the TypeScript compile-time error is expected while preserving the
runtime negative-path assertion for arktypeJsonColumn.

In `@packages/3-extensions/pgvector/src/core/codecs.ts`:
- Around line 76-118: PgVectorCodec currently ignores the declared vector
dimension so invalid-length or non-numeric vectors slip through; modify the
factory() that constructs PgVectorCodec to accept and store the vector length
into the codec instance, then validate that length in all ingress/egress paths:
in encode(value), ensure value is an array of numbers of the expected length; in
decode(wire) after parsing, ensure the resulting number[] has the expected
length; in encodeJson(value) validate the array contents and length before
returning; in decodeJson(json) validate that json is an array of numbers and the
correct length (don’t force-cast). Update the PgVectorCodec class signature to
carry a length field and use it in these methods to throw descriptive errors on
mismatch or non-numeric entries.

---

Nitpick comments:
In `@packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts`:
- Around line 238-248: Add a brief inline comment in the ExtractCodecTypes type
to clarify that both properties named input and output use DescriptorCodecInput
and therefore represent the application-facing type (TInput) rather than the
wire format; update the area around the ExtractCodecTypes declaration (reference
the type name ExtractCodecTypes and the properties input/output that use
DescriptorCodecInput and DescriptorCodecTraits) to include a one-line comment
explaining this semantic choice for future readers.

In `@packages/3-targets/3-targets/sqlite/src/exports/codec-types.ts`:
- Around line 11-45: The file currently computes codecDescriptorMap, Resolve and
CodecTypes inline; move that logic into a new core module (e.g.
../core/codec-types.ts) where you export the const codecDescriptorMap, the
helper Resolve type and the resulting export type CodecTypes (using
ExtractCodecTypes and the existing codec descriptors like sqliteTextDescriptor,
sqliteIntegerDescriptor, etc.), then change this src/exports/codec-types.ts to
be a pure re-export that only re-exports the finished type (e.g. export type {
CodecTypes } from '../core/codec-types';) and any needed descriptor
re-exports—remove all inline computation from the exports file.
🪄 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: 9bcd7dd3-79d5-45a7-9aef-23e5489f668f

📥 Commits

Reviewing files that changed from the base of the PR and between 583a8e9 and c4d81ad.

📒 Files selected for processing (42)
  • docs/reference/codec-authoring-guide.md
  • packages/2-sql/4-lanes/relational-core/README.md
  • packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs-class.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs-class.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • packages/2-sql/5-runtime/src/sql-context.ts
  • packages/3-extensions/arktype-json/src/core/arktype-json-codec.ts
  • packages/3-extensions/arktype-json/src/core/pack-meta.ts
  • packages/3-extensions/arktype-json/src/core/registry.ts
  • packages/3-extensions/arktype-json/src/exports/codecs.ts
  • packages/3-extensions/arktype-json/src/exports/column-types.ts
  • packages/3-extensions/arktype-json/src/exports/runtime.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.types.test-d.ts
  • packages/3-extensions/arktype-json/test/extension-descriptors.test.ts
  • packages/3-extensions/pgvector/src/core/codecs.ts
  • packages/3-extensions/pgvector/src/core/registry.ts
  • packages/3-extensions/pgvector/test/codec-render-output-type.test.ts
  • packages/3-extensions/pgvector/test/codecs-class.types.test-d.ts
  • packages/3-extensions/pgvector/test/codecs.test.ts
  • packages/3-extensions/pgvector/test/typed-descriptor-flow.test-d.ts
  • packages/3-extensions/sql-orm-client/test/codec-async.types.test-d.ts
  • packages/3-extensions/sql-orm-client/test/integration/codec-async.test.ts
  • packages/3-targets/3-targets/postgres/src/core/codec-helpers.ts
  • packages/3-targets/3-targets/postgres/src/core/codecs.ts
  • packages/3-targets/3-targets/postgres/src/core/registry.ts
  • packages/3-targets/3-targets/postgres/src/exports/codec-types.ts
  • packages/3-targets/3-targets/postgres/src/exports/codecs.ts
  • packages/3-targets/3-targets/postgres/test/codec-render-output-type.test.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.test.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.types.test-d.ts
  • packages/3-targets/3-targets/postgres/test/codecs.test.ts
  • packages/3-targets/3-targets/postgres/test/typed-descriptor-flow.test-d.ts
  • packages/3-targets/3-targets/sqlite/src/core/codec-helpers.ts
  • packages/3-targets/3-targets/sqlite/src/core/codecs.ts
  • packages/3-targets/3-targets/sqlite/src/core/registry.ts
  • packages/3-targets/3-targets/sqlite/src/exports/codec-types.ts
  • packages/3-targets/3-targets/sqlite/src/exports/codecs.ts
  • packages/3-targets/3-targets/sqlite/test/codecs-class.types.test-d.ts
  • packages/3-targets/3-targets/sqlite/test/typed-descriptor-flow.test-d.ts
✅ Files skipped from review due to trivial changes (16)
  • packages/3-targets/3-targets/postgres/src/core/registry.ts
  • packages/3-extensions/pgvector/src/core/registry.ts
  • packages/3-extensions/sql-orm-client/test/integration/codec-async.test.ts
  • packages/3-extensions/sql-orm-client/test/codec-async.types.test-d.ts
  • packages/3-targets/3-targets/sqlite/src/core/registry.ts
  • packages/3-targets/3-targets/postgres/src/exports/codecs.ts
  • packages/3-extensions/pgvector/test/codec-render-output-type.test.ts
  • packages/3-extensions/arktype-json/src/core/registry.ts
  • packages/3-extensions/pgvector/test/typed-descriptor-flow.test-d.ts
  • packages/3-extensions/arktype-json/src/exports/codecs.ts
  • packages/2-sql/4-lanes/relational-core/README.md
  • packages/3-targets/3-targets/postgres/test/codecs-class.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • docs/reference/codec-authoring-guide.md
  • packages/2-sql/5-runtime/src/sql-context.ts
  • packages/3-targets/3-targets/postgres/src/exports/codec-types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/3-extensions/arktype-json/src/exports/column-types.ts

Comment thread packages/3-targets/3-targets/postgres/src/core/codec-helpers.ts
Comment thread packages/3-targets/3-targets/postgres/src/core/codec-helpers.ts
Comment thread packages/3-targets/3-targets/postgres/src/core/codec-helpers.ts
Comment thread packages/3-targets/3-targets/sqlite/src/core/codecs.ts
Comment thread packages/1-framework/1-core/framework-components/src/control/control-stack.ts Outdated
Comment thread packages/1-framework/0-foundation/contract/src/standard-schema-utils.ts Outdated
Comment thread packages/1-framework/1-core/framework-components/src/control/control-stack.ts Outdated
Comment thread packages/1-framework/1-core/framework-components/test/control-stack.test.ts Outdated
Comment thread packages/3-targets/3-targets/postgres/src/core/codecs-class.ts Outdated
Comment thread packages/3-targets/3-targets/postgres/src/core/codecs-class.ts Outdated
Comment thread packages/1-framework/0-foundation/contract/src/standard-schema-utils.ts Outdated
Comment thread packages/1-framework/1-core/framework-components/src/control/control-stack.ts Outdated
Comment thread packages/1-framework/1-core/framework-components/src/shared/codec.ts Outdated
Comment thread packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts Outdated
Comment thread packages/2-sql/4-lanes/relational-core/src/ast/validate-param-refs.ts Outdated
@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented May 8, 2026

All actionable items in this review body are addressed in the inline thread replies; see those for closing commits.

On the outside-diff finding for packages/2-sql/5-runtime/src/sql-context.ts:493-516 (collapsing non-parameterized column codecs to one instance per codecId): this is the documented F27 phase 2 design (commit 0e3aafc0b). Non-parameterized codecs are, by definition, independent of column context — the name / usedAt from CodecInstanceContext is metadata for diagnostics, not state the conversion logic is allowed to depend on. Column-aware dispatch is reserved for parameterized codecs and flows through forColumn (F22+F26+F29 cluster, commit 20f99bffd); the cluster also adds ambiguousCodecIds rejection so a parameterized codec cannot accidentally collapse via this byCodecId path.

The nitpicks (column-spec generic threading, Object.hasOwn on the test fixture, barrel imports in relational-core/test/utils.ts, the unreachable precision === undefined check) are noted but out of scope for TML-2357 — they're cleanup follow-ups that don't affect this PR's acceptance criteria. Closing.

@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented May 8, 2026

All actionable findings in this review body are duplicates of inline threads or other review bodies and are closed:

  • arktype-json-codec-class.ts rehydrateSchema double-cast → F23 (48ed1d135): replaced with isArktypeSchemaLike type-predicate; rehydration throws RUNTIME.JSON_SCHEMA_VALIDATION_FAILED on shape mismatch.
  • arktype-json-codec-class.test.ts as any + biome-ignore → F24 (48ed1d135): replaced with @ts-expect-error.
  • arktype-json-codec-class.types.test-d.ts deprecated toMatchTypeOf → F25 (48ed1d135): replaced with toExtend.
  • sqlite/codecs-class.ts:245-258 invalid Date → F37 (182d10c88): shared parseDate helper.
  • sql-codecs-class.ts:67-76 lengthParamsSchema vs LengthParams mismatch → F20 (cfa078a23): schema tightened to 'length?': 'number.integer > 0'; helpers' params: LengthParams = {} now agrees end-to-end.

Nitpicks (nudges on adapter.ts factory(undefined) invariants and the codecs.test.ts paramsByScalar shape) are noted but out of scope for TML-2357. Closing.

@wmadden
Copy link
Copy Markdown
Contributor Author

wmadden commented May 8, 2026

All actionable findings in this review body are closed via the inline thread replies (F29, F34, F35, F36, F37, F39 — see those threads for closing commits).

On the outside-diff finding for packages/3-targets/3-targets/postgres/src/core/codecs.ts:110-124 (length-parameter helpers emitting params their descriptors reject): closed by the F20 closure (commit cfa078a23) that tightened lengthParamsSchema to 'length?': 'number.integer > 0' so the schema and the helpers' params: LengthParams = {} agree, and by F11 (f725db1f8) which split the SQL helpers cleanly.

Nitpicks (descriptor-first shape for codecs.test.ts:75-82, runtime-neutral base64 for sqlite/codecs-class.ts:204-211, fail-fast factory(undefined) invariant in postgres/sqlite adapters) are noted but out of scope for TML-2357. Closing.

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)
packages/2-sql/5-runtime/src/codecs/encoding.ts (1)

141-144: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Preserve codec-authored runtime errors during encode.

encodeParamValue() wraps every thrown error as RUNTIME.ENCODE_FAILED. That double-wraps codec-generated RUNTIME.ENCODE_FAILED envelopes and downgrades a codec-thrown RUNTIME.ABORTED into the wrong error code. Pass known runtime envelopes through before calling wrapEncodeFailure().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/2-sql/5-runtime/src/codecs/encoding.ts` around lines 141 - 144, In
encodeParamValue's catch block around codec.encode(value, ctx), detect if the
thrown error is already a runtime envelope (i.e., a codec-authored runtime
error/exception) and rethrow it unchanged instead of wrapping; otherwise call
wrapEncodeFailure(error, metadata, paramIndex, codec.id). Update the catch to
explicitly pass through known runtime envelopes (identify by the runtime
envelope shape/marker used in this project) before invoking wrapEncodeFailure so
codec-thrown RUNTIME.* errors are preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/2-sql/5-runtime/src/codecs/decoding.ts`:
- Around line 260-263: decodeField currently wraps every thrown error into
RUNTIME.DECODE_FAILED; change the catch in decodeField so it only calls
wrapDecodeFailure for non-runtime/foreign errors: if the caught error is already
a codec-produced runtime envelope (e.g., has the runtime failure shape or codes
like RUNTIME.DECODE_FAILED or RUNTIME.ABORTED) then rethrow it unchanged,
otherwise call wrapDecodeFailure(alias, ref, codec, wireValue) and throw that;
reference the decodeField function, the codec.decode call, and wrapDecodeFailure
when making this conditional check so codec-authored runtime envelopes are
preserved.

In `@packages/2-sql/5-runtime/src/sql-context.ts`:
- Around line 273-282: The partitioning logic currently checks
descriptor.paramsSchema !== voidParamsSchema which is brittle; change the branch
to use the descriptor.isParameterized boolean as the discriminator so
descriptors are routed correctly into the parameterized map
(parameterized.set(... as RuntimeParameterizedCodecDescriptor)) vs the
unparameterized path, ensuring validateTypeParams() and initializeTypeHelpers()
are invoked for parameterized descriptors; update any comments referencing
paramsSchema identity to reflect isParameterized as the source of truth.
- Around line 410-427: The current loop pre-creates and caches a single shared
codec instance in byCodecId and then reuses that same instance for column-bound
lookups, causing descriptor.factory to see the shared SqlCodecInstanceContext
instead of the real column context; change the logic so the pre-populated
instance remains only as the forCodecId() fallback, and when populating entries
for forColumn(table, column) always materialize a fresh codec instance via
descriptor.factory(...) with a column-specific SqlCodecInstanceContext (e.g.
name like `<col:${table}.${column}>` and usedAt set to the column site) rather
than reusing the shared instance; apply the same change in the second block
referenced (the code around the 492-512 region) so non-parameterized descriptors
are only cached as a fallback and per-column instances are created with real
column contexts.

In `@packages/3-mongo-target/2-mongo-adapter/src/core/codecs.ts`:
- Around line 121-124: The guard in renderOutputType that validates the variable
length currently only checks for number, finiteness, and integer-ness but allows
0 and negatives; update the validation in renderOutputType (in codecs.ts) to
also require length > 0 and throw the same (or a clearer) Error when length is
not a positive integer so invalid inputs cannot produce Vector<0> or Vector<-1>.

---

Outside diff comments:
In `@packages/2-sql/5-runtime/src/codecs/encoding.ts`:
- Around line 141-144: In encodeParamValue's catch block around
codec.encode(value, ctx), detect if the thrown error is already a runtime
envelope (i.e., a codec-authored runtime error/exception) and rethrow it
unchanged instead of wrapping; otherwise call wrapEncodeFailure(error, metadata,
paramIndex, codec.id). Update the catch to explicitly pass through known runtime
envelopes (identify by the runtime envelope shape/marker used in this project)
before invoking wrapEncodeFailure so codec-thrown RUNTIME.* errors are
preserved.
🪄 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: bd164814-d8cb-4c7c-9ca5-571e8aa245a4

📥 Commits

Reviewing files that changed from the base of the PR and between c4d81ad and 0e3aafc.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (61)
  • docs/reference/codec-authoring-guide.md
  • examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec.ts
  • packages/1-framework/1-core/framework-components/test/codec-types.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/control-stack.test.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/adapter-types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codec-helpers.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/validate-param-refs.ts
  • packages/2-sql/4-lanes/relational-core/src/codec-descriptor-registry.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/ast.ts
  • packages/2-sql/4-lanes/relational-core/src/query-lane-context.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codec-helpers.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/validate-param-refs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/utils.ts
  • packages/2-sql/5-runtime/src/codecs/decoding.ts
  • packages/2-sql/5-runtime/src/codecs/encoding.ts
  • packages/2-sql/5-runtime/src/codecs/validation.ts
  • packages/2-sql/5-runtime/src/sql-context.ts
  • packages/2-sql/5-runtime/src/sql-runtime.ts
  • packages/2-sql/5-runtime/test/before-compile-chain.test.ts
  • packages/2-sql/5-runtime/test/codec-async.test.ts
  • packages/2-sql/5-runtime/test/codec-decode-ctx.test.ts
  • packages/2-sql/5-runtime/test/codec-encode-ctx.test.ts
  • packages/2-sql/5-runtime/test/contract-codec-registry.test.ts
  • packages/2-sql/5-runtime/test/encoding-dispatch.test.ts
  • packages/2-sql/5-runtime/test/execution-stack.test.ts
  • packages/2-sql/5-runtime/test/parameterized-types.test.ts
  • packages/2-sql/5-runtime/test/sql-context.test.ts
  • packages/2-sql/5-runtime/test/sql-family-adapter.test.ts
  • packages/2-sql/5-runtime/test/sql-runtime-abort.test.ts
  • packages/2-sql/5-runtime/test/sql-runtime.test.ts
  • packages/2-sql/5-runtime/test/utils.ts
  • packages/3-extensions/arktype-json/package.json
  • packages/3-extensions/arktype-json/src/core/arktype-json-codec.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.test.ts
  • packages/3-extensions/arktype-json/test/arktype-json-codec.types.test-d.ts
  • packages/3-extensions/pgvector/package.json
  • packages/3-extensions/pgvector/src/core/codecs.ts
  • packages/3-extensions/pgvector/test/codecs.test.ts
  • packages/3-extensions/sql-orm-client/src/types.ts
  • packages/3-extensions/sql-orm-client/test/model-accessor.test.ts
  • packages/3-mongo-target/2-mongo-adapter/src/core/codecs.ts
  • packages/3-targets/3-targets/postgres/src/core/codec-helpers.ts
  • packages/3-targets/3-targets/postgres/src/core/codec-type-map.ts
  • packages/3-targets/3-targets/postgres/src/core/codecs.ts
  • packages/3-targets/3-targets/postgres/src/exports/codec-types.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.types.test-d.ts
  • packages/3-targets/3-targets/sqlite/src/core/codecs.ts
  • packages/3-targets/6-adapters/postgres/src/core/adapter.ts
  • packages/3-targets/6-adapters/postgres/test/adapter.test.ts
  • packages/3-targets/6-adapters/postgres/test/descriptor-parity.test.ts
  • packages/3-targets/6-adapters/postgres/test/sql-renderer.cast-policy.test.ts
  • packages/3-targets/6-adapters/sqlite/src/core/adapter.ts
  • test/integration/test/cross-package/cross-family-codec.test.ts
💤 Files with no reviewable changes (2)
  • packages/2-sql/4-lanes/relational-core/src/ast/adapter-types.ts
  • packages/2-sql/5-runtime/test/sql-family-adapter.test.ts
✅ Files skipped from review due to trivial changes (2)
  • packages/3-extensions/arktype-json/package.json
  • packages/3-extensions/arktype-json/test/arktype-json-codec.types.test-d.ts
🚧 Files skipped from review as they are similar to previous changes (16)
  • packages/2-sql/5-runtime/test/codec-async.test.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts
  • packages/3-targets/3-targets/postgres/test/codecs-class.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/control-stack.test.ts
  • packages/1-framework/1-core/framework-components/test/codec-types.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/codec-descriptor-registry.ts
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/2-sql/5-runtime/test/contract-codec-registry.test.ts
  • examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
  • packages/2-sql/5-runtime/test/execution-stack.test.ts
  • packages/2-sql/5-runtime/test/encoding-dispatch.test.ts
  • packages/3-extensions/pgvector/src/core/codecs.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs.ts
  • packages/3-targets/3-targets/postgres/src/core/codec-helpers.ts
  • packages/3-targets/3-targets/postgres/src/core/codecs.ts

Comment thread packages/2-sql/5-runtime/src/codecs/decoding.ts
Comment thread packages/2-sql/5-runtime/src/sql-context.ts Outdated
Comment thread packages/2-sql/5-runtime/src/sql-context.ts Outdated
Comment thread packages/3-mongo-target/2-mongo-adapter/src/core/codecs.ts Outdated
@wmadden wmadden force-pushed the tml-2357-codec-registration-model-complete-the-unified branch from 0e3aafc to c99c1ba Compare May 9, 2026 06:07
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: 2

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/adrs/ADR 204 - Single-Path Async Codec Runtime.md (1)

43-56: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clarify this section as historical to avoid implying defineCodec() is current.

This section reads as present-day behavior (defineCodec() lifting sync methods), but the retrospective note says that authoring surface is retired. Please mark these statements as historical-era mechanics so the ADR stays internally consistent.

As per coding guidelines, "**/*.{md,mdx}: Keep docs current (READMEs, rules, links)`."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/architecture` docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md
around lines 43 - 56, This section currently describes
defineCodec()/mongoCodec() and the Codec interface as if they are current; mark
these sentences as historical by adding a short qualifier (e.g., "Historical:",
"Legacy behavior:", or "Former design:") before the paragraph that explains that
defineCodec() lifts sync methods to Promise-returning query-time methods and the
listed Codec shape (encode/decode behavior), and update any present-tense verbs
to past-tense for symbols like defineCodec(), mongoCodec(), Codec, encode,
decode, encodeJson, decodeJson so it clearly reads as retired/legacy mechanics
rather than current behavior.
🧹 Nitpick comments (2)
docs/architecture docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md (1)

237-237: ⚡ Quick win

Move implementation mechanics out of the ADR body.

This line includes concrete internal wiring and file-path implementation detail. Prefer keeping ADR text at decision/constraint level and linking to subsystem docs for mechanics.

Based on learnings, "ADRs in prisma/prisma-next should document architectural design decisions and the key constraints/assumptions only. Do not include implementation algorithms, emitter derivation logic, or step-by-step derivation/migration rules."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/architecture` docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md at
line 237, The ADR includes low-level wiring and file-path detail; remove the
implementation mechanics and file paths and rephrase to the decision/constraint
level: state that component descriptors declare codecs
(ComponentMetadata.types.codecTypes.codecDescriptors), the framework aggregates
those via the execution-stack into a single MongoCodecRegistry exposed on the
execution context (context.codecs) by createMongoExecutionContext, and that
MongoRuntimeOptions no longer accepts a codecs field; move the detailed folding
algorithm and any package/file-specific implementation (e.g., the previous
package paths) into a linked subsystem implementation doc instead of the ADR
body.
docs/architecture docs/adrs/ADR 208 - Higher-order codecs for parameterized types.md (1)

166-175: ⚡ Quick win

Move the numbered runtime build sequence out of the ADR.

This section drops into implementation algorithm detail (forColumn prebuild steps, caching order, and validation flow) rather than the architectural decision itself. Keeping the ADR at the invariant level here would age better; the step-by-step assembly belongs in subsystem/runtime docs.

Based on learnings, "ADRs in prisma/prisma-next should document architectural design decisions and the key constraints/assumptions only. Do not include implementation algorithms, emitter derivation logic, or step-by-step derivation/migration rules."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/architecture` docs/adrs/ADR 208 - Higher-order codecs for parameterized
types.md around lines 166 - 175, The ADR currently includes implementation-level
algorithmic steps (the numbered "forColumn" build sequence, caching/validation
order and materialization details) that should be removed from the ADR and moved
to runtime/subsystem documentation; edit the ADR so it only documents the
high-level decision and invariants (that a descriptor map keyed by codecId
exists, that descriptorFor(codecId) exposes metadata, and forColumn(table,
column) resolves per-instance vs singleton codecs) and remove the detailed
prebuild steps referencing storage.tables[].columns[], descriptor.factory(...),
descriptor.paramsSchema['~standard'].validate(...), and decode(...) validation
behavior; instead add a short pointer/note in the ADR referencing the runtime
docs where the concrete assembly, caching, and JSON-schema validation
implementation is described.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/architecture` docs/adrs/ADR 208 - Higher-order codecs for parameterized
types.md:
- Around line 258-259: Replace the bullet that mentions "Mongo control-plane
parameterized-codecs slot" and any reference to "parameterizedCodecs:" with
phrasing that Mongo will adopt the unified "codecs:" registration surface (e.g.,
"Mongo control-plane to adopt unified codecs: registration surface") so the ADR
no longer reintroduces the retired `parameterized-codecs slot` vocabulary and
matches the deleted `parameterizedCodecs:` slot stated earlier.

In `@packages/1-framework/1-core/framework-components/README.md`:
- Line 34: The README incorrectly states that TypeScript bivariance permits
synchronous method bodies to satisfy Promise return types and shows an example
using property syntax and an optional ctx; fix the text and example: update the
explanation to state that bivariance only affects parameter type checking and
that methods declared to return Promise<T> must return a compatible Promise (use
async or explicitly return a Promise), change the sketch to extend CodecImpl and
implement encode(...) and decode(...) as class methods (not property shorthand),
and make the ctx parameter required and use ctx.signal (not ctx?.signal) in the
method signatures and bodies; reference the CodecImpl class and the
encode/decode methods when making these edits.

---

Outside diff comments:
In `@docs/architecture` docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md:
- Around line 43-56: This section currently describes defineCodec()/mongoCodec()
and the Codec interface as if they are current; mark these sentences as
historical by adding a short qualifier (e.g., "Historical:", "Legacy behavior:",
or "Former design:") before the paragraph that explains that defineCodec() lifts
sync methods to Promise-returning query-time methods and the listed Codec shape
(encode/decode behavior), and update any present-tense verbs to past-tense for
symbols like defineCodec(), mongoCodec(), Codec, encode, decode, encodeJson,
decodeJson so it clearly reads as retired/legacy mechanics rather than current
behavior.

---

Nitpick comments:
In `@docs/architecture` docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md:
- Line 237: The ADR includes low-level wiring and file-path detail; remove the
implementation mechanics and file paths and rephrase to the decision/constraint
level: state that component descriptors declare codecs
(ComponentMetadata.types.codecTypes.codecDescriptors), the framework aggregates
those via the execution-stack into a single MongoCodecRegistry exposed on the
execution context (context.codecs) by createMongoExecutionContext, and that
MongoRuntimeOptions no longer accepts a codecs field; move the detailed folding
algorithm and any package/file-specific implementation (e.g., the previous
package paths) into a linked subsystem implementation doc instead of the ADR
body.

In `@docs/architecture` docs/adrs/ADR 208 - Higher-order codecs for parameterized
types.md:
- Around line 166-175: The ADR currently includes implementation-level
algorithmic steps (the numbered "forColumn" build sequence, caching/validation
order and materialization details) that should be removed from the ADR and moved
to runtime/subsystem documentation; edit the ADR so it only documents the
high-level decision and invariants (that a descriptor map keyed by codecId
exists, that descriptorFor(codecId) exposes metadata, and forColumn(table,
column) resolves per-instance vs singleton codecs) and remove the detailed
prebuild steps referencing storage.tables[].columns[], descriptor.factory(...),
descriptor.paramsSchema['~standard'].validate(...), and decode(...) validation
behavior; instead add a short pointer/note in the ADR referencing the runtime
docs where the concrete assembly, caching, and JSON-schema validation
implementation is described.
🪄 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: 788f2e6c-0cb2-4466-aa83-d810249436a2

📥 Commits

Reviewing files that changed from the base of the PR and between 0e3aafc and c99c1ba.

📒 Files selected for processing (114)
  • docs/README.md
  • docs/Testing Guide.md
  • docs/architecture docs/adrs/ADR 152 - Execution Plane Descriptors and Instances.md
  • docs/architecture docs/adrs/ADR 184 - Codec-owned value serialization.md
  • docs/architecture docs/adrs/ADR 186 - Codec-dispatched type rendering.md
  • docs/architecture docs/adrs/ADR 202 - Codec trait system.md
  • docs/architecture docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md
  • docs/architecture docs/adrs/ADR 205 - SQL cast emission is adapter policy.md
  • docs/architecture docs/adrs/ADR 207 - Codec call context per-query AbortSignal and column metadata.md
  • docs/architecture docs/adrs/ADR 208 - Higher-order codecs for parameterized types.md
  • docs/architecture docs/adrs/ADR 209 - Mongo result-shape as a structural plan field.md
  • docs/architecture docs/subsystems/2. Contract Emitter & Types.md
  • docs/reference/codec-authoring-guide.md
  • docs/reference/community-generator-migration-analysis.md
  • docs/reference/framework-gaps.md
  • docs/reference/typescript-patterns.md
  • examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
  • packages/1-framework/0-foundation/contract/package.json
  • packages/1-framework/1-core/framework-components/README.md
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/1-framework/1-core/framework-components/src/exports/codec.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-types.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec.ts
  • packages/1-framework/1-core/framework-components/src/shared/column-spec.ts
  • packages/1-framework/1-core/framework-components/src/shared/framework-components.ts
  • packages/1-framework/1-core/framework-components/test/codec-call-context.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/codec-types.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/codec.test.ts
  • packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/control-stack.test.ts
  • packages/1-framework/2-authoring/contract/README.md
  • packages/1-framework/2-authoring/contract/src/descriptors.ts
  • packages/1-framework/2-authoring/contract/src/index.ts
  • packages/1-framework/2-authoring/contract/test/descriptors.test.ts
  • packages/1-framework/2-authoring/ids/package.json
  • packages/1-framework/2-authoring/ids/src/index.ts
  • packages/1-framework/3-tooling/cli/src/control-api/contract-enrichment.ts
  • packages/1-framework/3-tooling/cli/test/config-types.test.ts
  • packages/1-framework/3-tooling/cli/test/control-api/contract-enrichment.test.ts
  • packages/1-framework/3-tooling/emitter/src/domain-type-generation.ts
  • packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/README.md
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codec-registry.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codecs.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/exports/index.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/src/derive-json-schema.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/derive-json-schema.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.polymorphism.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.test.ts
  • packages/2-mongo-family/7-runtime/README.md
  • packages/2-mongo-family/7-runtime/src/mongo-execution-stack.ts
  • packages/2-mongo-family/7-runtime/test/codecs/decoding.test.ts
  • packages/2-mongo-family/7-runtime/test/decode.integration.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-stack.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-middleware.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime-abort.test.ts
  • packages/2-sql/2-authoring/contract-psl/src/provider.ts
  • packages/2-sql/2-authoring/contract-psl/src/psl-column-resolution.ts
  • packages/2-sql/2-authoring/contract-psl/test/fixtures.ts
  • packages/2-sql/2-authoring/contract-psl/test/provider.test.ts
  • packages/2-sql/2-authoring/contract-psl/test/ts-psl-parity.test.ts
  • packages/2-sql/2-authoring/contract-ts/src/contract-definition.ts
  • packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts
  • packages/2-sql/2-authoring/contract-ts/src/contract-lowering.ts
  • packages/2-sql/2-authoring/contract-ts/test/config-types.test.ts
  • packages/2-sql/2-authoring/contract-ts/test/contract-builder.contract-definition.test.ts
  • packages/2-sql/2-authoring/contract-ts/test/contract-builder.value-objects.test.ts
  • packages/2-sql/2-authoring/contract-ts/test/helpers/column-descriptor.ts
  • packages/2-sql/3-tooling/emitter/test/emitter-hook.typeref-resolver.test.ts
  • packages/2-sql/4-lanes/relational-core/README.md
  • packages/2-sql/4-lanes/relational-core/package.json
  • packages/2-sql/4-lanes/relational-core/src/ast/adapter-types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codec-helpers.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/types.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/validate-param-refs.ts
  • packages/2-sql/4-lanes/relational-core/src/codec-descriptor-registry.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/ast.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/codec-descriptor-registry.ts
  • packages/2-sql/4-lanes/relational-core/src/expression.ts
  • packages/2-sql/4-lanes/relational-core/src/query-lane-context.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory-ctx.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory-ctx.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-types.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/refs-propagation.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codec-helpers.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/test-codec.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/test-helpers.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/validate-param-refs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/expression.test.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/utils.ts
  • packages/2-sql/4-lanes/relational-core/tsdown.config.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/builder-base.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/expression-impl.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/field-proxy.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/functions.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/mutation-impl.ts
  • packages/2-sql/4-lanes/sql-builder/test/runtime/field-proxy.test.ts
  • packages/2-sql/4-lanes/sql-builder/test/runtime/functions.test.ts
  • packages/2-sql/5-runtime/src/codecs/decoding.ts
  • packages/2-sql/5-runtime/src/codecs/encoding.ts
  • packages/2-sql/5-runtime/src/codecs/json-schema-validation.ts
  • packages/2-sql/5-runtime/src/codecs/validation.ts
💤 Files with no reviewable changes (7)
  • packages/1-framework/2-authoring/contract/src/descriptors.ts
  • packages/2-sql/5-runtime/src/codecs/json-schema-validation.ts
  • packages/2-mongo-family/7-runtime/test/decode.integration.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-types.test.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/adapter-types.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test-d.ts
✅ Files skipped from review due to trivial changes (33)
  • packages/2-sql/4-lanes/relational-core/src/exports/codec-descriptor-registry.ts
  • packages/2-sql/4-lanes/relational-core/tsdown.config.ts
  • packages/1-framework/0-foundation/contract/package.json
  • docs/architecture docs/adrs/ADR 202 - Codec trait system.md
  • packages/2-sql/2-authoring/contract-ts/test/helpers/column-descriptor.ts
  • packages/1-framework/1-core/framework-components/test/codec-call-context.types.test-d.ts
  • packages/2-sql/2-authoring/contract-ts/test/config-types.test.ts
  • docs/architecture docs/subsystems/2. Contract Emitter & Types.md
  • docs/architecture docs/adrs/ADR 205 - SQL cast emission is adapter policy.md
  • packages/2-sql/2-authoring/contract-ts/src/contract-definition.ts
  • packages/2-mongo-family/7-runtime/src/mongo-execution-stack.ts
  • packages/1-framework/2-authoring/ids/package.json
  • packages/1-framework/2-authoring/ids/src/index.ts
  • packages/2-sql/3-tooling/emitter/test/emitter-hook.typeref-resolver.test.ts
  • docs/architecture docs/adrs/ADR 186 - Codec-dispatched type rendering.md
  • docs/README.md
  • packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts
  • docs/reference/community-generator-migration-analysis.md
  • docs/architecture docs/adrs/ADR 152 - Execution Plane Descriptors and Instances.md
  • packages/1-framework/2-authoring/contract/README.md
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory.test.ts
  • packages/2-sql/2-authoring/contract-ts/test/contract-builder.value-objects.test.ts
  • docs/architecture docs/adrs/ADR 209 - Mongo result-shape as a structural plan field.md
  • packages/2-mongo-family/7-runtime/README.md
  • docs/reference/framework-gaps.md
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/validate-param-refs.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-stack.test.ts
  • docs/architecture docs/adrs/ADR 207 - Codec call context per-query AbortSignal and column metadata.md
  • docs/reference/codec-authoring-guide.md
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory-ctx.test.ts
  • packages/2-sql/4-lanes/relational-core/README.md
  • docs/Testing Guide.md
🚧 Files skipped from review as they are similar to previous changes (60)
  • packages/2-sql/4-lanes/relational-core/package.json
  • packages/1-framework/2-authoring/contract/src/index.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime-abort.test.ts
  • packages/2-sql/2-authoring/contract-psl/test/ts-psl-parity.test.ts
  • packages/2-sql/2-authoring/contract-psl/src/provider.ts
  • packages/1-framework/3-tooling/cli/test/config-types.test.ts
  • packages/2-sql/4-lanes/relational-core/src/exports/ast.ts
  • packages/2-sql/2-authoring/contract-ts/src/contract-lowering.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/builder-base.ts
  • packages/2-sql/5-runtime/src/codecs/validation.ts
  • packages/1-framework/3-tooling/emitter/src/domain-type-generation.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/derive-json-schema.test.ts
  • packages/2-sql/4-lanes/relational-core/src/expression.ts
  • packages/1-framework/2-authoring/contract/test/descriptors.test.ts
  • packages/1-framework/1-core/framework-components/src/shared/framework-components.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/mutation-impl.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/refs-propagation.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/validate-param-refs.ts
  • packages/1-framework/1-core/framework-components/test/codec-types.types.test-d.ts
  • packages/1-framework/3-tooling/cli/test/control-api/contract-enrichment.test.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/expression-impl.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/codec-factory-ctx.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/codec-descriptor-registry.ts
  • packages/2-sql/4-lanes/relational-core/test/typed-codec-flow.test-d.ts
  • packages/2-sql/2-authoring/contract-ts/test/contract-builder.contract-definition.test.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codecs.ts
  • packages/2-sql/4-lanes/relational-core/test/expression.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.test.ts
  • packages/1-framework/1-core/framework-components/src/shared/column-spec.ts
  • packages/2-sql/2-authoring/contract-psl/test/fixtures.ts
  • packages/2-sql/5-runtime/src/codecs/encoding.ts
  • packages/1-framework/3-tooling/cli/src/control-api/contract-enrichment.ts
  • packages/2-sql/4-lanes/sql-builder/test/runtime/functions.test.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codecs.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/test/ast/sql-codec-helpers.test.ts
  • packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/types.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/README.md
  • packages/2-sql/4-lanes/relational-core/src/ast/sql-codec-helpers.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.test.ts
  • examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
  • packages/2-mongo-family/7-runtime/test/codecs/decoding.test.ts
  • packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codec-registry.ts
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test-d.ts
  • packages/2-sql/5-runtime/src/codecs/decoding.ts
  • packages/2-sql/2-authoring/contract-psl/test/provider.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-middleware.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.polymorphism.test.ts
  • packages/1-framework/1-core/framework-components/test/control-stack.test.ts
  • packages/2-sql/4-lanes/relational-core/test/utils.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codecs.ts
  • packages/2-sql/4-lanes/sql-builder/src/runtime/field-proxy.ts
  • packages/1-framework/1-core/framework-components/src/exports/codec.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts
  • packages/2-sql/4-lanes/relational-core/src/query-lane-context.ts
  • packages/2-sql/4-lanes/relational-core/src/ast/codec-types.ts

Comment thread packages/1-framework/1-core/framework-components/README.md Outdated
@wmadden wmadden force-pushed the tml-2357-codec-registration-model-complete-the-unified branch 2 times, most recently from aa0e4b3 to 70b386c Compare May 9, 2026 14:35
@wmadden wmadden requested a review from a team as a code owner May 9, 2026 14:35
wmadden and others added 11 commits May 9, 2026 17:48
Completes the registration-side migration codec-registry-unification
(TML-2229) deferred. Branched off origin/main post-TML-2229 merge.

Six structural defects in the codec registration model retire across
four milestones:

- M1: narrow runtime Codec instance to `{ id, encode, decode, encodeJson,
  decodeJson }`; route emit-path renderOutputType through
  descriptorFor(codecId).
- M2: every codec ships native CodecDescriptor through unified codecs:
  slot; synthesis bridge, parameterizedCodecs: slot, CodecParamsDescriptor,
  aliasCodec, and arktypeJsonEmitCodec all delete; aliasDescriptor
  replaces aliasCodec.
- M3: ParamRef gains refs?: { table, column }; validator-pass enforces
  refs-required for parameterized codec ids; encode-side dispatch goes
  through forColumn; forCodecId fallback retires for parameterized codec
  ids.
- M4: JsonSchemaValidatorRegistry deletes; validation lives inline in the
  resolved codec decode body (matching the arktype-json pattern parent
  established); json-validator trait retires if no consumer remains.

Mongo registration migration is folded into TML-2324.
…me Codec instance

Mid-flight WIP from the M1 implementer subagent (implementer-m1-r1).
Captured at user request before subagent return.

Substantive shape:
- Narrow framework Codec interface: drop traits / targetTypes /
  renderOutputType? from the instance; encode TTraits as a phantom-
  symbol carrier so trait-gated downstream type machinery still works
  without a runtime field.
- Extend CodecLookup with descriptor-routed accessors
  (targetTypesFor, metaFor, renderOutputTypeFor) so consumer sites
  reach codec-id-keyed metadata without reading off the codec
  instance.
- Migrate consumer reads in framework-components/control-stack,
  emitter/domain-type-generation, mongo-codec, mongo-contract-psl,
  sql-contract-psl/provider, relational-core/ast/codec-types,
  sql-runtime/sql-context, and postgres-adapter/sql-renderer to read
  through the new accessors.
- Thread explicit { traits, targetTypes, meta } args into
  synthesizeNonParameterizedDescriptor so contributor code keeps
  compiling while the bridge survives until M2.

Known incomplete: workspace typecheck fails in
@prisma-next/mongo-codec on an unused-import lint (`ifDefined`); the
subagent has not yet completed its M1 R1 round. Pushing as a
checkpoint per user request; subagent return + cleanup will land in a
follow-up commit.
Picks up from WIP commit 692178c and lands the changes the prior
implementer needed to reach a green validation gate.

What this commit adds, on top of the WIP:

- mongo-codec: drop the unused `ifDefined` import-then-unused regression,
  re-shape `MongoCodec` to extend the narrow framework `Codec` while
  keeping `traits` / `targetTypes` / `renderOutputType` as optional
  transitional fields (per the M1 plan, these survive on family-specific
  Codec extensions until M2). Re-thread the runtime factory so
  `mongoCodec()` still emits `targetTypes` / `traits` /
  `renderOutputType` on the resolved instance for downstream consumers.
- relational-core/ast/codec-types: keep SQL `Codec` extending the narrow
  framework `Codec` and re-declare `traits` / `targetTypes` / `meta` /
  `paramsSchema` / `init` / `renderOutputType` as optional transitional
  fields for M1; `targetTypes` becomes optional throughout. Defensively
  default `codec.targetTypes ?? []` in `CodecRegistryImpl.register`.
- sql-runtime/sql-context: pass `targetTypes ?? []` into the synthesis
  bridge so a codec without that field still lifts to a descriptor.
- arktype-json: type the emit-only shim against the SQL `Codec` (which
  still carries the transitional metadata fields) rather than the
  narrowed framework `Codec`.
- adapter-postgres/codec-lookup: implement the new `CodecLookup` accessors
  (`targetTypesFor`, `metaFor`, `renderOutputTypeFor`) on top of the
  built-in postgres codec map.

Test mocks updated to fully implement the widened `CodecLookup` shape:
emitter, sql-renderer cast-policy, mongo / sql contract-psl,
contract-ts, cli config + contract-enrichment, and integration tests
(`ts-psl-parity.real-packs`, `migration-psl-authoring`). Where tests
read `codec.targetTypes` directly, they now read through
`codecLookup.targetTypesFor(codecId)`.

No production reads of the removed framework-`Codec` fields remain:
the only direct `codec.traits` / `codec.targetTypes` / `codec.meta`
reads under packages/ are the synthesis bridge call site
(sql-context.ts) and the SQL `CodecRegistryImpl.register` loop, both
operating on SQL `Codec` whose interface still carries them in M1.

Validation: `pnpm typecheck`, `pnpm lint:deps`, `pnpm test:packages`,
`pnpm test:e2e`, `pnpm build`, and demo emit byte-identical against
`origin/main` all pass.

Refs: TML-2357
…nts (D1, D2)

- Spec AC-3 § 2: split family-extension narrow across M1 (framework) /
  M2 (family extensions, alongside synthesis-bridge deletion). The
  two-stage ordering is intentional and was implicit in the plan; the
  spec now states it explicitly so future readers and the AC scoreboard
  agree on the milestone boundary.
- Plan T1.4: tighten the emit-path file list to the single production
  site on origin/main (domain-type-generation.ts). The original
  enumeration of emit.ts / emit-types.ts / generate-contract-dts.ts
  was aspirational; reviewer grep on origin/main confirmed only one
  real read site.

Sourced from m1 R1 reviewer report § Items for the user's attention
(D1, D2). Refs TML-2357.
Drops two unnecessary `as unknown as ...` casts in
`adapter-postgres/codec-lookup.ts` and tightens the existing comment
block on the genuinely-transitional cast in
`framework-components/control-stack.ts` to name F1 explicitly.

Site (1) — `definition.codec as unknown as SqlCodec` (line 22): the
`defineCodecs` builder already types `definition.codec` as the SQL
`Codec` extension, so the cast was a no-op fossil from R1 plumbing.
Drop it; `byId.set(definition.codec.id, definition.codec)` typechecks
directly.

Site (2) — `byId.get(id) as Codec | undefined` (line 25): `SqlCodec`
extends the framework `Codec`, so the lookup return type widens
without an explicit cast. Drop it; `get: (id) => byId.get(id)`
typechecks under the `CodecLookup` interface contract directly.

Site (3) — `legacyMeta = codec as unknown as LegacyCodecInstanceMeta`
in `extractCodecLookup` (line 377): genuinely transitional. The
framework `Codec` interface narrowed in M1 but family-`Codec`
extensions still carry `traits` / `targetTypes` / `meta` /
`renderOutputType` as optional transitional fields, and the assembled
`CodecLookup` has to surface them to the new descriptor-routed
accessors until every contributor ships a native `CodecDescriptor`.
Comment block now names this disposition explicitly so the next
reader knows the cast is documented M2-bundled cleanup, not a
forgotten loose end.

Validation: `pnpm typecheck`, `pnpm lint:deps`, `pnpm test:packages`,
`pnpm test:e2e`, `pnpm build`, demo emit byte-identical against
`origin/main` all pass.

Refs: TML-2357
Composes a derived CodecDescriptor by overlaying codecId, targetTypes,
and optional meta on a base descriptor. The alias factory delegates to
the base factory and rewrites `id` on the resolved codec.

Replaces the legacy `aliasCodec` helper that composed at the codec-
instance level. Lives in framework-components so SQL families can share
it without a target-specific dep.

Refs TML-2357 T2.1.
…() parallel APIs

Introduces the descriptor-shaped factory + builder in
sql-relational-core that the per-package M2 migrations will adopt,
without disturbing the legacy codec()/defineCodecs() that 28+ existing
consumers (production + tests) still depend on.

The plan T2.2 deferred the absorb-vs-parallel choice to implementation
start, biased to absorb when "structurally clean". Implementation-time
recon found absorb is not clean: 28+ direct codec() consumers would
break simultaneously and 15+ test files read transitional fields off
the resolved Codec instance. Per the plan's fallback ("only introduce
a parallel defineCodecDescriptors if defineCodecs doesn't admit a
clean shape"), this is the parallel-API path.

Setup-commit only: every existing consumer compiles and tests pass.
Per-package migrations land in subsequent commits; the M2 cleanup
commit deletes both the legacy and parallel APIs once the migration
chain finishes.
…nal-core base codecs

Each of the six SQL base codecs (char, varchar, int, float, text,
timestamp) gains a sibling `*Descriptor` export authored natively via
`codecDescriptor()`. The descriptor builder is wired through
`defineCodecDescriptors()` and exposed as `sqlCodecDescriptorDefinitions`
and `sqlCodecDescriptorList` (mirroring the legacy `sqlCodecDefinitions`).

Encode/decode/render functions are extracted to module-level constants
so the legacy codec form and the descriptor form share a single source
of runtime behaviour during the migration window. The legacy codec
exports stay so postgres + sqlite + sql-codecs.test.ts keep compiling;
they migrate to the descriptor exports in subsequent per-package
commits and the legacy form deletes in the M2 cleanup.

Adds an `AnyCodecDescriptor` variance-erasure alias to `codec-types.ts`
so the descriptor builder can collect heterogeneous descriptors (the
descriptor `factory` and `renderOutputType` slots are contravariant in
`P`, so heterogeneous storage cannot use `CodecDescriptor<unknown>`).
…rget codecs

Each of the 22 postgres codecs gains a sibling `*Descriptor` definition
authored via `codecDescriptor()` (or composed from a base SQL descriptor
via `aliasDescriptor`). The descriptor builder is wired through
`defineCodecDescriptors()` and exposed as `codecDescriptorDefinitions`
and `codecDescriptorList`, mirroring the existing `codecDefinitions` /
`dataTypes` shape.

The legacy `Codec` instances + `aliasCodec` helper stay so the postgres
adapter (codec-lookup.ts, runtime.ts, descriptor-meta.ts, adapter.ts)
and the postgres test suite keep reading codec instances out of
`codecDefinitions[k].codec` until the unified `codecs:` slot reshape
(later in M2). Both shapes retire to descriptor-only in the M2 cleanup
commit.
…et codecs

Each of the seven sqlite codecs (text, integer, real, blob, datetime,
json, bigint) gains a sibling `*Descriptor` authored via
`codecDescriptor()`. The descriptor builder is wired through
`defineCodecDescriptors()` and exposed as `codecDescriptorDefinitions`
and `codecDescriptorList`, mirroring the existing `codecDefinitions` /
`dataTypes` shape (and reusing the shared SQL base descriptors —
char, varchar, int, float — by reference).

The legacy `Codec` exports stay so the sqlite adapter (codec-lookup,
runtime-adapter, adapter) and the sqlite test suite keep reading
codec instances out of `codecDefinitions[k].codec` until the unified
`codecs:` slot reshape later in M2; both shapes retire to descriptor-
only in the M2 cleanup commit.
The vector codec gains a native `pgVectorDescriptor` authored via
`codecDescriptor()` in core/codecs.ts (with `paramsSchema` and
`renderOutputType` consolidated into the descriptor). The runtime
extension drops its hand-rolled descriptor literal and references
`pgVectorDescriptor` directly; the legacy `parameterizedCodecs:` slot
still echoes the descriptor through the `RuntimeParameterizedCodecDescriptor<P>`
alias for the contributor protocol.

Both the legacy `codecDefinitions[k].codec` surface and the new
`codecDescriptorList` ship through this commit; the M2 cleanup commit
collapses the parameterized + non-parameterized slots into the unified
`codecs:` slot.
wmadden added 24 commits May 9, 2026 17:48
…egistry

The previous register(codec) method on the SQL CodecRegistry interface was
used in a strict build-then-read pattern: every consumer assembled a fresh
registry once and then read from it. The mutation surface was exposed
externally but never used to overwrite or alter a live registry post-read.

Collapse the surface to a single-shot builder:

- Add buildCodecRegistry(codecs: readonly Codec<string>[]): CodecRegistry
  that returns a read-only registry built once from the input array.
- Drop register(codec) from the CodecRegistry interface; drop the
  newCodecRegistry() factory (no remaining consumers).
- Migrate the production SQL execution-context construction in
  sql-context.ts and the postgres / sqlite adapter codec-registry
  closures to assemble a Codec[] up-front and call buildCodecRegistry
  once.
- Migrate the ~25 test fixtures (sql-runtime, relational-core,
  sql-orm-client, integration) to the same up-front-array + builder
  pattern. The pattern was mechanical — repeated registry.register(codec)
  calls collapse into a single array literal passed to the builder.

No behavioural change: duplicates still raise on construction; the
returned registry exposes the same get/has/values/iterator surface.
…criptorRegistry

After Phase 1 narrowed CodecRegistry to a build-then-read map of resolved
Codec instances, audit every CodecRegistry.get(id) consumer to determine
whether the resolved-instance contract is still required:

- ExecutionContext.codecs (sql-runtime): purely a relay to encode/decode
  call sites. Migrate-able (a) — replace with direct ContractCodecRegistry
  lookup at the encode/decode call site.
- encodeParam / decodeRow registry parameter (sql-runtime): hot-path
  dispatch. Migrate-able (a) — pre-populate ContractCodecRegistry.byCodecId
  with one canonical instance per non-parameterized descriptor at registry
  build time, so forCodecId(id) covers refs-less call sites without an
  external registry parameter.
- AdapterProfile.codecs (lane core): test instrumentation only — no
  production consumers post Phase 1. Replaced by a test-only StubAdapter
  shape that exposes the codec array directly.

No surviving (c) consumers. Retire the CodecRegistry interface and the
buildCodecRegistry factory entirely:

- Drop CodecRegistry / buildCodecRegistry from
  @prisma-next/sql-relational-core/ast.
- Drop AdapterProfile.codecs() (test-only surface).
- Drop ExecutionContext.codecs (lane-core query-lane-context); call sites
  read context.contractCodecs / context.codecDescriptors instead.
- Drop the registry parameter from encodeParam / encodeParams / decodeRow /
  buildDecodeContext / resolveProjectionCodec / resolveParamCodec.
- buildContractCodecRegistry now pre-populates byCodecId with non-
  parameterized canonical instances and a parameterizedRepresentatives
  fallback for parameterized descriptors whose factory tolerates
  factory(undefined). Refs-less forCodecId(id) lookups read both maps;
  parameterized descriptors that need real params (arktype-json, pgvector)
  fall through to column-aware dispatch via forColumn(table, column).
- Postgres / SQLite adapters drop their internal codec-registry closures.
- sql-orm-client model-accessor and sql-family-adapter tests drop the
  legacy codecs lambda from their test contexts.
- Cross-family integration test exercises the codec directly rather than
  going through the SQL CodecRegistry.

Migrate ~25 test fixtures across sql-runtime / sql-orm-client /
relational-core / integration to:
- Pass the codec array directly (replaces buildCodecRegistry([...]) calls).
- Use buildTestContractCodecs(codecs) to construct a ContractCodecRegistry
  for tests that exercise encode/decode paths.
- Use descriptorsFromCodecs(codecs) to build a CodecDescriptorRegistry.

The descriptor-parity test in adapter-postgres becomes obsolete (it asserted
parity between AdapterProfile.codecs() and the descriptor list, which no
longer exists) and is deleted.

Net effect: a single codec registry — CodecDescriptorRegistry — survives.
The runtime materializes resolved Codec instances on demand through
ContractCodecRegistry, which combines column-aware dispatch (forColumn)
with descriptor-derived canonical instances (forCodecId).

Cross-package gates pass:
- grep "registry\.register" packages/ — no SQL CodecRegistry hits remain
  (only unrelated mongo / operations / pgvector op registries).
- grep "interface CodecRegistry" packages/ — 0 hits in SQL family.
- grep "buildCodecRegistry|newCodecRegistry" packages/ — 0 hits.
…rebase

- psl-column-resolution.ts: ColumnDescriptor typeParams accepts undefined to match framework-components ColumnTypeDescriptor under exactOptionalPropertyTypes.
- intercept-decoding / marker-vs-intercept-ordering tests: replace retired createCodecRegistry/codec/parameterizedCodecs surface with defineTestCodec + descriptorsFromCodecs (the post-M2 codec registration shape).
- sql-context tests: drop parameterizedCodecs and createCodecRegistry residue from new mutation-default-generator stability tests.
- target-postgres codecs.test.ts: route the new bytea cases through codecForScalar like its siblings (codecDefinitions never existed on this branch).
Codec-authored RUNTIME.DECODE_FAILED and RUNTIME.ABORTED were being
double-wrapped (or coerced) by decodeFields catch. Rethrow runtime
envelopes unchanged; only wrap foreign errors.

Closes CodeRabbit thread on decoding.ts:263.
…hrough

The pre-existing codec-async test asserted the old (regression) behaviour
where decodeField double-wrapped a codec-authored
RUNTIME.JSON_SCHEMA_VALIDATION_FAILED into RUNTIME.DECODE_FAILED. With
F40 in place, codec-authored runtime envelopes pass through unchanged,
so the assertion now pins the correct surfaced code + details directly.
descriptor.paramsSchema !== voidParamsSchema is brittle — any descriptor
that doesn't reuse the exact singleton gets misrouted. Use the
descriptor.isParameterized getter (F12) as the canonical discriminator.

Closes CodeRabbit thread on sql-context.ts:282.
The byCodecId pre-populated representative was being reused for every
forColumn(table, column) entry, so non-parameterized descriptors saw
the shared context instead of the real column site even on
column-aware dispatch. Keep the representative as the forCodecId
fallback only; materialise fresh instances for forColumn entries with
the column-bound SqlCodecInstanceContext (name: <col:table.column>,
usedAt: [{ table, column }]).

Closes CodeRabbit thread on sql-context.ts:427 (also applies to 492-512).
Vector<0> and Vector<-1> previously rendered through the guard. Tighten
to require length > 0. Fix is local to mongo adapter renderOutputType;
parallel guards (e.g. pgvector) are out of scope for this thread.

Closes CodeRabbit thread on mongo-adapter codecs.ts:124.
…ork-components README codec sketch

F44: ADR 208 future-work bullet referenced the retired `parameterized-codecs slot`
vocabulary, contradicting the same ADR a few lines up; rephrase to "unified
`codecs:` registration surface".

F45: framework-components README codec-call-context sketch had two errors:
(a) line 34 incorrectly invoked TypeScript bivariance to justify sync method
bodies satisfying `Promise<T>` return types — bivariance is parameter-position
only; reframe as "mark the method `async`, or return `Promise.resolve(...)`
explicitly"; (b) the `encode` sketch used property syntax + optional `ctx?.signal`
inconsistent with the `CodecImpl` class story — rewrite as a real class method
with required `ctx: CodecCallContext`.

Closes CodeRabbit threads on ADR 208:259 and framework-components README:34.
…factory param

CI lint flagged `_params: void` in a parameter position. `void` outside a return
type is confusing per biome (lint/suspicious/noConfusingVoidType); switch the
F42 test fixture to `undefined`. Behaviour unchanged — the factory body never
reads the param, and the cast through unknown still pins it to
`CodecDescriptor<void>["factory"]`.
Deleted the standalone phantom-property block between imports and the
Codec interface (redundant with __codecTraits inline doc; merged the
string-key-vs-symbol rationale into that line).

Reflowed framework codec surface JSDoc (codec.ts, codec-descriptor.ts,
column-spec.ts, codec-types.ts, exports/codec.ts) so paragraphs are not
manually hard-wrapped mid-sentence.

Added `.cursor/rules/jsdoc-no-artificial-line-wraps.mdc` (force-added;
`.cursor/rules` is gitignored) and indexed it in `.cursor/rules/README.md`.
…s/rules

Canonical rulecard lives under `.agents/rules/` for agent discovery; removed
duplicate from `.cursor/rules/`. Updated `.cursor/rules/README.md` index entry.
…links

- Rewrap codec-cluster retrospective blockquotes as single-line paragraphs;
  replace transient codenames with class-based CodecImpl/CodecDescriptorImpl
  wording; drop ticket IDs from note titles.
- ADR 208: rename status heading; remove Pattern E / ticket bullets; Mongo
  follow-up without Linear URL.
- ADR 204 async: framework-gaps G9/G4 instead of tracker URLs; prose-only
  Mongo decode sentence.
- ADR 207: framework-gaps G4/G1 instead of tracker URLs.
- ADR 180 implementation note: drop Linear URL (same paragraph reflow).
- docs/README + codec-authoring guide: align wording with stable terminology.
- Extend `.agents/rules/jsdoc-no-artificial-line-wraps.mdc` with ADR guidance.
…olumns

The runtime sql-context materializes a representative codec for parameterized descriptors via factory(undefined)(ctx), used as the encode/decode fallback for columns whose codec id is parameterized but whose contract entry has no typeParams (e.g. the undimensioned vectorColumn variant). PgVectorDescriptor.factory threw when params was undefined because it eagerly read params.length, leaving forCodecId('pg/vector@1') with no representative. As a result, vector arrays passed through unencoded and node-postgres formatted them as PG array literals ({"'0.1'","'0.2'"}), which Postgres rejected with "invalid input syntax for type vector".

Make PgVectorCodec accept length: number | undefined and skip the dimension check when length is undefined; tolerate factory(undefined) by reading the optional length defensively. Typed call sites (pgVectorColumn(N), vector(N)) keep their strict signature so length is still required at column construction.

Adds a regression test that asserts factory(undefined) yields a length-agnostic codec encoding/decoding the wire format correctly.
Coverage gaps reported by CI fell into two clusters:

- New / heavily rewritten files on this branch had no targeted tests yet:
  - relational-core codec-descriptor-registry (0% — fully untested)
  - relational-core sql-codecs encodeJson/decodeJson + column helpers
  - relational-core validate-param-refs unknown-codec-id branch
  - pgvector codecs paramsSchema narrow, NaN decode, encodeJson/decodeJson, pgVectorColumn helper
  - arktype-json column-author and renderOutputType edge branches
  - mongo-adapter descriptor.factory invocation, defensive introspect parsing,
    and extractDb error path

- A handful of unmodified files dropped just below threshold; covered the
  reachable branches with targeted tests rather than relaxing thresholds:
  - sql-orm-client query-plan-meta missing-profileHash branch
  - sql-orm-client query-plan-mutations: unknown table/column errors,
    UPDATE/DELETE WHERE preservation, split helpers empty-rows guard

Defensive paths in arktype-json rehydration that arktype itself cannot reach
(non-Error throws and post-rehydrate non-callable returns) are marked with
`c8 ignore` rather than synthesised through mocks.

Verified with node scripts/coverage-report.mjs (61 packages, 0 failures).
…ynamic import

The contributes-parameterized-codec-descriptors test uses await import()
on src/exports/runtime, triggering vitests first-pass transform of the
runtime module graph. On cold CI workers this can exceed the package
default of 200ms (timeouts.default x multiplier).

Apply timeouts.coldTransformImport to the test directly, matching the
pattern used elsewhere in the repo for lazy-import suites.
…ode dispatch

Three related runtime issues surfaced together when the demo exercised
parameterized codecs through the ORM (cosineDistance/lt) and via SQL
DSL self-joins:

1. forColumn dispatch trusted refs blindly. The ORM lifts the column
   ref out of an OperationExpr that changed the codec id (e.g.
   `cosineDistance(p.embedding, x).lt(1)` carries refs={post,embedding}
   but a `pg/float8@1` comparison codec). forColumn returned the
   vector codec, which then rejected the float literal.

   resolveParamCodec / resolveProjectionCodec now require byColumn.id
   to agree with the declared codec id; a mismatch falls through to
   forCodecId so the float literal dispatches as float8.

2. forColumn missed for aliased self-joins (`db.sql.post.as(p1)
   .innerJoin(db.sql.post.as(p2), …)` projects p1.id, p2.id). byColumn
   is keyed by source table; the alias never matched, fell through to
   forCodecId(sql/char@1), and threw "ambiguous parameterized
   instances".

   Builds an alias→source table map from the query AST and resolves
   refs through it before forColumn dispatch (decode and encode share
   the helper in alias-resolver.ts).

3. F42 detached factory from its descriptor: `voidFactory(undefined)
   (ctx)` lost the `this`-on-descriptor binding, so descriptors whose
   factory body captures `this` (e.g. PgTextDescriptor: `() => new
   PgTextCodec(this)`) produced codecs with `descriptor: undefined`.
   Reading `codec.id` then threw. The bug was latent until #1 above
   started inspecting `byColumn.id`.

   Both factory call sites now use `factory.bind(descriptor)`.

Updates the demo offline-runtime test expectation: ProjectionItem refs
are now populated for top-level identifier projections (a side effect
of the existing select-shortcut path that the test was written before).
The alias resolver was casting `{ kind: string }` to per-branch shapes
(`{ name, alias? }` and `{ alias }`) inside the switch, which TS rejects
under `noImplicitAny`/strict structural checks once the surrounding code
matures. Type the helper directly as `AnyFromSource` so each branch
discriminates safely without unsafe casts.

Adds a unit test covering the resolver across SELECT, self-join,
derived table, and DELETE shapes.
…d runtime

CI per-file coverage thresholds tripped on:
- src/sql-runtime.ts (functions 83% < 92%)
- src/middleware/budgets.ts (statements 88% < 90%)
- src/middleware/lints.ts (statements 64% < 90%, branches 51% < 80%)

Tightens budgets.ts so primaryTableFromAst/estimateRowsFromAst return
non-nullable types, removes a dead `if (this.verified) return` defensive
check inside verifyMarker, and folds the default no-op log into a single
shared sink. Adds tests covering:
- alias resolver -> via the new test file in the previous commit.
- lints severity overrides for every rule code, raw guardrail fallback,
  and skip-fallback configuration.
- budgets unbounded SELECT with estimate below maxRows, derived-table
  source rows lookup.
- verifyMarker MARKER_MISSING, marker-passes, MARKER_MISMATCH on profile
  hash, and startup-mode caching.
- middleware ctx surface (now() and contentHash()) on a runtime using
  the default no-op log.
Removes references to in-flight code review issue IDs (F##, M0 R#, AC-CB-#,
Phase A/B markers) and strips malformed `// ---...---` decorative comment
lines from comments and test descriptions across the codec stack. The
surrounding technical content is preserved; only the transient pointers
into project review artifacts are dropped.
@wmadden wmadden force-pushed the tml-2357-codec-registration-model-complete-the-unified branch from ebcadb5 to 60d75b8 Compare May 9, 2026 15:49
Replaces `.agents/rules/jsdoc-no-artificial-line-wraps.mdc` with
`.agents/rules/jsdoc-line-width.mdc`. Doc-comment prose now wraps at the
same `lineWidth` the biome formatter uses (currently 100, read from
`biome.jsonc`) instead of being kept as one continuous line. Markdown is
explicitly exempt and continues to defer to the
markdown-no-artificial-line-wraps skill.
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: 2

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/adrs/ADR 208 - Higher-order codecs for parameterized types.md (1)

33-56: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add isParameterized to the descriptor snippet.

The CodecDescriptor / CodecDescriptorImpl example no longer matches the implementation: isParameterized is part of the real surface, and later prose in this ADR relies on it. Omitting it here makes the decision block self-inconsistent for readers copying the shape.

As per coding guidelines, "Keep docs, READMEs, and rules up-to-date during code changes."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/architecture` docs/adrs/ADR 208 - Higher-order codecs for parameterized
types.md around lines 33 - 56, The snippet for the descriptor types is missing
the isParameterized property; update both the consumer interface
CodecDescriptor<P> and the author abstract class CodecDescriptorImpl<P> to
include a readonly isParameterized: boolean property (same name and type in both
places) so the example matches the real surface and the later prose that uses
isParameterized.
🧹 Nitpick comments (1)
docs/architecture docs/adrs/ADR 208 - Higher-order codecs for parameterized types.md (1)

243-252: ⚡ Quick win

Move the migration close-out inventory out of the ADR.

This section reads like rollout status and deleted-symbol bookkeeping rather than a durable architectural decision, so it will drift as follow-ups land. I'd keep the ADR on the steady-state shape and move the completion inventory to subsystem docs or project tracking.

Based on learnings, "ADRs in prisma/prisma-next should document architectural design decisions and the key constraints/assumptions only. Do not include implementation algorithms, emitter derivation logic, or step-by-step derivation/migration rules."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/architecture` docs/adrs/ADR 208 - Higher-order codecs for parameterized
types.md around lines 243 - 252, Remove the migration close-out inventory
paragraph headed "Status — Unified descriptor authoring" (and the detailed
bullet list referencing defineCodec, mkCodec, defineCodecGroup,
synthesizeNonParameterizedDescriptor, CodecParamsDescriptor, ParamRef.refs,
forColumn, forCodecId, arktypeJsonEmitCodec, JsonSchemaValidatorRegistry, etc.)
from the ADR and relocate that rollout/deleted-symbol bookkeeping into a
separate subsystem migration or project-tracking document; edit the ADR so it
instead contains a short, steady-state summary of the final shape (class-based
authoring, single codecs: slot, narrow runtime Codec interface, ParamRef.refs
behavior, and JSON-schema validation in decode) without the step-by-step
migration status or per-symbol deletion notes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.agents/rules/jsdoc-line-width.mdc:
- Line 20: Update the "5. **Markdown is exempt** — Do not apply this rule to
`.md` files..." sentence to remove ambiguity and fix the malformed path token;
specifically, change the phrasing in the rule header text (the line starting
with "5. **Markdown is exempt**") to explicitly list the Markdown file types
(for example: ".md files such as README.md, ADRs, PR bodies, and rulecards") and
correct the path token to two distinct directories (e.g., "ADR callouts and
narrative Markdown under docs/architecture/ and docs/adrs/ follow the Markdown
rule, not this one") so there is no confusion about scope or tokenization.

In
`@packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts`:
- Around line 73-76: The isParameterized getter currently uses object identity
(this.paramsSchema !== voidParamsSchema) which misclassifies equivalent schemas;
update the CodecDescriptor surface to use an explicit marker/property instead:
add a boolean field (e.g., isParameterizedFlag) to the descriptor and set it
when the descriptor is constructed, change get isParameterized() to return that
flag (reference symbols: isParameterized, paramsSchema, voidParamsSchema,
CodecDescriptor constructor), and update any creation sites so descriptors that
represent "no params" set the flag false; ensure codepaths that read it
(descriptorFor(codecId).isParameterized, forColumn, validateParamRefRefs) use
the new property.

---

Outside diff comments:
In `@docs/architecture` docs/adrs/ADR 208 - Higher-order codecs for parameterized
types.md:
- Around line 33-56: The snippet for the descriptor types is missing the
isParameterized property; update both the consumer interface CodecDescriptor<P>
and the author abstract class CodecDescriptorImpl<P> to include a readonly
isParameterized: boolean property (same name and type in both places) so the
example matches the real surface and the later prose that uses isParameterized.

---

Nitpick comments:
In `@docs/architecture` docs/adrs/ADR 208 - Higher-order codecs for parameterized
types.md:
- Around line 243-252: Remove the migration close-out inventory paragraph headed
"Status — Unified descriptor authoring" (and the detailed bullet list
referencing defineCodec, mkCodec, defineCodecGroup,
synthesizeNonParameterizedDescriptor, CodecParamsDescriptor, ParamRef.refs,
forColumn, forCodecId, arktypeJsonEmitCodec, JsonSchemaValidatorRegistry, etc.)
from the ADR and relocate that rollout/deleted-symbol bookkeeping into a
separate subsystem migration or project-tracking document; edit the ADR so it
instead contains a short, steady-state summary of the final shape (class-based
authoring, single codecs: slot, narrow runtime Codec interface, ParamRef.refs
behavior, and JSON-schema validation in decode) without the step-by-step
migration status or per-symbol deletion notes.
🪄 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: 959fe392-d270-44a6-a14c-064039a9fa1b

📥 Commits

Reviewing files that changed from the base of the PR and between 0e3aafc and 1c6f0bf.

📒 Files selected for processing (67)
  • .agents/rules/jsdoc-line-width.mdc
  • .cursor/rules/README.md
  • .vscode/settings.json
  • docs/README.md
  • docs/Testing Guide.md
  • docs/architecture docs/adrs/ADR 152 - Execution Plane Descriptors and Instances.md
  • docs/architecture docs/adrs/ADR 180 - Dot-path field accessor.md
  • docs/architecture docs/adrs/ADR 184 - Codec-owned value serialization.md
  • docs/architecture docs/adrs/ADR 186 - Codec-dispatched type rendering.md
  • docs/architecture docs/adrs/ADR 202 - Codec trait system.md
  • docs/architecture docs/adrs/ADR 204 - Single-Path Async Codec Runtime.md
  • docs/architecture docs/adrs/ADR 204 - Single-tier runtime.md
  • docs/architecture docs/adrs/ADR 205 - SQL cast emission is adapter policy.md
  • docs/architecture docs/adrs/ADR 207 - Codec call context per-query AbortSignal and column metadata.md
  • docs/architecture docs/adrs/ADR 208 - Higher-order codecs for parameterized types.md
  • docs/architecture docs/adrs/ADR 209 - Mongo result-shape as a structural plan field.md
  • docs/architecture docs/subsystems/2. Contract Emitter & Types.md
  • docs/reference/codec-authoring-guide.md
  • docs/reference/community-generator-migration-analysis.md
  • docs/reference/framework-gaps.md
  • docs/reference/typescript-patterns.md
  • examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
  • examples/prisma-next-demo/test/runtime.offline.integration.test.ts
  • packages/1-framework/0-foundation/contract/package.json
  • packages/1-framework/1-core/framework-components/README.md
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/1-framework/1-core/framework-components/src/exports/codec.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-types.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec.ts
  • packages/1-framework/1-core/framework-components/src/shared/column-spec.ts
  • packages/1-framework/1-core/framework-components/src/shared/framework-components.ts
  • packages/1-framework/1-core/framework-components/test/codec-call-context.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/codec-types.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/codec.test.ts
  • packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts
  • packages/1-framework/1-core/framework-components/test/control-stack.test.ts
  • packages/1-framework/2-authoring/contract/README.md
  • packages/1-framework/2-authoring/contract/src/descriptors.ts
  • packages/1-framework/2-authoring/contract/src/index.ts
  • packages/1-framework/2-authoring/contract/test/descriptors.test.ts
  • packages/1-framework/2-authoring/ids/package.json
  • packages/1-framework/2-authoring/ids/src/index.ts
  • packages/1-framework/3-tooling/cli/src/control-api/contract-enrichment.ts
  • packages/1-framework/3-tooling/cli/test/config-types.test.ts
  • packages/1-framework/3-tooling/cli/test/control-api/contract-enrichment.test.ts
  • packages/1-framework/3-tooling/emitter/src/domain-type-generation.ts
  • packages/1-framework/3-tooling/emitter/test/domain-type-generation.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/README.md
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codec-registry.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codecs.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/exports/index.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/src/derive-json-schema.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/derive-json-schema.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.polymorphism.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.test.ts
  • packages/2-mongo-family/7-runtime/README.md
  • packages/2-mongo-family/7-runtime/src/mongo-execution-stack.ts
  • packages/2-mongo-family/7-runtime/test/codecs/decoding.test.ts
  • packages/2-mongo-family/7-runtime/test/decode.integration.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-stack.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-middleware.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime-abort.test.ts
💤 Files with no reviewable changes (3)
  • packages/1-framework/2-authoring/contract/src/descriptors.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs-ctx.test.ts
✅ Files skipped from review due to trivial changes (22)
  • .vscode/settings.json
  • docs/architecture docs/adrs/ADR 204 - Single-tier runtime.md
  • .cursor/rules/README.md
  • packages/1-framework/2-authoring/contract/README.md
  • docs/architecture docs/subsystems/2. Contract Emitter & Types.md
  • docs/README.md
  • docs/reference/framework-gaps.md
  • packages/2-mongo-family/7-runtime/README.md
  • packages/1-framework/1-core/framework-components/test/codec-call-context.types.test-d.ts
  • packages/1-framework/2-authoring/ids/src/index.ts
  • docs/architecture docs/adrs/ADR 180 - Dot-path field accessor.md
  • docs/reference/community-generator-migration-analysis.md
  • packages/1-framework/3-tooling/cli/test/control-api/contract-enrichment.test.ts
  • docs/architecture docs/adrs/ADR 184 - Codec-owned value serialization.md
  • docs/architecture docs/adrs/ADR 202 - Codec trait system.md
  • docs/architecture docs/adrs/ADR 209 - Mongo result-shape as a structural plan field.md
  • docs/architecture docs/adrs/ADR 186 - Codec-dispatched type rendering.md
  • docs/architecture docs/adrs/ADR 205 - SQL cast emission is adapter policy.md
  • docs/Testing Guide.md
  • examples/prisma-next-demo/test/no-emit-typed-flow.test-d.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/README.md
  • docs/reference/codec-authoring-guide.md
🚧 Files skipped from review as they are similar to previous changes (33)
  • docs/architecture docs/adrs/ADR 152 - Execution Plane Descriptors and Instances.md
  • packages/1-framework/0-foundation/contract/package.json
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.test.ts
  • packages/2-mongo-family/7-runtime/src/mongo-execution-stack.ts
  • packages/2-mongo-family/7-runtime/test/mongo-middleware.test.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/exports/index.ts
  • packages/1-framework/3-tooling/emitter/src/domain-type-generation.ts
  • packages/1-framework/2-authoring/contract/src/index.ts
  • packages/2-mongo-family/2-authoring/contract-psl/src/derive-json-schema.ts
  • packages/1-framework/2-authoring/contract/test/descriptors.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-runtime-abort.test.ts
  • packages/1-framework/3-tooling/cli/test/config-types.test.ts
  • packages/2-mongo-family/2-authoring/contract-psl/test/interpreter.polymorphism.test.ts
  • packages/1-framework/2-authoring/ids/package.json
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test-d.ts
  • packages/1-framework/1-core/framework-components/test/codec.test.ts
  • packages/2-mongo-family/7-runtime/test/mongo-execution-stack.test.ts
  • packages/1-framework/1-core/framework-components/README.md
  • packages/2-mongo-family/2-authoring/contract-psl/test/derive-json-schema.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/test/codecs.test.ts
  • packages/1-framework/1-core/framework-components/test/codec.types.test-d.ts
  • packages/1-framework/1-core/framework-components/src/exports/codec.ts
  • packages/1-framework/1-core/framework-components/src/control/control-stack.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codec-registry.ts
  • packages/1-framework/1-core/framework-components/src/shared/framework-components.ts
  • packages/1-framework/1-core/framework-components/src/shared/column-spec.ts
  • docs/reference/typescript-patterns.md
  • packages/1-framework/1-core/framework-components/test/control-stack.test.ts
  • packages/1-framework/1-core/framework-components/test/codec-types.types.test-d.ts
  • packages/1-framework/1-core/framework-components/src/shared/codec-types.ts
  • packages/2-mongo-family/7-runtime/test/codecs/decoding.test.ts
  • packages/2-mongo-family/1-foundation/mongo-codec/src/codecs.ts

Comment thread .agents/rules/jsdoc-line-width.mdc Outdated
Comment on lines +73 to +76
/** Boolean derived from `paramsSchema`: `true` whenever the schema is not the singleton `voidParamsSchema`. The framework registry's `validateParamRefRefs` pass reads this through `descriptorFor(codecId).isParameterized` to gate column-ref enforcement. */
get isParameterized(): boolean {
return this.paramsSchema !== voidParamsSchema;
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 9, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Don't derive parameterization from schema object identity.

isParameterized currently depends on this.paramsSchema !== voidParamsSchema. That makes correct dispatch depend on every non-parameterized descriptor reusing one sentinel instance; an equivalent StandardSchemaV1<void> will be misclassified and pushed through the parameterized-only forColumn / validateParamRefRefs paths. Please make this explicit on the descriptor surface or key it off a dedicated marker instead of raw reference equality.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts`
around lines 73 - 76, The isParameterized getter currently uses object identity
(this.paramsSchema !== voidParamsSchema) which misclassifies equivalent schemas;
update the CodecDescriptor surface to use an explicit marker/property instead:
add a boolean field (e.g., isParameterizedFlag) to the descriptor and set it
when the descriptor is constructed, change get isParameterized() to return that
flag (reference symbols: isParameterized, paramsSchema, voidParamsSchema,
CodecDescriptor constructor), and update any creation sites so descriptors that
represent "no params" set the flag false; ensure codepaths that read it
(descriptorFor(codecId).isParameterized, forColumn, validateParamRefRefs) use
the new property.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Valid concern, out of scope — the identity-with-singleton check is intentional design ratified by ADR 208 and documented in the getter's docstring. The fix would touch the public CodecDescriptor surface and every codec-descriptor subclass in the codebase. Not minimal, not a regression introduced on this branch.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@wmadden, understood — I'll accept this as intentional design and won't flag it again. Adding a learning to reflect this.


✏️ Learnings added
Learnt from: wmadden
Repo: prisma/prisma-next PR: 417
File: packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts:73-76
Timestamp: 2026-05-09T16:53:21.419Z
Learning: In prisma/prisma-next, the `isParameterized` getter on `CodecDescriptorImpl` (in `packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts`) intentionally uses object-identity comparison against the singleton `voidParamsSchema` (`this.paramsSchema !== voidParamsSchema`). This is by design, ratified by ADR 208, and documented in the getter's JSDoc. All non-parameterized descriptors are required to reuse the singleton `voidParamsSchema` instance. Do not flag this pattern as unsafe object-identity comparison or suggest replacing it with an explicit boolean marker property.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: wmadden
Repo: prisma/prisma-next PR: 38
File: packages/2-sql/3-tooling/family/src/core/migrations/plan-helpers.ts:40-47
Timestamp: 2025-12-26T23:02:40.679Z
Learning: In Prisma-next's TypeScript codebase, prefer using well-established utility libraries (e.g., Lodash) rather than building custom utilities for complex object operations such as deep freezing or deep cloning. Favor reliable, battle-tested functions and ensure dependencies are reviewed for tree-shaking and bundle size. If a lightweight utility suffices, consider modern native approaches or smaller libs.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 191
File: packages/1-framework/3-tooling/cli/src/commands/contract-emit.ts:5-5
Timestamp: 2026-03-01T13:54:21.863Z
Learning: In the Prisma-next repository, prefer importing and using 'pathe' over the built-in 'node:path' module for path operations across the codebase (including CLI commands and tooling files). Apply this in TypeScript files, replacing imports from 'node:path' with 'pathe' and adjusting API usage accordingly. Ensure consistent usage across all modules and update any affected tests or tooling imports when refactoring.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 234
File: packages/2-sql/4-lanes/sql-lane/test/rich-mutation.test.ts:2-2
Timestamp: 2026-03-23T10:01:15.075Z
Learning: In the prisma/prisma-next repo, prefer using `pathe` over Node’s built-in `node:path`. For any TypeScript file (including tests, test helpers, and integration tooling) replace imports like `import { dirname, join } from 'node:path'` with `import { dirname, join } from 'pathe'`—especially when code reads files/fixtures from disk.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 294
File: packages/2-mongo-family/2-query/query-ast/src/read-plan.ts:4-10
Timestamp: 2026-04-04T10:08:34.220Z
Learning: In prisma/prisma-next, don’t flag declaration-emit/typecheck warnings/errors when a file uses an intentional nominal/branding pattern with a non-exported `declare const <brand>: unique symbol` as a computed property key on an exported interface (e.g., `readonly [__mongoReadPlanRow]: ...` / `readonly [aggregateResultBrand]: ...`). The `unique symbol` must remain unexported to prevent external forging, while the branded property key staying on the exported interface provides compile-time discrimination. If the build correctly emits declaration files for this pattern, treat it as intentional rather than a declaration-emit error.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 293
File: packages/1-framework/1-core/shared/contract/src/canonicalization.ts:203-216
Timestamp: 2026-04-04T12:19:05.250Z
Learning: In the prisma/prisma-next repository, do not treat `Array.prototype.sort` comparators as “potentially non-deterministic” solely because the comparator does not include explicit tie-breaking keys. This is because the repo’s required runtime is Node >= 24, where `Array.prototype.sort` is stable (equal elements retain their original relative order via a stable sort such as TimSort). Therefore, equal-comparing elements should remain deterministic without additional tie-break logic.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 291
File: packages/1-framework/1-core/migration/control-plane/src/emission/emit.ts:112-119
Timestamp: 2026-04-05T07:41:53.422Z
Learning: In the prisma/prisma-next codebase, the in-memory `Contract` model stores hashes only in nested locations: `contract.storage.storageHash` (and `contract.execution.executionHash`). These values are promoted to top-level fields only during canonicalization/emission via `canonicalizeContractToObject`. Therefore, runtime code that consumes in-memory `Contract` objects (e.g., sql-builder, mongo ORM, other runtime processors) must read `contract.storage.storageHash` from the nested path, not `contract.storageHash`. Do not flag runtime accesses to `contract.storage.storageHash` as requiring migration to a top-level property.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 291
File: packages/1-framework/1-core/migration/control-plane/src/emission/emit.ts:112-119
Timestamp: 2026-04-05T07:49:50.627Z
Learning: In this prisma/prisma-next codebase, the in-memory runtime `Contract` model does not have top-level `storageHash` or `executionHash` fields. Hashes live only in nested properties: `contract.storage.storageHash` and `contract.execution.executionHash`, and they are only promoted to top-level fields during canonicalization/emission via `canonicalizeContractToObject` (and thus only appear in the emitted `contract.json` artifact). When reviewing runtime code that consumes in-memory `Contract` objects (e.g., sql-builder, mongo ORM, other runtime processors), require reads from the nested paths (`contract.storage.storageHash` / `contract.execution.executionHash`). Do not flag such nested accesses as needing a migration to top-level properties.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 334
File: packages/2-mongo-family/9-family/src/core/control-instance.ts:204-228
Timestamp: 2026-04-13T15:54:52.337Z
Learning: When reviewing TypeScript code in this repo, do not assume a property is potentially `undefined` at a call site just because an arktype schema definition uses the DSL syntax `'key?': 'type'` (a quoted string key with a trailing `?`). This DSL notation is not the same as TypeScript optional properties (`key?: type`). To determine whether `key` is truly optional/undefined-capable, verify the actual exported TypeScript type declaration (e.g., `contract-types.ts`) and the runtime validation schema (e.g., `validate-contract.ts`) for that property; only then should the review flag call-site handling for potential `undefined`.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 339
File: test/integration/test/cli.init-templates.e2e.test.ts:96-96
Timestamp: 2026-04-15T19:33:48.733Z
Learning: In prisma/prisma-next, when writing tests that run TypeScript compilation (e.g., via `tsc --noEmit`), avoid hardcoded timeout numbers (such as `30_000`). Instead, use `prisma-next/test-utils` timeout helpers—specifically `timeouts.typeScriptCompilation` (implemented in `test/utils/src/timeouts.ts`) for `tsc` compilation scenarios. Use `timeouts.spinUpPpgDev` for PostgreSQL server startup and `timeouts.databaseOperation` for database operation scenarios.

Learnt from: saevarb
Repo: prisma/prisma-next PR: 394
File: packages/1-framework/3-tooling/migration/src/graph-ops.ts:50-54
Timestamp: 2026-04-29T12:44:59.376Z
Learning: In TypeScript overload implementations, an internal “implementation-only” cast (e.g., `state as unknown as <ReturnType>`) can be safe and intentional when the public overload signatures and their structural typing prevent callers from reaching the implementation with an incompatible type. In these cases, reviewers should not flag the cast as a blind/unsafe cast, since compile-time overload enforcement substitutes for a runtime type guard. Don’t require an added `typeof`/runtime check solely to silence the cast when the overload design already prevents invalid inputs.

Learnt from: wmadden
Repo: prisma/prisma-next PR: 417
File: packages/3-extensions/sql-orm-client/src/types.ts:309-318
Timestamp: 2026-05-08T17:07:07.145Z
Learning: In prisma/prisma-next code, prefer `ifDefined` from `prisma-next/utils/defined` for conditional object spreads instead of inline ternary-based spreads. For example, when building option objects for `ParamRef.of` (or similar codec/param construction), wrap optional values with `ifDefined(...)` so that the spread only includes the property when the value is defined, improving readability and avoiding “{...cond ? {a: b} : {}}”-style patterns. Ensure you import `ifDefined` from `prisma-next/utils/defined` and use it consistently for these conditional spreads.

- jsdoc-line-width.mdc: drop the redundant ADR-callout sentence; the
  Markdown-exempt list already covers ADRs and PR bodies, and the
  embedded path with a space in `architecture docs` was visually
  confusing for readers.
- ADR 208: add the missing `readonly isParameterized: boolean` field
  to both the `CodecDescriptor<P>` interface and the
  `CodecDescriptorImpl<P>` abstract-class snippet so the example
  matches the real surface in
  `framework-components/src/shared/codec-descriptor.ts`.
- ADR 208: remove the "Status — Unified descriptor authoring"
  close-out inventory section. The migration rollout and per-symbol
  deletion notes belong in the project tracker
  (`projects/codec-registration-completion/spec.md`, which already
  carries them); the steady-state design is already described in
  the ADRs Decision / How it composes / Trade-offs sections.
@wmadden wmadden merged commit 14060ca into main May 9, 2026
16 checks passed
@wmadden wmadden deleted the tml-2357-codec-registration-model-complete-the-unified branch May 9, 2026 17:03
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.

3 participants