| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
TML-3060: plan 4-stage lossless codec JSON migration (#1013) ## Linked issue Refs [TML-3060](https://linear.app/prisma-company/issue/TML-3060/plan-codec-json-projections) ## At a glance ```text TML-3062 SQL JSON projection AST foundations ↓ TML-3061 Target codec descriptor foundations ↓ TML-3063 Lossless JSON projection hard cut ↓ TML-3064 Aggregate codec typing and extension testkits ``` This is the committed delivery shape in [`projects/codec-json-projections/plan.md`](projects/codec-json-projections/plan.md); no runtime behavior changes in this PR. ## Decision This PR promotes the PostgreSQL numeric precision investigation into a tracked four-slice project. It commits the complete evidence, the settled target-owned projection architecture, a system-level Definition of Done, the stacked handoff contracts, and an exact compressed copy of the prototype without adopting that prototype's hardcoded renderer design. ## Summary Database-produced JSON can narrow arbitrary-precision values before a codec sees them, so the original local decoder/renderer fix is not a safe boundary. These artifacts make the broader lossless codec JSON migration reviewable and executable without relying on transient conversation or worktree state. ## Reviewer notes - The historical checkpoint intentionally preserves contemporaneous references to its original branch, `wip/` location, and uncommitted files. Current state lives in the README, design notes, spec, plan, trace, and TML-3060. - [`postgres-numeric-prototype.patch.gz`](projects/codec-json-projections/assets/postgres-numeric-prototype.patch.gz) is evidence only. Its decompressed SHA-256 is `0ed2afae20a3824dad79ebbf27f9dace730b5d729a626a4888414a98be4e3e7a`; the hardcoded `PG_NUMERIC_CODEC_ID` branch and lineage inference are explicitly rejected. - The plan is serial by dependency, not scheduling preference: each slice establishes the semantic/type boundary consumed by the next. - The named local stash is only an operator convenience. The tracked compressed patch and hash are the portable evidence. ## How it fits together 1. **Preserve the failure evidence.** The checkpoint records PostgreSQL precision loss and SQLite JSON probes; the compressed patch retains the exact five-file experiment independently of the active source tree. 2. **Set the semantic boundary.** Codecs choose canonical lossless JSON, target-neutral planning marks codec/native/document intent, and target descriptor specializations own AST-to-AST SQL projection. 3. **Carry authoritative output identity.** `ProjectionItem.codec` becomes the projected-value codec fact rather than asking adapters to reconstruct column lineage. 4. **Cover arrays, aggregates, and extensions.** The design includes PostgreSQL element lifting, SQLite document retagging, a separate aggregate descriptor registry, emitted `aggregateTypes`, and dev-only target testkits. 5. **Deliver through stable handoffs.** AST foundations land first, then target descriptor foundations, then the JSON hard cut, then aggregate typing/testkits and migration surfaces. ## What lands in this PR | Commit | What it adds | |---|---| | `TML-3060: plan lossless codec JSON projections` | Project entry point, full checkpoint, synthesized design notes, system spec, four-slice plan, Drive trace, evidence manifest, and exact compressed prototype patch. | The project-specific completion bar is captured in [`spec.md`](projects/codec-json-projections/spec.md), and the current approved sequencing is in [`plan.md`](projects/codec-json-projections/plan.md). ## Behavior changes & evidence - **No executable behavior changes.** The committed range adds only [`projects/codec-json-projections/**`](projects/codec-json-projections/README.md); package source, active tests, generated contracts, and configuration are unchanged. - **The design becomes a durable repository contract.** [`design-notes.md`](projects/codec-json-projections/design-notes.md) records the selected model and rejected alternatives, while [`spec.md`](projects/codec-json-projections/spec.md) fixes the project boundary, transition constraints, contract/adapter impact, and Definition of Done. - **The prototype becomes independently verifiable evidence.** [`assets/README.md`](projects/codec-json-projections/assets/README.md) records decompression and integrity details, while the archive keeps rejected implementation code out of the active tree. - **Implementation becomes an explicit stacked sequence.** [`plan.md`](projects/codec-json-projections/plan.md) names each slice's outcome, dependency, handoff, scope boundary, and PR base. ## Compatibility / migration / risk This planning PR has no runtime or API compatibility impact. The planned project intentionally keeps existing codec IDs while changing canonical JSON and some application result types; regenerated contracts, bigint/decimal aggregate migrations, extension updates, documentation, and upgrade instructions are mandatory later-slice deliverables rather than changes hidden in this PR. ## Testing performed - `git diff --cached --check` - `gzip -t projects/codec-json-projections/assets/postgres-numeric-prototype.patch.gz` - `gzip -dc projects/codec-json-projections/assets/postgres-numeric-prototype.patch.gz | shasum -a 256` → `0ed2afae20a3824dad79ebbf27f9dace730b5d729a626a4888414a98be4e3e7a` - Drive trace emitter schema validation for `project-started`, `spec-authored`, `spec-amended`, `plan-authored`, and `plan-amended` - No runtime suites — documentation, planning, trace, and inert evidence only ## Skill update n/a — planning artifacts only; no user-facing CLI, public TypeScript API, configuration, error code, or glossary surface changes in this PR. ## Follow-ups - [TML-3062](https://linear.app/prisma-company/issue/TML-3062/sql-json-projection-ast-foundations) opens as the first stacked implementation PR. - TML-3061, TML-3063, and TML-3064 follow in the order recorded above. ## Alternatives considered - **Commit the prototype as the fix.** Rejected because its codec-ID branch and recursive lineage inference put open-world codec semantics in the renderer. - **Keep the design only in `wip/` or conversation.** Rejected because implementation, review, and later context compaction need a tracked source of truth. - **Collapse everything into one implementation PR.** Rejected because AST vocabulary, target descriptor ownership, codec behavior, and aggregate typing are distinct review boundaries with real handoff dependencies. - **Parallelize the four slices.** Rejected because each downstream slice consumes types and invariants introduced by its predecessor and would otherwise require coupled merges or temporary duplicate APIs. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated (n/a — doc/planning-only PR with no behavioral delta). - [x] The PR title is in `TML-NNNN: <sentence-case title>` form. - [x] The **Skill update** section above is filled in. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net> | 2 个月前 | |
feat: an application depends on one Prisma package (ADR 242) (#29864) ## What changes for someone using Prisma Today, an application that talks to Postgres installs a long list of our packages: ```jsonc { "dependencies": { "@prisma-next/postgres": "...", "@prisma-next/sql-runtime": "...", "@prisma-next/sql-orm-client": "...", "@prisma-next/target-postgres": "...", "@prisma-next/adapter-postgres": "...", "@prisma-next/sql-contract": "..." // ...a dozen more } } ``` After this PR, it installs one: ```jsonc { "dependencies": { "@prisma/orm-postgres": "0.16.0" } } ``` Everything else arrives as that package's own dependencies. Three of our example apps are converted in this PR to prove it — one per database — and each has exactly one Prisma package in its `dependencies`. This implements [ADR 242](https://github.com/prisma/prisma/pull/29852), which is already merged. ## What gets published 17 packages, all under the `@prisma` scope: - **3 database packages** — `@prisma/orm-postgres`, `orm-sqlite`, `orm-mongo`. An application installs exactly one. We call these *facades*: each is a small package that wires its database together and re-exports everything an application needs. - **6 extension packs** — PostGIS, pgvector, ParadeDB, Supabase, arktype-json, middleware-cache. Optional, installed alongside a database package. - **7 platform packages** — the framework, the toolchain, one per database family, one per database target. Applications never install these directly; they arrive as dependencies. Extension authors do install them. - **the `prisma` command**, as a bin-only package. Every other workspace package — around 50 of them — stops being published. They still exist in the repo as the unit we organise code in; they just stop having a life on the registry. **This PR does not make that switch yet.** It builds and proves the new surface while leaving today's publish list exactly as it is. Flipping it is a separate change. ## The problem this design has to avoid A published package can't depend on packages that won't exist on the registry. So each published package *contains a compiled copy* of the internal packages it covers. That creates a trap. If one application ends up with the same code twice — once inside a published package, once as its own package — then classes, registries, and anything compared by reference exist twice too. An `instanceof` check quietly returns false. Nothing crashes, nothing fails to compile, and both copies behave identically in isolation. You find out much later, somewhere unrelated. So the rule the whole design follows is: **every piece of internal code is published from exactly one package.** Concretely, that means: - Each published package is built in one pass, so code shared between its own entry points exists once. Verified from the build's source maps: no module appears in more than one chunk, in any published package. - When one published package needs code from another, it imports it as a real dependency rather than compiling in a second copy. - A facade re-exports from the platform packages; it never carries its own copy. `@prisma/orm-postgres/orm-client` and `@prisma/orm-family-sql/orm-client` are two names for the same object, and there's a test that asserts exactly that from installed tarballs. - One table in `packages/0-shared/publish-surface` maps every internal package to where it's published. The build, the code generator, and the lint checks all read it, so there's one answer to "where does this live" rather than three that can drift. ## Generated code follows the application Prisma writes imports into your project — contract types and migration files. Those imports have to name packages your project actually depends on, or they won't resolve. So the generator now reads the `package.json` next to the config it's generating for. A project that depends on `@prisma/orm-postgres` gets imports from that package. A project on today's names keeps today's names. Nothing to configure, because the manifest already says which it is. Contract hashes are unaffected, and that isn't an assumption — hashes are computed from a structure that import text never enters, and there's a test asserting the hash is identical across naming schemes *while* the emitted imports demonstrably differ. ## What stops the trap coming back Two checks, because the failure is silent and won't show up in a test suite: - Every example app and test project must use one naming scheme, not a mix. `lint-single-import-root` scans them and fails the build if any project imports from both, since that's the situation that loads code twice. - `lint-consumer-internal-imports` counts how many internal-package imports remain in those projects and compares against a committed number. It fails if the number goes up (someone added one) and also if it goes down without the number being updated (so improvements get locked in). Target is zero. The build itself also refuses to proceed if the published-package map would put one module in two places, or if a published package's `package.json` no longer matches what its code actually needs. ## Reading this PR It's large — 257 files — because it's a migration. The commits are grouped and meant to be read in order: 1. **Platform packages** — the build mechanism, and the seven platform packages it produces. 2. **Database packages, extension packs, the `prisma` command** — completes the set of 17. 3. **Generated imports become configurable** — one place decides which names get written, with today's names still the default. 4. **Database-family symmetry, publishing the map, the identity checks.** 5. **One package per application** — the three converted examples, the re-exports they proved necessary, and the counting check. 6. **Migration files follow the project too.** One thing worth knowing while reading: re-exporting a package republishes all of its sub-paths, not just the one that was needed. This PR adds 115 published sub-paths across the three database packages. Two candidates were dropped for exactly that reason — see below. ## Alternatives considered **Let an application install platform packages alongside its facade.** Nothing would need re-exporting and the facades would stay thinner. Rejected: an application would again juggle several Prisma dependencies whose correct combination it maintains by hand, and getting it wrong — upgrading one and not the other — produces the silent two-copies failure above. Re-exporting costs a generated line and nothing at runtime. **Re-export everything an application might plausibly want.** Rejected in review: because re-exporting brings a package's entire sub-path surface, generosity is expensive and hard to undo. Migration tooling (54 sub-paths) was dropped because its only users are extension packs, which install platform packages anyway; the SQL driver re-export was dropped because nothing imported it at all. What remains is what a converted example actually needed. **Flip the publish list in this same PR.** Rejected: it would mix "does the new surface work" with "is it safe to stop publishing 50 packages" in one review. The switch is mechanical once this lands, and gets its own change. ## Verification `build`, `typecheck` (156 tasks), `test:packages` (1077 files / 14087 tests), `test:e2e`, `lint`, `lint:deps`, `lint:docs`, `lint:manifests`, `check:publish-deps`, `check:clean-tree`, `lint:casts` and `lint:throws` (no new instances), `test:scripts`, coverage, the tarball-install suites, and regenerating every committed artifact leaves the tree unchanged. Known-unstable and unrelated to this change: the `relation-mode-gh-*` port suites (TML-3140), and several test timeouts that are too tight under load. ## Follow-ups TML-3124 switch the publish list · TML-3127 build cache can validate a stale published package on CI · TML-3140 unstable port suites · TML-3141 a test-helper sub-path reaches a package that is never published. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added consolidated public ORM packages for PostgreSQL, MongoDB, SQLite, framework tooling, database targets, and extensions. - Generated contracts, migrations, and scaffolds now adapt imports to the consuming project’s package surface. - Added facade-provided `prisma-next` CLI access and consolidated migration entrypoints. - **Documentation** - Updated installation, package naming, public entrypoint, and migration scaffolding guidance. - **Tests** - Added coverage for package installation, exports, CLI behavior, module identity, and import compatibility. - **Chores** - Added checks preventing incompatible internal and public package imports. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> | 2 个月前 | |
TML-3060: plan 4-stage lossless codec JSON migration (#1013) ## Linked issue Refs [TML-3060](https://linear.app/prisma-company/issue/TML-3060/plan-codec-json-projections) ## At a glance ```text TML-3062 SQL JSON projection AST foundations ↓ TML-3061 Target codec descriptor foundations ↓ TML-3063 Lossless JSON projection hard cut ↓ TML-3064 Aggregate codec typing and extension testkits ``` This is the committed delivery shape in [`projects/codec-json-projections/plan.md`](projects/codec-json-projections/plan.md); no runtime behavior changes in this PR. ## Decision This PR promotes the PostgreSQL numeric precision investigation into a tracked four-slice project. It commits the complete evidence, the settled target-owned projection architecture, a system-level Definition of Done, the stacked handoff contracts, and an exact compressed copy of the prototype without adopting that prototype's hardcoded renderer design. ## Summary Database-produced JSON can narrow arbitrary-precision values before a codec sees them, so the original local decoder/renderer fix is not a safe boundary. These artifacts make the broader lossless codec JSON migration reviewable and executable without relying on transient conversation or worktree state. ## Reviewer notes - The historical checkpoint intentionally preserves contemporaneous references to its original branch, `wip/` location, and uncommitted files. Current state lives in the README, design notes, spec, plan, trace, and TML-3060. - [`postgres-numeric-prototype.patch.gz`](projects/codec-json-projections/assets/postgres-numeric-prototype.patch.gz) is evidence only. Its decompressed SHA-256 is `0ed2afae20a3824dad79ebbf27f9dace730b5d729a626a4888414a98be4e3e7a`; the hardcoded `PG_NUMERIC_CODEC_ID` branch and lineage inference are explicitly rejected. - The plan is serial by dependency, not scheduling preference: each slice establishes the semantic/type boundary consumed by the next. - The named local stash is only an operator convenience. The tracked compressed patch and hash are the portable evidence. ## How it fits together 1. **Preserve the failure evidence.** The checkpoint records PostgreSQL precision loss and SQLite JSON probes; the compressed patch retains the exact five-file experiment independently of the active source tree. 2. **Set the semantic boundary.** Codecs choose canonical lossless JSON, target-neutral planning marks codec/native/document intent, and target descriptor specializations own AST-to-AST SQL projection. 3. **Carry authoritative output identity.** `ProjectionItem.codec` becomes the projected-value codec fact rather than asking adapters to reconstruct column lineage. 4. **Cover arrays, aggregates, and extensions.** The design includes PostgreSQL element lifting, SQLite document retagging, a separate aggregate descriptor registry, emitted `aggregateTypes`, and dev-only target testkits. 5. **Deliver through stable handoffs.** AST foundations land first, then target descriptor foundations, then the JSON hard cut, then aggregate typing/testkits and migration surfaces. ## What lands in this PR | Commit | What it adds | |---|---| | `TML-3060: plan lossless codec JSON projections` | Project entry point, full checkpoint, synthesized design notes, system spec, four-slice plan, Drive trace, evidence manifest, and exact compressed prototype patch. | The project-specific completion bar is captured in [`spec.md`](projects/codec-json-projections/spec.md), and the current approved sequencing is in [`plan.md`](projects/codec-json-projections/plan.md). ## Behavior changes & evidence - **No executable behavior changes.** The committed range adds only [`projects/codec-json-projections/**`](projects/codec-json-projections/README.md); package source, active tests, generated contracts, and configuration are unchanged. - **The design becomes a durable repository contract.** [`design-notes.md`](projects/codec-json-projections/design-notes.md) records the selected model and rejected alternatives, while [`spec.md`](projects/codec-json-projections/spec.md) fixes the project boundary, transition constraints, contract/adapter impact, and Definition of Done. - **The prototype becomes independently verifiable evidence.** [`assets/README.md`](projects/codec-json-projections/assets/README.md) records decompression and integrity details, while the archive keeps rejected implementation code out of the active tree. - **Implementation becomes an explicit stacked sequence.** [`plan.md`](projects/codec-json-projections/plan.md) names each slice's outcome, dependency, handoff, scope boundary, and PR base. ## Compatibility / migration / risk This planning PR has no runtime or API compatibility impact. The planned project intentionally keeps existing codec IDs while changing canonical JSON and some application result types; regenerated contracts, bigint/decimal aggregate migrations, extension updates, documentation, and upgrade instructions are mandatory later-slice deliverables rather than changes hidden in this PR. ## Testing performed - `git diff --cached --check` - `gzip -t projects/codec-json-projections/assets/postgres-numeric-prototype.patch.gz` - `gzip -dc projects/codec-json-projections/assets/postgres-numeric-prototype.patch.gz | shasum -a 256` → `0ed2afae20a3824dad79ebbf27f9dace730b5d729a626a4888414a98be4e3e7a` - Drive trace emitter schema validation for `project-started`, `spec-authored`, `spec-amended`, `plan-authored`, and `plan-amended` - No runtime suites — documentation, planning, trace, and inert evidence only ## Skill update n/a — planning artifacts only; no user-facing CLI, public TypeScript API, configuration, error code, or glossary surface changes in this PR. ## Follow-ups - [TML-3062](https://linear.app/prisma-company/issue/TML-3062/sql-json-projection-ast-foundations) opens as the first stacked implementation PR. - TML-3061, TML-3063, and TML-3064 follow in the order recorded above. ## Alternatives considered - **Commit the prototype as the fix.** Rejected because its codec-ID branch and recursive lineage inference put open-world codec semantics in the renderer. - **Keep the design only in `wip/` or conversation.** Rejected because implementation, review, and later context compaction need a tracked source of truth. - **Collapse everything into one implementation PR.** Rejected because AST vocabulary, target descriptor ownership, codec behavior, and aggregate typing are distinct review boundaries with real handoff dependencies. - **Parallelize the four slices.** Rejected because each downstream slice consumes types and invariants introduced by its predecessor and would otherwise require coupled merges or temporary duplicate APIs. ## Checklist - [x] All commits are signed off (`git commit -s`) per the [DCO](../CONTRIBUTING.md#developer-certificate-of-origin-dco). - [x] I read [CONTRIBUTING.md](../CONTRIBUTING.md) and the change is scoped to one logical concern. - [x] Tests are updated (n/a — doc/planning-only PR with no behavioral delta). - [x] The PR title is in `TML-NNNN: <sentence-case title>` form. - [x] The **Skill update** section above is filled in. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net> | 2 个月前 |
Project evidence
codec-json-projection-design-checkpoint.mdpreserves the complete design discussion, evidence, decisions, rejected alternatives, assumptions, and prototype state that preceded the tracked project.postgres-numeric-prototype.patch.gzpreserves the exact five-file uncommitted PostgreSQL numeric prototype. Decompress withgzip -dc projects/codec-json-projections/assets/postgres-numeric-prototype.patch.gz; the decompressed patch has SHA-2560ed2afae20a3824dad79ebbf27f9dace730b5d729a626a4888414a98be4e3e7a.
The prototype demonstrates the precision regression and that pre-JSON text projection prevents it. Its hardcoded codec-ID branch and derived-table lineage inference are evidence only, not the selected implementation architecture.