Skip to content
Merged
Show file tree
Hide file tree
Changes from 155 commits
Commits
Show all changes
156 commits
Select commit Hold shift + click to select a range
d54d39e
project(codec-registration-completion): draft spec and plan for TML-2357
wmadden May 1, 2026
b644abd
wip(codec-registration-completion): M1 in-progress narrowing of runti…
cursoragent May 1, 2026
8db27a9
(TML-2357) M1 R1: complete narrowed-Codec migration
wmadden May 1, 2026
aac9d87
project(codec-registration-completion): apply m1 R1 plan/spec amendme…
wmadden May 1, 2026
e28d7a9
(TML-2357) M1 R2: address reviewer F1 cast cleanup
wmadden May 1, 2026
2f1f4b8
TML-2357 M2: introduce aliasDescriptor for descriptor-level aliasing
wmadden May 1, 2026
378edd2
(TML-2357) M2 setup: add codecDescriptor() and defineCodecDescriptors…
wmadden May 1, 2026
7e7d30b
(TML-2357) M2 T2.2: add native CodecDescriptor exports to sql-relatio…
wmadden May 1, 2026
5855af1
(TML-2357) M2 T2.3: add native CodecDescriptor exports to postgres ta…
wmadden May 1, 2026
f457212
(TML-2357) M2 T2.4: add native CodecDescriptor exports to sqlite targ…
wmadden May 1, 2026
2ecb714
(TML-2357) M2 T2.5: migrate pgvector to native CodecDescriptor
wmadden May 1, 2026
eca4267
(TML-2357) M2 T2.6: delete arktypeJsonEmitCodec emit-only shim
wmadden May 1, 2026
824487f
M2 Phase A: unify SQL contributor codec slot, drop synthesis bridge
wmadden May 2, 2026
f9b5c98
M2 Phase B: retire CodecParamsDescriptor + aliasCodec + scrub stale s…
wmadden May 2, 2026
332208e
extractCodecLookup reads codec metadata from descriptor list
wmadden May 2, 2026
5e92b79
codecDescriptor() materializes a narrow codec instance
wmadden May 2, 2026
c0d12cf
M2 Phase B: narrow MongoCodec + scrub framework-components README
wmadden May 2, 2026
56094c1
M2 Phase B: narrow SQL Codec to id+conversion + migrate test reads to…
wmadden May 2, 2026
7ab483f
M2 Phase B: drop the four inlined as-unknown-as Codec casts at the po…
wmadden May 2, 2026
b331e13
M2 Phase B: add T2.10 no-synthesis-bridge constructive test
wmadden May 2, 2026
dac21cd
M2 R3: rename createCodecRegistry → newCodecRegistry; drop CodecRegis…
wmadden May 2, 2026
072a178
M2 R3: rename legacy + parallel codec factories and builder property …
wmadden May 2, 2026
1ba7535
M2 R3: retire F1 LegacyCodecInstanceMeta cast and codecInstances slot
wmadden May 2, 2026
df132bd
M2 R3: scrub legacy codec-API references from docs and retire no-synt…
wmadden May 2, 2026
bb5f299
M2 R4: add narrow buildCodec helper for runtime Codec materialization
wmadden May 2, 2026
0d03b34
M2 R4: derive SQL base codec maps from descriptors; drop legacy facto…
wmadden May 2, 2026
e67ce12
M2 R4: derive postgres codec maps from descriptors; drop legacy facto…
wmadden May 2, 2026
e49333c
M2 R4: derive sqlite codec maps from descriptors; drop legacy factories
wmadden May 2, 2026
8ad46cb
M2 R4: derive pgvector codec maps from descriptor; drop legacy factories
wmadden May 2, 2026
a97e421
M2 R4: migrate arktype-json closure to buildCodec helper
wmadden May 2, 2026
eb75c5c
M2 R4: delete legacy mkCodec test suites and stale comment refs
wmadden May 2, 2026
080a017
M2 R4: migrate test fixtures from mkCodec to buildCodec
wmadden May 2, 2026
79ce2ff
M2 R4: delete legacy mkCodec / defineCodecGroup / defineCodecBundle
wmadden May 2, 2026
dfc03f4
M2 R4: cleanup doc references and ADR 207 import drift (F4)
wmadden May 2, 2026
4fb8391
M2 R4: thread typed Codec through descriptor byScalar slots
wmadden May 2, 2026
0a156dc
M2 R4: type defineCodec factory return as Codec<Id, TTraits, TWire, T…
wmadden May 2, 2026
be10755
Revert "M2 R4: type defineCodec factory return as Codec<Id, TTraits, …
wmadden May 2, 2026
ea400f7
M2 R4: narrow descriptor-derived codec result type in sqlite test
wmadden May 2, 2026
beab69b
Reapply "M2 R4: type defineCodec factory return as Codec<Id, TTraits,…
wmadden May 2, 2026
387be31
Revert "Reapply "M2 R4: type defineCodec factory return as Codec<Id, …
wmadden May 2, 2026
7514d78
Revert "M2 R4: thread typed Codec through descriptor byScalar slots"
wmadden May 2, 2026
3f0041e
M2 R4 rollback: revert chain to M2 R3 HEAD (a29e06245)
wmadden May 2, 2026
2bcd26a
Add M0 typed-codec-flow precondition spec to TML-2357
wmadden May 7, 2026
a2cff7f
docs(codec-registration-completion): lock in Strength 3 forcing funct…
wmadden May 7, 2026
64bb328
docs(codec-registration-completion): factory-defined codec types goal…
wmadden May 7, 2026
b640c3c
docs(codec-registration-completion): refine Mode C goal spec per disc…
wmadden May 7, 2026
16725e6
docs(codec-registration-completion): add Data flow section to Mode C …
wmadden May 7, 2026
6521fd9
docs(codec-registration-completion): class-based codec design spec (M…
wmadden May 7, 2026
9db4009
docs(codec-registration-completion): rewrite class-based spec around …
wmadden May 7, 2026
fe81c65
docs(codec-registration-completion): fold spike findings into class-b…
wmadden May 7, 2026
62812c1
docs(codec-registration-completion): rewrite M0 plan around Pattern E…
wmadden May 7, 2026
09c5ab6
feat(framework-components)(TML-2357): M0 Phase A T0.A.1 — class-based…
wmadden May 7, 2026
f794126
test(framework-components)(TML-2357): M0 Phase A T0.A.3 — class-based…
wmadden May 7, 2026
0d1a75f
refactor(framework-components): move ColumnTypeDescriptor from contra…
wmadden May 7, 2026
d703b39
refactor(framework-components): consolidate codec interfaces and Impl…
wmadden May 7, 2026
891eed4
refactor(framework-components,postgres): delete aliasDescriptor; repl…
wmadden May 7, 2026
3d3fb96
docs(codec-registration-completion): update plan after Phase A landin…
wmadden May 7, 2026
d80c198
feat(sql-relational-core)(TML-2357): M0 Phase B1 — class-based base c…
wmadden May 7, 2026
58abe7a
refactor(postgres)(TML-2357): M0 Phase B1 — defensive rework of legac…
wmadden May 7, 2026
b3ef2c3
feat(contract)(TML-2357): arktypeParamsSchema helper for arktype → St…
wmadden May 7, 2026
db1d9d4
refactor(sql-relational-core)(TML-2357): use arktypeParamsSchema help…
wmadden May 7, 2026
35849ad
feat(postgres)(TML-2357): M0 Phase B2 — class-based form for native P…
wmadden May 7, 2026
f8f216c
docs(codec-registration-completion)(TML-2357): align spec § Heterogen…
wmadden May 7, 2026
4f4a6eb
fix(framework-components,sql-relational-core,postgres)(TML-2357): F5 …
wmadden May 7, 2026
1486401
test(framework-components)(TML-2357): F6 — drop CodecDescriptor<unkno…
wmadden May 7, 2026
5d0a351
test(framework-components)(TML-2357): F7 — runtime tests for CodecImp…
wmadden May 7, 2026
b057a84
feat(target-sqlite)(TML-2357): M0 Phase B3 — class-based form for nat…
wmadden May 7, 2026
bab0fe3
feat(extension-pgvector)(TML-2357): M0 Phase B4 — class-based form fo…
wmadden May 7, 2026
bce137d
feat(extension-arktype-json)(TML-2357): M0 Phase B4 — class-based for…
wmadden May 7, 2026
bb32ed3
codec(postgres): swap adapter consumption to class-form descriptors (…
wmadden May 7, 2026
9908c7f
codec(sqlite): swap adapter consumption to class-form descriptors (T0…
wmadden May 7, 2026
1b62cfb
codec(extensions): swap pgvector + arktype-json contributors to class…
wmadden May 7, 2026
f570a9d
test(arktype-json): update runtime descriptor test for B5 class-form …
wmadden May 7, 2026
866db31
TML-2357 M0 R5: migrate sql-runtime tests off mkCodec to defineTestCo…
wmadden May 7, 2026
c5c35b0
TML-2357 M0 R5: migrate relational-core tests onto class-form descrip…
wmadden May 7, 2026
789fc69
TML-2357 M0 R5: migrate postgres tests onto class-form descriptors
wmadden May 7, 2026
462a00c
TML-2357 M0 R5: migrate sqlite adapter codecs test onto class-form de…
wmadden May 7, 2026
9fe0c5f
TML-2357 M0 R5: migrate pgvector tests onto class-form descriptor
wmadden May 7, 2026
11bb1d3
TML-2357 M0 R5: migrate sql-orm-client + cross-family tests off mkCodec
wmadden May 7, 2026
ee70237
TML-2357 M0 R5: delete legacy postgres codec carriers
wmadden May 7, 2026
b48a88b
TML-2357 M0 R5: delete legacy sqlite codec carriers
wmadden May 7, 2026
9dd9fd3
TML-2357 M0 R5: delete legacy pgvector codec carriers
wmadden May 7, 2026
1aa2def
TML-2357 M0 R5: delete legacy arktype-json codec carriers
wmadden May 7, 2026
e4cd5ad
TML-2357 M0 R5: delete legacy carrier types + rename ExtractDescripto…
wmadden May 7, 2026
40d09d9
TML-2357 M0 R5: refresh stale legacy-carrier comments + docs after de…
wmadden May 8, 2026
7b39af9
TML-2357 M0 R5: F4 — replace ADR 207 grounding example with class-for…
wmadden May 8, 2026
3267c15
TML-2357 M0 R5: fix DescriptorCodecTraits to read traits off the desc…
wmadden May 8, 2026
9226bcf
TML-2357 M0 R6: fix F8 — restore CodecTypes portability across consumers
wmadden May 8, 2026
ff4c67a
TML-2357 M0 R6: T0.D.1 typed-codec-flow type tests in relational-core
wmadden May 8, 2026
0a73ac0
TML-2357 M0 R6: T0.D.2 per-target descriptor flow type tests
wmadden May 8, 2026
f1221bf
TML-2357 M0 R6: T0.D.3 no-emit authoring chain demo type test (AC-CB-6)
wmadden May 8, 2026
80134ab
TML-2357 M3: T3.2 extend ParamRef + ProjectionItem AST with refs
wmadden May 8, 2026
138f074
TML-2357 M3: T3.3 add validateParamRefRefs builder-pipeline pass
wmadden May 8, 2026
6481ed2
TML-2357 M3: T3.4 populate refs at every column-bound ParamRef site
wmadden May 8, 2026
73cfddb
TML-2357 M3: T3.5 encode-side dispatch via forColumn + run validator …
wmadden May 8, 2026
ea242ba
TML-2357 M4: delete JsonSchemaValidatorRegistry and retire `json-vali…
wmadden May 8, 2026
bb63791
TML-2357 close-out: align long-lived docs with post-migration state
wmadden May 8, 2026
87628b0
TML-2357 close-out: strip project-internal phase markers from code co…
wmadden May 8, 2026
162f1ae
TML-2357 close-out: delete projects/codec-registration-completion/
wmadden May 8, 2026
0509138
Restore projects/codec-registration-completion/ tracked files
wmadden May 8, 2026
c0847b1
TML-2357 close-out: cross-reference TML-2402 / TML-2403 follow-ups
wmadden May 8, 2026
220a6d3
F9 prep: export buildCodecDescriptorRegistry from relational-core
wmadden May 8, 2026
643f51a
F10: drop Class suffix from descriptor instance names
wmadden May 8, 2026
6f13bf1
F9+F10 (target-postgres): expose postgresCodecRegistry as the public …
wmadden May 8, 2026
a20b063
F9+F10 (target-sqlite): expose sqliteCodecRegistry as the public cons…
wmadden May 8, 2026
5903a7b
F9+F10 (extension-pgvector): expose pgvectorCodecRegistry as the publ…
wmadden May 8, 2026
e29a0ac
F9+F10 (extension-arktype-json): expose arktypeJsonCodecRegistry as t…
wmadden May 8, 2026
5afe73e
F10 (target-postgres): rename core/codecs-class.ts → core/codecs.ts a…
wmadden May 8, 2026
6ae3eb7
F10 (target-sqlite): rename core/codecs-class.ts → core/codecs.ts and…
wmadden May 8, 2026
9aab458
F10 (extension-pgvector): rename core/codecs-class.ts → core/codecs.t…
wmadden May 8, 2026
f3a6118
F10 (extension-arktype-json): align imports + test filenames after co…
wmadden May 8, 2026
46b4b3c
F10: scrub class-form / class-based vocabulary in shared layers and docs
wmadden May 8, 2026
92aa8c2
F10 (sql-orm-client tests): scrub residual class-form vocabulary in c…
wmadden May 8, 2026
70585b9
F11: rename ast/sql-codecs-class.ts to ast/sql-codecs.ts (helper-modu…
wmadden May 8, 2026
d665afa
F13+F14+F20: tighten arktype params schemas, retire arktypeParamsSche…
wmadden May 8, 2026
8a16cea
F12: move isParameterized to descriptor; retire IsParameterizedCodecI…
wmadden May 8, 2026
410fc4d
F15: replace unique symbol phantom branding with string-key phantom
wmadden May 8, 2026
be9eeab
F16: rewrite codec-authoring-guide alias section to match real pattern
wmadden May 8, 2026
6c2d4cc
F17: fix self-referential JSDoc helper-source reference
wmadden May 8, 2026
ce51930
F18: assert leaf scalar type in no-emit-typed-flow test
wmadden May 8, 2026
9ffbb54
F19+F31+F32+F33: harden extractCodecLookup; lift inline imports
wmadden May 8, 2026
88c6071
F21: stable codec registry in createStubAdapter
wmadden May 8, 2026
c8d26dd
F22+F26+F29: dispatch correctness for column-aware encode/decode
wmadden May 8, 2026
ad7a977
F23+F24+F25: tighten arktype-json schema rehydration + test hygiene
wmadden May 8, 2026
2c1f7d0
F28: throw on duplicate codecId in buildCodecDescriptorRegistry
wmadden May 8, 2026
08297bb
F30: move codecDescriptorMap into core; keep Resolve materialisation …
wmadden May 8, 2026
aef593e
F19 refinement: try empty params for parameterized representatives
wmadden May 8, 2026
498f9b6
F34+F35+F36: tighten postgres codec-helper input validation
wmadden May 8, 2026
a975473
F37: reject Invalid Date in SqliteDatetimeCodec decode/decodeJson
wmadden May 8, 2026
9f9d8e4
F39: tighten enumParamsSchema and EnumParams to string[]
wmadden May 8, 2026
ae581e5
F27 phase 1 — retire CodecRegistry.register() in favor of buildCodecR…
wmadden May 8, 2026
956bd0b
F27 phase 2 — retire CodecRegistry interface; consolidate to CodecDes…
wmadden May 8, 2026
31a21f8
chore: align main-introduced surfaces with codec consolidation after …
wmadden May 9, 2026
a96d9a4
F40: pass through runtime envelopes in decodeField
wmadden May 9, 2026
6cde7ed
F40 follow-up: update inline-validation test to expect envelope passt…
wmadden May 9, 2026
9535730
F41: partition descriptors by isParameterized, not paramsSchema identity
wmadden May 9, 2026
ad5ee28
F42: materialise per-column codec instances for forColumn dispatch
wmadden May 9, 2026
a35ff69
F43: reject non-positive vector lengths in mongo renderOutputType
wmadden May 9, 2026
e6a4c2f
F44+F45: doc fixes — ADR 208 future-work bullet vocabulary and framew…
wmadden May 9, 2026
2d84863
fix(sql-runtime test): biome noConfusingVoidType — use undefined for …
wmadden May 9, 2026
3d3f7da
docs(codec): remove orphaned JSDoc; reflow prose without ~80-col wraps
wmadden May 9, 2026
9da620e
chore(agents): move jsdoc line-wrap rule from .cursor/rules to .agent…
wmadden May 9, 2026
22f876f
docs: reflow JSDoc and wrapped line comments (TML-2357 branch)
wmadden May 9, 2026
0c9caee
docs(adrs): reflow retrospective callouts; drop Pattern E and Linear …
wmadden May 9, 2026
9ba07cd
docs: reflow markdown without artificial line wraps
wmadden May 9, 2026
33d13e7
fix(postgres): satisfy noApproximativeNumericConstant in codec tests
wmadden May 9, 2026
0708147
fix(pgvector): tolerate factory(undefined) for undimensioned vector c…
wmadden May 9, 2026
4c4e65e
test(coverage): close per-file threshold gaps surfaced by CI
wmadden May 9, 2026
f304177
test(postgres-adapter): use coldTransformImport timeout for runtime d…
wmadden May 9, 2026
3862677
fix(sql-runtime): resolve aliases and codec-id mismatch in encode/dec…
wmadden May 9, 2026
60a7eb6
Add arktype to dictionary
wmadden May 9, 2026
1a67979
fix(sql-runtime): type alias resolver against AnyFromSource
wmadden May 9, 2026
52be0fa
test(sql-runtime): close per-file coverage gaps in budgets, lints, an…
wmadden May 9, 2026
60d75b8
chore: drop transient project review IDs and decorative comment lines
wmadden May 9, 2026
1c6f0bf
docs(rules): wrap JSDoc prose at the biome line width
wmadden May 9, 2026
d60ab77
docs: address review nits on jsdoc rule and ADR 208
wmadden May 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .agents/rules/jsdoc-line-width.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
description: Wrap JSDoc / block-comment prose at the same line width as the biome formatter (currently 100). Markdown is exempt — see the markdown-no-artificial-line-wraps skill.
alwaysApply: false
---

# JSDoc / block-comment prose — wrap at the biome line width

When adding or editing **prose** in `/** ... */` or long `//` documentation:

1. **Wrap at biome's `lineWidth`** — Wrap prose at the line width configured in `biome.jsonc` (`formatter.lineWidth`, currently **100**). Source of truth: read `biome.jsonc` rather than hard-coding the number; if it changes, this rule changes with it.

2. **No fixed-column wraps below the biome width** — Do not break mid-sentence to stay under ~72 or ~80 characters. Editors soft-wrap; arbitrary narrow wraps make diffs noisy and conflict-prone.

3. **Bullet lists and tagged blocks**
- **Bullets** (`*` / `-`): keep each bullet's prose on one line up to the biome width before wrapping; wrap continuation lines aligned with the bullet text.
- **Tagged blocks** (`@param`, `@returns`, `@example`): follow normal JSDoc conventions; the same line-width rule applies to the sentence text.

4. **Orphaned blocks** — A doc comment must document the declaration that immediately follows it (after optional blank lines only before `import` / file headers). Do not leave a standalone `/** ... */` between imports and the next export with no attached symbol; merge into the relevant declaration's doc or delete redundancy.

5. **Markdown is exempt** — Do not apply this rule to `.md` files (READMEs, ADRs, PR bodies, rulecards). Markdown prose stays on one continuous line per paragraph; see `.agents/skills/markdown-no-artificial-line-wraps/SKILL.md`. ADR callouts and narrative Markdown under `docs/architecture docs/adrs/` follow the Markdown rule, not this one.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

6. **Rationale** — Wrapping at the same width that the formatter uses keeps doc-comment prose visually consistent with surrounding code, avoids both "one giant line" and "narrow 1990s terminal" extremes, and produces stable diffs because the wrap width is anchored to the formatter rather than picked per-author.

Related: `.agents/skills/markdown-no-artificial-line-wraps/SKILL.md` (Markdown files).
1 change: 1 addition & 0 deletions .cursor/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Thresholds are defined in `.cursor/rules-footprint.config.json`.

## TypeScript & Typing
- `.cursor/rules/typescript-patterns.mdc` — TS patterns index (short)
- `.agents/rules/jsdoc-no-artificial-line-wraps.mdc` — JSDoc prose: no manual ~80-column wraps; avoid orphaned doc blocks
- `.cursor/rules/generic-parameters.mdc` — Generic parameter defaults
- `.cursor/rules/interface-factory-pattern.mdc` — Interface-based design + factories
- `.cursor/rules/type-predicates.mdc` — Replace blind casts with type predicates
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"cSpell.words": ["codegen", "Lowerer", "pgvector"],
"cSpell.words": ["arktype", "codegen", "Lowerer", "pgvector"],
"editor.defaultFormatter": "biomejs.biome",
"typescript.tsdk": "node_modules/typescript/lib",
"[typescript]": {
Expand Down
1 change: 1 addition & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ This directory contains the primary documentation for the repository.
- [Glossary](./glossary.md) — user-facing terminology (source of truth for naming)
- [Commands](./commands/README.md) — command docs and entry points
- [Reference docs](./reference/) — conventions and patterns used across the codebase
- [Codec authoring guide](./reference/codec-authoring-guide.md) — class-based codecs (`CodecImpl`, `CodecDescriptorImpl`) and column helpers
- [CLI Style Guide](./CLI%20Style%20Guide.md) — CLI UX conventions

## Working with AI agents
Expand Down
11 changes: 3 additions & 8 deletions docs/Testing Guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ function createStubAdapter(): Adapter<SelectAst, SqlContract<SqlStorage>, Lowere
target: 'postgres',
targetFamily: 'sql',
capabilities: {},
codecs: createCodecRegistry(),
codecs: emptyCodecRegistry(),
},
lower: () => ({ sql: '', params: [] }),
};
Expand Down Expand Up @@ -330,10 +330,7 @@ Low-level helper tests (for IR builders, planners, CLI glue, etc.) should prove

### File Organization

**Unit tests:** `src/**/*.test.ts` (alongside source code)
**Integration tests:** `test/**/*.integration.test.ts` or `src/**/*.integration.test.ts`
**Type tests:** `src/**/*.test-d.ts` (type-level tests using `expectTypeOf`)
**E2E tests:** `test/e2e/framework/test/**/*.test.ts`
**Unit tests:** `src/**/*.test.ts` (alongside source code) **Integration tests:** `test/**/*.integration.test.ts` or `src/**/*.integration.test.ts` **Type tests:** `src/**/*.test-d.ts` (type-level tests using `expectTypeOf`) **E2E tests:** `test/e2e/framework/test/**/*.test.ts`

### Test File Structure

Expand Down Expand Up @@ -969,9 +966,7 @@ it('reads user', async () => {

### 6. Use Appropriate Test Level

**Unit test:** Test a single function in isolation
**Integration test:** Test multiple components working together
**E2E test:** Test complete execution path to database and back
**Unit test:** Test a single function in isolation **Integration test:** Test multiple components working together **E2E test:** Test complete execution path to database and back

**When in doubt:** Start with a unit test. If you need to test interactions, create an integration test. If you need to test the complete flow, create an E2E test.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,8 @@ The SQL family extends base execution-plane descriptors with `SqlStaticContribut

```ts
interface SqlStaticContributions {
codecs(): CodecRegistry
codecs(): ReadonlyArray<CodecDescriptor>
operationSignatures(): ReadonlyArray<SqlOperationSignature>
parameterizedCodecs(): ReadonlyArray<RuntimeParameterizedCodecDescriptor>
}
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ADR 180 — Dot-path field accessor

> **Implementation update (Mongo query builder unification).** The consolidated `FieldAccessor` shipped in `@prisma-next/mongo-query-builder` replaced the earlier `FieldProxy` and `FilterProxy` types — filter and update operators now hang off a single accessor, used by both read callbacks (`match`, `addFields`, `project`, `group`) and write callbacks (`updateMany`, `findOneAndUpdate`, etc.). Type-safe dot-path validation for the callable form `f("address.city")` was implemented in [TML-2281](https://linear.app/prisma-company/issue/TML-2281): a second generic `N extends NestedDocShape` threads the contract's model + value-object structure through the pipeline, paths are constrained by `ValidPaths<N>`, the resolved leaf's codec drives the returned `Expression`, and non-leaf paths surface a reduced `ObjectExpression` operator surface. Additive pipeline stages preserve `N`; replacement stages (`project`, `group`, `replaceRoot`, …) reset it, disabling the callable form downstream. For paths that are intentionally outside the typed model (canonically, migration authoring where a backfill writes a field that is not yet in the contract), `f.rawPath("path")` is the sanctioned escape hatch — it returns a `LeafExpression<DocField>` with the verbatim path and the full leaf operator surface. The method is named `rawPath` rather than `raw` so the escape hatch does not shadow a legitimate top-level `raw` field on a user model (the callable fallback `f("raw")` is disabled downstream of replacement stages, which would otherwise leave such a field inaccessible).
> **Implementation update (Mongo query builder unification).** The consolidated `FieldAccessor` shipped in `@prisma-next/mongo-query-builder` replaced the earlier `FieldProxy` and `FilterProxy` types — filter and update operators now hang off a single accessor, used by both read callbacks (`match`, `addFields`, `project`, `group`) and write callbacks (`updateMany`, `findOneAndUpdate`, etc.). Type-safe dot-path validation for the callable form `f("address.city")` added a second generic `N extends NestedDocShape` that threads the contract's model + value-object structure through the pipeline, constrains paths by `ValidPaths<N>`, drives the returned `Expression` from the resolved leaf's codec, and surfaces a reduced `ObjectExpression` operator surface for non-leaf paths. Additive pipeline stages preserve `N`; replacement stages (`project`, `group`, `replaceRoot`, …) reset it, disabling the callable form downstream. For paths that are intentionally outside the typed model (canonically, migration authoring where a backfill writes a field that is not yet in the contract), `f.rawPath("path")` is the sanctioned escape hatch — it returns a `LeafExpression<DocField>` with the verbatim path and the full leaf operator surface. The method is named `rawPath` rather than `raw` so the escape hatch does not shadow a legitimate top-level `raw` field on a user model (the callable fallback `f("raw")` is disabled downstream of replacement stages, which would otherwise leave such a field inaccessible).

## At a glance

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# ADR 184 — Codec-owned value serialization

> **Retrospective note.** This ADR's examples use the `defineCodec({...})` factory. That factory was the canonical codec-author surface at the time; it was later retired in favor of class-based authoring: concrete codecs extend `CodecImpl`, descriptors extend `CodecDescriptorImpl`, and per-codec column helpers tie helpers to descriptors with `satisfies`. The ADR's *decision* — that codecs own both wire and JSON-safe representations through `encode` / `decode` + `encodeJson` / `decodeJson` — is unchanged; only the authoring shape has moved on. See [ADR 208 — Higher-order codecs for parameterized types](ADR%20208%20-%20Higher-order%20codecs%20for%20parameterized%20types.md) and the [Codec authoring guide](../../reference/codec-authoring-guide.md) for the current shape.

## At a glance

A column with `codecId: "pg/timestamptz@1"` has a default value of `new Date('2024-01-15')` — a JavaScript `Date`. This value has to survive a round-trip through `contract.json`, but `Date` has no JSON representation. The codec handles it:

```ts
const pgTimestamptzCodec = codec({
const pgTimestamptzCodec = defineCodec({
typeId: 'pg/timestamptz@1',
targetTypes: ['timestamptz'],
traits: ['equality', 'order'],
Expand Down Expand Up @@ -42,7 +44,7 @@ The resulting contract JSON is plain — no tags, no wrappers:

The consumer reads `"2024-01-15T00:00:00.000Z"`, looks up `pg/timestamptz@1`, calls `decodeJson(...)`, gets a `Date` object.

Every codec has `encodeJson` and `decodeJson`. For JSON-safe types (strings, numbers, booleans, null), they are identity functions — the `codec()` factory provides these defaults. Only codecs for types that JSON can't represent (`Date`, binary data, etc.) override them.
Every codec has `encodeJson` and `decodeJson`. For JSON-safe types (strings, numbers, booleans, null), they are identity functions — the `defineCodec()` factory provides these defaults. Only codecs for types that JSON can't represent (`Date`, binary data, etc.) override them.
Comment thread
wmadden marked this conversation as resolved.

The same typed value crosses other boundaries too. The migration planner renders it into DDL (`DEFAULT '2024-01-15T00:00:00.000Z'`). The PSL printer renders it into schema source (`@default("2024-01-15T00:00:00.000Z")`). Migration operations carry it in `ops.json`. These are the same problem for different media, but they live at different layers:

Expand Down Expand Up @@ -119,7 +121,7 @@ Both SQL and Mongo families define structurally identical codec interfaces (`Cod

`encodeJson` and `decodeJson` are required on the `Codec` interface, not optional. Any type that can appear in the contract may need a literal value serialized for it (column defaults, discriminator values, type parameters, migration temporary defaults). Making the methods required eliminates null checks at every dispatch site.

For JSON-safe types (strings, numbers, booleans, null), the methods are identity functions. The `codec()` factory provides these defaults when not explicitly supplied, so codecs for JSON-safe types need no additional boilerplate.
For JSON-safe types (strings, numbers, booleans, null), the methods are identity functions. The `defineCodec()` factory provides these defaults when not explicitly supplied, so codecs for JSON-safe types need no additional boilerplate.

### Contract loading integrates decoding

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ADR 186 — Codec-dispatched type rendering

> **Retrospective note.** This ADR introduced the `renderOutputType` slot on the codec record (and shows `defineCodec({...})` examples). Both the codec authoring shape and the home of `renderOutputType` have since moved on: [ADR 208](ADR%20208%20-%20Higher-order%20codecs%20for%20parameterized%20types.md) relocated `renderOutputType` to the unified `CodecDescriptor`, and the `defineCodec({...})` factory was retired in favor of class-based descriptors (`CodecDescriptorImpl`) and codecs (`CodecImpl`). The decision this ADR records — that the codec is the dispatch authority for type rendering — is unchanged; only the slot's home and the authoring syntax have moved. See [Codec authoring guide](../../reference/codec-authoring-guide.md).

## At a glance

A `vector(1536)` column should produce `Vector<1536>` as its output type. A `jsonb(schema)` column should produce `{ name: string }`. Today, resolving a field's output type requires dispatching through `CodecTypes[codecId]['output']` or `parameterizedOutput` — a hoop that varies depending on whether the codec is parameterized. After this change, every field's output type is resolved once and stamped into a dedicated map in `contract.d.ts`:
Expand Down Expand Up @@ -124,7 +126,7 @@ Non-parameterized codecs don't need to implement it. The common case is zero cod
Here's what the JSONB codec looks like with `renderOutputType`:

```ts
const pgJsonbCodec = codec({
const pgJsonbCodec = defineCodec({
typeId: 'pg/jsonb@1',
targetTypes: ['jsonb'],
encode: (value): string => JSON.stringify(value),
Expand Down Expand Up @@ -210,7 +212,7 @@ Rejected because phantom types are gross, and mixing type-only metadata into the

### Make `renderOutputType` required with a default

Like `encodeJson`/`decodeJson` on [ADR 184](ADR%20184%20-%20Codec-owned%20value%20serialization.md), make it required with a default provided by the `codec()` factory.
Like `encodeJson`/`decodeJson` on [ADR 184](ADR%20184%20-%20Codec-owned%20value%20serialization.md), make it required with a default provided by the `defineCodec()` factory.

Deferred. Most codecs don't parameterize their output type — the default (`CodecTypes[codecId]['output']`) handles them. Optional with a well-defined fallback is cleaner for now.

Expand Down
12 changes: 7 additions & 5 deletions docs/architecture docs/adrs/ADR 202 - Codec trait system.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ADR 202 — Codec trait system

> **Retrospective note.** This ADR's examples show codec definitions via `defineCodec({...})`. That factory was retired in favor of class-based descriptors (`CodecDescriptorImpl`); traits are now declared as `override readonly traits = [...] as const` on the descriptor class. The `'json-validator'` trait this ADR introduced was also retired — JSON-Schema validation now lives uniformly inside the resolved codec's `decode` body rather than behind a parallel `JsonSchemaValidatorRegistry`. The trait system itself, the operator-gating semantics, and the canonical traits set are all unchanged. See [ADR 208](ADR%20208%20-%20Higher-order%20codecs%20for%20parameterized%20types.md) and the [Codec authoring guide](../../reference/codec-authoring-guide.md).

## Context

Data types in the system are identified by codec IDs (e.g., `pg/int4@1`, `pg/text@1`, `pg/vector@1`). Query surfaces need to know which operators and functions are valid for a given data type — for example, ordering a `jsonb` column with `lt` or applying `sum` to a `text` column are not meaningful SQL. Today there is no generic mechanism to express these semantic constraints.
Expand Down Expand Up @@ -63,7 +65,7 @@ Traits are declared at codec registration time. Core SQL codecs and adapter code

```ts
// sql-codecs.ts
const sqlIntCodec = codec({
const sqlIntCodec = defineCodec({
typeId: SQL_INT_CODEC_ID,
targetTypes: ['int'],
traits: ['equality', 'order', 'numeric'],
Expand All @@ -74,23 +76,23 @@ const sqlIntCodec = codec({

```ts
// postgres adapter codecs
const pgTextCodec = codec({
const pgTextCodec = defineCodec({
typeId: 'pg/text@1',
targetTypes: ['text'],
traits: ['equality', 'order', 'textual'],
encode: (value) => value,
decode: (wire) => wire,
});

const pgBoolCodec = codec({
const pgBoolCodec = defineCodec({
typeId: 'pg/bool@1',
targetTypes: ['bool'],
traits: ['equality', 'boolean'],
encode: (value) => value,
decode: (wire) => wire,
});

const pgJsonbCodec = codec({
const pgJsonbCodec = defineCodec({
typeId: 'pg/jsonb@1',
targetTypes: ['jsonb'],
traits: ['equality'], // equality only; not order-comparable
Expand All @@ -103,7 +105,7 @@ Extension codecs declare traits the same way:

```ts
// pgvector codec — vectors have equality but are not order-comparable or numeric
const pgVectorCodec = codec({
const pgVectorCodec = defineCodec({
typeId: 'pg/vector@1',
targetTypes: ['vector'],
traits: ['equality'],
Expand Down
Loading
Loading