From 553290606450c9e4e5c3b566f975d1ad18cb9a02 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 17:45:24 +0200 Subject: [PATCH 01/19] docs(harness): activate database architecture RFC run --- .../context-pack.md | 72 ++++++++++ .../drift.md | 29 ++++ .../plan.md | 128 ++++++++++++++++++ .../research.md | 62 +++++++++ .../supervisor.md | 36 +++++ .../worklog.md | 101 ++++++++++++++ 6 files changed, 428 insertions(+) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md new file mode 100644 index 0000000000..e90a83994f --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -0,0 +1,72 @@ +# Context Pack: NetScript Database Architecture and Prisma 8 RFC + +## Run Metadata + +| Field | Value | +| -------------- | ------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Current phase | `research` | +| Archetype | Docs-only RFC describing future A1/A2/A4/A5/A6 surfaces | +| Scope overlays | `SCOPE-docs.md` | + +## Current State + +A clean-break database architecture RFC run is activated from current `origin/main`. Issue #313 is +carried in as historical evidence but its compatibility-first solution is explicitly superseded. The +canonical RFC has not been authored; research and PLAN-EVAL come first. + +## Completed + +- Loaded current repository, RFC process, harness, PR, doctrine-navigation, and docs-profile rules. +- Created an isolated worktree/branch from `origin/main` @ `cd7205293`. +- Read GitHub issue #313 and its comments through the connected GitHub surface. +- Selected mandatory PLAN-EVAL and the owner-directed Fable 5 high final refinement override. + +## In Progress + +- Bootstrap commit/draft PR, then current-state and upstream research. + +## Next Steps + +1. Publish the bootstrap review surface. +2. Audit current NetScript DB code, generated assets, public APIs, CI, issues, and debt. +3. Audit Prisma 8/Next primary sources and market prior art. +4. Lock architecture and Design checkpoint, then obtain PLAN-EVAL PASS. +5. Author and evaluate the RFC. + +## Key Decisions + +| Decision | Source | Notes | +| ------------------------------ | --------------- | ----------------------------------------------------------------------------- | +| No backward compatibility | Owner directive | Migration safety is required; runtime compatibility shims are not. | +| NetScript owns its DB concepts | Initial plan | Prisma remains an adapter/engine target, not the framework-facing vocabulary. | +| Fable 5 high is last | Owner directive | Final gate includes refinement, not only critique. | + +## Files Changed + +| Path | Status | Notes | +| --------------------------------------------------------- | ------ | --------------------------------------- | +| `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` | new | Harness provenance and resumable state. | + +## Gates + +| Gate family | Current status | Evidence | +| ----------- | -------------- | ----------------------------------- | +| Static | pending | Bootstrap inspection follows. | +| Fitness | pending | Research/archetype mapping follows. | +| Runtime | N/A | Docs-only RFC run. | +| Consumer | pending | RFC not authored. | + +## Open Questions + +- All public architecture decisions remain open until research is complete. + +## Drift and Debt + +- Drift: #313 compatibility-first architecture is superseded; final-gate effort is owner-overridden. +- Debt: pending targeted ledger scan. + +## Commits + +- See the draft PR's commit list + per-slice PR comments (V3 retired `commits.md`). diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md new file mode 100644 index 0000000000..79598ceb3a --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -0,0 +1,29 @@ +# Drift Log: NetScript Database Architecture and Prisma 8 RFC + +Drift is append-only. Record facts that diverge from the plan, RFC, doctrine, or current-state +documentation. + +## 2026-08-13 — Issue #313 solution premise superseded + +- **What:** The carried-in plan preserves classic Prisma and adds Prisma Next as an opt-in Postgres + pilot. The owner now requires a clean architectural break with no backward-compatibility + constraint. +- **Source:** GitHub issue #313 body and the current owner directive. +- **Expected:** Reuse #313's additive migration architecture. +- **Actual:** Reuse only its evidence/problem inventory; redesign the target architecture from + current NetScript and Prisma 8 facts. +- **Severity:** architectural +- **Action:** rescope +- **Evidence:** + +## 2026-08-13 — Final refinement lane override + +- **What:** The final gate must use Fable 5 high and refine the RFC in place, not merely provide an + adversarial report. +- **Source:** Current owner directive. +- **Expected:** Ordinary docs/evaluator routing would use Fable medium for final polish or formal + evaluation. +- **Actual:** Owner-authorized Fable high is reserved as the absolute last substantive gate. +- **Severity:** significant +- **Action:** accept +- **Evidence:** `supervisor.md` routes and override record. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md new file mode 100644 index 0000000000..14e1bf0f2f --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -0,0 +1,128 @@ +# Plan: NetScript Database Architecture and Prisma 8 + +## Run Metadata + +| Field | Value | +| -------------- | --------------------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Phase | `research` | +| Target | `rfcs/0000-database-architecture.md` plus harness provenance | +| Archetype | Docs-only RFC describing future Archetypes 1, 2, 4, 5, and 6 surfaces | +| Scope overlays | `SCOPE-docs.md` | + +## Archetype + +The committed change is a documentation/RFC changeset, so `SCOPE-docs.md` governs its immediate +gates. The architecture it specifies spans separate future package boundaries: a small contract/IR +(A1), external database integration ports/adapters (A2), a user-facing definition DSL (A4), database +contribution packages (A5 where first-party plugins are used), and CLI/scaffold automation (A6). +Research must assign one smallest fitting archetype to each proposed package rather than forcing the +whole database system into one package shape. + +## Current Doctrine Verdict + +Pending the current database-package verdict and relevant debt-ledger scan. + +## Axioms in Play + +| Axiom | Why it matters | +| ----- | ----------------------------------------------------------------------------------------- | +| A1 | The RFC must lock the public contracts before implementation topology. | +| A2 | NetScript's durable boundary must remain simpler than Prisma internals. | +| A3 | The common database path must become one deterministic command/composition flow. | +| A5 | Provider, engine, migration, schema, validation, and observability axes must compose. | +| A7 | NetScript should wrap upstream capabilities and standards rather than rebuild an ORM. | +| A9 | Each proposed package needs an explicit doctrine archetype. | +| A10 | The app's generated composition root, not a service locator, wires database capabilities. | +| A11 | Extension axes must be named before the RFC introduces abstractions. | +| A14 | Contract tests and CI must preserve the architecture and eliminate manual drift. | + +## Goal + +Produce a state-of-the-art, implementation-grade RFC for a clean-break NetScript database +architecture built for Prisma 8, while remaining deliberately capable of multiple schemas, +databases, engines, providers, deployment runtimes, and third-party contributions. + +## Scope + +- Deep current-state and historical NetScript audit. +- Deep Prisma 8/Next and source/issue/PR audit. +- Competitor/prior-art analysis. +- Complete user-facing and contributor-facing architecture. +- Explicit breaking migration and parallel-branch rollout strategy. +- Implementation waves, contracts, test strategy, CI design, risk analysis, and acceptance gates. + +## Non-Scope + +- Production implementation of the accepted architecture in this RFC PR. +- Backward-compatible shims, aliases, dual clients, or preservation of obsolete generated assets. +- Premature selection of unverified Prisma 8 internals as stable NetScript public API. + +## Hidden Scope + +- Generator determinism and cacheability, plugin discovery, configuration provenance, secrets, + migration concurrency, destructive-change policy, transaction semantics, serverless/edge/runtime + constraints, telemetry, test databases, CI topology, version skew, supply-chain boundaries, + docs/scaffold synchronization, and AI-agent discoverability. + +## Locked Decisions + +| ID | Decision | Rationale | +| -- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| L0 | This RFC is a clean-break redesign; compatibility is not a design constraint. | Explicit owner directive; avoids encoding old foundation limits into the new layer. | +| L1 | Prisma is an implementation target behind NetScript-owned concepts, not the NetScript DB public API itself. | Preserves flexibility without pretending all database semantics are portable. | +| L2 | PLAN-EVAL is mandatory before authoring the canonical RFC. | The run is architecture-heavy, high-risk, and multi-wave. | +| L3 | Fable 5 high is the last substantive gate and may refine the document in place. | Explicit owner exception. | + +## Open-Decision Sweep + +All architecture decisions remain `must resolve now` until research closes them. The completed plan +will enumerate each one individually before PLAN-EVAL. + +## Risk Register + +| Risk | Mitigation | +| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| Designing against RC marketing rather than implementation reality | Verify official docs against source, tests, release diffs, and live issues/PRs. | +| Replacing manual glue with a larger proprietary abstraction | Keep NetScript IR/ports minimal, capability-oriented, and conformance-tested. | +| False portability across engines | Model capabilities and explicit escape hatches; never normalize away real provider semantics. | +| RFC too broad to implement | Define strict package boundaries, dependency graph, staged waves, and per-wave acceptance gates. | +| No-compat break becomes an unsafe migration | Supply a mechanical migration tool/doc, preflight report, data-preserving sequence, and rollback boundaries without runtime shims. | + +## Anti-Patterns to Resolve or Avoid + +Pending current-state and doctrine audit. + +## Fitness Gates + +Pending archetype assignment and Plan-Gate completion. + +## Arch-Debt Implications + +Pending targeted scan of `.llm/harness/debt/arch-debt.md`. + +## Validation Plan + +| Order | Gate | Command or check | Expected result | +| ----- | ------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- | +| 1 | Research provenance | Source/link inventory and claim ledger | Every load-bearing claim is traceable and current. | +| 2 | PLAN-EVAL | Fresh Fable 5 medium opposite-family session | `PASS` before RFC authoring. | +| 3 | RFC source alignment | Local paths, `deno doc`, focused code inspection, upstream primary sources | No unsupported present-state or proposed-surface claim. | +| 4 | Docs gates | Formatting, local links/paths, terminology, contradiction scan | PASS. | +| 5 | Independent architecture review | Qwen 3.8 Max | No unresolved critical/high finding. | +| 6 | IMPL-EVAL | Fresh opposite-family evaluator | `PASS`. | +| 7 | Final refinement | Fable 5 high | Final in-place refinement; no substantive gate follows. | + +## Dependencies + +- Current NetScript `main`, issue/PR history, doctrine, and RFC process. +- Official Prisma release/docs/source/issues/PRs and supported database/runtime matrix. +- Existing native Claude/Fable agentic route and phase-bound Qwen evaluator route. + +## Drift Watch + +- Prisma 8 RC releases or API changes during the run. +- New NetScript database changes merged to `main`. +- Any model route that reports a different identity or cannot attach observably. +- Any architecture decision that would implicitly recreate backward compatibility. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md new file mode 100644 index 0000000000..d05c6d0248 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md @@ -0,0 +1,62 @@ +# Research — docs-database-architecture-rfc--prisma-8-rfc + +## Re-baseline + +- Carried-in sources: GitHub issue #313, its linked Prisma Next v0.14-era design assumptions, and + related NetScript database issues discovered during research. +- Re-derived against `main` @ `cd720529333328bcba5e1a308ce7632f4350efdf` on 2026-08-13. +- Upstream target: Prisma 8.0.0 RC / Prisma Next, beginning with the official `v8.0.0-rc.1` release + and then current source, PRs, issues, and official documentation. +- What changed versus the carried-in version: + - #313 mandates an additive, backward-compatible Postgres pilot beside classic Prisma. + - The owner now mandates a clean architectural break with **no backward-compatibility + constraint**. #313 is evidence and problem inventory, not an inherited solution. + - Prisma Next has advanced from the v0.14 Early Access surface recorded in #313 to the Prisma 8 + release-candidate line, so every upstream capability and gap must be re-verified. + +## Research workstreams + +1. Current NetScript database topology, generated assets, public APIs, adapters, CLI flows, CI, + runtime scaffolds, and contributor extension seams. +2. Complete issue/PR history for #313 and the “Prisma Gaps” family, including later DB regressions + and architectural debt. +3. Prisma 8 / Prisma Next release, docs, source tree, packages, generators, schema/migration engine, + adapters, drivers, multi-schema/multi-database behavior, extension model, Deno compatibility, CI, + open PRs/issues, roadmap signals, and agent-facing surfaces. +4. Market prior art: batteries-included meta-frameworks, ORM/toolkit ecosystems, database-agnostic + frameworks, code-first/schema-first systems, migration systems, local-first/data layers, and + plugin contribution models. +5. Fresh NetScript architecture: contracts, ports, adapters, DSL/factories, plugin contributions, + capability negotiation, schema ownership, engine selection, deterministic generation, + zero-manual-step automation, observability, testing, CI, migration, and parallel-branch rollout. + +## Findings + +| # | Finding | How to verify | +| - | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------ | +| 1 | #313's compatibility-first premise conflicts with the current owner directive. | GitHub issue #313 body; current run prompt | +| 2 | This is decision-heavy, cross-package, multi-wave architecture work; PLAN-EVAL is mandatory. | `.llm/harness/workflow/run-loop.md` §4 | +| 3 | The canonical deliverable is a draft RFC under `rfcs/0000-*.md`; run artifacts preserve provenance but do not become the accepted design record. | `rfcs/README.md` | + +## jsr-audit surface scan (package/plugin waves) + +- Status: pending focused inventory of the database package, adapter packages, CLI/scaffold + surfaces, and any proposed new package exports. +- This RFC is docs-only, but it specifies future published package/plugin surfaces, so the planned + public API must receive the same slow-type, private-type-reference, upstream-re-export, and + subpath-boundary scrutiny before Plan-Gate. + +## Open questions + +- Which Prisma 8 capabilities are stable enough to own directly, and which must remain behind a + narrow NetScript port? +- What is the minimum durable NetScript database IR/contract that can serve Prisma without + recreating an ORM or schema engine? +- Should database integrations be ordinary plugin contributions, a dedicated capability family, or a + composition of schema/provider/runtime/migration contributions? +- How should one app express multiple logical schemas, databases, providers, tenants, and execution + runtimes without generator ordering or import-path ambiguity? +- What fully automated lifecycle replaces today's manual generation, patching, adapter selection, + migrations, seeding, registry wiring, and CI matrix maintenance? +- What implementation-wave boundaries preserve reviewability while explicitly avoiding a + compatibility layer? diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md new file mode 100644 index 0000000000..3d9acd52b1 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -0,0 +1,36 @@ +# Supervisor Identity — docs-database-architecture-rfc--prisma-8-rfc + +Written at run start per `workflow/lane-policy.md` § Supervisor identity. + +| Field | Value | +| -------- | ------------------------------------------------------------------------------------ | +| Model | Codex · OpenAI · GPT-5 family · high (root session; exact routed SKU is not exposed) | +| Session | `019ffbc7-133b-7852-905d-53a163fe9819` | +| Host | `YogaBook9i` · WSL2 Linux 6.18.33.2 · user `codex` | +| Checkout | `/home/codex/repos/netscript-547-lffix` | +| Worktree | `/home/codex/repos/netscript-db-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Baseline | `origin/main` @ `cd720529333328bcba5e1a308ce7632f4350efdf` (2026-08-13) | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | + +## Routes in force + +| Task lane | Provider / model / effort | Role in this run | +| --------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------- | +| `planning_decisions` | OpenAI · Codex · GPT-5 family · high | Root research coordinator and RFC generator in the active user session | +| `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | +| `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | +| third-opinion architecture review | OpenRouter · Qwen 3.8 Max · max | Diversity pass over the full architecture and implementation roadmap | +| owner-directed final refinement | Anthropic · Fable 5 · high | Absolute final review-and-refinement gate after every other substantive gate | + +## Recorded lane/eval overrides + +- The root session is Codex rather than the default Opus 5 orchestrator. This is the active + user-facing session surface; exact backend SKU is not exported, so the observed identity is + recorded without claiming GPT-5.6 Sol. +- The owner explicitly requires Fable 5 **high**, not merely an adversarial review, as the final + refinement gate. That owner directive overrides the ordinary `docs_polish` Fable-medium effort for + this run. No substantive model gate may follow it. +- Qwen 3.8 Max is selected as an in-policy independent architecture review for intelligence-family + diversity. Grok 4.6 will be used only if an existing policy-compliant, observable route is + present; no unrecorded paid escalation is authorized. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md new file mode 100644 index 0000000000..52da39b9c3 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -0,0 +1,101 @@ +# Worklog: NetScript Database Architecture and Prisma 8 RFC + +## Run Metadata + +| Field | Value | +| -------------- | ------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Archetype | Docs-only RFC describing future A1/A2/A4/A5/A6 surfaces | +| Scope overlays | `SCOPE-docs.md` | + +## Design + +The Design checkpoint is intentionally **not locked yet**. Research is active, and no canonical RFC +file may be created before the completed checkpoint passes PLAN-EVAL. + +### Public Surface + +- Planned RFC record: `rfcs/0000-database-architecture.md`. +- Future runtime/API/CLI surfaces: pending research and design lock. + +### Domain Vocabulary + +- Pending evidence-led definition. Candidate terms are not contracts until the plan is locked. + +### Ports + +- Pending identification of real external dependencies and exercised test seams. + +### Constants + +- Pending closed-vocabulary design for capability families, provider/runtime kinds, artifact kinds, + lifecycle phases, and gate identifiers. + +### Commit Slices + +| # | Slice | Gate | Files | +| - | -------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------- | +| 0 | Activate the harness run and publish the review surface | Run-artifact presence + clean diff | `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/*` | +| 1 | Research and lock the RFC design | PLAN-EVAL | Run research/plan/worklog artifacts | +| 2 | Author the implementation-grade RFC and migration design | Source-alignment/docs gates | `rfcs/0000-database-architecture.md` + run artifacts | +| 3 | Resolve multi-model review findings and close the run | IMPL-EVAL + Qwen review + owner-directed Fable 5 high final refinement | RFC + evaluation/run artifacts | + +### Deferred Scope + +- Production package/CLI/plugin implementation — begins only after RFC acceptance. + +### Contributor Path + +The RFC will define the final contributor path; until PLAN-EVAL, contributors start from this run's +research inventory and proposed package-boundary matrix. + +## Progress Log + +| Time | Slice | Step | Notes | +| ---------- | ----- | --------- | ---------------------------------------------------------------------------------------- | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | + +## Decisions + +| Decision | Reason | Source | +| ------------------------------------- | --------------------------------------------------------------------------------- | ------------------------- | +| Treat #313 as superseded design input | Its additive compatibility premise conflicts with the owner-directed clean break. | Issue #313 + owner prompt | +| Require PLAN-EVAL | Material architecture, sequencing, and multi-wave risk are unavoidable. | Harness run loop §4 | + +## Drift + +| Drift | Severity | Logged in drift.md | +| -------------------------------------------------------- | ------------- | ------------------ | +| #313 compatibility-first plan is no longer authoritative | architectural | yes | +| Fable 5 high is the owner-directed final refinement gate | significant | yes | + +## Gate Results + +### Static Gates + +| Gate | Command or check | Result | Notes | +| -------------- | ----------------------------------------------- | ------ | ----------------------------------------------------- | +| Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | + +### Fitness Gates + +| Gate | Result | Evidence | Notes | +| -------------------------- | ------- | ---------------- | -------------------------------------------- | +| Archetype/anti-pattern set | NOT_RUN | Pending research | RFC proposes future public package surfaces. | + +### Runtime Gates + +| Gate | Result | Evidence | Notes | +| ---------------- | ------ | ------------------- | ----------------------------------------------------- | +| Runtime behavior | N/A | Docs-only bootstrap | Future implementation gates will be specified by RFC. | + +### Consumer Gates + +| Consumer | Result | Evidence | Notes | +| ---------------------- | ------- | ----------- | ------------------------------------------------------ | +| RFC reader/implementer | NOT_RUN | Pending RFC | Must be implementation-grade and internally navigable. | + +## Handoff Notes + +- Research is active. No PLAN-EVAL or implementation/RFC authorship verdict is claimed. From 9f1d0244acafbd3f9cf7e5e861c480231fa5434e Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 18:18:41 +0200 Subject: [PATCH 02/19] docs(rfc): record database architecture research --- .../briefs/claude-opus-architecture.md | 122 ++++ .../context-pack.md | 8 +- .../drift.md | 14 + .../plan.md | 20 +- .../research.md | 22 +- .../research/market-analysis.md | 549 +++++++++++++++ .../research/netscript-current-state.md | 295 ++++++++ .../research/prisma-8-deep-dive.md | 653 ++++++++++++++++++ .../supervisor.md | 23 +- .../worklog.md | 16 +- 10 files changed, 1691 insertions(+), 31 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture.md new file mode 100644 index 0000000000..552d7f13c2 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture.md @@ -0,0 +1,122 @@ +# Claude Code Opus 5 High — Independent Database Architecture Deep Dive + +## Role + +Use the NetScript harness. You are a subordinate architecture/research lane in an active RFC run, +not the supervisor and not the formal PLAN-EVAL. Work independently from the Codex framing, +challenge it, and return decision-grade evidence. You may use native Claude Workflows or focused +Claude subagents when they materially improve coverage; if you do, record the workflow/subagent +roles and observable identifiers in your report. + +Requested route: native Claude Code, Opus 5, effort high. + +## Worktree and run + +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Branch: `docs/database-architecture-rfc` +- Run: `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` +- Baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` +- Prisma RC clone: `.llm/tmp/prisma-v8-rc1` +- Prisma RC pin: `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` +- Prisma current-main pin observed by the supervisor: `71e2e0d9ee1f306b5a11435cd1973023cb33866a` + +Read `AGENTS.md` and the complete `.agents/skills/netscript-harness/SKILL.md` first. Follow its +retrieval order for any doctrine/archetype decisions you make. This is a docs-only RFC research +slice describing future Archetype 1/2/4/5/6 surfaces. + +## Owner intent + +This is a clean-break architectural redesign of NetScript's database story around Prisma 8 / Prisma +Next. It is not a 1:1 Prisma migration. Backward compatibility must not constrain the design. Data +migration safety and a mechanical migration path are required, but runtime compatibility facades, +old generated clients, aliases, and hand-maintained shims are forbidden. + +The architecture must eliminate manual schema/type generation, generated-source patching, manual +adapter assembly, Prisma-related CI instability, and copied plugin fragments while supporting +multiple schemas, multiple databases (including two targets of the same provider), provider/runtime +capability differences, plugin contributions, deterministic tooling, and an excellent human/CI/ +agent experience. + +## Required reading + +Read these completely before forming conclusions: + +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md` +- `rfcs/PROCESS.md` and the RFC template it points to +- relevant source paths cited by the current-state audit +- Prisma RC source/scorecard/ADRs/control/runtime/skills in the local clone + +Do not accept the existing research's proposed conclusions merely because they are written. Verify +load-bearing claims against source and flag any error, overreach, or missed alternative. + +## Independent questions + +1. What is the smallest durable NetScript database kernel, and what must remain Prisma-specific? +2. Is a `DatabaseGraph` actually the right central abstraction? If so, define its identities, + invariants, compilation phases, and failure behavior. If not, propose a superior abstraction. +3. What are the exact package boundaries and dependency directions? Assign the smallest fitting + NetScript archetype to each. +4. Design implementation-grade TypeScript APIs for: + - application target definition and selection; + - runtime acquisition/scoping; + - schema/contract-space contributions; + - provider/driver/runtime adapters and capability negotiation; + - migration plan/apply/verify operations; + - validation artifact providers; + - testkit/conformance certification; and + - generated agent manifest/command context. +5. How should same-provider multi-target, same-database multi-schema, cross-space relations, + replicas, serverless/request scope, and externally managed schemas differ in the type/domain + model? +6. How should plugin upgrade, dependency ordering, collision, version skew, uninstall, retained + data, and external drift behave? +7. Where can the design accidentally create a proprietary second ORM, an over-broad generic + repository, a service locator, or a lowest-common-denominator portability layer? +8. Which Prisma 8 ideas should NetScript adopt, wrap, replace, or reject? Which exact upstream seams + are mature enough to integrate, and what must be gated? +9. Design the zero-manual-step development loop and the deterministic CI/deployment protocol, + including atomic artifacts, stale-output detection, plan approval, cross-target partial failure, + resume, receipts, locks, and offline/Aspire classification. +10. Design the clean-break migration and temporary parallel-branch strategy without reintroducing + compatibility into the product architecture. +11. Produce a failure-mode analysis and an implementation/conformance test matrix that would catch + the incidents in the NetScript audit and the open Prisma 8 issues/PRs. +12. Identify any decision that the RFC must leave conditional on Prisma 8 final rather than + pretending the RC has settled it. + +## Output contract + +Write exactly one file: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +Do not edit any other file. Do not commit, push, comment on GitHub, change labels, or author the +canonical RFC. + +The report must contain: + +- requested and observed model/effort/session identity; +- whether workflows/subagents were used and their roles/identifiers; +- independent executive verdict; +- corrected or missing research findings with evidence; +- explicit architecture decision table with alternatives and rejection reasons; +- package/dependency graph; +- concrete API/DSL sketches (not merely nouns); +- graph compilation/runtime/control lifecycle; +- plugin contribution and removal protocol; +- capability/ownership/error models; +- multi-target transaction/failure semantics; +- dev/CI/agent experience; +- clean-break migration/parallel-branch strategy; +- threat/failure-mode analysis; +- implementation waves and per-wave proof gates; +- unresolved decisions and upstream maturity gates; +- severity-tagged adversarial findings against the current research/plan; and +- a primary-source register. + +Distinguish observed fact, inference, and proposal. Prefer source and tests over stale prose. The +result should be suitable for direct use by the supervisor when locking the Plan-Gate. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index e90a83994f..870694d089 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -25,15 +25,17 @@ canonical RFC has not been authored; research and PLAN-EVAL come first. ## In Progress -- Bootstrap commit/draft PR, then current-state and upstream research. +- Claude Code Opus 5 high independent architecture deep dive, followed by plan synthesis and the + separate formal PLAN-EVAL. ## Next Steps 1. Publish the bootstrap review surface. 2. Audit current NetScript DB code, generated assets, public APIs, CI, issues, and debt. 3. Audit Prisma 8/Next primary sources and market prior art. -4. Lock architecture and Design checkpoint, then obtain PLAN-EVAL PASS. -5. Author and evaluate the RFC. +4. Incorporate the owner-directed Claude Opus 5 high independent report. +5. Lock architecture and Design checkpoint, then obtain PLAN-EVAL PASS. +6. Author and evaluate the RFC. ## Key Decisions diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md index 79598ceb3a..a01426a666 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -27,3 +27,17 @@ documentation. - **Severity:** significant - **Action:** accept - **Evidence:** `supervisor.md` routes and override record. + +## 2026-08-13 — Orchestration posture correction + +- **What:** The root session performed too much of the research directly instead of using the + harness as the orchestration layer. +- **Source:** Owner correction in the active session. +- **Expected:** Root research coordination followed by ordinary deep-analysis routing. +- **Actual:** The owner explicitly requires the root to orchestrate substantive independent work and + requests Claude Code Opus 5 high with its workflow capabilities. +- **Severity:** significant +- **Action:** correct +- **Evidence:** native background session `3f8a9a69-5589-4b91-9a32-91f7770fe7c2`, observed as Opus 5 + high in `/home/codex/repos/netscript-db-rfc`; exclusive briefing at + `briefs/claude-opus-architecture.md`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md index 14e1bf0f2f..685c7adeee 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -74,6 +74,7 @@ databases, engines, providers, deployment runtimes, and third-party contribution | L1 | Prisma is an implementation target behind NetScript-owned concepts, not the NetScript DB public API itself. | Preserves flexibility without pretending all database semantics are portable. | | L2 | PLAN-EVAL is mandatory before authoring the canonical RFC. | The run is architecture-heavy, high-risk, and multi-wave. | | L3 | Fable 5 high is the last substantive gate and may refine the document in place. | Explicit owner exception. | +| L4 | Claude Code Opus 5 high performs a fresh independent architecture deep dive before plan lock. | Owner explicitly requires orchestration and this model's workflow capabilities. | ## Open-Decision Sweep @@ -104,15 +105,16 @@ Pending targeted scan of `.llm/harness/debt/arch-debt.md`. ## Validation Plan -| Order | Gate | Command or check | Expected result | -| ----- | ------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- | -| 1 | Research provenance | Source/link inventory and claim ledger | Every load-bearing claim is traceable and current. | -| 2 | PLAN-EVAL | Fresh Fable 5 medium opposite-family session | `PASS` before RFC authoring. | -| 3 | RFC source alignment | Local paths, `deno doc`, focused code inspection, upstream primary sources | No unsupported present-state or proposed-surface claim. | -| 4 | Docs gates | Formatting, local links/paths, terminology, contradiction scan | PASS. | -| 5 | Independent architecture review | Qwen 3.8 Max | No unresolved critical/high finding. | -| 6 | IMPL-EVAL | Fresh opposite-family evaluator | `PASS`. | -| 7 | Final refinement | Fable 5 high | Final in-place refinement; no substantive gate follows. | +| Order | Gate | Command or check | Expected result | +| ----- | ---------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- | +| 1 | Research provenance | Source/link inventory and claim ledger | Every load-bearing claim is traceable and current. | +| 2 | Independent architecture deep dive | Fresh native Claude Code Opus 5 high | Decision-grade report incorporated before plan lock. | +| 3 | PLAN-EVAL | Fresh Fable 5 medium opposite-family session | `PASS` before RFC authoring. | +| 4 | RFC source alignment | Local paths, `deno doc`, focused code inspection, upstream primary sources | No unsupported present-state or proposed-surface claim. | +| 5 | Docs gates | Formatting, local links/paths, terminology, contradiction scan | PASS. | +| 6 | Independent architecture review | Qwen 3.8 Max | No unresolved critical/high finding. | +| 7 | IMPL-EVAL | Fresh opposite-family evaluator | `PASS`. | +| 8 | Final refinement | Fable 5 high | Final in-place refinement; no substantive gate follows. | ## Dependencies diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md index d05c6d0248..52ed54897a 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md @@ -32,11 +32,16 @@ ## Findings -| # | Finding | How to verify | -| - | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------ | -| 1 | #313's compatibility-first premise conflicts with the current owner directive. | GitHub issue #313 body; current run prompt | -| 2 | This is decision-heavy, cross-package, multi-wave architecture work; PLAN-EVAL is mandatory. | `.llm/harness/workflow/run-loop.md` §4 | -| 3 | The canonical deliverable is a draft RFC under `rfcs/0000-*.md`; run artifacts preserve provenance but do not become the accepted design record. | `rfcs/README.md` | +| # | Finding | How to verify | +| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| 1 | #313's compatibility-first premise conflicts with the current owner directive. | GitHub issue #313 body; current run prompt | +| 2 | This is decision-heavy, cross-package, multi-wave architecture work; PLAN-EVAL is mandatory. | `.llm/harness/workflow/run-loop.md` §4 | +| 3 | The canonical deliverable is a draft RFC under `rfcs/0000-*.md`; run artifacts preserve provenance but do not become the accepted design record. | `rfcs/README.md` | +| 4 | NetScript currently has five overlapping database systems rather than one source of truth; same-engine targets collide at `database/`. | [current-state audit](./research/netscript-current-state.md) | +| 5 | Prisma 8 replaces generated executable clients with a canonical contract plus runtime/control planes, but RC1 is Early Access and PostgreSQL is its only intended 8.0 GA target. | [Prisma deep dive](./research/prisma-8-deep-dive.md) | +| 6 | Prisma's programmatic control seam is strengthening while its CLI/config packaging changed materially within six days after RC1. | [Prisma deep dive](./research/prisma-8-deep-dive.md#six-days-of-post-rc-churn) | +| 7 | Market leaders solve individual parts—contract ownership, named connections, adapter factories, migration graphs, or policy—but no comparator composes all of them into a typed meta-framework database layer. | [market analysis](./research/market-analysis.md) | +| 8 | The owner requires orchestration-first execution; a native Claude Code Opus 5 high lane now independently challenges the research and designs the architecture before plan lock. | [architecture briefing](./briefs/claude-opus-architecture.md) | ## jsr-audit surface scan (package/plugin waves) @@ -46,6 +51,12 @@ public API must receive the same slow-type, private-type-reference, upstream-re-export, and subpath-boundary scrutiny before Plan-Gate. +## Completed research artifacts + +- [NetScript current-state and incident audit](./research/netscript-current-state.md) +- [Prisma 8 RC1/current-main source, scorecard, issue/PR, and agent-surface audit](./research/prisma-8-deep-dive.md) +- [Eleven-product market/prior-art comparison](./research/market-analysis.md) + ## Open questions - Which Prisma 8 capabilities are stable enough to own directly, and which must remain behind a @@ -60,3 +71,4 @@ migrations, seeding, registry wiring, and CI matrix maintenance? - What implementation-wave boundaries preserve reviewability while explicitly avoiding a compatibility layer? +- Which independent Opus findings require correction before the plan is eligible for PLAN-EVAL? diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md new file mode 100644 index 0000000000..53532145a8 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md @@ -0,0 +1,549 @@ +# Database Architecture Market Analysis + +## Scope and method + +This is not an ORM popularity comparison. NetScript is a meta-framework, so the relevant question is +which products have solved parts of the framework-level problem: + +- one coherent developer workflow over database tooling; +- schema ownership across application features and plugins; +- multiple databases, schemas, providers, and deployment modes; +- extensible adapters without forcing every contributor to reimplement framework mechanics; +- deterministic generation and migrations; +- safe, inspectable CI/deployment; +- runtime lifecycle and connection routing; and +- an accurate agent-facing surface. + +The comparison uses official product documentation and source repositories observed on 2026-08-13. +It evaluates eleven purposeful comparators: + +1. Wasp and RedwoodJS as Prisma-based full-stack frameworks; +2. Payload and Better Auth as plugin-heavy TypeScript products; +3. AdonisJS Lucid as an integrated application-framework database layer; +4. Drizzle, MikroORM, and Kysely as TypeScript data-tooling architectures; +5. Atlas as a database delivery/control-plane product; and +6. Django and Rails as mature app-owned migration and multi-database systems. + +No product is a template to copy wholesale. The desired NetScript architecture combines the +strongest ownership, extensibility, lifecycle, and safety ideas while avoiding their manual seams. + +## Executive comparison + +| Product | Strongest relevant idea | Important limitation for NetScript | +| -------------- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| Wasp | Framework commands and generated auth/app schema create a coherent Prisma happy path | Still fundamentally one framework-managed Prisma schema/client and provider story. | +| RedwoodJS | Framework-level schema, structural migrations, seeds, and explicit data migrations | Largely forwards Prisma CLI concepts; data and structural migration ordering remains manual. | +| Payload | Thin internal database contract with official Mongo/Drizzle adapters | Adapter abstraction serves Payload's CMS model, not arbitrary app/plugin contract ownership. | +| Better Auth | Typed plugin schema declarations plus an adapter factory that centralizes mechanics | Prisma/Drizzle users still generate an ORM schema and manually migrate it. | +| AdonisJS Lucid | Named typed connections, lifecycle ownership, programmatic runner, locks, data-migration defer | ORM/config is framework-specific and plugins do not own independent contract spaces. | +| Drizzle | Broad dialect coverage, SQL escape hatches, schema filters, many migration workflows | Multiple configs and exported schema aggregation remain developer-managed; ownership is implicit. | +| MikroORM | Clean core/driver/extension split with broad providers and programmable migration runner | One ORM instance does not span independent connections; multi-schema fan-out has stateful caveats. | +| Kysely | Small open dialect/driver/plugin interfaces, zero-dependency cross-runtime query core | Schema types/codegen and migration authoring are intentionally external/manual. | +| Atlas | Composite schema graph, semantic migration lint, drift, policy, promotion, target-group rollout | Separate product/control plane; application runtime typing and plugin APIs are out of scope. | +| Django | Per-app migration graphs with declared dependencies and mature routing | Multiple databases are operated one at a time and router mistakes may silently skip migrations. | +| Rails | Named DBs, per-DB migration roots, runtime role/shard switching, unmanaged DB flag | Database ownership is config/folder-based, not a typed plugin contribution protocol. | + +The market does not offer one complete equivalent of the proposed NetScript layer. The opportunity +is real: treat database structure as a composed, typed ownership graph; drive runtime and control +planes from it; and make safety and agent context first-class outputs. + +## Comparator deep dives + +### Wasp + +[Wasp entities](https://wasp.sh/docs/0.20/data-model/entities) are Prisma models in a +`schema.prisma` file. Wasp exposes a framework migration command and a singleton Prisma client +through `wasp/server`. Its [database documentation](https://wasp.sh/docs/data-model/databases) +supports SQLite as the default local route and PostgreSQL for production. Wasp Auth +[combines generated auth entities with the user's schema](https://wasp.sh/docs/auth/entities). + +What works: + +- the framework owns a simple end-to-end command surface; +- application code imports a framework database service rather than assembling a client; +- auth schema is derived as part of framework composition; and +- a new application gets a low-friction local database. + +What remains weak: + +- schema combination is a framework special case, not a public ownership protocol; +- plugin dependency/version/removal semantics are not first-class; +- the singleton/runtime shape is not capability- or deployment-mode-specific; +- multi-target identity and independent histories are not central; and +- migration safety remains constrained by the underlying Prisma workflow. + +NetScript lesson: preserve “one obvious workflow,” but replace implicit schema merging and singleton +service access with declared contract spaces and scoped target references. + +### RedwoodJS + +Redwood wraps Prisma migrations and client use through its CLI. Its +[data migration system](https://docs.redwoodjs.com/docs/data-migrations) adds an application-owned +ledger and timestamped TypeScript transforms alongside Prisma's structural migrations. The +[CLI reference](https://docs.redwoodjs.com/docs/cli-commands) separates `migrate dev`, +`migrate deploy`, reset, seed, and data-migrate commands. + +What works: + +- structural and content changes are recognized as different concerns; +- data migrations are plain application code with an execution ledger; +- CLI integration reduces raw tool invocation; and +- the framework documents environment-specific migration behavior. + +What remains weak: + +- structural and data migrations are separate sequences the developer must coordinate; +- new-developer replay can run structural drops before a historical data transform, requiring + defensive code or manual choreography; +- provider switching can require discarding migration history; and +- plugin schema ownership and multi-database composition are not solved. + +NetScript lesson: data transforms must be invariant-bound edges in the same plan as schema +transitions, not a second chronological folder whose correctness depends on invocation order. + +### Payload + +Payload documents a [thin database adapter](https://payloadcms.com/docs/database/overview) over its +internal data structures. Official adapters cover MongoDB/Mongoose and PostgreSQL or SQLite through +Drizzle. Its [migration commands](https://payloadcms.com/docs/database/migrations) share a common +framework surface while adapters implement provider-specific behavior; relational databases use +migration files, while Mongo workflows emphasize data transformations. + +What works: + +- framework code depends on an internal database contract; +- providers live in separate packages; +- the adapter selects the backing ORM without exposing it as the whole product contract; and +- lifecycle/migration commands remain product-level concepts. + +What remains weak: + +- the adapter is shaped around Payload collections and CMS operations; +- provider capability differences are not a general application type system; +- schema-contributing third-party packages do not get independent migration ownership by default; +- multiple arbitrary application databases are not the core abstraction. + +NetScript lesson: use an internal port and target packages, but do not create a giant generic +repository interface. Keep feature ports consumer-owned and make target capabilities explicit. + +### Better Auth + +Better Auth's [database model](https://better-auth.com/docs/concepts/database) supports multiple +adapters. Plugins can declare models/fields; the CLI can generate or migrate the required schema. +The [plugin API](https://better-auth.com/docs/beta/concepts/plugins) makes database schema part of a +typed plugin definition. Its +[adapter factory](https://better-auth.com/docs/beta/guides/create-a-db-adapter) centralizes model +and field mapping, ID generation, JSON conversion, joins, and schema configuration so an adapter +author focuses on database operations. + +What works: + +- plugin-owned database requirements are declarative and typed; +- one factory owns cross-cutting adapter behavior; +- the plugin schema is available to tooling; +- framework migration can be automatic when using the built-in Kysely route; and +- adapter authors do not repeat naming/serialization mechanics. + +What remains weak: + +- with Prisma or Drizzle, Better Auth generates ORM schema that the user must merge/apply; +- the contribution does not own a full independent migration graph and database marker; +- version upgrade/removal/data-retention policy is not a universal contract-space protocol; and +- application-wide target routing is out of scope. + +NetScript lesson: emulate the declaration and adapter-factory ergonomics, but eliminate the +“generate this then manually integrate/migrate it” boundary. + +### AdonisJS Lucid + +Lucid's [typed database configuration](https://lucid.adonisjs.com/docs/configuration) defines a +default and named connections, supports read replicas, opens connections lazily, and lets the +framework close them during shutdown. Each connection can own migration paths. Its +[migration system](https://lucid.adonisjs.com/docs/migrations) provides TypeScript up/down classes, +a ledger, transactions, advisory locks, dry runs, safe-mode options, rollback constraints, seed +integration, and a programmatic `MigrationRunner`. `defer` supports data work that should run after +schema operations. + +What works: + +- one framework config names every connection; +- runtime lifecycle belongs to the framework; +- CLI and programmatic runners use the same migration semantics; +- migration locks and transaction behavior are visible; +- connections can have separate migration roots; and +- generated schema types can be refreshed after migrations. + +What remains weak: + +- connection and migration ownership are configured in application files, not composed from + versioned plugin spaces; +- the relational/ORM model remains Lucid-specific; +- cross-connection apply is not globally atomic; and +- type regeneration is still an explicit lifecycle step. + +NetScript lesson: named connections, lazy lifecycle, one programmatic runner, and explicit lock/dry- +run behavior should all be first-class. NetScript can go further by deriving them from one graph and +making stale artifacts impossible to overlook. + +### Drizzle ORM and Drizzle Kit + +Drizzle supports +[code-first, database-first, and external migration workflows](https://orm.drizzle.team/docs/migrations). +`drizzle-kit generate` covers PostgreSQL, MySQL, SQLite, Turso, SingleStore, SQL Server, and +CockroachDB, accepts schema files or folders, checks conflicts, and permits custom SQL migrations. +The [schema declaration guide](https://orm.drizzle.team/docs/sql-schema-declaration) allows schema +split across files as long as all declarations are exported. The +[configuration file](https://orm.drizzle.team/docs/drizzle-config-file) offers schema/table/ +extension filters and multiple project configs. + +What works: + +- broad provider/dialect support; +- schema is ordinary TypeScript and can be split by feature; +- generated SQL remains inspectable and editable; +- database-first and code-first teams can use the same toolkit; +- filters can exclude externally managed objects such as PostGIS tables; and +- multiple configs can represent stages or databases. + +What remains weak: + +- multiple config files are the composition mechanism rather than one typed graph; +- exported declaration aggregation is a developer convention; +- filters express inclusion, not versioned ownership/history; +- extension/plugin migration ordering and removal are not a public framework protocol; and +- generated type/schema lifecycle is user-driven. + +NetScript lesson: retain inspectable SQL, broad adapters, and ownership filters, but make target and +space composition explicit and machine-checkable. + +### MikroORM + +MikroORM's [architecture](https://mikro-orm.io/docs/architecture) separates a database-agnostic core +from provider packages. Official drivers include PostgreSQL, MySQL/MariaDB, SQLite/libSQL, SQL +Server, Oracle, MongoDB, and others. The +[configuration system](https://mikro-orm.io/docs/configuration) registers extensions such as the +migrator, schema generator, entity generator, and seeder without forcing dynamic optional imports. +It supports replicas and attached SQLite databases. + +Its [migrator](https://mikro-orm.io/docs/migrations) is both CLI- and programmatically accessible, +supports transaction/all-or-nothing policy, snapshots, blank migrations, status/pending/check, +fresh/seed, rollup, and target ranges. Runtime schema selection can fan one migration set across +tenant schemas, with explicit documented caveats: shared-instance parallel fan-out is unsupported, +the schema state is reset in `finally`, and MSSQL does not support that runtime schema mode. + +What works: + +- clear core/driver/extension package boundaries; +- broad provider coverage without one monolithic driver; +- extension registration avoids bundler-hostile dynamic loading; +- programmatic operations match CLI operations; +- migration behavior is configurable and observable; and +- provider-specific limitations are documented rather than hidden. + +What remains weak: + +- one ORM instance does not span independent connections; +- parallel schema fan-out requires separate processes/instances; +- entity/schema ownership is still ORM metadata aggregation, not contributor contract spaces; +- feature packages do not naturally carry independent migration histories. + +NetScript lesson: capability documentation and programmatic extension registration are strong +patterns. The graph must instantiate isolated per-target runners and must never share stateful +migration instances across parallel targets. + +### Kysely + +Kysely presents a small type-safe SQL query core. Its +[`Dialect` interface](https://kysely-org.github.io/kysely-apidoc/interfaces/Dialect.html) creates a +driver, adapter, introspector, and compiler; users can implement their own. Official support covers +PostgreSQL, MySQL, SQL Server, SQLite, and PGlite. The [project overview](https://www.kysely.dev/) +emphasizes zero dependencies, cross-runtime execution, raw SQL escape hatches, and optional +migrations. + +The [official `kysely-ctl`](https://github.com/kysely-org/kysely-ctl) is TypeScript-first and +cross-runtime. Its config can accept a dialect or existing Kysely instance and replace migration +providers, migrators, seed providers, and seeders. Kysely's adapter base provides migration-lock +hooks, using native locks where available or a lock table otherwise. + +What works: + +- narrow, open, composable SPIs; +- query core is decoupled from schema generation; +- adapter authors can extend a base with forward-compatible defaults; +- migrations/providers are independently replaceable; +- Deno/Bun/Node are intentional targets; and +- raw SQL is an honest, typed escape hatch. + +What remains weak: + +- type generation/introspection belongs to external tools; +- schema source, migration source, and runtime type source can drift; +- migration authoring is intentionally manual; +- plugin schema ownership is not a built-in concept; and +- framework lifecycle/orchestration is left to the caller. + +NetScript lesson: keep the SPI small and extensible, but do not inherit the fragmented toolchain. +One graph must tie schema, types, migrations, connections, and agent surface together. + +### Atlas + +Atlas is the closest comparator for the database control plane rather than runtime ORM. Its +[project configuration](https://atlasgo.io/atlas-schema/projects) includes a `composite_schema` data +source that loads multiple schemas—from SQL, HCL, ORMs, or external sources—into one graph. Order +expresses dependencies, and multiple sources can extend the same database namespace. + +Its [CI/CD workflow](https://atlasgo.io/guides/evaluation/ci-cd) develops a desired schema, plans a +migration, runs semantic lint/simulation in review, delivers an approved artifact, and applies it. +Atlas exposes drift detection, schema testing, target groups, staged rollout, audit history, and +machine-readable output. Its +[destructive-change policy](https://atlasgo.io/guides/destructive-change-policy) can remove drops +from a plan, fail them deterministically in CI, and enforce deprecation workflows. The +[agent guidance](https://atlasgo.io/guides/ai-tools) treats migration generation, linting, policy, +and testing as a structured agent workflow. + +What works: + +- multiple schema sources become one inspectable graph; +- desired state and versioned migration workflows can coexist; +- semantic lint and policy run before apply; +- approved plans can be promoted across environments; +- drift and deployment history are explicit; +- target groups support database-per-tenant rollout; and +- agent behavior is constrained by deterministic policy. + +What remains weak: + +- runtime query typing/client lifecycle are separate concerns; +- advanced CI/registry/policy features may require a hosted/commercial control plane; +- composite ordering is configuration order unless stronger semantics are layered above it; +- app/plugin packages do not automatically expose a TypeScript contribution factory. + +NetScript lesson: copy the plan-review-deliver-apply state machine, policy gates, drift vocabulary, +receipts, and composed graph semantics. Keep the NetScript core local and provider-neutral; an Atlas +adapter can remain an optional future delivery backend. + +### Django + +Django owns migrations per installed application. Migrations are declarative operation objects, +loaded into a graph, and declare cross-app dependencies. The +[migration operations](https://docs.djangoproject.com/en/5.2/ref/migration-operations/) preserve +historical model state and support custom schema/data operations. The +[migration guide](https://docs.djangoproject.com/en/5.2/topics/migrations/) explains that per-app +execution is best effort because dependencies may require other apps. + +Django's [multiple database](https://docs.djangoproject.com/en/5.2/topics/db/multi-db/) model uses +named aliases and ordered routers for reads, writes, relations, and migrations. Commands operate on +one database at a time through `--database`. Cross-database relations are not supported, and the +documentation warns that changing router behavior can create missing tables, extra tables, broken +foreign keys, or silent migration skips. + +What works: + +- feature/app ownership of migrations is mature; +- dependency graphs compose histories without flattening files; +- historical state allows deterministic migration replay; +- database routing is a first-class policy surface; and +- app removal has an explicit migration/squash/deploy sequence. + +What remains weak: + +- router ordering and `None` fallthrough can be subtle; +- migration refusal can become a silent skip; +- multi-database commands require repeated explicit invocation; +- cross-database relations cannot be made transparent. + +NetScript lesson: adopt per-contributor graphs and explicit dependencies. Reject silent skip: +composition must return a complete target/space decision table, and every omitted operation needs a +reason code. + +### Rails Active Record + +Rails' +[multiple database guide](https://guides.rubyonrails.org/active_record_multiple_databases.html) +supports named databases, primary/replica roles, horizontal shards, automatic/manual connection +switching, per-database migration directories, and a generator `--database` selector. +`database_tasks: false` explicitly marks an external database whose schema/migrations/seeds Rails +must not manage. + +What works: + +- external/unmanaged databases are explicit; +- target identity controls migration folders and generators; +- runtime read/write role and shard switching are framework concepts; +- connection classes provide granular binding. + +What remains weak: + +- ownership is configuration/folder convention rather than a typed graph; +- schema-contributing engines/plugins do not automatically carry isolated migration spaces; +- cross-database associations have caveats; and +- target capability typing is limited. + +NetScript lesson: an explicit `managed: false`-style policy is essential. NetScript should +generalize it into managed/adopted/external/ignored ownership and use stable target IDs for every +artifact. + +## Cross-market capability matrix + +Legend: **strong** means the capability is a primary, documented abstraction; **partial** means it +exists but leaves important manual integration; **none** means it is not a product-level concept. + +| Product | Typed target graph | Plugin/feature schema owner | Independent migration graph | Multi-DB routing | Programmatic control | Semantic CI policy | Agent surface | +| ------------------ | ------------------------ | --------------------------- | --------------------------- | ------------------------- | --------------------- | ------------------- | -------------------- | +| Wasp | Partial | Partial | None | None | Partial | None | Partial | +| RedwoodJS | Partial | None | Partial (data ledger) | None | Partial | None | Partial | +| Payload | Partial | Partial | Partial | Partial | Partial | None | Partial | +| Better Auth | Partial | Strong declaration | None | Partial | Partial | None | Partial | +| Adonis Lucid | Strong named connections | Partial | Per connection | Strong | Strong | Partial | Partial | +| Drizzle | Partial/multi-config | Partial file exports | Per config | Partial | Strong | Partial | Partial | +| MikroORM | Strong per instance | Partial metadata | Per instance/schema | Partial | Strong | Partial | Partial | +| Kysely | Open dialect config | None | Replaceable provider | Caller-owned | Strong primitives | None | None | +| Atlas | Strong control graph | Strong source composition | Strong | Strong target groups | Strong | Strong | Strong | +| Django | Strong aliases/routers | Strong apps | Strong | Strong but one-at-a-time | Strong | Partial | Partial | +| Rails | Strong named DB/roles | Partial engines | Per database | Strong | Strong | Partial | Partial | +| Proposed NetScript | Strong, single graph | Strong contract spaces | Strong per space/target | Strong capability routing | Strong structured API | Strong local policy | Generated from graph | + +## Design patterns to import + +### 1. One framework graph, not many config files + +Adonis, Rails, and Django prove stable named connections are understandable. Atlas proves multiple +schema sources can be composed. NetScript should combine them: + +```text +defineDatabaseGraph({ + targets: { + primary: databaseTarget(...), + analytics: databaseTarget(...), + }, + contributions: [ + appDatabase(...), + auth.database(...), + billing.database(...), + ], +}); +``` + +The graph must resolve to a deterministic manifest before runtime or database access. + +### 2. Contributor-owned migration spaces + +Django's per-app graph and Prisma 8's contract spaces are the strongest ownership models. Each +contributor needs: + +- stable ID and version; +- target-selection predicate; +- provider/capability requirements; +- owned contract artifact; +- migration graph and head; +- dependencies; +- data transforms/invariants; +- ownership policy; +- removal/data-retention policy; and +- provenance/signature. + +The app consumes pinned mirrors; installation never mutates another contributor's source. + +### 3. A factory that owns adapter mechanics + +Better Auth and Kysely show how to make extension authors productive: a small factory/base +centralizes naming, lifecycle, serialization, errors, and compatibility. NetScript target authors +should supply only provider-specific capabilities and bindings, then pass a conformance kit. + +### 4. Plan is the deployment contract + +Atlas's develop/review/deliver/apply model should govern every mutating NetScript database +operation: + +```text +compose -> inspect -> plan -> policy/lint/test -> approve -> apply -> verify -> receipt +``` + +The approved artifact binds graph digest, target, environment, live baseline, operations, package +versions, and expiry. Apply refuses drifted inputs. + +### 5. Managed and external ownership are different + +Rails' `database_tasks: false`, Drizzle filters, Atlas external sources, and Prisma's Supabase drift +incident all point to the same requirement. NetScript must never treat every visible object as +framework-owned. + +### 6. Capability-specific APIs beat false portability + +MikroORM and Django document provider differences; Kysely exposes dialect behavior; Prisma separates +families and targets. NetScript should expose common lifecycle/control concepts but capability-gate +provider-specific query and migration features. + +### 7. Programmatic core, CLI and agents as projections + +Adonis, MikroORM, Kysely, and Atlas expose programmatic runners. NetScript commands should call one +typed operation API. Help, JSON schema, documentation, and agent skills should be generated views of +that operation catalog. + +## Anti-patterns to reject + +The market analysis reinforces explicit rejection of: + +- forwarding an upstream ORM CLI as the NetScript architecture; +- generated schema that still requires a manual merge or second migrate command; +- multiple same-provider databases represented by copied config files and engine folders; +- plugin installation that copies schema into the application; +- silent router/filter/selector skips; +- a universal singleton client; +- “supports multiple databases” that means only repeated manual commands; +- generated code repaired by string replacement; +- data transforms sequenced independently from structural migration state; +- shared stateful migration runners used concurrently; +- database-specific behavior hidden behind an over-broad generic repository; and +- agent instructions maintained separately from the real command/type surface. + +## Proposed market position + +NetScript can plausibly offer a distinctive database story: + +> Declare every database target and schema contributor once. NetScript composes and validates the +> graph, provisions connections, emits only canonical artifacts, binds typed runtime sessions, plans +> and verifies every migration, and gives humans, CI, plugins, and agents the same structured +> view—without copied schemas, patched clients, or hidden manual steps. + +That is materially more than a Prisma wrapper. It is a meta-framework control and composition layer +whose first high-fidelity runtime/control adapter is Prisma 8 PostgreSQL. + +## Primary source register + +- Wasp: [entities](https://wasp.sh/docs/0.20/data-model/entities), + [databases](https://wasp.sh/docs/data-model/databases), + [auth entities](https://wasp.sh/docs/auth/entities) +- RedwoodJS: [data migrations](https://docs.redwoodjs.com/docs/data-migrations), + [CLI commands](https://docs.redwoodjs.com/docs/cli-commands), + [database seeds](https://docs.redwoodjs.com/docs/database-seeds/) +- Payload: [database adapters](https://payloadcms.com/docs/database/overview), + [migrations](https://payloadcms.com/docs/database/migrations) +- Better Auth: [database](https://better-auth.com/docs/concepts/database), + [plugins](https://better-auth.com/docs/beta/concepts/plugins), + [adapter factory](https://better-auth.com/docs/beta/guides/create-a-db-adapter) +- AdonisJS Lucid: [configuration](https://lucid.adonisjs.com/docs/configuration), + [migrations](https://lucid.adonisjs.com/docs/migrations) +- Drizzle: [migration workflows](https://orm.drizzle.team/docs/migrations), + [generate](https://orm.drizzle.team/docs/drizzle-kit-generate), + [migrate](https://orm.drizzle.team/docs/drizzle-kit-migrate), + [schema declaration](https://orm.drizzle.team/docs/sql-schema-declaration), + [configuration](https://orm.drizzle.team/docs/drizzle-config-file) +- MikroORM: [architecture](https://mikro-orm.io/docs/architecture), + [configuration](https://mikro-orm.io/docs/configuration), + [multiple schemas](https://mikro-orm.io/docs/multiple-schemas), + [migrations](https://mikro-orm.io/docs/migrations) +- Kysely: [overview](https://www.kysely.dev/), + [Dialect SPI](https://kysely-org.github.io/kysely-apidoc/interfaces/Dialect.html), + [adapter base](https://kysely-org.github.io/kysely-apidoc/classes/DialectAdapterBase.html), + [official CLI](https://github.com/kysely-org/kysely-ctl) +- Atlas: [project/composite schema](https://atlasgo.io/atlas-schema/projects), + [CI/CD](https://atlasgo.io/guides/evaluation/ci-cd), + [destructive policy](https://atlasgo.io/guides/destructive-change-policy), + [agent workflow](https://atlasgo.io/guides/ai-tools), + [database-per-tenant control plane](https://atlasgo.io/guides/database-per-tenant/control-plane) +- Django: [migrations](https://docs.djangoproject.com/en/5.2/topics/migrations/), + [migration operations](https://docs.djangoproject.com/en/5.2/ref/migration-operations/), + [multiple databases](https://docs.djangoproject.com/en/5.2/topics/db/multi-db/), + [application removal](https://docs.djangoproject.com/en/5.2/howto/delete-app/) +- Rails: [multiple databases](https://guides.rubyonrails.org/active_record_multiple_databases.html) diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md new file mode 100644 index 0000000000..baf8564d7d --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md @@ -0,0 +1,295 @@ +# NetScript Database Current-State Audit + +## Scope and baseline + +- Repository: `rickylabs/netscript` +- Baseline: `origin/main` at `cd720529333328bcba5e1a308ce7632f4350efdf` +- Audit date: 2026-08-13 +- Package dependency baseline: Prisma `7.8.0` in the root catalog/lock; generated workspaces still + encode `^7.4.2` specifiers. +- Sources: current source and docs, architecture-debt ledger, Git history, GitHub issue/PR evidence, + and focused `deno doc`/dependency-tool inspection. + +This document describes the system that exists. It does not carry forward the compatibility-first +solution from issue [#313](https://github.com/rickylabs/netscript/issues/313). + +## Executive finding + +NetScript does not currently have one database architecture. It has five partially-overlapping +systems whose identities and ownership rules do not line up: + +1. an appsettings/Aspire database-resource model; +2. a fixed CLI engine registry and operation runner; +3. a generated per-engine Prisma workspace and task graph; +4. a runtime adapter wrapper around user-constructed Prisma clients; and +5. an install-time plugin Prisma-fragment copier. + +The happy path works only after those systems agree on config keys, engine directory names, +environment variables, generated files, Prisma CLI behavior, adapter packages, and a live Aspire +resource graph. The framework makes that agreement a developer and CI responsibility, then adds +post-generation repair scripts where upstream output does not fit Deno/browser expectations. + +The redesign therefore cannot be a Prisma version substitution. The missing foundation is one +NetScript-owned, typed, inspectable database graph from which resource provisioning, schema +composition, client construction, generated imports, migrations, validation artifacts, plugin +contributions, diagnostics, and CI plans are derived. + +## Present topology + +```text +appsettings.json + NetScript.PrimaryDatabase + NetScript.Databases. + | + +--> Aspire helpers/resources and allocated connection values + | + +--> DbWorkspaceResolver + configKey -> fixed DbEngine -> database// + | + +--> per-engine deno.json tasks + +--> prisma.config.ts + +--> schema/**/*.prisma + +--> migrations/ + +--> scripts/* + +--> schema/.generated/* + | + +--> generated engine mod.ts + +--> deep user imports / @database/zod + +plugin package database/**/*.prisma + | + +--> package/source resolution + +--> install-time file copy + +--> regex declaration collision scan + +--> database//schema/plugins//*.prisma +``` + +There is no canonical graph or manifest joining these views. The effective configuration is spread +across `appsettings.json`, the root workspace list, a generated database `deno.json`, +`prisma.config.ts`, schema files, generated Aspire helpers, generated engine modules, environment +variables, plugin package metadata, and generated output. + +## Identity model and its limitations + +| Identity | Current representation | Consequence | +| ------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------- | +| Logical target | `NetScript.Databases.` | Used for CLI selection and Aspire resource lookup. | +| Primary target | `NetScript.PrimaryDatabase` | Used by Aspire/service wiring, but ignored by `DbWorkspaceResolver.resolveTarget`. | +| Engine | Closed union: `postgres | mysql | +| Schema workspace | `database//` | Multiple same-engine targets share one schema, client, migrations, and tasks. | +| Physical database | `DatabaseName` plus Aspire resource | Coupled to config and provisioning mode. | +| Prisma datasource | One `datasource db` per generated workspace | Not a first-class NetScript object. | +| Generated client | Deep path under `schema/.generated/client.server.ts` | User code can import the wrong target or a stale artifact. | +| Plugin schema owner | Installed file path under `schema/plugins/` | Ownership is filesystem-derived, not a versioned contribution contract. | + +Two correctness gaps follow directly from this model: + +- `db add postgres --name analytics` creates another config target but still renders and resolves + `database/postgres/`. It cannot represent two PostgreSQL databases with independent schemas or + migration histories. The public second-database guide currently claims otherwise. +- With more than one enabled target, omitting `--db` does **not** resolve + `NetScript.PrimaryDatabase`; `resolveTarget` only defaults when exactly one target exists. This + conflicts with current documentation that says a bare command targets the primary database. + +## Public and generated runtime surfaces + +### `@netscript/database` + +The root package currently exposes: + +- tracing activation (`enableInstrumentation` / tracing subpath); +- generic adapter/status/connection/transaction types; +- the PostgreSQL adapter on the root and adapter barrel; +- MySQL and MSSQL adapters on explicit subpaths; +- JSON field extensions; +- a structurally-cast `withTransaction` helper; and +- connection-string parsers/builders. + +The central `DatabaseAdapter` port owns client lifecycle, health, status, and raw query +methods. Concrete adapters do not construct the client. The user must: + +1. create the NetScript wrapper; +2. ask it for a Prisma driver adapter; +3. construct the schema-generated `PrismaClient` with that driver; +4. pass the client back through `setClient`; and only then +5. call connect, health, status, or raw-query methods. + +This is circular assembly. The wrapper is neither a driver adapter nor an owning database factory, +and unsupported Prisma drivers bypass its lifecycle entirely. + +### Generated database package + +Each engine workspace generates another facade with its own singleton, connection resolution, driver +selection, health query, exported Prisma client symbols, and `DB` type. This duplicates the +published adapter layer rather than composing it. Applications and docs also import generated Prisma +clients by physical path. + +The generated package exposes `./zod` from generated output. Root workspace aliases and generated +contract templates depend on precise, hand-maintained generated symbol names. Issues +[#1254](https://github.com/rickylabs/netscript/issues/1254) and +[#1290](https://github.com/rickylabs/netscript/issues/1290) show that changing the barrel target +first hid models and then broke clean scaffolds at type-check and startup time. + +### Custom MySQL Prisma adapter + +`@netscript/prisma-adapter-mysql` implements Prisma's low-level `SqlDriverAdapter` contracts and +conversion/error/transaction behavior itself. It imports upstream unstable driver-adapter utility +types and `mysql2/promise`; comments still describe an earlier Deno MySQL implementation. This is a +large upstream-coupled maintenance surface, not merely a thin NetScript integration adapter. + +## CLI and lifecycle + +The CLI exposes fourteen verbs: add, list, remove, init, generate, migrate, seed, status, studio, +introspect, reset, deploy, validate, and resolve. + +The operation path is: + +1. parse `appsettings.json`; +2. map a closed engine enum to a fixed provider registry; +3. derive workdir as `database/`; +4. require the resident Aspire AppHost for every shared operation, including pure generation; +5. materialize an operation-request JSON file; +6. explicitly start `netscript-db-` inside the resident graph; +7. have that resource invoke a generated `deno task db::`; +8. poll Aspire until terminal, fetch logs, stop the resource, remove the request, and release a + filesystem lock. + +Important behavior: + +- `--db all` is sequential and fail-fast; there is no complete per-target result or resumable plan. +- Studio silently executes only the first resolved target. +- Pure `generate` is Aspire-coupled even though the generated workspace task can run without a + database. `DB-GENERATE-ASPIRE-COUPLING` remains open architecture debt. +- `db add` scaffolds and rewrites config/helpers, but intentionally does not migrate, generate, or + seed. Users must restart/reload orchestration and run the lifecycle steps themselves. +- The engine registry is a registry in implementation shape only. Its key type is closed, its + providers contain hard-coded template switches, and operation commands instantiate their own + default resolver/runner. Third-party database support cannot be contributed as a coherent public + capability. + +## Generation and repair pipeline + +A generated engine workspace contains at least: + +- `deno.json` with more than twenty database tasks and duplicated Prisma version specifiers; +- `prisma.config.ts` with connection-string normalization; +- a generated engine `mod.ts` with driver/client/tracing/lifecycle code; +- `schema/schema.prisma`; +- a seeded placeholder generated client; +- migrations and seed directories; +- Zod generator config in two locations; and +- clear-placeholder, migrate, generate-Zod, fix-Zod, and patch-client scripts. + +The nominal `db:generate` pipeline performs: + +1. placeholder removal; +2. Prisma client generation; +3. a second Prisma generation through the Zod wrapper; +4. generated Zod import rewriting; +5. circular-reference rewriting; +6. getter-pattern rewriting; +7. decimal compatibility rewriting; +8. a generated CRUD alias barrel; +9. Prisma client renaming/facade patching; and +10. another outer fix-Zod pass. + +The result is non-atomic generated source that NetScript mutates based on upstream textual output. +Users can edit the schema without running the pipeline and continue compiling against stale types. +Multi-database projects multiply this state and expose physical generated paths to consumers. + +## Plugin contribution model + +Plugins declare schema by shipping plain `database/**/*.prisma` files. During installation the CLI: + +- discovers or downloads package fragments; +- chooses one database target (explicit, primary-ish, or first available); +- copies each fragment into the consumer's active schema tree; +- scans top-level `model`, `enum`, `type`, and `view` blocks using a custom regex/balanced-brace + parser; +- removes byte-normalized identical declarations; and +- rejects same-name declarations with different normalized bodies. + +What this model does not express: + +- contribution contract or schema version; +- supported providers/capabilities; +- target selection policy beyond install-time flags; +- dependency ordering or contribution dependencies; +- declaration ownership and allowed augmentation; +- migration ownership, rollout, rollback, or data transforms; +- generated validator/client requirements; +- uninstall data policy; +- compatibility with an existing database version; +- deterministic graph digest/provenance; or +- a programmatic contributor test kit. + +The filesystem assumption already caused dependency-mode installs to report success while omitting +all plugin tables ([#1014](https://github.com/rickylabs/netscript/issues/1014)). Model-name clashes +then broke authentication installs and required namespacing plus a custom collision guard +([PR #1059](https://github.com/rickylabs/netscript/pull/1059)). The removal path deletes the copied +schema directory; it does not plan or execute a safe database migration. + +## Recurrent failure classes + +Path-scoped Git history since 2026-06-01 contains 30 `fix*` commits touching the database package, +custom adapter, CLI database kernel/templates, schema writer, or database E2E gate (release commits +excluded from that count). The audited implementation/test/template surface is about 9,175 lines. +The number is descriptive, not a quality metric; the failure history is the stronger evidence. + +| Failure class | Evidence | Architectural lesson | +| ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| Prisma schema-engine crash/hang on Windows | [PR #98](https://github.com/rickylabs/netscript/pull/98), [PR #145](https://github.com/rickylabs/netscript/pull/145), retry/timeout code in `migrate.ts` | NetScript CI owns upstream subprocess lifecycle and flake classification. | +| SQLite facade compiled only against placeholder, failed after real generation | [#173](https://github.com/rickylabs/netscript/issues/173) | Stubs and generated-client contracts can diverge; every capability axis needs generated-project proof. | +| Plugin schema silently absent in dependency installs | [#1014](https://github.com/rickylabs/netscript/issues/1014) | Source-layout discovery is not a contribution contract. | +| Plugin/base model collision | [PR #1059](https://github.com/rickylabs/netscript/pull/1059) | Global Prisma declaration namespace needs explicit ownership and conflict semantics. | +| Read-only DB command killed resident AppHost | #1011 / [PR #1088](https://github.com/rickylabs/netscript/pull/1088) | Database operations lacked a stable lifecycle owner. | +| Ephemeral AppHost leaked and masked the real host | [#1196](https://github.com/rickylabs/netscript/issues/1196), [PR #1301](https://github.com/rickylabs/netscript/pull/1301) | Fixing lifecycle symptoms without one operation model moved the failure. | +| Second AppHost mounted live PGDATA and corrupted it | [#1310](https://github.com/rickylabs/netscript/issues/1310), [PR #1311](https://github.com/rickylabs/netscript/pull/1311) | Resource reconstruction is unsafe; operations must bind an authoritative graph. | +| Stale allocated Postgres endpoint | [#1202](https://github.com/rickylabs/netscript/issues/1202), [PR #1393](https://github.com/rickylabs/netscript/pull/1393) | Runtime connection provenance must be inspectable and validated against the live allocation. | +| Headless migrate returned success without an artifact | [#1327](https://github.com/rickylabs/netscript/issues/1327), [PR #1393](https://github.com/rickylabs/netscript/pull/1393) | Exit code is insufficient; operations need typed plans and artifact/state postconditions. | +| Multi-model Zod alias hid symbols, then its repair broke startup | [#1254](https://github.com/rickylabs/netscript/issues/1254), [#1290](https://github.com/rickylabs/netscript/issues/1290) | Generated symbol paths cannot be the framework contract. | +| Split Zod module instances broke schema interoperability | [#1295](https://github.com/rickylabs/netscript/issues/1295) | Validation must use a standards-facing contract and controlled dependency boundary. | + +The most severe lifecycle bug cost a measured pilot hours, two database resets, and a privileged +host scrub. The final artifact-proof repair in PR #1393 took six serialized `scaffold.runtime` +attempts as successive test-harness assumptions surfaced. This is exactly the CI instability the new +design must structurally retire. + +## Architecture-debt alignment + +- `packages/database — AP-17` remains open: ports were renamed, but the composition root has never + been resolved. +- `DB-GENERATE-ASPIRE-COUPLING` remains open and documents the pure-codegen/Aspire mismatch. +- Current doctrine classifies `packages/database` as an A2 integration package needing refactor and + `packages/prisma-adapter-mysql` as an A2 integration package. The new owner directive supersedes + the old recommendation to preserve the existing database port unchanged. +- Auth roadmap item R1 independently requires deterministic plugin-aware schema and migration + generation; this RFC must make that an ordinary contribution, not an auth-specific escape hatch. + +## What is worth preserving as evidence, not API compatibility + +- Explicit subpaths keep heavy engine dependencies out of unrelated consumers. +- Artifact-first migration verification is correct and should become a general operation contract. +- Resident-resource binding fixed the unsafe duplicate-AppHost model. +- Deterministic provider registries and generated composition roots match doctrine in principle. +- Plugin schema conflicts now fail rather than silently overwrite. +- Engine-specific behavior is real and must remain capability-visible; a lowest-common-denominator + database API would be a regression. + +These are invariants to re-express in the new architecture. They do not justify retaining current +package names, ports, generated paths, task names, or runtime shims. + +## Clean-break implications + +The RFC design must make the following impossible or mechanically detectable: + +1. editing a database definition without refreshing the effective client/validator/schema graph; +2. constructing a driver, client, and lifecycle wrapper in the wrong order; +3. importing a client by its generated filesystem path; +4. running an operation against an implicit or ambiguous target; +5. reporting success without proving planned artifacts and database state; +6. copying an unversioned plugin fragment without capability/conflict/migration analysis; +7. representing two logical databases as one accidental engine directory; +8. adding an engine by editing switches across CLI, templates, Aspire, packages, docs, and CI; +9. requiring Aspire/Docker for pure compilation; and +10. patching upstream generated text as an undocumented permanent compatibility layer. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md new file mode 100644 index 0000000000..bbc6516be9 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md @@ -0,0 +1,653 @@ +# Prisma 8 / Prisma Next Deep Dive + +## Research pin and confidence model + +This audit deliberately separates three upstream states that must not be conflated: + +| State | Pin | Why it matters | +| ----------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| Announced release | [`v8.0.0-rc.1`](https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1), published 2026-08-07 | The version named by the NetScript RFC request. | +| RC source | [`a76a6c5`](https://github.com/prisma/prisma/tree/a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5) | Reproducible basis for package, runtime, migration, skill, and scorecard claims. | +| Upstream main | [`71e2e0d`](https://github.com/prisma/prisma/tree/71e2e0d9ee1f306b5a11435cd1973023cb33866a), observed 2026-08-13 | Six days of post-RC changes that reveal which integration seams are still moving. | + +Prisma calls this release Early Access and explicitly does not recommend it for production +workloads. The RC source requires Node.js 24+, declares TypeScript 5.9 as the package peer floor, +and describes PostgreSQL as the sole database intended for 8.0 GA. MongoDB remains Early Access, +SQLite is a proof of concept, MySQL follows later, and SQL Server is not present in the Prisma 8 +target set. + +The analysis below uses this confidence vocabulary: + +- **implemented**: an observable public or source-level implementation exists; +- **proven**: Prisma's RC scorecard cites a real-database integration test; +- **untested**: reachable through a public surface but not proven by the scorecard's + integration-test standard; +- **absent**: the RC scorecard explicitly says the capability is not in 8.0; +- **moving**: the relevant surface changed on `main` after the RC tag; +- **NetScript gate**: NetScript must prove the behavior independently before adopting it. + +## Executive conclusion + +Prisma 8 is not Prisma 7 with a new client generator. It is a TypeScript database framework built +around a canonical data contract, composable family/target/adapter/driver/extension descriptors, +structured query and migration plans, and separate control and execution planes. The generated +executable `PrismaClient` disappears. The durable emitted artifacts are a canonical `contract.json` +and a type declaration; a small runtime facade consumes the contract. + +That direction directly attacks several NetScript pain points: + +- generated executable client source can disappear; +- source-rewriting and Zod repair passes can disappear; +- schema ownership can be modeled rather than inferred from copied files; +- migrations can be planned and verified through a programmatic API; +- structured results and errors can replace log scraping; and +- database families, targets, adapters, drivers, and extensions are distinct axes. + +It is not yet a safe foundation to expose directly. The RC's public package surface is extremely +wide, its CLI/config distribution changed materially within six days, important runtime and +migration cells remain unproven, the project skill contains stale internal imports and behavioral +contradictions, and the only 8.0 GA target is PostgreSQL. NetScript should therefore adopt the +contract/control/runtime architecture, wrap a deliberately narrow upstream seam, and make release +adoption conditional on a NetScript-owned conformance suite. + +## The architecture that actually replaces Prisma 7 + +The source is arranged as layers rather than as one client package: + +```text +authoring source (.prisma or TypeScript DSL) + | + v +family + target + extension lowering + | + v +canonical contract.json + contract.d.ts + domain plane storage plane hashes/profile + | + +---------+---------+ + | | + v v + control plane execution plane + plan / diff / emit SQL DSL / ORM / raw + migrate / verify middleware / codecs + introspect / sign driver / transaction +``` + +The important decomposition is: + +| Axis | Meaning | NetScript consequence | +| -------------- | --------------------------------------------------------------- | ----------------------------------------------------------- | +| Family | Shared semantics, such as SQL versus Mongo | Do not use “engine” as the only discriminator. | +| Target | Concrete database behavior, such as PostgreSQL | Provider capabilities belong to a target descriptor. | +| Adapter | Lowers framework operations into target operations | NetScript must not reimplement this SPI unless certified. | +| Driver | Owns wire connectivity and lifecycle | Driver choice is distinct from database target. | +| Extension | Adds authoring, contract, control, execution, codecs, or schema | Contributions need declared capabilities and compatibility. | +| Contract space | One contributor's owned contract and migration history | Plugin schema ownership becomes first-class. | + +The framework core composes descriptors into control and execution stacks. Component descriptors +carry family and target identity, and their instances contribute capabilities. The source checks +several duplicate-ownership conditions, such as conflicting codec or authoring constructs, while +capability-value merging itself is last-writer-wins. NetScript must therefore validate contribution +identity and collisions before handing a resolved stack to Prisma; upstream merge order alone is not +a sufficient plugin policy. + +### Public packages and coupling risk + +The RC publishes facade, framework, family, target, toolchain, and extension packages under +`@prisma/orm-*`. `@prisma/orm-postgres` is described as the one package an application installs, but +its export map contains more than one hundred subpaths spanning adapters, control internals, +contract internals, migration tooling, query ASTs, runtime, target planning, and utilities. It also +depends on `pg`. + +This is useful for extension authors and dangerous for a meta-framework: + +- a direct NetScript re-export would turn upstream RC internals into NetScript public API; +- deep imports would make upstream refactors consumer-breaking; +- a duplicate component/engine package can become a runtime correctness problem; +- Node-oriented driver dependencies can silently leak into Deno/browser graphs. + +The integration boundary should therefore be one private NetScript package with an allowlist of +upstream imports and a dependency check that fails on every newly introduced deep import. + +## Contract-first emission + +### What is emitted + +Prisma 8 compiles PSL or a TypeScript builder into: + +- canonical `contract.json`, used by tooling and runtime; +- `contract.d.ts`, carrying the type-level contract; and +- a very small application facade that imports the two artifacts. + +This is the inverse of the Prisma 7 model: executable client implementation is not the generated +artifact. The runtime is a versioned package and the contract is data. The architecture explicitly +calls this “types-only emission.” + +Consequences for NetScript: + +1. Generated output can be content-addressed and atomically replaced. +2. A clean build can compare a graph digest rather than patch generated TypeScript. +3. Multiple targets can emit independently when their output directories are distinct. +4. Framework validation, docs, agent context, and CI can consume the same canonical graph. +5. Runtime upgrades do not require regenerating an executable client unless the contract format + itself changes. + +### Contract planes and hashes + +The unified contract separates domain structure from physical storage structure. Storage is +namespace-aware and uses an open entry-kind dictionary, allowing a target or pack to add target-only +entities. Prisma computes distinct identities for storage, execution, and profile concerns. +Migration identity is storage-based; runtime plans carry the storage hash and, when present, profile +hash. + +This separation is valuable, but NetScript must not make raw upstream hash fields its own long-lived +public identifiers. The RC upgrade recipes show contract canonicalization and hash representation +changing across pre-release versions. NetScript should record: + +- its own database-graph digest; +- the exact upstream package set and contract format version; +- each target's upstream storage/profile hashes; and +- the resolved contributor provenance. + +That lets NetScript explain drift without treating one upstream digest as the identity of the whole +application database graph. + +### Authoring modes + +Prisma supports PSL and a TypeScript contract builder. Both lower to the same contract model. The +TypeScript route provides immediate `typeof contract` inference; PSL relies on emitted declaration +artifacts and has a language server. + +NetScript should not invent a third database model DSL. It should provide a composition DSL for +targets, spaces, policies, routing, capabilities, and lifecycle while allowing the application +contract source to remain Prisma PSL or TypeScript. A NetScript plugin contribution should point at +or construct a contract space; it should not concatenate Prisma syntax. + +## Runtime surface + +The PostgreSQL facade consumes `contractJson` and returns a contract-typed runtime with: + +- `sql`: structured SQL builder; +- `orm`: model-oriented collection API; +- `raw`: escape hatch; +- `enums` and `nativeEnums`; +- `context` and `stack`; +- `connect` / `close`; +- `runtime` for lower-level access; +- `transaction`; and +- `prepare`. + +The serverless facade is intentionally asymmetric. It creates an async-disposable runtime per +request and omits closure-cached `orm`, `runtime()`, and `transaction()` surfaces that would be +unsafe in that lifecycle. This is a strong precedent for NetScript: runtime capability types should +reflect deployment mode rather than promising one universal client. + +### What NetScript should expose + +Application features should not receive the Prisma facade globally. They should receive +consumer-owned ports or an explicitly typed target reference: + +```ts +export interface AccountStore { + findByEmail(email: string): Promise; + save(account: Account): Promise; +} + +export const accountsDatabase = dbRef<'primary', AppDatabaseContract>(); +``` + +The application composition root can bind that reference to the Prisma 8 runtime. A feature that +truly needs the query surface may depend on a NetScript-owned `DatabaseSession` view; +most domain code should depend on a narrower feature port. This preserves query power without making +Prisma a framework-wide service locator. + +### Lifecycle implications + +Prisma separates long-lived, static, and serverless runtime shapes. NetScript must own: + +- target resolution; +- connection-source resolution; +- one lifecycle owner per runtime instance; +- request versus process scope; +- graceful close ordering; +- health/readiness semantics; +- transaction/session scoping; and +- observability middleware. + +It must not restore the current circular sequence in which a wrapper creates a driver, the user +creates a client, and the client is set back onto the wrapper. + +## Programmatic control plane + +The RC publishes `createControlClient` from `@prisma/orm-toolchain/cli/control-api`. It accepts +family, target, adapter, optional driver, extensions, and an optional connection. It can initialize +without a live driver for offline work and exposes domain operations for: + +- contract verification and emission; +- schema verification; +- database signing; +- `dbInit` and `dbUpdate` in plan/apply modes; +- migration planning/application; +- introspection; and +- lifecycle connect/close. + +Progress is modeled as nested start/end spans. Operations return structured results and dotted-code +errors instead of requiring terminal log parsing. The control client intentionally uses `any` at +descriptor variance boundaries; NetScript should type the resolved descriptors before that boundary +and contain the cast inside its integration package. + +Current `main` strengthens this seam: migration and database commands were routed through the +control API; output channels and typed next actions became explicit; a ControlClient test double was +added; and command-independent operations were exported. This makes the programmatic seam the +correct integration direction, while simultaneously proving that exact package paths and option +shapes are still moving. + +### Operation classification + +NetScript should classify operations before invoking Prisma: + +| Class | Examples | Required context | +| --------------- | -------------------------------------------------------------------------- | ------------------------------------------------- | +| Pure/offline | compose graph, validate ownership, emit, format, migration integrity check | Source tree only; never Aspire. | +| Live/direct | inspect, plan against live state, verify, status | Target connection; no resident app required. | +| Mutating/direct | initialize, apply migrations, sign, seed | Target connection, lock, consent policy, receipt. | +| Resident-only | operations whose connection exists only inside AppHost resource binding | Aspire session, explicitly selected. | + +The current NetScript rule that routes even generation through a resident AppHost must not survive. + +## Migration system + +### Graph, refs, marker, and ledger + +Prisma 8 models migrations as graph edges between storage hashes rather than only timestamped steps. +Named refs identify graph nodes. Contract snapshots are content-addressed. Each contract space has +its own marker state, and the migration ledger records applied edges. PostgreSQL and SQLite source +and tests implement the ledger; Mongo participates with target-specific atomicity semantics. + +For transactional SQL, the edge execution and ledger update are transactionally coupled. Mongo DDL +cannot rely on a multi-document transaction, so it verifies the destination before advancing the +marker and diagnoses partial state. + +This is a stronger model than NetScript's current “call the generated task and inspect logs,” but it +is not a distributed transaction system. Applying two different database targets can never be +globally atomic. NetScript needs a run receipt with per-target phases, idempotent resume, and +explicit partial-success reporting. + +### Plans and destructive consent + +`dbInit` and `dbUpdate` separate plan from apply. Destructive operations require explicit consent, +and structured errors can carry the destructive operation list. Current `main` further distinguishes +findings from execution errors and assigns different exit behavior. + +NetScript should add policy above consent: + +- an interactive “yes” is never enough in CI; +- production plans need a signed graph digest and environment binding; +- provider capability and transaction behavior must be visible; +- destructive operations need a deterministic policy decision; +- data-loss warnings require data-aware preflight where feasible; and +- apply must reject a plan if the graph, live baseline, package set, or target changed. + +### Data migrations + +Prisma models data transforms as invariant-guarded transitions. A transform declares a precondition +query that detects remaining work and a mutation plan; the runner verifies the invariant afterward. +The destination identity includes the required invariants. This is a sound foundation for resumable, +auditable data movement. + +The authoring experience is not finished. Planner output can leave placeholders in generated +`migration.ts` files that a developer must fill. The upstream multi-extension example still imports +contract/head/migration artifacts manually and uses several `as unknown` casts. NetScript should +preserve the invariant model but generate descriptor wiring, references, and contributor packaging +from its graph. + +### Important absent or weak migration capabilities + +The RC scorecard marks or reveals gaps that matter to NetScript: + +- no mature reset/resolve/diff/execute/squash workflow comparable with Prisma 7; +- no general shadow-database workflow; +- no complete advisory-lock story across targets; +- no row-count-aware data-loss analysis; +- no comprehensive diagnosis for unexecutable changes or unique constraints over dirty data; +- views absent from the 8.0 feature surface; +- raw migration operation coverage unproven; +- PostgreSQL and SQLite `dataTransform` integration coverage unproven; +- many individual destructive PostgreSQL operations unproven; and +- extension removal is unsupported. + +NetScript must not paper over these with shell scripts. Every required operation needs either an +upstream-proven capability, a NetScript implementation behind a target adapter, or an explicit +unsupported diagnostic. + +## Contract spaces: the key plugin concept + +[ADR 212](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20212%20-%20Contract%20spaces.md) +defines each contributor as a disjoint tuple: + +```text +(contract.json, migration graph, head ref) +``` + +The application owns one space. Each schema-contributing extension owns another. The consumer repo +contains a pinned mirror of extension artifacts, so production apply/verify does not need to import +`node_modules`. The database marker stores one row per space. The verifier aggregates spaces in +memory and rejects overlapping storage ownership. + +This solves the central semantic failure in NetScript's copied-fragment model: schema contribution +is a versioned owner with history, not a file copied into someone else's schema. + +### What contract spaces do and do not solve + +They provide: + +- one owner per storage object; +- independent migration histories; +- pinned consumer-side artifacts; +- per-space plan/run/verify; +- cross-space foreign-key declarations; +- extension-controlled schema versus app-controlled schema; and +- a basis for dependency ordering and removal diagnostics. + +They do not provide: + +- one merged on-disk contract; +- cross-database atomicity; +- transparent cross-database relations; +- runtime traversal across spaces as a complete ORM feature; +- extension removal/data-retention policy; +- automatic author descriptor packaging; +- a NetScript target-selection policy; or +- stable compatibility across arbitrary extension/core versions. + +The RC ADR text also contains stale layout and command statements relative to later source. Source +implements topological extension dependency ordering even where older ADR prose says dependency +ordering is deferred. NetScript's design must pin behavior to tests and package versions, not copy +upstream prose as an executable contract. + +### External ownership and drift + +Issue [#29896](https://github.com/prisma/prisma/issues/29896) shows a hosted Supabase database +failing `db verify` because a pinned extension contract and externally evolving tables diverged. The +workaround was effectively marker-only. This is not an edge case for NetScript plugins; it is the +normal shape of managed services. + +NetScript contributions therefore need an ownership policy: + +- `managed`: NetScript may plan and apply the object; +- `adopted`: NetScript verifies selected properties and can establish a baseline; +- `external`: another system owns lifecycle; NetScript records capabilities and allowed drift; +- `ignored`: deliberately excluded with an auditable reason. + +That policy belongs on each contract space or owned object set and must influence diff, plan, +verification, removal, and agent instructions. + +## Multiple schemas, databases, and engines + +Prisma's contract is namespace-aware, and the PostgreSQL runtime proves multi-namespace access. +Cross-space foreign keys can target another contributor's table in the same physical database. + +A Prisma config/control stack still describes one target and connection. Multiple independent +databases require a framework-level graph above Prisma. NetScript must model at least: + +```text +database graph + target id + family + provider target + driver/runtime mode + connection/provisioning source + namespaces + contract spaces + migration root + dependencies + operational policy +``` + +Target identity must be a stable user-defined key, not the engine name. `primary` and `analytics` +must be distinct even when both are PostgreSQL. Their output, migration history, runtime binding, +health, and operation receipts must never collide. + +The graph must be open to multiple adapters, but capability-driven rather than lowest-common- +denominator. PostgreSQL can expose RLS/native enums/vector operations; SQLite or a future SQL Server +adapter can expose different capabilities. Code requiring a capability should fail at composition or +type-check time, not at a late database call. + +## Validation and generated types + +Prisma 8 uses Standard Schema-compatible validation for extension/codec parameters and ships an +ArkType JSON extension. It does not replace NetScript's current generated Zod model/input/output +surface with a complete general validator generator. Zod and Valibot appear as future directions, +not RC guarantees. + +NetScript should separate three concerns: + +1. **database contract types**, emitted by Prisma; +2. **boundary validation**, owned by application/API/domain schemas through Standard Schema; and +3. **database codec validation**, contributed by database extensions. + +It should not generate, patch, and re-export a second model universe merely because Prisma types +exist. Where CRUD boundary schemas are desired, a validator provider should deterministically derive +them from a supported IR and emit them once into an atomic target-specific artifact root. Provider +output must pass semantic tests; textual repair is forbidden. + +## Runtime/platform support and Deno + +The RC documentation lists Node 24 as primary and Bun 1.2 / Deno 2.0 as best-effort. The PostgreSQL +facade depends on `pg`; serverless documentation requires Node compatibility in Cloudflare and +records a real Hyperdrive cursor limitation. Source imports Node built-ins in relevant paths. + +“Deno is listed” is therefore not sufficient for NetScript. Adoption needs: + +- Deno import-graph verification; +- Deno compile and runtime tests without undeclared Node globals; +- connection, query, transaction, stream, close, and error mapping tests; +- bundler tests for the supported deployment modes; +- no CLI/toolchain modules in runtime graphs; +- leak detection under repeated start/stop and request lifecycles; and +- one real external PostgreSQL run, not only PGlite or emulation. + +## Maturity scorecard + +Prisma's RC scorecard is unusually honest and should be used rather than feature-list marketing. Its +integration-test threshold counts a capability as proven only when a Prisma Next test executes +against the corresponding real database test environment and asserts observable behavior. + +Across 593 atomic feature rows and 1,779 database cells: + +| Verdict | Cells | +| ---------------------- | ----: | +| Proven | 416 | +| Reachable but untested | 488 | +| Experimental | 12 | +| Absent | 244 | +| Not applicable | 619 | + +Per database: + +| Target | Proven | Untested | Experimental | Absent | N/A | +| ---------- | -----: | -------: | -----------: | -----: | --: | +| PostgreSQL | 222 | 136 | 4 | 111 | 120 | +| SQLite | 85 | 235 | 4 | 98 | 171 | +| MongoDB | 109 | 117 | 4 | 35 | 328 | + +Selected consequences: + +- PostgreSQL is the only credible first adoption target, but still requires NetScript conformance. +- SQLite's presence in source is not feature parity. +- MongoDB validates family abstraction, not production equivalence. +- MySQL and SQL Server need different adapters or later upstream targets. +- Open query/result/transaction work after RC means type presence cannot substitute for runtime + verification. + +## Agent surface audit + +Prisma 8 treats agent instructions as product surface. `init` installs a version-pinned project +skill and a lock file, and the skill routes by workflow. The direction is excellent: an agent gets +local version-specific commands, structured errors, known gaps, and explicit references. + +The RC content is not trustworthy enough to consume directly: + +- 83 distinct legacy `@internal/...` import roots appear in the `prisma-8` skill; +- those roots occur 116 times; +- 47 legacy `PN-*` error-code references remain after the public move to dotted codes; +- one reference says raw SQL is unavailable while runtime source exposes `raw`; +- one reference says prepared statements are not a user surface while runtime source exposes + `prepare`; +- another debugging reference recommends raw access, contradicting the query reference; and +- migration workflow prose mentions commands or layouts that do not match the RC/current source. + +Issue [#29932](https://github.com/prisma/prisma/issues/29932), where a published `orderBy` nulls +type was accepted but ignored at runtime, is a concrete warning: type surface, docs, and execution +must be tested together. + +NetScript should generate its agent surface from its machine-readable database graph and command +catalog: + +- target/space inventory with capabilities and ownership; +- exact command schemas and structured outputs; +- environment/destructive policy; +- generated import examples that compile; +- known unsupported operations; +- error code and next-action catalog; and +- a conformance test that runs every documented example. + +The generated skill is an output of the architecture, not a hand-maintained parallel manual. + +## Six days of post-RC churn + +Between the RC tag and the 2026-08-13 `main` pin, Prisma landed a long chain of release-candidate +development commits. The following are integration-significant: + +| Change | Evidence | Interpretation | +| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| Stop publishing the `prisma-next` CLI; use unified `@prisma/cli@next` / `prisma-cli` and a nested ORM config | [`3dc98cb`](https://github.com/prisma/prisma/commit/3dc98cb) | RC binary/config names are not a stable NetScript contract. | +| Route migration/database commands through control API | [`d0c8333`](https://github.com/prisma/prisma/commit/d0c8333) and later command-port commits | Programmatic control is becoming the intended seam. | +| Add sectioned config diagnostics, config format marker, and ControlClient test double | [`15308c6`](https://github.com/prisma/prisma/commit/15308c6) | Config and testing contracts are still formalizing. | +| Generate contract JSON Schema from ArkType | [`92b6ee3`](https://github.com/prisma/prisma/commit/92b6ee3) | Machine validation is improving; pin schema format. | +| Add packed-import, non-throwing-validator, and tarball-install conformance checks | [`c4a5875`](https://github.com/prisma/prisma/commit/c4a5875) | Upstream recognizes publish-surface correctness as a release gate. | +| Lower PostgreSQL floor from 17 to 15 | [`5d4a4db`](https://github.com/prisma/prisma/commit/5d4a4db) | RC documentation can become stale within days. | +| Change aggregate number semantics and add lossless variants | [`a900bc1`](https://github.com/prisma/prisma/commit/a900bc1) | Result typing/precision is not frozen. | +| Make all command output channels explicit | [`71e2e0d`](https://github.com/prisma/prisma/commit/71e2e0d9ee1f306b5a11435cd1973023cb33866a) | Structured orchestration is improving but not settled. | + +The RFC should describe desired NetScript semantics and an upstream compatibility window, not freeze +RC package names into public examples. + +## Open upstream issue and pull-request ledger + +Observed 2026-08-13: + +| Item | Surface | NetScript risk/gate | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------- | +| [Issue #29896](https://github.com/prisma/prisma/issues/29896) | External Supabase contract drift breaks verify | Test external/adopted ownership and version-skew policy. | +| [Issue #29923](https://github.com/prisma/prisma/issues/29923) / [PR #29944](https://github.com/prisma/prisma/pull/29944) | Introspection schema selector silently ignored | Test every selector against a non-default schema; never accept silent ignore. | +| [Issue #29932](https://github.com/prisma/prisma/issues/29932) | Published null-ordering type ignored by runtime | Conformance must cross type, plan, SQL, and result. | +| [PR #29997](https://github.com/prisma/prisma/pull/29997) | Whole-query raw SQL redesign | Treat raw/escape-hatch API as moving. | +| [PR #30009](https://github.com/prisma/prisma/pull/30009) | Exact CLI-engine peer needed to prevent duplicate engine copies | Enforce one resolved upstream component set. | +| [PR #30006](https://github.com/prisma/prisma/pull/30006), [#30014](https://github.com/prisma/prisma/pull/30014), [#30015](https://github.com/prisma/prisma/pull/30015) | Prepared statement counts/results/guards and transaction lifecycle | Prepared/transaction behavior needs dedicated acceptance tests. | +| [PR #29979](https://github.com/prisma/prisma/pull/29979) | Shared PostgreSQL connection query serialization | Test concurrency with externally supplied pools/connections. | +| [PR #29956](https://github.com/prisma/prisma/pull/29956) | Structural pool compatibility | Do not type-promise arbitrary pool implementations before proof. | + +Only items applicable to the Prisma 8 source were used. Prisma 7 engine/client issues were not +silently generalized to the new stack. + +## Adopt, wrap, defer, reject + +| Upstream idea/surface | Decision | Reason | +| -------------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------- | +| Canonical contract JSON + declaration | Adopt | Eliminates executable client generation and enables one inspectable graph. | +| Domain/storage separation and hashes | Adopt behind NetScript manifest | Excellent internal identity; upstream representation may evolve. | +| Family/target/adapter/driver/extension split | Adopt conceptually | Correct open-axis model for multiple engines and runtimes. | +| PostgreSQL runtime facade | Wrap | Powerful but too upstream-specific to become NetScript-wide API. | +| Programmatic ControlClient | Wrap and pin | Correct orchestration seam; package/options still moving. | +| Contract spaces | Adopt and extend | Best basis for plugin ownership; needs NetScript target, policy, removal, and provenance. | +| Migration graph, refs, marker, ledger | Adopt after conformance | Stronger than linear scripts; operational gaps remain. | +| Invariant-guarded data transforms | Adopt | Correct semantic model; automate wiring and placeholder detection. | +| Structured errors/progress/results | Adopt and translate | Enables stable CLI/agent surfaces without log parsing. | +| Project-level agent skill | Recreate from NetScript graph | Direction good; RC content stale and internally coupled. | +| Prisma CLI binary/config surface | Do not bind | Changed immediately after RC. | +| Public Prisma package re-exports | Reject | Would transfer upstream RC churn into NetScript API. | +| Hand-written low-level driver adapters | Reject by default | High correctness/security/lifecycle burden; require certification if unavoidable. | +| Copied/merged schema fragments | Reject | No ownership, history, policy, or safe removal. | +| Generated-source text patching | Reject | Non-semantic, non-atomic, and upstream-output coupled. | +| Universal lowest-common-denominator DB API | Reject | Hides real capability differences and weakens every provider. | +| Prisma 7 compatibility facade | Reject | Owner explicitly requires a clean break. | + +## Required NetScript adoption gates + +Prisma 8 can become the PostgreSQL implementation only after all gates pass against a pinned release +candidate or final package set: + +1. **Publish integrity** + - install packed artifacts in a blank Deno/Node fixture; + - verify every NetScript-used export and peer resolves exactly once; + - reject internal/deep imports outside the allowlist. +2. **Contract determinism** + - emit twice from clean checkout and compare bytes/digests; + - emit multiple targets concurrently into distinct roots; + - prove atomic replacement and interruption recovery. +3. **Runtime** + - CRUD, relations, raw, codecs, transactions, prepared statements, streaming/cancellation; + - connection injection, serverless lifecycle, close/leak behavior; + - error mapping and sensitive-value redaction. +4. **Control** + - offline emission never starts Aspire; + - every plan/apply/verify result is structured; + - cancellation and progress spans behave deterministically. +5. **Migration** + - greenfield, existing adoption, drift, destructive refusal, stale-plan refusal; + - graph branch/ref resolution, ledger/marker atomicity, resume after failure; + - data-transform invariants and migration locking; + - non-default namespace and two same-provider target isolation. +6. **Contract spaces** + - two plugins, dependency order, collisions, cross-space FK; + - version upgrade, external drift, missing artifact, uninstall/retention refusal; + - apply/verify with no plugin package installed. +7. **Platform** + - Deno compile/runtime and dependency graph; + - supported bundlers/deployment modes; + - one real PostgreSQL service, not only an emulator. +8. **Docs/agent** + - all generated examples type-check and run; + - command/flag/error catalogs match machine output; + - no internal imports or stale command names. +9. **Upstream maturity** + - no unresolved blocker in the used surface; + - NetScript matrix records upstream scorecard status and local proof; + - an explicit owner signs off each waived upstream gap. + +## Architectural implications for the RFC + +The database RFC should make the following non-negotiable: + +- one NetScript-owned database graph is the composition source of truth; +- Prisma is one target implementation, not the definition of NetScript's database architecture; +- a target ID, not engine name, owns output, connection, migrations, runtime, and receipts; +- contract spaces replace plugin file copying; +- offline work is independent of Aspire; +- generated artifacts are minimal, deterministic, target-scoped, and atomically emitted; +- validation is provider-based and never repaired textually; +- runtime types expose actual capabilities and lifecycle mode; +- consumers own domain ports; database integration is bound at composition roots; +- control operations are programmatic and structured; +- cross-target apply is resumable, never falsely described as atomic; +- agent/docs surfaces derive from the same graph and command schema; +- no Prisma 7 compatibility client, legacy generated module, or runtime shim survives; and +- adoption is gated by NetScript proof, not by an upstream “supported” label. + +## Primary source register + +- [Prisma 8.0.0 RC1 release](https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1) +- [RC source tree](https://github.com/prisma/prisma/tree/v8.0.0-rc.1) +- [Root README and support posture](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/README.md) +- [Architecture overview](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/ARCHITECTURE.md) +- [Feature scorecard](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/scorecard.md) +- [Contract spaces ADR](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20212%20-%20Contract%20spaces.md) +- [Data migrations ADR](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20176%20-%20Data%20migrations%20as%20invariant-guarded%20transitions.md) +- [Public package policy ADR](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20242%20-%20Public%20npm%20surface%20-%20single%20%40prisma%20scope%20with%20consolidated%20publish%20packages.md) +- [Programmatic Control API source](https://github.com/prisma/prisma/tree/v8.0.0-rc.1/packages/1-framework/3-tooling/cli/src/control-api) +- [PostgreSQL runtime source](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/runtime/postgres.ts) +- [Serverless PostgreSQL runtime source](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/runtime/postgres-serverless.ts) +- [Prisma 8 project skill](https://github.com/prisma/prisma/tree/v8.0.0-rc.1/skills/prisma-8) +- [Supported versions](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/Supported%20Versions.md) +- [Serverless deployment guide](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/Serverless%20Deployment%20Guide.md) diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index 3d9acd52b1..1eceb2a997 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -15,19 +15,28 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. ## Routes in force -| Task lane | Provider / model / effort | Role in this run | -| --------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------- | -| `planning_decisions` | OpenAI · Codex · GPT-5 family · high | Root research coordinator and RFC generator in the active user session | -| `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | -| `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | -| third-opinion architecture review | OpenRouter · Qwen 3.8 Max · max | Diversity pass over the full architecture and implementation roadmap | -| owner-directed final refinement | Anthropic · Fable 5 · high | Absolute final review-and-refinement gate after every other substantive gate | +| Task lane | Provider / model / effort | Role in this run | +| ------------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------- | +| `planning_decisions` | OpenAI · Codex · GPT-5 family · high | Root research coordinator and RFC generator in the active user session | +| owner-directed architecture deep dive | Anthropic · Claude Code · Opus 5 · high | Fresh independent architecture/API review with optional native workflows | +| `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | +| `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | +| third-opinion architecture review | OpenRouter · Qwen 3.8 Max · max | Diversity pass over the full architecture and implementation roadmap | +| owner-directed final refinement | Anthropic · Fable 5 · high | Absolute final review-and-refinement gate after every other substantive gate | ## Recorded lane/eval overrides - The root session is Codex rather than the default Opus 5 orchestrator. This is the active user-facing session surface; exact backend SKU is not exported, so the observed identity is recorded without claiming GPT-5.6 Sol. +- The owner corrected the execution posture on 2026-08-13: the root must orchestrate rather than + absorb the substantive work. A fresh native Claude Code Opus 5 high lane is therefore added for + the independent architecture deep dive before plan lock. It is an input to, not a substitute for, + the separate PLAN-EVAL. +- Claude launch evidence: background handle `3f8a9a69`, full session + `3f8a9a69-5589-4b91-9a32-91f7770fe7c2`, PID `1944525`, worktree matched, native UI reported “Opus + 5 with high effort · Claude Max.” The session immediately exposed four internal agents; their + roles/identities must be recorded in its report. - The owner explicitly requires Fable 5 **high**, not merely an adversarial review, as the final refinement gate. That owner directive overrides the ordinary `docs_polish` Fable-medium effort for this run. No substantive model gate may follow it. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 52da39b9c3..8ba87fc637 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -52,16 +52,18 @@ research inventory and proposed package-boundary matrix. ## Progress Log -| Time | Slice | Step | Notes | -| ---------- | ----- | --------- | ---------------------------------------------------------------------------------------- | -| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| Time | Slice | Step | Notes | +| ---------- | ----- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | ## Decisions -| Decision | Reason | Source | -| ------------------------------------- | --------------------------------------------------------------------------------- | ------------------------- | -| Treat #313 as superseded design input | Its additive compatibility premise conflicts with the owner-directed clean break. | Issue #313 + owner prompt | -| Require PLAN-EVAL | Material architecture, sequencing, and multi-wave risk are unavoidable. | Harness run loop §4 | +| Decision | Reason | Source | +| ------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------- | +| Treat #313 as superseded design input | Its additive compatibility premise conflicts with the owner-directed clean break. | Issue #313 + owner prompt | +| Require PLAN-EVAL | Material architecture, sequencing, and multi-wave risk are unavoidable. | Harness run loop §4 | +| Delegate architecture deep dive | Owner explicitly requested Claude Code Opus 5 high and an orchestration-first posture. | Owner correction | ## Drift From 811fda1d31b7944d00d7813589ec0435f77ff3c0 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 19:04:09 +0200 Subject: [PATCH 03/19] docs(rfc): add independent database architecture reviews --- .../briefs/claude-opus-architecture-finish.md | 45 ++ .../briefs/claude-opus-architecture-resume.md | 36 ++ .../briefs/claude-opus-report-part-1.md | 38 ++ .../briefs/claude-opus-report-part-2.md | 42 ++ .../briefs/claude-opus-report-part-3.md | 25 + .../briefs/qwen-prisma-risk-review-finish.md | 30 ++ .../briefs/qwen-prisma-risk-review-resume.md | 38 ++ .../briefs/qwen-prisma-risk-review.md | 68 +++ .../drift.md | 104 ++++ .../plan.md | 44 +- .../research/market-gap-audit.md | 488 ++++++++++++++++++ .../research/netscript-current-state.md | 8 +- .../research/qwen-prisma-risk-review.md | 326 ++++++++++++ .../runtime-validation-maintainer-exchange.md | 116 +++++ .../supervisor.md | 26 +- .../worklog.md | 23 +- 16 files changed, 1425 insertions(+), 32 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-finish.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-resume.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-1.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-2.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-3.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-finish.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-resume.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-gap-audit.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-maintainer-exchange.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-finish.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-finish.md new file mode 100644 index 0000000000..3dbdb31123 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-finish.md @@ -0,0 +1,45 @@ +# Claude Opus 5 High — Immediate Architecture Report Synthesis + +Resume native Claude Code session `f79af5bb-e953-4aae-9585-a1c83e73a00d` at Opus 5, effort high. +This is the terminal synthesis turn for the independent architecture lane. + +The original and resumed workflow produced extensive specialist evidence. Multiple agents completed +NetScript current-state, doctrine/process, generated-pipeline, documentation-claim, git-history/LOC, +Prisma control/runtime, migration, contract, and adversarial fact-check work; a few children were +lost or killed at process boundaries. The interactive background parent then exited at a bridge +boundary before replacing its report placeholder. + +Do not launch or resume any Agent, Task, Workflow, Team, monitor, or child session. Do not repeat +the broad research. Use the completed specialist results preserved in the current conversation plus +the three committed research documents. Perform only a narrowly targeted read if a claim would +otherwise be unsupported. + +Replace exactly this file: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +with the complete decision-grade independent architecture report required by the original brief. It +must include: + +1. requested/observed provider, model, effort, parent session/handle chain, workflow roles, and + observable specialist identifiers/statuses; +2. verdict and architectural thesis; +3. target package/ownership graph with NetScript doctrine/archetype assignment; +4. target/config/schema-space/migration/runtime identities and invariants; +5. concrete TypeScript public API, definition DSL, contribution DSL, factory/port, and generated + composition-root sketches; +6. plugin contribution/extensibility protocol, ownership/conflict/dependency/version/removal rules; +7. typed plan/apply/result/progress/error command lifecycle, locks, concurrency, recovery, CI, + offline determinism, and agent-facing manifest/surface; +8. Prisma 8 adopt/wrap/reject/defer decisions and a volatility-containment boundary; +9. provider matrix and multi-target/multi-schema/multi-engine behavior without false portability; +10. clean-break migration/cutover and parallel-branch strategy with data safety but no runtime + compatibility shims; +11. conformance, generated-project, journey, negative-path, migration, release, and GA gates; +12. risks, rejected alternatives, unresolved questions, explicit decision checkpoints, and exact + local/primary source references. + +Correct known precision issues: the root catalog entries are `^7.8.0`, generated templates use +`^7.4.2`, and the generated workspace currently emits 30 database tasks. Separate RC-tag facts from +post-RC-main churn. Be comprehensive but write in one bounded synthesis turn. Do not edit any other +file. End only after the report is complete. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-resume.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-resume.md new file mode 100644 index 0000000000..b6c380b8f1 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-resume.md @@ -0,0 +1,36 @@ +# Claude Opus 5 High — Resume Independent Architecture Synthesis + +Resume session `3f8a9a69-5589-4b91-9a32-91f7770fe7c2` in the same worktree and continue the +already-started independent database architecture deep dive. You have already completed a broad +Claude workflow/subagent fan-out and began the report, but the background parent paused immediately +after creating its placeholder. + +Do not restart the research. Consume the specialist results already present in this session, resolve +their disagreements, and finish the synthesis. You may resume or add focused Claude subagents only +when a specific evidence gap genuinely remains. Stay Claude Opus 5 at high effort. + +Write exactly one substantive artifact: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +Replace the placeholder with the complete decision-grade report required by the original brief. It +must include: + +- requested and observed model/provider/effort/session identity; +- workflow/subagent roles and observable identifiers; +- independent verdict and architectural thesis; +- a complete target package/ownership graph and doctrine/archetype alignment; +- target/config/schema-space/migration/runtime identity semantics; +- concrete TypeScript API and DSL sketches; +- plugin contribution and extensibility protocol; +- control-plane command lifecycle, typed plan/apply/result/progress/error contracts, concurrency, + locking, recovery, and deterministic CI/offline behavior; +- Prisma 8 adopt/wrap/reject/defer decisions and volatility containment; +- provider matrix and multi-engine/multi-schema/multi-target behavior; +- no-backward-compatibility migration/cutover plan with data safety and parallel-branch strategy; +- conformance, generated-project, journey, negative-path, migration, and release gates; +- risks, rejected alternatives, unresolved questions, and explicit decision checkpoints; +- exact primary-source/local-source paths for load-bearing claims. + +Do not author or edit the canonical RFC, plan, worklog, supervisor, drift log, production code, or +any other repository file. When the report is complete, end with a concise completion summary. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-1.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-1.md new file mode 100644 index 0000000000..0ff433d849 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-1.md @@ -0,0 +1,38 @@ +# Claude Opus 5 High — Architecture Report Part 1 of 3 + +Resume the existing Opus architecture session. Do not reason from scratch, run commands, read more +files, or invoke any agent/task/workflow. You already completed the evidence work and attempted one +oversized final write that the transport interrupted before the tool envelope persisted. + +Use exactly one `Write` call to replace: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +Write a polished, self-contained first third (roughly 3,500–5,000 words; bounded enough to complete +within this turn) containing: + +1. title, run/route identity, requested and observed Opus 5 high evidence, parent handle/session + chain, and a table of workflow/subagent roles/identifiers/statuses with truthful + incomplete/killed disclosures; +2. independent verdict, architectural thesis, non-negotiable invariants, and what the redesign is + explicitly not; +3. target package/ownership/dependency graph with one doctrine archetype per future package; +4. complete identity model: target, connection/provisioning profile, namespace/schema, contribution + space, contract snapshot, migration lineage/head, runtime session, operation plan and receipt; +5. concrete TypeScript public API sketches for the manifest/definition DSL, typed target refs, + composition factory, session/runtime access, generated app composition root, and contract-derived + Standard Schema input/output validation. + +Resolve rather than obscure the minimal-kernel tension: explain which data/protocol concepts are +durable NetScript public contracts and which graph/factory/port machinery remains internal or +consumer-owned. The owner-provided Prisma-maintainer exchange establishes a particularly important +design hypothesis: the contract has enough runtime data to derive validation without another +generation step. Treat this as primary exploratory evidence, not an upstream commitment. Make the +default runtime-derived and contract-identity-cached; any AOT form is only an equivalent optional +optimization. Do not make unsupported exact-count claims. + +End the file with exactly: + +`` + +Do not edit any other file. After the single Write succeeds, end the turn immediately. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-2.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-2.md new file mode 100644 index 0000000000..d2d9ab0b4c --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-2.md @@ -0,0 +1,42 @@ +# Claude Opus 5 High — Architecture Report Part 2 of 3 + +Resume the same Opus architecture session. Do not run commands, read more files, or invoke any +agent/task/workflow. Part 1 already exists and ends with ``. + +Use exactly one `Edit` call replacing that marker with a polished second third (roughly 3,500–5,000 +words) containing: + +6. contribution/plugin DSL and protocol: provenance, dependency ordering, capabilities, + ownership/conflict/augmentation, version skew, install/upgrade/removal/retention, migrations, + uninstall safety, conformance kit, upstream extension coexistence; +7. control-plane operation lifecycle and concrete types for classify/compose/plan/apply/verify/ + status/emit, consent, dotted errors, progress, receipts, locks, concurrency, expiry, resume, + partial multi-target success, artifact postconditions, offline determinism, CI cacheability, and + generated agent surface; +8. Prisma 8 adopt/wrap/reject/defer table and volatility-containment boundary; +9. provider/engine/runtime matrix, Postgres-first implementation, multi-target/multi-schema + semantics, external/unmanaged schemas, Deno/serverless constraints, and non-Postgres contingency; +10. a first-class pure-TypeScript schema-authoring and end-to-end type-system subsystem based on + Prisma Next's architecture direction: exact upstream capability versus NetScript ownership; + schema-as-code composition/imports/namespaces; models, relations, constraints, indexes, native + types and defaults; plugin-owned augmentation and conflict policy; multi-schema/multi-target + boundaries; static inference versus stable runtime contract identity; deterministic migration + coupling; and propagation from schema to typed operations, validation, routes/RPC/forms/SSR, + generated projects, tooling and agents. Include concrete public API sketches and explicitly + assess whether NetScript should expose, wrap, or translate Prisma's TypeScript schema surface. +11. a deep runtime-validation subsystem based on the owner/Prisma-maintainer exchange: Standard + Schema boundary; mutation/query input validation; selection/projection-aware output validation + at API/SSR/external-service trust boundaries; runtime versus wire representations; codecs; + plugin spaces; cache identity/invalidation; structured failures; Fresh/forms/RPC integration; + and semantic equivalence for any optional atomic AOT projection. Explicitly reject + mirror-validator codegen as the default. + +Correct known precision points: `^7.8.0` root ranges, 30 generated DB tasks, TypeScript 5.9 optional +peer, 138 top-level `orm-postgres` export keys, and no fragile skill-count totals. Clearly separate +RC tag from post-RC main. + +End the inserted text with exactly: + +`` + +Do not edit any other file. After the single Edit succeeds, end the turn immediately. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-3.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-3.md new file mode 100644 index 0000000000..055e3aa4de --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-3.md @@ -0,0 +1,25 @@ +# Claude Opus 5 High — Architecture Report Part 3 of 3 + +Resume the same Opus architecture session. Do not run commands, read more files, or invoke any +agent/task/workflow. Parts 1–2 already exist and end with ``. + +Use exactly one `Edit` call replacing that marker with the final polished third (roughly 3,500–5,000 +words) containing: + +12. clean-break migration/cutover strategy with no runtime compatibility, data preflight/safety, + mechanical migration tool/docs, rollback boundaries, parallel branch policy, and feature-parity + accounting. Before leaving the API architecture, add an explicit transfer analysis from + NetScript's existing oRPC extension/factory/composition pattern to Prisma's native + `defineContract` TypeScript schema builder: what should be reused to preserve native inference, + what must not become a wrapper/re-export, and what database-only ownership/migration/lifecycle + rules are additionally required; +13. implementation waves with package-by-package dependencies and acceptance gates; +14. exhaustive conformance matrix spanning type/plan/artifact/result/lifecycle, generated-project, + journey, negative paths, real PostgreSQL, multi-target, plugin lifecycle, migration failure, + deterministic/atomic emission, Deno/import purity, CI and publish/release gates; +15. failure-mode/risk ledger, rejected alternatives, unresolved/conditional decisions, kill/switch + criteria, explicit decision checkpoints for plan lock, and implementation blockers; +16. exact local/primary source register and a concise final recommendation. + +Finish cleanly with no continuation marker. Do not edit any other file. After the single Edit +succeeds, end the turn immediately. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-finish.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-finish.md new file mode 100644 index 0000000000..55fd982c7b --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-finish.md @@ -0,0 +1,30 @@ +# Qwen 3.8 Max — Immediate Final Synthesis + +Resume session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` on OpenRouter `qwen/qwen3.8-max`, effort +`max`. + +Your single-parent recovery successfully re-verified the NetScript load-bearing claims and began the +Prisma package audit, then the local PTY supervisor terminated the transport with signal 15 / exit +143. There was no additional evaluator-model policy violation, and all of your reasoning and tool +results are preserved in the resumed conversation. + +Do not perform another broad audit. Do not invoke Agent, Task, TaskCreate, Workflow, Team, or any +child-session facility. Synthesize the final report **now** from: + +- the evidence already in this resumed conversation; +- the committed current-state, Prisma deep-dive, and market-analysis research documents; +- at most a few narrowly targeted read-only checks needed to avoid an unsupported correction. + +Write exactly one artifact and no others: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md` + +Retain the original required structure: observed route/interruptions, verdict, corrected-fact +ledger, minimum viable architecture, ownership/boundary table, Prisma adopt/wrap/reject/defer +decisions, multi-provider/GA contingency, adversarial risk ledger, conformance/release matrix, +conditional decisions/kill criteria, and source register. Explicitly correct the root catalog to +`^7.8.0`, state that the generated workspace has 30 DB tasks, and separate RC-tag evidence from +post-RC-main evidence. Be concise enough to complete this turn but decision-grade enough to +influence plan lock. + +End only after the report file has been fully written. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-resume.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-resume.md new file mode 100644 index 0000000000..7f321b62fd --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-resume.md @@ -0,0 +1,38 @@ +# Qwen 3.8 Max — Recover and Finish Prisma Risk Review + +Resume session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` using the same requested and observed route: +OpenRouter `qwen/qwen3.8-max`, effort `max`. + +The parent review was interrupted because an automatically spawned child requested `claude-opus-5`; +the evaluator model guard denied that cross-model request. This is a route-policy failure, not a +finding about the architecture. + +Hard constraint for this resumed turn: do **not** invoke Agent, Task, TaskCreate, Workflow, Team, or +any subagent/child-session facility. Work as one Qwen parent. Use the evidence and completed child +results already in the resumed conversation; use only read-only file/search/shell tools if a small +gap remains. + +Finish the original independent falsification report. Correct any imprecise claims (including exact +versus caret Prisma catalog ranges), distinguish RC-tag proof from post-RC-main proof, and make +every load-bearing conclusion evidence-backed. + +Write exactly one repository artifact: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md` + +The report must contain: + +- requested/observed route and the guard-interruption disclosure; +- verdict on the architectural direction; +- corrected-fact ledger with exact sources; +- minimum viable NetScript-owned architecture; +- boundary table for NetScript vs Prisma vs providers/plugins/apps; +- Prisma adopt/wrap/reject/defer table; +- multi-provider and Prisma-GA contingency strategy; +- adversarial failure/risk ledger; +- conformance and release matrix; +- conditional decisions and kill/switch criteria; +- source register. + +Do not edit the canonical RFC, plan, worklog, supervisor, drift log, existing research, production +code, or any other file. End only after the report is complete. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review.md new file mode 100644 index 0000000000..e26721b924 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review.md @@ -0,0 +1,68 @@ +# Qwen 3.8 Max — Prisma 8 Integration and Abstraction Falsification + +Use the NetScript harness as an independent open-model research/review lane. This is not PLAN-EVAL, +not RFC authorship, and not permission to edit the repository. + +## Identity and scope + +- Requested provider/model: OpenRouter / `qwen/qwen3.8-max` +- Requested effort: `max` +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` +- Prisma RC source: `.llm/tmp/prisma-v8-rc1` at `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` +- Prisma current-main comparison pin: `71e2e0d9ee1f306b5a11435cd1973023cb33866a` + +Read `AGENTS.md`, `.agents/skills/netscript-harness/SKILL.md`, and these three research files +completely: + +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` + +Verify load-bearing claims against the local NetScript and Prisma sources. Do not trust the research +conclusions by default. + +## Assignment + +Falsify or strengthen the proposed direction from three angles: + +1. **Abstraction minimization:** determine whether a NetScript database graph, target descriptors, + contract spaces, capability negotiation, and consumer-owned ports are the minimum durable + concepts or an accidental second ORM/control plane. Propose a smaller superior alternative where + possible. +2. **Prisma integration risk:** identify every place Prisma 8 RC1/current-main churn, package + topology, migration semantics, runtime lifecycle, Deno behavior, contract versioning, extension + model, or agent surface could invalidate a NetScript public contract. Cite exact source paths, + commits, scorecard rows, issues, or PRs. +3. **Proof design:** specify negative-path conformance tests and adoption gates that distinguish + compile-time promises from actual plan/SQL/result/lifecycle behavior. Include two same-provider + targets, multi-schema, external ownership, plugin upgrade/removal, partial cross-target apply, + interrupted emission, version skew, stale plans, and Deno dependency graphs. + +Also answer: + +- Which provider strategy avoids blocking the architecture on Prisma 8's PostgreSQL-only GA target + without retaining Prisma 7 compatibility? +- Which proposed NetScript concepts must be public, internal, generated data, or adapter-local? +- What should be conditionally deferred until Prisma 8 final? +- What dangerous market analogy or missing competitor invalidates a conclusion in the market audit? +- What are the ten highest-risk RFC decisions, with severity, evidence, and required disposition? + +## Output + +Make no file edits and do not run mutation commands. Return one self-contained Markdown report in +your final response with: + +- requested/observed route caveat; +- independent verdict; +- corrected facts; +- minimum viable architecture; +- public/internal boundary table; +- Prisma adopt/wrap/reject/defer table; +- provider/parity strategy; +- adversarial finding ledger; +- conformance matrix; +- decisions that must remain conditional; +- source register. + +Label facts, inferences, and proposals. Do not write generic advice. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md index a01426a666..cd193ec2ff 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -41,3 +41,107 @@ documentation. - **Evidence:** native background session `3f8a9a69-5589-4b91-9a32-91f7770fe7c2`, observed as Opus 5 high in `/home/codex/repos/netscript-db-rfc`; exclusive briefing at `briefs/claude-opus-architecture.md`. + +## 2026-08-13 — Qwen child-route guard interruption + +- **What:** The Qwen 3.8 Max falsification parent spawned read-only verification children; one child + request attempted to use `claude-opus-5`, which is outside the evaluator child-model allowlist. +- **Source:** Evaluator HTTP-boundary audit and parent stream result. +- **Expected:** Parent and all child requests remain on the approved OpenRouter evaluator model set. +- **Actual:** The parent was observed as `qwen/qwen3.8-max` from provider `Alibaba`, but the denied + child requested `claude-opus-5`; the guard aborted the run with exit code 78 before synthesis. +- **Severity:** significant +- **Action:** recover +- **Evidence:** `.llm/tmp/agentic/evaluator-policy/f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b.jsonl`; + parent session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b`; recovery brief forbids every child-agent + facility and requires single-parent synthesis on the same Qwen route. + +## 2026-08-13 — Qwen recovery transport termination + +- **What:** The single-parent Qwen recovery re-verified the NetScript claims and started the Prisma + source audit, then its local exec/PTTY transport ended with signal 15 / exit 143 before report + emission. +- **Source:** Unified exec session `30446` and the persisted recovery stream. +- **Expected:** One resumed turn completes the bounded falsification report. +- **Actual:** No second model-guard audit record exists; the run ended at a normal Qwen tool + boundary while still on `qwen/qwen3.8-max`. All completed reasoning/tool results remain in session + history. +- **Severity:** operational +- **Action:** recover +- **Evidence:** `.llm/tmp/qwen-prisma-risk-review-resume.jsonl`; evaluator audit remains a single + earlier `claude-opus-5` denial; finish brief requires immediate single-parent synthesis with no + broad re-audit. + +## 2026-08-13 — Opus background-parent bridge exit + +- **What:** The resumed native Opus background parent re-established specialist work, but the + background service exited at a bridge/task-notification boundary before synthesizing the report. +- **Source:** Native sessions `3f8a9a69-5589-4b91-9a32-91f7770fe7c2` and + `f79af5bb-e953-4aae-9585-a1c83e73a00d`, their subagent transcripts, and the unchanged placeholder. +- **Expected:** Parent remains attached after its read-only workflow fan-out and writes one report. +- **Actual:** Several specialist reports completed and are persisted, while several in-flight + children were killed; the parent disappeared from `claude agents` at the bridge boundary. +- **Severity:** operational +- **Action:** recover +- **Evidence:** Resume the same Opus 5 high evidence chain in non-background print mode, forbid all + further child facilities, and require immediate one-file synthesis. + +## 2026-08-13 — Grok 4.6 adversarial lane override + +- **What:** The owner requires Grok 4.6 high in the review loop. +- **Source:** Active owner directive and live OpenRouter model metadata. +- **Expected:** The initial optional-model note allowed Grok only if an observable compliant route + already existed; the checked-in catalog currently stops at `x-ai/grok-4.5`. +- **Actual:** OpenRouter's live `/api/v1/models` response exposes `x-ai/grok-4.6`, 500k context, and + `reasoning_effort`; the bounded OpenCode runner accepts an explicit model and high variant without + changing production harness configuration. +- **Severity:** significant +- **Action:** accept +- **Evidence:** Owner-directed post-draft adversarial lane using + `openrouter/x-ai/grok-4.6 --variant high`; capture raw route receipt and observed identity. It + runs before IMPL-EVAL and the absolute-final Fable refinement. + +## 2026-08-13 — Prisma evidence checkout moved to trash and restored + +- **What:** During terminal model synthesis, the untracked pinned Prisma source checkout was moved + from `.llm/tmp/prisma-v8-rc1` to the desktop trash. +- **Source:** Freedesktop trash metadata recorded the exact original path and deletion timestamp + `2026-08-13T18:43:58`; no matching explicit deletion command appears in the preserved lane + transcripts. +- **Expected:** The source checkout remains available through report reconciliation and evaluation. +- **Actual:** Tracked run/research files were unaffected. The checkout was immediately restored with + the recoverable trash restore operation and verified at RC tag commit + `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`; post-RC main pin `71e2e0d...` remains present. +- **Severity:** operational +- **Action:** recover +- **Evidence:** `gio trash --list` original-path record; post-restore `git rev-parse HEAD` and + `git cat-file -t 71e2e0d9ee1f306b5a11435cd1973023cb33866a`. + +## 2026-08-13 — Opus monolithic report write interrupted + +- **What:** The attached non-background Opus synthesis reached “Writing the complete report now” but + the transport received signal 15 before the large `Write` tool call was emitted or persisted. +- **Source:** Native print session `f79af5bb-e953-4aae-9585-a1c83e73a00d`, exit 143 after 497845ms; + transcript ends before a report `Write` tool-use envelope. +- **Expected:** One bounded parent turn replaces the placeholder. +- **Actual:** Evidence and reasoning are preserved, but the all-or-nothing payload was not. The + placeholder remained unchanged. +- **Severity:** operational +- **Action:** recover +- **Evidence:** Resume the same Opus 5 high session for three strictly bounded single-tool writes to + one report, joined by explicit continuation markers; no additional research or subagents. + +## 2026-08-13 — Prisma evidence checkout moved to trash a second time + +- **What:** After the first safe restore, the same untracked pinned Prisma checkout was moved back + to the desktop trash at `2026-08-13T18:47:23` while delegated source audits were active. +- **Source:** `/home/codex/.local/share/Trash/info/prisma-v8-rc1.trashinfo`; the recorded original + path is `.llm/tmp/prisma-v8-rc1` and the intact checkout still resolves RC HEAD `a76a6c5...`. +- **Expected:** The restored evidence checkout remains at its run-local path. +- **Actual:** No tracked file was affected. Auditors can still read the intact recoverable trash + copy, so moving it again during their reads would create avoidable disruption. +- **Severity:** operational +- **Action:** recover after active source audits finish, then verify RC HEAD and post-RC main object + again. Treat the trash copy as read-only evidence until then. +- **Evidence:** filesystem path and `.trashinfo` above; `git -C` against the trash copy returned + `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md index 685c7adeee..cf77f4020b 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -50,6 +50,8 @@ databases, engines, providers, deployment runtimes, and third-party contribution - Deep Prisma 8/Next and source/issue/PR audit. - Competitor/prior-art analysis. - Complete user-facing and contributor-facing architecture. +- Pure-TypeScript schema authoring and end-to-end type propagation from definition through runtime + validation and application integration. - Explicit breaking migration and parallel-branch rollout strategy. - Implementation waves, contracts, test strategy, CI design, risk analysis, and acceptance gates. @@ -64,17 +66,23 @@ databases, engines, providers, deployment runtimes, and third-party contribution - Generator determinism and cacheability, plugin discovery, configuration provenance, secrets, migration concurrency, destructive-change policy, transaction semantics, serverless/edge/runtime constraints, telemetry, test databases, CI topology, version skew, supply-chain boundaries, - docs/scaffold synchronization, and AI-agent discoverability. + docs/scaffold synchronization, AI-agent discoverability, input/output trust-boundary validation, + selection-aware output shapes, codec/wire representations, and runtime/AOT equivalence. The sweep + also covers schema-as-code composition, namespace and plugin augmentation, contract identity, + type-inference ownership, migration coupling, and generated application bindings. ## Locked Decisions -| ID | Decision | Rationale | -| -- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | -| L0 | This RFC is a clean-break redesign; compatibility is not a design constraint. | Explicit owner directive; avoids encoding old foundation limits into the new layer. | -| L1 | Prisma is an implementation target behind NetScript-owned concepts, not the NetScript DB public API itself. | Preserves flexibility without pretending all database semantics are portable. | -| L2 | PLAN-EVAL is mandatory before authoring the canonical RFC. | The run is architecture-heavy, high-risk, and multi-wave. | -| L3 | Fable 5 high is the last substantive gate and may refine the document in place. | Explicit owner exception. | -| L4 | Claude Code Opus 5 high performs a fresh independent architecture deep dive before plan lock. | Owner explicitly requires orchestration and this model's workflow capabilities. | +| ID | Decision | Rationale | +| -- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| L0 | This RFC is a clean-break redesign; compatibility is not a design constraint. | Explicit owner directive; avoids encoding old foundation limits into the new layer. | +| L1 | Prisma is an implementation target behind NetScript-owned concepts, not the NetScript DB public API itself. | Preserves flexibility without pretending all database semantics are portable. | +| L2 | PLAN-EVAL is mandatory before authoring the canonical RFC. | The run is architecture-heavy, high-risk, and multi-wave. | +| L3 | Fable 5 high is the last substantive gate and may refine the document in place. | Explicit owner exception. | +| L4 | Claude Code Opus 5 high performs a fresh independent architecture deep dive before plan lock. | Owner explicitly requires orchestration and this model's workflow capabilities. | +| L5 | Grok 4.6 high performs a focused adversarial review of the complete RFC before IMPL-EVAL. | Owner-directed intelligence diversity is highest-value once all APIs are concrete. | +| L6 | Standard Schema is the durable validation boundary. The default path interprets a deliberately bounded algebra from the resolved contract at runtime; unsupported operations/codecs fail during schema construction, and any AOT form is only an equivalent optimization. | Owner/Prisma-maintainer exchange plus pinned-source proof that the RC contract omits parts of Prisma's operation type system and custom-codec value predicates. | +| L7 | Prisma's native pure-TypeScript `defineContract` builder and an end-to-end type system are primary RFC design axes. NetScript should extend the native surface using its oRPC integration as the local precedent, while the source audit decides the exact volatility boundary. | Owner directive; this preserves upstream inference and removes mirror artifacts without inventing a parallel model DSL. | ## Open-Decision Sweep @@ -83,13 +91,14 @@ will enumerate each one individually before PLAN-EVAL. ## Risk Register -| Risk | Mitigation | -| ----------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | -| Designing against RC marketing rather than implementation reality | Verify official docs against source, tests, release diffs, and live issues/PRs. | -| Replacing manual glue with a larger proprietary abstraction | Keep NetScript IR/ports minimal, capability-oriented, and conformance-tested. | -| False portability across engines | Model capabilities and explicit escape hatches; never normalize away real provider semantics. | -| RFC too broad to implement | Define strict package boundaries, dependency graph, staged waves, and per-wave acceptance gates. | -| No-compat break becomes an unsafe migration | Supply a mechanical migration tool/doc, preflight report, data-preserving sequence, and rollback boundaries without runtime shims. | +| Risk | Mitigation | +| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | +| Designing against RC marketing rather than implementation reality | Verify official docs against source, tests, release diffs, and live issues/PRs. | +| Replacing manual glue with a larger proprietary abstraction | Keep NetScript IR/ports minimal, capability-oriented, and conformance-tested. | +| False portability across engines | Model capabilities and explicit escape hatches; never normalize away real provider semantics. | +| Runtime validation silently overclaims contract completeness | Publish a bounded algebra, require representation-specific codec schemas, and fail closed wherever operation/result metadata is insufficient. | +| RFC too broad to implement | Define strict package boundaries, dependency graph, staged waves, and per-wave acceptance gates. | +| No-compat break becomes an unsafe migration | Supply a mechanical migration tool/doc, preflight report, data-preserving sequence, and rollback boundaries without runtime shims. | ## Anti-Patterns to Resolve or Avoid @@ -113,8 +122,9 @@ Pending targeted scan of `.llm/harness/debt/arch-debt.md`. | 4 | RFC source alignment | Local paths, `deno doc`, focused code inspection, upstream primary sources | No unsupported present-state or proposed-surface claim. | | 5 | Docs gates | Formatting, local links/paths, terminology, contradiction scan | PASS. | | 6 | Independent architecture review | Qwen 3.8 Max | No unresolved critical/high finding. | -| 7 | IMPL-EVAL | Fresh opposite-family evaluator | `PASS`. | -| 8 | Final refinement | Fable 5 high | Final in-place refinement; no substantive gate follows. | +| 7 | Adversarial architecture review | OpenCode/OpenRouter Grok 4.6 high with observable route receipt | No unresolved critical/high finding. | +| 8 | IMPL-EVAL | Fresh opposite-family evaluator | `PASS`. | +| 9 | Final refinement | Fable 5 high | Final in-place refinement; no substantive gate follows. | ## Dependencies diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-gap-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-gap-audit.md new file mode 100644 index 0000000000..312ad2aae7 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-gap-audit.md @@ -0,0 +1,488 @@ +# Independent Market-Analysis Gap Audit + +Provenance: independent delegated audit, current 2026-08-13, using official/primary sources only. + +Read-only audit completed against the existing `market-analysis.md`, current as of 2026-08-13. No +repository files were changed during the audit. + +## Executive corrections + +The omitted products materially change the market conclusions: + +- Flyway and Liquibase establish that migration ledgers, checksums, locks, repair, rollback + previews, and partial-failure handling are mature prior art. NetScript’s differentiation is not + inventing those mechanics; it is composing them across stable targets and contributor-owned spaces + with typed runtime validation. +- Terraform is useful mainly as negative and recovery prior art. Terraform state is a mutable + binding database, not a manifest or receipt; its apply is not transactional; saved plans are + opaque and sensitive; and targeted apply is explicitly exceptional. +- Pulumi strengthens the checkpoint/unknown-outcome lesson, but also shows the operational cost of + transactional state backends. Its saved update plans remain experimental and are checked + incrementally during execution. +- Bytebase is a persistent database control plane, not a local framework library. Most of its + impressive features depend on server-side plans, issues, IAM, stages, tasks, schedulers, and + metadata. Importantly, Bytebase removed schema drift detection in version 3.14.0 in January 2026. +- ZenStack v3 is the closest omitted comparator for schema/runtime composition. It explicitly + imports schema files into one AST, has preview schema/CLI/runtime plugins, and derives + selection-shaped Zod validators from its runtime schema. But it does not provide contributor-owned + migration spaces, Standard Schema neutrality, or plugin removal/retention semantics. +- No further comparator clears the “truly essential” bar. Kubernetes controllers/finalizers could + add recovery vocabulary, but would pull the RFC toward a continuous reconciler—the exact + control-plane expansion NetScript should avoid. + +The current matrix’s “Proposed NetScript = Strong everywhere” row should be removed. All proposed +capabilities are design targets, and contributor removal remains conditional on NetScript policy +plus upstream conformance. + +## Comparator findings + +### Flyway + +Architecture and mechanics: + +- The Java API centers on `Flyway.configure().dataSource(...).load()` and methods such as + `migrate()`. The CLI exposes `migrate`, `info`, `validate`, `repair`, `baseline`, and + edition-gated `undo`, dry-run, drift, and schema-comparison commands. + [Java API](https://documentation.red-gate.com/flyway/reference/usage/api-java), + [command inventory](https://documentation.red-gate.com/flyway/reference/commands) +- Recursively scanned `locations` provide SQL or classpath Java migrations. All locations feed one + resolved migration sequence and one schema-history table; they are not independent owner + histories. + [Locations](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-locations-setting) +- The history table records version, description, checksum, installer, duration, success, and states + including `Pending`, `Success`, `Failed`, `Missing`, `Future`, `Out of Order`, `Outdated`, and + `Superseded`. Flyway explicitly warns that replay after an out-of-order migration may differ. + [Schema history table](https://documentation.red-gate.com/flyway/flyway-concepts/migrations/flyway-schema-history-table) +- `validate` compares available migrations against applied metadata and checksums. `repair` deletes + failed ledger entries, aligns metadata/checksums, and marks missing migrations deleted. It does + not clean user objects left by a failed non-transactional migration, and it must use the same + locations as `migrate`. + [Repair](https://documentation.red-gate.com/flyway/reference/commands/repair) +- Flyway locks before migration, retrying once per second; the current default is 50 attempts, with + `-1` meaning indefinitely. Native Connectors currently do not implement this locking. + [Lock retry](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-lock-retry-count-setting) +- Migrations are normally transactional where the database permits it. `group=true` can place all + pending migrations in one transaction, but only on transactional-DDL databases; callbacks are + excluded and Native Connectors do not support this transaction mode. + [Group transaction](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-group-setting) +- PostgreSQL uses transactional advisory locking by default; `CREATE INDEX CONCURRENTLY` may require + session-level locking instead. + [PostgreSQL behavior](https://documentation.red-gate.com/flyway/reference/database-driver-reference/postgresql-database) +- Extension hooks include Java migrations, lifecycle callbacks, and custom `MigrationResolver` plus + `MigrationExecutor` pairs. These add executable migration formats and behavior, not typed schema + contributions or ownership spaces. + [API hooks](https://documentation.red-gate.com/flyway/reference/usage/api-java/api-hooks) + +DX strengths: + +- Extremely legible operational model. +- Same lifecycle available from CLI, build tools, and Java API. +- Explicit status vocabulary and machine-readable command results. +- Honest transaction and cleanup caveats. + +Failure modes and NetScript lessons: + +- Never let “repair ledger” imply “repair database.” Record cleanup-required and outcome-unknown + states separately. +- A lock capability must be part of target conformance; unsupported connectors cannot silently + proceed. +- Out-of-order/cherry-picked application can make fresh replay differ. Selective operations must be + recovery-only or produce a mandatory full verification. +- Multiple locations do not create ownership. NetScript spaces need stable IDs, independent heads, + dependency edges, overlap detection, and removal policy. +- Drift checking and dry-run facilities are edition-gated. NetScript’s local safety baseline should + not depend on reproducing Redgate’s complete comparison product. + +### Liquibase + +Architecture and mechanics: + +- A root changelog in XML, YAML, JSON, or formatted SQL includes changesets and other changelogs. + `includeAll` recursively includes files in alphabetical order unless a custom comparator is + installed. + [includeAll](https://docs.liquibase.com/secure/reference-guide-5-0/changelog-attributes/includeall) +- A changeset is identified by `id + author + filepath`. `logicalFilePath` stabilizes identity + across moves and can prevent module collisions, but module files still share one changelog + execution model and ledger. + [logicalFilePath](https://docs.liquibase.com/secure/reference-guide-5-1-1/changelog-attributes/logicalfilepath) +- `DATABASECHANGELOG` stores each execution, checksum, execution type, order, contexts, labels, and + deployment ID. A deployment ID groups changesets from one update run. + [DATABASECHANGELOG](https://docs.liquibase.com/community/user-guide-5-0-2/what-is-the-databasechangelog-table) +- `DATABASECHANGELOGLOCK` is a single-row database lock. Concurrent updaters wait; an unclean exit + can leave it set, requiring `release-locks`. + [Lock table](https://docs.liquibase.com/pro/user-guide-4-33/what-is-the-database-changelog-lock-table) +- `update-sql` previews generated SQL but explicitly does not establish correctness or predict + deployment errors. It is not an apply-bound plan artifact. + [update-sql](https://docs.liquibase.com/secure/reference-guide-5-2-1/init-update-and-rollback-commands/update-sql) +- Changesets run in a transaction by default where possible. With `runInTransaction=false`, a + mid-changeset failure can leave both the database and `DATABASECHANGELOG` inconsistent. + [runInTransaction](https://docs.liquibase.com/secure/reference-guide-5-1/changelog-attributes/runintransaction) +- Checksums reject unexpected edits; `runOnChange` deliberately re-executes changed definitions. + [runOnChange](https://docs.liquibase.com/reference-guide/changelog-attributes/runonchange) +- Rollback can target a tag, date, count, changeset, or deployment ID depending on edition. Rows are + removed from the active changelog ledger during rollback; newer history facilities preserve a + fuller audit. Rollback SQL is often author-supplied and can lose data. + [Rollback commands](https://docs.liquibase.com/community/reference-guide-5-0/init-update-and-rollback-commands/what-are-rollback-commands) +- `diff`, `snapshot`, and `diff-changelog` compare databases or snapshots. This is explicit + inspection, not Terraform-style continuous state reconciliation. Machine-readable drift reporting + and richer object coverage vary by edition. + [Inspection commands](https://docs.liquibase.com/secure/reference-guide-5-2-1/database-inspection-change-tracking-and-utility-commands/what-are-database-inspection-commands) +- Liquibase’s Java extension surface is broad: database types, changelog formats, changes, + executors, preconditions, snapshot generators, SQL generators, and resource handlers. Java + `ServiceLoader` discovers implementations; priority selects the applicable implementation. + `customChange` can execute code or generate SQL. + [Extension anatomy](https://contribute.liquibase.com/extensions-integrations/extensions-overview/extension-anatomy/), + [extension points](https://contribute.liquibase.com/extensions-integrations/extension-guides/), + [customChange](https://docs.liquibase.com/secure/reference-guide-5-0/change-types/customchange) + +DX strengths: + +- Flexible changelog formats and database coverage. +- Mature module/path identity tools. +- Rich preview, inspection, rollback, and extension ecosystem. +- Integration-independent engine semantics. + +Failure modes and NetScript lessons: + +- Path is part of identity. NetScript space IDs and migration IDs must be logical, never derived + from consumer filesystem layout. +- Alphabetical include order is not a dependency graph. Composition must use declared dependencies + and deterministic topological ordering. +- A global single-row lock and shared ledger do not isolate contributors. +- `validate` checks changelog structure/checksums, not database-specific SQL correctness or all live + drift. +- A plugin priority contest is not a safe schema-contribution protocol. NetScript should reject + ambiguous providers instead of choosing whichever implementation reports the highest priority. +- Arbitrary extension code is a supply-chain boundary; plugin version, checksum, provenance, and + allowed execution phases belong in the manifest snapshot. + +### Terraform state, plan/apply, and providers + +Architecture and mechanics: + +- Terraform configuration plus modules form desired configuration. State is a separate mutable + mapping between resource addresses and real remote objects, including provider metadata. It is + neither desired configuration nor an immutable execution receipt. + [State](https://developer.hashicorp.com/terraform/language/state) +- `plan` refreshes current objects, compares configuration with prior state, and proposes a graph of + actions. A speculative plan has no apply intent. `-out` creates an opaque saved plan consumed by + `apply`; the file embeds full configuration, values, options, and potentially cleartext sensitive + data. [Plan](https://developer.hashicorp.com/terraform/cli/commands/plan) +- Backends store state and may provide locking. Locking is optional by backend. If remote + persistence fails, Terraform writes state locally and requires manual recovery. State snapshots + carry lineage and monotonically increasing serial values to reduce unsafe pushes. + [Backends](https://developer.hashicorp.com/terraform/language/state/backends) +- State locking is automatic for operations that may write state. `force-unlock` requires a unique + lock ID but can still cause concurrent writers if misused. + [State locking](https://developer.hashicorp.com/terraform/language/state/locking) +- On apply failure, Terraform records completed changes in state, unlocks, and exits. It does not + roll back a partially completed apply; the operator fixes the cause and applies again. + [Apply failure](https://developer.hashicorp.com/terraform/tutorials/cli/apply) +- `-target` deliberately produces an incomplete view and is documented only for exceptional + recovery. Terraform recommends splitting routinely independent systems rather than normalizing + targeted apply. + [Resource targeting](https://developer.hashicorp.com/terraform/tutorials/state/resource-targeting) +- Normal plan/apply performs an in-memory refresh. `-refresh-only` lets operators review adoption of + live drift into state; careless refresh can forget resources if provider configuration or + credentials point at the wrong place. + [Refresh-only](https://developer.hashicorp.com/terraform/tutorials/state/refresh) +- Providers are separately downloaded executable plugins using gRPC. `GetProviderSchema`, + validation, configure, read, plan, and apply RPCs form the lifecycle. Provider and resource + schemas describe configuration and state—not application input/output validation. Provider + versions and checksums are pinned in the dependency lock file. + [Provider RPCs](https://developer.hashicorp.com/terraform/plugin/framework/internals/rpcs), + [provider requirements](https://developer.hashicorp.com/terraform/language/providers/requirements) + +DX strengths: + +- Clear preview/apply workflow and dependency graph. +- Strong provider isolation and version locking. +- Good partial-failure recovery vocabulary. +- Backend locking, lineage, serial, and state recovery are proven operational patterns. + +False analogy and lessons: + +- NetScript’s manifest snapshot must not become “Terraform state.” It is immutable resolved + configuration; live database markers and migration ledgers remain provider-owned. +- An operation receipt must not become an authoritative shadow copy of the database. It records what + was attempted and observed. +- A NetScript executable plan should exclude secrets, use secret references, bind the live baseline, + and have a documented stable schema. Copying Terraform’s opaque, sensitive plan artifact would be + wrong. +- Database migration edges are not CRUD resources. DDL atomicity, irreversible data transforms, and + “operation completed but ledger write was lost” need explicit treatment. +- Do not expose casual `--target` semantics. A selected apply needs dependency closure, + omitted-operation reason codes, and a subsequent whole-target verification. +- Do not build a remote state backend, workspace service, or generic provider RPC system merely to + resemble Terraform. + +### Pulumi + +Architecture and mechanics: + +- `pulumi up` executes the user program, observes resource registrations, builds a goal graph, + compares it to recorded stack state, and calls resource providers. Unlike Terraform, Pulumi does + not refresh live resources before every preview/update unless requested. + [State and refresh](https://www.pulumi.com/docs/iac/concepts/state-and-backends/) +- `pulumi preview --save-plan=plan.json` and `pulumi up --plan=plan.json` constrain an update, but + update plans are experimental. They are not validated all at once: discrepancies are discovered as + program execution and input resolution proceed, so earlier planned operations may already have + run. Unknown outputs, resources created inside `apply`, and providers configured with unknown + values reduce plan completeness. + [Update plans](https://www.pulumi.com/docs/iac/concepts/update-plans/) +- State is stored as frequent checkpoints. Pulumi Cloud uses transactional checkpoint APIs; DIY blob + backends have history and locking but explicitly offer weaker recovery from some partial failures. + [State backends](https://www.pulumi.com/docs/iac/concepts/state-and-backends/) +- An interrupted create can leave a `pending operation` because the engine cannot know whether the + provider completed it. Recovery requires checking the provider, then using `pulumi refresh` to + clear or import the created physical resource. + [Interrupted updates](https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/) +- Pulumi does not automatically roll back a failed update. By default it finishes in-flight + operations and stops; `--continue-on-error` may continue independent branches while preserving + dependency constraints. + [Failure behavior](https://www.pulumi.com/docs/support/faq/infrastructure/) +- Targeted operations use URNs. Non-targeted dependencies are read from recorded state, so targeted + work can defer code/infrastructure drift. + [Targeted updates](https://www.pulumi.com/docs/iac/guides/basics/targeted-updates/) +- Providers consist of an executable and a language SDK generated from a package schema. Providers + can be native, bridged from Terraform/OpenTofu, parameterized, or dynamic. Plugins run as separate + processes, mostly over gRPC. [Providers](https://www.pulumi.com/docs/iac/concepts/providers/), + [package schema](https://www.pulumi.com/docs/iac/using-pulumi/extending-pulumi/schema/), + [plugins](https://www.pulumi.com/docs/iac/concepts/plugins/) + +DX strengths: + +- Familiar programming languages and strong generated SDKs. +- Frequent checkpoints preserve partial progress. +- Excellent explicit treatment of unknown outcomes after interruption. +- Components and provider inheritance are ergonomic. + +Failure modes and NetScript lessons: + +- “Preview” is not necessarily a complete plan when the desired graph is computed by arbitrary code. + NetScript composition must be pure and deterministic. +- Receipts need an `outcome_unknown` phase, not just success/failure, for connection loss after an + operation begins. +- Resume must verify uncertain operations before retrying; non-idempotent replay can corrupt data. +- Transactional checkpoint services, audit history, scheduled drift, policy hosting, and KMS-backed + secrets are backend products—not appropriate NetScript kernel responsibilities. +- Pulumi package schemas generate language SDKs. They are not a precedent for Standard + Schema-compatible runtime boundary validation. + +### Bytebase + +Architecture and mechanics: + +- A Bytebase `Plan` contains one or more DDL/DML changes targeting databases or database groups. It + begins in `Draft`, receives automatic SQL review, becomes an Issue for approval, and then produces + a Rollout. [Plans](https://docs.bytebase.com/change-database/plan) +- A rollout is organized into environment stages and per-database tasks. Stages can run sequentially + while tasks within a stage can run in parallel; the API exposes task status and explicit skip + operations with a reason. [Batch change](https://docs.bytebase.com/change-database/batch-change), + [rollout API](https://docs.bytebase.com/api-reference/rolloutservice/get-v1projects-rollouts) +- Rollout policy controls manual versus automatic execution, role permissions, required approvals, + and enforcement of plan-check errors/warnings. + [Rollout permissions](https://docs.bytebase.com/change-database/environment-policy/rollout-policy) +- SQL Review checks syntax, engine-specific policy, schema practices, security, and performance, but + some enforcement levels and approval features are commercial. + [SQL Review](https://docs.bytebase.com/change-database/review) +- Change history records applied SQL plus before/after schema snapshots. Schema Synchronization + compares a selected historical/source schema to targets and generates editable DDL. + [Change history](https://docs.bytebase.com/change-database/change-history), + [schema synchronization](https://docs.bytebase.com/change-database/synchronize-schema) +- Bytebase previously offered automatic schema-drift detection, but release 3.14.0 explicitly + removed the feature and related API fields. Current comparisons and synchronization must not be + described as continuous drift monitoring. + [3.14.0 removal](https://docs.bytebase.com/changelog/bytebase-3-14-0) +- Bytebase is a persistent server even when self-hosted in one Docker container. Its workflow + depends on workspace metadata, users, roles, issues, approvals, schedulers, and database + credentials. It has no application runtime ORM, Standard Schema surface, or typed third-party + schema-contribution protocol. + +DX strengths: + +- Excellent human review and fleet rollout UI. +- Concrete stage/task partial-progress reporting. +- Strong SQL policy and approval workflow. +- Useful before/after schema history. + +Failure modes and NetScript lessons: + +- Do not claim current Bytebase drift detection. +- A server-side Plan/Issue/Rollout record is not the same as a local, portable, signed plan + artifact. +- Multi-database rollout is visibly staged and partially successful, never atomic. +- Automatic retry is safe only when the operation/task defines idempotency and outcome verification. +- NetScript should integrate with Bytebase as an optional delivery backend, not reproduce IAM, + approvals, scheduling, audit UI, notifications, database groups, or persistent metadata services. + +### ZenStack v3 + +Architecture and mechanics: + +- ZenStack v3 is no longer Prisma-backed at runtime; it uses a Kysely-based ORM while retaining a + Prisma-superset ZModel language and PrismaClient-compatible query style. Current v3 supports + PostgreSQL, MySQL, and SQLite. [v3 overview](https://zenstack.dev/docs), + [v2 migration](https://zenstack.dev/docs/migrate-v2) +- ZModel uses explicit `import` statements. Imported files are type-checked and merged into one + schema AST before downstream tools run. This is better than implicit directory merging, but still + one aggregate owner/history. [Multi-file schema](https://zenstack.dev/docs/modeling/multi-file) +- A `plugin` declaration names a built-in plugin, local module, or npm package. Plugins can + contribute ZModel attributes/functions, generation behavior, CLI behavior, and ORM runtime + interception. The entire plugin facility is marked preview and subject to breaking changes. + [Plugin model](https://zenstack.dev/docs/modeling/plugin) +- An npm plugin exports `plugin.zmodel`; the CLI loads ESM from a file, folder, or npm package. CLI + plugins receive the full resolved AST and arbitrary options. Runtime plugins intercept ORM/Kysely + query lifecycles. [Plugin development](https://zenstack.dev/docs/recipe/plugin-dev) +- Schema-level enablement and runtime enablement are distinct. For example, the policy plugin must + be declared in ZModel and installed on the ORM client. This creates a potential mismatch NetScript + should prevent through one resolved manifest. +- `zen migrate dev/deploy/status/resolve` exposes a single schema and migrations path. The current + CLI still creates temporary Prisma schemas and provides `resolve --applied` / `--rolled-back`; + `db push` accepts data-loss and force-reset flags. It is a wrapper around one migration history, + not contributor-owned histories. [CLI](https://zenstack.dev/docs/reference/cli) +- `@zenstackhq/zod` takes the generated/runtime ZenStack schema and builds typed Zod 4 schemas. + `makeModelSchema` supports `select`, `include`, `omit`, nested relation selection, and + create/update optionality. This is the strongest direct prior art for runtime derivation and + selection-shaped validation. [Zod factory](https://zenstack.dev/docs/utilities/zod) + +DX strengths: + +- One expressive schema drives runtime, generation, policies, and validators. +- Explicit imports and a typed AST are understandable. +- Selection-shaped runtime validation avoids one-validator-per-model boilerplate. +- Plugins can span schema, tooling, and runtime behavior. + +Failure modes and NetScript lessons: + +- Explicit imports do not establish independent ownership, migration heads, provenance, retention, + or removal semantics. +- Schema and runtime plugin installation can diverge. NetScript must resolve both from one + contribution record and reject half-installed plugins. +- Preview arbitrary-code plugins are not a stable public contract. NetScript’s contribution protocol + should be declarative; executable hooks belong behind phase-specific, capability-limited adapters. +- ZenStack’s validator is tied to Zod rather than Standard Schema, and documented coverage is + model/type/enum shape rather than full query/mutation argument semantics, provider codecs, storage + values, or wire representations. +- NetScript should copy runtime derivation and selection-aware factories, not a generated Zod-only + layer. + +## Revised focused capability matrix + +Legend: `Strong` = primary current capability; `Partial` = similar but materially different/manual; +`Hosted` = capability depends on a persistent control plane; `None` = absent. The NetScript row is +deliberately labeled as an unimplemented design target. + +| Product/pattern | Resolved desired manifest | Apply-bound plan | Durable run evidence / partial recovery | Contributor-owned schema + history | Runtime selection-aware validation | Lock / drift semantics | +| --------------------- | ---------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------- | +| Flyway | Partial: config + ordered migrations | None; dry-run is not a bound plan | Strong history/repair, but manual cleanup after non-transactional failure | None; locations merge into one history | None | Strong DB lock on JDBC; Native Connector gap; drift Enterprise | +| Liquibase | Partial: root changelog | Partial: `update-sql` preview only | Strong ledger/lock/rollback vocabulary | Partial module identity, shared ledger | None | Strong lock; explicit diff/snapshot, not state reconciliation | +| Terraform CLI | Strong config graph; mutable state is separate | Strong saved opaque plan | Strong mutable state and partial-apply recovery; no rollback | Partial modules/providers, not DB ownership spaces | None; provider schemas are unrelated | Backend-dependent locks; refresh/refresh-only drift | +| Pulumi OSS | Partial: graph emerges from program execution | Partial/experimental; incrementally enforced | Strong checkpoints and pending-operation recovery | Partial packages/components, not DB migration owners | None; package schema generates SDKs | DIY locks; explicit refresh | +| Pulumi Cloud | Same program graph | Partial/experimental | Hosted transactional checkpoints, history, policy | None for DB schema ownership | None | Hosted locking and scheduled drift | +| Atlas CLI/Pro | Strong schema graph | Partial/strong migration/declarative planning | Strong migration directory/ledger; local apply evidence | Partial composite sources; configuration order, not owned histories | None | Pre-apply drift is Pro; local apply semantics | +| Atlas Cloud | Strong registry source of truth | Strong promotion/registry workflow | Hosted deployment history and fleet status | Partial source composition | None | Hosted agents, scheduled drift, notifications | +| Bytebase current | Strong persistent server-side Plan | Strong Plan → Issue → Rollout, but not offline artifact | Strong stage/task history and partial fleet rollout | None | None | Persistent scheduler; current drift detection removed | +| ZenStack v3 | Strong single composed AST | None beyond wrapped migration workflow | Partial Prisma migration status/resolve | Partial schema/plugin contribution; one history | Strongest comparator, but Zod-specific and incomplete | No framework-level multi-target lock/drift layer | +| Prisma 8 RC substrate | Strong contract snapshot per target | Emerging control plan | Stronger graph/marker/ledger substrate | Strong spaces, but removal/retention conditional | No stable public Standard Schema layer | Adapter/provider dependent | +| Proposed NetScript | **Design target, not implemented** | **Design target, conditional on live-baseline binding** | **Design target; must prove unknown/partial/resume paths** | **Conditional on NetScript policy + upstream conformance** | **Design target; runtime/AOT equivalence unproven** | **Design target; local per-target only, no hosted monitor** | + +## Atlas and Terraform analogy corrections + +The RFC should state these explicitly: + +1. Atlas `composite_schema` is useful source composition, but its documented dependency mechanism is + load order. NetScript must require semantic dependency edges and reject cycles/overlaps rather + than inherit configuration order. + [Atlas project configuration](https://atlasgo.io/atlas-schema/projects) +2. Atlas Cloud’s registry, deployment audit, promotion, fleet status, continuous drift, agents, + notifications, and UI are online commercial services. They are not evidence that equivalent local + functionality is cheap. [Atlas Cloud](https://atlasgo.io/cloud/getting-started), + [Atlas Agent](https://atlasgo.io/cloud/agents), + [deployment reporting](https://atlasgo.io/cloud/deployment) +3. Terraform configuration, saved plan, mutable state, and backend are four distinct things. + NetScript must likewise keep source manifest, resolved snapshot, executable plan, database + ledger, and receipt distinct—but it should not create Terraform-style mutable framework state. +4. Terraform/Pulumi apply proves that plan approval does not imply atomic execution. + State/checkpoint updates preserve partial progress; rerun converges or continues. NetScript’s + database operations need per-operation idempotency and verification, not generic “convergence.” +5. Provider schema analogies stop at extension isolation and version pinning. Terraform/Pulumi + schemas describe provider configuration and resource CRUD, not application query/mutation/result + validation. +6. Terraform targeting is recovery machinery. It is positive evidence against treating `--db`, + `--space`, or `--operation` filters as routine unbound apply selectors. +7. Refresh/adoption changes the operator’s record of reality. NetScript verification must never + silently turn external drift into a new baseline; adoption requires an explicit ownership-policy + transition and reviewed plan. + +## Capabilities a local meta-framework should not rebuild + +Keep local: + +- pure manifest resolution and digesting; +- contributor dependency/overlap/provenance checks; +- plan generation and local policy evaluation; +- direct database-native lock acquisition; +- target/space migration invocation; +- per-run receipts, uncertain-outcome diagnostics, and resumable verification; +- optional adapters that export plans/results to external systems; +- runtime Standard Schema derivation from the pinned resolved contract. + +Leave to optional Atlas/Bytebase/Pulumi/HCP-style integrations: + +- remote state/checkpoint backends; +- organization workspaces and RBAC; +- human approval engines and issue tracking; +- schema registries and environment promotion; +- continuous drift agents/schedulers; +- fleet/tenant rollout schedulers and dashboards; +- permanent audit-log servers; +- notifications/webhooks; +- secret storage, KMS, and credential brokering; +- hosted policy distribution. + +## Plan-lock decisions affected + +1. **Artifact taxonomy:** lock separate definitions for source manifest, resolved snapshot, + executable plan, upstream ledger/marker, and immutable operation receipt. +2. **No mutable NetScript state:** the snapshot is generated data; receipts are evidence. Neither + becomes an authoritative shadow database. +3. **Executable plan contract:** bind manifest digest, target IDs, space versions, provider/package + lock, live baseline, operation digests, policy result, expiry, and environment. Store secret + references only. +4. **Speculative versus executable:** give offline/speculative plans a distinct type/status; only + live-baseline-bound plans can be applied. +5. **Apply revalidation:** reacquire the lock and recheck baseline, manifest, package set, target + identity, ownership policy, and expiry immediately before mutation. +6. **Lock protocol:** specify target/space scope, timeout, owner/nonce, stale-lock diagnostics, safe + force-unlock rules, and behavior when an adapter lacks locking. +7. **Receipt state machine:** include at least `planned`, `locked`, `started`, `applied`, + `verified`, `failed`, `partial_success`, `skipped(reason)`, `cleanup_required`, and + `outcome_unknown`. +8. **Checkpoint granularity:** persist a receipt checkpoint after every irreversible operation or + transaction group; never only at end-of-target. +9. **Recovery:** uncertain operations are inspected before retry; resume never blindly re-executes + non-idempotent DDL or data transforms. +10. **No cross-target atomicity:** lock wording now. Multi-target applies are staged collections of + independent target outcomes. +11. **Selective apply:** target/space filters require dependency closure, explicit omitted reasons, + plan binding, and whole-target verification afterward. They are not routine convenience + shortcuts. +12. **Ownership-aware drift:** distinguish migration-integrity drift, managed-object drift, adopted + baselines, allowed external drift, and ignored objects. Baseline adoption is a reviewed + mutation. +13. **Contribution identity:** use stable logical space and migration IDs independent of file paths, + package install paths, provider names, or include order. +14. **Plugin execution boundary:** pin version/checksum/provenance and declare which phases may + execute code. Composition should consume declarative records by default. +15. **Removal remains conditional:** NetScript can define diagnostics and retention policy now, but + must not score removal as implemented until upstream behavior and conformance prove it. +16. **Validation scope:** lock operation-aware inputs, selection-aware outputs, runtime versus wire + representations, codec contribution, stale-cache rejection, and fail-closed unsupported + constructs. +17. **Validation portability:** Standard Schema is public; Zod is one adapter. ZenStack’s runtime + schema factory is prior art for ergonomics, not for choosing Zod as the kernel. +18. **Hosted boundary:** explicitly defer RBAC, approval workflows, registry/promotion, continuous + monitoring, fleet scheduling, and permanent audit services. +19. **Matrix honesty:** replace the proposed “Strong” self-score with “design target / conditional / + unproven” until each conformance gate passes. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md index baf8564d7d..1c811fd685 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md @@ -5,8 +5,8 @@ - Repository: `rickylabs/netscript` - Baseline: `origin/main` at `cd720529333328bcba5e1a308ce7632f4350efdf` - Audit date: 2026-08-13 -- Package dependency baseline: Prisma `7.8.0` in the root catalog/lock; generated workspaces still - encode `^7.4.2` specifiers. +- Package dependency baseline: the root catalog declares Prisma caret ranges `^7.8.0` (the lock + resolves the installed versions); generated workspaces still encode `^7.4.2` specifiers. - Sources: current source and docs, architecture-debt ledger, Git history, GitHub issue/PR evidence, and focused `deno doc`/dependency-tool inspection. @@ -257,8 +257,8 @@ design must structurally retire. ## Architecture-debt alignment -- `packages/database — AP-17` remains open: ports were renamed, but the composition root has never - been resolved. +- `packages/database — AP-17` remains open. Source has already renamed `interfaces/` to `ports/`, so + that part of the debt entry is stale; the unresolved composition-root finding remains current. - `DB-GENERATE-ASPIRE-COUPLING` remains open and documents the pure-codegen/Aspire mismatch. - Current doctrine classifies `packages/database` as an A2 integration package needing refactor and `packages/prisma-adapter-mysql` as an A2 integration package. The new owner directive supersedes diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md new file mode 100644 index 0000000000..83da8c4a8b --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md @@ -0,0 +1,326 @@ +# Qwen 3.8 Max — Prisma 8 Integration and Abstraction Falsification Review + +Run: `docs-database-architecture-rfc--prisma-8-rfc` · Date: 2026-08-13 · Status: independent +research/review lane (not PLAN-EVAL, not RFC authorship). + +## 1. Route identity and interruptions + +| Field | Value | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Requested route | OpenRouter · `qwen/qwen3.8-max` · effort `max` | +| Observed harness | Claude Code session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b`; backend SKU is not self-verifiable from inside the session | +| Route caveat | The session executes inside an Anthropic Claude Code harness. The launcher's dispatch record, not this report, is authoritative for whether OpenRouter actually routed `qwen/qwen3.8-max`. Treat this lane as "the session briefed as the Qwen third-opinion lane" until the dispatch log confirms it. | +| Interruption 1 | The original parent spawned four read-only verification children; one child requested `claude-opus-5` and the evaluator model guard denied the cross-model request. This is a route-policy failure, not an architecture finding. The children left no completion records, so the parent re-verified all load-bearing claims itself, single-parent, read-only. | +| Interruption 2 | The single-parent recovery pass was terminated by the local PTY supervisor (signal 15 / exit 143) mid-Prisma-audit. All reasoning and tool results survived in-session; this report synthesizes from them plus a final narrow verification batch. | +| Constraint honored | No Agent/Task/Workflow/child facilities used in the recovery turns; no files edited except this artifact. | + +## 2. Independent verdict + +**[INFERENCE]** The proposed direction is **correct and should proceed to plan lock, with three +corrections and five conditional deferrals**. The evidence supports every structural claim that +motivates it: + +- NetScript verifiably has no join point between its five database systems; target resolution + provably ignores `PrimaryDatabase`, same-provider targets provably collide at + `database/`, and every operation — including pure codegen — provably requires the + resident Aspire AppHost (§3, items F1–F10). +- Prisma 8 RC1 verifiably replaces the executable generated client with contract data + a versioned + runtime, exposes a real programmatic control seam (`createControlClient`, confirmed at source), + and verifiably churned its CLI/config/publish surface within days of the RC tag (all eight churn + commits confirmed present and post-RC in the local clone). + +**[INFERENCE]** The direction is falsified in no place, but it over-specifies in three: + +1. **"Capability negotiation" as a first-class mechanism** risks becoming the seed of a second + type-level ORM. Compile-time capability tags are sufficient; a runtime negotiation protocol is + unnecessary and should be deferred indefinitely (§4). +2. **"Consumer-owned ports" framed as a NetScript concept** — ports are an application practice, not + framework API. NetScript should ship a typed target reference (`dbRef`-style) and guidance, not a + port framework (§4). +3. **Treating contract spaces as a solved plugin-removal story** — the deep dive itself records that + extension removal is unsupported in RC; the market matrix nonetheless scores proposed NetScript + "Strong" on plugin/feature schema ownership. That strength is conditional on an upstream + capability that does not exist (§8, R6; §9). + +The minimum durable NetScript surface is **smaller than the research proposes**: a declarative +manifest, an operation protocol with receipts, and a contribution/ownership record — nothing else +(§4). Everything deeper (contract, hashes, migration graph, runtime facade) is Prisma-owned and +stays adapter-local. + +## 3. Corrected-fact ledger + +Evidence classes: **[RC-tag]** = verified against local `v8.0.0-rc.1` checkout (`a76a6c5`); +**[main]** = verified against post-RC commits present in the same clone (`origin/main` tip +`71e2e0d`, 50 commits after the RC tag); **[NS]** = verified against NetScript worktree at baseline +`cd72052`; **[doc]** = restated from the run's research documents, not independently re-verified +this session (flagged for PLAN-EVAL). + +### 3.1 Corrections to the research documents + +| # | Research claim | Verified fact | Class | Evidence | +| --- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F1 | "Prisma `7.8.0` in the root catalog/lock" | Root catalog uses **caret ranges `^7.8.0`**, not exact pins, for `@prisma/adapter-mssql`, `@prisma/adapter-pg`, `@prisma/client`, `@prisma/driver-adapter-utils`, `@prisma/instrumentation-contract`. The lock resolves them; the catalog does not pin. | [NS] | `deno.json:231–235` | +| F2 | Generated workspaces encode `^7.4.2` | Confirmed, and the divergence is structural: templates render `npm:prisma@^7.4.2` and `npm:@prisma/adapter-pg@^7.4.2` while the root catalog carries `^7.8.0`. Templates also reference `npm:@prisma/adapter-libsql@^7.4.2` — a libsql/SQLite axis exists in current templates and has **no Prisma 8 GA equivalent** (SQLite is proof-of-concept upstream). | [NS] | `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts:36,56,59,61,67,71,74`; `generators_test.ts:41,58,219` | +| F3 | "more than twenty database tasks" in generated `deno.json` | **Exactly 30 unique `db:*` tasks** (incl. `db:fix-zod`, `db:patch-client`, `db:clear-seeded-client`, `db:resolve-applied`, `db:resolve-rolled-back`, `db:zod`, `db:format`, and per-op `:all` variants). | [NS] | `generate-db-deno-json.ts` (enumerated) | +| F4 | Fourteen CLI verbs | Confirmed exactly: add, deploy, generate, init, introspect, list, migrate, remove, reset, resolve, seed, status, studio, validate (`operations/` is internal plumbing, `db-group.ts` the group). | [NS] | `packages/cli/src/public/features/db/` | +| F5 | `resolveTarget` ignores `NetScript.PrimaryDatabase` and defaults only with exactly one enabled target | Confirmed; strengthened: `PrimaryDatabase` **is maintained** (set on `db add`, reassigned on `db remove`) but is never consulted during operation resolution. With >1 enabled target and no `--db`, resolution throws `Unknown database target: (default)`. | [NS] | `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66` (body quoted below); `workspace-mutator.ts:67–71,120–121` | +| F6 | Two same-engine targets collide at `database//` | Confirmed: `workspaceDir: join('database', provider.dirName)` — keyed by provider dir, not target id. | [NS] | `workspace-resolver.ts:51` | +| F7 | Circular adapter assembly (`setClient`) | Confirmed on all three adapters; port is `DatabaseAdapter` + `DatabaseAdapterFactory`. | [NS] | `packages/database/adapters/postgres.adapter.ts:97`, `mssql.adapter.ts:434`, `mysql.adapter.ts:368`; `ports/database-client.ts:85,132` | +| F8 | `@netscript/database` subpath story | Confirmed with nuance: exports are `.`, `./ports`, `./adapters`, `./adapters/postgres`, `./adapters/mssql`, `./adapters/mysql`, `./extensions`, `./scripts`, `./tracing`, `./testing` (package v0.0.6). MySQL/MSSQL adapters exist **both** in-package (subpath) and, for MySQL's low-level driver adapter, in the separate `packages/prisma-adapter-mysql`. | [NS] | `packages/database/deno.json` | +| F9 | Custom MySQL adapter is a large upstream-coupled surface | Confirmed: implements `SqlDriverAdapter` directly, imports `@prisma/driver-adapter-utils` types/`Debug`/`DriverAdapterError`, uses `mysql2/promise` (dynamic import), and carries legacy lineage in its debug namespace `prisma:driver-adapter:deno-mysql`. | [NS] | `packages/prisma-adapter-mysql/src/adapter.ts:15–23,30,319,427,570`; `errors.ts:7`; `conversion.ts:8–9` | +| F10 | Plugin fragment model is regex-based file copying | Confirmed: 123-line scanner with header regex `/^\s*(model\|enum\|type\|view)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/gm`. | [NS] | `packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts:2,13` | +| F11 | Aspire coupling incl. pure generate; studio first-target; `--db all` sequential fail-fast | All confirmed: detached execution demands the resident AppHost ("The resident Aspire AppHost is not running…"); `studio` executes `databases[0]` only; the `all` loop returns on first non-zero exit with no per-target result record. | [NS] | `packages/cli/src/kernel/adapters/database/operation-runner.ts:85–101,116–117,179–181`; debt entry `DB-GENERATE-ASPIRE-COUPLING` (`.llm/harness/debt/arch-debt.md:1954+`, cites `executeDetached` + `aspire start --apphost apphost.mts`, ~243ms fast-fail without Aspire) | +| F12 | Debt entries `packages/database — AP-17` and `DB-GENERATE-ASPIRE-COUPLING` open | Confirmed, with a wording correction: the AP-17 entry says "`interfaces/` should become `ports/`; composition root needs confirmation" — the rename is **pending**, not already done ("ports were renamed" in the current-state audit is inaccurate). Note AP-17 is a per-package verdict id reused across packages (the `packages/cron` AP-17 entry is closed). | [NS] | `.llm/harness/debt/arch-debt.md:316–324` | +| F13 | `@prisma/orm-postgres` export map has "more than one hundred subpaths" | Undercount. The published package.json contains **~275 unique `./…` export subpath keys**. It depends on `pg` (`"pg": "catalog:"`), and TypeScript is an **optional** peer with floor `>=5.9`, enforced by a `MIN_TYPESCRIPT_PEER` constant + `pnpm lint:manifests` CI gate. No `engines.node` field was observed in that package.json; the Node 24 floor is documented in Supported Versions, not that manifest. | [RC-tag] | `packages/9-public/@prisma/orm-postgres/package.json:24,32,35–39`; `docs/Supported Versions.md:11,26–32` | +| F14 | Skill audit: "83 distinct `@internal/` roots, 116 occurrences, 47 `PN-*` codes" | Directionally confirmed, numerically **not reproducible**: this review measured **35 distinct roots, 191 occurrences, 66 `PN-*` references** over `skills/prisma-8` (grep methodology: `grep -rho "@internal/[A-Za-z0-9_./$-]*" | sort -u | wc -l`, etc.). The qualitative conclusion — the shipped agent skill is laced with legacy internals and obsolete error codes — holds under either measurement. The RFC must not cite either set of counts as load-bearing. | +| F15 | Post-RC churn table (8 commits) | All eight commits exist locally, all are descendants of `v8.0.0-rc.1`, and `71e2e0d` is the tip of `origin/main` (50 commits after the RC tag). Exact subjects: `3dc98cb` feat(cli)!: stop publishing the prisma-next CLI — unified prisma-cli replaces it (#30005); `d0c8333` Route migration/db commands through the control-api seam (TML-3173) (#29911); `15308c6` Config diagnostics by section, defineConfig version marker, ControlClient test double (#29936); `92b6ee3` generate contract.json JSON schema from arktype source (#29935); `c4a5875` publish path gains three conformance checks (#29998); `5d4a4db` lower PostgreSQL floor from 17 to 15 (ADR 244) (#29971); `a900bc1` count/sum/avg return JS numbers, with lossless variants (#29930); `71e2e0d` ORM commands state all four output channels (#30004). | [main] | local git objects; `git merge-base --is-ancestor v8.0.0-rc.1 ` for each | +| F16 | RC1 publishes a `prisma-next` CLI | Confirmed — `packages/9-public/prisma-next` is `private: false` at the RC tag, and post-RC `3dc98cb` then **stops publishing it**. This is the sharpest locally-proven example of a public name dying within days of the RC. | [RC-tag] + [main] | `packages/9-public/prisma-next/package.json`; `3dc98cb` | +| F17 | Scorecard methodology: "proven" = integration test against a real database | Confirmed with a critical nuance: for **Postgres, "proven" includes PGlite-backed integration tests** ("Postgres via PGlite, SQLite via its real driver, MongoDB via mongodb-memory-server"). Upstream "proven" therefore does **not** imply proof against a server PostgreSQL. NetScript's gate "one real external PostgreSQL run, not only PGlite" is necessary, not redundant. | [RC-tag] | `scorecard.md:3,9–15` | +| F18 | Early Access posture; DB target set | Confirmed: README — "Prisma Next is currently in Early Access … we don't recommend it for production workloads yet" (line 21); MongoDB "early access; proves the framework works beyond SQL" (line 91); scorecard matrix has **only Postgres/SQLite/MongoDB columns** — MySQL and SQL Server are absent from the RC feature surface entirely; Supported Versions at RC: Node 24 primary, Bun 1.2/Deno 2.0 best-effort, PostgreSQL floor **17** (lowered to 15 only post-RC, `5d4a4db`). | [RC-tag] + [main] | `README.md:21,91`; `scorecard.md:3`; `docs/Supported Versions.md:11–21` | +| F19 | Package topology `@prisma/orm-*` | Confirmed: 16 published `@prisma/*` packages — facades `orm-postgres`/`orm-mongo`/`orm-sqlite`; `orm-framework`; families `orm-family-sql`/`orm-family-mongo`; targets `orm-target-postgres`/`-sqlite`/`-mongo`; `orm-toolchain`; extensions `orm-extension-arktype-json`, `-middleware-cache`, `-paradedb`, `-pgvector`, `-postgis`, `-supabase`. The extension list is **missing from the deep dive** and matters: upstream already ships vendor/pack extensions (Supabase, PostGIS, pgvector, ParadeDB) — NetScript's contribution model must coexist with upstream extensions, not assume it is the only extension layer. | [RC-tag] | `packages/9-public/@prisma/*/package.json` | +| F20 | `createControlClient` programmatic seam | Confirmed at source: `export function createControlClient(options: ControlClientOptions): ControlClient`; consumed by `commands/migrate.ts`, `commands/migration-show.ts`, with `test/control-api/client.errors.test.ts`. The published subpath spelling (`@prisma/orm-toolchain/cli/control-api`) was not re-verified in the exports map. | [RC-tag] | `packages/1-framework/3-tooling/cli/src/control-api/client.ts:69` | + +### 3.2 Claims NOT re-verified this session ([doc] class — carry as research assertions) + +- Exact scorecard verdict tallies (593 rows / 1,779 cells / 416-488-12-244-619; per-DB table). + Methodology verified (F17); tallies not re-counted. +- ADR 212 (contract spaces) and ADR 176 (invariant-guarded data transforms) text details. +- Runtime facade surface inventory (`sql`/`orm`/`raw`/`prepare`/`transaction`/…) and serverless + facade asymmetry details. +- Upstream issue/PR ledger semantics (#29896, #29923/#29944, #29932, #29997, #30009, + #30006/#30014/#30015, #29979, #29956) — GitHub-side evidence; the RC-side churn commits that + correspond to them (F15) are locally verified. +- Contract emission file names (`contract.json`/`contract.d.ts`) and "types-only emission" phrase. + +## 4. Minimum viable NetScript-owned architecture + +**[PROPOSAL]** The durable kernel is **three artifacts, not five concepts**. "Database graph, target +descriptors, contract spaces, capability negotiation, consumer-owned ports" collapses to: + +1. **Database manifest (data, not an object system).** A declarative, typed document + one pure + resolution function producing a deterministic, content-addressed manifest snapshot. Contents per + target: stable user-defined target id; family + provider target; connection / provisioning source + reference; namespaces; list of contribution-space refs; operational policy (consent, environment + binding). No methods, no runtime graph object, no service registry. This is the join point the + five current systems lack (F1–F11). Renaming "graph" → "manifest" is deliberate: graphs accrete + traversal APIs and become control planes; manifests do not. +2. **Operation protocol.** One typed API — `classify / compose / plan / apply / verify / status` — + with structured results, dotted-code errors, and **receipts** (per-target phases, graph digest, + package-set identity, live-baseline binding, expiry, resume cursor). Offline classification is a + protocol property: `compose/emit/format` must never start Aspire (kills F11's coupling). `apply` + refuses drifted inputs (graph, baseline, package set, or target changed since plan). Cross-target + apply is resumable with explicit partial success — never described as atomic. +3. **Contribution record.** Per schema contributor: space id, version, provenance digest, target + binding predicate, ownership policy (`managed` / `adopted` / `external` / `ignored`), dependency + list, removal/retention policy. NetScript maps this 1:1 onto Prisma contract spaces (ADR 212) — + it wraps and polices them; it does not reimplement the marker/ledger machinery. + +**Demoted from the research proposal:** + +- _Capability negotiation_ → static capability tags on targets checked at composition/type time (a + branded `TargetRef` constraint). Runtime negotiation deferred indefinitely; + it is the most likely seed of a second ORM. +- _Consumer-owned ports_ → application practice + guidance + `dbRef`-style typed target references. + Not a NetScript port framework, not a generated repository interface. +- _Validation generation_ → pluggable validator providers emitting once into an atomic target-scoped + artifact root, proven by semantic tests; textual repair forbidden (this already follows from the + research; retained as-is). +- _Agent surface_ → generated projection of manifest + operation catalog; never hand-maintained (the + RC skill audit, F14, is the cautionary tale). + +**[INFERENCE]** This kernel is the minimum: remove the manifest and the five systems diverge again; +remove the protocol and success-without-artifacts (#1327-class failures) returns; remove the +contribution record and plugin schema falls back to regex file copying (F10). Nothing else is +load-bearing — everything further is Prisma-owned mechanics or app-owned practice. + +## 5. Ownership / boundary table + +| Concept | Owner | Surface class | Rationale / evidence | +| --------------------------------------------------------------------------------------------- | ---------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Database manifest schema + resolution | NetScript | **Public** (types + one function) | The join point; must be inspectable by users, CI, agents. | +| Manifest snapshot / digest lockfile | NetScript | **Generated data** | Content-addressed, atomically replaced; the stale-artifact detector. | +| Operation protocol (`plan/apply/verify/status`), receipts, error codes | NetScript | **Public** | Replaces log scraping; stable contract even as upstream seams move (F15). | +| Target id, ownership-policy enum, consent policy | NetScript | **Public** | Durable vocabulary; survives provider swaps. | +| `dbRef`-style typed target reference, session scoping types | NetScript | **Public (narrow)** | The only runtime-facing public type; capability-tagged at type level. | +| Capability tag registry | NetScript | **Public data, closed extension process** | Tags are data; adding one is a reviewed change, not a plugin right. | +| Contribution descriptor types + conformance kit | NetScript | **Public** | Plugin authors need only this. | +| Resolution algorithms, digest computation, lock management | NetScript | **Internal** | No public promise; free to change. | +| Aspire/provisioning binding | NetScript | **Internal** | F11 shows what happens when orchestration leaks into operations. | +| `contract.json` / `contract.d.ts`, storage/profile hashes, migration graph/refs/marker/ledger | Prisma | **Adapter-local** (surfaces in receipts only as opaque, versioned handles) | Upstream representation still moving (92b6ee3: contract JSON schema itself regenerated from ArkType post-RC). Raw upstream hashes must never be NetScript public identifiers. | +| ControlClient invocation + option translation | NetScript adapter | **Adapter-local** | `createControlClient` confirmed real (F20) but command routing/output channels moved post-RC (d0c8333, 71e2e0d). | +| Runtime facade (`sql/orm/raw/prepare/transaction`) | Prisma | **Adapter-local**, exposed only through capability-tagged session types | Result/number semantics moved post-RC (a900bc1); raw redesign open (#29997 per deep dive). | +| Engine/provider specifics (Postgres floor, PGlite-vs-server behavior) | Provider/target adapter | **Adapter-local data** | Floor moved 17→15 post-RC (5d4a4db); NetScript records, does not hardcode. | +| Plugin schema artifacts (pinned mirrors of spaces) | Plugin author; pinned by app | **Generated data in consumer repo** | ADR 212 model; removal/retention policy is NetScript's addition (unsupported upstream in RC). | +| Validator artifacts (Zod etc.) | Validator provider | **Generated data** | One atomic target-scoped root; semantic tests required. | +| Agent skill/manifest | NetScript generator | **Generated data** | F14 proves hand-maintained upstream skills rot within a release. | + +## 6. Prisma adopt / wrap / reject / defer + +Evidence class in brackets. Decisions differ from the deep dive only where noted. + +| Upstream surface | Decision | Evidence | +| -------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | +| Canonical contract data + types-only emission | **Adopt** behind manifest snapshot | Eliminates generated executable client and text patching (F3 pipeline); [doc] emission names | +| Domain/storage hash separation | **Adopt as adapter-local handles** in receipts; NetScript digest stays primary | 92b6ee3 [main]: contract JSON schema regenerated from ArkType — format not frozen | +| Family/target/adapter/driver/extension axis split | **Adopt conceptually** as manifest vocabulary | F19 topology confirms the decomposition is real | +| Programmatic ControlClient | **Wrap + pin** inside integration package; translate to NetScript operation protocol | F20 source confirmed; d0c8333/15308c6/71e2e0d [main] prove the seam is improving but moving | +| PostgreSQL runtime facade | **Wrap**, capability-tagged; no NetScript-wide re-export | F13: ~275 subpaths + `pg` dep — direct re-export would import RC internals and Node-only deps into Deno graphs | +| Contract spaces (ADR 212) | **Adopt + extend with NetScript ownership/removal policy** | [doc] ADR text; F19 vendor extensions mean NetScript spaces must coexist with upstream packs | +| Migration graph/marker/ledger | **Adopt after conformance** | [doc]; PG "proven" includes PGlite (F17) — server-proof is NetScript's job | +| Invariant-guarded data transforms | **Adopt semantics**; automate wiring | [doc] ADR 176; placeholder ergonomics unfinished per deep dive | +| Structured errors/progress spans | **Adopt + translate** to NetScript code catalog | 71e2e0d [main]: output channels still being formalized | +| `prisma-next` / unified CLI binary & config names | **Reject as contract** | F16 + 3dc98cb [main]: the RC's own CLI package stopped being published six days later | +| Re-exporting any `@prisma/orm-*` subpath | **Reject** | F13 surface breadth | +| Hand-written low-level driver adapters | **Reject by default** | F9 shows the cost: `packages/prisma-adapter-mysql` is a full `SqlDriverAdapter` implementation on an unstable upstream utils package | +| Copied/merged schema fragments; generated-source text patching | **Reject** | F10, F3 | +| Prisma 7 compatibility facade | **Reject** | Owner directive; clean break | +| Prepared-statement/transaction public guarantees | **Defer until final** | [doc] PR ledger #30006/#30014/#30015 in flight | +| Raw SQL escape hatch as NetScript API | **Defer/reject as public**; adapter-local at most | [doc] #29997 whole-query redesign | +| Numeric/aggregate semantics promises | **Defer until final** | a900bc1 [main]: count/sum/avg semantics changed post-RC | +| Extension removal via upstream primitive | **Defer; NetScript owns interim diagnostics** | [doc] scorecard: removal unsupported in RC | +| MySQL/SQL Server/MongoDB production posture | **Defer past 8.0 GA** | F18: absent from RC matrix / early access | + +## 7. Multi-provider and Prisma-GA contingency strategy + +**[PROPOSAL]** Do not block the architecture on Prisma 8's PostgreSQL-only GA, and do not retain +Prisma 7 compatibility: + +1. **Ship the kernel provider-neutral; ship the adapter Postgres-only.** The manifest, operation + protocol, and contribution record (§4) contain no Prisma concepts in their public fields — the + schema artifact is an implementation-defined handle. The first (and for v1 only) implementation + adapter targets Prisma 8 PostgreSQL. +2. **Non-Postgres targets get an explicit `unsupported-target` diagnostic**, never a silent skip and + never a legacy fallback path. This retires the current MySQL/MSSQL adapter surface (F8, F9) as a + product direction while the architecture stays open. +3. **Reserved-but-unbuilt SPI.** A target-implementation interface thin enough that a future + Drizzle/Kysely-backed or later-Prisma-family adapter can be added without manifest changes. Do + not build it now; conformance-kit first, second adapter later. +4. **SQLite regression is explicit debt.** Current templates carry `adapter-libsql` (F2); Prisma 8 + SQLite is proof-of-concept (F18). The clean break must state in the RFC that SQLite/libsql + targets are **not carried forward** until upstream SQLite cells are proven (scorecard), or a + non-Prisma SQLite adapter is built under the SPI. +5. **If Prisma 8 GA slips or regresses**: the kernel ships anyway; the adapter stays feature-flagged + and unpublished; conformance gates (§9) are the only release valve. Delay the adapter, never the + architecture, and never re-open a Prisma 7 code path (release-policy maintenance of the old major + is a branch question, not an architecture question). +6. **Duplicate-component guard**: exactly one resolved `@prisma/orm-*` set per app (deep-dive PR + #30009 concern — exact CLI-engine peer to prevent duplicate engine copies); a dependency check + fails on any second copy or off-allowlist deep import. + +## 8. Adversarial failure / risk ledger + +### 8.1 Ten highest-risk RFC decisions + +| # | Decision at risk | Severity | Evidence | Required disposition | +| --- | -------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| R1 | Freezing any upstream package/CLI name into public API or examples | **Critical** | F15/F16: `prisma-next` CLI unpublished 6 days post-RC; config/output channels moved (`3dc98cb`, `15308c6`, `71e2e0d`) | RFC names NetScript semantics + a compatibility window; zero upstream import paths in public contracts | +| R2 | Binding NetScript operation contracts to ControlClient option shapes | **High** | F20 + d0c8333/15308c6 [main] — seam real but still formalizing | Translate layer inside the integration package; regenerate per pinned upstream release; conformance covers shape drift | +| R3 | Public numeric/result promises (aggregates, decimals) | **High** | a900bc1 [main]: count/sum/avg semantics changed post-RC | No numeric-semantics guarantees until GA; tests assert observed behavior per pin | +| R4 | Plugin removal promised via contract spaces | **High** | [doc] extension removal unsupported in RC; market matrix "Strong" ownership score contradicts it | RFC specifies NetScript-level removal diagnostics + retention policy now; marks upstream removal a conditional enhancement | +| R5 | Deno support assumed from "Deno listed" | **High** | F18: Bun/Deno explicitly best-effort; F13: facade depends on `pg`; F17: PG proof is PGlite-based | NetScript platform gate (import graph, compile, lifecycle, leaks, one real server PostgreSQL) before any adapter publishes | +| R6 | Externally-owned schemas treated as verifiable like managed ones | **High** | [doc] #29896 Supabase drift breaks `db verify`; workaround marker-only | Ownership policy (`managed/adopted/external/ignored`) is manifest data and changes plan/verify behavior; conformance scenario required | +| R7 | Multi-target apply described or implemented as atomic | **Medium** | No cross-DB atomicity upstream; current `--db all` is fail-fast with no result record (F11) | Per-target receipt phases + idempotent resume + explicit partial-success; RFC must forbid the word "atomic" cross-target | +| R8 | Same-provider multi-target identity by engine/provider name | **Medium** | F6: `join('database', provider.dirName)` | Target id owns output/connection/migrations/runtime/receipts; conformance: two postgres targets, independent schemas/histories, zero shared paths | +| R9 | Capability negotiation runtime enters the kernel | **Medium** | Abstraction-minimization analysis (§4); market's second-ORM hazard | Compile-time tags only; runtime negotiation rejected unless a concrete use case survives plan-gate | +| R10 | Stale artifacts remain possible after schema edits | **Medium** | F3 (30-task non-atomic pipeline); #1254/#1290-class history in current-state audit | Manifest snapshot digest gates compile/run; mismatch = typed error, not warning | + +### 8.2 Market-audit falsifications + +**[INFERENCE]** + +- **Missing competitors that weaken conclusions:** (1) **Flyway/Liquibase** — the deepest prior art + for migration ledgers, locks, out-of-order handling; absent entirely, so the audit's + ledger/lessons appear newer than they are. (2) **Terraform/Pulumi** — the origin of + plan/apply/state-lock/drift/partial-apply semantics the audit borrows from Atlas; their hardest + lessons (state backends, locking, `-target`-style partial apply, tainted resources) map directly + onto NetScript receipts and are unconsidered. (3) **Bytebase** — open-source schema-change control + plane with review policy + drift detection; closer comparator to the proposed policy gates than + Atlas. (4) **ZenStack** — Prisma-schema extension/plugin model directly relevant to contract-space + contributions on Prisma. +- **Dangerous analogies:** (1) **Atlas-as-local**: Atlas's drift monitoring, target groups, rollout, + and audit history are hosted-control-plane products; assuming local replication underprices the + build, and its `composite_schema` "order = dependency" is a weak ordering NetScript must not + import. (2) **The capability matrix self-score**: "Proposed NetScript" is scored "Strong" across + the board, including plugin ownership, while the deep dive records extension removal as + unsupported upstream — the matrix must be re-scored as _conditional_. (3) **Django routers** as + routing precedent risk importing runtime-string resolution into what must be compile-time binding; + the audit's own anti-pattern list (silent skips) already shows why. + +## 9. Conformance and release matrix + +**[PROPOSAL]** Every row must cross **type → plan → SQL/artifact → result → lifecycle**; a +compile-time pass alone never satisfies a row (this is the direct answer to #29932-class +type/runtime divergence and to F17's PGlite nuance). Negative paths are first-class tests. + +| Scenario | Negative path that MUST fail correctly | Layers asserted | +| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| Two same-provider targets (`primary`, `analytics`, both postgres) | Cross-target import/operation by engine name; shared output path | type, plan, artifacts, runtime isolation | +| Multi-schema / non-default namespace | Introspect/selector silently ignoring schema (cf. [doc] #29923) — must error, not skip | plan, SQL, result | +| External ownership | `apply` against `external`-policy objects; `verify` with accepted drift must pass, unaccepted drift must fail with reason code | plan, verify, receipt | +| Plugin upgrade | Apply with stale pinned space artifacts; version skew between space and core | plan refusal, receipt | +| Plugin removal | Removal without retention decision → typed refusal; copied-directory deletion path must not exist | lifecycle, migration state | +| Partial cross-target apply | Second target fails mid-run → receipt records phase per target; resume continues only unfinished targets; no re-execution of applied ones | receipt, resume, result | +| Interrupted emission | Kill during emit → no partial artifact visible to consumers; re-emit byte-identical | artifact atomicity, determinism | +| Stale plan | Apply after graph/baseline/package-set change → refusal with drift reason; expired plan refusal | plan binding, receipt | +| Version skew | App runtime package vs pinned contract format mismatch → typed error naming both versions | contract version check | +| Deno dependency graph | Any Node builtin/`pg` leak outside the adapter package; CLI/toolchain modules in runtime graphs → import-graph test fails | graph purity, compile, leak tests | +| Real server PostgreSQL | Full lifecycle (connect/query/txn/stream/close/leak) against a server instance, never satisfied by PGlite (F17) | runtime, lifecycle | +| Agent/docs surface | Every documented example must compile and run; command/flag/error catalogs diffed against machine output | docs-as-tests | + +**Release gates (adapter publishes only when):** publish integrity (packed install, single +resolution of the `@prisma/orm-*` set, allowlist enforced) → contract determinism (double-emit byte +equality, concurrent multi-target emit) → runtime + control + migration conformance rows above → +platform rows → docs/agent rows → upstream-maturity row (no unresolved blocker in the used surface; +each waived gap owner-signed). The `scaffold.runtime` E2E remains the merge-readiness proof per +AGENTS.md, with the db suite exercising rows 1, 6, 7, 8 end-to-end. + +## 10. Conditional decisions and kill/switch criteria + +**[PROPOSAL]** Must remain conditional until Prisma 8 final (or a NetScript-gated exception): + +| Conditional item | Unblocks when | Kill/switch criterion | +| -------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | +| Upstream import allowlist frozen | GA package topology stable ≥1 release | Any post-GA rename of a used subpath → allowlist bump is a NetScript patch, never a public break | +| Prepared/transaction guarantees | PR ledger (#30006/#30014/#30015 class) merged + proven cells | Still unproven at GA → ship session API without `prepare`; no facade promises | +| Raw SQL surface | #29997-class redesign lands + proven | Still moving at GA → raw stays adapter-local, undocumented publicly | +| Numeric semantics | GA behavior + scorecard proven | Any post-GA semantic change → NetScript pins and translates, does not chase | +| Contract hash/format identity | Format stable across two releases | Canonicalization change → receipts treat hashes as opaque handles (already the design; this is the switch) | +| Extension removal | Upstream primitive proven | Absent at GA → NetScript removal diagnostics + retention policy is the product behavior (R4) | +| PostgreSQL floor | GA docs confirm 15 (post-RC direction, 5d4a4db/ADR 244) vs RC's 17 | Floor rises again → adapter records floor as adapter-local data | +| Deno support | NetScript platform gate passes on GA bits | Fails → adapter unpublished for Deno; kernel unaffected (§7.5) | +| Scorecard tallies as adoption evidence | Re-counted at GA | Tallies move materially → conformance matrix re-run, not re-argued | +| `orm-*` single-resolution invariant | #30009-class peer guarantee in GA | Duplicate-component corruption observed → hard dependency-check gate blocks release | + +## 11. Source register + +**NetScript (worktree @ baseline `cd720529`, class [NS]):** `deno.json:231–235` (catalog `^7.8.0`); +`packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` (30 tasks, `^7.4.2`, libsql +specifier); `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:51,66`; +`workspace-mutator.ts:67–71,120–121`; +`packages/cli/src/kernel/adapters/database/operation-runner.ts:85–101,116–117,179–181`; +`packages/cli/src/public/features/db/` (14 verbs); +`packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts`; +`packages/database/deno.json`, `ports/database-client.ts:85,132`, +`adapters/{postgres,mssql,mysql}.adapter.ts` (`setClient`); +`packages/prisma-adapter-mysql/src/{adapter,errors,conversion}.ts`; +`.llm/harness/debt/arch-debt.md:316–324,1954+`. + +**Prisma RC (`.llm/tmp/prisma-v8-rc1`, HEAD = tag `v8.0.0-rc.1` = `a76a6c5`, class [RC-tag]):** +`README.md:21,91`; `scorecard.md:3,9–15`; `docs/Supported Versions.md:11–32`; +`packages/9-public/@prisma/*/package.json` (16 packages + surface counts); +`packages/9-public/prisma-next/package.json`; +`packages/9-public/@prisma/orm-postgres/package.json:24,32,35–39`; +`packages/1-framework/3-tooling/cli/src/control-api/client.ts:69`; `skills/prisma-8/**`. + +**Post-RC main (same clone, class [main]):** commits `3dc98cb`(#30005), `d0c8333`(#29911), +`15308c6`(#29936), `92b6ee3`(#29935), `c4a5875`(#29998), `5d4a4db`(#29971, ADR 244), +`a900bc1`(#29930), `71e2e0d`(#30004) — all verified descendants of `v8.0.0-rc.1`; `origin/main` tip += `71e2e0d` (50 commits after RC tag). + +**Run research documents ([doc] where not re-verified):** `research/netscript-current-state.md`, +`research/prisma-8-deep-dive.md`, `research/market-analysis.md`; upstream issue/PR ledger therein +(#29896, #29923/#29944, #29932, #29997, #30009, #30006/#30014/#30015, #29979, #29956); ADRs 212, +176, 242. + +**Process artifacts:** `supervisor.md` (route table), `plan.md` (locked decisions L0–L4), +`drift.md`, `briefs/qwen-prisma-risk-review.md`, `briefs/claude-opus-architecture.md`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-maintainer-exchange.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-maintainer-exchange.md new file mode 100644 index 0000000000..0f536c5c96 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-maintainer-exchange.md @@ -0,0 +1,116 @@ +# Runtime Validation — Owner / Prisma Maintainer Exchange + +## Provenance and confidence + +- Source: three owner-provided screenshots from the public `#prisma-next` Discord channel. +- Exchange dates: 2026-03-05 through 2026-03-06. +- Participants visible in the screenshots: `rickyshowtime` (NetScript owner) and `wmadden` + (identified by the owner as a Prisma maintainer). +- Confidence: primary evidence of an exploratory maintainer conversation, **not** an upstream + roadmap commitment or proof that a stable public validation API ships in Prisma 8 RC1. + +## What the exchange establishes + +The owner proposed deriving Standard Schema-compatible validation from Prisma Next's +machine-readable contract so applications no longer hand-write or third-party-generate schemas that +mirror model types, nullability, and constraints. The proposed scope covered both: + +1. mutation/query inputs; and +2. query outputs when data crosses trust boundaries such as API responses, SSR hydration, or an + external service. + +The owner initially described either a built-in emission step or a first-party `afterEmit` plugin. +The maintainer replied that the idea was viable and then sharpened the direction: validation could +probably be derived from the contract **at runtime**, skipping the extra generation step, because +the contract contains the necessary type and runtime data. + +That distinction is architectural. The opportunity is not “replace one Zod generator with another.” +It is to make the resolved contract the runtime validation authority and treat any emitted validator +artifact as an optional, semantically equivalent optimization. + +## NetScript design implications to resolve in the RFC + +### Durable boundary + +- Standard Schema is the interoperability contract; Zod, Valibot, ArkType, and other libraries are + consumer choices, not framework foundations. +- The default validator is interpreted/compiled from the resolved contract snapshot and cached by + target + contract/profile identity. +- Validation artifacts must never become a second source of truth. Optional ahead-of-time emission + is atomic, derived, replaceable, and proven equivalent to the runtime interpreter. +- Plugin/contribution spaces participate automatically through the same resolved aggregate contract; + plugin authors do not maintain parallel validator files. + +### Two distinct planes + +- **Input validation:** operation-aware mutation/query inputs, including required/optional/defaulted + fields, nested writes, relation identifiers, constraint metadata, provider types, codecs, and + plugin-contributed fields. +- **Output validation:** selection/projection-aware result shapes at an explicit trust boundary. A + whole-model validator is incorrect for partial selects, aggregates, raw/provider results, or + relation projections. + +The RFC must also separate runtime database values from serialized/wire values. Dates, decimals, +bigints, bytes, native enums, JSON, custom codecs, and redacted fields can have different valid +representations before and after serialization. + +### Candidate public shape + +```ts +const users = db.ref('primary').model('User'); + +const createUser = users.input('create'); // StandardSchemaV1 +const publicUser = users.output({ // selection-aware StandardSchemaV1 + select: { id: true, email: true }, + representation: 'wire', +}); + +const parsed = await createUser['~standard'].validate(requestBody); +const safe = await publicUser['~standard'].validate(responseBody); +``` + +The exact names remain subject to plan lock. The important constraints are that the surface is +target-aware, operation/selection-aware, representation-aware, and derived from a pinned contract +identity. + +### Integration surface + +- Fresh route/action params and bodies; +- form libraries that consume Standard Schema; +- tRPC/oRPC or other request/response boundaries; +- SSR serialization/hydration checks; +- plugin configuration and plugin-owned model inputs/outputs; +- test-fixture/data-factory validation without generated mirror types. + +### Required failure semantics + +- structured issues with target, contract identity, operation/selection path, field path, expected + representation, actual value class, and stable NetScript error code; +- explicit errors for an unsupported contract construct or codec—never silently weakening to + `unknown`; +- stale-contract/cache rejection when the manifest snapshot changes; +- deterministic behavior across interpreted and optional ahead-of-time modes. + +## Plan-lock questions + +1. Which Prisma contract constraints are public/stable enough at RC1 versus adapter-local? +2. Does the result plan expose enough selection/result-shape metadata for output validation without + reconstructing Prisma's type system? +3. Which validation representations are required initially: runtime, JSON/wire, storage, or a strict + subset? +4. How do custom extension codecs contribute Standard Schema behavior and serialization rules? +5. Is output validation opt-in per trust boundary, policy-driven, or both? +6. What is the cache and optional AOT equivalence proof? +7. What performance budget makes runtime derivation acceptable for cold start, edge, and hot paths? + +## Mandatory RFC gates + +- No hand-written or copied model validator in the default path. +- Input and selection-aware output examples compile and execute. +- Standard Schema consumer proof with at least two independent libraries/integrations. +- Contract-space/plugin fields appear automatically. +- Codec and wire-representation fixtures cover dates, decimals, bigints, bytes, JSON, enums, and one + extension-defined type. +- Runtime and optional AOT modes, if both exist, pass the same semantic corpus. +- Contract change invalidates cached validators and stale artifacts deterministically. +- Unsupported constructs fail closed with structured diagnostics. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index 1eceb2a997..48c2db6c5b 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -22,6 +22,7 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | | `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | | third-opinion architecture review | OpenRouter · Qwen 3.8 Max · max | Diversity pass over the full architecture and implementation roadmap | +| owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | | owner-directed final refinement | Anthropic · Fable 5 · high | Absolute final review-and-refinement gate after every other substantive gate | ## Recorded lane/eval overrides @@ -41,5 +42,26 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. refinement gate. That owner directive overrides the ordinary `docs_polish` Fable-medium effort for this run. No substantive model gate may follow it. - Qwen 3.8 Max is selected as an in-policy independent architecture review for intelligence-family - diversity. Grok 4.6 will be used only if an existing policy-compliant, observable route is - present; no unrecorded paid escalation is authorized. + diversity. +- The owner subsequently requires Grok 4.6 high. On 2026-08-13 the live OpenRouter models API + returned `x-ai/grok-4.6` with `reasoning_effort` support. The repository's static model catalog + still names Grok 4.5, so this is an explicit owner-directed route override rather than a claim + that the catalog is current. Use the existing bounded OpenCode/OpenRouter runner with model + `openrouter/x-ai/grok-4.6` and variant `high`, record requested/observed identity and raw receipt, + and run it after the complete RFC draft but before IMPL-EVAL. Grok is not the formal evaluator and + no substantive gate may follow the final Fable 5 high refinement. +- Qwen integration-risk launch evidence: OpenRouter evaluator guard requested `qwen/qwen3.8-max` at + `max`; session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` initialized with observed model + `qwen/qwen3.8-max` and provider `Alibaba`. This is a complementary falsification pass, not + PLAN-EVAL. +- Qwen's initial parent was interrupted before synthesis when a child request attempted + `claude-opus-5`; the HTTP-boundary evaluator guard recorded the denial and exited 78. The same + Qwen session is resumed in single-parent mode with all child-agent facilities forbidden. This + failed attempt is route evidence only and cannot be counted as a completed review. +- The native Opus parent paused after its specialist fan-out and placeholder creation. The same Opus + 5 high session is resumed for synthesis, preserving its completed workflow evidence rather than + launching a replacement author. +- The owner elevated Prisma Next's proposed pure-TypeScript schema authoring as a second primary + architecture axis beside contract-derived validation. A separate read-only source audit must + establish the exact upstream state and derive candidate end-to-end NetScript type flows before + plan lock; the Opus synthesis brief now requires this subsystem explicitly. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 8ba87fc637..bb9c086ee8 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -52,18 +52,23 @@ research inventory and proposed package-boundary matrix. ## Progress Log -| Time | Slice | Step | Notes | -| ---------- | ----- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | -| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | +| Time | Slice | Step | Notes | +| ---------- | ----- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | +| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | +| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | +| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | +| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, `runtime | ## Decisions -| Decision | Reason | Source | -| ------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------- | -| Treat #313 as superseded design input | Its additive compatibility premise conflicts with the owner-directed clean break. | Issue #313 + owner prompt | -| Require PLAN-EVAL | Material architecture, sequencing, and multi-wave risk are unavoidable. | Harness run loop §4 | -| Delegate architecture deep dive | Owner explicitly requested Claude Code Opus 5 high and an orchestration-first posture. | Owner correction | +| Decision | Reason | Source | +| ------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------- | +| Treat #313 as superseded design input | Its additive compatibility premise conflicts with the owner-directed clean break. | Issue #313 + owner prompt | +| Require PLAN-EVAL | Material architecture, sequencing, and multi-wave risk are unavoidable. | Harness run loop §4 | +| Delegate architecture deep dive | Owner explicitly requested Claude Code Opus 5 high and an orchestration-first posture. | Owner correction | +| Elevate TypeScript schema authoring | It can remove the schema/type/codegen split and anchor one end-to-end application type graph. | Owner directive + pending pinned-source audit | ## Drift From 29415709e0b0250275ffff8a5a3a9d16ca9bc0aa Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 19:13:35 +0200 Subject: [PATCH 04/19] docs(rfc): deepen Prisma architecture evidence --- .../drift.md | 26 +- .../claude-opus-architecture-review.md | 2004 +++++++++++++++++ .../research/market-analysis.md | 402 +++- .../research/prisma-8-deep-dive.md | 103 +- .../runtime-validation-source-audit.md | 299 +++ .../research/typescript-schema-orpc-audit.md | 853 +++++++ .../supervisor.md | 12 + .../worklog.md | 18 +- 8 files changed, 3625 insertions(+), 92 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md index cd193ec2ff..e66f694f1f 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -141,7 +141,25 @@ documentation. - **Actual:** No tracked file was affected. Auditors can still read the intact recoverable trash copy, so moving it again during their reads would create avoidable disruption. - **Severity:** operational -- **Action:** recover after active source audits finish, then verify RC HEAD and post-RC main object - again. Treat the trash copy as read-only evidence until then. -- **Evidence:** filesystem path and `.trashinfo` above; `git -C` against the trash copy returned - `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`. +- **Action:** recovered after both source audits finished. GIO no longer enumerated the intact trash + item despite its file and metadata being present, so it was moved directly back to the exact + recorded run-local path. +- **Evidence:** post-recovery `git -C .llm/tmp/prisma-v8-rc1 rev-parse HEAD` returned + `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`; `git cat-file` verified post-RC object + `71e2e0d9ee1f306b5a11435cd1973023cb33866a`. + +## 2026-08-13 — Opus bounded synthesis completed + +- **What:** The resumed native Opus report was successfully written in three bounded, marker-joined + sections after the monolithic write failure. +- **Source:** Native Claude Code session `f79af5bb-e953-4aae-9585-a1c83e73a00d`, observed model + `claude-opus-5`, effort `high`. +- **Expected:** One independent architecture report that preserves route/workflow provenance and + feeds plan lock without acting as PLAN-EVAL. +- **Actual:** `research/claude-opus-architecture-review.md` is complete at sixteen top-level + sections with no continuation marker. It records incomplete specialist lanes honestly and marks + carried Prisma claims that need the separate source-audit ledger. +- **Severity:** operational recovery +- **Action:** accept as a research input; reconcile its broader validation assumptions against the + later pinned-source validation audit before plan lock. +- **Evidence:** report section index and native turn receipts for parts 1–3. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md new file mode 100644 index 0000000000..4401cc3f05 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md @@ -0,0 +1,2004 @@ +# Independent Database Architecture Deep Dive — Claude Opus 5 High + +Subordinate architecture/research lane for run `docs-database-architecture-rfc--prisma-8-rfc`. This +is **not** PLAN-EVAL. It is an independent report intended to be consumed by the supervisor when +locking the Plan-Gate. + +Part 1 of 3. Continuation marker at end of file. + +--- + +## 1. Route identity, evidence provenance, and lane disclosures + +### 1.1 Requested versus observed identity + +| Field | Requested (brief) | Observed (this session) | +| ------------ | ------------------------------------------------------ | ---------------------------------------------------- | +| Provider | Anthropic | Anthropic | +| Surface | Native Claude Code | Native Claude Code CLI, `CLAUDE_CODE_ENTRYPOINT=cli` | +| Model | Opus 5 | `claude-opus-5` | +| Effort | high | `CLAUDE_EFFORT=high` | +| Client build | — | Claude Code `2.1.231` (`CLAUDE_CODE_EXECPATH`) | +| Host | `/home/codex/repos/netscript-db-rfc` | same; WSL2 Linux 6.18.33.2, user `codex` | +| Branch | `docs/database-architecture-rfc` | same | +| Baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | same | + +**Session/handle chain.** This lane spanned three process boundaries. The original architecture +session was `3f8a9a69-5589-4b91-9a32-91f7770fe7c2` (`CLAUDE_CODE_CHILD_SESSION=1`, bridge handle +`session_01JusEvesoAn7Jjo2EDPPMcZ`, PID 1944525, job dir `/home/codex/.claude/jobs/3f8a9a69`). It +performed the required reading, the specialist fan-out, and the direct source verification recorded +below, then exited at a bridge boundary immediately after creating the report placeholder. The +resumed session is `f79af5bb-e953-4aae-9585-a1c83e73a00d`, which performed the targeted gap-closing +reads and authored this report. Model and effort are identical across both. + +### 1.2 Workflow and sub-agent disclosures + +No Claude dynamic **Workflow** was used. The Workflow tool was not invoked at any point in this +lane; CLAUDE.md scopes Claude workflows to a supervisor accelerator and this lane's work was +evidence extraction plus synthesis, which fan-out sub-agents served directly. Delegation used the +`Agent` tool only. + +| Identifier | Role | Model | Status | Consumed? | +| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------ | ----------------------------------------------- | ------------------------------------------------------------------------------------ | +| `a1dc0e7df5546aa82` | NetScript doctrine, archetype definitions, gate matrix, Plan-Gate text, arch-debt scan, RFC process/template extraction | inherited (Opus 5) | **completed** | **Yes — fully.** Load-bearing for §3 and for every doctrine citation in this report. | +| `a37ac7656406f51bb` | Prisma 8 RC control-plane + runtime + contract-space API signature extraction | inherited (Opus 5) | **lost at process exit; no result returned** | No | +| `a34be5940cff46313` | Adversarial falsification of the Prisma deep-dive's numeric claims | inherited (Opus 5) | **lost at process exit; no result returned** | No | +| `a81f742dd6bc62971` | Adversarial fact-check of the NetScript current-state audit | inherited (Opus 5) | **lost at process exit; no result returned** | No | +| `a0529d68dcea25a85` | Relaunch: Prisma RC numeric + seam re-verification | Sonnet | **stopped at process exit; no result returned** | No | +| `a540186ffe4827b0e` | Relaunch: NetScript db CLI/resolver/installer re-verification | Sonnet | **stopped at process exit; no result returned** | No | + +**Truthful disclosure.** Five of six sub-agents returned nothing. One returned a complete result. +Everything in this report that is marked `[OBSERVED]` was therefore verified either by the completed +doctrine agent or by my own direct reads and greps in this worktree, cited by `path:line`. Claims +that originate only in the committed research documents and that I could **not** re-verify in this +session are explicitly marked `[CARRIED — NOT RE-VERIFIED]`. They must be re-proved before the +canonical RFC cites them; I flag this as a Plan-Gate obligation in Part 3. + +### 1.3 Evidence vocabulary used throughout + +- `[OBSERVED]` — I read the file or ran the command in this worktree; citation given. +- `[CARRIED — NOT RE-VERIFIED]` — asserted by `research/netscript-current-state.md`, + `research/prisma-8-deep-dive.md`, or `research/market-analysis.md`; plausible; not independently + confirmed here. +- `[INFERENCE]` — my reasoning from observed facts. +- `[PROPOSAL]` — my design recommendation. + +### 1.4 Precision corrections applied + +Per the supervisor's correction, and used consistently from here on: the root catalog pins Prisma at +`^7.8.0`; generated workspace templates encode `^7.4.2`; the generated database workspace currently +emits **30** database tasks (the current-state audit's "more than twenty" understates it). RC-tag +facts (`v8.0.0-rc.1`, `a76a6c5`) are kept strictly separate from post-RC `main` churn (`71e2e0d`) +everywhere in this report; where a claim depends on post-RC main it is labelled as moving, never as +a contract. + +--- + +## 2. Independent verdict and architectural thesis + +### 2.1 Verdict + +**The direction in the committed research is correct, and its central abstraction is named wrong in +a way that will produce the wrong package if it is carried into the RFC unchanged.** + +I agree with the research on the substance: five overlapping subsystems must collapse into one +NetScript-owned model; Prisma 8's contract/control/runtime split is the right shape to integrate +against; contract spaces are the right ownership primitive; engine-as-identity must die; generated +source must stop being textually patched; offline work must stop requiring Aspire. Those conclusions +survive independent scrutiny. + +I disagree on three points that change the design: + +1. **`DatabaseGraph` is correct as a compile-time intermediate representation and wrong as a runtime + object.** A "graph" that exists at runtime, that features can reach into to obtain a target, is a + service locator wearing a domain name. The durable artifact is not a graph — it is a **compiled, + content-addressed manifest**, which is a _value_: diffable, cacheable, signable, transportable to + CI, consumable by agents, and comparable across builds. A graph is how you build it, not what you + ship. Everything the research wants from `DatabaseGraph` — inspection, provenance, digests, agent + surface, deterministic CI — are properties of a manifest, not of a live object graph. + +2. **The plan's archetype set is incomplete and therefore its gate set is under-scoped.** The plan + names future Archetype 1/2/4/5/6 surfaces. The runtime half of this system owns connection + lifetime, per-request and per-process scope, graceful close ordering, health/readiness, and + `AbortSignal` propagation. That is Archetype 3 — "packages that own long-running behavior with + state, lifecycle, and supervised execution" (`docs/architecture/doctrine/06-archetypes.md:78-83`) + `[OBSERVED]`. Archetype 3 makes **all** fitness gates F-1 through F-19 required and makes + **runtime gates required**, not optional (`.llm/harness/gates/archetype-gate-matrix.md:20-65`) + `[OBSERVED]`. Omitting A3 silently omits a mandatory gate column. + +3. **A repo-wide constraint that no research document mentions determines the package boundary.** + NetScript compiles with `isolatedDeclarations: true` repo-wide (`deno.json` `compilerOptions`) + `[OBSERVED]`, and doctrine restricts the `--allow-slow-types` carve-out to oRPC-bound packages + only — `packages/contracts` and plugin `-core`/`services` packages extending the contract base + classes — with the explicit rule that "any other package that sets `--allow-slow-types` is a + finding and must carry a debt entry" (`docs/architecture/doctrine/02-public-surface.md:217-242`) + `[OBSERVED]`. A database package is not covered. Prisma 8's application-facing type is derived by + inference from the emitted contract. **Therefore no published `@netscript/*` package may export a + contract-typed runtime value.** This is not a stylistic preference; it is a hard publishability + constraint that decides where the typed binding lives. I develop the consequence in §3 and §5. + +### 2.2 Thesis + +> NetScript's durable database asset is a **compiled manifest plus a narrow provider port**, not a +> database abstraction. NetScript owns _identity, composition, ownership, lifecycle, and +> operations_. The provider owns _language, execution, and diffing_. NetScript never abstracts the +> query surface — it delivers a correctly-scoped, lifecycle-owned, target-typed handle and gets out +> of the way. + +The single most valuable rule in this design is a refusal: **NetScript does not define a query +API.** Every framework that has tried to sit above an ORM and normalise its query surface has +produced a second, worse ORM with a smaller feature set and a larger bug budget. The research names +this risk ("Replacing manual glue with a larger proprietary abstraction", `plan.md` risk register) +but does not convert it into a structural rule. The structural rule is: the kernel packages contain +**zero query types**. The query surface reaches the application as a generic type parameter that the +application's own generated code supplies. If a future provider replaces Prisma, the kernel does not +change shape; only the generic argument does. + +### 2.3 Non-negotiable invariants + +These are the properties I would refuse to trade in review. Each is stated so it can be mechanically +checked. + +- **I-1 Identity is declared, never derived.** A target's identity is a user-chosen stable key. No + artifact path, migration lineage, runtime binding, receipt, or output root may be derived from a + provider or engine name. +- **I-2 One owner per storage object.** Every owned object resolves to exactly one contribution + space. Overlapping ownership is a compile-time error, not a runtime collision. +- **I-3 Composition is pure.** Compiling a definition into a manifest performs no network, no + database, no Aspire, and no process spawn. It is a total function from source to + `Result`. +- **I-4 Determinism is content-addressed.** The same inputs produce the same manifest digest; every + emitted artifact root records the digest that produced it; a mismatch is detectable without a + database. +- **I-5 No generated source is ever textually repaired.** Artifacts are produced from an IR by a + provider and replaced atomically, or they are not produced. +- **I-6 Nothing reports success from an exit code.** Every operation returns a typed result and a + receipt with per-target, per-space phase outcomes. +- **I-7 Capability requirements fail early.** A space that needs a capability the target cannot + provide fails at composition or type-check, never at a late database call. +- **I-8 No published NetScript package re-exports upstream provider types.** Enforced by doctrine + AP-14 (`09-anti-patterns-and-fitness-functions.md:112-116`) `[OBSERVED]` and by the + slow-types/`isolatedDeclarations` constraint in §2.1(3). +- **I-9 Cross-target atomicity is never claimed.** Multi-target apply is a resumable saga with + explicit partial-success reporting. +- **I-10 Data is never destroyed implicitly.** Uninstall, removal, and destructive plan steps + require an explicit, environment-aware policy decision; the default is retention. + +### 2.4 What this redesign explicitly is not + +Stating the refusal boundary is as load-bearing as stating the design; +`rfcs/0003-command-composition-kit.md` carries a "Precise refusal boundary" subsection for exactly +this reason `[OBSERVED]`. + +- **Not a query abstraction.** No `Repository`, no portable `findMany`, no NetScript query DSL. +- **Not a portability layer.** NetScript will not make PostgreSQL and SQLite look identical. + Provider differences are surfaced as capabilities, not hidden behind a lowest common denominator. +- **Not a compatibility layer.** No Prisma 7 facade, no legacy generated module, no alias barrel, no + `setClient` lifecycle, no runtime shim. Data migration safety is required; API compatibility is + not. +- **Not a schema language.** NetScript does not invent a third model DSL. The application's data + contract stays in the provider's authoring language. NetScript's DSL composes _targets, spaces, + policy, capabilities, and lifecycle_ — never entities. +- **Not a control plane product.** Atlas-class semantic lint, promotion pipelines, and hosted policy + registries are out of scope; the plan/approve/apply/verify _state machine_ is in scope so that + such a backend could be added later as one more adapter. +- **Not an implementation.** This is a design report feeding an RFC. Nothing here authorises code. + +--- + +## 3. Target package, ownership, and dependency graph + +### 3.1 Doctrine constraints that decide the shape + +Four doctrine rules bind the partition, all `[OBSERVED]` via the completed doctrine agent: + +- **One archetype per package.** "If two archetypes apply, choose the larger one and fold the + smaller concerns inside it. Do not split one package across two archetypes" + (`.llm/harness/archetypes/README.md:23-26`). Where two archetypes genuinely apply and neither can + be folded without harming the other's gate profile, the correct move is **two packages**, not one + package with two shapes. That is the reasoning behind splitting definition from runtime below. +- **Ports are small.** AP-3 caps a port at three or four methods and names "a port with every + operation the backend can perform" as the integration-package failure mode + (`09-anti-patterns-and-fitness-functions.md:46-52`; `ARCHETYPE-2-integration.md:55`). The current + `DatabaseAdapter` — client lifecycle plus health plus status plus raw query plus + `setClient` — is a live AP-3 god interface and must be split, not renamed. +- **Engine selection is a typed registry, never a switch.** AP-24's canonical counter-example is + literally a database-engine switch over `'postgres' | 'mysql' | 'sqlite'` + (`09-anti-patterns-and-fitness-functions.md:167-198`). The current `mapEngine` switch in + `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:96+` is that anti-pattern in the + shipped code `[OBSERVED]`. +- **Surface size is capped.** F-5 caps a `mod.ts` at ~20 exported symbols and subpaths are semver + surface (`02-public-surface.md:111-138`). + +### 3.2 The packages + +Names are indicative; the archetype assignment and the dependency direction are the contribution. + +| Package | Archetype | Owns | Must not contain | +| ------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `@netscript/database-contract` | **1 — Small Contract** | Branded identities, manifest schema, capability vocabulary, ownership policy vocabulary, diagnostic/error code catalog, operation request/result/receipt/progress types, the contribution-space descriptor type, and the port _interfaces_ shared by more than one consumer. Pure types and small invariants; no IO. | Any runtime, any provider, any query type, any Prisma import. | +| `@netscript/database` | **4 — Public DSL / Builder** | `defineTarget`, `defineSpace`, `defineDatabase`, and the pure compiler `compileDatabase(definition) → Result`. Frozen definition objects; one file per builder concern per `06-archetypes.md:127-155`. | IO, connections, provider packages, Aspire, filesystem access other than through an injected port. | +| `@netscript/database-runtime` | **3 — Runtime / Behavior** | Binding a manifest + provider to live connections; process and request scope; connection lifetime; graceful close ordering; health/readiness; `AbortSignal` propagation; `{ stop() }` handles; diagnostics normalisation. | Query types, migration logic, CLI presentation, Prisma imports. | +| `@netscript/database-control` | **2 — Integration** | The operation plane behind small ports: emit, plan, apply, verify, introspect. Owns locking, receipts, resume, plan expiry, destructive policy, and cross-target sequencing. | Provider-specific SQL, query surface, Aspire specifics. | +| `@netscript/database-prisma-postgres` | **2 — Integration** | The _only_ package permitted to import `@prisma/orm-*`. Supplies a capability descriptor, a contract emitter, a control adapter, and a runtime factory. Independently versioned and released. | Being imported by anything except an application composition root and the testkit. | +| `@netscript/database-testkit` | **6 — CLI / Tooling** | Provider conformance certification as user-run automation: a runnable suite that certifies a provider against the capability contract and emits a machine-readable conformance report. | Being a dependency of any runtime package. | +| `@netscript/cli` (existing, A6) | **6 — CLI / Tooling** | The `db` command surface as a _projection_ of the control operation catalog, plus generated agent-manifest emission. | Any database logic not reachable through `@netscript/database-control`. | +| `@netscript/aspire` (existing, A2) | **2 — Integration** | One `ConnectionSourcePort` adapter that resolves an allocated Aspire endpoint. | Being required by any package for non-Aspire connection sources. | +| `@netscript/plugin` (existing, A4) | **4 — DSL / Builder** | `defineDatabaseSpace`, typed **only** by `@netscript/database-contract`. | Depending on `-runtime`, `-control`, or any provider — otherwise every plugin drags a driver into its graph. | + +**Why definition and runtime are two packages.** They have incompatible gate profiles and +incompatible dependency needs. The definition/compiler package must be usable in a CI job with no +driver, no database, and no provider installed — that is what makes offline determinism and +stale-artifact detection cheap. The runtime package owns lifecycle and therefore carries Archetype +3's mandatory runtime-gate column. Folding them produces a package that is either over-gated when +used as a pure compiler or under-gated when used as a runtime. Doctrine's "do not split one package +across two archetypes" is satisfied by splitting the _packages_, which is the intended remedy. + +**Why control is separate from runtime.** Control operations are transactional, one-shot, and +frequently offline. Runtime operations are long-lived and connection-scoped. They share the manifest +and nothing else. Merging them reproduces the current failure in which a read-only database command +had to own the resident AppHost lifecycle. + +### 3.3 Dependency directions + +```text + @netscript/database-contract (A1, leaf, zero deps) + ^ ^ ^ ^ + | | | | + @netscript/database -runtime -control @netscript/plugin + (A4) (A3) (A2) (A4) + ^ ^ ^ + | | | + +--------+---------+ + | + @netscript/database-prisma-postgres (A2, leaf on the far side) + ^ + | + @netscript/database-testkit (A6) + + application composition root -> -database, -runtime, -control, one provider, emitted contract +``` + +Rules, each mechanically checkable: + +1. `-contract` imports nothing from this family. It is the only package every other member may + depend on. +2. `-database` (A4) depends on `-contract` only. It never imports a provider. +3. `-runtime` and `-control` depend on `-contract` and may depend on `-database` for manifest types + they do not redeclare. They never import each other, and never import a provider. +4. Provider packages depend on `-contract` and on upstream. **Nothing in the framework depends on a + provider.** Providers are selected by the application, passed in as a value. +5. `@netscript/plugin` depends on `-contract` only. This is the rule that keeps `pg` out of every + plugin's dependency graph. +6. The testkit may depend on everything; nothing may depend on the testkit. + +### 3.4 Ownership map — which concept is a durable public contract + +This resolves the minimal-kernel tension the brief asks about explicitly: not everything in this +design is public API, and conflating the two is how the current system grew five overlapping +subsystems. + +| Concept | Status | Rationale | +| ----------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| Target identity, space identity, namespace reference, object key | **Durable public data contract** (`-contract`) | These are the join keys for every artifact, receipt, and diagnostic. They must be stable across provider replacement. | +| Manifest schema and manifest digest | **Durable public data contract** | It is the CI/agent/runtime interchange format. Versioned with an explicit format version. | +| Capability vocabulary and ownership policy vocabulary | **Durable public data contract** | Plugins and providers both declare against it. | +| Diagnostic/error codes, operation request/result/receipt/progress types | **Durable public data contract** | The CLI, CI, and agent surfaces are projections of these; log parsing must become impossible. | +| Contribution-space descriptor | **Durable public data contract** | It is a third-party authoring surface. | +| `defineTarget` / `defineSpace` / `defineDatabase` | **Public API**, but a builder, not data | A4 surface; `defineX` returns a frozen definition per `02-public-surface.md:73-82`. | +| Provider ports (emitter, control, runtime factory, connection source) | **Public SPI**, small, each ≤4 methods | Third-party providers must be possible without forking. | +| The compiler's internal phases, graph structures, resolution order | **Internal** | Nobody outside needs them; publishing them freezes the implementation. | +| The provider registry instance | **Internal, constructed at the composition root** | Publishing a mutable registry is how a service locator is born. | +| The query surface | **Consumer-owned**, supplied as a generic argument | See §2.2 and §5.4. | +| The typed per-target binding | **Consumer-owned**, generated into the application | Forced by `isolatedDeclarations` + slow-types; see §2.1(3). | + +### 3.5 Doctrine registration obligations + +Two obligations follow that the plan does not currently carry `[OBSERVED]`, both from the doctrine +agent's extraction: + +- Every new package must be added to **both** `docs/architecture/doctrine/06-archetypes.md` + (archetype table, `:374-411`) and `docs/architecture/doctrine/10-codebase-verdict-and-handoff.md` + (verdict table, `:25-62`), because `discoverDoctrineRoots()` gates exactly the paths in that table + (`10:90-95`). An unregistered package is an ungated package. +- Doctrine currently **codifies the model this RFC removes**: Archetype 5 states that plugin schema + contributions "are plain `*.prisma` files referenced from `database/`. They do not contain a + private workspace" (`06-archetypes.md:209-211`). The RFC must amend doctrine, and amending + doctrine is itself an RFC trigger (`rfcs/README.md:14-32`). This is in scope for the same RFC, and + the plan should say so. + +--- + +## 4. The identity model + +Identity is where the current system fails first, so it is where the design must be most precise. +The current system collapses at least four distinct identities into the string `engine`. + +### 4.1 What is wrong today, observed + +- `workspaceDir` is computed as `join('database', provider.dirName)` where `provider` is looked up + from a closed engine enum (`packages/cli/src/kernel/adapters/database/workspace-resolver.ts:50`) + `[OBSERVED]`. Two PostgreSQL targets therefore share one schema tree, one migration history, one + generated client, and one task set. The identity of a _logical database_ has no representation. +- `resolveTarget` defaults only when exactly one target is enabled: + `if (!dbFlag && enabled.length === 1) return { kind: 'single', database: enabled[0] }` + (`workspace-resolver.ts:71-77`) `[OBSERVED]`. With two or more enabled targets and no `--db`, the + lookup falls through and throws `Unknown database target: (default)`. `NetScript.PrimaryDatabase` + is never consulted here. The audit's claim is confirmed, and the failure is a throw rather than a + silent wrong-target selection, which is the better of the two failure modes. +- The plugin installer's target-selection chain is + `enabled.find(configKey === primaryDatabase) ?? enabled[0] ?? databases[0]` + (`packages/cli/src/kernel/adapters/plugin/db-integration.ts:101-105`) `[OBSERVED]`. The final + fallback drops out of the `enabled` filter, so a plugin can be installed into a **disabled** + target. The audit does not surface this. +- `--db` accepts either a config key or an engine name, resolved by + `explicitDb.toLowerCase() as DbEngine` after a config-key lookup fails + (`db-integration.ts:275-300`) `[OBSERVED]`. Two identity spaces share one flag and one string + type. +- The config schema accepts provider aliases — `postgresql|postgres`, `mssql|sqlserver` + (`packages/config/src/domain/schemas/database-schema.ts`) `[OBSERVED]` — and `mapEngine` + normalises `'Postgres'|'postgres'` (`workspace-resolver.ts:96+`) `[OBSERVED]`. Two normalisation + sites for one concept. + +### 4.2 The proposed identities + +Each is a branded primitive, which doctrine sanctions for non-interchangeable ids +(`02-public-surface.md:85-99`) `[OBSERVED]`. + +| Identity | Shape | Stability | Derived from | +| ------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| **TargetId** | `'primary'`, `'analytics'` | Permanent; renaming is a breaking migration | Author's choice. **Never** a provider name. | +| **ConnectionProfileId** | `'local'`, `'ci'`, `'production'` | Per environment | Author's choice; orthogonal to TargetId. | +| **RoleRef** | `(TargetId, 'writer' \| 'reader:')` | Derived | A replica is a _role of a target_, not a target. | +| **NamespaceRef** | `(TargetId, namespace)` | Permanent | Author's choice; a physical schema inside one database. | +| **SpaceId** | `'app'`, `'plugin:@netscript/plugin-auth'` | Permanent per contributor | Package identity for plugin spaces; fixed literal for the app. | +| **ObjectKey** | `(TargetId, namespace, entryKind, name)` | Derived | The unit of ownership; I-2 is stated over this key. | +| **ContractSnapshotId** | content hash of a space's canonicalised contract | Derived | Content-addressed. | +| **MigrationNodeRef** | `(SpaceId, ContractSnapshotId)` + optional human ref | Derived + author's label | Lineage nodes are content-addressed; names are labels, not identity. | +| **HeadRef** | `(SpaceId, TargetId) → MigrationNodeRef` | Mutable state | Recorded both in the manifest (intent) and in the database marker (fact). Divergence is drift. | +| **ManifestDigest** | content hash over the canonical manifest | Derived | The determinism anchor (I-4). | +| **PlanId** | `hash(ManifestDigest, TargetId, baselineFingerprint, providerPackageSet, policy)` | Derived | Binds a plan to everything that could invalidate it. | +| **RunId** / **ReceiptId** | ULID-like, supplied by the caller or generated at the edge | Per execution | Receipts are addressable and resumable. | +| **SessionScope** | `'process' \| 'request'` | Per binding | A _type-level_ discriminator, not a config flag. | + +Three deliberate consequences: + +1. **Provider is an attribute of a target, never its identity.** `primary` and `analytics` may both + be PostgreSQL and share nothing. This is the single change that makes + `db add postgres --name + analytics` mean what users already believe it means. +2. **A replica is not a target.** Modelling replicas as targets is how Rails users end up migrating + a read replica. A role is a binding-time choice with a read-only runtime type; migrations are + defined over targets and cannot address a reader role at all. +3. **Scope is a type, not a flag.** The request-scoped runtime and the process-scoped runtime are + different types with different capabilities. Prisma's serverless facade already demonstrates that + the asymmetry is real rather than cosmetic `[CARRIED — NOT RE-VERIFIED]`; making it a type + prevents the class of bug where a closure caches a per-request handle. + +### 4.3 Invariants over the identity model + +Compilation is the enforcement point. Each invariant maps to a diagnostic code (Part 2 carries the +catalog). + +- **V-1** Every `SpaceId` binds to exactly one `TargetId`. A space never spans databases. +- **V-2** Every `ObjectKey` has exactly one owning space with `ownership: 'managed'`. Two managed + owners is an error; a managed owner overlapping an `external` declaration is an error. +- **V-3** Cross-space references are legal only within one `TargetId` **and** only along a declared + `dependsOn` edge. A relation across targets is an error with a next-action that points at the + application-level composition pattern instead. +- **V-4** The space dependency graph is acyclic; execution order is its topological order, and the + order is recorded in the manifest so it is reviewable rather than emergent. +- **V-5** Every space's `requires` capability set is a subset of its target's provider capability + set, checked at compile time and, where expressible, at type-check time. +- **V-6** No two targets share an output root, a migration root, or a runtime binding key. +- **V-7** `ManifestDigest` is a pure function of the definition plus the resolved space contract + snapshots plus the provider package set. Nothing environmental participates. +- **V-8** Every emitted artifact root records the `ManifestDigest` that produced it. Runtime binding + refuses a mismatch with a diagnostic naming the exact command to run. + +--- + +## 5. Public API and DSL sketches + +These are implementation-grade sketches, not nouns. They are written to satisfy +`isolatedDeclarations` — every exported symbol has an explicit type — and to keep every published +type free of upstream generics. + +### 5.1 Identities and the manifest (`@netscript/database-contract`, A1) + +```ts +/** Author-chosen stable identity of one logical database. Never a provider name. */ +export type TargetId = string & { readonly __targetId: unique symbol }; +/** Author-chosen stable identity of one schema-contributing owner. */ +export type SpaceId = string & { readonly __spaceId: unique symbol }; +/** Content address of one space's canonicalised contract. */ +export type ContractSnapshotId = string & { readonly __snapshot: unique symbol }; +/** Content address of a compiled manifest. */ +export type ManifestDigest = string & { readonly __digest: unique symbol }; + +/** How much authority NetScript has over a set of storage objects. */ +export type OwnershipPolicy = 'managed' | 'adopted' | 'external' | 'ignored'; + +/** One capability a provider may offer and a space may require. */ +export type CapabilityId = string & { readonly __capability: unique symbol }; + +/** Fully-resolved, serialisable composition output. The CI/agent/runtime interchange format. */ +export interface DatabaseManifest { + readonly formatVersion: 1; + readonly digest: ManifestDigest; + readonly targets: readonly ManifestTarget[]; + readonly spaces: readonly ManifestSpace[]; + /** Topological execution order over spaces; recorded so review sees it. */ + readonly spaceOrder: readonly SpaceId[]; + readonly providerSet: readonly ProviderPin[]; +} + +export interface ManifestTarget { + readonly id: TargetId; + readonly family: string; + readonly provider: ProviderPin; + readonly namespaces: readonly string[]; + readonly capabilities: readonly CapabilityId[]; + readonly roles: readonly TargetRole[]; + readonly outputRoot: string; + readonly migrationRoot: string; + readonly policy: TargetPolicy; +} + +export interface ManifestSpace { + readonly id: SpaceId; + readonly version: string; + readonly target: TargetId; + readonly ownership: OwnershipPolicy; + readonly requires: readonly CapabilityId[]; + readonly dependsOn: readonly SpaceId[]; + readonly owns: readonly ObjectKey[]; + readonly snapshot: ContractSnapshotId; + readonly removal: RemovalPolicy; +} + +export interface ObjectKey { + readonly target: TargetId; + readonly namespace: string; + readonly entryKind: string; + readonly name: string; +} +``` + +Note what is absent: no provider types, no query types, no generics that could become slow types. +`DatabaseManifest` is plain data and can be serialised, hashed, diffed, and shipped to CI. + +### 5.2 The definition DSL (`@netscript/database`, A4) + +```ts +export interface TargetDefinition { + readonly id: TId; + readonly provider: ProviderDescriptor; + readonly connection: ConnectionSourceRef; + readonly namespaces: Readonly>; + readonly roles?: Readonly>; + readonly policy: TargetPolicy; +} + +/** Frozen definition; performs no runtime work. */ +export declare function defineTarget( + input: TargetInput, +): TargetDefinition; + +export declare function defineSpace( + input: SpaceInput, +): SpaceDefinition; + +export interface DatabaseDefinition< + TTargets extends Readonly>>, + TSpaces extends readonly SpaceDefinition>[], +> { + readonly targets: TTargets; + readonly spaces: TSpaces; +} + +export declare function defineDatabase< + TTargets extends Readonly>>, + TSpaces extends readonly SpaceDefinition>[], +>( + input: { readonly targets: TTargets; readonly spaces: TSpaces }, +): DatabaseDefinition; + +/** Pure. No network, no database, no Aspire, no process spawn. */ +export declare function compileDatabase( + definition: DatabaseDefinition, + sources: ContractSourceReader, +): Promise; + +export type CompileResult = + | { + readonly ok: true; + readonly manifest: DatabaseManifest; + readonly warnings: readonly Diagnostic[]; + } + | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] }; +``` + +Authoring, as a user would write it: + +```ts +// database.ts — the whole database story in one reviewable file +import { defineDatabase, defineSpace, defineTarget, prismaSchema } from '@netscript/database'; +import { postgres } from '@netscript/database-prisma-postgres'; +import { fromAspire, fromEnv } from '@netscript/database/connection'; +import { authDatabaseSpace } from '@netscript/plugin-auth/database'; + +const primary = defineTarget({ + id: 'primary', + provider: postgres({ minVersion: 15 }), + connection: fromAspire('netscript-db'), + namespaces: { app: 'public', auth: 'auth' }, + roles: { writer: {}, 'reader:reporting': { readOnly: true } }, + policy: { destructive: 'deny', defaultOwnership: 'managed' }, +}); + +const analytics = defineTarget({ + id: 'analytics', // same provider, different database, zero shared state + provider: postgres({ minVersion: 15 }), + connection: fromEnv('ANALYTICS_DATABASE_URL'), + namespaces: { warehouse: 'warehouse' }, + policy: { destructive: 'plan-only', defaultOwnership: 'adopted' }, +}); + +export const database = defineDatabase({ + targets: { primary, analytics }, + spaces: [ + defineSpace({ + id: 'app', + target: 'primary', // compile error if not a key of `targets` + namespace: 'app', + source: prismaSchema('./database/app'), + ownership: 'managed', + }), + authDatabaseSpace({ target: 'primary', namespace: 'auth' }), + ], +}); +export type AppDatabase = typeof database; +``` + +`target: 'primary'` is checked against `keyof typeof targets`. Misrouting a space is a type error at +the authoring site, not a runtime surprise at install time — which is precisely the class of failure +the plugin installer's `?? databases[0]` fallback produces today `[OBSERVED]`. + +### 5.3 Typed target references and composition (`@netscript/database-runtime`, A3) + +```ts +/** Scope is a type, not a flag: the two shapes are not interchangeable. */ +export type SessionScope = 'process' | 'request'; + +export interface TargetSession { + readonly id: TId; + readonly scope: TScope; + /** The provider's own surface, supplied by the application. NetScript never names it. */ + readonly query: TQuery; + health(signal: AbortSignal): Promise; +} + +/** Interactive transactions exist only on process scope. */ +export interface ProcessTargetSession + extends TargetSession { + transaction(fn: (tx: TQuery) => Promise, options?: TransactionOptions): Promise; +} + +/** Request scope is disposable and carries no cached collaborators. */ +export interface RequestTargetSession + extends TargetSession, AsyncDisposable {} + +/** Long-running handle, per Archetype 3 doctrine. */ +export interface DatabaseRuntime { + stop(): Promise; + health(signal: AbortSignal): Promise; +} + +export declare function createDatabaseRuntime( + options: DatabaseRuntimeOptions, +): Promise; +``` + +Two design points worth defending in review: + +- **`query` is a generic parameter, never a declared type.** This is what keeps every published + NetScript package free of upstream generics and therefore free of the slow-types problem in + §2.1(3). It also means replacing the provider changes one type argument, not the kernel. +- **`transaction` exists only on `ProcessTargetSession`.** The current `withTransaction` types its + callback parameter as the _full_ client — + `withTransaction(client: Client, fn: (tx: Client) => Promise, ...)` + with an unchecked cast (`packages/database/mod.ts:128-140`) `[OBSERVED]` — so + `tx.$transaction(...)` type-checks inside an interactive transaction. That is a type-level + correctness defect, not merely an unsafe cast; the current-state audit's phrase + "structurally-cast" understates it. + +### 5.4 The generated application composition root + +This is where the typed binding lives, and the reason is structural rather than stylistic: the +application is not published to JSR, so it may use inference freely; a framework package may not. + +```ts +// .netscript/database/primary.binding.ts — GENERATED. Do not edit. digest: +import contract from './primary/contract.json' with { type: 'json' }; +import type { PrimaryContract } from './primary/contract.d.ts'; +import { createPostgresQuery } from '@netscript/database-prisma-postgres/runtime'; +import type { ProcessTargetSession } from '@netscript/database-runtime'; + +export type PrimaryQuery = ReturnType>; +export type PrimarySession = ProcessTargetSession<'primary', PrimaryQuery>; +export const PRIMARY_MANIFEST_DIGEST = '' as const; +``` + +```ts +// composition-root.ts — hand-written, small, and the only place a target is looked up by name +const runtime = await createDatabaseRuntime({ + manifest, + definition: database, + providers: [postgresProvider], + targets: ['primary'], + scope: 'process', + connections, +}); +const primary: PrimarySession = runtime.bind('primary'); +const accounts: AccountStore = new PrismaAccountStore(primary); +``` + +**The service-locator boundary.** `runtime.bind()` is legal only in a composition root. Feature code +receives `AccountStore`, not the runtime — doctrine A10 requires exactly this +(`01-thesis-and-axioms.md:78-82`) `[OBSERVED]`, and a database handle reachable from anywhere is the +service locator the brief asks me to guard against. This is enforceable as an `arch:check` rule +(reachability of `bind`/`target` outside declared composition-root files), and Part 3 lists it as a +required fitness gate rather than a convention. + +### 5.5 Contract-derived validation + +The owner-provided Prisma-maintainer exchange establishes an important hypothesis: **the contract +carries enough runtime data to derive validation without a second generation step.** I treat this as +primary exploratory evidence and as a design hypothesis, **not** as an upstream commitment — Part 3 +records it as a decision checkpoint conditional on Prisma 8 final. + +The architectural consequence, if the hypothesis holds, is significant: the entire "generate Zod, +then rewrite its imports, then fix circular references, then rewrite getters, then patch decimals, +then emit an alias barrel, then fix it again" pipeline has no reason to exist. Validation becomes a +_derivation from data already present_, cached by contract identity. + +```ts +/** Standard Schema is the boundary contract; NetScript does not re-export a validator. */ +import type { StandardSchemaV1 } from '@standard-schema/spec'; + +export interface ContractSchemas { + input, TOp extends 'create' | 'update'>( + model: K, + op: TOp, + ): StandardSchemaV1>; + output>( + model: K, + ): StandardSchemaV1>; +} + +/** + * Default: derived at runtime from the contract, memoised by contract identity. + * No generation step, no emitted validator source, nothing to keep in sync. + */ +export declare function contractSchemas( + contract: ContractRuntime, + options?: { readonly cache?: SchemaCache }, +): ContractSchemas; +``` + +Three rules govern this surface: + +1. **Runtime-derived is the default.** Cached by contract identity (the emitted contract's own hash + plus model plus operation), so derivation happens once per process per shape. +2. **Any ahead-of-time form is an optional optimisation that must be observationally equivalent.** + An AOT emitter may exist for cold-start-sensitive deployments, but it is not the source of truth, + and a conformance case must assert that AOT and runtime-derived schemas accept and reject the + same corpus. If they can diverge, the AOT path is a second model universe and is rejected. +3. **NetScript exposes Standard Schema, not a validator.** `@standard-schema/spec` is already a + NetScript dependency (`packages/plugin/deno.json`, `packages/sdk/deno.json`) `[OBSERVED]`, and + doctrine AP-14 forbids re-exporting upstream packages + (`09-anti-patterns-and-fitness-functions.md:112-116`) `[OBSERVED]`. Consumers who want Zod import + Zod and adapt. + +This also removes a contradiction in the current core config contract: `DatabaseConfigSchema` +hardcodes a `zodGenerator` block with an `output` path and a `mode` enum +(`packages/config/src/domain/schemas/database-schema.ts`) `[OBSERVED]`, which bakes one validator +choice into the framework's configuration vocabulary. Under this design the config vocabulary +carries no validator at all. + +--- + +## 6. Contribution protocol: how a package owns part of a database + +### 6.1 What exists today, observed + +The current-state audit describes plugin schema contribution as "plugins declare schema by shipping +plain `database/**/*.prisma` files". That is true of the _runtime behaviour_, but it misses that +NetScript already publishes a contribution protocol which nothing implements: + +- `ContributionAxis` is a closed union that already contains `'database-schema'` and `'migration'` + (`packages/plugin/src/domain/constants.ts:16-26`) `[OBSERVED]`. +- `PluginDbSchemaContribution` is an exported abstract class with `axis = 'database-schema'`, an + abstract `path: string`, and an abstract `engine?: 'postgres' | 'mysql' | 'mssql' | 'sqlite'` + (`packages/plugin/src/abstracts/plugin-db-schema-contribution.ts`) `[OBSERVED]`. + `PluginMigrationContribution` adds `name` and `path` + (`packages/plugin/src/abstracts/plugin-migration-contribution.ts`) `[OBSERVED]`. Both are exported + from `@netscript/plugin/abstracts`. +- A repository-wide grep for implementations returns none: the only hits are the definitions, the + barrel re-exports, and an axis-list unit test `[OBSERVED]`. + +So the published contribution surface is hollow, and the four first-party plugins bypass it entirely +with plain fragments. Three consequences follow that the research does not state: + +1. **The clean break is a breaking change to `@netscript/plugin` (Archetype 4), not only to + `@netscript/database`.** Removing or replacing `PluginDbSchemaContribution`, + `PluginMigrationContribution`, and two members of the `ContributionAxis` union changes a + published package's public surface. The plan scopes future A1/A2/A4/A5/A6 surfaces but never + scopes this removal. +2. **The abstract already repeats the identity collapse.** + `engine?: 'postgres' | 'mysql' | 'mssql' | + 'sqlite'` is optional and names an engine, not a + target. Even the intended protocol could not express "this contribution belongs to the + `analytics` target". +3. **The fragments are already provider-locked while declaring nothing.** Across the four + first-party plugin schemas the native type attributes used are `@db.VarChar`, `@db.Text`, and + `@db.Uuid`, with `@db.Uuid` appearing in `plugins/triggers/database/triggers.prisma:13`, + `plugins/workers/database/workers.prisma:219`, and `plugins/sagas/database/sagas.prisma:57` and + `:179` `[OBSERVED]`. `@db.Uuid` is PostgreSQL-specific. Meanwhile the installer's + target-selection chain ends in `?? databases[0]`, which escapes the `enabled` filter + (`packages/cli/src/kernel/adapters/plugin/db-integration.ts:101-105`) `[OBSERVED]`. Today a + plugin whose schema only compiles on PostgreSQL can be copied into a disabled MySQL target, and + nothing in the pipeline objects until Prisma fails to parse. + +Model naming reinforces the point: `plugins/auth` and `plugins/sagas` prefix their declarations +(`AuthUser`, `SagaInstance`), while `plugins/workers` and `plugins/triggers` do not +(`JobDefinition`, `TaskDefinition`, `WrapperType`, `TriggerEvent`, `TriggerDefinition`) +`[OBSERVED]`. The namespacing remedy from the historical collision fix was applied where the +collision happened, not as a protocol. `JobDefinition` remains a globally-scoped name in a shared +declaration space. + +Finally, the contribution's _capability declaration_ today is a boolean: `scaffold.plugin.json` +carries `capabilities.hasDatabaseMigrations: true` (`plugins/workers/scaffold.plugin.json`) +`[OBSERVED]`. Plugin-level ordering exists (`officialSource.dependencies: ["streams"]`) but is not +connected to schema ordering. + +### 6.2 The contribution DSL + +A contribution is a **space**: a versioned owner of a disjoint set of storage objects, with its own +lineage. It is declared with types from `@netscript/database-contract` only, so a plugin that +contributes schema does not acquire a driver dependency. + +```ts +// plugins/auth/database/space.ts +import { defineDatabaseSpace, sql } from '@netscript/plugin/database'; +import { CAP } from '@netscript/database-contract/capabilities'; + +export const authDatabaseSpace = defineDatabaseSpace({ + id: 'plugin:@netscript/plugin-auth', + version: '0.0.7', + contractFormat: '>=1 <2', + + /** Declared, not inferred. Composition fails if the target cannot satisfy these. */ + requires: [CAP.sqlFamily, CAP.nativeUuid, CAP.caseInsensitiveText], + + /** Ordering is a declared edge, not install order. */ + dependsOn: [], + + /** Everything this space owns, and nothing else may own. */ + owns: { namespace: 'auth', entries: ['user', 'session', 'account', 'verification'] }, + + /** What another space may add to this space's objects, and what it may never touch. */ + augmentation: { + grants: [{ entry: 'user', kind: 'add-optional-column', prefix: 'x_' }], + denies: ['drop-column', 'change-type', 'add-required-column'], + }, + + ownership: 'managed', + + /** Uninstall is a plan, never a delete. */ + removal: { default: 'retain', allowed: ['retain', 'archive'], dropRequires: 'explicit-consent' }, + + source: sql.schema(import.meta.resolve('./contract.ts')), +}); +``` + +The consuming application binds it to a target explicitly: + +```ts +spaces: [authDatabaseSpace({ target: 'primary', namespace: 'auth' })]; +``` + +`target` is checked against `keyof targets` (§5.2). There is no primary-ish fallback, no +first-available fallback, and no engine string. If the author does not say where a contribution +goes, compilation fails with a diagnostic that lists the candidate targets — which is strictly +better than the current `?? databases[0]`. + +### 6.3 Provenance and the pinned mirror + +Installation never mutates another contributor's source and never copies declarations into the +application's schema tree. Instead, installation writes a **pinned mirror** under the application's +generated root: + +```text +.netscript/database/spaces/plugin--netscript--plugin-auth/ + space.json # descriptor snapshot: id, version, requires, dependsOn, owns, ownership + contract.json # the space's canonicalised contract at the pinned version + lineage/ # the space's own migration lineage nodes + PROVENANCE # package identity, resolved version, integrity hash, mirror digest +``` + +Three properties fall out. Production apply and verify read the mirror, not `node_modules`, so a +deployment does not need the plugin's package graph resolvable. The mirror digest is comparable +against the installed package's digest, which makes version skew detectable rather than latent. And +because the mirror is per-space, uninstalling a plugin removes a directory that owns nothing of the +application's. + +### 6.4 Lifecycle and its state machine + +| Transition | Precondition | Effect | Refusal conditions | +| -------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | +| **Install** | Target declared; `requires ⊆ target capabilities`; no `owns` overlap; `dependsOn` all present and acyclic | Mirror written; manifest recompiled; a plan is produced | Capability gap, ownership overlap, missing/cyclic dependency, contract-format mismatch | +| **Upgrade** | New version's `owns` diff is expressible; lineage from pinned head to new head resolvable | New mirror; lineage edges appended; plan produced | Non-linear lineage without an explicit resolve, ownership widening onto an object another space owns, capability regression | +| **Skew detected** | Installed package digest ≠ mirror digest | Refuse apply; emit `db.space.skew` with both digests and the sync command | — | +| **Uninstall** | Space is not a `dependsOn` of another installed space | Space unbound; retirement plan produced | A dependent space still installed; retention policy not satisfiable | +| **Retire (retain)** | Default | Objects remain; space marked orphaned; ownership downgraded `managed → adopted` so verify still notices drift instead of going blind | — | +| **Retire (archive)** | Allowed by policy | Objects moved to a quarantine namespace with a recorded reason and a restore path | Capability missing (e.g. no schema-move support) | +| **Retire (drop)** | Explicit consent + environment policy allows destructive | Destructive plan produced, requires approval like any destructive plan | CI without an approved plan; production without signed plan | + +The important asymmetry: **install is cheap and reversible; removal is a planned operation.** The +current removal path deletes the copied schema directory and plans nothing +`[CARRIED — NOT +RE-VERIFIED]`; under this protocol deleting a directory cannot be the removal, +because the directory was never the ownership record — the database marker and the manifest are. + +### 6.5 Ownership, conflict, and augmentation + +Conflict resolution today is byte comparison: identical normalised bodies are elided, and differing +bodies are rejected (`packages/cli/src/kernel/adapters/plugin/prisma-schema-writer.ts:133`) +`[OBSERVED]`. That is a _text_ policy standing in for an _ownership_ policy. It cannot express "this +plugin may add an optional column to that plugin's table", and it cannot distinguish "same +declaration, both owners" from "same name, different concept". + +The replacement is ownership-first: + +- **V-2 disjointness** (Part 1 §4.3) is checked over `ObjectKey`, not over text. Two managed owners + of one object is `db.space.ownership.conflict`, and the diagnostic names both spaces. +- **Augmentation is a grant, not a merge.** A space may only modify another space's objects along an + explicitly granted axis; the grant lives with the _owner_, which is the only party that can reason + about its own invariants. Denied axes are enumerated so the refusal is legible. +- **Namespaces make collisions structural rather than lexical.** `auth.user` and `app.user` are + different objects; no prefixing convention is required, and the `JobDefinition`-style unprefixed + global name stops being a hazard. +- **`external` and `ignored` are first-class.** An object marked `external` is excluded from + planning and diffing but still verifiable as assertions; `ignored` is excluded from everything + with a recorded reason. This is what makes hosted/managed databases workable rather than a + permanent source of false drift. + +### 6.6 Migrations, conformance, and coexistence with upstream extensions + +**Per-space lineage.** Each space carries its own lineage of content-addressed nodes; the database +holds one marker row per `(space, target)`. Applying a space advances only that space's marker. +Cross-space ordering is the topological order recorded in the manifest, so a reviewer can see it +before it runs. + +**Data transforms are edges, not a second folder.** The invariant-guarded transition model — a +precondition query that detects remaining work, a mutation plan, and a post-verification of the +invariant `[CARRIED — NOT RE-VERIFIED]` — is the right semantic model and NetScript should adopt it +rather than reinventing a timestamped data-migration directory. The historical failure mode in +comparable frameworks is exactly a second chronological sequence whose correctness depends on +invocation order. + +**A contributor conformance kit.** `@netscript/database-testkit` must certify a _space_, not only a +provider: given a space descriptor and an ephemeral target, it asserts that install → upgrade → +skew-detect → uninstall-retain → uninstall-archive all produce the declared outcomes, that `owns` is +truthful (nothing outside `owns` is touched), that `requires` is minimal-and-sufficient (removing +any capability makes composition fail; the declared set is enough to apply), and that augmentation +grants and denials are enforced. Without this, third-party contributions are a documentation +promise. + +**Coexistence with upstream extensions.** Prisma 8 extensions can themselves own contract spaces +`[CARRIED — NOT RE-VERIFIED]`. NetScript must not treat an upstream-owned space as unknown +territory: the manifest records it with `ownership: 'external'` and a provenance entry naming the +upstream extension, so verify accounts for its objects instead of reporting them as drift. NetScript +spaces and upstream extension spaces coexist under one disjointness check. + +--- + +## 7. Control plane: typed operations, receipts, and determinism + +### 7.1 What must be replaced, observed + +The current runner's entire result type is an exit code: `execute(request): Promise` +(`packages/cli/src/kernel/adapters/database/operation-runner.ts:85`) `[OBSERVED]`. Two behaviours +follow directly from that signature: + +```ts +if (request.operation === 'studio') { + return await this.executeOne(request, databases[0]); // silently the first target only +} +for (const database of databases) { + const code = await this.executeOne(request, database, controller.signal); + if (code !== 0) return code; // fail-fast, no per-target outcome +} +``` + +(`operation-runner.ts:90-105`) `[OBSERVED]` + +So `--db all` is sequential and fail-fast with no record of which targets succeeded, and `studio` +uses `databases[0]` regardless of the resolved target set. This is not a missing feature that +receipts would improve; **the return type makes structured reporting impossible.** Replacing it is +the load-bearing change, and it is why "add receipts" cannot be an incremental slice. + +The CLI surface itself is confirmed as fourteen verbs — `add`, `list`, `remove`, `init`, `generate`, +`migrate`, `seed`, `status`, `studio`, `introspect`, `reset`, `deploy`, `validate`, `resolve` +(`packages/cli/src/public/features/db/db-group.ts:32-53`) `[OBSERVED]`. + +### 7.2 Operation classification + +Classification is the mechanism that decouples pure work from orchestration, and it must be data on +the operation, not a convention. + +| Class | Examples | Requires connection | Requires Aspire | Requires lock | Produces receipt | +| ----------- | -------------------------------------------------------------------------------- | ------------------- | -------------------------------------------------- | ------------- | ---------------------- | +| `pure` | compose, validate, emit, format, lineage integrity check | No | **Never** | No | Yes (artifact receipt) | +| `live-read` | introspect, status, plan-against-live, verify | Yes | Only if the target's connection source _is_ Aspire | No | Yes | +| `mutating` | init, apply, seed, sign, retire | Yes | Only if the connection source is Aspire | **Yes** | Yes | +| `resident` | studio and any operation whose connection exists only inside a resident resource | Yes | Yes, explicitly selected | Advisory | Yes | + +The rule that matters: **Aspire is a property of a target's connection source, not of an operation +class.** The recorded architecture debt `DB-GENERATE-ASPIRE-COUPLING` documents the current inverse +— `DbOperationRunner.executeDetached` always runs `aspire start` before executing any database +operation, so pure codegen fails where the Aspire CLI or .NET is absent +(`.llm/harness/debt/arch-debt.md`, entry `DB-GENERATE-ASPIRE-COUPLING`) `[OBSERVED]`. Under +classification, `emit` cannot reach an orchestrator because a `pure` operation is not given a +connection resolver at all. + +### 7.3 Concrete operation types + +```ts +export type OperationClass = 'pure' | 'live-read' | 'mutating' | 'resident'; + +export interface OperationRequest { + readonly operation: TOp; + readonly manifestDigest: ManifestDigest; + /** Explicit target set. There is no implicit "all" and no implicit default. */ + readonly targets: readonly TargetId[]; + readonly spaces?: readonly SpaceId[]; + readonly policy: ExecutionPolicy; + readonly runId: RunId; + readonly signal: AbortSignal; +} + +export interface ExecutionPolicy { + readonly environment: 'development' | 'ci' | 'staging' | 'production'; + readonly destructive: 'deny' | 'plan-only' | 'allow-with-approval'; + readonly onPartialFailure: 'stop' | 'continue'; + readonly lockTimeoutMs: number; + readonly planMaxAgeMs: number; +} + +/** Every operation returns this. Nothing returns a number. */ +export interface OperationResult { + readonly runId: RunId; + readonly outcome: 'succeeded' | 'partially-succeeded' | 'failed' | 'refused'; + readonly perTarget: readonly TargetOutcome[]; + readonly diagnostics: readonly Diagnostic[]; + readonly receipt: Receipt; + /** Present iff outcome is 'partially-succeeded' or 'failed' and the run is resumable. */ + readonly resume?: ResumeToken; +} + +export interface TargetOutcome { + readonly target: TargetId; + readonly status: 'succeeded' | 'failed' | 'skipped' | 'not-attempted'; + /** Why a target was skipped or not attempted. No silent omissions. */ + readonly reason?: DiagnosticCode; + readonly spaces: readonly SpaceOutcome[]; + readonly value?: TOutcome; +} +``` + +**No silent skip.** Every target in the requested set appears in `perTarget` with a status, and +`skipped`/`not-attempted` carry a reason code. This is the direct answer to the market analysis's +strongest cross-product lesson — routing and filter mechanisms that silently omit work are the +recurring severe failure in Django-style multi-database systems. + +### 7.4 Plan, consent, expiry, and apply + +```ts +export interface MigrationPlan { + readonly planId: PlanId; + readonly target: TargetId; + readonly manifestDigest: ManifestDigest; + readonly baseline: BaselineFingerprint; // what the live database looked like when planned + readonly providerSet: readonly ProviderPin[]; + readonly spaceOrder: readonly SpaceId[]; + readonly steps: readonly PlanStep[]; + readonly destructive: readonly DestructiveOperation[]; + readonly capabilitiesUsed: readonly CapabilityId[]; + readonly createdAt: string; + readonly expiresAt: string; + readonly signature?: PlanSignature; // required in production +} + +export interface DestructiveOperation { + readonly kind: + | 'drop-entry' + | 'drop-column' + | 'narrow-type' + | 'add-required-without-default' + | 'unique-over-existing-data' + | 'namespace-drop'; + readonly object: ObjectKey; + readonly dataLossRisk: 'certain' | 'possible' | 'none'; + /** Present only when the provider proved it. Absence is not "safe". */ + readonly observedRowCount?: number; +} +``` + +Apply refuses a plan whose `manifestDigest`, `baseline`, `providerSet`, or target no longer match, +and refuses an expired plan. Consent is _not_ an interactive prompt: in `ci` and `production` the +policy must be `allow-with-approval` **and** the plan must carry a signature. An interactive "yes" +is a development affordance only. This is the ordering the research proposes and I endorse without +change. + +### 7.5 Progress, dotted diagnostics, and receipts + +```ts +export type DiagnosticCode = + | 'db.compose.ownership.conflict' + | 'db.compose.capability.missing' + | 'db.compose.dependency.cycle' + | 'db.space.skew' + | 'db.plan.stale' + | 'db.plan.expired' + | 'db.apply.destructive.refused' + | 'db.apply.lock.held' + | 'db.verify.drift' + | 'db.artifact.stale' + | 'db.target.ambiguous'; + +export interface Diagnostic { + readonly code: DiagnosticCode; + readonly severity: 'error' | 'warning' | 'info'; + readonly subject: ObjectKey | TargetId | SpaceId; + readonly message: string; // human text, never parsed by anything + readonly nextAction: NextAction; // structured: a command + args, not prose +} + +export type ProgressEvent = + | { readonly kind: 'span-start'; readonly span: SpanRef; readonly label: string } + | { readonly kind: 'span-end'; readonly span: SpanRef; readonly status: 'ok' | 'error' } + | { readonly kind: 'note'; readonly span: SpanRef; readonly diagnostic: Diagnostic }; + +export interface Receipt { + readonly receiptId: ReceiptId; + readonly runId: RunId; + readonly operation: OperationName; + readonly manifestDigest: ManifestDigest; + readonly startedAt: string; + readonly finishedAt: string; + readonly phases: readonly ReceiptPhase[]; // per target, per space, per step + readonly artifacts: readonly ArtifactAssertion[]; + readonly environment: string; + readonly toolVersions: readonly ProviderPin[]; +} + +/** A postcondition the operation proved, not a log line claiming it. */ +export interface ArtifactAssertion { + readonly path: string; + readonly expected: 'created' | 'unchanged' | 'replaced' | 'absent'; + readonly digestBefore?: string; + readonly digestAfter?: string; +} +``` + +`nextAction` being structured rather than prose is what lets the CLI, CI annotations, and the agent +surface all render the same remediation without any of them parsing text. This directly retires the +weakest link in the current gate: the merge-readiness migration fixture asserts on the literal +string `'created no migration artifact'` and refuses to run outside Linux +(`packages/cli/e2e/src/application/gates/scaffold/verify-db-migration-artifacts.ts`) `[OBSERVED]`. A +reworded message breaks the gate, and the platform where the historical schema-engine hangs occurred +is not covered by it at all. + +### 7.6 Locks, concurrency, resume, and CI determinism + +- **Lock scope is `(target, physical database)`,** acquired for `mutating` operations only, with an + owner identity, a heartbeat, and a TTL. A lock is a database-level advisory lock where the + provider has one and a ledger row with fencing otherwise; the capability is declared, so a + provider without either is refused for concurrent-safe apply rather than silently racing. +- **No shared stateful runner across targets.** Each target gets its own runner instance. This is + the concrete lesson from ORMs whose migration fan-out documents "shared instance parallel fan-out + is unsupported"; the architecture should make the unsupported configuration unrepresentable. +- **Resume is per `(runId, target, space, stepIndex)`.** A resumed run re-validates the plan against + the live baseline before continuing, so resume can refuse rather than compound a divergence. +- **Cross-target apply is a saga, never a transaction.** `partially-succeeded` is a first-class + outcome. Claiming atomicity across two databases would be a lie, and I-9 forbids it. +- **Offline determinism.** `pure` operations take a source reader and a clock port, never a network. + Emitting twice from a clean checkout must produce identical digests; emitting into distinct target + roots must be safe concurrently; artifacts are written to a temporary root and moved atomically so + an interrupted emit leaves either the old tree or the new tree, never a half-patched one. +- **CI cacheability.** The manifest digest is the cache key. A CI job that has already emitted for a + digest can skip emission and assert the recorded `ManifestDigest` in the artifact root instead + (I-4/V-8). Receipts are written as atomic JSON, which is the pattern this repository already uses + for gate evidence (`.llm/tools/gates/run-gate.ts` receipts under `.llm/tmp/gate-receipts/`) + `[OBSERVED]` — the database receipts should adopt that shape rather than invent a second one. + +### 7.7 The generated agent surface + +The agent surface is an _output_, not a maintained document: a generated manifest containing the +target/space inventory with capabilities and ownership, the command catalog with argument schemas +and result schemas, the diagnostic catalog with `nextAction` for each code, the +destructive/environment policy, the list of operations the resolved provider does **not** support, +and compile-checked import examples. Two rules keep it honest: it is regenerated from the manifest +plus the operation catalog on every emit, and a conformance case executes every generated example. A +generated skill that is not executed in CI decays exactly the way hand-maintained agent instructions +do. + +--- + +## 8. Prisma 8: adopt, wrap, defer, reject — and the volatility boundary + +### 8.1 Decisions + +| Upstream surface or idea | Decision | Reasoning | +| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Canonical contract artifact + type declaration ("types-only emission") | **Adopt** | Removes executable generated clients, which removes the entire textual-repair pipeline. This is the single highest-value upstream change for NetScript. | +| Domain/storage plane separation and per-plane hashes | **Adopt as internal identity; do not re-publish** | Excellent internal structure; the representation is explicitly still moving, so NetScript records its own manifest digest and treats upstream hashes as recorded attributes. | +| Family / target / adapter / driver / extension axis split | **Adopt conceptually** | Correct open-axis model; it is what makes "engine" stop being the only discriminator. | +| Contract spaces | **Adopt and extend** | The right ownership primitive. NetScript adds target binding, capability requirements, augmentation grants, removal/retention policy, and provenance — none of which upstream provides. | +| Migration lineage as content-addressed edges + per-space marker + ledger | **Adopt the semantics; own the operations** | See §8.2. | +| Invariant-guarded data transforms | **Adopt** | Correct model; NetScript generates the descriptor wiring rather than leaving planner placeholders for a human to fill. | +| Structured results, progress spans, dotted error codes | **Adopt and translate** | Enables §7 without log parsing. Translate into NetScript codes so upstream renaming is not a NetScript breaking change. | +| Programmatic control client | **Wrap behind a NetScript port, with a contingency backend** | See §8.3. This is where I diverge from the research. | +| PostgreSQL runtime facade | **Wrap; expose as a generic type argument** | Powerful, and far too upstream-specific to become NetScript-wide API. | +| Standard Schema for parameter validation | **Adopt** | Already a NetScript dependency; aligns the boundary. | +| Project-level agent skill | **Recreate from the NetScript manifest** | Direction is right; content generated from RC-era material is not trustworthy enough to consume. | +| CLI binary name and config file shape | **Do not bind** | RC-tag names are already not what post-RC `main` carries. Bind to the programmatic seam instead. | +| Public package re-exports | **Reject** | Doctrine AP-14, plus the slow-types constraint (Part 1 §2.1(3)). | +| Hand-written low-level driver adapters | **Reject by default** | The existing `@netscript/prisma-adapter-mysql` is the cautionary case. Require certification through the testkit if ever unavoidable. | +| Copied/merged schema fragments | **Reject** | No ownership, no lineage, no capability guard, no safe removal. | +| Generated-source text patching | **Reject** | I-5. | +| Universal lowest-common-denominator database API | **Reject** | Weakens every provider and hides real semantics. | +| Prisma 7 compatibility facade | **Reject** | Owner directive; also the source of the current architecture's shape. | +| MySQL / SQL Server as 8.0 targets | **Defer** | Not in the 8.0 target set. See §9.4. | +| Extension removal, shadow-database workflow, cross-target advisory locking, row-count-aware data-loss analysis | **Defer upstream; own in NetScript where required** | These are precisely the operational gaps §7 fills. | + +### 8.2 Where I diverge from the research: own the operational layer outright + +The research recommends adopting the migration graph "after conformance". I recommend a sharper +split. **Adopt the semantic layer** — content-addressed lineage nodes, per-space markers, +edge/ledger coupling, invariant-guarded transforms. **Own the operational layer outright** — +locking, receipts, resume, plan expiry and signing, destructive policy, cross-target sequencing, +partial-success reporting, and drift classification. + +The reason is that the operational gaps are not incidental: the absence of a mature +reset/resolve/diff/squash workflow, of a general shadow-database workflow, of a complete +advisory-lock story across targets, and of row-count-aware data-loss analysis +`[CARRIED — NOT RE-VERIFIED]` are all in the operational layer. If NetScript waits for upstream to +close them, adoption is gated on someone else's roadmap; if NetScript owns them, adoption is gated +only on the semantic layer, which is the part that is genuinely good. This also means these +operations are NetScript's to keep when a second provider arrives, rather than being re-acquired per +provider. + +### 8.3 Volatility containment + +The control API is the correct integration direction _and_ it is demonstrably moving: routing +migration and database commands through the control API, adding sectioned config diagnostics and a +control-client test double, and making command output channels explicit are all **post-RC `main`** +changes, not RC-tag facts `[CARRIED — NOT RE-VERIFIED]`. Pinning a moving seam inside a package that +must satisfy JSR publish gates is a real risk, so containment is structural rather than a version +pin: + +1. **One package may import upstream.** `@netscript/database-prisma-postgres` and nothing else. A + dependency-cruiser-style rule fails the build on any upstream import elsewhere. +2. **One module inside that package may name upstream symbols.** An `upstream.ts` facade module is + the sole import site; every other file imports from it. The blast radius of an upstream rename is + one file. +3. **An explicit import allowlist.** `@prisma/orm-postgres` publishes on the order of 138 top-level + export keys `[CARRIED — NOT RE-VERIFIED]`; the overwhelming majority are extension-author + surface. The allowlist enumerates the handful NetScript uses, and any newly-introduced deep + import fails a check. Without this, "we depend on Prisma" silently becomes "we depend on Prisma's + internals". +4. **The provider package is versioned and released independently of the kernel.** An upstream break + is then a provider patch release, not a framework break. This is the property that makes the + whole design survivable across an RC-to-GA transition. +5. **A contingency backend behind the same port.** The NetScript `ControlPort` must be satisfiable + by a second implementation that uses the emitted artifacts plus direct SQL, exercised in CI even + if it is never the default. A port with exactly one possible implementation is not containment; + it is a rename. +6. **Contract format version is a gate, not an assumption.** The manifest records the upstream + contract format version; a change is a deliberate migration with its own conformance run. + +--- + +## 9. Provider, engine, and runtime matrix + +### 9.1 Capability model, not a compatibility table + +Capabilities are an **open, provider-declared** set. The kernel never requires a capability; only +spaces do (I-7). This is the structural difference between a capability model and a portability +layer: adding a capability does not force every provider to implement it, and using one is a +compile-time decision. + +| Axis | Example capabilities | +| --------- | ------------------------------------------------------------------------------------------------ | +| Family | `sql`, `document` | +| Types | `nativeUuid`, `caseInsensitiveText`, `nativeEnum`, `jsonb`, `arrayColumn`, `vector` | +| Schema | `multiNamespace`, `namespaceMove`, `viewDefinition`, `checkConstraint`, `partialIndex` | +| Migration | `transactionalDdl`, `advisoryLock`, `shadowDatabase`, `rowCountEstimate` | +| Runtime | `interactiveTransaction`, `preparedStatement`, `streamingCursor`, `cancellation`, `externalPool` | + +Provider capability claims are not self-certified: they are what `@netscript/database-testkit` +proves against a live instance, and a claim without a passing conformance case is a conformance +failure. + +### 9.2 Target matrix and the PostgreSQL-first decision + +PostgreSQL is the only credible first implementation, and this is a decision rather than a +preference: it is the sole database intended for the 8.0 GA target set, with MongoDB earlier-stage, +SQLite proof-of-concept, MySQL later, and SQL Server absent `[CARRIED — NOT RE-VERIFIED]`. + +| Provider | Wave | Status | Notes | +| --------------------- | -------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| Prisma 8 · PostgreSQL | 1 | **Primary implementation** | Must pass the full conformance suite against a real PostgreSQL service, not an emulator. | +| Prisma 8 · SQLite | 3 | Candidate, capability-reduced | Useful for local/dev and for proving the capability model has teeth; must not be presented as production parity. | +| Prisma 8 · MongoDB | Deferred | Validates family abstraction | Proves the `family` axis is real; not a NetScript deliverable in the first waves. | +| MySQL | Deferred | Contingency, see §9.4 | | +| SQL Server | Deferred | Not in the upstream 8.0 target set | Requires a different provider entirely. | + +### 9.3 Multi-target, multi-schema, and external ownership semantics + +- **Same-provider multi-target** is the default case, not a special case. `primary` and `analytics` + may both be PostgreSQL; they share no output root, no lineage, no runtime binding, and no receipt + namespace (V-6). This is the concrete repair for `db add postgres --name analytics` resolving to + `database/postgres/` (`workspace-resolver.ts:50`) `[OBSERVED]`. +- **Same-database multi-schema** is namespaces within one target. Spaces own namespaces or object + sets inside them. +- **Cross-space relations** are legal within one target along a declared dependency edge (V-3). + Cross-_target_ relations are refused at composition with a diagnostic — the honest answer, since + no amount of framework code makes a foreign key work across two databases. +- **Replicas are roles** (Part 1 §4.2). A reader role yields a read-only session type and is not + addressable by any migration operation. +- **External/unmanaged** ownership is required, not optional. Hosted platforms evolve tables outside + the framework's knowledge; a framework that treats every visible object as its own reports + permanent false drift. `external` objects are excluded from plan and diff and included in verify + as assertions only. + +### 9.4 Runtime constraints: Deno, serverless, and the MySQL contingency + +NetScript is a Deno framework publishing to JSR, and the upstream posture is Node-primary with +Bun/Deno best-effort, a PostgreSQL facade that depends on `pg`, and TypeScript 5.9 as an +**optional** peer `[CARRIED — NOT RE-VERIFIED]`. "Deno is listed" is therefore not an adoption +argument. The platform gate must prove: a clean Deno import graph with no undeclared Node globals in +runtime paths; connect/query/transaction/stream/close/error-mapping behaviour against a real +service; no CLI or toolchain module reachable from a runtime graph; leak behaviour under repeated +start/stop and request lifecycles; and the supported bundler/deployment modes. + +Serverless is a _scope_, not a deployment flag: the request-scoped session type omits interactive +transactions and cached collaborators and is `AsyncDisposable` (Part 1 §5.3). The upstream +serverless facade's asymmetry is a precedent worth copying rather than smoothing over. + +**MySQL contingency.** The current `@netscript/prisma-adapter-mysql` implements Prisma's low-level +driver-adapter contracts directly `[CARRIED — NOT RE-VERIFIED]`; doctrine's verdict for it is _Keep_ +(`docs/architecture/doctrine/10-codebase-verdict-and-handoff.md:50`) `[OBSERVED]`, which reflects +its fit to the _current_ port, not its fit to this design. Under a clean break there are three +options: retire it and defer MySQL to an upstream target; port it to the new provider port and +certify it through the testkit; or keep it as an out-of-tree provider. I recommend **retire and +defer**, with the testkit path available if a MySQL requirement lands before upstream ships the +target. Carrying a hand-maintained low-level driver adapter through a clean break re-imports the +exact maintenance surface the redesign exists to remove. + +--- + +## 10. Pure-TypeScript schema authoring and the end-to-end type system + +### 10.1 The question, answered directly + +Prisma 8 supports both a schema language and a TypeScript contract builder, both lowering to the +same contract, with the TypeScript route giving immediate `typeof contract` inference +`[CARRIED — NOT +RE-VERIFIED]`. The brief asks whether NetScript should **expose**, **wrap**, or +**translate** that surface. + +**Answer: expose upstream authoring for entities; wrap at the composition seam; translate nothing.** + +- **Translate — rejected.** A NetScript model DSL that lowers to the upstream contract is a third + schema language. It would need to track every native type, index kind, constraint, and default the + provider supports, it would lag upstream permanently, and its error messages would be a + translation of a translation. This is the clearest instance of the "proprietary second ORM" + failure the brief asks me to guard against, and it should be rejected explicitly in the RFC rather + than left as an open option. +- **Bare expose — rejected.** Handing users the upstream builder with no NetScript layer leaves + exactly the gaps that produced the current situation: no target binding, no ownership, no + capability requirement, no augmentation policy, no provenance, no lineage ownership. +- **Wrap at the composition seam — chosen.** NetScript owns _which_ contracts exist, _where_ they + live, _who_ owns each object, _what capabilities_ they require, and _how_ they compose. Upstream + owns what a model, relation, index, constraint, native type, and default _are_. + +### 10.2 The seam in code + +```ts +// plugins/auth/database/contract.ts — entity authoring is upstream's job +import { model, ref, string, timestamp, uuid } from '@netscript/database-prisma-postgres/schema'; + +export const user = model('user', { + id: uuid().primaryKey(), + email: string().unique().citext(), // requires CAP.caseInsensitiveText + createdAt: timestamp().defaultNow(), +}); + +export const session = model('session', { + id: uuid().primaryKey(), + userId: ref(user).onDelete('cascade'), + expiresAt: timestamp(), +}).index(['userId']); +``` + +```ts +// NetScript's wrapper: composition, ownership, capability — no entity vocabulary at all +export declare function schemaSpace>>( + entries: TEntries, +): ContractSource; +``` + +The re-export in the first snippet is deliberate and is **not** an AP-14 violation: it is exported +from the _provider_ package, which is the one package permitted to name upstream symbols (§8.3), and +it is provider-specific by design — `citext()` exists on the PostgreSQL provider and nowhere else. +That is the capability model expressed as an import path, and it is the structural fix for the +observed `@db.Uuid` problem: today a PostgreSQL-only native type sits in a fragment declaring no +provider and gets copied into whatever target the installer picks `[OBSERVED]`; under schema-as-code +the PostgreSQL-only builder is only importable from the PostgreSQL provider, and the space that uses +it must declare `requires: [CAP.nativeUuid]`, which composition checks against the bound target +(V-5). + +### 10.3 Two-track identity: inference for DX, content hash for correctness + +Static inference and durable identity are different jobs and must not share a mechanism. + +- **Static inference** gives editor completion and compile-time errors. It flows from the authored + TypeScript through `typeof`, and it is _only_ valid within the application's own compilation. +- **Stable runtime identity** is the content hash of the canonicalised contract. It is what + receipts, markers, lineage nodes, plans, and caches key on. + +Conflating them is how a system ends up unable to answer "is this database consistent with this +build?" without type-checking. Keeping them separate is also what makes the `isolatedDeclarations` +constraint tractable: the inferred track never crosses a published package boundary (Part 1 §5.4), +while the hashed track is plain data that crosses every boundary freely. + +### 10.4 Propagation: one contract, many consumers + +The value of schema-as-code is that a single authored contract propagates without a second +generation step at each hop: + +| Consumer | What it derives | How | +| ------------------ | ---------------------------------------------- | ---------------------------------------------------------------------- | +| Typed operations | The query surface | Provider's contract-typed runtime, delivered as `TQuery` (Part 1 §5.3) | +| Validation | Input/output Standard Schemas | Runtime derivation from the contract (§11) | +| RPC / routes | Contract-bound procedure input/output | Standard Schema handed to the existing oRPC-bound surface | +| Forms / SSR | Field-level schemas and error paths | The same Standard Schema instances, per field path | +| Migrations | Lineage edges | Storage-plane diff between content-addressed snapshots | +| Generated projects | The typed binding module | Emitted per target (Part 1 §5.4) | +| Tooling / agents | Inventory, capabilities, commands, diagnostics | The manifest plus the operation catalog (§7.7) | + +Every one of those is a _derivation_, and none is a hand-maintained mirror. That is the property +that retires the current pipeline: the generated workspace today emits 30 database tasks and a +repair chain that rewrites Prisma and Zod output textually +`[OBSERVED for the task count; CARRIED — NOT +RE-VERIFIED for the step ordering]`. Derivations do not +need repair passes because there is no second artifact to keep in sync. + +--- + +## 11. Runtime validation subsystem + +### 11.1 The hypothesis and the default + +The owner-provided Prisma-maintainer exchange establishes the design hypothesis that **the contract +carries enough runtime data to derive validation without a second generation step**. I treat this as +primary exploratory evidence and as a hypothesis to be proven by NetScript's own conformance run — +not as an upstream commitment. Part 3 records it as an explicit decision checkpoint conditional on +Prisma 8 final. + +If it holds, the architectural consequence is large, and it is the reason to reject the obvious +approach: + +> **Mirror-validator code generation is rejected as the default.** Generating a parallel validator +> universe from the contract — a schema file per model, per input shape, per output shape — is what +> produces import rewriting, circular-reference repair, getter rewriting, decimal compatibility +> patches, alias barrels, and the split-module-instance class of failure. A mirror must be +> regenerated, re-patched, re-exported, and kept in sync forever, and it is stale the moment the +> schema changes without the pipeline running. + +The default is **runtime derivation, memoised by contract identity**. + +### 11.2 Why selection-awareness settles the argument + +The decisive technical argument against mirror codegen is not maintenance burden — it is +combinatorics. Output validation at a trust boundary must validate _the shape that was actually +selected_, not the full model. A query selecting three fields with one relation included produces a +different result shape from the same model selected wholly. + +A static mirror would need one schema per selection shape, which is unbounded. A runtime derivation +takes the selection as a parameter and produces the schema for exactly that shape: + +```ts +export interface ContractValidation { + /** Input validation for a mutation or query argument set. */ + input, TOp extends OperationKind>( + model: K, + op: TOp, + ): StandardSchemaV1>; + + /** Output validation for the exact projection that was requested. */ + output, TSel extends Selection>( + model: K, + selection: TSel, + representation: Representation, + ): StandardSchemaV1>; +} + +export type Representation = 'runtime' | 'wire'; +``` + +### 11.3 Runtime versus wire representations, and codecs + +One contract yields **two** schema families, and conflating them is a common source of subtle bugs: + +- **Runtime representation** — what the provider hands back in-process: decimal objects, `BigInt`, + `Date`, byte arrays, provider-specific enum values. +- **Wire representation** — what crosses an API, SSR boundary, or external-service call, after JSON + serialisation: strings for decimals and big integers, ISO-8601 for timestamps, base64 for bytes. + +`representation` is therefore a parameter of `output()`, not an afterthought. Codecs are the +bidirectional mapping between them, contributed by the provider or by a space; a codec registers +against a contract type and supplies encode, decode, and the two schemas. Because codecs can be +contributed, a space that introduces a custom column type also introduces its validation without any +framework change — and because codec ownership is checked the same way object ownership is (V-2), +two spaces cannot silently register conflicting codecs for the same type. + +### 11.4 Trust boundaries: where validation is mandatory + +Input validation is always applied at mutation and query boundaries. **Output** validation is +deliberately _not_ universal, because validating every row on every read is a real cost. It is +mandatory at three boundaries and optional elsewhere: + +1. **API/RPC responses** — the shape is a published contract; drift here is a consumer break. +2. **SSR/forms payloads** — the shape reaches a browser and is often user-visible. +3. **External-service calls** — data leaving the trust boundary must match what the recipient was + promised. + +Everywhere else, output validation is opt-in and defaults to off with the cost documented. A design +that validates everything by default gets disabled wholesale in production, which is worse than a +design that validates precisely at boundaries. + +### 11.5 Cache identity and invalidation + +```ts +type SchemaCacheKey = { + readonly contractIdentity: ContractSnapshotId; // changes ⇒ every derived schema invalid + readonly space: SpaceId; // plugin spaces cache independently + readonly model: string; + readonly operation: OperationKind | 'output'; + readonly selectionHash: string; // canonicalised selection shape + readonly representation: Representation; +}; +``` + +Invalidation is by construction: the key contains the contract identity, so a contract change cannot +produce a stale hit — there is nothing to invalidate, only new keys. Plugin spaces cache under their +own `SpaceId`, so upgrading one plugin does not evict the application's schemas. The cache is +bounded and per-process; a cold process pays derivation once per distinct shape it actually uses. + +### 11.6 Structured failures and framework integration + +Validation failures are Standard Schema issues enriched with NetScript's structured diagnostic +shape: a dotted code, the `ObjectKey` or model/field path, the boundary at which the failure +occurred, and whether the failure is an input rejection (client error) or an output mismatch +(server/contract error). The distinction matters operationally: an input failure is a 4xx with field +paths; an output failure is a 5xx _and_ a signal that the database and the contract have diverged, +which is drift, not a request problem. + +Integration follows NetScript's existing seams rather than new ones. `@standard-schema/spec` is +already a dependency of `@netscript/plugin` and `@netscript/sdk` `[OBSERVED]`, so contract-derived +schemas feed the existing oRPC-bound contract surface directly, and forms/SSR consume the same +schema instances per field path. NetScript does not re-export a validator library; a consumer +wanting Zod adapts from Standard Schema, which keeps doctrine AP-14 satisfied and keeps the +split-validator-module failure class out of the design entirely. + +### 11.7 The optional AOT projection + +An ahead-of-time projection may exist for cold-start-sensitive deployments, under three conditions +that make it an optimisation rather than a second source of truth: + +1. **Atomic and content-addressed.** Emitted into a target-scoped root, keyed by contract identity, + replaced atomically, never patched. +2. **Semantically equivalent.** A conformance case must assert that the AOT and runtime-derived + schemas accept and reject an identical corpus, across every representation and a representative + set of selection shapes. Divergence is a build failure, not a warning. +3. **Never the default and never required.** Any code path that works only with AOT artifacts + present is a design failure; the runtime derivation must remain sufficient. + +If condition (2) cannot be met mechanically, the AOT path is a mirror validator wearing a different +name and must be dropped. + +--- + +## 12. Clean-break cutover + +### 12.1 Transfer analysis: NetScript's oRPC pattern → Prisma's TypeScript contract builder + +Before leaving the API architecture, one question deserves a direct answer, because NetScript has +already solved a structurally identical problem once and the temptation to copy the solution +wholesale is strong. + +**The parallel.** NetScript's oRPC surface has exactly the shape the database contract surface will +have: a deeply-inferred upstream type system (`@orpc/contract`) that the framework composes, extends +per plugin, and binds at a composition root. `packages/contracts` (Archetype 1) exports `.`, +`./crud`, `./query`, and `./transform` over `@orpc/contract` and `zod` `[OBSERVED]`; +`packages/plugin` publishes a `./contract-base` subpath and depends on `@orpc/contract`, +`@orpc/server`, and `@standard-schema/spec` `[OBSERVED]`; `packages/service` and `packages/sdk` +consume the same axis `[OBSERVED]`; and `ContributionAxis` already carries a `'contract-version'` +member with a `PluginContractVersionContribution` abstract `[OBSERVED]`. Doctrine grants those +packages — and only those — the `--allow-slow-types` carve-out, precisely because deeply-inferred +contract types cannot be explicitly annotated +(`docs/architecture/doctrine/02-public-surface.md:217-242`) `[OBSERVED]`. + +**What should transfer.** + +1. **The `defineX` → frozen definition → composition-root binding pattern.** This is already + NetScript's entry-verb vocabulary (`02-public-surface.md:73-82`) `[OBSERVED]` and it is the right + shape for `defineTarget`/`defineSpace`/`defineDatabase`. Inference is preserved because the + definition is a `const` whose type flows through `typeof`, exactly as oRPC contracts do today. +2. **Versioned contribution with skew detection.** The `contract-version` axis is the precedent for + §6's pinned mirror and `db.space.skew`. NetScript has already accepted that a contribution + carries a version that can diverge from what the consumer pinned. +3. **Standard Schema as the interop boundary.** `@netscript/contracts` already bridges oRPC and Zod + through schema interop; the database contract's derived schemas plug into the same seam without + any new bridging concept (§11.6). +4. **Per-package subpath discipline.** oRPC concerns are split across `./crud`, `./query`, + `./transform` rather than one barrel. The database surface should split the same way, which F-5's + 20-symbol cap forces anyway. + +**What must not transfer.** + +1. **The slow-types carve-out must not be extended.** This is the most important line in this + subsection. The oRPC carve-out is defensible because the inferred contract _is the product_ of + those packages — consumers import `@netscript/contracts` specifically to obtain those types. The + database case is different in kind: the inferred type is derived from _the application's own_ + contract, so no framework package ever needs to export it. Extending the carve-out would convert + an application-local inference problem into permanent framework-wide publish debt, and doctrine + is explicit that any other package setting `--allow-slow-types` "is a finding and must carry a + debt entry" `[OBSERVED]`. The correct answer is the generated app-side binding (Part 1 §5.4), not + a second exception. +2. **No `BaseDatabaseContract`-style cross-package base class.** Plugin `-core` packages extending + `BaseContractRoute` sits in tension with AP-4, which forbids cross-package implementation + inheritance and prescribes "registration against an extension axis instead" + (`09-anti-patterns-and-fitness-functions.md:54-57`; `07-composition-and-extension.md:114-141`) + `[OBSERVED]`. The database design has no legacy reason to inherit that tension; spaces register, + they do not subclass. +3. **No wrapper around `defineContract` and no re-export of it from a kernel package.** Wrapping the + upstream builder to "make it NetScript-flavoured" destroys the native inference that motivates + using it, adds a translation layer with worse errors, and re-creates the second-DSL failure §10.1 + rejects. The builder is re-exported from the _provider_ package only, where provider-specific + vocabulary belongs. +4. **No mirror of `packages/contracts` for the database.** A `@netscript/database-contracts` package + holding CRUD/query/transform mirrors of database models would be the mirror-validator failure of + §11.1 in a different costume. + +**What is additionally required, because a database is not an RPC contract.** These have no analogue +in the oRPC pattern and are the reason the database surface needs its own machinery rather than a +copy: + +| Requirement | Why oRPC has no equivalent | +| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Ownership disjointness over `ObjectKey` (V-2) | Two RPC contracts declaring the same procedure name is a routing conflict caught at composition; two schemas owning one table is a silent data hazard. | +| Lineage coupling | An RPC contract version can be published freely; a schema change implies a _data_ transition that must be planned, ordered, and verified. | +| Physical identity separate from logical contract | An RPC contract has no target, namespace, or connection; a space must be bound to one target and one namespace. | +| Lifecycle and scope | An oRPC contract has no lifetime. A database binding owns connections, close ordering, and request-versus-process scope (Archetype 3). | +| Destructive policy and consent | There is no destructive operation in publishing a contract. | +| Drift against live state | A contract cannot drift from a running server the way a schema drifts from a live database that another system also writes to. | +| Capability requirements | Every oRPC contract is expressible on every transport; a schema using `citext` is not expressible on every provider. | + +**Conclusion of the transfer analysis.** Reuse the composition, contribution, and interop +_patterns_; reuse none of the type-escape _mechanisms_; and add ownership, lineage, physical +identity, lifecycle, consent, drift, and capability as genuinely new concerns. The oRPC pattern is +the right template for how NetScript composes upstream type systems and the wrong template for how +it publishes them. + +### 12.2 Cutover principles + +- **No runtime compatibility, ever.** No Prisma 7 facade, no `setClient` lifecycle, no alias barrel, + no dual client, no deprecated re-export. A compatibility shim would encode the old foundation's + limits into the new layer, which is precisely the outcome the owner directive exists to prevent. +- **Data continuity is absolute.** The database is adopted, never rebuilt. Cutover must be possible + on a production database with real data and no drop-and-recreate step anywhere in the sequence. +- **Parallel branching is a release-line concern, not a product-API concern.** The old and new + stacks may coexist in the repository during the waves; they must never coexist in one + application's composition. + +### 12.3 The mechanical migration path + +A one-shot importer, `netscript db adopt`, converts an existing project. It is a _tool_, not a +compatibility layer, and it is deleted after the migration window. + +| Step | Operation | Mutates the database? | Failure behaviour | +| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------- | +| 1 | Read `appsettings.json` targets, engine mapping, and the generated workspace layout | No | Refuse on ambiguous or duplicate config keys | +| 2 | Emit a proposed `database.ts` with one `defineTarget` per config key — **target ids taken from config keys, never from engine names** | No | Refuse when two config keys resolved to the same engine directory; require the author to name them | +| 3 | Introspect each live target | No | Report unreachable targets; adoption can proceed offline for reachable ones only | +| 4 | Derive one space per detected owner: `app` for the base schema, one per installed plugin, inferred from the copied `schema/plugins//` directories | No | Objects that cannot be attributed are reported, not guessed | +| 5 | Emit the ownership proposal for review: every `ObjectKey` mapped to a space or to `external`/`adopted` | No | The author must resolve every unattributed object before continuing | +| 6 | Compile the manifest and emit artifacts | No | Standard composition diagnostics | +| 7 | Establish the baseline: write a lineage root node per space matching the _observed_ live state, and write the marker rows | **Yes — marker rows only** | Idempotent; re-runnable; produces a receipt | +| 8 | `verify` | No | Any diff at this point is a genuine finding: either an unattributed object or an incorrect ownership assignment | +| 9 | Cutover commit: delete `database//`, its 30 generated tasks, the repair scripts, and the old package dependencies | No | Reversible by reverting the commit | + +The critical property is **step 7 writes marker rows and nothing else**. No table is created, +altered, or dropped during adoption. That is what makes the migration safe on production data and +what makes step 9 the only irreversible-looking step — and it is reversible, because it touches only +the repository. + +### 12.4 Data preflight and safety + +Before step 7, a preflight report is mandatory and must be attached to the cutover PR: every target +with its reachability and provider version; every `ObjectKey` with its assigned owner and ownership +policy; every object the importer could not attribute; every capability the derived spaces require +against what each target actually provides; and every plugin whose copied fragment cannot be +attributed to an installed package. A preflight with unattributed objects is a hard stop — guessing +ownership is how a later `verify` proposes dropping a table someone else owns. + +### 12.5 Rollback boundaries + +| Point | Rollback | Cost | +| -------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------- | +| Before step 7 | Delete generated artifacts | None; nothing was written | +| After step 7, before step 9 | Delete marker rows for the adopted spaces | Trivial; markers are metadata | +| After step 9, before first apply | Revert the cutover commit | Repository-only; database untouched | +| After the first `apply` | Forward-only, using the lineage and the receipt | Ordinary migration rollback semantics; the receipt identifies exactly which steps ran | + +There is deliberately no "run both stacks" rollback. That option would require the compatibility +layer this design refuses, and it would double the failure surface during precisely the window when +the system is least understood. + +### 12.6 Feature-parity accounting + +The fourteen current verbs `[OBSERVED]` map as follows. Parity is claimed only where the new +operation is a superset; everything else is stated as a deliberate removal. + +| Current verb | Disposition | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------- | +| `add` | Replaced by editing `database.ts`. Scaffolding becomes a code-mod, not a config rewrite plus helper regeneration. | +| `list` | `inventory` — superset: targets, spaces, ownership, capabilities, heads, drift status, as structured output. | +| `remove` | Replaced by the space retirement protocol (§6.4). **Behaviour change:** removal produces a plan; it no longer deletes and hopes. | +| `init` | `apply` against an empty baseline. | +| `generate` | `emit` — **now `pure`**; never touches an orchestrator. This closes `DB-GENERATE-ASPIRE-COUPLING`. | +| `migrate` | `plan` + `apply`, separated. **Behaviour change:** planning and applying are distinct operations with distinct policies. | +| `seed` | `mutating` operation with a receipt. | +| `status` | `verify` + `inventory`, structured. | +| `studio` | Retained as `resident`, but **must take an explicit target**; the `databases[0]` silent selection is removed. | +| `introspect` | `introspect`, feeding adoption. | +| `reset` | Retained, `mutating`, destructive-policy-gated; refused in `production` regardless of consent. | +| `deploy` | `apply` with a signed plan and `environment: production`. | +| `validate` | `compose` — a `pure` operation returning full diagnostics rather than first-error. | +| `resolve` | Replaced by explicit lineage operations against named nodes. | + +Two capabilities are removed on purpose and must be stated in the RFC as such: implicit target +defaulting (there is no primary-ish fallback anywhere), and silent single-target execution for +multi-target commands. + +--- + +## 13. Implementation waves + +Each wave lands independently and has a gate that can fail. No wave depends on a later wave. + +| Wave | Scope | Depends on | Acceptance gate | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **W0 — Doctrine and RFC** | Amend `06-archetypes.md` (Archetype 5 fragment rule; archetype table), add verdict rows in `10-codebase-verdict-and-handoff.md`, register the new packages in the gated denominator, land the RFC | — | RFC accepted; `arch:check` discovers the new roots; doctrine drift (A9 "six archetypes" vs seven) resolved or explicitly deferred with a debt entry | +| **W1 — `@netscript/database-contract` (A1)** | Identities, manifest schema, capability vocabulary, ownership vocabulary, diagnostic catalog, operation/receipt types, space descriptor, ports | W0 | A1 gate set; `deno publish --dry-run` **without** `--allow-slow-types`; `deno doc --lint`; F-5 ≤20 root exports; zero dependencies | +| **W2 — `@netscript/database` (A4)** | `defineTarget`/`defineSpace`/`defineDatabase`, the pure compiler, all composition invariants V-1…V-8, diagnostics | W1 | A4 gate set; property test: compile is deterministic and total; every invariant has a negative test producing the right code; no IO reachable (AP-25 scan) | +| **W3 — `@netscript/database-prisma-postgres` (A2)** | Capability descriptor, emitter, control adapter, runtime factory, `upstream.ts` facade, import allowlist | W1, W2 | A2 gate set + runtime gates; conformance suite green against a **real** PostgreSQL service; import-allowlist check; Deno import-purity check | +| **W4 — `@netscript/database-runtime` (A3)** | Binding, process/request scope, lifetimes, health, close ordering, `AbortSignal`, `{ stop() }` | W1, W3 | **All F-1…F-19** and **required runtime gates**; leak test under repeated start/stop and request lifecycles; scope-type test proving request scope cannot cache | +| **W5 — `@netscript/database-control` (A2)** | classify/compose/plan/apply/verify/emit, locks, receipts, resume, expiry, partial success | W1, W2, W3 | A2 gate set; negative-path matrix (§14); atomic-emission test; offline test proving `pure` never reaches an orchestrator | +| **W6 — `@netscript/database-testkit` (A6)** | Provider conformance suite, space conformance suite, machine-readable report | W1, W3, W5 | A6 gate set + F-CLI rules; certifies W3 provider; a deliberately broken provider fixture must fail | +| **W7 — `@netscript/plugin` contribution surface (A4)** | `defineDatabaseSpace`; remove `PluginDbSchemaContribution`/`PluginMigrationContribution`; adjust `ContributionAxis` | W1, W6 | A4 gate set; **breaking-change accounting for a published package**; consumer import validation | +| **W8 — CLI + agent surface (A6)** | `db` verbs as projections; generated agent manifest; adoption tool | W5, W6 | A6 gate set; every generated example compiles and runs; command/diagnostic catalogs match machine output | +| **W9 — First-party plugin migration (A5)** | Convert `auth`, `workers`, `sagas`, `triggers` to spaces; namespace their objects; declare capabilities | W7, W8 | A5 gate set + **required runtime gates**; each plugin passes the space conformance kit; `@db.Uuid`-class provider locks now declared | +| **W10 — Cutover** | Adoption tool applied; delete `database//`, the 30 tasks, the repair scripts, the old packages | W8, W9 | Release-gate class (DB wiring + scaffold output + Aspire helper generation all change); full `scaffold.runtime` E2E; production-shaped adoption rehearsal on a seeded database | + +Retirement of `@netscript/prisma-adapter-mysql` and `@netscript/database` happens in W10, not +earlier: they must keep working until the last consumer moves. + +--- + +## 14. Conformance matrix + +This is the artifact that makes "adoption is gated by NetScript proof, not by an upstream label" +operational. Each row is a required, independently-failing case. + +### 14.1 Type, plan, artifact, result, and lifecycle + +| # | Case | Passes when | +| ---- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | +| T-1 | Space requires a capability the bound target lacks | Composition fails, `db.compose.capability.missing`, names capability + space + target | +| T-2 | Space bound to an undeclared target id | **Type error** at the authoring site, not a runtime diagnostic | +| T-3 | Two spaces own one `ObjectKey` | `db.compose.ownership.conflict` naming both spaces | +| T-4 | Cyclic `dependsOn` | `db.compose.dependency.cycle` with the cycle path | +| T-5 | Cross-target relation declared | Refused at composition with a next-action, never emitted | +| T-6 | Type surface, plan, emitted SQL, and result agree for a non-trivial feature (e.g. null-ordering) | All four consistent — this is the case that catches "published type ignored at runtime" | +| T-7 | Request-scoped session used after disposal | Type-level prevention where possible; runtime error otherwise | +| T-8 | Interactive transaction handle escapes its callback | Rejected; `tx` must not expose transaction-opening members (repairs the observed `withTransaction` defect) | +| T-9 | Every operation returns a typed result | No code path returns a bare number or relies on an exit code | +| T-10 | Artifact postconditions asserted | Every receipt's `ArtifactAssertion` matches the filesystem | + +### 14.2 Deterministic and atomic emission + +| # | Case | Passes when | +| --- | ------------------------------------------------- | ------------------------------------------------------------------ | +| E-1 | Emit twice from a clean checkout | Byte-identical artifacts and identical `ManifestDigest` | +| E-2 | Emit two targets concurrently into distinct roots | Both succeed; no interleaving | +| E-3 | Emit interrupted mid-write (SIGKILL) | Artifact root is either fully old or fully new; never half-patched | +| E-4 | Schema edited without re-emitting | `db.artifact.stale` at bind time, naming the exact command | +| E-5 | Manifest digest recorded in every artifact root | Present and matching (V-8) | +| E-6 | CI re-run with an unchanged digest | Emission skipped; recorded digest asserted instead | + +### 14.3 Migration and failure + +| # | Case | Passes when | +| ---- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| M-1 | Greenfield apply | Succeeds with a full receipt | +| M-2 | Adoption of an existing populated database | Marker rows only; zero DDL; `verify` clean | +| M-3 | Drift introduced externally | `db.verify.drift` classifies managed vs adopted vs external correctly | +| M-4 | Destructive change under `destructive: 'deny'` | Refused with the destructive operation list | +| M-5 | Destructive change in `production` with an unsigned plan | Refused regardless of interactive consent | +| M-6 | Plan applied after the manifest changed | `db.plan.stale` | +| M-7 | Plan applied after `planMaxAgeMs` | `db.plan.expired` | +| M-8 | Apply fails mid-run | Receipt shows the exact failed step; `resume` continues and re-validates the baseline first | +| M-9 | Two concurrent applies on one target | Second gets `db.apply.lock.held` with owner and TTL; no interleaved DDL | +| M-10 | Lock holder dies | TTL/fencing releases; no permanent wedge | +| M-11 | Data transform with an unsatisfied invariant | Fails and reports remaining work; does not advance the head | +| M-12 | Non-default namespace | All operations honour it; a silently ignored schema selector is a failure | +| M-13 | Two same-provider targets | Fully isolated output, lineage, markers, receipts | +| M-14 | Migration on Windows | Runs — **explicitly required**, since the current fixture refuses non-Linux `[OBSERVED]` | + +### 14.4 Plugin lifecycle + +| # | Case | Passes when | +| ---- | ------------------------------------------------- | --------------------------------------------------------------------------- | +| P-1 | Two plugins, one target, declared ordering | Applied in topological order recorded in the manifest | +| P-2 | Plugin object-name collision across spaces | Namespaced and non-conflicting; no lexical prefix convention required | +| P-3 | Cross-space foreign key along a declared edge | Allowed; without the edge, refused | +| P-4 | Plugin upgrade with a lineage step | Head advances for that space only | +| P-5 | Installed package digest ≠ mirror digest | `db.space.skew` with both digests | +| P-6 | Apply/verify with **no plugin package installed** | Succeeds from the pinned mirror alone | +| P-7 | Uninstall with retention | Objects retained; ownership downgraded to `adopted`; verify still sees them | +| P-8 | Uninstall with a dependent space installed | Refused, naming the dependent | +| P-9 | Uninstall with `drop` | Requires explicit consent and produces a destructive plan | +| P-10 | Plugin declares a capability its target lacks | Install refused at composition (the `@db.Uuid`-class case) | +| P-11 | Augmentation outside a granted axis | Refused, naming the grant that would be required | +| P-12 | Upstream extension owning its own space | Recorded as `external`; not reported as drift | + +### 14.5 Real PostgreSQL, Deno/import purity, generated projects, journeys, CI/release + +| # | Case | Passes when | +| --- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| R-1 | Full runtime suite against a **real** PostgreSQL service | CRUD, relations, raw, codecs, transactions, prepared statements, streaming, cancellation all pass — not an emulator | +| R-2 | Connection injection and external pool | Behaves under concurrency; no query serialisation surprise | +| R-3 | Error mapping and secret redaction | Connection strings and passwords never appear in diagnostics, receipts, or logs | +| D-1 | Deno import graph of runtime paths | No undeclared Node globals; no CLI/toolchain module reachable | +| D-2 | Packed-artifact install into a blank fixture | Every used export and peer resolves exactly once | +| D-3 | Deep-import allowlist | Any new upstream deep import fails the build | +| D-4 | `deno publish --dry-run` on every new package | Passes **without** `--allow-slow-types` | +| G-1 | Generated project type-checks and starts | Scaffold → emit → apply → run, unattended | +| G-2 | `emit` in a container with no Aspire CLI, no .NET, no Docker | Succeeds | +| J-1 | Journey: scaffold → add second same-provider target → add two plugins → migrate → deploy | No manual step, no hand-edited generated file | +| J-2 | Journey: adopt an existing populated project (§12.3) | Preflight clean; zero DDL; verify clean | +| N-1 | Every diagnostic code has a negative test | Each code is reachable and carries a `nextAction` | +| N-2 | No gate asserts on human-readable message text | Gates assert on codes and structured results only (repairs the observed string-matching fixture) | +| C-1 | Release-gate class | Full `scaffold.runtime` E2E green on the cutover | +| C-2 | Agent surface | Every generated example compiles and executes; catalogs match machine output | + +--- + +## 15. Risks, findings, unresolved decisions, and checkpoints + +### 15.1 Severity-tagged findings against the current research and plan + +| # | Severity | Finding | Consequence if unaddressed | +| ---- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| F-1 | **Critical** | `isolatedDeclarations: true` is repo-wide `[OBSERVED]` and the `--allow-slow-types` carve-out covers only oRPC-bound packages `[OBSERVED]`. No research document mentions either. | The RFC would propose a package that cannot be published, discovered during implementation rather than at plan lock. | +| F-2 | **Critical** | The plan's archetype set (A1/A2/A4/A5/A6) omits Archetype 3, but the runtime half owns lifecycle and scope `[OBSERVED:`06-archetypes.md:78-83`]`. | All F-1…F-19 and _required_ runtime gates are silently dropped from the gate set. | +| F-3 | **High** | The clean break removes published surface from `@netscript/plugin`: `PluginDbSchemaContribution`, `PluginMigrationContribution`, and two `ContributionAxis` members `[OBSERVED]`, none of which has any implementation `[OBSERVED]`. Not scoped anywhere. | An unplanned breaking change to a second Archetype-4 package, discovered late. | +| F-4 | **High** | Doctrine currently _codifies_ the model being removed: plugin schema contributions "are plain `*.prisma` files… They do not contain a private workspace" (`06-archetypes.md:209-211`) `[OBSERVED]`. Amending doctrine is itself an RFC trigger `[OBSERVED]`. | The RFC contradicts doctrine it never amends; `arch:check` and the RFC disagree. | +| F-5 | **High** | Live defect the audit does not surface: plugin fragments use PostgreSQL-only `@db.Uuid` `[OBSERVED]` while the installer's target chain ends `?? databases[0]`, escaping the `enabled` filter `[OBSERVED]`. | The capability model is argued abstractly when a concrete reproducible defect could anchor it. | +| F-6 | **High** | `execute(): Promise` `[OBSERVED]` means receipts are not additive — the return type makes structured reporting impossible. The audit presents this as missing behaviour. | Sequencing error: "add receipts" is planned as a slice when it is a replacement of the operation contract. | +| F-7 | **Medium** | `withTransaction` types its callback parameter as the full `Client` `[OBSERVED]`, so `tx.$transaction` type-checks inside an interactive transaction. The audit's "structurally-cast" understates a type-level correctness defect. | A known-unsound signature is carried forward as merely inelegant. | +| F-8 | **Medium** | `packages/database` declares **zero** dependencies `[OBSERVED]` — upstream independence is achieved by duck typing, not by design. | The RFC must state how the provider obtains _real_ types without re-exporting them; otherwise the new design silently re-adopts structural typing. | +| F-9 | **Medium** | `DatabaseConfigSchema` hardcodes a `zodGenerator` block and accepts provider aliases (`postgresql\|postgres`, `mssql\|sqlserver`) `[OBSERVED]`, and `mapEngine` normalises again `[OBSERVED]`. | A validator choice is baked into the core config vocabulary, and there are two normalisation sites for one concept. | +| F-10 | **Medium** | `mapEngine`'s `switch` over the engine union selecting providers `[OBSERVED]` is doctrine AP-24, whose canonical counter-example is literally a database-engine switch `[OBSERVED]`. | A live doctrine violation goes uncited in the RFC's motivation. | +| F-11 | **Medium** | The merge-readiness migration fixture refuses to run outside Linux and asserts on the literal string `'created no migration artifact'` `[OBSERVED]`. | The gate proving the most expensive historical repair neither covers the platform where the schema-engine hangs occurred nor survives a reword. | +| F-12 | **Medium** | Five of six specialist sub-agents returned nothing (§1.2). The Prisma numeric claims, the ADR coverage, the 30-fix-commit count, the ~9,175-line figure, and the control/runtime signatures are `[CARRIED — NOT RE-VERIFIED]`. | The RFC would cite unverified figures as evidence. | +| F-13 | **Low** | The plan's validation table has no gate that re-proves numeric research claims. | Nothing catches F-12. | +| F-14 | **Low** | The plan's risk register lacks "the upstream seam moves during the RFC's own authoring window" — which has already happened (post-RC CLI/config unification) `[CARRIED — NOT RE-VERIFIED]`. | The mitigation (§8.3) is not tracked as a risk. | +| F-15 | **Low** | Doctrine drift: A9 says "six archetypes" while seven exist `[OBSERVED]`. | Minor, but the RFC touches this file and should not silently inherit it. | + +### 15.2 Failure-mode ledger + +| Failure mode | Structural prevention | Proven by | +| ----------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------ | +| Two logical databases collapsed into one directory | Target id is declared; V-6 forbids shared roots | T-3, M-13 | +| Wrong or ambiguous target selected implicitly | No fallback chain anywhere; explicit target sets | T-2, feature-parity removals (§12.6) | +| Client constructed in the wrong order | No `setClient`; the runtime owns construction | W4 gates | +| Stale generated types compiled against | Digest recorded in every artifact root; bind refuses a mismatch | E-4, E-5 | +| Success reported without artifacts or state | Typed results plus `ArtifactAssertion` postconditions | T-9, T-10 | +| Unversioned fragment copied without analysis | Spaces with capability requirements and ownership | P-10, P-11 | +| Adding an engine requires editing switches everywhere | Typed provider registry populated at the composition root | F-10 remediation | +| Aspire/Docker required for pure compilation | Operation classification; `pure` gets no connection resolver | G-2 | +| Generated text patched as a permanent shim | I-5; no repair step exists | E-1, E-3 | +| Plugin schema silently absent | Pinned mirror is the source; apply works with no package installed | P-6 | +| Read-only command kills the resident host | Only `resident` operations bind a resident graph | §7.2 | +| Cross-target apply falsely described as atomic | `partially-succeeded` is a first-class outcome (I-9) | M-8 | +| Secret leakage through connection parsing | Redaction is a conformance case | R-3 | +| Agent instructions drift from reality | Generated from the manifest; every example executed | C-2 | + +### 15.3 Rejected alternatives + +| Alternative | Rejected because | +| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Keep `DatabaseGraph` as a live runtime object | It is a service locator with a domain name; the durable artifact is a manifest value (Part 1 §2.1). | +| One `@netscript/database` package holding DSL, runtime, and control | Two incompatible gate profiles and dependency needs; doctrine's "one archetype per package" is satisfied by splitting packages. | +| Re-export the provider's runtime type from a framework package | Blocked by `isolatedDeclarations` + slow-types, and by AP-14. | +| Extend the `--allow-slow-types` carve-out to the database packages | Converts an application-local inference problem into permanent framework publish debt (§12.1). | +| A NetScript model DSL that lowers to the upstream contract | A third schema language, permanently lagging, with translated error messages (§10.1). | +| Mirror-validator codegen from the contract | Combinatorially impossible for selection-aware output validation, and it re-creates the repair pipeline (§11.1–11.2). | +| Port `@netscript/prisma-adapter-mysql` forward | Re-imports the hand-maintained low-level driver surface the redesign exists to remove (§9.4). | +| Wait for upstream to close the operational gaps | Gates adoption on someone else's roadmap; the gaps are NetScript's to own anyway (§8.2). | +| A compatibility facade during cutover | Doubles the failure surface in the least-understood window; contradicts the owner directive (§12.5). | +| Universal output validation | Gets disabled wholesale in production, which is worse than precise boundaries (§11.4). | + +### 15.4 Unresolved and conditional decisions + +These must be recorded in the RFC as conditional on Prisma 8 **final**, not resolved by the RC. + +| # | Decision | Conditional on | +| ---- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| U-1 | Whether validation can be derived from contract runtime data without a generation step | The maintainer-exchange hypothesis proven by NetScript's own conformance run; if false, revisit §11 wholesale | +| U-2 | The exact control-API package path and option shapes | Post-RC churn settling; contained by §8.3 but not eliminated | +| U-3 | Contract format version and hash representation | Explicitly still moving; NetScript records its own digest meanwhile | +| U-4 | Whether the contingency control backend is ever needed | Built and CI-exercised regardless; promotion decided at GA | +| U-5 | SQLite's capability set | Requires conformance measurement, not the upstream scorecard | +| U-6 | MySQL strategy | Retire-and-defer recommended; revisit if a requirement lands before an upstream target | +| U-7 | Whether an AOT validation projection ships at all | Only if semantic equivalence is mechanically provable (§11.7) | +| U-8 | Advisory-lock strategy per provider | Native lock vs ledger row with fencing, decided per certified provider | +| U-9 | Whether `@netscript/database-testkit` is A6 or folds into `./testing` subpaths | Depends on whether it ships a runnable binary | +| U-10 | Plan signing mechanism and key custody | Out of scope here; required before W10 production use | + +### 15.5 Kill-switch criteria + +Adoption of Prisma 8 as the first provider should be abandoned, and the provider port satisfied by a +different implementation, if any of these hold at GA: + +- The Deno import graph cannot be made clean without vendoring or patching upstream (D-1 unfixable). +- `deno publish --dry-run` cannot pass on the provider package without `--allow-slow-types` (D-4). +- Emission is not deterministic (E-1) or not atomic (E-3) and upstream will not make it so. +- Per-space markers or ledger coupling cannot be made transactional on PostgreSQL (M-9, M-11). +- Contract format changes without a migration path more than once between GA and the first NetScript + release that depends on it. + +The design survives all five because the provider is a leaf behind a port — which is the point of +§8.3. The kill switch costs a provider, not an architecture. + +### 15.6 Decision checkpoints for plan lock + +The supervisor can treat these as a tick-list before locking the Plan-Gate: + +1. Accept or reject the manifest-over-live-graph reframing (Part 1 §2.1). +2. Accept the seven/nine-package split and the per-package archetype assignments, including + **Archetype 3** for the runtime package (F-2). +3. Confirm that no published package will export a contract-typed value, and that the typed binding + is generated app-side (F-1). +4. Add the `@netscript/plugin` breaking-change scope to the plan (F-3). +5. Add the doctrine amendment (`06-archetypes.md` Archetype 5 + archetype table + verdict table) to + the RFC scope (F-4). +6. Add a claim-ledger gate that re-proves every numeric research claim before the RFC cites it + (F-12, F-13). +7. Decide `expose / wrap / translate` for the upstream TypeScript schema builder — recommended: + expose for entities, wrap at the composition seam, translate nothing (§10.1). +8. Decide the validation default — recommended: runtime-derived, memoised by contract identity, with + mirror codegen explicitly rejected (§11.1). +9. Decide the MySQL disposition — recommended: retire and defer (§9.4). +10. Approve the operational-layer ownership split (§8.2), which is the largest scope decision here. +11. Confirm the cutover has no compatibility layer and that adoption writes marker rows only + (§12.3). +12. Record U-1…U-10 as conditional on Prisma 8 final. + +### 15.7 Implementation blockers + +- **B-1.** Plan signing and key custody (U-10) block W10 production use, not earlier waves. +- **B-2.** A real PostgreSQL service in CI blocks W3's acceptance gate; PGlite or an emulator does + not satisfy R-1. +- **B-3.** Windows coverage for migration operations (M-14) needs a runner; without it, the + historical schema-engine failure class stays unproven. +- **B-4.** The maintainer-exchange hypothesis (U-1) blocks finalising §11's default, though the + Standard Schema boundary is safe either way. + +--- + +## 16. Source register and recommendation + +### 16.1 Local sources verified in this session `[OBSERVED]` + +| Path | Used for | +| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `deno.json` (root) | `isolatedDeclarations: true`; workspace globs; `arch:check`, `quality:scan`, `publish:dry-run`, `doc:lint` tasks | +| `packages/database/deno.json` | 10 exports; **zero** dependencies | +| `packages/database/mod.ts:128-140` | `withTransaction` cast and callback typing | +| `packages/database/scripts/` | `patch-prisma-client.ts`, `migrate.ts`, `fix-zod-imports.ts`, `generate-zod.ts` published via `./scripts` | +| `packages/plugin/src/domain/constants.ts:16-26` | `ContributionAxis` closed union incl. `database-schema`, `migration` | +| `packages/plugin/src/abstracts/plugin-db-schema-contribution.ts` | `path`, optional `engine` union | +| `packages/plugin/src/abstracts/plugin-migration-contribution.ts` | `name`, `path` | +| repo-wide grep for those abstracts | Zero implementations | +| `packages/config/src/domain/schemas/database-schema.ts` | Provider aliases; `zodGenerator` in core config | +| `packages/cli/src/public/features/db/db-group.ts:32-53` | The fourteen verbs | +| `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:50` | `join('database', provider.dirName)` | +| `…/workspace-resolver.ts:71-88` | `resolveTarget` single-target defaulting | +| `…/workspace-resolver.ts:96+` | `mapEngine` switch (AP-24) | +| `packages/cli/src/kernel/adapters/database/operation-runner.ts:85-107` | `Promise`; `studio → databases[0]`; fail-fast loop | +| `packages/cli/src/kernel/adapters/plugin/db-integration.ts:101-105, 275-300` | Target chain ending `?? databases[0]`; `as DbEngine` cast | +| `packages/cli/src/kernel/adapters/plugin/prisma-schema-writer.ts:133` | Normalised-body collision policy | +| `packages/cli/e2e/…/verify-db-migration-artifacts.ts` | Linux-only guard; literal-string assertion | +| `packages/cli/e2e/…/database-gates.ts` | `GATE.DATABASE_*` command gates | +| `plugins/{auth,workers,sagas,triggers}/database/*.prisma` | `@db.Uuid`/`@db.VarChar`/`@db.Text`; unprefixed vs prefixed names | +| `plugins/workers/scaffold.plugin.json` | `hasDatabaseMigrations` boolean; `dependencies: ["streams"]` | +| `packages/{contracts,plugin,service,sdk}/deno.json` | oRPC + `@standard-schema/spec` topology | +| `docs/architecture/doctrine/01-thesis-and-axioms.md` | A1–A14 | +| `docs/architecture/doctrine/02-public-surface.md:73-138, 217-242` | Entry verbs; subpaths; slow-types carve-out | +| `docs/architecture/doctrine/05-folder-structure.md` | Layering law; folder vocabulary | +| `docs/architecture/doctrine/06-archetypes.md` | Archetypes 1–7; `:209-211` fragment rule; `:374-411` table | +| `docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md` | AP-3, AP-4, AP-14, AP-18, AP-24, AP-25; F-1…F-19 | +| `docs/architecture/doctrine/10-codebase-verdict-and-handoff.md:37, 50, 90-95` | Verdicts; the 36-path gated denominator | +| `.llm/harness/archetypes/README.md:23-26` | One-archetype-per-package law | +| `.llm/harness/gates/archetype-gate-matrix.md` | Gate columns; release-gate class | +| `.llm/harness/gates/plan-gate.md:18-40` | Plan-Gate checklist | +| `.llm/harness/debt/arch-debt.md` | `AP-17` on `packages/database`; `DB-GENERATE-ASPIRE-COUPLING`; auth roadmap R1 | +| `rfcs/README.md`, `rfcs/0000-template.md`, `rfcs/0003-command-composition-kit.md` | RFC triggers, front-matter, section structure, implementation-grade reference | + +### 16.2 Sources carried from the committed research `[CARRIED — NOT RE-VERIFIED]` + +The Prisma 8 primary-source register in `research/prisma-8-deep-dive.md` — RC tag `v8.0.0-rc.1` +(`a76a6c5`), post-RC `main` (`71e2e0d`), the RC scorecard, ADRs 176/212/242, the control-API and +PostgreSQL runtime sources, the project skill, supported-versions and serverless docs, and the +upstream issue/PR ledger — plus the market comparators in `research/market-analysis.md`. The +owner-provided maintainer exchange is treated as primary exploratory evidence for U-1. Every figure +drawn from these must pass the claim-ledger gate (F-12/F-13) before the RFC cites it. Where this +report needed a number I used the supervisor's corrected values: `^7.8.0` root ranges, `^7.4.2` in +generated templates, 30 generated database tasks, TypeScript 5.9 as an **optional** peer, and +roughly 138 top-level `@prisma/orm-postgres` export keys. No skill-count totals are relied upon +anywhere in this report. + +### 16.3 Recommendation + +Proceed, with three amendments to the plan before Plan-Gate lock. + +The research's direction is sound and the Prisma 8 integration thesis holds: adopt the contract, +space, and lineage _semantics_; own the _operational_ layer; keep the provider a replaceable leaf. +The design that follows is smaller than the system it replaces because it refuses to abstract the +query surface — that refusal is what keeps NetScript from building a second ORM, and it should be +stated in the RFC as a non-goal rather than left implicit. + +The three amendments are not stylistic. **First**, reframe the central abstraction from a live graph +to a compiled manifest; this changes what gets published and what stays internal. **Second**, add +Archetype 3 and its mandatory runtime gates; without it the plan's gate set is incomplete by +construction. **Third**, record the `isolatedDeclarations`/slow-types constraint as a first-class +design input; it decides where the typed binding lives, and discovering it during implementation +would invalidate a package boundary after the RFC is accepted. + +One caution on the evidence base. Five of six specialist lanes in this session returned nothing, so +a meaningful share of the Prisma-side detail in the committed research remains unverified by any +independent pass. The architecture in this report does not depend on those figures — it depends on +the upstream _shape_, which is corroborated by multiple independent descriptions — but the RFC will +cite them, and it should not do so until the claim-ledger gate has run. That is the cheapest +remaining risk to retire before locking the plan. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md index 53532145a8..afc10fa286 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md @@ -15,33 +15,46 @@ which products have solved parts of the framework-level problem: - an accurate agent-facing surface. The comparison uses official product documentation and source repositories observed on 2026-08-13. -It evaluates eleven purposeful comparators: +It evaluates seventeen purposeful comparators: 1. Wasp and RedwoodJS as Prisma-based full-stack frameworks; 2. Payload and Better Auth as plugin-heavy TypeScript products; 3. AdonisJS Lucid as an integrated application-framework database layer; 4. Drizzle, MikroORM, and Kysely as TypeScript data-tooling architectures; -5. Atlas as a database delivery/control-plane product; and -6. Django and Rails as mature app-owned migration and multi-database systems. +5. Flyway and Liquibase as mature migration-ledger, locking, repair, and extension systems; +6. Terraform and Pulumi as plan/apply/state/checkpoint and partial-failure prior art; +7. Atlas and Bytebase as database delivery/control-plane products; +8. ZenStack v3 as a TypeScript schema/plugin/runtime-validation comparator; and +9. Django and Rails as mature app-owned migration and multi-database systems. + +A focused independent correction audit covers the additional evidence and exact recovery semantics +in more depth in [market-gap-audit.md](./market-gap-audit.md). This document integrates its +decision-relevant conclusions without reproducing the companion report verbatim. No product is a template to copy wholesale. The desired NetScript architecture combines the strongest ownership, extensibility, lifecycle, and safety ideas while avoiding their manual seams. ## Executive comparison -| Product | Strongest relevant idea | Important limitation for NetScript | -| -------------- | ----------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | -| Wasp | Framework commands and generated auth/app schema create a coherent Prisma happy path | Still fundamentally one framework-managed Prisma schema/client and provider story. | -| RedwoodJS | Framework-level schema, structural migrations, seeds, and explicit data migrations | Largely forwards Prisma CLI concepts; data and structural migration ordering remains manual. | -| Payload | Thin internal database contract with official Mongo/Drizzle adapters | Adapter abstraction serves Payload's CMS model, not arbitrary app/plugin contract ownership. | -| Better Auth | Typed plugin schema declarations plus an adapter factory that centralizes mechanics | Prisma/Drizzle users still generate an ORM schema and manually migrate it. | -| AdonisJS Lucid | Named typed connections, lifecycle ownership, programmatic runner, locks, data-migration defer | ORM/config is framework-specific and plugins do not own independent contract spaces. | -| Drizzle | Broad dialect coverage, SQL escape hatches, schema filters, many migration workflows | Multiple configs and exported schema aggregation remain developer-managed; ownership is implicit. | -| MikroORM | Clean core/driver/extension split with broad providers and programmable migration runner | One ORM instance does not span independent connections; multi-schema fan-out has stateful caveats. | -| Kysely | Small open dialect/driver/plugin interfaces, zero-dependency cross-runtime query core | Schema types/codegen and migration authoring are intentionally external/manual. | -| Atlas | Composite schema graph, semantic migration lint, drift, policy, promotion, target-group rollout | Separate product/control plane; application runtime typing and plugin APIs are out of scope. | -| Django | Per-app migration graphs with declared dependencies and mature routing | Multiple databases are operated one at a time and router mistakes may silently skip migrations. | -| Rails | Named DBs, per-DB migration roots, runtime role/shard switching, unmanaged DB flag | Database ownership is config/folder-based, not a typed plugin contribution protocol. | +| Product | Strongest relevant idea | Important limitation for NetScript | +| -------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| Wasp | Framework commands and generated auth/app schema create a coherent Prisma happy path | Still fundamentally one framework-managed Prisma schema/client and provider story. | +| RedwoodJS | Framework-level schema, structural migrations, seeds, and explicit data migrations | Largely forwards Prisma CLI concepts; data and structural migration ordering remains manual. | +| Payload | Thin internal database contract with official Mongo/Drizzle adapters | Adapter abstraction serves Payload's CMS model, not arbitrary app/plugin contract ownership. | +| Better Auth | Typed plugin schema declarations plus an adapter factory that centralizes mechanics | Prisma/Drizzle users still generate an ORM schema and manually migrate it. | +| AdonisJS Lucid | Named typed connections, lifecycle ownership, programmatic runner, locks, data-migration defer | ORM/config is framework-specific and plugins do not own independent contract spaces. | +| Drizzle | Broad dialect coverage, SQL escape hatches, schema filters, many migration workflows | Multiple configs and exported schema aggregation remain developer-managed; ownership is implicit. | +| MikroORM | Clean core/driver/extension split with broad providers and programmable migration runner | One ORM instance does not span independent connections; multi-schema fan-out has stateful caveats. | +| Kysely | Small open dialect/driver/plugin interfaces, zero-dependency cross-runtime query core | Schema types/codegen and migration authoring are intentionally external/manual. | +| Flyway | Mature history states, checksum validation, database locks, repair, and programmatic runner | Locations share one history; repair does not clean objects left by failed non-transactional DDL. | +| Liquibase | Changeset ledger/lock, preview/rollback, broad changelog and Java extension surfaces | Path/order-based composition and one shared ledger are not contributor-owned migration spaces. | +| Terraform | Explicit config/plan/state/backend split and honest partial-apply recovery semantics | Mutable state is not a manifest/receipt; apply is non-atomic and saved plans are opaque/sensitive. | +| Pulumi | Frequent checkpoints and first-class recovery for interrupted, outcome-unknown operations | Complete planning is weakened by program execution/unknowns; robust backends are a hosted concern. | +| Atlas | Composite schema, semantic lint, migration planning, and optional registry/control plane | Composition uses load order; continuous drift, promotion, and fleet history are Cloud services. | +| Bytebase | Plan/issue/rollout stages, SQL review, approvals, and per-database task history | Persistent control plane; current releases removed automatic schema drift detection. | +| ZenStack v3 | Explicit schema imports, schema/CLI/runtime plugins, and runtime-derived shaped Zod schemas | One aggregate history; plugins are preview and validation is Zod-specific rather than Standard. | +| Django | Per-app migration graphs with declared dependencies and mature routing | Multiple databases are operated one at a time and router mistakes may silently skip migrations. | +| Rails | Named DBs, per-DB migration roots, runtime role/shard switching, unmanaged DB flag | Database ownership is config/folder-based, not a typed plugin contribution protocol. | The market does not offer one complete equivalent of the proposed NetScript layer. The opportunity is real: treat database structure as a composed, typed ownership graph; drive runtime and control @@ -285,17 +298,144 @@ What remains weak: NetScript lesson: keep the SPI small and extensible, but do not inherit the fragmented toolchain. One graph must tie schema, types, migrations, connections, and agent surface together. +### Flyway + +Flyway's Java API centers on `Flyway.configure().dataSource(...).load()` and programmatic operations +such as `migrate()`. Its +[command surface](https://documentation.red-gate.com/flyway/reference/commands) includes `migrate`, +`info`, `validate`, `repair`, and `baseline`, with undo, dry-run, comparison, and drift features +varying by edition. Recursively scanned +[locations](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-locations-setting) +feed one migration sequence and one +[schema history table](https://documentation.red-gate.com/flyway/flyway-concepts/migrations/flyway-schema-history-table). +That table records checksums and precise states including failed, missing, future, out-of-order, +outdated, and superseded migrations. + +Migration starts under a database lock with a configurable retry count; Native Connectors currently +do not implement that locking. Where the database supports transactional DDL, migrations can run +individually or, with `group=true`, as one pending-migration transaction. PostgreSQL may need a +session-level rather than transactional advisory lock for operations such as +`CREATE INDEX CONCURRENTLY`. +[Repair](https://documentation.red-gate.com/flyway/reference/commands/repair) can remove failed +ledger rows and realign checksums, but user objects left by a failed non-transactional migration +still require manual cleanup. + +Flyway also supports Java migrations, callbacks, and custom migration resolvers/executors through +its [Java hooks](https://documentation.red-gate.com/flyway/reference/usage/api-java/api-hooks). +Those are strong execution-extension points, not typed schema ownership: multiple locations still +share one history and do not acquire stable contributor IDs, independent heads, or removal policy. + +NetScript lesson: migration state vocabulary, locks, checksum integrity, and structured repair are +mature prior art. NetScript must add contributor/target identity and distinguish `failed`, +`cleanup_required`, and `outcome_unknown`; “repair ledger” must never imply “repair database.” + +### Liquibase + +Liquibase composes XML, YAML, JSON, or formatted-SQL changelogs. A changeset's durable identity is +`id + author + filepath`; +[`logicalFilePath`](https://docs.liquibase.com/secure/reference-guide-5-1-1/changelog-attributes/logicalfilepath) +stabilizes moves and avoids module collisions. `includeAll` loads recursively in alphabetical order +unless a custom comparator is supplied. These mechanisms support modular files, but not semantic +dependency edges or independent contributor histories. + +`DATABASECHANGELOG` stores checksum, order, execution type, contexts, labels, and a deployment ID; +`DATABASECHANGELOGLOCK` serializes updates with a single database row and may require +`release-locks` after an unclean exit. +[`update-sql`](https://docs.liquibase.com/secure/reference-guide-5-2-1/init-update-and-rollback-commands/update-sql) +previews generated SQL but explicitly does not prove correctness or bind a later apply. Changesets +are transactional where possible; with +[`runInTransaction=false`](https://docs.liquibase.com/secure/reference-guide-5-1/changelog-attributes/runintransaction), +a mid-changeset error can leave both schema and ledger inconsistent. Rollback, snapshot, `diff`, and +`diff-changelog` provide explicit recovery and inspection, not a continuously reconciled state +backend. +[Inspection command coverage](https://docs.liquibase.com/secure/reference-guide-5-2-1/database-inspection-change-tracking-and-utility-commands/what-are-database-inspection-commands) +also varies by object and edition. + +Liquibase has a broad Java extension model covering databases, changes, changelog formats, +executors, preconditions, snapshots, SQL generators, and resource access. `ServiceLoader` discovers +implementations and priority selects one for the current context. This is powerful but demonstrates +why NetScript contribution resolution should reject ambiguity rather than hold a plugin priority +contest. +[Extension anatomy](https://contribute.liquibase.com/extensions-integrations/extensions-overview/extension-anatomy/) + +NetScript lesson: use logical, path-independent space/migration IDs; topologically order declared +dependencies rather than files; treat arbitrary extension code as a pinned supply-chain boundary; +and do not mistake a shared lock/ledger for contributor isolation. + +### Terraform + +Terraform's most useful analogy is its explicit separation of configuration, saved plan, mutable +state, and state backend. [State](https://developer.hashicorp.com/terraform/language/state) maps +resource addresses to remote object identities and provider metadata. It is not desired +configuration and is not an immutable run receipt. A +[saved plan](https://developer.hashicorp.com/terraform/cli/commands/plan) is an opaque apply input +that can contain the full configuration, values, options, and cleartext sensitive data; a +speculative plan carries no apply intent. + +Backends store state and may provide locking, but locking is optional by backend. State uses lineage +and monotonically increasing serials to reduce unsafe manual pushes. On +[apply failure](https://developer.hashicorp.com/terraform/tutorials/cli/apply), Terraform records +completed changes, unlocks, and exits without automatic rollback; the operator fixes the cause and +applies again. `-target` is explicitly exceptional recovery machinery because it may leave changes +and outputs incomplete. `-refresh-only` makes adoption of observed drift reviewable, and also shows +why changing the framework's record of reality must be a deliberate operation. + +Provider executables expose schema, validate, configure, read, plan, and apply RPCs over gRPC and +are version/checksum-pinned. Those schemas describe provider/resource configuration and state, not +application query/mutation/result validation. +[Provider RPC lifecycle](https://developer.hashicorp.com/terraform/plugin/framework/internals/rpcs) + +NetScript lesson: the resolved manifest is immutable generated configuration, not Terraform state; +the operation receipt is evidence, not an authoritative shadow database; executable plans must be +secret-free, baseline-bound, and revalidated; and routine `--target`-style partial apply should be +rejected. NetScript should not build a remote state backend or generic provider RPC ecosystem. + +### Pulumi + +`pulumi up` executes a program, observes resource registrations, constructs a goal graph, and +compares it with recorded stack state. Pulumi does not query every provider automatically before +each preview/update; explicit refresh incorporates live drift. +[Saved update plans](https://www.pulumi.com/docs/iac/concepts/update-plans/) remain experimental and +are checked incrementally as the program runs. Unknown outputs, resources created inside `apply`, +and providers configured with unknown values can make preview incomplete, so earlier operations may +run before a plan discrepancy is discovered. + +Pulumi writes frequent checkpoints. Pulumi Cloud supplies transactional checkpoint APIs, while DIY +blob backends have locking/history but document weaker recovery from some partial failures. +Interrupted creates can remain `pending` because the engine cannot know whether the provider +finished; recovery requires inspecting the provider and then clearing or importing the object with +`pulumi refresh`. +[Interrupted-update recovery](https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/) +Pulumi does not automatically roll back failed updates, and targeted operations may use stale +recorded values for non-targeted dependencies. + +Providers combine a separate executable with language SDKs generated from a package schema; native, +Terraform-bridged, parameterized, and dynamic providers are supported. The +[plugin architecture](https://www.pulumi.com/docs/iac/concepts/plugins/) is strong extensibility +prior art, but package schemas generate SDKs rather than Standard Schema-compatible trust-boundary +validators. + +NetScript lesson: composition must be pure enough to yield a complete deterministic plan; receipts +need an `outcome_unknown` phase; uncertain operations must be inspected before retry; and hosted +transactional checkpoints, policy, audit, scheduled drift, and KMS are integration concerns rather +than kernel features. + ### Atlas Atlas is the closest comparator for the database control plane rather than runtime ORM. Its [project configuration](https://atlasgo.io/atlas-schema/projects) includes a `composite_schema` data source that loads multiple schemas—from SQL, HCL, ORMs, or external sources—into one graph. Order -expresses dependencies, and multiple sources can extend the same database namespace. +controls loading for dependencies, and multiple sources can extend the same database namespace. That +is useful composition, but configuration order is weaker than declared semantic dependency edges and +independent contributor histories. Its [CI/CD workflow](https://atlasgo.io/guides/evaluation/ci-cd) develops a desired schema, plans a migration, runs semantic lint/simulation in review, delivers an approved artifact, and applies it. -Atlas exposes drift detection, schema testing, target groups, staged rollout, audit history, and -machine-readable output. Its +The local CLI/Pro surface provides schema testing, machine-readable output, versioned/declarative +planning, and synchronous pre-apply drift checks. Registry promotion, fleet deployment history, +continuous drift monitoring, notifications, and agent-mediated database access belong to +[Atlas Cloud](https://atlasgo.io/cloud/getting-started) and its +[paid agent](https://atlasgo.io/cloud/agents). Its [destructive-change policy](https://atlasgo.io/guides/destructive-change-policy) can remove drops from a plan, fail them deterministically in CI, and enforce deprecation workflows. The [agent guidance](https://atlasgo.io/guides/ai-tools) treats migration generation, linting, policy, @@ -306,21 +446,72 @@ What works: - multiple schema sources become one inspectable graph; - desired state and versioned migration workflows can coexist; - semantic lint and policy run before apply; -- approved plans can be promoted across environments; -- drift and deployment history are explicit; -- target groups support database-per-tenant rollout; and +- executable migration artifacts can be reviewed before local apply; +- synchronous pre-apply drift can guard deployments; and - agent behavior is constrained by deterministic policy. What remains weak: - runtime query typing/client lifecycle are separate concerns; -- advanced CI/registry/policy features may require a hosted/commercial control plane; +- registry/promotion, fleet status, continuous drift, audit history, approvals, and notifications + require a hosted/commercial control plane; - composite ordering is configuration order unless stronger semantics are layered above it; - app/plugin packages do not automatically expose a TypeScript contribution factory. NetScript lesson: copy the plan-review-deliver-apply state machine, policy gates, drift vocabulary, -receipts, and composed graph semantics. Keep the NetScript core local and provider-neutral; an Atlas -adapter can remain an optional future delivery backend. +and composed graph semantics that can run locally. Do not infer that Atlas Cloud's registry, +continuous monitoring, rollout history, agents, or collaboration layer are cheap local primitives. +An Atlas adapter can remain an optional future delivery backend. + +### Bytebase + +Bytebase's [Plan](https://docs.bytebase.com/change-database/plan) defines DDL/DML changes for one or +more databases, receives automatic SQL review, becomes an Issue for approval, and then drives a +Rollout. Rollouts contain environment stages and per-database tasks; stages can progress +sequentially while tasks within a stage can run in parallel. SQL review, rollout policy, approvals, +scheduling, task status/logs, explicit skip reasons, and before/after schema history make partial +fleet progress visible. + +This is a persistent database control plane even when self-hosted in one container: it owns +workspace metadata, users, roles, issues, schedulers, credentials, policies, and audit history. It +does not provide an application ORM, runtime Standard Schema layer, or typed contributor-owned +migration spaces. A server-side Plan/Issue/Rollout record is not the same as a portable, signed, +offline NetScript plan artifact. + +A material current correction is that Bytebase +[removed Schema Drift Detection in 3.14.0](https://docs.bytebase.com/changelog/bytebase-3-14-0), +including its related API fields. Current schema comparison, history, and +[synchronization](https://docs.bytebase.com/change-database/synchronize-schema) must not be scored +as continuous drift monitoring. + +NetScript lesson: borrow staged per-target result visibility, SQL policy vocabulary, and explicit +partial success. Keep IAM, approval flows, schedulers, database groups, notifications, permanent +audit storage, and fleet dashboards outside the local kernel; integrate with Bytebase optionally. + +### ZenStack v3 + +ZenStack v3 is no longer Prisma-backed at runtime; it uses a Kysely-based ORM while retaining a +Prisma-superset ZModel language and PrismaClient-compatible query shape. +[Explicit imports](https://zenstack.dev/docs/modeling/multi-file) are type-checked and merged into +one schema AST before downstream tools run. This is clearer than implicit directory merging, but it +still produces one aggregate schema and one migration history rather than contributor-owned spaces. + +The preview [plugin model](https://zenstack.dev/docs/modeling/plugin) accepts a built-in provider, +local module, or npm package. Plugins can contribute schema attributes/functions, generation, CLI +behavior, and ORM runtime interception. Schema enablement and runtime installation remain distinct, +so a contribution can be only half-installed unless a higher-level manifest binds both. The current +`zen migrate` commands expose a single schema and migrations path, temporary Prisma schema +mechanics, and manual `resolve --applied`/`--rolled-back` recovery. + +The [`@zenstackhq/zod` runtime factory](https://zenstack.dev/docs/utilities/zod) is the strongest +direct comparator to NetScript validation: it derives typed model schemas from the resolved ZenStack +schema and supports `select`, `include`, `omit`, nested relation shaping, and create/update +optionality. It remains Zod 4-specific and does not document a provider-neutral Standard Schema +surface for complete operation arguments, storage/wire representations, or extension codecs. + +NetScript lesson: adopt explicit composition, runtime derivation, and selection-aware validator +ergonomics. Add stable contributor identity/history/provenance/removal policy, bind schema and +runtime installation in one record, and keep Standard Schema—not Zod—as the durable public boundary. ### Django @@ -385,33 +576,36 @@ artifact. ## Cross-market capability matrix -Legend: **strong** means the capability is a primary, documented abstraction; **partial** means it -exists but leaves important manual integration; **none** means it is not a product-level concept. - -| Product | Typed target graph | Plugin/feature schema owner | Independent migration graph | Multi-DB routing | Programmatic control | Semantic CI policy | Agent surface | -| ------------------ | ------------------------ | --------------------------- | --------------------------- | ------------------------- | --------------------- | ------------------- | -------------------- | -| Wasp | Partial | Partial | None | None | Partial | None | Partial | -| RedwoodJS | Partial | None | Partial (data ledger) | None | Partial | None | Partial | -| Payload | Partial | Partial | Partial | Partial | Partial | None | Partial | -| Better Auth | Partial | Strong declaration | None | Partial | Partial | None | Partial | -| Adonis Lucid | Strong named connections | Partial | Per connection | Strong | Strong | Partial | Partial | -| Drizzle | Partial/multi-config | Partial file exports | Per config | Partial | Strong | Partial | Partial | -| MikroORM | Strong per instance | Partial metadata | Per instance/schema | Partial | Strong | Partial | Partial | -| Kysely | Open dialect config | None | Replaceable provider | Caller-owned | Strong primitives | None | None | -| Atlas | Strong control graph | Strong source composition | Strong | Strong target groups | Strong | Strong | Strong | -| Django | Strong aliases/routers | Strong apps | Strong | Strong but one-at-a-time | Strong | Partial | Partial | -| Rails | Strong named DB/roles | Partial engines | Per database | Strong | Strong | Partial | Partial | -| Proposed NetScript | Strong, single graph | Strong contract spaces | Strong per space/target | Strong capability routing | Strong structured API | Strong local policy | Generated from graph | +The earlier broad matrix overstated Atlas's local capabilities and scored an unimplemented NetScript +proposal as already strong. This narrower matrix evaluates the four artifacts at the center of the +RFC: resolved manifest, executable plan, receipt/recovery record, and contributor space, plus the +runtime validation boundary. **Strong** means a current primary capability; **partial** means +materially different or manual; **hosted** means a persistent control plane is required. The +NetScript row is an unimplemented design target, not a market fact. + +| Product/pattern | Resolved desired manifest | Apply-bound plan | Durable run evidence / partial recovery | Contributor-owned schema + history | Runtime selection-aware validation | Lock / drift boundary | +| --------------------- | -------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------- | +| Flyway | Partial config + ordered migrations | None; dry-run is not bound | Strong history/repair; manual object cleanup can remain | None; locations merge into one history | None | JDBC database lock; Native Connector gap; drift edition-gated | +| Liquibase | Partial root changelog | Partial `update-sql` preview | Strong ledger/lock/rollback vocabulary | Partial module identity, shared ledger | None | Database lock; explicit diff/snapshot, not reconciliation | +| Terraform CLI | Strong config graph; mutable state separate | Strong opaque saved plan | Strong mutable state and partial-apply recovery; no rollback | Partial modules/providers, not DB owners | None; provider schemas are unrelated | Backend-dependent lock; refresh/refresh-only drift | +| Pulumi OSS | Partial graph emerges from program execution | Partial/experimental and incrementally enforced | Strong checkpoints and pending-operation recovery | Partial packages/components, not DB owners | None; package schemas generate SDKs | DIY lock; explicit refresh | +| Pulumi Cloud | Same program graph | Partial/experimental | Hosted transactional checkpoints, history, and policy | None for DB schema ownership | None | Hosted locking and scheduled drift | +| Atlas CLI/Pro | Strong schema graph | Partial/strong migration and declarative planning | Strong migration directory/ledger and local apply evidence | Partial composite sources; load order, not owned histories | None | Pre-apply drift is Pro; local apply semantics | +| Atlas Cloud | Strong registry source of truth | Strong promotion/registry workflow | Hosted deployment history and fleet status | Partial source composition | None | Hosted agents, scheduled drift, notifications | +| Bytebase current | Strong persistent server-side Plan | Strong Plan → Issue → Rollout, not offline artifact | Strong stage/task history and partial fleet rollout | None | None | Persistent scheduler; automatic drift feature removed | +| ZenStack v3 | Strong single composed AST | None beyond wrapped migration workflow | Partial migration status/resolve | Partial schema/plugin contribution; one history | Strongest comparator, but Zod-specific and incomplete | No multi-target lock/drift layer | +| Prisma 8 RC substrate | Strong contract snapshot per target | Emerging control plan | Stronger graph/marker/ledger substrate | Strong spaces; removal/retention conditional | No stable public Standard Schema layer | Adapter/provider dependent | +| Proposed NetScript | **Design target, not implemented** | **Design target; live-baseline binding unproven** | **Design target; unknown/partial/resume paths unproven** | **Conditional on NetScript policy and upstream conformance** | **Design target; runtime/AOT equivalence unproven** | **Design target; local per-target only, no hosted monitor** | ## Design patterns to import -### 1. One framework graph, not many config files +### 1. One resolved manifest, not many config files Adonis, Rails, and Django prove stable named connections are understandable. Atlas proves multiple schema sources can be composed. NetScript should combine them: ```text -defineDatabaseGraph({ +defineDatabaseManifest({ targets: { primary: databaseTarget(...), analytics: databaseTarget(...), @@ -424,7 +618,9 @@ defineDatabaseGraph({ }); ``` -The graph must resolve to a deterministic manifest before runtime or database access. +The source manifest must resolve through one pure function to a deterministic, content-addressed +snapshot before runtime or database access. Array position, file path, provider discovery order, and +package-manager traversal must not become semantic dependency edges. ### 2. Contributor-owned migration spaces @@ -450,17 +646,21 @@ Better Auth and Kysely show how to make extension authors productive: a small fa centralizes naming, lifecycle, serialization, errors, and compatibility. NetScript target authors should supply only provider-specific capabilities and bindings, then pass a conformance kit. -### 4. Plan is the deployment contract +### 4. An apply-bound plan is the deployment contract -Atlas's develop/review/deliver/apply model should govern every mutating NetScript database -operation: +Atlas's develop/review/deliver/apply model is useful process prior art. Terraform and Pulumi add the +harder recovery lesson: a preview is not an executable plan, and applying a valid plan is not an +atomic transaction. Every mutating NetScript database operation should follow: ```text compose -> inspect -> plan -> policy/lint/test -> approve -> apply -> verify -> receipt ``` -The approved artifact binds graph digest, target, environment, live baseline, operations, package -versions, and expiry. Apply refuses drifted inputs. +The approved artifact binds the resolved-manifest digest, exact target and contribution spaces, +environment, live-baseline fingerprint, ordered operations, policy result, provider/package lock +digests, and expiry. It excludes secret values and carries only stable references. Apply acquires +the native lock, revalidates every binding, checkpoints irreversible operations, and refuses stale +inputs. A speculative preview may be human-readable, but it must not be accepted as this artifact. ### 5. Managed and external ownership are different @@ -480,6 +680,67 @@ Adonis, MikroORM, Kysely, and Atlas expose programmatic runners. NetScript comma typed operation API. Help, JSON schema, documentation, and agent skills should be generated views of that operation catalog. +## Artifact and control-plane boundary + +The RFC should name five artifacts and keep their responsibilities disjoint: + +1. **Source manifest:** authored targets, contributions, dependencies, ownership, and policy. +2. **Resolved snapshot:** pure, deterministic, content-addressed composition with provenance. +3. **Executable plan:** an expiring deployment contract bound to one inspected baseline and exact + provider/package locks. +4. **Upstream ledger or marker:** provider-native migration history and lock evidence; NetScript + reads it but does not invent a second mutable source of truth. +5. **Operation receipt:** immutable append-only evidence of attempted work, checkpoints, + verification, and any uncertain or partial outcome. + +The local NetScript kernel should own deterministic resolution and digests; overlap and provenance +checks; local policy/lint/test; native lock orchestration; target/space invocation; immutable +receipts and inspect-before-resume; and the runtime Standard Schema validation boundary. It should +not turn the manifest or receipts into Terraform-like mutable state. + +Remote state and transactional checkpoints, organization/RBAC systems, approval and issue workflow, +artifact registries and promotion, continuous drift schedulers, fleet dashboards, centralized audit +servers, notifications, agents, and KMS/secrets are optional control-plane concerns. Pulumi Cloud, +Atlas Cloud, and Bytebase show their value, but also the persistent services and operators they +require. The local meta-framework should expose stable integration events and artifact formats for +such systems, not quietly rebuild them. + +## Plan-lock consequences + +The comparison changes these RFC decisions: + +1. The manifest, snapshot, plan, upstream ledger, and receipt are separate types. None is a mutable + general-purpose state backend. +2. Preview and executable planning are different operations. Only the latter may be approved and + applied, and it binds manifest digest, target/space set, baseline, ordered operations, policy, + package/provider locks, environment, and expiry. +3. Apply acquires a provider-native lock and then revalidates the baseline and all plan bindings. + Lock scope, timeout, owner/nonce, stale-lock inspection, and any force-unlock path are explicit; + unsupported locking is surfaced as a capability gap. +4. Receipt states include at least `planned`, `locked`, `started`, `applied`, `verified`, `failed`, + `partial_success`, `skipped`, `cleanup_required`, and `outcome_unknown`. Checkpoint after each + irreversible operation. +5. After interruption or transport loss, inspect the database and upstream ledger before retrying. + Never blindly replay an operation whose outcome is unknown. +6. Cross-target execution is a dependency-ordered saga, not an atomic transaction. Report each + target/space result and do not promise automatic rollback. +7. Selective target/space execution includes dependency closure, records omitted work and reasons, + and still verifies whole-manifest invariants. Terraform-style targeting is exceptional recovery, + not the normal deployment model. +8. Drift comparison is ownership-aware: managed, adopted, external, and ignored objects have + different policies. Adoption is an explicit reviewed operation. +9. Logical IDs, not paths, array order, config order, or provider discovery, define identity and + dependencies. +10. Plugin contributions carry version, digest, provenance, capabilities, owned space, lifecycle + phase, and removal policy. Schema-time and runtime halves must install and validate together. +11. Contributor removal and data retention remain conditional until the upstream substrate proves + the required semantics and NetScript passes conformance tests. +12. Runtime validation binds operation, target, normalized selection, wire representation, codecs, + cache key, and runtime/AOT equivalence. A Zod adapter is useful, but is not the Standard Schema + contract itself. +13. Registry, promotion, fleet history, continuous drift, RBAC, approvals, notifications, and + centralized secrets remain external control-plane integrations unless separately chartered. + ## Anti-patterns to reject The market analysis reinforces explicit rejection of: @@ -494,6 +755,15 @@ The market analysis reinforces explicit rejection of: - generated code repaired by string replacement; - data transforms sequenced independently from structural migration state; - shared stateful migration runners used concurrently; +- treating the source manifest or immutable receipts as a Terraform-style mutable state backend; +- accepting a dry run or speculative preview as an apply-bound plan; +- using targeted partial apply as the routine deployment path; +- deriving dependencies from alphabetical, filesystem, array, or provider-discovery order; +- treating migration-ledger repair as proof that partially created database objects were cleaned up; +- claiming registry, promotion, fleet, continuous drift, audit, approval, or notification features + without the hosted control plane that implements them; +- assigning a proposed capability a market score of “strong” before implementation and conformance + evidence; - database-specific behavior hidden behind an over-broad generic repository; and - agent instructions maintained separately from the real command/type surface. @@ -502,9 +772,9 @@ The market analysis reinforces explicit rejection of: NetScript can plausibly offer a distinctive database story: > Declare every database target and schema contributor once. NetScript composes and validates the -> graph, provisions connections, emits only canonical artifacts, binds typed runtime sessions, plans -> and verifies every migration, and gives humans, CI, plugins, and agents the same structured -> view—without copied schemas, patched clients, or hidden manual steps. +> resolved manifest, provisions connections, emits only canonical artifacts, binds typed runtime +> sessions, plans and verifies every migration, and gives humans, CI, plugins, and agents the same +> structured view—without copied schemas, patched clients, or hidden manual steps. That is materially more than a Prisma wrapper. It is a meta-framework control and composition layer whose first high-fidelity runtime/control adapter is Prisma 8 PostgreSQL. @@ -537,11 +807,35 @@ whose first high-fidelity runtime/control adapter is Prisma 8 PostgreSQL. [Dialect SPI](https://kysely-org.github.io/kysely-apidoc/interfaces/Dialect.html), [adapter base](https://kysely-org.github.io/kysely-apidoc/classes/DialectAdapterBase.html), [official CLI](https://github.com/kysely-org/kysely-ctl) +- Flyway: [commands](https://documentation.red-gate.com/flyway/reference/commands), + [locations](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-locations-setting), + [schema history](https://documentation.red-gate.com/flyway/flyway-concepts/migrations/flyway-schema-history-table), + [repair](https://documentation.red-gate.com/flyway/reference/commands/repair), + [Java hooks](https://documentation.red-gate.com/flyway/reference/usage/api-java/api-hooks) +- Liquibase: + [logical file identity](https://docs.liquibase.com/secure/reference-guide-5-1-1/changelog-attributes/logicalfilepath), + [SQL preview](https://docs.liquibase.com/secure/reference-guide-5-2-1/init-update-and-rollback-commands/update-sql), + [transaction control](https://docs.liquibase.com/secure/reference-guide-5-1/changelog-attributes/runintransaction), + [inspection](https://docs.liquibase.com/secure/reference-guide-5-2-1/database-inspection-change-tracking-and-utility-commands/what-are-database-inspection-commands), + [extension anatomy](https://contribute.liquibase.com/extensions-integrations/extensions-overview/extension-anatomy/) +- Terraform: [state](https://developer.hashicorp.com/terraform/language/state), + [saved/speculative plans](https://developer.hashicorp.com/terraform/cli/commands/plan), + [apply failure](https://developer.hashicorp.com/terraform/tutorials/cli/apply), + [provider RPC lifecycle](https://developer.hashicorp.com/terraform/plugin/framework/internals/rpcs) +- Pulumi: [update plans](https://www.pulumi.com/docs/iac/concepts/update-plans/), + [interrupted updates](https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/), + [plugins](https://www.pulumi.com/docs/iac/concepts/plugins/) - Atlas: [project/composite schema](https://atlasgo.io/atlas-schema/projects), [CI/CD](https://atlasgo.io/guides/evaluation/ci-cd), [destructive policy](https://atlasgo.io/guides/destructive-change-policy), [agent workflow](https://atlasgo.io/guides/ai-tools), - [database-per-tenant control plane](https://atlasgo.io/guides/database-per-tenant/control-plane) + [Cloud](https://atlasgo.io/cloud/getting-started), [Cloud agents](https://atlasgo.io/cloud/agents) +- Bytebase: [plans](https://docs.bytebase.com/change-database/plan), + [schema synchronization](https://docs.bytebase.com/change-database/synchronize-schema), + [3.14.0 drift-feature removal](https://docs.bytebase.com/changelog/bytebase-3-14-0) +- ZenStack v3: [multi-file schemas](https://zenstack.dev/docs/modeling/multi-file), + [plugins](https://zenstack.dev/docs/modeling/plugin), + [selection-aware Zod factory](https://zenstack.dev/docs/utilities/zod) - Django: [migrations](https://docs.djangoproject.com/en/5.2/topics/migrations/), [migration operations](https://docs.djangoproject.com/en/5.2/ref/migration-operations/), [multiple databases](https://docs.djangoproject.com/en/5.2/topics/db/multi-db/), diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md index bbc6516be9..48a306a43c 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md @@ -11,10 +11,10 @@ This audit deliberately separates three upstream states that must not be conflat | Upstream main | [`71e2e0d`](https://github.com/prisma/prisma/tree/71e2e0d9ee1f306b5a11435cd1973023cb33866a), observed 2026-08-13 | Six days of post-RC changes that reveal which integration seams are still moving. | Prisma calls this release Early Access and explicitly does not recommend it for production -workloads. The RC source requires Node.js 24+, declares TypeScript 5.9 as the package peer floor, -and describes PostgreSQL as the sole database intended for 8.0 GA. MongoDB remains Early Access, -SQLite is a proof of concept, MySQL follows later, and SQL Server is not present in the Prisma 8 -target set. +workloads. The RC source requires Node.js 24+, declares TypeScript 5.9 as an optional package peer +floor, and describes PostgreSQL as the sole database intended for 8.0 GA. MongoDB remains Early +Access, SQLite is a proof of concept, MySQL follows later, and SQL Server is not present in the +Prisma 8 target set. The analysis below uses this confidence vocabulary: @@ -95,9 +95,9 @@ a sufficient plugin policy. The RC publishes facade, framework, family, target, toolchain, and extension packages under `@prisma/orm-*`. `@prisma/orm-postgres` is described as the one package an application installs, but -its export map contains more than one hundred subpaths spanning adapters, control internals, -contract internals, migration tooling, query ASTs, runtime, target planning, and utilities. It also -depends on `pg`. +its export map contains 138 top-level subpath keys spanning adapters, control internals, contract +internals, migration tooling, query ASTs, runtime, target planning, and utilities. It also depends +on `pg`. This is useful for extension authors and dangerous for a meta-framework: @@ -415,21 +415,72 @@ type-check time, not at a late database call. ## Validation and generated types -Prisma 8 uses Standard Schema-compatible validation for extension/codec parameters and ships an -ArkType JSON extension. It does not replace NetScript's current generated Zod model/input/output -surface with a complete general validator generator. Zod and Valibot appear as future directions, -not RC guarantees. - -NetScript should separate three concerns: - -1. **database contract types**, emitted by Prisma; -2. **boundary validation**, owned by application/API/domain schemas through Standard Schema; and -3. **database codec validation**, contributed by database extensions. - -It should not generate, patch, and re-export a second model universe merely because Prisma types -exist. Where CRUD boundary schemas are desired, a validator provider should deterministically derive -them from a supported IR and emit them once into an atomic target-specific artifact root. Provider -output must pass semantic tests; textual repair is forbidden. +The pinned RC source supports a qualified runtime-interpreter design. The emitted contract contains +a bounded runtime value algebra: scalar codec references, value objects, unions, nullability, +`many`, `dict`, and value-set references +(`packages/1-framework/0-foundation/contract/src/domain-types.ts:5-39`). SQL storage adds native +type, codec parameters/references, defaults, nullability, and value sets +(`packages/2-sql/1-core/contract/src/ir/storage-column.ts:15-25`), while model relations and +cross-space coordinates remain explicit (`domain-types.ts:41-75` and +`packages/1-framework/0-foundation/contract/src/cross-reference.ts:5-14`). NetScript can interpret +that bounded algebra directly into `StandardSchemaV1` values without generating validator source. +This is feasibility against `v8.0.0-rc.1`, not evidence of a stable upstream validation API. + +Standard Schema is the right NetScript public boundary, but Prisma's existing Standard Schema slot +does not validate model values. `CodecDescriptor.paramsSchema` validates JSON-sourced codec +_parameters_ and exposes TypeScript renderers +(`packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts:27-54`). Codec +instances instead define three conversion representations—application runtime, database-driver wire, +and contract/database JSON +(`packages/1-framework/1-core/framework-components/src/shared/codec.ts:16-30,44-51`)—without a value +predicate. NetScript should therefore expose `representation: 'runtime' | 'json'`, reserve driver +wire for adapter internals, and require every built-in or custom codec contributor to provide an +explicit value schema for each supported representation. A codec with conversion functions but no +matching value schema is unsupported; conversion success must not be treated as validation. + +The interpreter must remain narrower than Prisma's generated type universe. SQL plans retain the +operation AST, parameters, projection aliases, expressions, and optional codec references +(`packages/2-sql/4-lanes/relational-core/src/plan.ts:19-22` and +`src/ast/types.ts:1480-1505,1510-1538,1892-1910,1984-2002`), but codec metadata is explicitly absent +for computed, subquery, and raw projections (`ast/types.ts:1484-1488`). Mongo plans retain the +command and an optional nested result shape +(`packages/2-mongo-family/4-query/query-ast/src/query-plan.ts:15-20` and +`src/result-shape.ts:1-13`), yet that shape permits `unknown`. Generated SQL field, operation, +codec, and aggregate type maps are phantom/type-only +(`packages/2-sql/1-core/contract/src/types.ts:90-139,207-215`) and are emitted into `contract.d.ts` +(`packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts:179-221`), not retained as +runtime validation metadata. Direct model fields and fully known selections can be validated; +filters, nested writes, polymorphic narrowing, computed/aggregate/include/raw results, and any +unknown shape require an explicit operation/result contributor or must fail closed. + +Contract spaces also remain separate identities. The aggregate exposes app and extension contracts +per space rather than merging them +(`packages/1-framework/3-tooling/migration/src/aggregate/types.ts:32-79,81-123`), and cross-space +domain checks are deferred to aggregate deployment +(`packages/1-framework/0-foundation/contract/src/validate-domain.ts:140-147`). Validator lookup and +cache identity must include `spaceId`, resolve references through an integrity-checked aggregate, +and never flatten equal namespace/model names from different spaces. + +No existing section hash is a complete validator cache key. RC hashing separately covers storage, +execution, and capability profile +(`packages/1-framework/0-foundation/contract/src/hashing.ts:74-106`), while domain, roots, and +extensions can change independently. NetScript should digest the canonical full-contract +representation (`contract/src/canonicalization.ts:250-277`) together with schema version, space, +target/family, operation or selection, representation, interpreter ABI, and codec/pack contributor +identities; include execution identity when defaults matter. Unsupported metadata must raise a +deterministic schema-construction error, never silently become `unknown` or pass-through. + +Ahead-of-time output remains an optional startup/performance optimization only if conformance tests +prove it is semantically identical to the runtime interpreter for success values, issue paths, +representation handling, unsupported-case failures, and cache invalidation. It must not become a +second hand-maintained model universe or require textual repair. + +Post-RC evidence is narrower and must not be read back into the RC: object `71e2e0d` adds +`packages/2-sql/2-authoring/contract-ts/src/data-contract-json-schema.ts:10-15,31-38,68-110`, which +labels generated contract JSON Schema lossy/advisory, keeps ArkType authoritative, and accepts +unknown pack maps generically because a static editor schema cannot know contributed kinds. That +improves validation of `contract.json`; it does not add model-data schemas, codec value predicates, +or universal result-shape metadata. ## Runtime/platform support and Deno @@ -486,11 +537,11 @@ Prisma 8 treats agent instructions as product surface. `init` installs a version skill and a lock file, and the skill routes by workflow. The direction is excellent: an agent gets local version-specific commands, structured errors, known gaps, and explicit references. -The RC content is not trustworthy enough to consume directly: +The RC content is not trustworthy enough to consume directly. Repo-local scans find dozens of legacy +`@internal/...` paths and `PN-*` error-code references, but exact totals vary materially with the +token/root-counting pattern and are not load-bearing evidence. More importantly: -- 83 distinct legacy `@internal/...` import roots appear in the `prisma-8` skill; -- those roots occur 116 times; -- 47 legacy `PN-*` error-code references remain after the public move to dotted codes; +- legacy internal imports and error-code vocabulary remain after the public move to dotted codes; - one reference says raw SQL is unavailable while runtime source exposes `raw`; - one reference says prepared statements are not a user surface while runtime source exposes `prepare`; diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md new file mode 100644 index 0000000000..73b9b31834 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md @@ -0,0 +1,299 @@ +# Runtime validation source audit + +> Provenance: independent delegated pinned-source audit. RC-tag evidence and post-RC-main evidence +> are explicitly separated below. No web sources were used. The requested `.llm/tmp/prisma-v8-rc1` +> path was absent; the evidence checkout actually inspected was the intact, clean, detached checkout +> at `/home/codex/.local/share/Trash/files/prisma-v8-rc1`, verified at HEAD +> `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` (`v8.0.0-rc.1`). Post-RC comparison used the locally +> available Git object `71e2e0d` only where explicitly labeled. + +## Bottom-line decision + +**Qualified YES to interpretation, NO to contract-only full parity.** A NetScript runtime can +interpret the emitted contract into `StandardSchemaV1` validators for a deliberately bounded algebra +(model/value-object/union/list/dict/nullability/value-set plus known codecs), and can use plan +metadata for a bounded set of projections. That can eliminate generated validator _code_. It cannot +eliminate validator _metadata/contributions_, and it cannot correctly validate Prisma’s complete +create/update/filter/nested-write/aggregate/raw surface from the RC contract alone. Full parity +would require rebuilding the missing operation type system and custom-codec application predicates; +unsupported cases must fail at schema construction, never degrade to `unknown`/pass-through. + +This is **source-level feasibility, not a stable Prisma API commitment**. The relevant common +contract facade is exported by the RC public package, but family IR/plan details remain experimental +and the package itself is `8.0.0-rc.1`. + +## 1. What the machine contract actually contains (RC proof) + +**Envelope/namespaces.** `packages/1-framework/0-foundation/contract/src/contract-types.ts:29-56` +calls `Contract` the canonical in-memory model and carries `target`, `targetFamily`, `roots`, +namespaced `domain`, family storage, `capabilities`, opaque `extensions: Record`, +optional execution, `profileHash`, metadata, control policy; `:36-37` explicitly says persisted +`schemaVersion`/`sources` live only at serialization. `domain-envelope.ts:9-21` gives each +application namespace `models`, optional `valueObjects`, optional `enum`. `cross-reference.ts:5-14` +has namespace/model and optional cross-space `space`; `value-set-ref.ts:25-30` has plane, +namespaceId, entity kind/name and optional `spaceId`. + +**Model/value shape.** `domain-types.ts:5-29` is the runtime value algebra: scalar +`{codecId,typeParams?}`, value-object by name, union of scalar/value-object, and fields with +mandatory `nullable` plus `many?`, `dict?`, `valueSet?`. `:31-39` gives ordered domain enums as +`{codecId,members:[{name,value:JsonValue}]}`. `:41-75` represents reference/embed relations, +local/target fields, cardinality, and N:M junction coordinates. `:77-99` has discriminator/variants, +value objects, model fields/relations/storage/base/owner. There is **no field-level +required/optional flag and no per-value Standard Schema**. + +**Defaults.** `contract/src/types.ts:95-133` defines JSON values and storage column defaults +(`literal` or opaque function expression; author input may be `Date`); `:147-179` defines execution +generators by namespace/table/column and `onCreate`/`onUpdate`. These help determine some +omission/default behavior, but are not a complete create/update input grammar. + +**SQL provider/native detail and constraints.** `packages/2-sql/1-core/contract/src/types.ts:65-75` +maps a model field to `{column,codecId?,nullable?}` and model to `{table,namespaceId,fields}`. +`ir/storage-column.ts:15-25,40-63` carries `nativeType`, `codecId`, `nullable`, `many`, mutually +exclusive `typeParams`/`typeRef`, default/control/valueSet. `ir/storage-table.ts:12-20,34-69` +carries columns, PK, uniques, indexes, FKs, checks and control. `ir/primary-key.ts:4-7`, +`ir/unique-constraint.ts:4-7`, and `ir/foreign-key.ts:5-24` carry names, column tuples, target refs +and referential actions. `ir/sql-index.ts:13-43,63-97` permits column or opaque expression, opaque +partial predicate, unique/type/options. `ir/check-constraint.ts:10-22` only models a structured +column→valueSet check, not arbitrary check SQL. Thus DB structural constraints are present, but +uniqueness/FK/index enforcement is not locally decidable and opaque expressions are +information-losing. + +**SQL contract extensibility.** `ir/sql-storage.ts:65-69,98-118` is namespaced storage with known +`table`/`valueSet` plus open pack entity kinds; `:168-203` deliberately fails unknown storage type +discriminators. `validators.ts:131-177` validates registered entity kinds and fails unregistered +kinds; `:416-442` defines the full ArkType contract envelope. +`sql-contract-serializer-base.ts:40-61,81-99` validates structure then hydrates IR; `:219-240` +serializes all registered namespace entry kinds. Pack entities are therefore runtime-extensible but +only interpretable when their contributor is installed. + +**Postgres native enum.** +`packages/3-targets/3-targets/postgres/src/core/postgres-native-enum.ts:6-12,21-38,49-59` stores +target-only native enum `typeName`, ordered string members and control under +`storage.namespaces[ns].entries.native_enum`. `postgres/src/core/codecs.ts:374-388` says its codec +is string pass-through and does **not** carry members; membership comes from the column +valueSet/native type. NetScript must resolve the valueSet/native-enum entity, not infer membership +from codec ID. + +**Mongo family.** `packages/2-mongo-family/1-foundation/mongo-contract/src/contract-types.ts:37-78` +has model collection/relation storage and one namespaced domain; `:87-107,154-167` has phantom type +maps and falls back to `unknown` without them. `contract-schema.ts:7-80` validates field +algebra/enums/relations; `:82-135` Mongo JSON validator; `:139-211` indexes/collection options; +`:213-238` model discriminators/variants/base/owner; `:245-343` collection storage; `:345-351` value +sets; `:380-413` pack-fragment handling; `:416-458` full envelope. +`ir/mongo-validator.ts:3-10,29-40` stores Mongo JSON Schema/validation level/action; +`ir/mongo-collection.ts:19-24` stores indexes/validator/options/control. A stored Mongo validator is +DB-side collection validation, not automatically the application model/result schema. + +**Type information that is NOT runtime data.** SQL `contract/src/types.ts:90-139` defines +codec/query-operation/field input/output/storage/aggregate maps, but `:207-215` installs them under +an optional phantom key. `framework/emitter/src/generate-contract-dts.ts:179-221` emits those maps +into generated `contract.d.ts`; SQL emitter `src/index.ts:531-541` says defaults use the codec JSON +channel, and `:575-615` renders refined input/output/valueSet/many/nullability types. These type +maps are erased at runtime. This is the strongest evidence against “contract alone has all Prisma +type semantics.” + +## 2. Plans: operation and result-shape sufficiency (RC proof) + +**Common plan.** `framework-components/src/execution/query-plan.ts:15-22` carries only `meta` plus +runtime-absent phantom `_row`; `:25-33` adds nothing in `ExecutionPlan`. +`contract/src/types.ts:223-232` plan metadata is target/family, storageHash, optional profileHash, +lane, arbitrary annotations—no executionHash, contract-full hash, or runtime row schema. + +**SQL.** `relational-core/src/plan.ts:19-22` retains `AnyQueryAst` and params. AST operation kinds +are explicit: `ast/types.ts:1892-1910` insert rows/onConflict/returning, `:1984-2002` update +set/where/returning, `:2051-2065` delete/where/returning, and `:2122-2140` raw SQL. Select +`:1510-1538` retains from/joins/projection/filter/group/having/etc. Projection `:1480-1505` retains +alias, expression, optional `CodecRef`, but `:1484-1488` explicitly says codec is absent for +computed expressions, subqueries and raw aliases. Table source `:346-368` has namespaceId; direct +columns can be resolved to storage. The current decoder confirms the limits: +`packages/2-sql/5-runtime/src/codecs/decoding.ts:28-45` extracts projections and only resolves +codecs; `:164-171` says value validation lives only inside a codec; `:179-186` accepts null and +missing codecs/pass-through; `:198-223` checks only the array container for `many`; `:251-299` +checks missing projected aliases but is not a declarative result validator. Result: operation-aware +input walking is possible for literal/simple AST positions, and direct-column returning/select +output is recoverable by alias+column+codec; computed/raw/subquery/include/aggregate output is not +generally recoverable. + +**Mongo.** `query-ast/src/query-plan.ts:15-20` retains collection, discriminated command and +optional `resultShape`. `result-shape.ts:1-13` is unusually useful: document/unknown, leaf +`{codecId,nullable}`, nested document/array/unknown. Commands `commands.ts:8-179` distinguish +insert/update/delete/find-and/aggregate and retain documents/filter/update/options. Raw commands +`raw-commands.ts:4-156` use opaque `Document`. The decoder proves the shape is a decode hint, not +enforcement: `runtime/src/codecs/decoding.ts:48-60` passes unknown/nonobject; `:65-85` passes +missing codecs; `:100-149` accepts null regardless of `nullable` and passes wrong document/array +types; `:159-175` passes unshaped keys. Thus NetScript can interpret a fully-known Mongo +`resultShape` more strictly than Prisma’s decoder, but must reject `unknown`/raw and needs a +separate operation grammar for filters/updates. + +**Conclusion for plans.** They retain enough metadata for a useful subset and selection-aware +outputs when every leaf is known. They do **not** retain a universal runtime schema equivalent to +phantom `ResultType`/generated operation type maps. + +## 3. Existing Standard Schema use (RC proof) + +`packages/9-public/@prisma/orm-framework/package.json:17-20` depends on +`@standard-schema/spec ^1.1.0` and ArkType; exports include `./contract` and `./contract/types` at +`:50-75`. But `framework-components/src/shared/codec-descriptor.ts:27-54` gives +`paramsSchema: StandardSchemaV1

` specifically for JSON-sourced **codec parameters** and TS +renderers; it has no application/wire/json value schema. `:34-41` is explicit about parameter +validation and `.d.ts` rendering. `Codec` itself (`shared/codec.ts:16-32,34-51`) carries conversions +only. Other Standard Schema occurrences similarly cover config/control/policy/extension parameters. +Contract envelopes are authoritative ArkType schemas (which happen to be Standard-Schema-compatible +implementations), but they validate the **contract document**, not CRUD model data. There is no +existing general model-data Standard Schema surface. + +## 4. Runtime vs driver-wire vs JSON (RC proof) + +Prisma actually has **three** representations, not two: `shared/codec.ts:16-30` defines application +`TInput`, database-driver `TWire`, and target JSON used in artifacts/database-produced JSON; +`:44-51` exposes async encode/decode and sync encodeJson/decodeJson. Therefore a NetScript API +option named `wire` is ambiguous; public boundary modes should be `runtime | json`, reserving driver +wire for internal adapters. + +Postgres examples: + +- BigInt/int8: `postgres/codecs.ts:659-689` application `bigint`, driver string|number|bigint + (canonical write string), JSON decimal string. +- Decimal/numeric: `:860-910` application/output is canonical numeric **string**, driver + string|number, JSON string. It is not Prisma.Decimal in this codebase. +- Date: `:921-960`; timestamps `:971-1036`: runtime `Date`; JSON conversion is target helper/ISO. + Date-only is UTC-midnight canonicalized. +- Bytes: `:1262-1298`: runtime/wire `Uint8Array` (Buffer normalized), JSON/base projection base64. +- JSON/jsonb: `:1471-1547`: application `JsonValue`, wire string|JsonValue, JSON identity. +- Native enum: `:390-410` runtime/wire/JSON string; membership elsewhere. + +Mongo builtins `packages/3-mongo-target/2-mongo-adapter/src/core/codecs.ts:22-71`: ObjectId wire +BSON `ObjectId` → runtime hex string; primitives identity; Date runtime/wire Date ↔ JSON ISO; vector +number array. `:78-86,139-166` lists the standard builtins—no contract scalar codec for +Decimal128/Long/bytes/JSON there. Do not assume provider BSON exports imply supported application +scalar semantics. + +Custom codecs are the hard stop: `mongo-codec/src/codecs.ts:23-42,44-82` requires conversion +functions and JSON roundtrip for non-JsonValue inputs, but no Standard Schema value predicate. +Conversion success is not validation (arbitrary coercion/acceptance is legal). Without a new +contributor-provided `{runtimeSchema,jsonSchema}` (and driver schema only if needed), a custom codec +must be unsupported/fail closed. + +## 5. Contract-space aggregation (RC proof) + +`migration/src/aggregate/types.ts:32-79` defines each app/extension as a separate space with its own +head/hash/contract; `:81-123` exposes an aggregate, sorted extension spaces and an ownership +oracle—it does not merge contracts. `aggregate/loader.ts:23-38,53-74` takes the live app contract +and lazily deserializes extension snapshots; `:77-95` synthesizes app head from storageHash; +`:108-148` loads extension spaces independently. Cross-space relation validation is explicitly +deferred: `contract/src/validate-domain.ts:140-147` skips `CrossReference.space` targets for +aggregate deploy-time verification. + +Implication: validator identity and resolution must include `spaceId`; resolve cross-space +references/valueSets through a verified aggregate, never flatten models by namespace/name. Call +aggregate integrity first; unreadable/missing/mismatched space heads must make validator +construction fail. + +## 6. Hash/version/cache identity (RC proof) + +`contract/src/hashing.ts:14` fixes schema version `'1'`; `:39-43` is SHA-256. Crucially `:74-106` +computes three section hashes only: storage (`target/family/storage`), execution +(`target/family/execution`), profile (`target/family/capabilities`). Domain/roots/extensions are +excluded from all three. `contract-types.ts:21-26,41-55` stores executionHash only with execution, +storageHash inside storage, profileHash top-level. `canonicalization.ts:250-277` can produce +canonical full-contract bytes including roots/domain/storage/execution/extensions/capabilities/meta, +but there is no full-contract hash field. Plan meta only has storage/profile (`types.ts:223-232`). +SQL execution content hashing (`packages/2-sql/5-runtime/src/content-hash.ts:5-43`) keys +storageHash+SQL+params; that is an execution-result cache key, not sufficient validator identity. + +Required derived-validator key: digest(canonical full contract snapshot + schemaVersion + spaceId + +target/family + representation + operation/selection shape + NetScript validator ABI/version + +codec/pack contributor ID/version). Include executionHash when default-sensitive. Do not use +storageHash alone: domain/API/extension semantics can change without storage changing. Codec IDs +conventionally embed `@version`, but a custom contributor registry version/identity should also be +explicit. + +`contract/src/types.ts:238-247` marker has storage/profile hashes, contractJson, `canonicalVersion`, +timestamps etc.; it still supplies no domain/full-content digest. Contract JSON schemaVersion is +serialization-only (`contract-types.ts:36-37`). + +## 7. Mandatory fail-closed cases + +Throw a deterministic `DB_VALIDATION_UNSUPPORTED` while constructing a schema for: unknown codec or +codec without representation-specific value schema; async-only/non-deterministic value validators if +NetScript promises synchronous validation; unknown pack entity kind; unresolved/corrupt cross-space +ref/valueSet; union branches whose runtime identity cannot be discriminated safely; model +variants/discriminators when selection/branch cannot be resolved; opaque SQL +raw/computed/subquery/aggregate/include result with no explicit shape; `selectAllIntent` that cannot +map a unique table namespace; Mongo `resultShape.kind:'unknown'` or any unknown leaf; raw Mongo +`Document`; arbitrary SQL index/check expression (not local data validation); DB-state constraints +(unique/FK/exclusion/etc.); create/update/filter/nested-write semantics absent from a registered +operation contributor; JSON values with custom semantic schemas not contributed. Never mirror Prisma +decoders’ permissive pass-through behavior. + +## 8. Can this be a StandardSchemaV1 interpreter without recreating Prisma’s type system? + +**Yes, if bounded:** implement a small internal validation IR for +scalar/valueObject/union/list/dict/null/valueSet, plus object presence/default policy and +plan-shaped projections; wrap it as `StandardSchemaV1`. Codec/pack contributors supply +representation-specific leaf schemas. This is interpretation, not source generation and not a +reimplementation of Prisma’s TS conditional types. + +**No for full Prisma parity:** create/update/filter operators, nested relation writes, polymorphic +narrowing, aggregates/computed expressions, custom codec predicates and exact projected rows live in +generated type maps/builders/phantoms, not in the runtime contract. Supporting all of them would +recreate Prisma’s operation type system. State the supported subset and fail closed outside it. + +## 9. Smallest public API + conformance matrix + +Recommended API (two methods, no public compiler/cache/generator): + +```ts +const users = db.ref('primary').model('User'); +const createSchema: StandardSchemaV1 = users.input('create', { representation: 'runtime' }); +const resultSchema: StandardSchemaV1 = users.output(planOrSelection, { representation: 'runtime' }); +``` + +Allow `representation: 'runtime' | 'json'`; do not call JSON `wire`. `output` should require a +plan/selection for selection-aware shape; optional whole-model output may be an explicit +`users.output('model', …)` form. Unsupported schema construction throws immediately. Keep +space/model lookup and contract pinning behind `db.ref()`. + +Minimum conformance matrix before claiming support: + +| Axis/case | Expected | +| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| SQL/Postgres + Mongo; each namespace and extension space | Exact coordinate resolution; duplicate names never collide | +| Primitive identity scalars | accept correct, reject wrong, null independently | +| Date, bigint, numeric, bytes, ObjectId, JSON | test runtime and JSON separately with roundtrips and malformed/canonical edge cases | +| Domain enum/valueSet/Postgres native enum | only declared encoded values; order irrelevant to validation; cross-space refs tested | +| nullable / many / dict / value object / union | nested paths and issues; reject `many+dict` (domain validation already rejects at `validate-domain.ts:273-300`) | +| create defaults / update patches | support only operations with explicit presence policy; otherwise unsupported | +| SQL direct select/returning | aliases, missing/extra fields policy, column codec/nullability; namespace qualification | +| SQL computed/subquery/include/aggregate/raw | unsupported absent explicit contributed result schema | +| Mongo fully-known nested resultShape | strict object/array/nullability/leaf enforcement | +| Mongo unknown/raw | unsupported | +| custom codec with runtime+JSON schemas | supported and representation-specific | +| custom codec without either schema | unsupported, never `unknown` | +| unique/FK/index/arbitrary DB check | documented as DB constraints, not claimed as local value validation | +| contract-space broken head/hash/ref | construction fails before validator is returned | +| cache mutation tests | invalidate on domain-only, extension-only, execution-default, codec-version, representation, selection and space changes | +| Standard Schema protocol | sync success, path-rich issues, no throws for invalid user data; construction errors only for unsupported metadata | + +## RC vs post-RC-main and stability + +**RC-tag proof above is authoritative for v8.0.0-rc.1.** The checked-in RC SQL editor schema is +visibly stale: `packages/2-sql/2-authoring/contract-ts/schemas/data-contract-sql-v1.json:71-98` +still describes flat `models` and `storage.tables`, unlike the namespaced runtime types—do not treat +that JSON Schema as authoritative. + +**Post-RC main evidence only:** object `71e2e0d` adds +`packages/2-sql/2-authoring/contract-ts/src/data-contract-json-schema.ts:10-15`, explicitly calling +generated JSON Schema lossy/advisory and ArkType authoritative; `:31-38` accepts unknown pack maps +generically because static JSON Schema cannot know contributed kinds; `:68-110` generates the editor +schema and wire-only keys from the contract schema. This fixes editor-schema drift, not model-data +validation. No post-RC change adds codec value Standard Schemas or a universal result schema. Treat +this as corroborating direction, not RC functionality. + +**Public/stability seam:** `@prisma/orm-framework/package.json:2-7,50-75` is an RC public package +exporting contract surfaces. `packages/0-shared/publish-surface/src/shells.ts:156-170,182-194` says +facades republish `@internal/contract`; `:197-203` describes family/target/runtime republishing. +That makes pinned consumption feasible without importing `@internal/*`, but the detailed +contract/AST layouts are not demonstrated stable. Pin exact Prisma version, probe +schemaVersion/target/family/contributor IDs, and isolate all Prisma decoding behind one NetScript +adapter. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md new file mode 100644 index 0000000000..9d5eddb358 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md @@ -0,0 +1,853 @@ +# Prisma 8 TypeScript-schema and oRPC transfer audit + +> Provenance: independent delegated architecture/source audit for the NetScript DB RFC, completed +> 2026-08-13. Prisma RC source inspected at `/home/codex/.local/share/Trash/files/prisma-v8-rc1`, +> detached at `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` (`v8.0.0-rc.1`, 2026-08-07), with +> current-main object `71e2e0d9ee1f306b5a11435cd1973023cb33866a` also inspected. Historical +> evolution was checked against commit `fd88abf4`, redesign PR +> [prisma-next#261](https://github.com/prisma/prisma-next/pull/261) / commit +> [`27ccefc3`](https://github.com/prisma/prisma-next/commit/27ccefc3), and legacy-removal commit +> [`e1e5ab2c`](https://github.com/prisma/prisma-next/commit/e1e5ab2c) / PR #317. NetScript oRPC +> evidence was inspected in `/home/codex/repos/netscript-db-rfc`. + +Legend: **Fact** = directly source-backed; **Inference** = architectural consequence of those facts; +**Recommendation** = proposed NetScript design. + +## 1. Executive conclusion + +**Fact:** The fluent API shown in the early architecture +material—`defineContract().target(...).model(...).column(...).primaryKey(...)...`—was real, but it +is no longer Prisma Next's authoring direction. It was replaced in April 2026 by a model-first +callback API: + +```ts +defineContract( + { extensions: { pgvector } }, + ({ field, model, rel, type }) => { + const User = model('User', { + fields: { + id: field.id.uuidv4String(), + email: field.text().unique(), + }, + }); + + return { models: { User } }; + }, +); +``` + +The redesign explicitly removed the separate table/column choreography, stringly typed cross-model +references, hard-coded helper vocabulary, and required storage-name repetition. The current API +instead uses typed model tokens, semantic fields and relations, pack-contributed helpers, and a +`.sql(...)` storage overlay. + +**Recommendation:** NetScript should adopt the current native Prisma builder as its authoring +foundation. It should not recreate the old fluent chain or introduce a parallel NetScript model DSL. +NetScript's layer should own composition, policy, contract-space ownership, extension bundles, +artifact automation, migrations, runtime lifecycle, validation, and consumer adapters while +preserving native Prisma builder values and `typeof contract` end to end. + +This is directly analogous to how NetScript already augments oRPC: it starts with the real upstream +builder, applies NetScript policy and conventions, derives types from upstream-native values, and +fans the result into other framework surfaces. + +## 2. Evolution of the Prisma API + +### Historical fluent builder + +**Fact:** Historical source at commit `fd88abf4` contained: + +- `SqlContractBuilder` +- `.target(...)` +- `.extensionPacks(...)` +- `.table(...)` +- `.model(...)` +- top-level `defineContract()` + +The associated table builder exposed `.column(...)`, `.primaryKey(...)`, `.unique(...)`, +`.index(...)`, and `.foreignKey(...)`. + +Primary historical source: + +- [`contract-builder.ts` at `fd88abf4`](https://github.com/prisma/prisma-next/blob/fd88abf4/packages/2-sql/2-authoring/contract-ts/src/contract-builder.ts) +- [`table-builder.ts` at `fd88abf4`](https://github.com/prisma/prisma-next/blob/fd88abf4/packages/1-framework/2-authoring/contract/src/table-builder.ts) + +**Fact:** [PR prisma-next#261](https://github.com/prisma/prisma-next/pull/261), merged on April 3, +2026, documents the redesign. Its “before” example shows the fluent table/model chains; its “after” +example introduces callback-scoped helpers, typed model tokens, inline semantic attributes, and +`.sql(...)`. + +The implementation landed in [`27ccefc3`](https://github.com/prisma/prisma-next/commit/27ccefc3). +The legacy implementation was subsequently removed in +[`e1e5ab2c`](https://github.com/prisma/prisma-next/commit/e1e5ab2c), associated with PR #317. + +### RC1/current authoring model + +**Fact:** ADR 181 now says “No table or column layer.” The relevant source is: + +- `docs/architecture docs/adrs/ADR 181 - Contract authoring DSL for SQL TS authoring.md:7-70` +- Same ADR at `:90-104`, `:108-151`, and `:153-183` + +The ADR's core principles are: + +- semantic model first, storage second; +- pack-driven vocabulary; +- typed local references; +- same canonical downstream contract; +- pure, deterministic canonical output. + +The exact RC1 demo is at: + +- `examples/prisma-8-demo/prisma/contract.ts:1-70` + +It demonstrates: + +- Postgres public `defineContract`; +- an extension pack, pgvector; +- `type.pgvector.Vector(1536)`; +- native enums; +- `field.id.uuidv4String()`; +- temporal presets; +- JSON and optional fields; +- literal defaults; +- typed `rel.hasMany`/`rel.belongsTo`; +- foreign-key authoring using typed column/model references; +- table mapping through `.sql(...)`. + +The Postgres-bound public overloads are at: + +- `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121` + +The callback receives exactly: + +```ts +ComposedAuthoringHelpers; +``` + +and may return native `types`, `models`, and `enums`. The Postgres wrapper delegates to the generic +`buildBoundContract`. + +### Volatility + +**Fact:** The RC release notes explicitly warn that RC respins may break, remove, or rename APIs and +the contract format. See the +[Prisma 8.0.0 RC1 release](https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1). + +**Fact:** Churn has continued after the callback redesign: + +- `extensionPacks` became `extensions`; +- current main adds check-constraint/no-check functionality absent from RC1; +- current main adds generated JSON Schema for `contract.json`; +- authoring and contract-format commits continue to land between RC1 and current main. + +**Recommendation:** The RFC should commit to the architectural direction, not freeze the exact RC1 +overload syntax. Put all Prisma-version-sensitive integration behind a very small adapter package +and pin Prisma tightly during implementation. + +## 3. Exact current builder anatomy + +### Contract definition and lowering + +**Fact:** `ContractDefinition` currently contains: + +- family and target; +- extension packs; +- naming; +- storage hash; +- foreign-key defaults; +- control policy; +- namespaces; +- types; +- models; +- codec lookup; +- enums; +- entity handles. + +Source: + +- `packages/2-sql/2-authoring/contract-ts/src/contract-builder.ts:43-82` + +`buildBoundContract` constructs the composed helper surface before invoking the callback and then +merges returned types, models, enums, and entities: + +- `contract-builder.ts:416-505` + +The callback overload preserves its returned literal types: + +- `contract-builder.ts:437-462` + +### Schema DSL + +The implementation in: + +- `packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts` + +contains: + +- naming strategies around `:30-35`; +- scalar field state around `:43-76`; +- scalar builder methods—optional, column mapping, list cardinality, literal defaults, SQL defaults, + identity, unique, SQL overlay—around `:162-434`; +- relation state/builders around `:555-700`; +- typed references, including cross-contract-space references, around `:709-757`; +- indexes, foreign keys, and referential actions around `:771-895`; +- SQL constraints around `:965-1137`; +- model attributes and SQL stages around `:1141-1184`; +- typed model builders around `:1370-1563`; +- contract input around `:1659-1738`; +- model overloads and per-model namespaces around `:1741-1796`; +- branded `extensionModel` cross-space handles around `:1813-1850`; +- relation and lazy-token handling around `:1878-2028`. + +**Fact:** The core helper surface only hard-codes `field.column`, `field.generated`, and +`field.namedType`; the richer vocabulary is composed from family, target, and extension packs: + +- `packages/2-sql/2-authoring/contract-ts/src/composed-authoring-helpers.ts:43-102` +- `:132-154` + +Packs may contribute type helpers, field helpers, entity helpers, and index types. Composition +includes collision checks: + +- `composed-authoring-helpers.ts:214-233` +- `:272-306` + +**Inference:** Prisma's own native builder is already an extensible semantic DSL. A competing +NetScript DSL would duplicate the part Prisma has specifically designed as an extension seam. + +## 4. Plugin fragments without a proprietary schema DSL + +### Feasibility + +**Fact:** The callback may return maps of native builder values: + +```ts +{ + types?: Record; + models?: Record; + enums?: Record; + entities?: readonly PackEntityHandle[]; +} +``` + +**Inference:** A NetScript plugin can contribute native Prisma model/type/enum/entity values without +translating them into a NetScript-owned AST. + +A fragment can therefore be a function receiving the exact native helper object and returning a +const-preserved native result: + +```ts +export const workersFragment = definePrismaFragment({ + id: 'workers', + ownership: 'app', + build(h) { + const Job = h.model('Job', { + fields: { + id: h.field.id.uuidv4String(), + status: h.field.text(), + }, + }); + + return { + models: { Job }, + } as const; + }, +}); +``` + +`definePrismaFragment` must be a composition/metadata facility, not a schema language. Its returned +`Job` remains Prisma's model-builder value. + +### Two-phase composition requirement + +**Fact:** Extension packs are part of the scaffold and determine the helper object's static and +runtime shape before the callback runs. + +**Inference:** Arbitrary “register an extension while executing a fragment” composition cannot be +sound. NetScript needs two phases: + +1. Collect fragment manifests: required packs, control/runtime/validation facets, target + requirements, ownership, dependencies and namespaces. +2. Build the final scaffold, obtain the fully composed native Prisma helper object, then invoke + fragments. + +### Literal-type preservation + +**Inference:** A generic `Array.reduce()` into `Record` would erase literal model +names, relation coordinates and field inference. This would repeat an existing problem visible in +NetScript CRUD contracts, where widening to oRPC's `AnySchema` required phantom markers to restore +exact types. + +**Recommendation:** Generate an app-local composition root with explicit const-preserving calls and +object spreads. Do not expose a general runtime registry whose return type is merely +`Record`. + +### Two ownership modes + +**Recommendation:** Make ownership explicit: + +```ts +ownership: 'app' | 'space'; +``` + +- `app`: the host app owns the model fragment and its migration history. The generated app contract + composes it. +- `space`: the plugin owns a complete native Prisma contract space with its own canonical artifact, + migration graph and head. + +Plugin-owned tables should normally use `space`. App-owned fragments are appropriate only when the +application deliberately owns the resulting schema and migrations. + +Prisma's contract-space ADR already defines one `contract.json`, migration graph and head per owner: + +- `docs/architecture docs/adrs/ADR 212 - Contract spaces.md:46-88` +- package and emit layout at `:90-127` +- per-space planning at `:194-228` +- artifact self-consistency at `:251-268` + +Cross-space model handles are already represented by Prisma-native branded values: + +- `packages/3-extensions/supabase/src/contract/handles.ts:1-77` + +## 5. NetScript's oRPC architecture as the direct precedent + +| Existing NetScript/oRPC pattern | Prisma-builder transfer | DB-specific addition | +| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| `baseContract = oc.errors(commonErrorMap)` uses the real oRPC builder | Start with the real public Prisma `defineContract`; apply NetScript presets around it | Persist canonical contract identity and migration ownership | +| Precise types flow from the upstream builder into `implement()` | Preserve exact `typeof contract` into ORM/query/runtime/validation | Preserve family, target, namespace, contract-space and resource identity | +| CRUD factory returns real oRPC route-builder values | Fragment factories return real Prisma model/type/enum/entity values | Fragments must be deterministic and migration-owning | +| Generated const-generic service root creates clients, queries and query utils | Generated DB root creates resources, operations, validators and framework adapters | Must also construct pools, transactions, health and disposal | +| Standard Schema is consumed structurally through `~standard` | Derived database validators implement Standard Schema V1 | Must distinguish create/update/read/wire channels and codec semantics | +| `$context()` supplies typed handler context | `createDatabase(definition, binding)` supplies typed runtime resource context | Runtime URLs, credentials, pools and transaction scopes | +| Soundness tests use compile failures and `@ts-expect-error` | Builder/fragment/namespace/operation compile-time conformance tests | Artifact, migration and provider-capability conformance | +| One source contract fans into SDK surfaces | One database definition fans into ORM, queries, validation, SSR and agents | Canonical artifact emission and migration ledger | + +Exact NetScript evidence: + +- Real upstream oRPC builder and NetScript error augmentation:\ + `packages/contracts/src/application/contract-primitives.ts:1-9`, `:55-89`, `:125-159` +- CRUD generation through real `.route().input().output()` calls:\ + `packages/contracts/crud/create-crud-contract.ts:107-145`, `:278-407` +- The type-erasure workaround that DB composition should avoid:\ + `create-crud-contract.ts:119-145` +- Structural Standard Schema contract:\ + `packages/contracts/src/domain/schema-types.ts:16-52` +- SDK inference from Standard Schema and public `~orpc` metadata:\ + `packages/sdk/src/ports/service-client.ts:7-46`, `:49-124` +- One const-generic service map fanning into three surfaces:\ + `packages/sdk/src/presets/define-services.ts:19-127` +- Generated app-local composition root:\ + `packages/cli/src/kernel/assets/workspace/contracts/v1-aggregate.ts.template:1-20` +- Real upstream builder plus typed worker context and implementation:\ + `packages/plugin-workers-core/src/contracts/v1/workers.contract-definition.ts:70-96`, `:437-573` +- Types derived from native contract values:\ + `packages/plugin-workers-core/src/contracts/v1/workers.contract-types.ts:59-89` +- Typed `$context()`:\ + `plugins/workers/services/src/routers/router-context.ts:27-61` +- Compile-time soundness tests:\ + `plugins/workers/services/src/routers/workers-contract-soundness_test.ts:11-75` +- Runtime definition/lifecycle precedent:\ + `packages/service/src/presets/define-service.ts:216-275` + +**Recommendation:** The Prisma analogue of `baseContract` is not a new model language. It is a +policy-applied native builder entry point or a native contract wrapped in a frozen NetScript +database definition. + +## 6. Candidate public APIs + +These are RFC candidates, not descriptions of existing APIs. + +### Candidate A — native contract plus NetScript database definition + +This is the recommended baseline because it minimizes coupling to unstable Prisma type internals. + +```ts +import pgvector from '@prisma/orm-extension-pgvector/pack'; +import { defineContract, rel } from '@prisma/orm-postgres/contract-builder'; +import { defineDatabase } from '@netscript/database/prisma'; + +export const contract = defineContract( + { + extensions: { pgvector }, + namespaces: ['app'], + }, + ({ field, model, type }) => { + const types = { + Embedding: type.pgvector.Vector(1536), + } as const; + + const User = model('User', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + email: field.text().unique(), + }, + }); + + const Post = model('Post', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + userId: field.uuidString(), + embedding: field.namedType(types.Embedding).optional(), + }, + }); + + return { + types, + models: { + User: User.relations({ + posts: rel.hasMany(Post, { by: 'userId' }), + }), + Post: Post.relations({ + user: rel.belongsTo(User, { from: 'userId', to: 'id' }), + }), + }, + }; + }, +); + +export const appDatabase = defineDatabase({ + id: 'app', + contract, + migrations: { space: 'app' }, + validation: { profile: 'boundaries' }, +}); +``` + +`defineDatabase` must retain `typeof contract` unchanged. It adds identity and policy; it does not +reinterpret models. + +Runtime creation remains separate: + +```ts +export const db = createDatabase(appDatabase, { + url: env.DATABASE_URL, +}); +``` + +This follows NetScript doctrine: `defineDatabase` is a frozen definition; `createDatabase` performs +environment-sensitive runtime construction. + +### Candidate B — generated native fragment composition + +```ts +export const workersSchema = definePrismaFragment({ + id: 'workers', + ownership: 'app', + extensions: [workersExtension], + build(h) { + const Job = h.model('Job', { + fields: { + id: h.field.id.uuidv4String(), + state: h.field.text(), + }, + }); + + return { models: { Job } } as const; + }, +}); +``` + +A generated app root performs explicit native composition: + +```ts +export const contract = defineContract(scaffold, (h) => { + const workers = workersSchema.build(h); + const app = appSchema.build(h, { workers }); + + return { + types: { + ...workers.types, + ...app.types, + }, + models: { + ...workers.models, + ...app.models, + }, + enums: { + ...workers.enums, + ...app.enums, + }, + } as const; +}); +``` + +The generator resolves dependencies and collisions before emitting this root. It should not use a +type-erasing registry/reduce path. + +Plugin-owned schema instead exports a full space: + +```ts +export const workersSpace = defineDatabaseSpace({ + id: 'workers', + target: 'postgres', + contract: defineContract(/* native Prisma contract */), + migrations: { + owner: '@netscript/plugin-workers', + directory: './migrations', + }, +}); +``` + +### Candidate C — policy-applied native factory + +This is the closest analogue to NetScript's `baseContract`: + +```ts +export const postgresContract = createPrismaContractFactory({ + naming: { + tables: 'snake_case', + columns: 'snake_case', + }, + defaultControlPolicy: 'managed', + extensions: [pgvector], +}); + +export const contract = postgresContract.define((h) => { + // `h` must be Prisma's exact composed helper surface. +}); +``` + +**Kill condition for Candidate C:** Reject it if implementing it requires copying Prisma's +overloads, reaching into private package paths, or re-declaring its generic model/type machinery. In +that case Candidate A is safer and still gives excellent DX. + +## 7. End-to-end type system + +Recommended flow: + +```text +native Prisma TS builder + ↓ +native typed contract value + ↓ +canonical contract + stable content hash + ↓ +NetScript database definition/resource identity + ↓ +typed ORM/query/operation definitions + ↓ +Standard Schema input / output / wire views + ↓ +oRPC · tRPC · Fresh · TanStack · forms · SSR · agents +``` + +### Operation surface + +```ts +const createUser = db.operations.User.create({ + select: { + id: true, + email: true, + }, +}); + +createUser.input; // StandardSchemaV1 +createUser.output; // selection-aware StandardSchemaV1 +createUser.wire; // JSON/SSR representation +createUser.execute; +``` + +It can be plugged directly into oRPC: + +```ts +const route = baseContract + .route({ method: 'POST', path: '/users' }) + .input(createUser.input) + .output(createUser.output); +``` + +A custom query uses the same operation abstraction: + +```ts +export const recentPosts = defineDatabaseOperation(appDatabase, { + input: schemas.recentPosts.input, + output: schemas.recentPosts.output, + query: ({ orm }, input) => + orm.post.findMany({ + where: { createdAt: { gte: input.since } }, + select: { id: true, title: true }, + }), +}); +``` + +### Runtime validation model + +**Fact:** Prisma's codec layer distinguishes input, wire and JSON representations and supplies +encode/decode functions: + +- `packages/1-framework/1-core/framework-components/src/shared/codec.ts:16-51` +- `codec-descriptor.ts:27-55` + +However, Standard Schema currently validates codec constructor parameters, not arbitrary model +values. + +**Fact:** TypeScript authoring helper arguments are not fully runtime-validated: + +- `packages/2-sql/2-authoring/contract-ts/src/authoring-type-utils.ts:32-38` +- confirmed by `packages/2-sql/9-family/test/authoring-field-presets.test.ts:68-87` + +**Fact:** The ArkType JSON extension documents that its no-emit type may be `unknown` and that +encoding does not validate the value. An invalid write can reach the database before failing on +RETURNING decode: + +- `packages/3-extensions/arktype-json/README.md:7-17`, `:40`, `:74-87` + +**Recommendation:** NetScript's Standard Schema layer must be an interpreter over the canonical +contract plus a codec-validation registry. It cannot assume that SQL native types or codec +encode/decode alone provide sound validation. + +Expose at least these separate schemas: + +- `create`: accepted mutation input, accounting for defaults and generated values; +- `update`: partial mutation semantics; +- `read`: full domain output; +- `wire`: serialized JSON/SSR representation. + +Do not collapse those into one “model schema.” + +Selection-aware query output schemas are mandatory. A full-model validator cannot validate a +projection correctly. + +Database-dependent invariants—unique constraints, foreign keys, and arbitrary SQL check +expressions—must not be advertised as synchronous local structural validation. They may be exposed +as optional asynchronous database refinements. + +For SSR: + +1. validate/encode the domain value; +2. validate the wire representation; +3. serialize; +4. validate/decode after hydration. + +For agents, expose an allowlisted operation registry with input/output schemas and policy metadata. +Do not automatically hand agents unrestricted ORM access. + +## 8. Multi-schema, multi-provider and runtime identity + +### Multi-schema gap + +**Fact:** Runtime lowering honors per-model namespaces, but RC1 type inference does not faithfully +preserve them: + +- `packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-648` notes the current namespace + limitation; +- `:658-689` places storage models into the default namespace and leaves additional namespace maps + empty; +- `:771-798` similarly constructs field type maps under the default target namespace. + +Current main still retains this limitation. + +**Inference:** NetScript cannot claim sound end-to-end multi-schema inference merely because the +runtime contract accepts namespaces. + +**Recommendation:** Make namespace type/runtime parity an upstream-blocking conformance gate. Do not +mask the problem with NetScript casts or flatten namespaces. + +### Multi-provider + +**Fact:** Prisma configuration currently describes one family/target/adapter/extension set and one +contract/migration location: + +- `packages/1-framework/1-core/config/src/config-types.ts:70-116` + +**Recommendation:** NetScript multi-database support should mean multiple explicitly named database +resources: + +```ts +defineDataPlatform({ + primary: postgresDatabase, + analytics: clickhouseDatabase, + cache: sqliteDatabase, +}); +``` + +Each resource has exactly one provider/target and independent: + +- canonical contract identity; +- runtime binding; +- pool/client lifecycle; +- migration ledger; +- provider capabilities. + +A cross-resource reference is an application-level link, not a foreign key. NetScript must not imply +cross-provider atomic transactions. + +## 9. Migration and artifact boundary + +**Fact:** The migration system is artifact-driven, not source-driven. Migration planning consumes +canonical JSON and operations artifacts, with storage hashes and per-space markers: + +- `docs/architecture docs/subsystems/7. Migration System.md:59-102` +- canonical offline diff at `:127-139` +- content-addressed snapshots and apply artifacts at `:287-318` + +**Fact:** Native no-emit runtime use is supported, but even an in-memory native contract is +serialized/deserialized before runtime use: + +- `packages/3-extensions/postgres/src/runtime/postgres.ts:96-130` +- no-emit versus emitted modes at `:150-166` + +**Fact:** Emit canonicalizes and atomically publishes artifacts: + +- `packages/1-framework/3-tooling/cli/src/control-api/operations/contract-emit.ts:134-149` +- source-provider invocation at `:198-211` +- serialization/canonicalization at `:230-271` +- atomic publication/hash at `:279-302` + +**Recommendation:** NetScript should eliminate manual emit/generate/migrate choreography, but not +erase the artifact boundary. Tooling and production migration application should consume canonical +artifacts, never execute arbitrary app/plugin TypeScript. + +The generated root/build pipeline should automatically: + +1. evaluate native schema authoring in the controlled build phase; +2. canonicalize; +3. verify deterministic hash; +4. emit contract and type artifacts atomically; +5. compare migration head; +6. generate or validate a migration; +7. attach provenance and ownership; +8. make the runtime use the exact verified artifact in CI/production. + +## 10. Extension-bundle design + +**Fact:** Prisma's current pgvector example requires the same logical extension to appear +independently in: + +- schema authoring as `/pack`; +- control/config as `/control`; +- runtime construction as `/runtime`. + +Evidence: + +- `examples/prisma-8-demo/prisma/contract.ts:1`, `:18` +- `examples/prisma-8-demo/prisma-next.config.ts:1-10` +- `examples/prisma-8-demo/src/prisma-no-emit/context.ts:1-11` + +**Recommendation:** NetScript should define one database-extension contribution bundle: + +```ts +defineDatabaseExtension({ + id: 'pgvector', + version: '...', + provider: 'postgres', + authoring: pgvectorPack, + control: pgvectorControl, + runtime: pgvectorRuntime, + validation: pgvectorValidation, +}); +``` + +The generated root fans this single declaration into all Prisma phases. NetScript must verify that +every facet has the same stable extension ID/version and compatible provider capabilities. + +This replaces today's primitive DB contribution: + +- `packages/plugin/src/config/domain/db-schema-contribution.ts:1-7` +- `packages/plugin/src/config/builders/plugin-builder.ts:192-202` +- `packages/plugin/src/config/contribution-merger.ts:3-26` + +It also removes the currently generated instructions to copy a schema and manually run +migration/generation: + +- `packages/cli/src/kernel/assets/generated/plugins/generate-plugin-db-schema-1.ts.template:1-10` + +## 11. Required invariants + +1. The native Prisma contract is the sole schema truth. NetScript has no parallel model AST. +2. `typeof contract` is preserved through database definitions and fragment composition. +3. Authoring identity, canonical contract hash, NetScript resource ID, runtime binding, and + migration space/head are distinct concepts. +4. Schema evaluation is deterministic and independent of environment, filesystem ordering, + randomness, time and network. +5. Environment access is confined to `createDatabase` and application composition. +6. Extension authoring/control/runtime/validation facets must share verified identity and version. +7. Namespace inference must match runtime namespace lowering exactly. +8. Input, output and wire validation are distinct. +9. Every codec used by a public validated operation has a sound validation facet; unsupported codecs + fail closed. +10. Query output schemas are selection-aware. +11. Plugin ownership is explicit, and model/constraint collisions report both owners. +12. Fragment order cannot alter the canonical contract hash. +13. One database definition has one provider/target. +14. Cross-database foreign keys and atomic transactions are not representable. +15. Migration apply executes immutable artifacts, not schema TypeScript. +16. Artifact publication is atomic and includes hash/provenance. +17. Unsupported provider capabilities are either statically unavailable or rejected during + definition, never deferred to a production migration. + +## 12. Anti-patterns to forbid + +- Reimplementing the obsolete screenshot fluent chain. +- A proprietary NetScript schema DSL parallel to Prisma. +- Re-exporting Prisma's builder as though NetScript owns it. +- Copying Prisma private overloads or phantom type maps into public NetScript types. +- Fragment merging through widened `Record` registries. +- Copying plugin PSL/schema files into applications. +- Requiring users to register the same extension separately for authoring, migrations and runtime. +- Executing plugin/application TS during migration apply. +- Generating a separate validation schema that can drift from the canonical contract. +- Treating TypeScript checking as runtime boundary validation. +- Validating a query projection with a full-model schema. +- Flattening namespaces to work around upstream inference bugs. +- Pretending uniqueness, foreign keys or arbitrary SQL checks are purely local validation. +- Reading environment variables or network state during schema construction. +- One mega-contract spanning unrelated providers. +- Exposing unrestricted ORM methods as an agent tool surface. + +## 13. Conformance suite + +The RFC should require at least: + +1. Direct native Postgres contract, both emitted and no-emit. +2. App fragment composition preserving literal model/field/relation types. +3. Plugin-owned contract space with independent migration head. +4. One extension declaration correctly supplying authoring/control/runtime/validation. +5. Required/optional/default/generated/nullable create and update validation. +6. Selection-aware output validation. +7. Date, bigint, decimal, bytes, JSON, enum and vector input/output/wire round trips. +8. Multiple namespaces, including duplicate model names, with exact type/runtime parity. +9. Cross-space handle and ownership validation. +10. Duplicate model/constraint contribution diagnostics naming both owners. +11. Fragment reordering yielding the same canonical hash. +12. Environment/time/random/filesystem/network access rejected during deterministic evaluation. +13. Stale or half-published contract artifacts rejected. +14. Migration apply functioning from JSON/ops artifacts only. +15. Multiple database resources remaining type-, pool- and ledger-isolated. +16. Namespace use on SQLite rejected. +17. Postgres native enum, vector, RLS, indexes and checks. +18. SSR serialization/hydration round trip. +19. The same Standard Schema value consumed by Fresh, TanStack, oRPC, tRPC and form adapters. +20. Output corruption detected at an enabled trust boundary. +21. Prisma RC upgrade contained to the integration adapter. +22. Type-check and editor latency on a 500-model representative application. +23. Agent operation allowlisting and provenance. +24. Invalid helper arguments rejected even from JavaScript/untyped/generated code. +25. Invalid custom JSON input rejected before the database write, not after commit/RETURNING. + +## 14. Kill criteria + +Stop or redesign the proposal if any of these remain true: + +- Native builder integration requires Prisma private import paths. +- The wrapper or fragment mechanism widens away Prisma's native inference. +- Multi-schema no-emit types remain wrong and NetScript can only hide the bug with casts. +- Schema evaluation cannot be made deterministic and build-phase-isolated. +- Extension facets cannot be identity/version checked. +- Canonical contract plus codec facets cannot produce sound value validators. +- Custom codecs silently become `unknown` rather than failing closed. +- Runtime and AOT validators cannot pass semantic-equivalence tests. +- Plugin migrations require arbitrary TypeScript execution during apply. +- Type-check/editor latency breaches the agreed budget. +- Migration hashes/receipts cannot bind applied migrations to exact contract artifacts. +- Prisma RC churn repeatedly leaks as public NetScript breaking changes. +- Multi-provider abstraction collapses into a lowest-common-denominator ORM surface. +- Invalid input can be committed before validation completes. +- Contract-space ordering/dependencies cannot safely represent NetScript plugin dependencies. + +The architectural stance should be: **native Prisma model-first authoring, NetScript-owned +composition and operational system**. That preserves Prisma's strongest new idea—the TypeScript +contract as the source of a complete inferred model—while putting NetScript's effort into the gaps +that actually determine framework DX: zero-manual composition, deterministic artifacts, migration +ownership, extension bundles, runtime lifecycle, validation, and all consumer surfaces. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index 48c2db6c5b..c478ada5ac 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -25,6 +25,18 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | | owner-directed final refinement | Anthropic · Fable 5 · high | Absolute final review-and-refinement gate after every other substantive gate | +## Delegated research and synthesis lanes + +| Agent path | Model / effort | Scope | Status | +| ----------------------------------- | --------------------------- | --------------------------------------------------------------- | --------- | +| `/root/market_gap_audit` | OpenAI · GPT-5.6 Sol · high | Missing delivery/control/validation comparators and market QA | Complete | +| `/root/validation_source_audit` | OpenAI · GPT-5.6 Sol · high | RC contract/result-plan proof for runtime Standard Schema | Complete | +| `/root/typescript_schema_audit` | OpenAI · GPT-5.6 Sol · high | Native TypeScript builder evolution and NetScript oRPC transfer | Complete | +| `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Reconcile all evidence into a decision-grade Plan-Gate proposal | In flight | + +These lanes are independent research/synthesis inputs. None is the formal PLAN-EVAL, IMPL-EVAL, or +owner-directed final Fable refinement. + ## Recorded lane/eval overrides - The root session is Codex rather than the default Opus 5 orchestrator. This is the active diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index bb9c086ee8..51c6dd3e0f 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -52,14 +52,16 @@ research inventory and proposed package-boundary matrix. ## Progress Log -| Time | Slice | Step | Notes | -| ---------- | ----- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | -| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | -| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | -| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | -| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | -| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, `runtime | +| Time | Slice | Step | Notes | +| ---------- | ----- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | +| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | +| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | +| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | +| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | +| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | +| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | ## Decisions From 3cbcfcec8b8af3071ae5ffba1b9cabf9c43559ec Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 19:33:49 +0200 Subject: [PATCH 05/19] docs(rfc): lock database architecture plan --- .../plan.md | 599 +++++++++-- .../research.md | 154 +-- .../research/architecture-plan-synthesis.md | 973 ++++++++++++++++++ .../research/planned-jsr-audit.md | 79 ++ .../supervisor.md | 13 +- .../worklog.md | 205 +++- 6 files changed, 1790 insertions(+), 233 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md index cf77f4020b..930cff574b 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -2,139 +2,510 @@ ## Run Metadata -| Field | Value | -| -------------- | --------------------------------------------------------------------- | -| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | -| Branch | `docs/database-architecture-rfc` | -| Phase | `research` | -| Target | `rfcs/0000-database-architecture.md` plus harness provenance | -| Archetype | Docs-only RFC describing future Archetypes 1, 2, 4, 5, and 6 surfaces | -| Scope overlays | `SCOPE-docs.md` | - -## Archetype - -The committed change is a documentation/RFC changeset, so `SCOPE-docs.md` governs its immediate -gates. The architecture it specifies spans separate future package boundaries: a small contract/IR -(A1), external database integration ports/adapters (A2), a user-facing definition DSL (A4), database -contribution packages (A5 where first-party plugins are used), and CLI/scaffold automation (A6). -Research must assign one smallest fitting archetype to each proposed package rather than forcing the -whole database system into one package shape. - -## Current Doctrine Verdict - -Pending the current database-package verdict and relevant debt-ledger scan. - -## Axioms in Play - -| Axiom | Why it matters | -| ----- | ----------------------------------------------------------------------------------------- | -| A1 | The RFC must lock the public contracts before implementation topology. | -| A2 | NetScript's durable boundary must remain simpler than Prisma internals. | -| A3 | The common database path must become one deterministic command/composition flow. | -| A5 | Provider, engine, migration, schema, validation, and observability axes must compose. | -| A7 | NetScript should wrap upstream capabilities and standards rather than rebuild an ORM. | -| A9 | Each proposed package needs an explicit doctrine archetype. | -| A10 | The app's generated composition root, not a service locator, wires database capabilities. | -| A11 | Extension axes must be named before the RFC introduces abstractions. | -| A14 | Contract tests and CI must preserve the architecture and eliminate manual drift. | +| Field | Value | +| ------------------- | -------------------------------------------------------------------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | +| Phase | `plan-eval-ready` | +| Target | `rfcs/0000-database-architecture.md` plus harness provenance; no canonical RFC before PLAN-EVAL PASS | +| Current changeset | Documentation/RFC under `SCOPE-docs.md` | +| Future architecture | A1 contract, A2 control/provider integrations, A3 runtime, A4 definition/plugin DSL, A5 thin plugins, A6 testkit/CLI | ## Goal -Produce a state-of-the-art, implementation-grade RFC for a clean-break NetScript database -architecture built for Prisma 8, while remaining deliberately capable of multiple schemas, -databases, engines, providers, deployment runtimes, and third-party contributions. +Produce an implementation-grade, clean-break database architecture RFC whose first certified +provider is Prisma 8 PostgreSQL, while NetScript owns a provider-neutral composition, contribution, +runtime-lifecycle, validation, and operations system. The experience must eliminate copied schemas, +manually synchronized types, hand-wired clients/adapters, textual generated-source repair, implicit +target selection, Aspire-coupled pure work, terminal-log contracts, and hand-maintained agent +instructions. ## Scope -- Deep current-state and historical NetScript audit. -- Deep Prisma 8/Next and source/issue/PR audit. -- Competitor/prior-art analysis. -- Complete user-facing and contributor-facing architecture. -- Pure-TypeScript schema authoring and end-to-end type propagation from definition through runtime - validation and application integration. -- Explicit breaking migration and parallel-branch rollout strategy. -- Implementation waves, contracts, test strategy, CI design, risk analysis, and acceptance gates. - -## Non-Scope - -- Production implementation of the accepted architecture in this RFC PR. -- Backward-compatible shims, aliases, dual clients, or preservation of obsolete generated assets. -- Premature selection of unverified Prisma 8 internals as stable NetScript public API. - -## Hidden Scope - -- Generator determinism and cacheability, plugin discovery, configuration provenance, secrets, - migration concurrency, destructive-change policy, transaction semantics, serverless/edge/runtime - constraints, telemetry, test databases, CI topology, version skew, supply-chain boundaries, - docs/scaffold synchronization, AI-agent discoverability, input/output trust-boundary validation, - selection-aware output shapes, codec/wire representations, and runtime/AOT equivalence. The sweep - also covers schema-as-code composition, namespace and plugin augmentation, contract identity, - type-inference ownership, migration coupling, and generated application bindings. - -## Locked Decisions - -| ID | Decision | Rationale | -| -- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| L0 | This RFC is a clean-break redesign; compatibility is not a design constraint. | Explicit owner directive; avoids encoding old foundation limits into the new layer. | -| L1 | Prisma is an implementation target behind NetScript-owned concepts, not the NetScript DB public API itself. | Preserves flexibility without pretending all database semantics are portable. | -| L2 | PLAN-EVAL is mandatory before authoring the canonical RFC. | The run is architecture-heavy, high-risk, and multi-wave. | -| L3 | Fable 5 high is the last substantive gate and may refine the document in place. | Explicit owner exception. | -| L4 | Claude Code Opus 5 high performs a fresh independent architecture deep dive before plan lock. | Owner explicitly requires orchestration and this model's workflow capabilities. | -| L5 | Grok 4.6 high performs a focused adversarial review of the complete RFC before IMPL-EVAL. | Owner-directed intelligence diversity is highest-value once all APIs are concrete. | -| L6 | Standard Schema is the durable validation boundary. The default path interprets a deliberately bounded algebra from the resolved contract at runtime; unsupported operations/codecs fail during schema construction, and any AOT form is only an equivalent optimization. | Owner/Prisma-maintainer exchange plus pinned-source proof that the RC contract omits parts of Prisma's operation type system and custom-codec value predicates. | -| L7 | Prisma's native pure-TypeScript `defineContract` builder and an end-to-end type system are primary RFC design axes. NetScript should extend the native surface using its oRPC integration as the local precedent, while the source audit decides the exact volatility boundary. | Owner directive; this preserves upstream inference and removes mirror artifacts without inventing a parallel model DSL. | +- Current-state, failure-history, doctrine/debt, Prisma RC/current-source, market, and agent-surface + evidence. +- Exact durable vocabulary, artifact taxonomy, package/archetype/dependency graph, public versus + adapter-local ownership, and refusal boundaries. +- Current model-first native Prisma TypeScript authoring, const-preserving app/plugin composition, + contract spaces, extension bundles, app-local inferred bindings, and an E2E type flow. +- Bounded contract-derived Standard Schema validation for runtime and JSON representations, + selection-aware results, codec contributions, fail-closed semantics, caching, and optional AOT + equivalence. +- Multiple explicitly named targets, same-provider isolation, namespaces with honest capability + gating, ownership policy, provider/runtime modes, and plugin lifecycle. +- Programmatic operation catalog, deterministic manifest, preview/plan/apply/verify state machines, + provider locking, receipts, partial/unknown outcomes, resume, CI determinism, and generated agent + surface. +- Clean adoption of populated databases, no-compat cutover, parallel branch/release-line strategy, + implementation waves, conformance/release gates, kill criteria, and migration documentation. +- Required doctrine and debt consequences for the future implementation program. + +## Non-Scope and Refusal Boundary + +- Production package, CLI, plugin, or provider implementation in this RFC PR. +- Any backward-compatible facade, Prisma 7 client, legacy generated module, alias barrel, dual + migration history, `setClient`, copied fragment, or runtime shim. +- A NetScript query DSL, generic repository, ORM, model language, or lowest-common-denominator + portability API. +- Recreating Prisma's obsolete target/table/column fluent builder or re-exporting Prisma as though + NetScript owns it. +- Runtime capability negotiation; capabilities are declared static data. +- Cross-database foreign keys, transparent joins, atomic transactions, or automatic rollback. +- Hosted control-plane products: RBAC, approval workflow, registries/promotion, fleet schedulers, + continuous drift agents, KMS/secrets, notifications, or permanent audit servers. +- Claims that Prisma SQLite, MongoDB, MySQL, SQL Server, multi-namespace E2E typing, plugin + archive/drop, AOT validation, or moving raw/prepared/aggregate conveniences are implemented. + +## Doctrine Verdict and Axioms + +The current `packages/database` is an A2 integration package marked Refactor. Its recorded AP-17 +`interfaces/` rename is stale because source now uses `ports/`; the composition-root question is +still relevant. `DB-GENERATE-ASPIRE-COUPLING` is open and is closed structurally when pure +operations cannot resolve Aspire. Auth roadmap R1 independently requires deterministic plugin-aware +schema/migration automation and must converge on contract spaces rather than an auth-only generator. + +Doctrine currently codifies plain `*.prisma` plugin fragments and does not register the proposed +packages in its gated denominator. The implementation program must amend +`docs/architecture/doctrine/06-archetypes.md` and `10-codebase-verdict-and-handoff.md` before new +packages land. This RFC records the target; it does not mutate doctrine before acceptance. + +| Axiom | Application | +| ----- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| A1 | Public data/types and README examples precede implementation. | +| A2 | NetScript's stable surface stays smaller than Prisma internals. | +| A3 | The common author/compose/emit/plan/apply path is one deterministic flow. | +| A5 | Targets, spaces, providers, extensions, runtime modes, and validators compose without inheritance. | +| A7 | Wrap Prisma and Standard Schema; do not rebuild an ORM or validator ecosystem. | +| A8 | Definition, runtime, control, provider, and tooling responsibilities live in separate role-named packages/folders. | +| A9 | Each future package has exactly one archetype; runtime is explicitly A3. | +| A10 | Generated application composition roots bind providers/targets; no global registry/service locator. | +| A11 | Extension axes are named as target, role, namespace, space, provider, capability, connection source, runtime scope, and validation representation. | +| A12 | Plan/apply/recovery, contribution lifecycle, and multi-target execution are explicit state machines. | +| A13 | Runtime/control crash boundaries, cancellation, unknown outcomes, and supervision are explicit. | +| A14 | Conformance, publish, generated-project, journey, and release gates preserve the design. | + +Applicable anti-patterns include AP-3 god ports, AP-4 cross-package implementation inheritance, AP-9 +premature abstraction, AP-14 upstream re-export, AP-17 stale folder/debt tracking, AP-18 giant +generated snapshots, AP-24 engine switches, and AP-25 side effects outside edges. The RFC must also +reject service-location, widened native-fragment registries, source-text repair, message-string gate +assertions, implicit fallback selection, and arbitrary schema TypeScript during production apply. + +## Locked Vocabulary and Artifact Taxonomy + +| Term | Locked meaning | +| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Pure authored TypeScript composition of targets, spaces, connection-source references, policies, and native contracts. | +| `NativeContract` | Provider-owned authored value, initially Prisma's model-first `defineContract` result. | +| `SpaceContribution` | Declarative owner/version/dependency/capability/provenance/retention record for one contract space. | +| `ContractArtifact` | Canonical provider contract data/declaration, lineage, and provenance pinned per space. | +| `DatabaseManifest` | Deterministic, versioned, content-addressed resolved snapshot; the durable join point. A graph is private compiler IR only. | +| `AppBinding` | Generated application-local inferred bridge from native contract declarations to sessions, validators, and consumers. | +| `TargetRef` / `TargetSession` | Explicit target reference and process/request lifecycle shell; concrete provider query type is app-local. | +| `SpeculativePreview` | Advisory output that cannot be approved or applied. | +| `ExecutablePlan` | Expiring plan bound to manifest, target/space closure, live baseline, provider pins, policy, environment, and secret references. | +| `ProviderMarker` / `ProviderLedger` | Provider-owned authoritative applied migration state; not duplicated as NetScript mutable state. | +| `OperationReceipt` | Immutable evidence/checkpoints, not desired state or a shadow database. | +| `OperationCatalog` | Machine names/classes/request/result/diagnostic/next-action catalog; CLI/docs/agents are projections. | +| `ValidationIR` | Internal bounded value/selection algebra producing Standard Schema values; never a second entity/query model. | + +Declared identities are `TargetId`, `RoleRef`, `NamespaceRef`, `SpaceId`, `ObjectKey`, +`ContractSnapshotId`, `ManifestDigest`, `PlanId`, `RunId`, and `ReceiptId`. Provider names, engine +names, paths, config aliases, array order, traversal order, and discovery order are never identities +or dependency edges. + +## Exact Future Package and Dependency Graph + +| Unit | Archetype | Owns | Must not own | +| ------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| `@netscript/database-contract` | A1 | Plain identities, manifests/plans/receipts/diagnostics, capabilities, ownership, shared small SPIs. | IO, query types, provider imports. | +| `@netscript/database` | A4 | `defineDatabase`, target/space/policy definitions, pure compiler/resolver, frozen definitions. | Connections, provider/Aspire imports, execution. | +| `@netscript/database-runtime` | A3 | Process/request lifecycle, binding, connection ownership, health/readiness, cancellation, validation coordination. | Migration orchestration, CLI, provider query vocabulary. | +| `@netscript/database-control` | A2 | Programmatic classify/compose/emit/preview/plan/apply/verify/inspect, provider ports, locks, receipts, recovery, cross-target saga. | Provider SQL/AST/types, terminal text, CLI rendering. | +| `@netscript/database-prisma-postgres` | A2 | Sole framework runtime/control Prisma boundary, capability descriptor, artifact/control/runtime/validation adapters, import allowlist. | Prisma re-export, private-type public surface, hand-written low-level driver. | +| `@netscript/database-testkit` | A6 | Runnable provider/space certification and machine reports if a binary is justified. | Application runtime dependency. Reconsider split before W1 if no binary exists. | +| `@netscript/plugin` | Existing A4 | Plain `defineDatabaseSpace` contribution seam and legacy-surface removal. | Provider/runtime/control dependency. | +| First-party `plugins/*` | Existing A5 | Thin descriptors and generated contract/lineage assets sourced from `-core`. | Copied app schema or convention-bearing DB implementation. | +| `@netscript/aspire` | Existing A2 | Narrow connection-source/provisioning adapter. | Requirement for pure/non-Aspire operations. | +| `@netscript/cli` | Existing A6 | Operation-catalog projection, adoption codemod, generated help/agent assets. | Database/provider business logic. | + +Dependency law: + +```text +@netscript/database-contract + <- @netscript/database + <- @netscript/database-runtime + <- @netscript/database-control + <- @netscript/plugin + +chosen provider implements runtime/control SPIs and is supplied by the app composition root +@netscript/database-testkit may depend on all public SPIs; no runtime package depends on it +application/plugin controlled-build schema modules may import Prisma's public authoring builder +``` + +No framework package re-exports Prisma. Runtime/control Prisma imports exist only inside the +PostgreSQL adapter. App/plugin native authoring imports are controlled build inputs; deployments use +their plain canonical artifacts. + +## Public Surfaces, Ports, and Closed Vocabularies + +### Public surfaces + +- Candidate A is the baseline: native current model-first Prisma `defineContract`, then thin + `defineDatabase({ contract, ... })` or `defineDatabaseSpace({ contract, ... })` preserving + `typeof contract` unchanged. +- An optional policy factory exists only if it forwards exact native helpers without private + imports, copied overloads, or inference widening; otherwise it is killed. +- `ownership: app` fragments return const-preserved native builder values and are composed by an + explicit generated root. `ownership: space` contributions own a full contract artifact and + migration head; this is the default for plugin-owned tables. +- One identity/version-checked `DatabaseExtension` bundle fans authoring, control, runtime, and + validation facets through two-phase collection. +- `TargetRef`/session handles expose lifecycle and a narrow query generic. Application-owned stores + receive concrete sessions at composition roots; NetScript does not generate repositories. +- Standard Schema is public. Schema classes are model value, explicitly contributed operation input, + and fully known selection/result. Public representations are `runtime` and `json`. +- Control requests/results/plans/receipts/diagnostics are plain NetScript data. Human CLI text is + never a contract. + +### Consumed ports + +Each port stays at three or four cohesive methods and has at least two exercised implementations or +a concrete external seam: + +- `ContractArtifactSource` / atomic artifact publisher for controlled native evaluation and pinned + mirrors. +- `ProviderRuntimeFactory` for scope-correct sessions and lifecycle. +- `ProviderControl` for emit/inspect/plan/apply/verify translation. +- `ConnectionSource` for environment/Aspire/secret-reference resolution. +- `MigrationLock`/provider lock capability with owner/nonce/fencing evidence. +- `ReceiptSink` for atomic immutable checkpoint evidence. +- `Clock`/ID/signature policy only where deterministic testing or production approval requires it. + +Provider registries are immutable composition-root values, not public global registries. Concrete +Prisma control/runtime/contract/codec/AST shapes stay adapter-local. + +### Closed vocabularies + +- Ownership: `managed`, `adopted`, `external`, `ignored`. +- Runtime scope: `process`, `request`. +- Validation representation: `runtime`, `json`; driver wire is internal. +- Operation class: `pure`, `live-read`, `mutating`, `resident`. +- Plan status: speculative, inspected, planned, policy-refused/allowed, approved, ready, expired, + stale, revoked. +- Receipt phases/outcomes: planned, acquiring-lock, locked, revalidating, started, applying, + applied, verifying, verified, succeeded, refused, skipped, failed, partial-success, + cleanup-required, outcome-unknown, cancelled. +- Ownership/removal initial guarantee: detach-and-retain; archive/drop are capability-conditional. +- Capabilities are open namespaced IDs but static declared data; no runtime negotiation protocol. + +## Locked Decision Ledger + +| ID | Decision | Status | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | +| D-01 | Clean break; no backward-compatibility API/runtime surface. | Locked | +| D-02 | Data continuity and mechanical migration are mandatory. | Locked | +| D-03 | Durable join point is `DatabaseManifest`; live graph is private compiler IR. | Locked | +| D-04 | Definition, manifest, executable plan, provider ledger, and receipt remain separate values. | Locked | +| D-05 | NetScript defines no query DSL, repository, or portable client facade. | Locked | +| D-06 | Current native model-first Prisma TypeScript authoring is primary; obsolete fluent chaining is not recreated. | Locked; import spelling adapter-pinned | +| D-07 | Candidate A native contract plus thin definition is baseline; optional factory dies on private imports/overload copying/type widening. | Locked | +| D-08 | App-specific inferred binding is generated app-local, never a kernel package export. | Locked | +| D-09 | Package/archetype graph above is exact; runtime is A3. | Locked | +| D-10 | Kernel is provider-neutral; first certified adapter is Prisma 8 PostgreSQL only. | Locked | +| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | Locked | +| D-12 | Capabilities are static tags/requirements, never runtime negotiation. | Locked | +| D-13 | Provider registry is composition-root data, never global/public mutable state. | Locked | +| D-14 | Stable target ID owns connection, output, runtime, migrations, locks, and receipts. | Locked | +| D-15 | Target selection is explicit, dependency-closed, and records every omission/reason. | Locked | +| D-16 | Replicas are roles of a target, never migration targets. | Locked | +| D-17 | Provider-native contract spaces plus NetScript policy replace copied fragments. | Locked | +| D-18 | One managed owner per `ObjectKey`; augmentation requires owner grant. | Locked | +| D-19 | Pinned mirrors make apply/verify independent of installed plugin code. | Locked | +| D-20 | Detach-and-retain is guaranteed removal; archive/drop are conditional. | Locked | +| D-21 | Standard Schema is public; bounded runtime interpretation is default. | Locked | +| D-22 | Public validation representations are `runtime` and `json`; driver wire is internal. | Locked | +| D-23 | Complete Prisma operation validation is not contract-derived; exact operation contributors are required. | Locked | +| D-24 | Unknown validation metadata fails while constructing the schema. | Locked | +| D-25 | Optional AOT validation is corpus-equivalent only and never required. | Locked | +| D-26 | Pure operations cannot resolve connections, Aspire, Docker, or network. | Locked | +| D-27 | Programmatic operation catalog is primary; CLI/docs/agents are generated projections. | Locked | +| D-28 | Preview is not executable plan; apply accepts only bound/revalidated plans. | Locked | +| D-29 | NetScript owns policy/lock/recovery/receipts/cross-target saga; provider owns diff/lineage/marker mechanics. | Locked | +| D-30 | Cross-target apply is never atomic; partial and unknown outcomes are first-class. | Locked | +| D-31 | Local kernel does not rebuild hosted registry/RBAC/fleet/drift products. | Locked | +| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | Locked | +| D-33 | Agent instructions/catalogs are generated and every example executes. | Locked | +| D-34 | Existing MySQL/MSSQL/SQLite support is not carried through compatibility code. | Locked | +| D-35 | Production plans require signatures; mechanism/key custody is selected before production cutover. | Pre-implementation W5/W10 | +| D-36 | Model-first callback, Candidate A, two-phase collection, const-preserving root, and no-re-export rule define builder strategy. | Locked; exact RC/GA path W3 | +| D-37 | Multi-namespace adapter capability is withheld while Prisma type maps flatten runtime namespaces; no cast workaround. | Conditional upstream block | +| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin tables default to full space ownership. | Locked | +| D-39 | One extension bundle supplies identity-matched authoring/control/runtime/validation facets. | Locked | +| D-40 | CI/production migration and runtime consume canonical verified artifacts, not arbitrary schema TypeScript. | Locked | +| D-41 | Exact Prisma control/runtime import allowlist and compatibility window are selected in W3. | Pre-implementation W3 | +| D-42 | Native advisory versus fenced-row lock is certified per provider. | Pre-implementation provider detail | +| D-43 | Whether AOT validation ships is safe to defer. | Deferred | +| D-44 | A real second provider is safe to defer. | Deferred | +| D-45 | Public raw/prepared/aggregate conveniences are safe to defer/keep adapter-local. | Deferred | +| D-46 | Archive/drop plugin retirement in v1 is safe to defer. | Deferred | +| D-47 | Remote approval/registry/continuous-drift integrations are safe to defer. | Deferred | + +No must-resolve-now decision remains. Pre-implementation items have stable public semantics and +cannot force a package-boundary rewrite. D-37 withholds a capability claim rather than blocking the +provider-neutral architecture. + +## Control and Contribution State Machines + +- Composition: authored → resolving → resolved(manifest, warnings) or refused(diagnostics), as a + pure total `Result`. +- Planning: resolved → speculative preview or baseline inspection → executable plan → policy → + approval/signature → ready, with expired/stale/revoked refusal branches. +- Apply: planned → lock → revalidate → start → checkpoint each irreversible step/group → applied → + verify → succeeded; refusal, skip, failure, partial-success, cleanup-required, cancellation, and + outcome-unknown are explicit. +- Resume always inspects live state/provider ledger and revalidates bindings before action; it never + blindly replays unknown non-idempotent work. +- Multi-target execution is a dependency-ordered saga with separate runners/locks and complete + per-target/per-space outcomes. +- Contribution lifecycle: install, upgrade, skew refusal, detach, retain, conditional archive/drop. + App-owned fragments compose into the app space; plugin-owned tables default to full spaces with + independent artifacts/heads. Extension facets install as one identity/version-checked bundle. + +## Runtime Validation Boundary + +The internal supported algebra is registered scalar codecs, nullability, lists, dictionaries, value +objects, resolvable unions, value sets/enums/native enums, integrity-checked cross-space relations, +whole-model values with explicit presence policy, and direct-column result projections with complete +alias/codec/nullability/representation metadata. + +Construction fails with stable `DB_VALIDATION_UNSUPPORTED` coordinates for unknown/missing codec +schemas, pack kinds, cross-space refs/heads, ambiguous unions/variants, missing Prisma operation +grammar, computed/subquery/raw/aggregate/include/unknown results, opaque checks, database-state +constraints, and incompatible async predicates. Invalid values return Standard Schema issues; they +do not throw. Cache identity includes canonical full-contract digest, schema version, space, +target/family, normalized operation/selection, representation, interpreter ABI, codec/pack +identity/version, and execution identity when defaults matter. + +## Provider and Target Matrix + +| Case | Architecture | First adapter claim | +| -------------------------------------- | -------------------------------------------------------------------- | --------------------------------------------------------- | +| Two PostgreSQL databases | Named targets with isolated artifacts/runtime/ledger/locks/receipts. | Required. | +| Multiple PostgreSQL namespaces | First-class kernel axis. | Withheld until no-cast Prisma type/runtime parity passes. | +| Writer/read replicas | Roles on one target. | Conditional runtime capability; readers cannot migrate. | +| App plus plugin spaces | Independent ownership/artifacts/heads/dependency order. | Required. | +| Managed/adopted/external/ignored | Ownership-aware plan/verify/drift. | Required. | +| Process/request scope | Distinct lifecycle/capability types. | Required. | +| Prisma SQLite/MongoDB/MySQL/SQL Server | Provider/family axis remains open. | Explicitly unsupported/deferred; no fallback. | +| Cross-target relation/transaction | Not representable. | Structured composition refusal. | +| Provider-specific queries | Native app-local provider surface. | No portable wrapper. | + +## Clean Cutover + +`netscript db adopt` is a temporary codemod/tool, not compatibility. It reads legacy config/layout, +generates explicit target definitions from config keys, introspects reachable databases, proposes +object ownership, hard-stops on unattributed objects, compiles/emits canonical artifacts, writes +baseline marker metadata only, verifies zero drift, and then deletes the old engine workspaces, 30 +tasks, copied fragments, repair scripts, adapters, and dependencies. Baseline establishment performs +zero table/data DDL/DML. + +Old/new stacks may coexist on separate branches/release lines while features are developed, but one +application never composes both. Before first new apply, rollback is repository-only plus idempotent +marker cleanup where supported. After apply, recovery is forward via lineage and receipts. + +## Implementation Waves + +| Wave | Scope | Dependency | Exit evidence | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------------------------ | +| W0 | Accepted RFC, doctrine/verdict amendments planned, package/gate registration. | — | RFC gates and architecture acceptance. | +| W1 | A1 contract kernel. | W0 | Zero-provider-dependency publish/doc/consumer gates. | +| W2 | A4 definition/compiler and manifest invariants. | W1 | Pure deterministic property/negative tests; no IO. | +| W3 | Experimental Prisma PostgreSQL spike: native builder, artifacts, control/runtime, spaces, extensions, validation decoder, Deno, namespace check. | W1–W2 | Real PostgreSQL, packed Deno, import allowlist, kill/switch review. | +| W4 | A3 runtime and Aspire connection adapter. | W1–W3 | Lifecycle/leak/cancellation/scope/validation gates. | +| W5 | A2 control, plans, locks, receipts, recovery, cross-target saga. | W1–W4 | Failure injection, atomic emit, pure path without Aspire. | +| W6 | A6 provider/space conformance testkit. | W1–W5 | Intentionally broken fixtures fail; real-service machine report. | +| W7 | `@netscript/plugin` contribution seam and first plugin-core fixture. | W1–W6 | Breaking surface and thinness/seam/package-free gates. | +| W8 | CLI/agent/adoption projection. | W2, W5–W7 | Generated examples/catalog freshness, populated adoption preflight. | +| W9 | First-party auth/workers/sagas/triggers spaces. | W7–W8 | Each space certified; package-free apply/verify and runtime parity. | +| W10 | Clean cutover and legacy deletion. | W1–W9 | Full release class, Windows/Linux, production-shaped adoption, remote published E2E. | +| W11 | Second real provider only when demanded/mature. | W10 | Same provider conformance; no kernel/manifest public rewrite. | + +## RFC Commit Slices + +| # | Slice and proof | Gate | Files | +| - | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| 0 | Harness bootstrap and draft review surface. | Artifact presence, scoped format/diff; already landed. | Run root artifacts. | +| 1 | Current research corpus and Plan-Gate lock are complete. | Research/source/claim index, planned JSR audit, scoped format/diff, PLAN-EVAL input completeness. | `research.md`, `research/*.md`, `plan.md`, `worklog.md`, `context-pack.md`, `drift.md`. | +| 2 | Independent PLAN-EVAL accepts the locked plan before RFC authorship. | Fresh separate-session evaluator `PASS`. | `plan-eval.md`, planning artifacts only. | +| 3 | Canonical RFC defines vocabulary, APIs, package graph, TypeScript/E2E types, validation, control, contributions, providers, and refusal boundary. | Source alignment, local-link/terminology/docs format, decision coverage. | `rfcs/0000-database-architecture.md`, run context/worklog. | +| 4 | RFC completes adoption/cutover, implementation waves, exhaustive conformance/release matrix, market implications, risks, and kill/switch criteria. | Requirement/decision trace, migration safety, claim/source audit, docs gates. | Same RFC plus run context/worklog. | +| 5 | Independent Qwen/Grok/adversarial findings are resolved with no open critical/high issue. | Qwen review disposition; Grok 4.6 high observable route receipt; source audit. | RFC plus review/run artifacts. | +| 6 | Separate-session IMPL-EVAL accepts the complete RFC. | Evaluator `PASS`; no self-certification. | `evaluate.md`, RFC/run artifacts. | +| 7 | Owner-directed Fable 5 high performs the absolute final substantive refinement; publish the final review state. | Fable refinement, docs static checks only afterward, commit/push/PR trail. | RFC and final run/handoff artifacts. | + +There are eight ordered slices, below the Plan-Gate limit. The canonical RFC does not exist before +Slice 2 passes. Fable 5 high is the last substantive model gate; only mechanical static verification +may follow. + +## Gate Set + +### Plan and research gates + +- Run-root `research.md` current-main rebaseline and complete report/source index. +- Every load-bearing numeric/factual claim is pinned to NetScript baseline, Prisma RC tag, post-RC + object, or official primary source; corrected claims are not copied from independent reports. +- Locked D-01–D-47, no must-resolve-now item, ordered slices, risks, gates, deferred scope, doctrine + implications, and implementation waves. +- Separate-session PLAN-EVAL using the harness plan protocol; hard stop until `PASS`. + +### Current docs/RFC gates + +- `SCOPE-docs.md`: source alignment, current/target scope separation, local-link/path integrity, + doctrine/glossary terminology, and drift recording. +- Targeted `deno fmt --check` and `git diff --check` for run/RFC Markdown. +- Claim/source ledger, contradiction scan, decision-to-section trace, migration-safety trace, and + generated/local example syntax review. +- Canonical RFC template/process/front matter and implementation-grade API/state-machine/matrix + coverage. +- No production package/runtime gate is claimed by a docs-only RFC. + +### Future archetype and source gates + +- Per future unit, required F-1…F-19 by the archetype matrix; A3 has required runtime gates, A5 + required plugin/runtime parity, A6 applicable F-CLI family. +- Scoped check/lint/fmt, `quality:scan`, `arch:check`, public surface/subpath audit, naming/folder/ + layering/inheritance/upstream-re-export/permission/test-shape gates. +- Provider import allowlist, exact single Prisma component set, Deno import purity, no toolchain in + runtime graphs, real PostgreSQL, lifecycle/leak/cancellation/transaction/error/redaction gates. +- Deterministic/atomic emission, stale digest refusal, canonical-artifact-only migration, target/ + namespace/space isolation, locks, crash/unknown/resume, ownership/removal, and negative diagnostic + matrices. +- App fragment literal-type preservation, extension-bundle facet identity, namespace type/runtime + parity, 500-model editor/type-check budget, and no private/cast workaround. +- Standard Schema runtime/JSON corpus, two independent consumers, selection-aware outputs, + fail-closed unsupported cases, contract-space aggregation, and optional AOT equivalence. +- Generated project journeys, agent/help catalog freshness, executable examples, and full + `scaffold.runtime` when DB/scaffold/Aspire/plugin wiring changes. + +### Prospective JSR gates + +The planned JSR audit verdict is **PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS**. The six new +packages do not exist, so `deno publish --dry-run`, `deno doc --lint`, publish-file inspection, and +packed/remote install are **N/A now**, never recorded as PASS. + +At implementation each unit requires: scoped manifest metadata/license/description, explicit export +map and include whitelist, test/fixture exclusions, `@module` docs and runnable examples, 100% +stable symbol docs target, explicit public declarations, relative same-package imports, ESM/Deno +purity, no HTTP/CommonJS/top-level filesystem assumptions, generated-asset freshness, +`deno doc --lint` zero diagnostics, `deno publish --dry-run` without `--allow-slow-types`, inspected +publish list, public import tests, clean packed consumer install, `quality:scan`, and `arch:check`. + +Publishable generated assets are checked-in deterministic TypeScript constants unless an +authenticated registry canary proves JSON/import-attribute limitations resolved. W10 additionally +requires release preflight, GitHub OIDC/SLSA provenance, authenticated canary, registry settings +reconciliation, and production `e2e-cli-prod` against exact published JSR versions. Local dry-run or +packed install cannot substitute for the remote-graph verdict. + +### Review/evaluator order + +1. PLAN-EVAL: fresh Fable 5 medium separate session, `PASS` before RFC. +2. Root/source/doctrine audit during drafting; no generator self-certification. +3. Independent Qwen findings disposition and Grok 4.6 high adversarial complete-RFC review. +4. IMPL-EVAL: fresh separate evaluator session. +5. Fable 5 high final in-place refinement as the absolute last substantive gate. +6. Mechanical format/link/diff checks, commit/push, and PR handoff only. -## Open-Decision Sweep +## Risk Register -All architecture decisions remain `must resolve now` until research closes them. The completed plan -will enumerate each one individually before PLAN-EVAL. +| Risk | Mitigation / kill response | +| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | +| Designing to RC marketing or stale builder screenshots | Pin source; current model-first API; keep exact paths adapter-local; W3 spike. | +| Upstream changes during RFC/implementation | RC/current split, exact provider pin/allowlist, independent provider release, compatibility-window gate. | +| Replacing glue with a second ORM/control plane | No query/model DSL, no runtime negotiation, no hosted services, small SPIs and refusal boundary. | +| Published slow types or Prisma leakage | App-local inference; no re-export/private imports; isolated declarations; no slow-types waiver; prospective JSR gates. | +| Native fragment composition widens inference | Two-phase explicit const-preserving generated root; compile-failure soundness fixtures and editor budget. | +| False multi-schema claim | Withhold capability until Prisma type/runtime parity passes without casts. | +| Contract-derived validation overclaims full operations | Bounded algebra, explicit contributors, runtime/JSON split, fail at schema construction. | +| Custom codec accepts invalid values | Mandatory representation-specific value schemas; encode/decode is not validation. | +| Stale or half-published artifacts | Full canonical digest, atomic publish, facet identity, runtime/apply mismatch refusal. | +| Plugin removal destroys data | Retain default; archive/drop conditional destructive plan; no directory-delete semantics. | +| Provider spaces mistaken for complete portability | PostgreSQL-only certification; explicit unsupported targets; native capability surface. | +| Apply success/exit code masks partial work | Typed per-target/space outcomes, immutable checkpoints, `outcome-unknown`, inspect-before-resume. | +| Cross-target atomicity/rollback implied | Saga language only; no global transaction; complete partial-success receipt. | +| Mutable receipts become shadow state | Provider ledger remains authority; receipts are append-only evidence. | +| No-compat cutover causes data loss | Ownership preflight, marker-only adoption, zero-DDL rehearsal, forward recovery, parallel release line only. | +| JSR plan mistaken for actual readiness | Explicit N/A now; per-package dry-run/docs/packed/canary/remote E2E receipts required later. | +| RFC breadth becomes unimplementable | Exact packages, W0–W11 dependencies, per-wave exits, kill/switch criteria. | +| Agent/docs drift | Generate from operation catalog/manifest and execute every example. | +| CI remains long/flaky | Pure/offline paths, digest caching, real-service gates only at bounded stages, atomic structured receipts. | + +## Kill and Switch Criteria + +Do not publish/switch to Prisma 8 if Deno requires vendoring/text patching; public packages cannot +pass without slow types/private imports; native inference widens; controlled authoring is +non-deterministic; canonical emit is non-atomic; control cannot produce structured bound plans and +results; marker/ledger advancement is unsafe; contract spaces cannot prove disjoint/package-free +operation; real PostgreSQL lifecycle fails; or upstream contract churn lacks a migration path. + +Narrow validation rather than rebuild Prisma types; retain runtime interpretation if AOT equivalence +fails; delete capability abstractions that grow into queries; ship detach-and-retain if destructive +removal cannot be certified; defer a generic SPI change until a second real provider needs it. +Reopen the architecture only if a deterministic manifest depends on live state, app inference +necessarily becomes published slow types, target identity cannot remain provider-independent, or +ownership/ history cannot remain separate from query/runtime types. -## Risk Register +## Open-Decision Sweep -| Risk | Mitigation | -| ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | -| Designing against RC marketing rather than implementation reality | Verify official docs against source, tests, release diffs, and live issues/PRs. | -| Replacing manual glue with a larger proprietary abstraction | Keep NetScript IR/ports minimal, capability-oriented, and conformance-tested. | -| False portability across engines | Model capabilities and explicit escape hatches; never normalize away real provider semantics. | -| Runtime validation silently overclaims contract completeness | Publish a bounded algebra, require representation-specific codec schemas, and fail closed wherever operation/result metadata is insufficient. | -| RFC too broad to implement | Define strict package boundaries, dependency graph, staged waves, and per-wave acceptance gates. | -| No-compat break becomes an unsafe migration | Supply a mechanical migration tool/doc, preflight report, data-preserving sequence, and rollback boundaries without runtime shims. | +### Must resolve now -## Anti-Patterns to Resolve or Avoid +None. -Pending current-state and doctrine audit. +### Must resolve before implementation wave -## Fitness Gates +- W1: canonical manifest/digest encoding and public format-version evolution. +- W3: exact Prisma pin/import allowlist/public builder subpath, runtime/Deno matrix, extension facet + mappings, namespace capability result, and experimental publication status. +- W4: concrete request/process scope and transaction capability shapes. +- W5/W10: signature format/key custody, provider lock implementation, receipt storage/retention, and + crash-fault harness. +- W7: initial augmentation grant vocabulary and executable contribution phase allowlist. +- W10: migration window, parallel legacy branch end date, rollback/runbook, remote release evidence. -Pending archetype assignment and Plan-Gate completion. +These are mechanism/version/release decisions behind locked public semantics and cannot force a +package-boundary rewrite. -## Arch-Debt Implications +### Safe to defer -Pending targeted scan of `.llm/harness/debt/arch-debt.md`. +Second provider; Prisma SQLite/MongoDB/MySQL/SQL Server; runtime capability negotiation; AOT +validation; archive/drop removal; public raw/prepared/aggregate conveniences; hosted control-plane +services; cross-database relation/transaction support (explicitly unsupported rather than parity +debt). -## Validation Plan +## Deferred Implementation Scope -| Order | Gate | Command or check | Expected result | -| ----- | ---------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- | -| 1 | Research provenance | Source/link inventory and claim ledger | Every load-bearing claim is traceable and current. | -| 2 | Independent architecture deep dive | Fresh native Claude Code Opus 5 high | Decision-grade report incorporated before plan lock. | -| 3 | PLAN-EVAL | Fresh Fable 5 medium opposite-family session | `PASS` before RFC authoring. | -| 4 | RFC source alignment | Local paths, `deno doc`, focused code inspection, upstream primary sources | No unsupported present-state or proposed-surface claim. | -| 5 | Docs gates | Formatting, local links/paths, terminology, contradiction scan | PASS. | -| 6 | Independent architecture review | Qwen 3.8 Max | No unresolved critical/high finding. | -| 7 | Adversarial architecture review | OpenCode/OpenRouter Grok 4.6 high with observable route receipt | No unresolved critical/high finding. | -| 8 | IMPL-EVAL | Fresh opposite-family evaluator | `PASS`. | -| 9 | Final refinement | Fable 5 high | Final in-place refinement; no substantive gate follows. | +All W1–W11 production code, doctrine mutation, package publication, provider certification, plugin +migration, legacy deletion, release-line operation, and hosted integrations are deferred to +post-acceptance implementation programs. This RFC must specify them precisely but does not claim +their gates have run. -## Dependencies +## Dependencies and Drift Watch -- Current NetScript `main`, issue/PR history, doctrine, and RFC process. -- Official Prisma release/docs/source/issues/PRs and supported database/runtime matrix. -- Existing native Claude/Fable agentic route and phase-bound Qwen evaluator route. +- Current NetScript baseline, issue/PR history, doctrine, debt, RFC process, and harness protocols. +- Prisma RC1/pinned current source, official release/ADRs/scorecard/issues/PRs, plus a fresh pin + check during RFC drafting and W3. +- Standard Schema and current NetScript oRPC/Fresh/plugin composition precedents. +- Drift watch: Prisma RC/API/contract changes; namespace typing; moving control/runtime paths; + NetScript DB changes merged to main; model route identity; any compatibility or hosted-control- + plane creep; any package surface requiring slow types. -## Drift Watch +## Plan-Gate Readiness -- Prisma 8 RC releases or API changes during the run. -- New NetScript database changes merged to `main`. -- Any model route that reports a different identity or cannot attach observably. -- Any architecture decision that would implicitly recreate backward compatibility. +- Research is current and indexed in `research.md`. +- D-01–D-47 are locked/classified; no must-resolve-now decision remains. +- Eight ordered RFC slices name proof/gates/files. +- Risk, deferred scope, doctrine/debt, future package/JSR/source/consumer gates, and waves are + explicit. +- Prospective JSR audit is applied honestly as planning evidence, with actual dry runs N/A. +- The next action is a fresh separate-session PLAN-EVAL. Canonical RFC authorship remains blocked + until `PASS`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md index 52ed54897a..59011d275a 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md @@ -1,74 +1,104 @@ -# Research — docs-database-architecture-rfc--prisma-8-rfc +# Research Index: NetScript Database Architecture and Prisma 8 -## Re-baseline +## Rebaseline and evidence policy -- Carried-in sources: GitHub issue #313, its linked Prisma Next v0.14-era design assumptions, and - related NetScript database issues discovered during research. -- Re-derived against `main` @ `cd720529333328bcba5e1a308ce7632f4350efdf` on 2026-08-13. -- Upstream target: Prisma 8.0.0 RC / Prisma Next, beginning with the official `v8.0.0-rc.1` release - and then current source, PRs, issues, and official documentation. -- What changed versus the carried-in version: - - #313 mandates an additive, backward-compatible Postgres pilot beside classic Prisma. - - The owner now mandates a clean architectural break with **no backward-compatibility - constraint**. #313 is evidence and problem inventory, not an inherited solution. - - Prisma Next has advanced from the v0.14 Early Access surface recorded in #313 to the Prisma 8 - release-candidate line, so every upstream capability and gap must be re-verified. +- Repository: `rickylabs/netscript` +- Current-main baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` +- Research date: 2026-08-13 +- Upstream Prisma pins: RC1 tag `v8.0.0-rc.1@a76a6c5`; post-RC comparison object + `71e2e0d9ee1f306b5a11435cd1973023cb33866a` +- Carried issue: #313 is rebaselined as historical problem evidence only. Its compatibility-first + solution is superseded by the owner's explicit clean-break directive. -## Research workstreams +Evidence classes used by the reports: -1. Current NetScript database topology, generated assets, public APIs, adapters, CLI flows, CI, - runtime scaffolds, and contributor extension seams. -2. Complete issue/PR history for #313 and the “Prisma Gaps” family, including later DB regressions - and architectural debt. -3. Prisma 8 / Prisma Next release, docs, source tree, packages, generators, schema/migration engine, - adapters, drivers, multi-schema/multi-database behavior, extension model, Deno compatibility, CI, - open PRs/issues, roadmap signals, and agent-facing surfaces. -4. Market prior art: batteries-included meta-frameworks, ORM/toolkit ecosystems, database-agnostic - frameworks, code-first/schema-first systems, migration systems, local-first/data layers, and - plugin contribution models. -5. Fresh NetScript architecture: contracts, ports, adapters, DSL/factories, plugin contributions, - capability negotiation, schema ownership, engine selection, deterministic generation, - zero-manual-step automation, observability, testing, CI, migration, and parallel-branch rollout. +- **Current source fact:** directly inspected NetScript baseline or pinned Prisma source. +- **Primary external fact:** official source, release, ADR, issue, PR, or product documentation. +- **Exploratory evidence:** the owner/Prisma-maintainer exchange; directional, not an upstream + commitment. +- **Inference:** reconciliation of facts; not presented as an implemented capability. +- **Proposal:** future architecture to be gated by the RFC and conformance suite. +- **Conditional/unproven:** provider or release capability withheld until implementation evidence. -## Findings +The detailed synthesis is +[research/architecture-plan-synthesis.md](./research/architecture-plan-synthesis.md). This index is +the harness-required current research entrypoint; it does not duplicate the reports. -| # | Finding | How to verify | -| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | -| 1 | #313's compatibility-first premise conflicts with the current owner directive. | GitHub issue #313 body; current run prompt | -| 2 | This is decision-heavy, cross-package, multi-wave architecture work; PLAN-EVAL is mandatory. | `.llm/harness/workflow/run-loop.md` §4 | -| 3 | The canonical deliverable is a draft RFC under `rfcs/0000-*.md`; run artifacts preserve provenance but do not become the accepted design record. | `rfcs/README.md` | -| 4 | NetScript currently has five overlapping database systems rather than one source of truth; same-engine targets collide at `database/`. | [current-state audit](./research/netscript-current-state.md) | -| 5 | Prisma 8 replaces generated executable clients with a canonical contract plus runtime/control planes, but RC1 is Early Access and PostgreSQL is its only intended 8.0 GA target. | [Prisma deep dive](./research/prisma-8-deep-dive.md) | -| 6 | Prisma's programmatic control seam is strengthening while its CLI/config packaging changed materially within six days after RC1. | [Prisma deep dive](./research/prisma-8-deep-dive.md#six-days-of-post-rc-churn) | -| 7 | Market leaders solve individual parts—contract ownership, named connections, adapter factories, migration graphs, or policy—but no comparator composes all of them into a typed meta-framework database layer. | [market analysis](./research/market-analysis.md) | -| 8 | The owner requires orchestration-first execution; a native Claude Code Opus 5 high lane now independently challenges the research and designs the architecture before plan lock. | [architecture briefing](./briefs/claude-opus-architecture.md) | +## Load-bearing rebaseline findings -## jsr-audit surface scan (package/plugin waves) +1. NetScript currently has five overlapping database systems with no canonical join point: + appsettings/Aspire resources, a fixed CLI operation runner, generated engine workspaces, runtime + wrappers, and install-time plugin schema copying. +2. Target identity collapses into provider/engine paths. Two same-provider databases share + `database/`; operation target resolution ignores `PrimaryDatabase`; pure generation is + Aspire-coupled; the generated workspace has exactly 30 `db:*` tasks. +3. Plugin schema is inferred from files and regex collisions rather than versioned ownership, + capability, migration history, provenance, or retention policy. +4. Prisma 8 is an architectural change: canonical contract data and declaration artifacts, + programmatic control, provider runtimes, migration graphs/markers/ledgers, and contract spaces. + RC1 is Early Access and PostgreSQL is the sole intended 8.0 GA database. +5. The current Prisma TypeScript authoring API is model-first `defineContract(scaffold, callback)`. + The screenshot's older target/table/column fluent API was real but was replaced and removed. +6. Prisma's canonical contract can support a bounded runtime Standard Schema interpreter, but it + does not retain the complete create/update/filter/nested-write/result type universe. Unsupported + operation/result/codec metadata must fail when a schema is constructed. +7. Prisma codecs distinguish application runtime, driver wire, and contract/database JSON. The + public validation representations are `runtime` and `json`; driver wire is adapter-internal. +8. Prisma runtime lowering supports namespaces, but RC1 and the inspected post-RC source flatten + namespaces in type maps. Sound multi-namespace E2E typing is an upstream-blocked capability, not + a current product claim. +9. NetScript's `isolatedDeclarations` and doctrine slow-type boundary require application-specific + inferred Prisma bindings to remain generated app-local values rather than published framework + exports. +10. Market evidence separates source definition, resolved manifest, executable plan, provider + ledger, and immutable receipt. It supports partial/unknown outcome recovery and rejects a local + reinvention of hosted RBAC, fleet, registry, and continuous-drift products. -- Status: pending focused inventory of the database package, adapter packages, CLI/scaffold - surfaces, and any proposed new package exports. -- This RFC is docs-only, but it specifies future published package/plugin surfaces, so the planned - public API must receive the same slow-type, private-type-reference, upstream-re-export, and - subpath-boundary scrutiny before Plan-Gate. +## Corrections and conflict resolutions -## Completed research artifacts +- Root Prisma catalog entries are caret ranges `^7.8.0`; generated templates still use `^7.4.2`. +- `@prisma/orm-postgres` has 138 audited top-level export keys, not the approximate 275 in the Qwen + independent report. +- The AP-17 `interfaces/` rename debt for `packages/database` is stale because `ports/` exists; its + composition-root question remains relevant. +- A live `DatabaseGraph` is rejected. Graphs may be internal compiler IR; the durable public join + point is a plain, content-addressed `DatabaseManifest`. +- Qwen's three minimum public responsibilities and the market audit's five artifact categories are + compatible: definition/manifest, operation protocol, and contribution record produce separate + definition, manifest, plan, ledger, and receipt values. +- Opus's broad runtime validation recommendation is narrowed by the pinned-source validation audit. +- Qwen's generated-validator recommendation is superseded by runtime interpretation plus optional + corpus-equivalent AOT. +- Opus's provider re-export sketch is rejected. Applications and controlled plugin authoring may + import Prisma's public builder directly; NetScript wraps the resulting native value and never + pretends to own or vendor the builder. +- Plugin removal is not solved by contract spaces alone. Detach-and-retain is the initial guaranteed + lifecycle; archive/drop remain conditional. +- The kernel is provider-neutral while the first adapter is Prisma 8 PostgreSQL-only. Unsupported + targets fail explicitly; no Prisma 7 fallback remains. -- [NetScript current-state and incident audit](./research/netscript-current-state.md) -- [Prisma 8 RC1/current-main source, scorecard, issue/PR, and agent-surface audit](./research/prisma-8-deep-dive.md) -- [Eleven-product market/prior-art comparison](./research/market-analysis.md) +## Report index -## Open questions +| Report | Evidence class and role | +| ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [netscript-current-state.md](./research/netscript-current-state.md) | Current NetScript source/history/debt rebaseline and failure taxonomy. | +| [prisma-8-deep-dive.md](./research/prisma-8-deep-dive.md) | Pinned RC/current source, release, scorecard, issue/PR, runtime/control/migration/agent analysis. | +| [market-analysis.md](./research/market-analysis.md) | Official-source comparison across seventeen framework, ORM, migration, IaC, control-plane, and mature-framework products. | +| [market-gap-audit.md](./research/market-gap-audit.md) | Independent correction for Flyway, Liquibase, Terraform, Pulumi, Bytebase, ZenStack, and hosted/local scope. | +| [runtime-validation-maintainer-exchange.md](./research/runtime-validation-maintainer-exchange.md) | Owner-supplied exploratory primary evidence for runtime-derived validation direction. | +| [runtime-validation-source-audit.md](./research/runtime-validation-source-audit.md) | Pinned-source proof of bounded validation algebra, missing operation metadata, codec representations, cache identity, and fail-closed cases. | +| [typescript-schema-orpc-audit.md](./research/typescript-schema-orpc-audit.md) | Historical/current Prisma builder evolution, native fragment/space composition, oRPC transfer, extension bundles, namespace blocker, and artifact boundary. | +| [qwen-prisma-risk-review.md](./research/qwen-prisma-risk-review.md) | Independent adversarial minimum-kernel, provider-contingency, risk, conformance, and kill review; factual conflicts corrected above. | +| [claude-opus-architecture-review.md](./research/claude-opus-architecture-review.md) | Independent package/archetype, identity, runtime, control, contribution, cutover, waves, and conformance architecture review. | +| [planned-jsr-audit.md](./research/planned-jsr-audit.md) | Prospective JSR verdict `PASS-AS-PLANNED`; explicitly not actual publish readiness because packages do not exist. | +| [architecture-plan-synthesis.md](./research/architecture-plan-synthesis.md) | Final decision-grade reconciliation and source for the formal Plan-Gate. | -- Which Prisma 8 capabilities are stable enough to own directly, and which must remain behind a - narrow NetScript port? -- What is the minimum durable NetScript database IR/contract that can serve Prisma without - recreating an ORM or schema engine? -- Should database integrations be ordinary plugin contributions, a dedicated capability family, or a - composition of schema/provider/runtime/migration contributions? -- How should one app express multiple logical schemas, databases, providers, tenants, and execution - runtimes without generator ordering or import-path ambiguity? -- What fully automated lifecycle replaces today's manual generation, patching, adapter selection, - migrations, seeding, registry wiring, and CI matrix maintenance? -- What implementation-wave boundaries preserve reviewability while explicitly avoiding a - compatibility layer? -- Which independent Opus findings require correction before the plan is eligible for PLAN-EVAL? +## Research verdict + +Research supports proceeding to PLAN-EVAL with no must-resolve-now architecture decision. The exact +Prisma RC/GA import spelling, provider lock mechanism, signature/key custody, and other +implementation details are classified by wave and cannot force a package-boundary rewrite. The +Prisma namespace type/runtime mismatch is a capability block: it withholds a claim rather than +blocking the provider-neutral architecture. + +No canonical RFC may be authored until the separate evaluator returns `PASS`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md new file mode 100644 index 0000000000..0a87ac0275 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md @@ -0,0 +1,973 @@ +# Architecture Plan Synthesis — NetScript Database Foundation + +> Status: Plan-Gate synthesis, not PLAN-EVAL and not the canonical RFC.\ +> Baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf`.\ +> Evidence date: 2026-08-13.\ +> Confidence labels: **[FACT]** is directly supported by a cited research/source artifact; +> **[INFERENCE]** reconciles facts; **[PROPOSAL]** is the architecture recommended for plan lock. + +## 1. Executive decision + +**[PROPOSAL]** NetScript should replace its database foundation with a clean-break, provider-neutral +composition and operations kernel whose first certified provider is Prisma 8 PostgreSQL. The kernel +owns identity, deterministic composition, schema-contributor ownership, runtime lifecycle, operation +state machines, policy, and evidence. Prisma owns its schema language, query language, contract +format, execution engine, migration semantics, and database-specific lowering. The application owns +domain ports and the final inferred query types. + +The durable center is not a live `DatabaseGraph`. It is a sequence of distinct values: + +```text +provider-native TypeScript contracts + NetScript database definition + | + v + content-addressed DatabaseManifest + | | + v v + app-local typed bindings speculative preview + | | + v v + lifecycle-owned sessions baseline-bound ExecutablePlan + | + v + provider marker / ledger + | + v + immutable OperationReceipt +``` + +**[INFERENCE]** This reconciles the two strongest independent findings: + +- the five current database systems need one NetScript-owned join point, but a live runtime graph + would become a service locator ([netscript-current-state.md](./netscript-current-state.md), + “Executive finding”; [claude-opus-architecture-review.md](./claude-opus-architecture-review.md), + §§2.1–2.2); and +- the manifest, plan, upstream ledger, and receipt must not collapse into Terraform-like mutable + state ([market-analysis.md](./market-analysis.md), “Artifact and control-plane boundary”; + [market-gap-audit.md](./market-gap-audit.md), “Plan-lock decisions affected”). + +The redesign has five refusal boundaries: + +1. **No NetScript query DSL or repository abstraction.** The provider's query surface remains intact + and application-local. +2. **No compatibility layer.** No Prisma 7 facade, legacy generated module, dual client, + `setClient`, alias barrel, copied schema, or textual generated-source repair survives. +3. **No false portability.** Provider capabilities are visible and statically checked. Unsupported + targets and operations fail explicitly. +4. **No local hosted control-plane clone.** RBAC, approvals, registries, fleet schedulers, + continuous drift agents, KMS, and permanent audit servers are optional integrations. +5. **No validation overclaim.** Standard Schema interpretation is deliberately bounded; unsupported + Prisma operations, result shapes, pack kinds, and codecs fail while constructing a schema. + +## 2. Reconciled evidence and corrections + +### 2.1 Facts that carry the architecture + +- **[FACT]** NetScript currently has five overlapping systems—configuration/Aspire resources, CLI + registry/runner, generated engine workspaces, runtime wrappers, and plugin fragment copying—with + no canonical join point. Target resolution ignores `PrimaryDatabase`; two same-provider targets + share `database/`; generation is Aspire-coupled; the generated workspace carries exactly + 30 `db:*` tasks; plugin contribution is source-layout discovery plus regex collision checking + ([netscript-current-state.md](./netscript-current-state.md); corrected facts in + [qwen-prisma-risk-review.md](./qwen-prisma-risk-review.md), §3). +- **[FACT]** Prisma 8 RC1 is Early Access, Node 24-primary, TypeScript 5.9 optional-peer, and + intends PostgreSQL as the only 8.0 GA database. MongoDB is EA, SQLite is proof-of-concept, MySQL + is later, and SQL Server is absent. Prisma's current direction is canonical contract data, a + separate control client, provider runtimes, contract spaces, and types-only emission + ([prisma-8-deep-dive.md](./prisma-8-deep-dive.md), “Research pin,” “Executive conclusion,” and + “Maturity scorecard”). +- **[FACT]** `@prisma/orm-postgres` has 138 top-level export keys at the audited pin, not the + approximate 275 stated in one independent report. This number is evidence of breadth, not a public + API requirement ([prisma-8-deep-dive.md](./prisma-8-deep-dive.md), “Public packages and coupling + risk”). +- **[FACT]** Prisma's public programmatic control direction is real but moving. The CLI/config + distribution, control routing, schema generation, PostgreSQL floor, numeric semantics, and output + channels changed after RC1. Public NetScript types therefore cannot name those option shapes or + package paths ([prisma-8-deep-dive.md](./prisma-8-deep-dive.md), “Six days of post-RC churn”). +- **[FACT]** NetScript builds with `isolatedDeclarations: true`; doctrine's slow-type exception is + intentionally restricted to oRPC-bound packages. Application-specific inferred Prisma contract + types must therefore terminate in generated app-local bindings unless publish conformance proves + an explicitly annotated provider surface + ([claude-opus-architecture-review.md](./claude-opus-architecture-review.md), §§2.1, 12.1; + `docs/architecture/doctrine/02-public-surface.md`). +- **[FACT]** The owner/maintainer exchange is evidence for a runtime-derived validation direction, + not an upstream commitment. The pinned source proves a useful bounded value algebra but disproves + full contract-only Prisma operation parity + ([runtime-validation-maintainer-exchange.md](./runtime-validation-maintainer-exchange.md); + [runtime-validation-source-audit.md](./runtime-validation-source-audit.md), “Bottom-line + decision”). + +### 2.2 Disagreements resolved + +| Disagreement | Resolution for plan lock | Reason | +| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| Live `DatabaseGraph` versus manifest | **[PROPOSAL]** `DatabaseGraph` may exist only as a private compiler IR. `DatabaseManifest` is the durable resolved value. | A live graph invites lookup/service-location; a manifest is serializable, hashable, reviewable, and transportable. | +| Three artifacts versus five artifacts | **[PROPOSAL]** Three public responsibilities—definition/manifest, operation protocol, contribution record—produce five distinct artifact classes: definition, resolved manifest, executable plan, provider ledger, receipt. | Qwen correctly minimizes the public kernel; the market audit correctly separates operational artifacts. | +| Who owns migration/control semantics? | **[PROPOSAL]** Prisma owns provider plan/diff/lineage/marker semantics. NetScript owns target selection, classification, policy, locking orchestration, expiry, cross-target sequencing, recovery, receipts, and error translation. | NetScript must not reimplement Prisma's migration engine, but the missing cross-target and operational guarantees are framework concerns. | +| Capability negotiation | **[PROPOSAL]** Static manifest capability claims and requirements only. No runtime negotiation protocol. | Prevents a second ORM and makes unsupported composition deterministic. | +| Consumer-owned ports | **[PROPOSAL]** App architecture guidance, not a NetScript port framework. NetScript exposes typed target/session references; applications bind them to their own stores at composition roots. | Preserves domain boundaries without generating repositories. | +| Provider contingency backend | **[PROPOSAL]** Specify and test a narrow provider SPI, but do not pre-build a direct-SQL fallback solely to prove it. A second real provider certifies the SPI later. | A speculative fallback would recreate low-level database machinery and violate “wrap, do not reinvent.” | +| Validation generation | **[PROPOSAL]** Runtime Standard Schema interpretation is the default for a bounded algebra. Optional AOT is derived, atomic, and corpus-equivalent. | Qwen's generated-validator recommendation predates the source audit; the source audit supersedes broad generation assumptions. | +| Public representation name | **[PROPOSAL]** `runtime` and `json`. Driver wire is adapter-internal. | Prisma codecs have three channels; calling JSON “wire” is ambiguous. | +| Full mutation/query input validation | **[PROPOSAL]** Do not promise it from the contract alone. Model-value and explicitly contributed operation schemas are supported; missing operation grammar is an unsupported-construction error. | Prisma's phantom operation type maps are emitted to `.d.ts`, not retained as runtime validation data. | +| Plugin removal | **[PROPOSAL]** Detach-and-retain is the initial guaranteed operation. Archive/drop remain capability- and conformance-conditional. | Contract spaces solve ownership and history, not RC1 extension removal. | +| Provider breadth | **[PROPOSAL]** Provider-neutral kernel, Prisma 8 PostgreSQL-only first release. Other targets return structured unsupported diagnostics; no Prisma 7 fallback. | Honest match to upstream maturity while preserving the architecture. | + +## 3. Durable vocabulary and artifact taxonomy + +The RFC must use these terms consistently. Similar-looking values are intentionally distinct. + +| Term | Kind and owner | Meaning and invariant | +| ----------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Public TypeScript value, NetScript | Authored composition of targets, spaces, connection-source references, capability requirements, and policies. Pure; it performs no IO. It is not called a manifest. | +| `NativeContract` | Provider-native authored value, provider | A Prisma `defineContract` result or another provider's equivalent. NetScript does not translate its entity/query vocabulary. | +| `SpaceContribution` | Public declarative record, NetScript/plugin | Stable owner ID, version, target binding input, dependencies, ownership, capabilities, artifact references, provenance, and retention policy for one contract space. | +| `ContractArtifact` | Versioned generated data, provider | Canonical provider contract data plus its declaration/types and lineage artifacts. It is pinned and mirrored per space. | +| `DatabaseManifest` | Public versioned generated data, NetScript | Fully resolved, deterministic snapshot of target/space identity, ownership, capability proof, artifact digests, provider pins, topological order, output roots, and policies. It is the durable join point. | +| `ManifestDigest` | NetScript content address | Digest of the canonical full manifest, including provider/contributor identities. It is not any Prisma storage/profile hash. | +| `AppBinding` | App-local generated TypeScript | Minimal inferred bridge from native contract declarations to concrete target sessions, validators, and transport consumers. Never a published framework export. | +| `TargetRef` | Public narrow generic value, NetScript | Explicit stable reference to one target. It carries identity/capability/scope types but no query methods by itself. | +| `TargetSession` | Public lifecycle shell + app-local query generic, NetScript/application | Provider-created process/request-scoped binding. Query surface remains the provider's inferred type parameter. | +| `ConnectionSource` | Public consumed port, NetScript | Resolves credentials/allocation for one target/environment. Environment values never participate in manifest identity. Aspire is one adapter. | +| `SpeculativePreview` | Public structured value, NetScript control | Offline or live advisory preview. Cannot be approved or applied. | +| `ExecutablePlan` | Public signed/versioned value, NetScript control | Bound to manifest digest, exact target/space closure, provider pins, environment, live baseline, operations, policy decision, expiry, and secret references. | +| `ProviderMarker` / `ProviderLedger` | Provider-owned database state | Authoritative provider record of applied space heads/edges. NetScript reads and cites it; NetScript does not create a second mutable shadow state. | +| `OperationReceipt` | Immutable append-only evidence, NetScript control | What was attempted, observed, checkpointed, verified, skipped, failed, or left uncertain. It is not desired state. | +| `OperationCatalog` | Public machine-readable data, NetScript | Names, classes, request/result schemas, diagnostics, and next actions. CLI/help/docs/agent instructions are projections. | +| `ValidationIR` | Internal bounded value algebra, NetScript runtime | Provider-decoded scalar/value-object/union/list/dict/null/value-set/selection shape used to produce Standard Schema values. It never becomes a second entity or query model. | + +Identity is declared, never inferred from provider names or paths: + +- `TargetId` identifies one logical database (`primary`, `analytics`). +- `RoleRef` identifies writer/read-only roles of a target; a replica is not a migration target. +- `NamespaceRef` identifies a physical namespace inside one target. +- `SpaceId` identifies one schema owner (`app`, `plugin:@netscript/auth`). +- `ObjectKey` is `(target, namespace, entryKind, name)` and has one managed owner. +- `ContractSnapshotId` addresses one canonical provider contract artifact. +- `PlanId` binds a manifest, baseline, provider set, policy, and target/space closure. +- `RunId`/`ReceiptId` identify executions and evidence. + +**[PROPOSAL]** Paths, array order, package traversal order, provider discovery order, config +aliases, and engine names must never become identity or dependency edges. + +## 4. Exact package and dependency graph + +### 4.1 Package assignments + +One package receives exactly one doctrine archetype. This corrects the current plan's missing +Archetype 3 runtime surface. + +| Package | Archetype | Public responsibility | Forbidden responsibility | +| ------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `@netscript/database-contract` | **A1 Small Contract** | Identities, manifest/plan/receipt/diagnostic data shapes, capability and ownership vocabularies, provider pins, small public SPIs shared across packages. | IO, runtime lifecycle, query types, Prisma imports. | +| `@netscript/database` | **A4 Public DSL/Builder** | `defineDatabase`, target/space/policy composition, pure resolution/compilation to `DatabaseManifest`, frozen definitions, deterministic diagnostics. | Connections, Aspire, provider imports, migration execution. | +| `@netscript/database-runtime` | **A3 Runtime/Behavior** | Process/request lifecycle, target binding, connection ownership, close order, health/readiness, cancellation, validation cache/interpreter coordination, small session handles. | Migration orchestration, CLI, provider query vocabulary. | +| `@netscript/database-control` | **A2 Integration** | Programmatic operation protocol; provider/control ports; classify/preview/plan/apply/verify/inspect/emit; lock coordination; receipts; resume and cross-target saga. | Provider SQL/AST types, direct Prisma imports, CLI rendering. | +| `@netscript/database-prisma-postgres` | **A2 Integration** | The only **framework runtime/control** Prisma import boundary; PostgreSQL capability descriptor; native-contract/artifact adapter; control adapter; runtime factory; validation-IR decoder; upstream compatibility allowlist. | Re-exporting Prisma as NetScript's generic API; importing CLI into runtime; hand-written Prisma driver internals. | +| `@netscript/database-testkit` | **A6 CLI/Tooling** | Runnable provider and contribution conformance certification with machine receipts, negative fixtures, and real-service profiles. | Runtime dependency of an application. | +| `@netscript/plugin` (existing) | **A4 Public DSL/Builder** | `defineDatabaseSpace`/contribution seam using `@netscript/database-contract`; removal of hollow path/engine contribution abstracts in the clean break. | Provider, runtime, or control dependencies. | +| First-party `plugins/*` | **A5 Plugin** | Thin contribution records and pinned release artifacts sourced from their `-core`; provider requirements and lifecycle policy. | Copied application schema, migration ownership hidden in install scripts, framework conventions. | +| `@netscript/aspire` (existing) | **A2 Integration** | One `ConnectionSource`/provisioning adapter and resource projection from the manifest. | Mandatory dependency for pure or non-Aspire operations. | +| `@netscript/cli` (existing) | **A6 CLI/Tooling** | Thin rendering/projection of `OperationCatalog` and `@netscript/database-control`; adoption codemod and agent artifact emission. | Database orchestration logic or provider switches. | + +`@netscript/database-testkit` is deliberately A6 rather than a `./testing` subpath because +third-party provider certification is runnable automation that provisions real services, executes a +matrix, and emits a signed machine report. If implementation proves no binary is needed, this is the +only package split that may be revisited before Wave 1; it must not be folded after public release. + +### 4.2 Dependency direction + +```text + @netscript/database-contract (A1) + / | | \ + v v v v + @netscript/database(A4) -runtime(A3) -control(A2) @netscript/plugin(A4) + ^ ^ ^ + | \ | + +------\-----+ + v + @netscript/database-prisma-postgres(A2) + ^ + | + @netscript/database-testkit(A6) + + application composition root -> definition + runtime + control + chosen provider + app bindings + provider-native app/plugin schema source -> Prisma public authoring builder (controlled build only) + @netscript/aspire -> runtime/contract connection-source SPI only + @netscript/cli -> control/contract operation catalog only + first-party plugin -> plugin + database-contract only +``` + +The arrows denote “depends on” toward the top-level contract seam: kernel packages never import a +provider. The provider implements runtime/control SPIs and is selected as a value in the application +composition root. Only the testkit may fan across all public SPIs. + +### 4.3 Doctrine and publish obligations + +**[FACT]** Doctrine currently describes database schema contributions as plain `*.prisma` fragments, +and its verdict/gated-root tables do not contain the proposed packages +([claude-opus-architecture-review.md](./claude-opus-architecture-review.md), §§3.5, 15.1). + +**[PROPOSAL]** Wave 0 must amend `docs/architecture/doctrine/06-archetypes.md` and +`10-codebase-verdict-and-handoff.md`, register every new package in the gated denominator, replace +the plain-fragment rule, and ensure A9's archetype count is current. Every package must pass +F-1…F-19 as required by its archetype; A3 additionally has required runtime gates. Package/plugin +waves require JSR surface design, `deno doc --lint`, packed install, consumer imports, +`quality:scan`, and `arch:check`. No database package receives the oRPC slow-types exception by +assumption. + +## 5. Public versus adapter-local ownership + +| Surface | Public NetScript contract | Adapter-local/provider-owned detail | +| ----------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| Authoring | Targets, spaces, ownership, policy, capability requirements, native-contract artifact references. | Prisma model/field/index/default helpers, scaffold shape, lowering and contract AST. | +| Types | Plain identities/artifacts plus generic `TargetRef`/`TargetSession`; concrete app bindings. | Prisma conditional/query/result types and contract generics. | +| Runtime | Scope, lifecycle, health, cancellation, transaction capability marker, validation requests. | `sql`, `orm`, `raw`, `prepare`, concrete transaction/runtime facade, driver/pool types. | +| Control | Operation classes, plan binding, policy, lock requirements, result/receipt/error catalog. | Exact `createControlClient` path/options, upstream plans/errors/progress, migration graph representation. | +| Contract identity | NetScript `ManifestDigest`, `ContractSnapshotId`, provider pin. | Prisma storage/execution/profile hashes and contract schema version, recorded as opaque attributes. | +| Contributions | Stable `SpaceId`, provenance, target/capability/dependency/ownership/removal policy, mirror digest. | Prisma contract-space artifact layout, marker/ledger tables, extension descriptors. | +| Validation | `StandardSchemaV1`, `runtime` and `json`, bounded supported/unsupported semantics, NetScript issue codes. | Prisma contract/AST decoding, driver-wire values, codec conversions, pack-specific metadata. | +| Operations UI | Machine catalog, JSON requests/results, `nextAction`; CLI/help/docs/agents generated from it. | Upstream command names, terminal text, config file layout. | + +No framework package re-exports Prisma. No public example imports a moving upstream control path. +Application and provider-specific plugin schema-authoring modules may import Prisma's **public +authoring builder** directly during the controlled build phase; that is provider-native authoring, +not a NetScript re-export. They may not import Prisma runtime/control internals, and their emitted +plain contribution descriptor/artifacts—not the schema module—are the deployment input. + +## 6. Native TypeScript schema extension and end-to-end typing + +### 6.1 Locked strategy + +**[FACT]** The fluent target/model/table/column chain shown in the owner's screenshot was real at +historical commit `fd88abf4`. Prisma redesign PR #261 / commit `27ccefc3` replaced it with the +model-first callback form, and PR #317 / commit `e1e5ab2c` removed the legacy implementation. RC1's +PostgreSQL API is `defineContract(scaffold, ({ field, model, rel, type }) => …)`: semantic models +first, `.sql(...)` storage overlay second, typed model tokens, and helper vocabulary composed from +family/target/extension packs. The callback preserves its literal return type +([typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md), §§1–3). + +**[PROPOSAL]** Use the same architectural pattern as NetScript's oRPC integration—preserve the +upstream inferred contract, add a NetScript-owned typed composition seam, and bind it at the +application root—but do not copy the mechanisms that would erase inference or publish slow types: + +1. **Candidate A is the baseline: native contract plus thin NetScript definition.** An application + or plugin author invokes Prisma's public `defineContract` directly, then passes the exact native + value to `defineDatabase({ contract, … })` or `defineDatabaseSpace({ contract, … })`. The + NetScript function retains `typeof contract` unchanged while adding identity and policy. + NetScript does not translate entity/model vocabulary and does not publish a shadow + `model()/column()` DSL. +2. **NetScript wraps the result, not the builder.** The frozen database/space definition records + target, ownership, migration head, capabilities, validation policy, and lifecycle around the + native value. It must not copy Prisma overloads or widen the value to a generic contract record. +3. **Composition uses contract spaces, not object spreading.** App and plugin contracts remain + separately owned snapshots with declared dependency edges. A “merged TypeScript contract” may be + an app-local inferred view only where Prisma publicly supports it; it is never the ownership + record. +4. **Plugin publication exports artifacts and plain contribution metadata.** A plugin's release + pipeline emits/pins its contract JSON, declaration artifact, lineage, provenance, and descriptor. + Consumer apply/verify works without importing the plugin package. +5. **Inferred binding stays application-local.** The app emitter writes a minimal binding module + from the manifest and provider declaration artifacts. This is automatic generated glue, never + hand-authored and never text-patched. +6. **A policy-applied native factory is optional, never foundational.** A + `createPrismaContractFactory(...).define(callback)` convenience is allowed only if it forwards + Prisma's exact composed helper surface without copied overloads, private imports, or inference + widening. Otherwise Candidate A remains the complete public API. + +This is “extend Prisma like oRPC” at the correct seam: +`native inferred contract → structurally +checked NetScript contribution → generated app-local binding`. +It does not mean wrapping `defineContract` with a parallel builder or re-exporting all upstream +helpers. + +### 6.2 End-to-end type flow + +```text +native defineContract() value + | typeof contract (editor/compiler inference) + +-----------------------> provider query/result types + | + v +defineDatabase()/defineDatabaseSpace(contract, ownership/capabilities) + | + v +DatabaseDefinition -> DatabaseManifest + pinned contract.d.ts/contract.json + | | + | +--> bounded ValidationIR -> StandardSchemaV1 + v +generated app-local TargetBinding + | + +--> process/request TargetSession> + +--> typed selection/result helper where provider metadata is complete + +--> oRPC/Fresh/form/SSR schemas at explicit trust boundaries + +--> application-owned AccountStore/BillingStore adapters at composition root +``` + +Static inference and durable identity are independent: + +- `typeof contract` is the DX track. It may contain complex provider generics and never crosses a + published framework boundary. +- `ContractSnapshotId`/`ManifestDigest` is the correctness track. It is plain data used by plans, + markers, receipts, validators, caches, agents, and stale-artifact checks. + +Every derived binding includes the manifest digest and exact provider pin. Runtime startup rejects a +binding/manifest/contract mismatch with a structured `db.artifact.stale` or +`db.contract.version-mismatch` diagnostic and a machine `nextAction`. + +### 6.3 Minimal illustrative shape + +This is an audited architectural sketch. The Prisma import subpath and exact RC overload remain +adapter-pin details, so the canonical RFC must label them version-specific rather than promise the +literal path. + +```ts +// Application-local provider-native authoring. +export const appContract = defineContract( + { extensions: {}, namespaces: ['app'] }, + ({ field, model }) => { + const User = model('User', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + email: field.text().unique(), + }, + }); + return { models: { User } } as const; + }, +); + +// NetScript composition adds ownership/lifecycle, not model vocabulary. +export const appDatabase = defineDatabase({ + id: 'app', + contract: appContract, + target: 'primary', + migrations: { space: 'app' }, + validation: { profile: 'boundaries' }, +}); +``` + +The public RFC must explicitly state that the screenshot's deleted fluent syntax is not the target +API and must not be recreated by NetScript merely for aesthetic familiarity. + +### 6.4 Native fragments, ownership modes, and extension bundles + +There are two contribution modes, and the mode decides migration ownership: + +- `ownership: 'app'` is a native fragment function that receives Prisma's exact composed helpers and + returns const-preserved native `types/models/enums/entities`. A generated app-local root composes + fragments through explicit calls and object spreads. It must not use `Array.reduce()` or a + registry widened to `Record`. +- `ownership: 'space'` is a complete plugin-owned native contract, canonical artifact, migration + graph, and head. This is the default for plugin-owned tables. The consumer binds the space to a + target but does not acquire its migration ownership. + +Composition is necessarily two-phase because extension packs determine the static and runtime shape +of the helper object before Prisma invokes the callback: + +1. collect contribution manifests, required packs, dependencies, target/namespace requirements, + ownership, and extension facets; +2. resolve one scaffold, obtain the fully composed native helper surface, and then invoke app-owned + fragments in deterministic dependency order. + +A database extension is one NetScript contribution bundle with a single verified ID/version and four +phase facets: + +```ts +defineDatabaseExtension({ + id: 'pgvector', + version: '…', + authoring: pgvectorPack, + control: pgvectorControl, + runtime: pgvectorRuntime, + validation: pgvectorValidation, +}); +``` + +The generated root fans that bundle into Prisma's authoring, control, runtime, and validation +locations. A missing, mismatched, or half-installed facet is a composition error. This eliminates +the current class of manual registration where one logical extension must be repeated independently +per phase ([typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md), §§4, 10). + +### 6.5 Canonical artifact boundary + +Native no-emit development does not remove the production artifact boundary: Prisma itself +serializes/deserializes even an in-memory native contract before runtime use, and migration planning +is canonical-artifact-driven. The automated build therefore evaluates native authoring only in a +controlled deterministic phase, canonicalizes, atomically emits contract and declaration artifacts, +checks the migration head, validates or creates migration artifacts, attaches ownership/provenance, +and makes CI/production runtime consume the exact verified artifact. Migration apply never executes +arbitrary application or plugin TypeScript +([typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md), §9). + +## 7. Runtime validation subsystem + +### 7.1 Public boundary and algebra + +**[PROPOSAL]** Standard Schema is the only public validator protocol. NetScript returns +`StandardSchemaV1` from app-local typed bindings; it does not re-export Zod, Valibot, ArkType, or +Prisma's ArkType contract-document validators. + +The supported internal `ValidationIR` is deliberately closed per interpreter ABI: + +- registered scalar codec leaves; +- nullability; +- `many` lists and `dict` values; +- value objects; +- value sets, domain enums, and resolvable provider native enums; +- unions only when branch identity is deterministic; +- model fields/relations whose cross-space references resolve through a verified aggregate; +- whole-model values with explicit presence policy; and +- direct-column selection/returning projections whose alias, codec, nullability, and representation + are fully known. + +Public representations are: + +```ts +type ValidationRepresentation = 'runtime' | 'json'; +``` + +Prisma driver-wire values and schemas are adapter-internal. A built-in or custom codec is supported +only when its contributor supplies a deterministic value schema for every advertised public +representation. Conversion success is not validation. + +### 7.2 Three schema classes + +The RFC must not hide materially different guarantees behind one `input()` method. + +| Class | Supported initial guarantee | Refusal boundary | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | +| Model value schema | Validate a named model/value-object/enum in `runtime` or `json`, using explicit object-presence/default policy. | No inference that database uniqueness/FK/check constraints are locally satisfied. | +| Operation input schema | Available only when the provider/extension contributes a runtime operation grammar and typed binding for that exact operation. | Prisma create/update/filter/nested-write semantics absent from runtime contract data fail at construction. | +| Result schema | Validate whole-model or fully-known direct projections/selections with complete leaves. | Computed/subquery/raw/aggregate/include/unknown leaves require an explicit contributed result schema or fail at construction. | + +Candidate app-local shape: + +```ts +const users = database.primary.space('app').model('User'); + +const runtimeUser = users.value({ representation: 'runtime' }); +const createData = users.operation('create', { representation: 'runtime' }); +const publicUser = users.result(selection, { representation: 'json' }); +``` + +`operation()` and `result()` throw `DB_VALIDATION_UNSUPPORTED` while constructing a schema if the +requested metadata is incomplete. Invalid user values do not throw; they return Standard Schema +issues. + +### 7.3 Mandatory unsupported cases + +Schema construction fails closed for at least: + +- unknown codec or missing representation-specific codec value schema; +- unknown provider pack entity kind; +- corrupt/missing aggregate space, head, hash, cross-space reference, or value set; +- ambiguous unions or unresolved model variants/discriminators; +- Prisma operation types whose runtime grammar is absent: filters, relation traversal, nested + writes, polymorphic narrowing, and default/presence semantics without a contributor; +- SQL computed, subquery, raw, aggregate, or include results without an explicit result shape; +- Mongo `resultShape: unknown`, raw `Document`, or unknown leaves; +- opaque SQL index/check expressions and database-state constraints such as uniqueness, FK, or + exclusion checks; and +- async/non-deterministic value predicates where the requested Standard Schema mode promises sync. + +No unsupported case becomes `unknown`, pass-through, or a warning. + +### 7.4 Cache identity and AOT equivalence + +No existing Prisma section hash covers validator identity. Cache keys contain: + +```text +canonical full-contract digest + schema version + space id + target/family ++ operation or normalized selection + representation + interpreter ABI ++ codec/pack contributor id/version + execution identity when defaults matter +``` + +An optional AOT projection ships only if it passes the same semantic corpus as runtime +interpretation: successes, issue paths, representation behavior, unsupported-construction failures, +contract-space resolution, and invalidation. It is content-addressed, target-scoped, atomic, and +replaceable. It is never hand-maintained, repaired, or required for correctness. + +### 7.5 Trust-boundary policy + +- Input/model-value validation is mandatory at external mutation boundaries where a supported schema + exists. +- Output validation is mandatory for declared API/RPC responses, SSR/hydration payloads, and + external-service messages; it is opt-in for internal query loops. +- Failure issues include stable code, target, space, contract digest, model/operation/selection, + representation, field path, expected class, and observed value class. +- Contract-space plugin fields participate automatically after aggregate integrity verification. +- oRPC, Fresh, forms, and SSR consume the same Standard Schema values; adapters must not regenerate + library-specific mirrors. + +## 8. Control state machines + +### 8.1 Operation classes + +| Class | Examples | Allowed dependencies | +| ----------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `pure` | compose, validate definition, emit, format, lineage integrity | Source/artifact readers and atomic writer only; never connection, Aspire, Docker, or network. | +| `live-read` | inspect, introspect, live preview, verify, status | Explicit target connection; no mutation lock. | +| `mutating` | initialize, seed, apply, sign, adopt baseline, retire | Explicit target; provider-native lock/fencing; executable plan where applicable. | +| `resident` | studio or connection available only inside an existing host | Explicit target and resident orchestration binding. | + +Aspire is a connection-source/provisioning adapter, never an operation class. + +### 8.2 Composition state machine + +```text +authored + -> resolving + -> resolved(manifest, warnings) + -> refused(diagnostics) +``` + +Resolution is pure and total as `Result`. It validates declared identities, output/root isolation, +provider pins, target binding, capability subsets, ownership disjointness, dependency +closure/cycles, cross-target reference refusal, contribution provenance, contract version, and +mirror integrity. + +### 8.3 Preview/plan state machine + +```text +resolved manifest + -> speculative-preview ----------------------> non-applicable + -> inspect baseline + -> executable-plan-created + -> policy-evaluated(allowed | refused) + -> approved/signed (required by environment) + -> ready + -> expired | stale | revoked +``` + +A speculative preview is never accepted by `apply`. An executable plan binds manifest digest, +target/space dependency closure, environment, live baseline, provider/package locks, ordered +operations, destructive findings, policy result, secret references, and expiry. Production requires +a signature, but signing/key custody is a pre-production decision rather than a Wave 1 blocker. + +### 8.4 Apply/receipt state machine + +```text +planned + -> acquiring-lock + -> locked + -> revalidating + -> started + -> applying(step checkpoint)* + -> applied + -> verifying + -> verified + -> succeeded + +terminal/interrupt branches: + refused | skipped(reason) | failed | partial_success + | cleanup_required | outcome_unknown | cancelled +``` + +Every irreversible operation or provider transaction group appends an atomic receipt checkpoint. +Loss of transport after dispatch produces `outcome_unknown`, never `failed`. Resume first inspects +the database and provider ledger, revalidates plan bindings, and then continues only operations +whose outcome is known and unfinished. It never blindly repeats non-idempotent DDL or data +transforms. + +Lock scope is target + physical database. Lock evidence includes provider capability, owner, nonce, +fencing token where used, start/expiry, timeout, and safe force-unlock preconditions. An adapter +that cannot provide a certified lock is refused for concurrent-safe apply. + +### 8.5 Cross-target saga + +Target and space selection always expands dependency closure. The plan records omitted items and +reason codes. Execution orders independent targets deterministically and may run them concurrently +only when policies and resource limits allow; each target has a separate runner and lock. + +There is no cross-database transaction and no automatic rollback claim. A second-target failure +returns complete per-target/per-space results and `partial_success`; resume continues after +inspection. Selective apply is recovery machinery, not the normal path, and it requires subsequent +whole-manifest verification. + +## 9. Plugin and contract-space lifecycle + +### 9.1 Contribution record + +Every contribution declares: + +- stable `SpaceId` and semantic version; +- provider contract-format range and contract artifact digest; +- target binding supplied by the application, never a default/fallback; +- namespace/object ownership and `managed | adopted | external | ignored` policy; +- static capability requirements; +- declared dependency edges; +- migration head/lineage artifact and data invariants; +- package/integrity/provenance/signature information; +- one identity/version-checked extension bundle fanning into authoring, control, runtime, and + representation-specific validation facets; +- representation-specific codec/operation/result validation contributions; +- allowed executable phases; and +- default retention/removal policy. + +The consumer pins a mirror containing descriptor, contract data/declaration, lineage, and +provenance. Production apply/verify reads the mirror, not `node_modules`. Half-installation—schema +contribution present without its runtime/codec half, or vice versa—is a composition error. + +### 9.2 Ownership and augmentation + +- Each `ObjectKey` has one managed owner. +- Equal text from two contributors is still conflicting ownership. +- Namespaces prevent lexical collisions but do not replace ownership checks. +- Cross-space references require the same target plus a declared dependency edge. +- Augmentation is an owner-granted closed permission, not implicit merge. Initial grant kinds are + deliberately narrow; unsupported modification asks the owner or uses an app-owned migration. +- `external` is not planned/mutated and is verified only against declared assertions. `adopted` has + an explicit reviewed baseline. `ignored` requires an auditable reason and participates in neither. + +### 9.3 Lifecycle + +| Transition | Guaranteed behavior | Refusal/conditional behavior | +| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | +| Install | Validate target/capability/dependency/ownership/provenance; pin mirror; recompile manifest; produce plan. | Refuse overlap, missing/cyclic dependency, contract skew, unsupported provider/codec. | +| Upgrade | Require lineage path from pinned head; pin new mirror; plan each changed edge. | Refuse ownership widening, incompatible contract format, capability regression, ambiguous branch. | +| Skew | Refuse mutation when installed package, mirror, manifest, and marker identities disagree. | Diagnostic names every observed identity and sync action. | +| Detach/uninstall | Remove runtime/package binding while retaining pinned space tombstone and data by default. | Refuse if dependents remain or contribution cannot be verified without package code. | +| Retain | Guaranteed initial removal mode; preserve data, marker, mirror/tombstone, and ownership history; downgrade future mutation authority to `adopted`. | Exact upstream extension-detach mechanics must pass conformance. | +| Archive | Provider-capability conditional; planned namespace/table relocation with restoration path. | Unsupported for v1 unless Prisma PostgreSQL conformance proves it. | +| Drop | Destructive-plan conditional; explicit policy/approval, dependent closure, and verified lineage. | Not claimed as a general RC1 capability; no delete-directory shortcut. | + +**[PROPOSAL]** The RFC defines the lifecycle vocabulary now but only marks detach-and-retain as a +first-release guarantee. Archive/drop do not block the architecture and may not be scored as +implemented until provider conformance succeeds. + +## 10. Multi-target and provider matrix + +| Axis/case | Kernel support | Prisma 8 PostgreSQL adapter v1 | Required behavior | +| ---------------------------------------- | ---------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Two PostgreSQL databases | Yes | Required | Distinct `TargetId`, connections, outputs, spaces, markers, runtimes, plans, locks, receipts. | +| Multiple PostgreSQL namespaces | Yes | **Upstream-blocked capability** | Runtime lowering supports per-model namespaces, but RC1/current-main type maps flatten them into the default namespace. The adapter must not claim `multiNamespace` until exact type/runtime parity passes without casts. | +| Writer/read replicas | Roles on one target | Runtime conditional | Reader session is read-only; no migration operation can address a reader. | +| App + multiple plugin spaces | Yes | Required | Independent artifacts/heads, dependency order, overlap refusal, package-free apply/verify. | +| Managed/adopted/external/ignored objects | Yes | Required | Ownership-aware plan and drift semantics. | +| Request/process scope | Yes | Required | Different types and lifecycle; serverless request handles disposable and capability-reduced. | +| Prisma 8 SQLite | Kernel-ready | Unsupported/deferred | Structured `db.target.unsupported`; no legacy fallback. | +| Prisma 8 MongoDB | Family axis ready | Unsupported/deferred | No production claim based on EA source presence. | +| Prisma 8 MySQL | Provider axis ready | Absent/deferred | Retire hand-rolled adapter; revisit after upstream or a separately certified provider. | +| SQL Server | Provider axis ready | Absent/deferred | Requires another provider implementation. | +| Cross-target relation/transaction | Explicitly unsupported | Unsupported | Composition error for relations; multi-target operations are sagas, never transactions. | +| Provider-specific query features | Capability-visible | Native Prisma surface | No lowest-common-denominator wrapper. | + +The provider-neutral kernel may ship independently of Prisma readiness. The Prisma adapter remains +experimental/unpublished until every release gate passes. A Prisma delay never reopens a Prisma 7 +path. + +## 11. Clean cutover and parallel development + +### 11.1 No-compatibility law + +The old and new systems may live on separate branches/release lines during implementation, but one +application composition may never load both. There are no runtime shims, aliases, deprecated +facades, dual migration histories, or copied schema bridges. + +### 11.2 Adoption workflow + +`netscript db adopt` is a temporary migration tool, not a compatibility layer: + +1. Read legacy config and generated layouts; report duplicate/ambiguous identities. +2. Generate a proposed TypeScript `DatabaseDefinition`, taking target IDs from config keys, never + providers. +3. Introspect every reachable target without mutation. +4. Propose one space per attributable owner plus app/external/adopted classifications. +5. Produce a complete ownership/capability/provenance preflight; unattributed objects hard-stop. +6. Compile the manifest and emit atomic provider/app-binding artifacts. +7. Establish one baseline/root per space and write provider marker metadata **only**—zero DDL/DML. +8. Verify the live target against the manifest and baseline. +9. Commit the new composition and delete old engine workspaces, 30 tasks, repair scripts, copied + plugin fragments, old adapters, and dependencies only after verification. + +After baseline and before the first new apply, rollback is repository-only plus idempotent removal +of new marker metadata where provider semantics permit. After first apply, recovery is forward +through lineage and receipts. There is no “run both clients” rollback. + +### 11.3 Safety and parity + +- A seeded/populated production-shaped rehearsal must prove adoption performs zero schema/data + mutation. +- Preflight is a committed CI artifact with target/provider versions, every object/owner, capability + proof, plugin provenance, and unresolved blockers. +- The fourteen legacy verbs receive explicit mapped/replaced/removed dispositions; implicit + target/default and silent first-target execution are deliberate removals. +- The parallel architecture branch merges only after feature-parity accounting, migration guide, + data-safety rehearsal, and full scaffold/runtime gates. This is branch strategy, not public API. + +## 12. Implementation waves and dependencies + +| Wave | Proves | Depends on | Primary surfaces | Exit gate | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| W0 RFC/doctrine lock | Vocabulary, package archetypes, refusal boundaries, acceptance matrix. | — | RFC + doctrine/gated-root amendments planned, not production code. | Accepted RFC; PLAN-EVAL/IMPL-EVAL complete; no unresolved must-resolve decision. | +| W1 Contract kernel | Plain identities, artifact schemas, capability/ownership vocabularies, diagnostic/operation types. | W0 | `@netscript/database-contract` | A1 gates; zero upstream deps; publish/doc/consumer proof. | +| W2 Definition/compiler | Pure native-contract wrapping, definition DSL, deterministic manifest resolution, ownership/dependency/capability checks. | W1 | `@netscript/database` | A4 gates; property/determinism tests; zero IO reachability. | +| W3 Prisma PostgreSQL spike | Validate public native builder, contract artifacts, ControlClient, runtime, spaces, extension bundles, Deno, bounded ValidationIR, and namespace parity behind adapter-local facade. | W1–W2 | Experimental `@netscript/database-prisma-postgres` | Kill/switch review; real PostgreSQL + packed Deno proof; no public stability claim; do not advertise `multiNamespace` while upstream types flatten namespaces. | +| W4 Runtime | Process/request sessions, lifecycle, connection sources, health/readiness, validation cache and trust-boundary adapters. | W1–W3 | `@netscript/database-runtime`, Aspire adapter | A3 gates; lifecycle/leak/cancellation/scope tests. | +| W5 Control | Operation catalog, preview/plan/apply/verify, lock/recovery/receipt state machines, atomic emission, cross-target saga. | W1–W4 | `@netscript/database-control` | A2 gates; exhaustive negative/failure injection; pure path no Aspire. | +| W6 Conformance testkit | Certify providers and spaces, generated-project fixtures, machine reports. | W1–W5 | `@netscript/database-testkit` | A6/F-CLI gates; intentionally broken fixtures fail; real PostgreSQL. | +| W7 Contribution seam | Replace hollow path/engine abstracts with space contributions and pinned artifacts. | W1–W6 | `@netscript/plugin`, first plugin-core fixture | Breaking surface accounting; plugin seam/thinness gates. | +| W8 CLI/agent/adoption | Thin command projection, generated docs/skill, adoption codemod/preflight. | W2, W5–W7 | `@netscript/cli`, generated app surface | Every example compiles/runs; codes/catalogs match; zero text-log assertions. | +| W9 First-party spaces | Auth/workers/sagas/triggers converted; capability and lineage artifacts published. | W7–W8 | Plugin core + thin A5 packages | Each space conformance suite; package-free apply/verify; runtime E2E parity. | +| W10 Clean cutover | Adopt populated fixtures; delete old database foundation and manual pipeline. | W1–W9 | Repo-wide DB wiring/scaffold/docs | Full release-gate class, Windows/Linux, production-shaped adoption, no compatibility remnants. | +| W11 Provider expansion | Prove SPI with a real second provider only when demanded and mature. | W10 | Separate provider package | Full provider conformance; no kernel/public manifest change. | + +W3 is intentionally a spike before public runtime/control stabilization. A failed Prisma adapter +must not invalidate W1–W2. No old package is deleted before W10; that temporary repository +coexistence does not authorize dual runtime composition. + +## 13. Exhaustive Plan-Gate decision table + +| ID | Decision | Status before PLAN-EVAL | Rationale / evidence | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| D-01 | Clean break; no backward compatibility surface. | **LOCK** | Owner directive; old constraints caused current architecture. | +| D-02 | Data continuity and mechanical migration are mandatory. | **LOCK** | No-compat does not authorize data loss. | +| D-03 | Durable join point is `DatabaseManifest`; live graph is private compiler IR. | **LOCK** | Opus/Qwen/market reconciliation. | +| D-04 | Definition, manifest, plan, provider ledger, and receipt are separate values. | **LOCK** | Terraform/Pulumi/Flyway/Liquibase corrections. | +| D-05 | NetScript defines no query DSL/repository/client facade. | **LOCK** | Avoid second ORM; native provider semantics remain available. | +| D-06 | Native model-first Prisma `defineContract` authoring is primary; obsolete fluent chaining is not recreated. PSL may remain provider input but is not NetScript's preferred E2E path. | **LOCK; exact import path adapter-pinned** | Owner directive plus historical/current source audit. | +| D-07 | Candidate A—direct native contract plus thin `defineDatabase`/space wrapper—is the baseline. Optional policy factory dies if it copies overloads, uses private imports, or widens inference. | **LOCK** | Preserves native values and ownership; exact oRPC transfer audit. | +| D-08 | App-specific inferred binding is generated app-local, never published from kernel packages. | **LOCK** | `isolatedDeclarations` and slow-type boundary. | +| D-09 | Exact package graph/archetypes are §4; runtime is A3. | **LOCK** | Doctrine gate correctness. | +| D-10 | Kernel is provider-neutral; first certified adapter is Prisma 8 PostgreSQL only. | **LOCK** | Upstream maturity matrix. | +| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | **LOCK** | Honest capability model and clean break. | +| D-12 | Capabilities are static declared tags, not runtime negotiation. | **LOCK** | Minimum kernel; prevents abstraction growth. | +| D-13 | Provider registry is composition-root data, never global/public mutable registry. | **LOCK** | A10 and service-locator refusal. | +| D-14 | Stable target ID, not engine/provider, owns connection/output/runtime/migrations/receipts. | **LOCK** | Repairs same-provider collision. | +| D-15 | Target selection is explicit; selection expands dependency closure and records omissions. | **LOCK** | No fallback/silent skip; market recovery lessons. | +| D-16 | Replicas are target roles, not migration targets. | **LOCK** | Prevents accidental mutation of readers. | +| D-17 | Provider-native contract spaces plus NetScript contribution policy replace copied fragments. | **LOCK** | Ownership/history/provenance. | +| D-18 | One managed owner per `ObjectKey`; augmentation requires owner grant. | **LOCK** | Text collision is not ownership. | +| D-19 | Pinned mirrors make production apply/verify independent of installed plugin packages. | **LOCK** | Contract-space deployment property. | +| D-20 | Detach-and-retain is guaranteed removal; archive/drop are conditional. | **LOCK** | RC extension removal gap. | +| D-21 | Standard Schema is public; runtime bounded interpretation is default. | **LOCK** | Maintainer direction plus source proof. | +| D-22 | Public validation representations are `runtime` and `json`; driver wire is internal. | **LOCK** | Three-channel codec source. | +| D-23 | Full Prisma operation validation is not contract-derived; explicit operation contributors are required. | **LOCK** | Phantom operation maps erased at runtime. | +| D-24 | Unknown validation metadata fails at schema construction. | **LOCK** | Fail-closed safety. | +| D-25 | Optional AOT validation is semantic-equivalence-only and never required. | **LOCK** | No second model universe. | +| D-26 | Pure operations cannot resolve connections or Aspire. | **LOCK** | Closes recorded architecture debt. | +| D-27 | Control API is programmatic; CLI/docs/agents project the operation catalog. | **LOCK** | Eliminates log parsing/drift. | +| D-28 | Preview differs from executable plan; apply accepts only bound, revalidated plans. | **LOCK** | Market plan/apply evidence. | +| D-29 | NetScript owns policy/lock/recovery/receipt/cross-target saga; provider owns diff/lineage/marker mechanics. | **LOCK** | Avoid both shell forwarding and migration-engine reinvention. | +| D-30 | Cross-target apply is never atomic; partial/unknown outcomes are first-class. | **LOCK** | Database reality and recovery prior art. | +| D-31 | Local kernel does not implement hosted registry/RBAC/fleet/drift services. | **LOCK** | Scope control. | +| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | **LOCK** | Retires current repair pipeline. | +| D-33 | Agent instructions are generated and every example is executed. | **LOCK** | Upstream skill drift evidence. | +| D-34 | Existing MySQL/MSSQL/SQLite product support is not carried through compatibility code. | **LOCK** | Clean break; structured unsupported behavior. | +| D-35 | Production plan signing is required. | **PRE-IMPLEMENTATION** | Key custody/algorithm can be chosen before W10, not before kernel work. | +| D-36 | Exact provider-native builder strategy and extension collection. | **LOCK; import spelling PRE-IMPLEMENTATION W3** | Current model-first callback, Candidate A, two-phase composition, const-preserving generated root, and no-re-export rule are source-audited; exact RC/GA subpath remains adapter-local. | +| D-37 | Multi-namespace capability claim. | **CONDITIONAL / upstream-blocking** | RC1 and current main lower runtime namespaces but type maps flatten into default namespace; no cast workaround is allowed. | +| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin-owned tables default to full space ownership. | **LOCK** | Preserves literal native values while keeping migration history with the real owner. | +| D-39 | One database-extension bundle supplies identity-matched authoring/control/runtime/validation facets through two-phase collection. | **LOCK** | Prevents manual half-registration and helper-shape unsoundness. | +| D-40 | Migration/runtime in CI and production consume canonical verified artifacts, never arbitrary schema TypeScript. | **LOCK** | Prisma's migration system and even no-emit runtime cross the canonical artifact boundary. | +| D-41 | Exact Prisma control/runtime import allowlist and compatibility window. | **PRE-IMPLEMENTATION (W3)** | Adapter-local and intentionally version-pin dependent. | +| D-42 | Lock implementation strategy (native advisory vs fenced row). | **PRE-IMPLEMENTATION PER PROVIDER** | Public semantics are locked; mechanism is conformance-driven. | +| D-43 | AOT validator ships. | **SAFE TO DEFER** | Runtime is sufficient; ship only for measured cold-start need. | +| D-44 | Second provider identity. | **SAFE TO DEFER** | SPI is proven when a real requirement/mature provider exists. | +| D-45 | Raw/prepared/aggregate numeric public conveniences. | **SAFE TO DEFER / adapter-local** | Moving upstream semantics; native query surface remains accessible app-locally. | +| D-46 | Archive/drop plugin retirement in v1. | **SAFE TO DEFER** | Retain path supplies safe lifecycle; destructive paths require proof. | +| D-47 | Remote approval/registry/continuous-drift integration. | **SAFE TO DEFER** | Optional control-plane charter. | + +There is no open decision that would force a package-boundary rewrite after PLAN-EVAL. D-37 is an +honest capability block: it prevents a Prisma PostgreSQL adapter from advertising sound +multi-namespace E2E typing, but it does not alter the provider-neutral manifest or package graph. + +## 14. Conformance and release gates + +Every behavioral feature crosses **type → composition/plan → provider artifact/SQL → result → +lifecycle/evidence**. A type-only or exit-code-only pass is not evidence. + +### 14.1 Composition, typing, and artifacts + +- Native TypeScript contract preserves model/query/result inference through the app binding. +- App-owned fragment composition preserves literal model/field/relation names under reordering; a + widened registry fixture must fail its type-soundness gate. +- Plugin contribution compiles without slow-type erasure and publishes its plain descriptor plus + artifact set. +- One extension bundle proves identical ID/version across authoring/control/runtime/validation, and + a missing or mismatched facet fails composition. +- Same-provider targets have no shared paths, heads, connections, locks, bindings, or receipts. +- Every ownership/capability/dependency/contract-skew diagnostic has a negative test and structured + `nextAction`. +- Resolve/emit twice from clean inputs yields byte-identical manifest/artifacts; interruption shows + fully old or fully new roots only. +- Domain-only, extension-only, codec, provider, representation, selection, and default-sensitive + changes invalidate the appropriate app binding/validation cache. +- Packed clean-consumer install resolves one exact Prisma component set and no off-allowlist import. +- Migration apply succeeds from canonical JSON/operations artifacts with application/plugin source + TypeScript unavailable. +- Type-check/editor latency passes an agreed 500-model representative application budget. + +### 14.2 Runtime and validation + +- Real PostgreSQL (not only PGlite) proves connect/query/relation/transaction/cancel/stream/close, + request/process scope, external pool where supported, and leak-free repeated lifecycle. +- Deno import graph has no unintended Node/CLI/toolchain reachability; deployment/bundler profiles + named by the adapter pass. +- `runtime | json` corpus covers strings/numbers/booleans, Date, bigint, numeric string, bytes, + JSON, domain enum/value set/native enum, null/list/dict/value object/union, and one custom codec. +- Every unsupported case in §7.3 fails constructing the schema with stable coordinates; invalid + values return path-rich Standard Schema issues. +- Direct selection/result shapes are strict; computed/raw/unknown paths never pass through. +- App plus two extension spaces proves aggregate resolution and duplicate model names never collide. +- Standard Schema consumption is proven through at least two independent consumers (for example oRPC + plus a form/validator integration), without generated Zod mirror files. +- If AOT exists, the full semantic corpus and cache invalidation suite is identical. + +### 14.3 Control, migration, and recovery + +- Offline emit succeeds with no Aspire/.NET/Docker/network. +- Non-default namespace selectors are honored; a silently ignored selector is a failure. +- Greenfield, populated adoption (marker-only), drift, destructive refusal, stale/expired plan, + package/contract skew, lock contention/death, invariant transform, and external ownership pass. +- Connection loss after dispatch produces `outcome_unknown`; resume inspects marker/live state + before action. +- Cross-target failure records all target/space phases and resumes only known-unfinished steps. +- Target/space selective recovery proves dependency closure, omitted reasons, and subsequent full + verification. +- Plugin install/upgrade/dependency/skew/package-absent verify/detach-retain pass. Archive/drop are + excluded until individually certified. +- Windows and Linux migration gates run; no gate asserts human message strings. + +### 14.4 Doctrine, consumer, journey, and release + +- Each new package is doctrine-registered and passes archetype F-1…F-19, scoped check/lint/fmt, + `quality:scan`, `arch:check`, JSR audit, docs score, packed install, and public import tests. +- A3 lifecycle packages pass mandatory runtime/Aspire gates; A5 plugins pass thinness, base-seam, + golden emitter, doctor, contract-soundness, and `scaffold.runtime` parity. +- Generated CLI/help/agent catalogs exactly match machine operation/diagnostic schemas; every + example compiles and runs. +- Journeys: scaffold → second PostgreSQL target → two plugin spaces → plan/apply/deploy with no + manual generated edit; and populated legacy adoption → zero DDL → verify. +- Cutover runs the full release-gate class and proves no legacy Prisma adapter, generated task, + copied fragment, repair script, deep generated import, or compatibility alias remains. + +## 15. Kill and switch criteria + +### 15.1 Kill only the Prisma adapter + +Keep the provider-neutral kernel but do not publish/switch to Prisma 8 if any remains true at the +adoption pin: + +- Deno runtime/import purity requires vendoring or textual patching upstream. +- Packed provider artifacts cannot publish/install without unsupported slow-type or duplicate- + component failures. +- Native TypeScript authoring cannot preserve app-local inference through a stable public builder + seam. +- Contract emission cannot be deterministic and atomically installed. +- Programmatic control cannot produce enough structured information to bind plans, verify outcomes, + and avoid terminal-text parsing. +- PostgreSQL marker/ledger advancement cannot be proven safe with migration effects. +- Contract spaces cannot prove disjoint ownership/package-free apply for app plus plugins. +- Required runtime lifecycle/transaction/error/cancellation behavior fails against real PostgreSQL. +- Upstream changes contract format without a viable migration path more than once before NetScript's + first stable adapter release. + +Switch to a different provider adapter only after it passes the same SPI conformance. Do not reopen +Prisma 7 compatibility. + +### 15.2 Kill or narrow a subsystem + +- If full-operation Standard Schema derivation would require reproducing Prisma's phantom type + system, keep only model-value and known-result validation plus explicit contributors; this + narrowing is already the plan, not a failure. +- If runtime interpretation misses cold-start budgets, test AOT equivalence; if equivalence fails, + retain runtime and require explicit schemas at the affected boundary rather than shipping a + divergent mirror. +- If provider-generic capability types grow into query abstractions or negotiation, delete them and + keep literal static tags. +- If contribution archive/drop cannot be verified, ship detach-and-retain only. +- If the public provider SPI changes to accommodate hypothetical providers before a second adapter + exists, revert to the smallest Prisma-exercised seam and defer generalization. + +### 15.3 Architecture kill criteria + +Reopen the RFC—not merely the adapter—if implementation proves that: + +- a deterministic manifest cannot express one target/space composition without depending on live + state; +- app-local type binding necessarily becomes a published framework slow type; +- target identity cannot stay provider-independent; or +- ownership/history cannot remain distinct from query/runtime types. + +## 16. Unresolved items by gate + +### Must resolve before PLAN-EVAL + +None. The TypeScript/oRPC source audit closes the last package-boundary decision: current native +model-first `defineContract`, direct public authoring plus thin `defineDatabase`, two-phase +extension collection, const-preserving app-local fragment composition, plugin-owned full spaces by +default, and no provider re-export or copied overloads. PLAN-EVAL must verify these locks, not +reopen them from illustrative RC syntax. + +### Must resolve before implementation wave + +- W1: canonical manifest/digest encoding and public format-version policy. +- W3: exact Prisma import allowlist/version window, GA/RC pin, Deno/runtime matrix, native builder + conformance, namespace capability status, extension-bundle facets, and adapter experimental + status. +- W4: request/process lifecycle and transaction capability types. +- W5: plan signature schema, key custody before production, provider lock mechanism, receipt storage + location/retention, and crash-fault injection harness. +- W7: initial augmentation grant vocabulary and executable contribution phase allowlist. +- W10: migration window, legacy branch support end date, and release rollback runbook. + +### Safe to defer + +- Any second provider; Prisma SQLite/Mongo/MySQL/SQL Server support. +- Runtime capability negotiation (rejected until a concrete case exists). +- AOT validation. +- Archive/drop plugin removal beyond retain. +- Public raw/prepared/aggregate convenience APIs. +- Hosted approvals/RBAC/registry/promotion/fleet/continuous-drift/secret services. +- Cross-database relations and transactions (explicitly unsupported, not future parity debt). + +## 17. Conflict ledger and final recommendations + +| Source position | Finding | Final recommendation | +| ----------------------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Current-state audit: one database graph | Correct need, risky runtime noun. | Private compiler graph; public resolved manifest. | +| Qwen: three durable artifacts | Correct API-minimization pressure. | Three public responsibilities, five distinct artifact classes. | +| Opus: nine-node package graph | Correct doctrine separation, with one caution. | Adopt graph in §4; do not build speculative direct-SQL contingency backend. | +| Opus/Qwen: provider-neutral kernel, PostgreSQL-only implementation | Convergent. | Lock. | +| Opus: full input/output runtime validation | Too broad after pinned-source audit. | Bounded algebra, three schema classes, fail closed. | +| Opus: runtime/wire | Incorrect public naming after codec audit. | Use `runtime` and `json`; driver wire is internal. | +| Qwen: generated validator provider | Superseded by source proof and owner/maintainer direction. | Runtime interpreter default; optional equivalent AOT only. | +| Opus: provider re-export of Prisma builder | Conflicts with doctrine and moving exact surface. | Application imports native Prisma builder; provider adds wrapper/extension values only where publishable. | +| Owner: extend TypeScript schema like oRPC | Architecturally correct, mechanics differ. | Current native model-first builder + thin definition, const-preserving app-root composition, extension bundle fan-out; add DB-specific ownership/lineage/lifecycle. | +| TypeScript source: namespaces lower at runtime but flatten in type maps | Blocks a broad multi-schema claim. | Keep kernel axis, withhold adapter capability until no-cast type/runtime conformance passes. | +| Prisma contract spaces solve removal | Overclaim. | Ownership/history adopt; detach-retain first; archive/drop conditional. | +| Market analogies to Terraform/Atlas/Bytebase | Useful only with scope correction. | Import plan/recovery vocabulary; do not rebuild mutable/hosted control plane. | + +**[PROPOSAL] Final recommendation.** Lock the architecture described here, then submit it to the +separate-session PLAN-EVAL before creating the canonical RFC. The canonical RFC should optimize for +one extraordinary user journey: author provider-native TypeScript contracts and NetScript +target/space policy once; obtain query types, lifecycle-owned sessions, Standard Schema +trust-boundary validation, migrations, runtime wiring, CLI/CI evidence, plugin ownership, and agent +context automatically—without a copied schema, manually synchronized type, hand-written adapter, +textual repair, or implicit target choice. + +## 18. Local evidence register + +- Current NetScript reality: [netscript-current-state.md](./netscript-current-state.md). +- Prisma RC/current source, issues, PRs, and maturity: + [prisma-8-deep-dive.md](./prisma-8-deep-dive.md). +- Market comparators and corrected control-plane analogies: + [market-analysis.md](./market-analysis.md) and [market-gap-audit.md](./market-gap-audit.md). +- Owner/maintainer validation exchange: + [runtime-validation-maintainer-exchange.md](./runtime-validation-maintainer-exchange.md). +- Pinned-source validation feasibility/refusal boundary: + [runtime-validation-source-audit.md](./runtime-validation-source-audit.md). +- Native TypeScript builder evolution, oRPC transfer, extension bundles, namespace blocker, and + artifact boundary: [typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md). +- Qwen adversarial minimal-kernel review: + [qwen-prisma-risk-review.md](./qwen-prisma-risk-review.md). +- Claude Opus package/runtime/control/contribution review: + [claude-opus-architecture-review.md](./claude-opus-architecture-review.md). +- Doctrine: `docs/architecture/doctrine/01-thesis-and-axioms.md`, `02-public-surface.md`, + `05-folder-structure.md`, `06-archetypes.md`, `07-composition-and-extension.md`, + `08-runtime-state-failure.md`, `09-anti-patterns-and-fitness-functions.md`, and + `11-plugin-thinness-and-base-seams.md`. +- Harness Plan-Gate: `.llm/harness/gates/plan-gate.md` and + `.llm/harness/gates/archetype-gate-matrix.md`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md new file mode 100644 index 0000000000..a437689cf3 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md @@ -0,0 +1,79 @@ +# Prospective JSR Audit — Planned Database Surface + +> Scope: Plan-Gate audit of the proposed packages, not an audit of implemented packages.\ +> Verdict: **PASS-AS-PLANNED**; **NOT ACTUAL PUBLISH READINESS**. + +The planned database graph satisfies the JSR rubric if the implementation preserves the boundaries +below. The six new packages do not exist, so running `deno publish --dry-run`, `deno doc --lint`, or +a packed/remote install against them is currently **N/A**, not a pass. Actual readiness begins only +when each package has a real manifest, export graph, source surface, and publish file list. + +## Planned surface + +| Unit | Status / archetype | Intended exports and boundary | JSR obligations and principal risk | +| ------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database-contract` | Public, A1 | Root for small identities/invariants; split focused subpaths only if the root approaches 20 symbols. | Zero provider dependencies; explicit annotations; no Prisma types. | +| `@netscript/database` | Public, A4 | Root `defineDatabase` authoring surface; focused definition/compiler subpaths only when responsibilities require them. | Frozen plain definitions and explicit public return types. Native Prisma contracts are accepted without being re-exported. | +| `@netscript/database-runtime` | Public, A3 | Root lifecycle factory and small session handles; validation or connection-source subpaths only if independently consumable. | Public generics remain narrow. Concrete inferred query/session bindings are generated **app-locally**, never exported here. | +| `@netscript/database-control` | Public, A2 | Root programmatic operations; focused catalog/testing subpaths if needed. | Plain plans, receipts, diagnostics, and ports; no provider control types or terminal-text contract. | +| `@netscript/database-prisma-postgres` | Public only after certification, A2 | Experimental provider root, with narrowly justified authoring/runtime/control subpaths. | Sole framework Prisma import boundary. It must not re-export Prisma, expose private/deep-import types, or make moving upstream types part of NetScript semver. | +| `@netscript/database-testkit` | Public tooling, A6 | Root library plus binary only if provider certification genuinely needs one. | Never a runtime dependency; machine receipts and fixtures excluded or deliberately published. Reconsider the package split before W1 if no binary exists. | +| `@netscript/plugin` | Existing public A4, changed | Add one documented database-space/contribution subpath; remove legacy copied-schema abstractions in the clean break. | Plain descriptor types only; no runtime/control/provider dependency. Breaking surface accounting required. | +| first-party `plugins/*` | Existing public A5, changed | Thin root plus established service/contract/scaffold surfaces; publish descriptors and generated contract/lineage assets. | Provider-native authoring stays in controlled build input. Deployment must work from pinned plain artifacts without importing plugin code. | +| `@netscript/aspire` | Existing public A2, changed | Add a narrow connection-source/provisioning adapter on an existing relevant subpath. | Deno/Aspire edge only; must not become required by pure database packages. | +| `@netscript/cli` | Existing public A6, changed | Existing binary/root project the operation catalog; no new database logic export. | Generated help/agent assets require freshness checks and production remote-graph E2E. | + +Each unit has exactly one archetype. The testkit exception is explicitly conditional before public +release, so the one-package/one-archetype law is satisfied as planned. + +## Non-negotiable publish rules + +- Every package gets one `deno.json` with scoped name, synchronized version, license, a concise + description/tagline under 250 bytes, explicit exports, and an `include` whitelist plus test and + fixture exclusions. Every entrypoint has `@module` documentation, a runnable example, and full + symbol JSDoc; stable surfaces target a 100% JSR documentation score. +- Root and subpath surfaces remain skimmable. Cross-package imports use declared `jsr:`/`npm:`/ + `node:` specifiers under repository dependency policy. Imports within the same package are + relative, preventing JSR self-referential-subpath resolution against an older published version. +- All published code is ESM and Deno-compatible. Node/Bun/browser compatibility is claimed only + after its matrix passes; default JSR settings may claim Deno alone. No CommonJS, HTTP imports, + top-level filesystem assumptions, or unconditional `fromFileUrl(import.meta.url)` are allowed. +- No database package receives the doctrine's oRPC-only slow-type carve-out. Public declarations + must satisfy root `isolatedDeclarations`; `--allow-slow-types` is a failure. Application-specific + `typeof contract`, Prisma query types, and inferred `TargetBinding` values terminate in generated + application files. Direct application authoring may import Prisma's public builder; NetScript + packages neither vendor nor re-export it. +- Publishable generated assets are checked-in TypeScript constants with deterministic + regeneration-plus-diff gates. Runtime file reads and text/JSON import attributes are forbidden + until an authenticated registry canary proves the known JSR limitation resolved. Contract JSON, + declarations, lineage, and provenance are explicit whitelisted artifacts, content-addressed and + atomically generated—not patched source. + +## Implementation and release gates + +W1–W6 must add each new unit to the publish denominator and require, per unit: scoped +check/lint/fmt, `deno doc --lint` with zero diagnostics across every export, +`deno publish --dry-run` without slow types, inspected publish file list, README/tagline checks, +`quality:scan`, `arch:check`, generated asset freshness, public import tests, and a clean packed +consumer install. W3 additionally requires an exact Prisma import allowlist, one resolved component +set, Deno import purity, and real PostgreSQL conformance before the provider package is advertised. + +W7–W9 apply the same gates to the changed plugin/CLI/Aspire surfaces, plus breaking-surface diff, +plugin thinness/seam checks, package-free artifact consumption, and executed generated examples. W10 +requires release preflight, authenticated canary publish with GitHub OIDC/SLSA provenance, registry +settings reconciliation, and the production `e2e-cli-prod` path against exact published JSR +versions. A local dry-run or packed install cannot substitute for this remote-graph verdict. + +## Blocking findings / kill criteria + +Plan Gate remains satisfied only while implementation proves all of the following. Kill or split a +surface if Prisma types leak into a public declaration, app inference requires a published slow +type, any unit needs `--allow-slow-types`, the provider requires private/deep imports or upstream +re-exports, internal bare self-imports appear, generated assets need runtime filesystem access, a +package combines two archetypes, or a clean remote consumer resolves duplicate/off-allowlist Prisma +components. Do not publish the Prisma adapter if its dry-run, docs, Deno graph, packed consumer, +provenance, canary, or production E2E gate is red. + +**Final audit verdict:** the proposed boundaries provide enough explicit mitigation for a +**PASS-AS-PLANNED** at PLAN-EVAL. They provide no evidence of actual publish readiness until the +implementation-time and release-time commands above produce green receipts. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index c478ada5ac..c5940a45c2 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -27,12 +27,13 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. ## Delegated research and synthesis lanes -| Agent path | Model / effort | Scope | Status | -| ----------------------------------- | --------------------------- | --------------------------------------------------------------- | --------- | -| `/root/market_gap_audit` | OpenAI · GPT-5.6 Sol · high | Missing delivery/control/validation comparators and market QA | Complete | -| `/root/validation_source_audit` | OpenAI · GPT-5.6 Sol · high | RC contract/result-plan proof for runtime Standard Schema | Complete | -| `/root/typescript_schema_audit` | OpenAI · GPT-5.6 Sol · high | Native TypeScript builder evolution and NetScript oRPC transfer | Complete | -| `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Reconcile all evidence into a decision-grade Plan-Gate proposal | In flight | +| Agent path | Model / effort | Scope | Status | +| ----------------------------------- | --------------------------- | ---------------------------------------------------------------- | -------- | +| `/root/market_gap_audit` | OpenAI · GPT-5.6 Sol · high | Missing delivery/control/validation comparators and market QA | Complete | +| `/root/validation_source_audit` | OpenAI · GPT-5.6 Sol · high | RC contract/result-plan proof for runtime Standard Schema | Complete | +| `/root/typescript_schema_audit` | OpenAI · GPT-5.6 Sol · high | Native TypeScript builder evolution and NetScript oRPC transfer | Complete | +| `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Reconcile all evidence into a decision-grade Plan-Gate proposal | Complete | +| `/root/planned_jsr_audit` | OpenAI · GPT-5.6 Sol · high | Prospective publishability/slow-type review of the planned graph | Complete | These lanes are independent research/synthesis inputs. None is the formal PLAN-EVAL, IMPL-EVAL, or owner-directed final Fable refinement. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 51c6dd3e0f..332318073e 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -2,53 +2,139 @@ ## Run Metadata -| Field | Value | -| -------------- | ------------------------------------------------------- | -| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | -| Branch | `docs/database-architecture-rfc` | -| Archetype | Docs-only RFC describing future A1/A2/A4/A5/A6 surfaces | -| Scope overlays | `SCOPE-docs.md` | +| Field | Value | +| -------------- | ------------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Phase | `plan-eval-ready` | +| Archetype | Docs-only RFC describing future A1/A2/A3/A4/A5/A6 surfaces | +| Scope overlays | `SCOPE-docs.md`; future packages use their archetype matrices | ## Design -The Design checkpoint is intentionally **not locked yet**. Research is active, and no canonical RFC -file may be created before the completed checkpoint passes PLAN-EVAL. - -### Public Surface - -- Planned RFC record: `rfcs/0000-database-architecture.md`. -- Future runtime/API/CLI surfaces: pending research and design lock. +The Design checkpoint is **locked and ready for PLAN-EVAL**. It is not evaluator-approved yet. No +canonical RFC file may be created until a fresh separate evaluator writes `plan-eval.md` with +`PASS`. + +### Public Surface and Package Graph + +- Planned RFC record: `rfcs/0000-database-architecture.md`; it does not exist before PLAN-EVAL. +- `@netscript/database-contract` (A1): plain identities, manifest/plan/receipt/diagnostic schemas, + capabilities, ownership, and shared small SPIs; zero provider dependencies. +- `@netscript/database` (A4): thin `defineDatabase`/target/space/policy definitions and pure + deterministic manifest compiler. +- `@netscript/database-runtime` (A3): process/request lifecycle, connection ownership, + health/readiness, cancellation, and validation coordination. +- `@netscript/database-control` (A2): programmatic operation catalog, emit/preview/plan/apply/ + verify/inspect, provider ports, locks, receipts, recovery, and cross-target saga. +- `@netscript/database-prisma-postgres` (A2): experimental/certified provider and sole framework + Prisma runtime/control boundary; no Prisma re-export. +- `@netscript/database-testkit` (A6): runnable provider/space conformance only if a binary is + justified; reconsider before W1 otherwise. +- Existing `@netscript/plugin` (A4), first-party plugins (A5), Aspire (A2), and CLI (A6) receive + thin database contribution, connection-source, and operation-projection changes. + +Candidate A is the authoring baseline: applications and controlled plugin build inputs call current +model-first Prisma `defineContract`, then pass the exact native value into thin +`defineDatabase`/`defineDatabaseSpace` functions that preserve inference. NetScript neither +recreates the deleted screenshot fluent DSL nor vendors/re-exports Prisma. App-specific inferred +bindings and const-preserving fragment composition are generated application-locally. ### Domain Vocabulary -- Pending evidence-led definition. Candidate terms are not contracts until the plan is locked. +- `DatabaseDefinition`: pure authored TypeScript composition. +- `NativeContract`: provider-native schema value. +- `SpaceContribution`: declarative owner/version/capability/dependency/provenance/retention record. +- `ContractArtifact`: canonical provider data/declaration/lineage/provenance, pinned per space. +- `DatabaseManifest`: deterministic versioned resolved value and durable join point; a graph is + private compiler IR only. +- `AppBinding`: generated app-local inferred target/session/validation bridge. +- `TargetRef`/`TargetSession`: explicit identity and lifecycle shell with app-local query generic. +- `SpeculativePreview` versus baseline-bound `ExecutablePlan`. +- Provider-owned `ProviderMarker`/`ProviderLedger` versus immutable NetScript `OperationReceipt`. +- `OperationCatalog`: machine source for CLI/help/docs/agents. +- `ValidationIR`: bounded internal value/selection algebra, never a second ORM type system. + +Stable identities are target, role, namespace, space, object, contract snapshot, manifest, plan, +run, and receipt IDs. Provider/engine/path/order/discovery strings never substitute for identity. ### Ports -- Pending identification of real external dependencies and exercised test seams. - -### Constants - -- Pending closed-vocabulary design for capability families, provider/runtime kinds, artifact kinds, - lifecycle phases, and gate identifiers. +- `ContractArtifactSource` and atomic artifact publisher. +- `ProviderRuntimeFactory` for process/request sessions. +- `ProviderControl` for provider-native emit/inspect/plan/apply/verify translation. +- `ConnectionSource` for environment, Aspire, or secret-reference resolution. +- Provider `MigrationLock` capability with owner/nonce/fencing evidence. +- `ReceiptSink` for atomic immutable checkpoints. +- Clock/ID/signature policy only where deterministic tests or production approval need seams. + +Ports stay cohesive at three or four methods. Provider registries are immutable composition-root +values, not globals. Concrete Prisma contracts/control/runtime/codec/AST types remain adapter-local. +Application domain ports remain application practice, not a generated NetScript repository system. + +### Constants and State Machines + +- Ownership: `managed`, `adopted`, `external`, `ignored`. +- Runtime scope: `process`, `request`. +- Validation representation: `runtime`, `json`; driver wire is internal. +- Operation class: `pure`, `live-read`, `mutating`, `resident`. +- Receipt outcomes include success, refusal, skip, failure, partial success, cleanup required, + cancellation, and outcome unknown. +- Removal guarantee: detach-and-retain; archive/drop are conditional. +- Capability IDs are open namespaced static data, not a negotiation protocol. + +Composition, planning/approval, apply/checkpoint/verify/recovery, contribution lifecycle, and +multi-target saga transitions are specified in `plan.md`. Preview cannot be applied; every unknown +outcome is inspected before resume; cross-target atomicity is never claimed. ### Commit Slices -| # | Slice | Gate | Files | -| - | -------------------------------------------------------- | ---------------------------------------------------------------------- | ---------------------------------------------------------- | -| 0 | Activate the harness run and publish the review surface | Run-artifact presence + clean diff | `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/*` | -| 1 | Research and lock the RFC design | PLAN-EVAL | Run research/plan/worklog artifacts | -| 2 | Author the implementation-grade RFC and migration design | Source-alignment/docs gates | `rfcs/0000-database-architecture.md` + run artifacts | -| 3 | Resolve multi-model review findings and close the run | IMPL-EVAL + Qwen review + owner-directed Fable 5 high final refinement | RFC + evaluation/run artifacts | - -### Deferred Scope - -- Production package/CLI/plugin implementation — begins only after RFC acceptance. - -### Contributor Path - -The RFC will define the final contributor path; until PLAN-EVAL, contributors start from this run's -research inventory and proposed package-boundary matrix. +| # | Slice | Gate | Files | +| - | ------------------------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------- | +| 0 | Harness bootstrap/review surface. | Artifact/format/diff; landed. | Run root. | +| 1 | Research corpus, rebaseline index, planned JSR audit, and Plan-Gate lock. | PLAN-EVAL input completeness, source/claim, format/diff. | `research.md`, `research/*.md`, planning/context/drift artifacts. | +| 2 | Independent Plan-Gate verdict. | Fresh separate-session `PASS`. | `plan-eval.md`, planning artifacts only. | +| 3 | Canonical architecture/API RFC body. | Source alignment, docs, decision coverage. | RFC plus run context/worklog. | +| 4 | Cutover/waves/conformance/risks/market completion. | Migration safety, claim trace, docs gates. | RFC plus run context/worklog. | +| 5 | Qwen/Grok adversarial findings resolved. | No open critical/high; Grok 4.6 route receipt. | RFC plus review/run artifacts. | +| 6 | Separate-session IMPL-EVAL. | Evaluator `PASS`. | `evaluate.md`, RFC/run artifacts. | +| 7 | Absolute final Fable 5 high refinement and publish handoff. | Fable substantive gate, then mechanical checks only. | RFC/final run/handoff artifacts. | + +### Prospective JSR Verdict + +`research/planned-jsr-audit.md` returns **PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS**. The six +new packages do not exist, so actual `deno publish --dry-run`, `deno doc --lint`, publish-list, +packed-install, canary, and remote-consumer results are **N/A**, not PASS. + +Implementation requires per unit: explicit manifest/export/include surface, docs/JSDoc/examples, +isolated declarations, no slow-types waiver, scoped check/lint/fmt, `quality:scan`, `arch:check`, +`deno doc --lint`, `deno publish --dry-run`, publish-list inspection, generated-asset freshness, +public import and packed-consumer tests. W10 adds authenticated OIDC/SLSA canary, registry +reconciliation, and `e2e-cli-prod` against exact JSR versions. + +### Open Decisions and Deferred Scope + +- Must resolve now: **none**. +- Pre-implementation by wave: manifest encoding/versioning; exact Prisma pin/import allowlist; + namespace capability verdict; lifecycle/transaction types; signature/key custody; provider lock; + receipt retention/fault harness; augmentation grants; cutover window/runbook. +- Safe to defer: second provider, Prisma non-PostgreSQL targets, runtime negotiation, AOT, archive/ + drop, raw/prepared/aggregate conveniences, hosted control plane, cross-database relation/ + transaction support. +- All production packages, doctrine mutations, publication, provider certification, plugin + conversion, legacy deletion, and release operation begin only after RFC acceptance. + +### Contributor Path and Implementation Waves + +Contributors author native provider contracts, then declare app-owned fragments or plugin-owned full +spaces. A two-phase generated root collects extension bundles/dependencies first, then invokes +native fragments with exact helpers. Plugin tables default to their own space, artifacts, lineage, +and head; production apply/verify consumes the pinned mirror without plugin code. + +W0 RFC/doctrine plan → W1 contract → W2 definition/compiler → W3 experimental Prisma PostgreSQL +spike → W4 runtime → W5 control → W6 testkit → W7 plugin seam → W8 CLI/agent/adoption → W9 +first-party spaces → W10 clean cutover → W11 second provider only when real/mature. Every wave has +the archetype, source, JSR, consumer, conformance, and release exits recorded in `plan.md`. ## Progress Log @@ -62,15 +148,23 @@ research inventory and proposed package-boundary matrix. | 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | | 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | | 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | +| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | ## Decisions -| Decision | Reason | Source | -| ------------------------------------- | --------------------------------------------------------------------------------------------- | --------------------------------------------- | -| Treat #313 as superseded design input | Its additive compatibility premise conflicts with the owner-directed clean break. | Issue #313 + owner prompt | -| Require PLAN-EVAL | Material architecture, sequencing, and multi-wave risk are unavoidable. | Harness run loop §4 | -| Delegate architecture deep dive | Owner explicitly requested Claude Code Opus 5 high and an orchestration-first posture. | Owner correction | -| Elevate TypeScript schema authoring | It can remove the schema/type/codegen split and anchor one end-to-end application type graph. | Owner directive + pending pinned-source audit | +| Decision | Reason | Source | +| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| #313 is superseded design evidence | Its additive/compatibility premise conflicts with the owner-directed clean break. | Owner directive + current rebaseline | +| Compiled manifest, not live graph | A plain deterministic value is the durable join point and avoids service location. | Synthesis D-03/D-04 | +| Exact A1/A4/A3/A2/A2/A6 package split | One archetype per responsibility; runtime lifecycle requires A3 gates. | Doctrine + synthesis §4 | +| Native model-first Prisma authoring | Preserve the real current builder/inference; never recreate the deleted fluent screenshot API or another DSL. | TypeScript/oRPC audit + D-06/D-07 | +| App-local inferred binding | Satisfies isolated declarations without expanding the oRPC-only slow-type exception. | Doctrine/JSR audit + D-08 | +| Contract spaces and extension bundles | Plugin ownership/history and one authoring/control/runtime/validation registration replace copied fragments/manual facets. | Prisma source + D-17–D-20/D-38–D-40 | +| Bounded Standard Schema interpreter | Contract runtime data is useful but omits full operation/result types; runtime/JSON schemas fail closed. | Validation source audit + D-21–D-25 | +| Provider-neutral kernel, PostgreSQL-only first adapter | Matches Prisma maturity without compatibility fallback or false portability. | Prisma scorecard/source + D-10/D-11/D-34 | +| NetScript operational semantics, provider migration mechanics | NetScript owns policy/locks/recovery/receipts/saga while provider owns diff/lineage/marker. | Market/source reconciliation + D-27–D-30 | +| PLAN-EVAL before RFC | Architecture has no open must-resolve item but still requires independent acceptance. | Harness Plan-Gate + D-01–D-47 | +| Fable 5 high remains last substantive gate | Explicit owner exception; no substantive model review follows it. | Owner directive | ## Drift @@ -89,22 +183,31 @@ research inventory and proposed package-boundary matrix. ### Fitness Gates -| Gate | Result | Evidence | Notes | -| -------------------------- | ------- | ---------------- | -------------------------------------------- | -| Archetype/anti-pattern set | NOT_RUN | Pending research | RFC proposes future public package surfaces. | +| Gate | Result | Evidence | Notes | +| ---------------------------- | --------------- | ------------------------------- | ------------------------------------------------------------------------------------ | +| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | +| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | +| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | +| PLAN-EVAL | NOT_RUN | Fresh evaluator required | Hard stop before canonical RFC. | ### Runtime Gates -| Gate | Result | Evidence | Notes | -| ---------------- | ------ | ------------------- | ----------------------------------------------------- | -| Runtime behavior | N/A | Docs-only bootstrap | Future implementation gates will be specified by RFC. | +| Gate | Result | Evidence | Notes | +| ---------------- | ------ | ------------------- | ----------------------------------------------------------------------------------------------- | +| Runtime behavior | N/A | Docs-only Plan-Gate | Future A3/provider/control runtime matrices are selected in `plan.md`; no implementation claim. | ### Consumer Gates -| Consumer | Result | Evidence | Notes | -| ---------------------- | ------- | ----------- | ------------------------------------------------------ | -| RFC reader/implementer | NOT_RUN | Pending RFC | Must be implementation-grade and internally navigable. | +| Consumer | Result | Evidence | Notes | +| ---------------------- | ------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------- | +| PLAN-EVAL reader | READY | `research.md`, `plan.md`, `worklog.md`, synthesis and audits | Complete current rebaseline, locked design, risks, slices, waves, and gates. | +| RFC reader/implementer | NOT_RUN | RFC blocked | Canonical RFC authorship begins only after PLAN-EVAL PASS. | ## Handoff Notes -- Research is active. No PLAN-EVAL or implementation/RFC authorship verdict is claimed. +- Planning is complete, not evaluator-approved. The next action is a fresh separate-session + PLAN-EVAL. No implementation or canonical RFC authorship verdict is claimed. +- Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until + packages exist and must produce implementation/release receipts later. +- After PLAN-EVAL PASS, follow the eight RFC slices and preserve Fable 5 high as the final + substantive gate. From 383170bbc919da5e43f897e416c95936750cc27a Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 19:49:35 +0200 Subject: [PATCH 06/19] docs(rfc): record plan evaluation correction --- .../briefs/fable-plan-eval.md | 77 ++++++++ .../plan-eval.md | 180 ++++++++++++++++++ .../plan.md | 6 +- .../research.md | 10 +- .../research/architecture-plan-synthesis.md | 14 +- .../supervisor.md | 14 ++ .../worklog.md | 46 +++-- 7 files changed, 322 insertions(+), 25 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval.md new file mode 100644 index 0000000000..8065ee8fd3 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval.md @@ -0,0 +1,77 @@ +use harness + +# Formal PLAN-EVAL — NetScript Database Architecture / Prisma 8 RFC + +You are the fresh, separate formal PLAN-EVAL evaluator for run +`docs-database-architecture-rfc--prisma-8-rfc`. You did not author the research or plan. Be +adversarial, evidence-led, and independent. This is PLAN-EVAL only: judge the locked plan, never +author the RFC, evaluate implementation that does not exist, or soften the harness checklist. + +## Route and identity + +- Required route: native Claude Code, `claude-fable-5`, effort `medium`. +- Record the observed model, effort, session ID, date, worktree, branch, and evaluated commit. +- Evaluated worktree: `/home/codex/repos/netscript-db-rfc`. +- Evaluated branch/head: `docs/database-architecture-rfc` at `3cbcfcec8` + (`docs(rfc): lock database architecture plan`). +- This session is separate from the Codex supervisor, Opus research lane, Qwen review, and all + delegated research/synthesis agents. + +## Mandatory harness inputs, in this order + +1. `.llm/harness/gates/plan-gate.md` +2. `.llm/harness/evaluator/plan-protocol.md` +3. `.llm/harness/evaluator/verdict-definitions.md` +4. `.llm/harness/templates/plan-eval.md` +5. Run files: `research.md`, `plan.md`, `supervisor.md`, `drift.md`, and the complete `## Design` + section of `worklog.md` under `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/`. +6. Detailed synthesis and planned publish audit: `research/architecture-plan-synthesis.md` and + `research/planned-jsr-audit.md`. +7. Every other report linked by run-root `research.md`; use them to challenge load-bearing claims + and conflict resolutions rather than merely trusting the synthesis. +8. `.llm/harness/archetypes/SCOPE-docs.md`, `.llm/harness/gates/archetype-gate-matrix.md`, the + applicable A1/A2/A3/A4/A5/A6 archetype profiles, and the doctrine files cited in the plan. +9. `.llm/harness/debt/arch-debt.md` entries relevant to database, Prisma, plugin schema, generation, + and Aspire coupling. +10. Repo `AGENTS.md`, `rfcs/README.md`, and `rfcs/0000-template.md` where they constrain the plan. + +## Mandatory procedure + +- Confirm run-root `research.md` is current and explicitly rebaselined to current main baseline + `cd720529333328bcba5e1a308ce7632f4350efdf`. +- Spot-check at least three load-bearing findings against the actual tree, including one current + NetScript fact, one pinned Prisma RC/current-source fact, and one doctrine/JSR/package-boundary + fact. Record exact paths/lines or commits. +- Walk every Plan-Gate checkbox individually and cite the exact plan/research/worklog location that + satisfies it, or mark it failed. +- Run your own open-decision sweep. Any decision still open that could force rework is an automatic + failed checkbox, even if the plan labels it deferred. +- Verify all D-01 through D-47 exist and classifications are coherent; specifically attack D-35, + D-37, D-41, and D-42 to decide whether their deferral is safe. +- Verify there are fewer than 30 ordered commit slices and each names proof, gate, and files. +- Verify the exact future package graph assigns one archetype per unit, includes A3 runtime gates, + and does not allow a provider/query/slow-type dependency leak. +- Apply the planned JSR requirement honestly: planned packages do not exist, so dry-run/doc/packed + results must be N/A now; decide whether the prospective audit names sufficient implementation + mitigations. +- Challenge the clean-break/data-safety boundary, native Prisma TypeScript builder strategy, + app-local E2E inference, bounded fail-closed runtime validation, plugin ownership/removal, + multi-target/provider claims, operation/receipt recovery, implementation waves, and absolute-final + Fable ordering. +- Confirm the canonical RFC file `rfcs/0000-database-architecture.md` is absent. Its absence is + correct before PASS. + +## Verdict and output contract + +Write exactly one evaluator artifact using the harness template to the absolute path: + +`/home/codex/repos/netscript-db-rfc/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md` + +Emit exactly one verdict: + +- `PASS` only if every Plan-Gate box is satisfied and no rework-forcing decision remains. +- `FAIL_PLAN` otherwise, with numbered, severity-tagged, actionable required fixes and exact + file/line evidence. Do not edit the plan yourself. + +Do not edit any other file. Do not create the RFC. Do not commit or push. End the artifact with +exactly `PLAN-EVAL: PASS` or `PLAN-EVAL: FAIL_PLAN`, and end your turn immediately after writing it. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md new file mode 100644 index 0000000000..6b6e647e47 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md @@ -0,0 +1,180 @@ +# PLAN-EVAL — docs-database-architecture-rfc--prisma-8-rfc + +- Plan evaluator session: native Claude Code, observed model `claude-fable-5`, effort `medium`, + session `dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`, 2026-08-13 (UTC) +- Route: matches the required lane (`formal_plan_evaluation` — Anthropic · Fable 5 · medium); fresh + session, separate from the Codex supervisor, Opus research lane, Qwen review, and all delegated + research/synthesis agents +- Run: `docs-database-architecture-rfc--prisma-8-rfc` +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Branch / evaluated commit: `docs/database-architecture-rfc` @ `3cbcfcec8` + (`docs(rfc): lock database architecture plan`) +- Surface / archetype: docs-only RFC plan under `SCOPE-docs.md`, describing future A1/A2/A3/A4/A5/A6 + surfaces +- Scope overlays: `SCOPE-docs.md`; future packages evaluated against + `gates/archetype-gate-matrix.md` +- Canonical RFC file `rfcs/0000-database-architecture.md`: **absent — correct** (verified by listing + `rfcs/`; only `0000-template.md`, `0001`–`0005`, `README.md` exist) + +## Rebaseline verification + +- `research.md` lines 4–9 explicitly rebaseline to + `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf`, date 2026-08-13, with Prisma pins RC1 + `a76a6c5` and post-RC object `71e2e0d9…`. Verified: `cd720529` is an ancestor of HEAD and of + `origin/main`; the pinned Prisma checkout at `.llm/tmp/prisma-v8-rc1` resolves HEAD + `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` and `git cat-file -t 71e2e0d9…` returns `commit`. +- Note (non-blocking): `origin/main` has since advanced by exactly one commit, + `01e096049 ci: adopt structured check reports (#1639)`. The delta touches CI/check-report tooling + only (no `packages/database`, no scaffold DB templates, no doctrine). The plan already commits to + "a fresh pin check during RFC drafting" (plan.md § Dependencies and Drift Watch), which covers + this. + +## Spot-checks of load-bearing findings + +1. **Current NetScript facts.** + - `resolveTarget` ignores `PrimaryDatabase` and only defaults with exactly one enabled target — + **confirmed** at `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66-86`. + - AP-17 `interfaces/` rename debt for `packages/database` is stale — **confirmed**: + `packages/database/ports/` exists (no `interfaces/`) while the debt entry at + `.llm/harness/debt/arch-debt.md:316-324` remains open and still says "`interfaces/` should + become `ports/`". The composition-root half of the entry remains live, as the plan states. + - `DB-GENERATE-ASPIRE-COUPLING` is open — **confirmed** at + `.llm/harness/debt/arch-debt.md:1954-1990` (status: open; `DbOperationRunner.executeDetached` + always boots Aspire). + - Root catalog uses caret `^7.8.0` while generated templates use `^7.4.2` — **confirmed** + (`deno.json:231-235`; `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` + lines 36, 59, 122-124). + - **"the generated workspace has exactly 30 `db:*` tasks" — REFUTED.** I executed + `generateDatabaseDenoJson` from + `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` at the evaluated head for + all four providers (`postgresProvider`, `sqliteProvider`, `mysqlProvider`, `mssqlProvider`): + every engine emits **42** `db:*` task keys, not 30. The Qwen "correction" + (`research/qwen-prisma-risk-review.md:64`, F3: "Exactly 30 unique `db:*` tasks") undercounts by + omitting the twelve computed per-engine keys (`db::${provider.engine}`); its own inclusion + list (14 base ops + 12 `:all` variants + `format`/`zod`/`patch-client`/`fix-zod`) sums to 30 + only without them. The original current-state claim "more than twenty database tasks" + (`research/netscript-current-state.md:174`) was accurate. The false count was adopted as a + rebaselined load-bearing finding in `research.md:34` (finding 2), restated as **[FACT]** in + `research/architecture-plan-synthesis.md:70` and repeated at + `architecture-plan-synthesis.md:681`, and copied into the plan itself at plan.md § Clean + Cutover ("deletes the old engine workspaces, 30 tasks, …"). See Required fixes. +2. **Pinned Prisma RC/current-source facts.** + - Model-first authoring (D-06/D-36): **confirmed** — + `.llm/tmp/prisma-v8-rc1/packages/3-extensions/postgres/src/contract/define-contract.ts:91-105` + is `defineContract(scaffold, (helpers: ComposedAuthoringHelpers<…>) => { types/models/enums })` + with `const` generics preserving literal return types; no fluent target/table/column chain. + - Namespace type-map flattening (D-37): **confirmed** — + `.llm/tmp/prisma-v8-rc1/packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-690`: + comments state "the authoring path lumps every model under the default storage namespace"; + non-default namespaces receive `entries.table: Record` (empty). The audit's cited + line ranges (`typescript-schema-orpc-audit.md:629-645`) match. Withholding the `multiNamespace` + capability claim is well-founded. + - `@prisma/orm-postgres` 138 top-level export keys: pinned to the run's own audit + (`research/prisma-8-deep-dive.md:98`), correcting Qwen's ~275; direction and provenance + consistent. +3. **Doctrine / JSR / package-boundary facts.** + - `isolatedDeclarations: true` — **confirmed** at root `deno.json:174`. + - Slow-type exception is sanctioned only for oRPC-bound packages — **confirmed** at + `docs/architecture/doctrine/02-public-surface.md:217-239`; the plan/JSR audit's rule that no + database package inherits it is consistent. + - Doctrine codifies plain `*.prisma` plugin fragments and does not register the proposed packages + — **confirmed**: `docs/architecture/doctrine/06-archetypes.md:209`; zero hits for + `database-contract|database-runtime|database-control` in `06-archetypes.md` and + `10-codebase-verdict-and-handoff.md`. The plan's W0 doctrine-amendment obligation is correct. + +## Checklist results + +| Plan-Gate item | Result | Evidence / location | +| --------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Research present and current | **FAIL** | `research.md` exists, is explicitly rebaselined to `cd720529` with pinned Prisma sources, and #313 is rebaselined as historical evidence only — but load-bearing finding 2 (`research.md:34`, "exactly 30 `db:*` tasks") is false at the pinned baseline (actual: 42 per engine, generator executed), and it was copied unverified from the Qwen independent report into research.md, the synthesis ([FACT] at `architecture-plan-synthesis.md:70`), and plan.md § Clean Cutover — violating the plan's own gate "corrected claims are not copied from independent reports" (plan.md § Plan and research gates). | +| Decisions locked | PASS | plan.md § Locked Decision Ledger D-01–D-47 with rationale columns; expanded rationale in `architecture-plan-synthesis.md` §13. | +| Open-decision sweep | PASS | plan.md § Open-Decision Sweep (must-resolve-now: none; per-wave items W1/W3/W4/W5/W7/W10; safe-to-defer list). My independent sweep (below) found no unflagged rework-forcing decision. | +| Commit slices (< 30, gate + files each) | PASS | plan.md § RFC Commit Slices: eight ordered slices (0–7), each naming what it proves, its gate, and its files; mirrored in `worklog.md` § Commit Slices. | +| Risk register | PASS | plan.md § Risk Register: 20 risks each with mitigation/kill response; § Kill and Switch Criteria adds adapter/subsystem/architecture kill tiers. | +| Gate set selected | PASS | plan.md § Gate Set: current docs/RFC gates match the `SCOPE-docs.md` overlay (source alignment, link integrity, terminology, drift log, fmt/diff); future units mapped to F-1…F-19 per `gates/archetype-gate-matrix.md`, A3 runtime gates required, A5 parity, A6 F-CLI family, release-gate class (`scaffold.runtime`, `e2e-cli-prod`) at W10. | +| Deferred scope explicit | PASS | plan.md § Deferred Implementation Scope and § Open-Decision Sweep "Safe to defer"; non-scope/refusal boundary in § Non-Scope. | +| jsr-audit surface scan (pkg/plugin) | PASS | `research/planned-jsr-audit.md`: verdict `PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`; dry-run/doc-lint/packed/canary honestly `N/A` because the six packages do not exist (plan.md § Prospective JSR gates; worklog § Prospective JSR Verdict). Named risks (slow types, re-export, self-import, generated assets, duplicate Prisma components) each map to W1–W10 gates and kill criteria. | + +## Directed challenges (per evaluator brief) + +- **D-35 (production plan signatures, W5/W10).** Public semantics are locked (`ExecutablePlan` is a + signed/versioned value; plan-status vocabulary includes approved/signed; production requires a + signature). Only mechanism/algorithm/key custody is deferred, and W1 locks + manifest/digest-encoding format-versioning first, so a later custody choice cannot rewrite package + boundaries. **Deferral safe.** +- **D-37 (multi-namespace withheld).** Verified against pinned source (above). The kernel keeps + `NamespaceRef` as a first-class axis; only the adapter's capability claim is withheld, with an + explicit no-cast rule and a conformance gate. If upstream never fixes it, the kernel carries an + unused axis — no rework. **Conditional classification correct.** +- **D-41 (Prisma import allowlist/compat window, W3).** Adapter-local by construction: the + dependency law keeps every kernel package Prisma-free, the adapter stays experimental/unpublished + until W3 gates pass, and the kill criteria keep W1–W2 valid if the adapter dies. Post-RC path + churn is documented (`prisma-8-deep-dive.md` "Six days of post-RC churn"), which is precisely why + pinning now would be designing to a moving surface. **Deferral safe.** +- **D-42 (advisory vs fenced-row lock).** Public lock semantics (owner, nonce, fencing evidence + where used, timeout, force-unlock preconditions, refusal of uncertified adapters for + concurrent-safe apply) are locked; only the per-provider mechanism is conformance-driven. + **Deferral safe.** +- **D-01–D-47 existence/coherence.** All 47 present in plan.md § Locked Decision Ledger; + classifications match `architecture-plan-synthesis.md` §13 (Locked / Pre-implementation W3–W10 / + Conditional / Deferred). No contradiction found between the ledger, the open-decision sweep, and + the wave exits. +- **Package graph.** Each unit has exactly one archetype; runtime is explicitly A3 with required + runtime gates (matrix: F-13 + runtime/Aspire validation required for Arch 3). The dependency law + forbids kernel→provider imports; concrete Prisma types are adapter-local; app-specific inferred + bindings are generated app-local (consistent with `isolatedDeclarations` and the oRPC-only + slow-type exception). No provider/query/slow-type leak path found. The testkit A6-vs-subpath + question is explicitly bounded ("reconsider before W1"), pre-publication, and cannot rework other + units. +- **Clean-break/data-safety, builder strategy, validation, lifecycle, recovery, waves, ordering.** + Adoption is marker-only (zero DDL/DML) with hard-stop on unattributed objects, rehearsal gate, and + forward-only recovery after first apply; the native-builder strategy matches the pinned source; + validation is bounded with enumerated fail-closed cases and construction-time refusal; plugin + removal guarantees only detach-and-retain; multi-target apply is a saga with `outcome_unknown` and + inspect-before-resume; W0–W11 have explicit dependencies and exit evidence; slice 7 keeps + owner-directed Fable 5 high as the absolute last substantive gate with only mechanical checks + after. All coherent; no unstated open decision found. + +## Open-decision sweep (evaluator-run) + +No unflagged decision that would force rework if deferred. Candidates examined and dismissed: +testkit package-vs-subpath (flagged, bounded before W1, pre-publication); manifest/digest encoding +(W1-first, format-versioned); Grok 4.6 route availability for slice 5 (operational lane dependency, +live-route evidence recorded in `supervisor.md`; not an architecture decision); RFC +tracking-issue/label mechanics from `rfcs/README.md` (implementation-time process owned by +`netscript-pr`, not a plan decision). + +## Verdict + +`FAIL_PLAN` + +### Required fixes + +1. **[MEDIUM — factual integrity of a load-bearing rebaselined claim]** Correct the "exactly 30 + `db:*` tasks" count to the verified value (42 `db:*` tasks per generated engine workspace at + baseline `cd720529`; counted by executing `generateDatabaseDenoJson` for all four providers) — or + drop the exact number in favor of the accurate "more than twenty/forty-odd" formulation — in + every location that carries it: + - `research.md:34` (load-bearing finding 2); + - `research/architecture-plan-synthesis.md:70` ([FACT] bullet) and `:681` (cutover step 9); + - `plan.md` § Clean Cutover ("…deletes the old engine workspaces, 30 tasks, …"); + - record the disposition of Qwen finding F3 (`research/qwen-prisma-risk-review.md:64`) as an + incorrect correction in `research.md`'s "Corrections and conflict resolutions" section, the + same way the ~275-export claim was dispositioned. Rationale: the plan's own research gate + states "Every load-bearing numeric/factual claim is pinned to NetScript baseline… corrected + claims are not copied from independent reports" (plan.md § Plan and research gates). This + number was copied from an independent report, labeled [FACT], and would be inherited by the + canonical RFC's cutover/deletion inventory in slices 3–4. No architecture decision changes; + this is a research-integrity fix only. + +## Notes + +- Non-blocking: `origin/main` advanced by one CI-only commit (`01e096049`) after the rebaseline; the + plan's committed "fresh pin check during RFC drafting" covers it. No database surface is touched + by that commit. +- All other spot-checked load-bearing claims held against the tree and the pinned Prisma source; the + architecture, decision ledger, slices, gates, risks, JSR honesty, and deferral classifications are + otherwise sound. A corrected resubmission should be a fast second cycle. +- Per the hard stop: no canonical RFC authorship until a PLAN-EVAL `PASS`. + +PLAN-EVAL: FAIL_PLAN diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md index 930cff574b..ffa6df8f90 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -306,9 +306,9 @@ identity/version, and execution identity when defaults matter. `netscript db adopt` is a temporary codemod/tool, not compatibility. It reads legacy config/layout, generates explicit target definitions from config keys, introspects reachable databases, proposes object ownership, hard-stops on unattributed objects, compiles/emits canonical artifacts, writes -baseline marker metadata only, verifies zero drift, and then deletes the old engine workspaces, 30 -tasks, copied fragments, repair scripts, adapters, and dependencies. Baseline establishment performs -zero table/data DDL/DML. +baseline marker metadata only, verifies zero drift, and then deletes the old engine workspaces, the +42 per-workspace generated `db:*` task keys, copied fragments, repair scripts, adapters, and +dependencies. Baseline establishment performs zero table/data DDL/DML. Old/new stacks may coexist on separate branches/release lines while features are developed, but one application never composes both. Before first new apply, rollback is repository-only plus idempotent diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md index 59011d275a..d989b808b7 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md @@ -31,7 +31,8 @@ the harness-required current research entrypoint; it does not duplicate the repo wrappers, and install-time plugin schema copying. 2. Target identity collapses into provider/engine paths. Two same-provider databases share `database/`; operation target resolution ignores `PrimaryDatabase`; pure generation is - Aspire-coupled; the generated workspace has exactly 30 `db:*` tasks. + Aspire-coupled. Executing `generateDatabaseDenoJson` for PostgreSQL, SQLite, MySQL, and MSSQL at + the baseline produces 42 `db:*` task keys in every generated engine workspace. 3. Plugin schema is inferred from files and regex collisions rather than versioned ownership, capability, migration history, provenance, or retention policy. 4. Prisma 8 is an architectural change: canonical contract data and declaration artifacts, @@ -57,6 +58,13 @@ the harness-required current research entrypoint; it does not duplicate the repo ## Corrections and conflict resolutions - Root Prisma catalog entries are caret ranges `^7.8.0`; generated templates still use `^7.4.2`. +- Qwen finding F3 incorrectly “corrected” the current-state report's accurate “more than twenty” + wording to exactly 30 tasks by omitting twelve computed provider-specific task keys. The PLAN-EVAL + evaluator executed `generateDatabaseDenoJson` for all four providers and verified 42 `db:*` keys + for each. Qwen's report remains immutable independent audit evidence; its count is explicitly + superseded here. The same copied 30-task premise propagated into the immutable Opus review and + model briefs and is likewise non-authoritative. Mutable synthesis and plan records use the + executed-generator result. - `@prisma/orm-postgres` has 138 audited top-level export keys, not the approximate 275 in the Qwen independent report. - The AP-17 `interfaces/` rename debt for `packages/database` is stale because `ports/` exists; its diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md index 0a87ac0275..c2243616e2 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md @@ -66,10 +66,11 @@ The redesign has five refusal boundaries: - **[FACT]** NetScript currently has five overlapping systems—configuration/Aspire resources, CLI registry/runner, generated engine workspaces, runtime wrappers, and plugin fragment copying—with no canonical join point. Target resolution ignores `PrimaryDatabase`; two same-provider targets - share `database/`; generation is Aspire-coupled; the generated workspace carries exactly - 30 `db:*` tasks; plugin contribution is source-layout discovery plus regex collision checking - ([netscript-current-state.md](./netscript-current-state.md); corrected facts in - [qwen-prisma-risk-review.md](./qwen-prisma-risk-review.md), §3). + share `database/`; generation is Aspire-coupled; executing `generateDatabaseDenoJson` for + all four providers produces 42 `db:*` task keys in every generated engine workspace; plugin + contribution is source-layout discovery plus regex collision checking + ([netscript-current-state.md](./netscript-current-state.md); executed-generator correction in the + [run-root rebaseline](../research.md), “Corrections and conflict resolutions”). - **[FACT]** Prisma 8 RC1 is Early Access, Node 24-primary, TypeScript 5.9 optional-peer, and intends PostgreSQL as the only 8.0 GA database. MongoDB is EA, SQLite is proof-of-concept, MySQL is later, and SQL Server is absent. Prisma's current direction is canonical contract data, a @@ -678,8 +679,9 @@ facades, dual migration histories, or copied schema bridges. 6. Compile the manifest and emit atomic provider/app-binding artifacts. 7. Establish one baseline/root per space and write provider marker metadata **only**—zero DDL/DML. 8. Verify the live target against the manifest and baseline. -9. Commit the new composition and delete old engine workspaces, 30 tasks, repair scripts, copied - plugin fragments, old adapters, and dependencies only after verification. +9. Commit the new composition and delete old engine workspaces, the 42 per-workspace generated + `db:*` task keys, repair scripts, copied plugin fragments, old adapters, and dependencies only + after verification. After baseline and before the first new apply, rollback is repository-only plus idempotent removal of new marker metadata where provider semantics permit. After first apply, recovery is forward diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index c5940a45c2..ace5df6988 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -38,6 +38,20 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. These lanes are independent research/synthesis inputs. None is the formal PLAN-EVAL, IMPL-EVAL, or owner-directed final Fable refinement. +## Formal plan evaluation + +| Cycle | Route / model / effort | Session | Evaluated commit | Verdict | Disposition | +| ----- | ---------------------------------------------- | -------------------------------------- | ---------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Native Claude Code · `claude-fable-5` · medium | `dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22` | `3cbcfcec8` | `FAIL_PLAN` | Sole medium factual-integrity finding corrected in mutable records; cycle 2 resubmission ready, with canonical RFC authorship still blocked. | + +Cycle 1 used the required fresh `formal_plan_evaluation` route, separate from the supervisor and all +research/synthesis lanes. Its only required fix was the copied claim of 30 generated `db:*` tasks: +evaluator execution of `generateDatabaseDenoJson` established 42 keys per generated engine workspace +for PostgreSQL, SQLite, MySQL, and MSSQL. `research.md`, the architecture synthesis, and `plan.md` +now carry the executed result and disposition Qwen F3 as an incorrect correction; independent model +reports, briefs, and `plan-eval.md` remain immutable evidence. The phase remains `plan-eval-ready`; +a fresh cycle 2 `PASS` is required before the canonical RFC is authored. + ## Recorded lane/eval overrides - The root session is Codex rather than the default Opus 5 orchestrator. This is the active diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 332318073e..14a96c4f9b 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -12,9 +12,12 @@ ## Design -The Design checkpoint is **locked and ready for PLAN-EVAL**. It is not evaluator-approved yet. No -canonical RFC file may be created until a fresh separate evaluator writes `plan-eval.md` with -`PASS`. +The Design checkpoint is **locked and ready for PLAN-EVAL cycle 2**. Cycle 1 returned `FAIL_PLAN` +solely because the copied generated-workspace task count was factually wrong; the evaluator executed +the generator for all four providers and found 42 `db:*` keys per workspace. The mutable +research/synthesis/plan records are corrected and ready for resubmission. The architecture remains +evaluator-unapproved, and no canonical RFC file may be created until a fresh separate evaluator +returns `PASS`. ### Public Surface and Package Graph @@ -150,6 +153,18 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in | 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | | 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | +### PLAN-EVAL Cycle 1 + +Fresh Fable 5 medium cycle 1 returned `FAIL_PLAN` on one medium factual-integrity defect only: an +independently reported count of 30 generated `db:*` tasks was copied into mutable Plan-Gate records, +while executing the generator produced 42 per engine workspace for every provider. All architecture +decisions, slices, risks, gates, and deferrals otherwise passed. + +The three mutable records now use the executed 42-per-workspace result and disposition Qwen F3 as an +incorrect correction while preserving independent reports and evaluator evidence. Targeted format +and full diff checks passed. Cycle 2 resubmission is ready; phase remains `plan-eval-ready` and RFC +authorship remains blocked. + ## Decisions | Decision | Reason | Source | @@ -183,12 +198,12 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in ### Fitness Gates -| Gate | Result | Evidence | Notes | -| ---------------------------- | --------------- | ------------------------------- | ------------------------------------------------------------------------------------ | -| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | -| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | -| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | -| PLAN-EVAL | NOT_RUN | Fresh evaluator required | Hard stop before canonical RFC. | +| Gate | Result | Evidence | Notes | +| ---------------------------- | ----------------- | ------------------------------- | ------------------------------------------------------------------------------------ | +| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | +| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | +| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | +| PLAN-EVAL | FAIL_PLAN_CYCLE_1 | `plan-eval.md`; correction diff | Sole factual-integrity finding corrected; cycle 2 required before canonical RFC. | ### Runtime Gates @@ -198,15 +213,16 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in ### Consumer Gates -| Consumer | Result | Evidence | Notes | -| ---------------------- | ------- | ------------------------------------------------------------ | ---------------------------------------------------------------------------- | -| PLAN-EVAL reader | READY | `research.md`, `plan.md`, `worklog.md`, synthesis and audits | Complete current rebaseline, locked design, risks, slices, waves, and gates. | -| RFC reader/implementer | NOT_RUN | RFC blocked | Canonical RFC authorship begins only after PLAN-EVAL PASS. | +| Consumer | Result | Evidence | Notes | +| ---------------------- | -------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------- | +| PLAN-EVAL reader | RESUBMIT_READY | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 1's sole factual finding is corrected; cycle 2 remains required. | +| RFC reader/implementer | NOT_RUN | RFC blocked | Canonical RFC authorship begins only after PLAN-EVAL PASS. | ## Handoff Notes -- Planning is complete, not evaluator-approved. The next action is a fresh separate-session - PLAN-EVAL. No implementation or canonical RFC authorship verdict is claimed. +- Planning is complete, not evaluator-approved. PLAN-EVAL cycle 1 returned `FAIL_PLAN` only for the + corrected generated-task count; the next action is fresh separate-session cycle 2. No + implementation or canonical RFC authorship verdict is claimed. - Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until packages exist and must produce implementation/release receipts later. - After PLAN-EVAL PASS, follow the eight RFC slices and preserve Fable 5 high as the final From a9a9df47b9931d235dcdb739b2780ead63f59bda Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 20:01:08 +0200 Subject: [PATCH 07/19] docs(rfc): pass database plan gate --- .../briefs/claude-opus-rfc-author.md | 631 ++++++++++++++++++ .../briefs/fable-plan-eval-cycle-2.md | 97 +++ .../context-pack.md | 57 +- .../plan-eval.md | 285 ++++---- .../plan.md | 38 +- .../supervisor.md | 22 +- .../worklog.md | 70 +- 7 files changed, 989 insertions(+), 211 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-author.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval-cycle-2.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-author.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-author.md new file mode 100644 index 0000000000..1b15180f3f --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-author.md @@ -0,0 +1,631 @@ +# Lead-author briefing — canonical NetScript database architecture RFC + +You are the single lead author for NetScript's canonical database architecture RFC. Work in: + +`/home/codex/repos/netscript-db-rfc` + +Use native Claude Code Opus 5 with high effort. You own the RFC's structure, technical coherence, +prose, API design, and final internal consistency. Do not delegate RFC sections or merge +independently authored prose. You may use read-only search and analysis workflows, but the canonical +document must have one architectural voice. + +PLAN-EVAL cycle 2 passed. It is the final Plan-Gate cycle. The owner has ended pre-writing loops: do +not start, request, or simulate another PLAN-EVAL. Begin canonical RFC authorship now. Architecture +diversity happens against the completed draft, not before it. + +## Mission + +Write: + +`rfcs/0000-database-architecture.md` + +This is not a narrow Prisma 7→8 migration note. It is a clean-slate replacement for NetScript's +inherited database foundation, using Prisma Next where it is mature while introducing a genuine +NetScript database layer. + +The RFC must make the intended developer experience concrete: + +- Pure TypeScript, native Prisma contract authoring. +- A thin, inference-preserving NetScript layer analogous in spirit to NetScript's oRPC extension + approach. +- No hand-maintained schema mirrors, copied plugin fragments, repair scripts, provider-specific + workspace forests, manually synchronized validators, or CLI-only orchestration. +- Explicit multi-target, contract-space, ownership, migration, runtime, validation, plugin, and + operational semantics. +- A provider-neutral kernel with one first certified adapter: Prisma 8 PostgreSQL. +- A clean break with no compatibility API, Prisma 7 fallback, dual runtime, legacy adapter facade, + or in-application mixed stack. +- Mechanical adoption and data continuity without backwards compatibility. + +The RFC must be implementation-grade: an implementer should be able to derive package work, public +types, state transitions, test matrices, refusal behavior, and release gates without inventing +architecture. + +## Editing scope + +Edit only: + +- `rfcs/0000-database-architecture.md` + +The root owns all run bookkeeping. Do not edit `plan.md`, `research.md`, `worklog.md`, +`context-pack.md`, `drift.md`, `supervisor.md`, anything under `research/` or `briefs/`, +`plan-eval.md`, independent model reports, production packages, doctrine, or existing RFCs. Do not +commit or push. + +## Required source order + +Read these completely before drafting: + +1. `AGENTS.md`, `SCOPE-docs.md`, `rfcs/README.md`, and `rfcs/0000-template.md`. +2. Run-root `research.md`, `plan.md`, `worklog.md`, `context-pack.md`, `drift.md`, `supervisor.md`, + and the now-`PASS` cycle-2 `plan-eval.md`. +3. `research/architecture-plan-synthesis.md` as the reconciled decision source. +4. The two priority source audits, in full: + - `research/typescript-schema-orpc-audit.md` + - `research/runtime-validation-source-audit.md` +5. Every remaining supporting report: + - `research/netscript-current-state.md` + - `research/prisma-8-deep-dive.md` + - `research/runtime-validation-maintainer-exchange.md` + - `research/market-analysis.md` + - `research/market-gap-audit.md` + - `research/planned-jsr-audit.md` + - `research/qwen-prisma-risk-review.md` + - `research/claude-opus-architecture-review.md` + +Treat run-root `research.md` as the correction ledger. Independent model reports are adversarial +evidence, not factual authority. In particular: + +- The generated engine workspace has 42 `db:*` keys per workspace at the evaluated baseline, not 30. +- `@prisma/orm-postgres` has 138 audited top-level export keys, not approximately 275. +- The current-state report's “more than twenty” task statement was accurate. +- The live `DatabaseGraph` recommendation was rejected in favor of a durable plain + `DatabaseManifest`. +- Broad contract-derived validation claims were narrowed by the pinned source audit. +- Provider re-export proposals were rejected. +- Plugin contract spaces do not independently solve removal semantics. + +The TypeScript/validation acceptance sentence must appear explicitly in the RFC, in equivalent or +stronger language: + +> Accept the native integration only if it preserves Prisma's exact contract inference without +> private imports, copied overloads, casts, or declaration widening, and accept contract-derived +> validation only where the canonical contract plus contributed codec, operation, and selection +> metadata can produce sound fail-closed Standard Schema validators; otherwise narrow or kill the +> affected layer rather than pretending parity. + +## Evidence discipline + +Keep these evidence classes visibly distinct: + +- Current NetScript source fact. +- Prisma RC1 source fact. +- Post-RC Prisma source fact. +- Official primary-source fact. +- Owner/maintainer exchange as exploratory direction, not an upstream commitment. +- Architectural inference. +- NetScript proposal. +- Conditional or unproven implementation capability. + +Pin Prisma RC1 claims to `v8.0.0-rc.1@a76a6c5`. Label post-RC observations against the audited +post-RC object `71e2e0d9ee1f306b5a11435cd1973023cb33866a`. Never present post-RC code as RC1 +behavior or RC1 behavior as a GA guarantee. + +Source-link every material external, upstream, market, maturity, release, issue, and PR claim to +primary sources. Local research reports are a claim index, not substitutes for upstream citations. +Explicitly label unknowns and implementation-time decisions. Do not turn an attractive inference +into a supported capability. + +## Template and front matter + +Follow `rfcs/0000-template.md` completely. Preserve every required top-level section: + +- Summary +- Motivation +- Guide-level explanation +- Reference-level explanation +- Drawbacks +- Rationale and alternatives +- Breaking changes and migration +- Prior art +- Unresolved questions +- Future possibilities + +Use valid draft front matter consistent with repository conventions: + +- `rfc: 0000` +- `status: Draft` +- `authors: ['@rickylabs']` +- `created: 2026-08-13` +- A precise architecture title +- Issue #313 as historical/tracking context if consistent with `rfcs/README.md` +- `Backlog / Triage` if no milestone is yet committed + +Do not omit template sections because equivalent material appears elsewhere. Add structured +subsections and appendices under them. + +## Eight-slice trace + +Map the complete RFC to all eight planned slices: + +- Slices 0–2: provenance, research, plan lock, and the passing final Plan-Gate; summarize, do not + rewrite. +- Slice 3: vocabulary, package graph, public APIs, TypeScript/E2E types, validation, operations, + spaces, targets, state machines, and refusal boundaries. +- Slice 4: adoption, clean cutover, data safety, waves, conformance, CI/JSR/release gates, market + implications, risk register, and kill/switch criteria. +- Slice 5: leave an explicit review/disposition surface for Qwen 3.8 Max and Grok 4.6 high. +- Slice 6: implementation-grade completeness review may occur later inside the fixed post-draft + review sequence, but it is not another PLAN-EVAL and must not restart planning. +- Slice 7: reserve the one final substantive refinement for Fable 5 high. + +Include a decision-trace appendix mapping every D-01–D-47 decision to its definitive RFC section. +Nothing may be silently dropped or weakened. + +Group the decisions coherently: + +- D-01–D-05: clean break, data continuity, artifact separation, no query/repository abstraction. +- D-06–D-08 and D-36: native TypeScript contract authoring, Candidate A, inference preservation, + app-local binding. +- D-09–D-16: exact packages, provider boundary, target identity, explicit selection, replicas, + static capabilities. +- D-17–D-20 and D-38–D-40: contract spaces, ownership, extension bundles, pinned artifacts, plugin + lifecycle. +- D-21–D-25: bounded Standard Schema interpretation. +- D-26–D-33: pure operations, catalog projections, preview/plan separation, control ownership, + saga/receipts, artifact generation, agent surface. +- D-34–D-35: no legacy provider parity and signed production plans. +- D-37: namespace capability withheld pending sound type/runtime parity. +- D-41–D-42: W3/provider implementation-time pin, import, and lock choices. +- D-43–D-47: explicitly deferred optional capabilities. + +## Central design narrative + +The RFC should tell one continuous story: + +```text +native authored TypeScript contracts + NetScript definitions/contributions + → pure two-phase composition + → canonical ContractArtifacts + → deterministic DatabaseManifest + → generated app-local AppBinding + → runtime sessions + bounded validators + → inspected baseline + → bound ExecutablePlan + → provider apply/ledger + → immutable OperationReceipts + → verify/recovery +``` + +Do not conflate source definition, resolved manifest, speculative preview, executable plan, provider +ledger, or receipt. + +## Native Prisma TypeScript authoring and NetScript extension layer + +This is a primary RFC axis, not a small implementation detail. + +Use the current model-first native Prisma form: + +```ts +defineContract(scaffold, (helpers) => ({ + models: {/* native Prisma definitions */}, + types: {/* native Prisma definitions */}, + enums: {/* native Prisma definitions */}, +})); +``` + +The owner's screenshot showed a real historical target/table/column fluent API, but Prisma removed +it. Do not recreate it. Do not invent a NetScript schema DSL. Do not vendor or re-export Prisma as +though NetScript owns it. + +Candidate A is mandatory as the baseline: + +```ts +const contract = defineContract(scaffold, (p) => /* native value */); + +export default defineDatabase({ + targets: { main: /* explicit target */ }, + spaces: { + app: defineDatabaseSpace({ + ownership: "app", + contract, + // owner/version/dependencies/policy + }), + }, +}); +``` + +Define exact public signatures and inference behavior for: + +- `defineDatabase` +- `defineDatabaseTarget` +- `defineDatabaseSpace` +- `defineDatabaseExtension` +- App-owned native fragments +- Plugin-owned full spaces +- Two-phase extension collection +- Const-preserving generated composition roots +- `DatabaseDefinition` +- `NativeContract` +- `SpaceContribution` +- `DatabaseExtension` +- `AppBinding` +- `TargetRef` +- `TargetSession` + +Show the oRPC precedent precisely: preserve the native upstream authoring and inferred value, then +add NetScript policy, lifecycle, ownership, artifact, and orchestration around it. Do not transfer +oRPC-specific slow-type exceptions, global builder ownership, transport concepts, or re-export +patterns. + +An optional factory survives only if it forwards exact public Prisma helpers without copied +overloads, private imports, declaration widening, or cast workarounds. State the kill criterion +directly. + +Show end-to-end type propagation from native contract to generated application-local binding, +query/session use, Standard Schema consumers, route/procedure/form boundaries, and serialization. +Published kernel packages must remain declaration-safe and provider-neutral; application-specific +inferred Prisma types remain app-local. + +## Runtime Standard Schema interpretation + +This is the other primary axis. + +Define the public API and internal boundary for runtime contract-derived Standard Schema values. +Include examples for: + +- Whole-model runtime values. +- JSON/serialized model values. +- Mutation inputs only when exact operation metadata is explicitly contributed. +- Selection/results only when aliases, codecs, nullability, and representation are fully known. +- Two independent Standard Schema consumers. + +The only public representations are: + +- `runtime` +- `json` + +Driver-wire representation remains adapter-internal. + +Specify the supported `ValidationIR` algebra: registered scalar codecs, nullability, lists, +dictionaries, value objects, resolvable unions, enums/value sets/native enums, integrity-checked +cross-space relations, whole-model presence policy, and fully known direct-column projections. + +Specify construction-time `DB_VALIDATION_UNSUPPORTED` refusal for missing or ambiguous codecs, +packs, variants, cross-space metadata, Prisma operation grammar, raw/computed/subquery/aggregate/ +include results, opaque checks, database-state constraints, incompatible async predicates, and +unknown result shapes. + +Invalid values return Standard Schema issues; unsupported schemas fail during schema construction. +Custom codecs must contribute representation-specific value schemas—encode/decode functions are not +validation. + +Define cache identity using the full canonical contract digest, schema version, space, +target/family, operation or normalized selection, representation, interpreter ABI, codec/pack +identity and version, and execution identity where defaults matter. + +Do not claim full Prisma create/update/filter/nested-write/result parity from the contract. AOT is +optional and may ship only with corpus equivalence to runtime interpretation. + +## Exact package and ownership graph + +Specify the exact graph and one archetype per unit: + +- `@netscript/database-contract` — A1 +- `@netscript/database` — A4 +- `@netscript/database-runtime` — A3 +- `@netscript/database-control` — A2 +- `@netscript/database-prisma-postgres` — A2 +- `@netscript/database-testkit` — A6, conditional on a justified binary +- Existing `@netscript/plugin` — A4 +- First-party plugins — A5 +- Existing Aspire integration — A2 +- Existing CLI — A6 + +For every package, document: + +- Owned responsibilities. +- Forbidden responsibilities. +- Dependencies and import law. +- Public versus adapter-local types. +- Runtime permissions. +- JSR/publication status. +- Archetype gates. +- Kill or split criteria. + +No framework package re-exports Prisma. Only the PostgreSQL adapter owns Prisma runtime/control +imports. Controlled app/plugin build inputs may directly import Prisma's public authoring builder. +Production apply and runtime consume canonical verified artifacts, not arbitrary schema TypeScript. + +## Public contracts and artifacts + +Provide complete TypeScript examples and field-level contract tables for: + +- Stable IDs: target, role, namespace, space, object, contract snapshot, manifest, plan, run, + receipt. +- `DatabaseDefinition` +- `NativeContract` +- `SpaceContribution` +- `ContractArtifact` +- `DatabaseManifest` +- `AppBinding` +- `TargetRef` and `TargetSession` +- `SpeculativePreview` +- `ExecutablePlan` +- `ProviderMarker` +- `ProviderLedger` +- `OperationReceipt` +- `OperationCatalog` +- Public diagnostics and results +- Internal-only `ValidationIR` + +For every durable artifact, state producer, consumer, authority, version, identity, digest inputs, +canonical encoding, persistence, atomicity, provenance, redaction, and stale/mismatch behavior. + +Define the ports with cohesive three/four-method shapes: + +- `ContractArtifactSource` and atomic publisher +- `ProviderRuntimeFactory` +- `ProviderControl` +- `ConnectionSource` +- `MigrationLock` +- `ReceiptSink` +- Clock/ID/signature policy where justified + +Provider registries are immutable composition-root data, not global registries. + +## Formal behavior + +Include formal state-transition tables or Mermaid diagrams for: + +- Pure definition composition and manifest resolution. +- Runtime process/request session lifecycle. +- Inspection, preview, plan, policy, approval/signature, readiness, expiry/staleness/revocation. +- Lock, revalidation, apply, checkpoint, verification, cancellation, and recovery. +- `outcome_unknown` inspect-before-resume. +- Dependency-ordered multi-target saga and partial success. +- Plugin install, upgrade, version skew refusal, detach, retain, conditional archive/drop. +- Extension-bundle identity/version verification. + +Define legal transitions, forbidden transitions, persistent evidence, retry/idempotency rules, +cancellation semantics, and structured diagnostics. Preview must never be applicable. Cross-target +atomicity must never be implied. + +## Targets, providers, spaces, ownership + +Cover: + +- Multiple PostgreSQL targets of the same provider. +- Explicit target selection and dependency closure. +- Roles and writer/read replicas; replicas never migrate. +- Namespaces as a kernel identity axis, while Prisma multi-namespace certification remains withheld + until no-cast type/runtime parity passes. +- App space plus independently versioned plugin spaces. +- `managed`, `adopted`, `external`, and `ignored` ownership. +- One managed owner per `ObjectKey`. +- Owner-granted augmentation only. +- Pinned mirrors that allow apply/verify without installed plugin code. +- Detach-and-retain as the only guaranteed v1 removal. +- Explicit unsupported/refusal behavior for Prisma SQLite, MongoDB, MySQL, SQL Server, cross-target + relations, and cross-target transactions. + +Do not turn the provider-neutral kernel into false portable query semantics. Native provider query +surfaces remain app-local. + +## Programmatic control, CLI, agents, and CI + +Define a typed `OperationCatalog` as the source for classify/compose/emit/preview/plan/apply/verify/ +inspect/resume operations. CLI commands, help, documentation, and agent instructions are generated +projections. + +Show programmatic and CLI journeys with machine results, human rendering, diagnostics, exit +semantics, and next actions. Every example should be executable or explicitly pseudocode pending a +W3 import pin. + +Separate: + +- `pure` +- `live-read` +- `mutating` +- `resident` + +Pure operations must not resolve connections, Aspire, Docker, secrets, or network access. + +Explain how the architecture shortens and stabilizes CI through pure compilation, canonical digests, +atomic artifacts, bounded real-service stages, reusable structured receipts, and removal of +hand-patching/repair workflows. Do not promise unmeasured CI reductions; define measurements and +release thresholds. + +## Migration, clean break, and data safety + +No backwards compatibility is allowed. + +`netscript db adopt` is a temporary migration codemod/tool, not a compatibility layer. Specify the +complete adoption protocol: + +1. Read legacy config/layout. +2. Generate explicit target identities. +3. Introspect reachable databases. +4. Propose object ownership. +5. Hard-stop on unattributed or conflicting objects. +6. Compile and atomically emit canonical artifacts. +7. Establish one baseline/root per space. +8. Write provider marker metadata only, with zero table/data DDL/DML. +9. Verify live state and zero drift. +10. Delete legacy engine workspaces, the 42 per-workspace generated `db:*` task keys, copied plugin + fragments, repair scripts, adapters, and dependencies only after verified adoption. + +Separate-branch/release-line coexistence is allowed during development, but a single application may +never compose old and new stacks. Before the first new apply, rollback is repository-only plus safe +marker cleanup. After apply, recovery is forward through lineage, provider ledger, and receipts. + +Include rehearsal, backup, ownership, destructive-consent, partial-outcome, crash, marker, secret, +lock, and release-window safety gates. + +## Market and rationale + +Use the market reports to compare NetScript against: + +- Wasp +- RedwoodJS +- Payload +- Better Auth +- AdonisJS Lucid +- Drizzle/Drizzle Kit +- MikroORM +- Kysely +- Flyway +- Liquibase +- Terraform +- Pulumi +- Atlas +- Bytebase +- ZenStack v3 +- Django +- Rails Active Record + +Do not produce a feature-list dump. Derive the architectural lessons: + +- One resolved manifest. +- Contributor-owned migration spaces. +- Native authoring with framework policy around it. +- Apply-bound plans. +- Managed versus external ownership. +- Capability-specific behavior instead of false portability. +- Programmatic core with CLI/agent projections. +- Separate source, manifest, plan, ledger, and receipt. + +State clearly what a local meta-framework must not rebuild: hosted RBAC, organization/fleet +management, remote registry, policy SaaS, approval service, or continuous-drift control plane. + +Explain alternatives rejected: Prisma 7 compatibility, one-to-one migration, a proprietary schema +DSL, recreating the deleted fluent builder, live graph/service locator, global mutable provider +registry, provider re-export, portable query client, generated validator parity claims, plugin +fragment copying, CLI as business logic, and hosted-control-plane creep. + +## Implementation and release plan + +Carry W0–W11 into the RFC with dependencies and exit evidence: + +- W0 RFC/doctrine preparation +- W1 contract kernel +- W2 pure definition/compiler +- W3 experimental Prisma PostgreSQL spike +- W4 A3 runtime +- W5 A2 control +- W6 conformance testkit +- W7 plugin seam +- W8 CLI/agent/adoption +- W9 first-party spaces +- W10 clean cutover +- W11 second provider only with real demand and maturity + +Include the exhaustive conformance matrix: + +- Archetype F-1…F-19 requirements. +- A3 lifecycle/leak/cancellation/scope gates. +- Real PostgreSQL, Deno, provider import allowlist, and exact single Prisma component set. +- Literal-type preservation and no-cast/private-import checks. +- Namespace type/runtime parity. +- Standard Schema runtime/JSON corpus and two consumers. +- Extension facet identity. +- Target/space/namespace isolation. +- Failure injection, lock, crash, unknown-outcome, and resume. +- Ownership/removal. +- Deterministic/atomic artifact production. +- Generated example/catalog freshness. +- Generated-project and `scaffold.runtime` journeys. +- Windows/Linux and release-class adoption rehearsal. + +Reflect the prospective JSR result honestly: `PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`. The +packages do not exist, so dry-run, doc lint, packed install, canary, and remote consumer results are +currently N/A. + +Specify implementation-time: + +- Explicit export maps and include lists. +- Stable JSDoc/module docs/examples. +- Isolated declarations. +- No slow-types waiver. +- `deno doc --lint`. +- `deno publish --dry-run`. +- Publish-list inspection. +- Packed clean consumer. +- `quality:scan` and `arch:check`. +- Generated asset freshness. +- OIDC/SLSA canary and exact-version remote E2E at W10. + +## Risks, kill criteria, and unknowns + +Carry the complete risk register and mitigation/kill response into the RFC. Explicitly distinguish: + +- Locked semantics. +- W1/W3/W4/W5/W7/W10 implementation decisions. +- Conditional upstream blockers. +- Safe deferred capabilities. + +No must-resolve-now architecture question may be reintroduced casually. If source inspection reveals +a genuine contradiction, report it to the root, narrow the capability, and continue unless it +invalidates the package boundary. + +Never silently widen support. In particular, do not claim: + +- Prisma 8 GA stability from RC1. +- Non-PostgreSQL certification. +- Multi-namespace soundness. +- Full operation/result validation from contract data. +- Archive/drop safety. +- Cross-database relations or transactions. +- Runtime capability negotiation. +- AOT validation. +- Hosted control-plane behavior. +- Actual JSR publish readiness. + +Include decisive subsystem and provider kill/switch criteria. Preserve the provider-neutral kernel +if the Prisma adapter fails; narrow validation rather than recreating Prisma's type system; withhold +unsupported capabilities instead of casting around them. + +## Expected depth + +This must be a substantial architectural RFC, not a polished summary of the plan. Expect roughly +18,000–30,000 coherent words, or comparable implementation-grade depth. Word count is not a quota: +prefer one consistent model, precise tables, complete examples, explicit invariants, and +traceability over repetition. It should be materially deeper than a typical 5–10 page proposal while +remaining readable from guide-level DX through reference-level mechanics. + +Avoid copying the synthesis section-by-section. Re-author it as one narrative, eliminate +duplication, and use appendices for decision/source/conformance trace tables. + +## Fixed post-draft process + +After the complete draft, the sequence is exactly: + +1. Root performs a personal substantive source/doctrine/API review. +2. Qwen 3.8 Max performs the focused review across TypeScript inference, Standard Schema, + control/recovery, migration safety, package/JSR surfaces, and market claims. +3. Grok 4.6 high performs the whole-RFC adversarial review. +4. The author/editor explicitly dispositions findings and revises the RFC. +5. One Fable 5 high session performs the absolute final substantive review and refinement. + +There is no generic additional focused-review party and there are no more PLAN-EVAL loops. Nothing +substantive follows the final Fable 5 high refinement; only mechanical checks and publication +actions may follow. + +## Final checks for this authoring session + +Before handing back the draft: + +- Verify every template heading and valid front matter. +- Produce a D-01–D-47 section trace. +- Produce a requirement/source/claim trace for load-bearing facts. +- Search for contradictions between RC1, post-RC, and proposals. +- Search for accidental compatibility, Prisma 7 fallback, provider re-export, full-validation, + namespace, non-PostgreSQL, or hosted-control-plane overclaims. +- Check local links and referenced paths. +- Check for placeholders, invented import paths, unsupported capability claims, and stale + 30-task/~275-export claims. +- Run `deno fmt --check rfcs/0000-database-architecture.md`. +- Run `git diff --check`. +- Report the RFC size/line count, coverage, explicit unknowns, and check results. + +Do not commit or push. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval-cycle-2.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval-cycle-2.md new file mode 100644 index 0000000000..1ecd8047b4 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval-cycle-2.md @@ -0,0 +1,97 @@ +use harness + +# Formal PLAN-EVAL Cycle 2 — NetScript Database Architecture / Prisma 8 RFC + +You are the fresh, separate formal PLAN-EVAL evaluator for run +`docs-database-architecture-rfc--prisma-8-rfc`. You did not author the research, plan, or cycle 1 +correction. Be adversarial, evidence-led, and independent. This is PLAN-EVAL only: judge the locked +plan, never author the RFC, evaluate implementation that does not exist, or soften the harness +checklist. + +## Route and identity + +- Required route: native Claude Code, `claude-fable-5`, effort `medium`. +- Record the observed model, effort, fresh session ID, date, worktree, branch, and evaluated commit. +- Evaluated worktree: `/home/codex/repos/netscript-db-rfc`. +- Evaluated branch/head: `docs/database-architecture-rfc` at `383170bbc` + (`docs(rfc): record plan evaluation correction`). +- This session must be new and separate from cycle 1 (`dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`), the + Codex supervisor, Opus research lane, Qwen review, and every delegated research/synthesis agent. + +## Cycle 1 context — verify, do not assume + +Cycle 1 evaluated commit `3cbcfcec8` and returned `FAIL_PLAN`. Seven Plan-Gate boxes passed; the +only required fix was a copied claim that generated workspaces contained exactly 30 `db:*` task +keys. The evaluator executed `generateDatabaseDenoJson` for PostgreSQL, SQLite, MySQL, and MSSQL and +found 42 keys in every generated engine workspace. Commit `383170bbc` corrected the mutable +rebaseline, synthesis, and plan records; dispositioned Qwen F3 as an incorrect correction; and +preserved the cycle 1 artifact and independent model outputs as audit evidence. + +Read the current `plan-eval.md` before replacing it. Independently verify that the required fix is +complete and does not introduce ambiguity such as treating 42 as a cross-workspace total. Then run +the **entire** Plan-Gate again. A corrected cycle-1 finding is not by itself grounds for PASS. + +## Mandatory harness inputs, in this order + +1. `.llm/harness/gates/plan-gate.md` +2. `.llm/harness/evaluator/plan-protocol.md` +3. `.llm/harness/evaluator/verdict-definitions.md` +4. `.llm/harness/templates/plan-eval.md` +5. Run files: `research.md`, `plan.md`, `supervisor.md`, `drift.md`, and the complete `## Design` + section of `worklog.md` under `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/`. +6. Detailed synthesis and planned publish audit: `research/architecture-plan-synthesis.md` and + `research/planned-jsr-audit.md`. +7. Every other report linked by run-root `research.md`; challenge load-bearing claims and conflict + resolutions rather than trusting the synthesis. +8. `.llm/harness/archetypes/SCOPE-docs.md`, `.llm/harness/gates/archetype-gate-matrix.md`, the + applicable A1/A2/A3/A4/A5/A6 archetype profiles, and the doctrine files cited in the plan. +9. `.llm/harness/debt/arch-debt.md` entries relevant to database, Prisma, plugin schema, generation, + and Aspire coupling. +10. Repo `AGENTS.md`, `rfcs/README.md`, and `rfcs/0000-template.md` where they constrain the plan. + +## Mandatory procedure + +- Confirm run-root `research.md` is explicitly rebaselined to + `cd720529333328bcba5e1a308ce7632f4350efdf`. Fetch/inspect current `origin/main`: if it has + advanced, state the exact delta and independently decide whether it invalidates any research, + plan, archetype, gate, or RFC-authoring premise. Do not call drift irrelevant without evidence. +- Re-execute or otherwise independently prove the 42-per-workspace correction across all four + providers, and verify every mutable false-count occurrence was corrected while immutable evidence + was explicitly superseded. +- Spot-check at least three other load-bearing findings against the actual tree, including one + current NetScript fact, one pinned Prisma RC/current-source fact, and one doctrine/JSR/package- + boundary fact. Record exact paths/lines or commits. +- Walk every Plan-Gate checkbox individually and cite the exact plan/research/worklog location that + satisfies it, or mark it failed. +- Run your own open-decision sweep. Any decision still open that could force rework is an automatic + failed checkbox, even if the plan labels it deferred. +- Verify all D-01 through D-47 exist and classifications are coherent; specifically attack D-35, + D-37, D-41, and D-42 to decide whether their deferral is safe. +- Verify there are fewer than 30 ordered commit slices and each names proof, gate, and files. +- Verify the exact future package graph assigns one archetype per unit, includes A3 runtime gates, + and does not allow a provider/query/slow-type dependency leak. +- Apply the planned JSR requirement honestly: planned packages do not exist, so dry-run/doc/packed + results must be N/A now; decide whether the prospective audit names sufficient implementation + mitigations. +- Challenge the clean-break/data-safety boundary, native Prisma TypeScript builder strategy, + app-local E2E inference, bounded fail-closed runtime validation, plugin ownership/removal, + multi-target/provider claims, operation/receipt recovery, implementation waves, and absolute-final + Fable ordering. +- Confirm the canonical RFC file `rfcs/0000-database-architecture.md` is absent. Its absence is + correct before PASS. + +## Verdict and output contract + +Replace exactly one evaluator artifact using the harness template at: + +`/home/codex/repos/netscript-db-rfc/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md` + +The cycle 1 version is preserved in commit `383170bbc`; summarize its disposition in the cycle 2 +artifact. Emit exactly one verdict: + +- `PASS` only if every Plan-Gate box is satisfied and no rework-forcing decision remains. +- `FAIL_PLAN` otherwise, with numbered, severity-tagged, actionable required fixes and exact + file/line evidence. This is the second allowed failure cycle, so be especially explicit. + +Do not edit any other file. Do not create the RFC. Do not commit or push. End the artifact with +exactly `PLAN-EVAL: PASS` or `PLAN-EVAL: FAIL_PLAN`, and end your turn immediately after writing it. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index 870694d089..e8240b94b9 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -6,15 +6,17 @@ | -------------- | ------------------------------------------------------- | | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | -| Current phase | `research` | -| Archetype | Docs-only RFC describing future A1/A2/A4/A5/A6 surfaces | +| Current phase | `rfc-authoring` | +| Archetype | Docs-only RFC describing future A1/A4/A3/A2/A2/A6 graph | | Scope overlays | `SCOPE-docs.md` | ## Current State -A clean-break database architecture RFC run is activated from current `origin/main`. Issue #313 is -carried in as historical evidence but its compatibility-first solution is explicitly superseded. The -canonical RFC has not been authored; research and PLAN-EVAL come first. +A clean-break database architecture RFC run is active. Issue #313 is historical evidence; its +compatibility-first solution is superseded. Native Fable 5 medium PLAN-EVAL cycle 2 session +`f3286656-7d0f-4da2-a22d-32897a5e6482` passed commit `383170bbc`. Canonical RFC authorship is +unblocked but not yet complete. Current-main commit `01e096049` is recorded as nonblocking +CI/gate-tooling drift. ## Completed @@ -22,28 +24,32 @@ canonical RFC has not been authored; research and PLAN-EVAL come first. - Created an isolated worktree/branch from `origin/main` @ `cd7205293`. - Read GitHub issue #313 and its comments through the connected GitHub surface. - Selected mandatory PLAN-EVAL and the owner-directed Fable 5 high final refinement override. +- Completed the research corpus, D-01–D-47 lock, prospective JSR audit, and architecture synthesis. +- Preserved cycle 1 `FAIL_PLAN`, corrected the task finding to 42 keys per generated engine + workspace, and obtained cycle 2 `PASS`. ## In Progress -- Claude Code Opus 5 high independent architecture deep dive, followed by plan synthesis and the - separate formal PLAN-EVAL. +- Slice 3 canonical RFC authorship from the evaluator-approved architecture. ## Next Steps -1. Publish the bootstrap review surface. -2. Audit current NetScript DB code, generated assets, public APIs, CI, issues, and debt. -3. Audit Prisma 8/Next primary sources and market prior art. -4. Incorporate the owner-directed Claude Opus 5 high independent report. -5. Lock architecture and Design checkpoint, then obtain PLAN-EVAL PASS. -6. Author and evaluate the RFC. +1. Author the complete canonical RFC from D-01–D-47 and the W0–W11 implementation waves. +2. Perform the root personal source/doctrine/architecture review. +3. Run Qwen 3.8 Max as the focused post-draft review. +4. Run Grok 4.6 high as the whole-RFC adversarial review. +5. Apply author/editor dispositions for every actionable finding. +6. Run one final Fable 5 high substantive refinement. +7. Run mechanical checks only, then commit/push and update the PR trail. ## Key Decisions -| Decision | Source | Notes | -| ------------------------------ | --------------- | ----------------------------------------------------------------------------- | -| No backward compatibility | Owner directive | Migration safety is required; runtime compatibility shims are not. | -| NetScript owns its DB concepts | Initial plan | Prisma remains an adapter/engine target, not the framework-facing vocabulary. | -| Fable 5 high is last | Owner directive | Final gate includes refinement, not only critique. | +| Decision | Source | Notes | +| ------------------------------ | --------------- | -------------------------------------------------------------------------------------------------- | +| No backward compatibility | Owner directive | Migration safety is required; runtime compatibility shims are not. | +| NetScript owns its DB concepts | Initial plan | Prisma remains an adapter/engine target, not the framework-facing vocabulary. | +| Exact future package graph | Plan lock | A1 contract → A4 definition → A3 runtime → A2 control → A2 Prisma PostgreSQL adapter → A6 testkit. | +| Fable 5 high is last | Owner directive | Final gate includes refinement, not only critique. | ## Files Changed @@ -53,16 +59,17 @@ canonical RFC has not been authored; research and PLAN-EVAL come first. ## Gates -| Gate family | Current status | Evidence | -| ----------- | -------------- | ----------------------------------- | -| Static | pending | Bootstrap inspection follows. | -| Fitness | pending | Research/archetype mapping follows. | -| Runtime | N/A | Docs-only RFC run. | -| Consumer | pending | RFC not authored. | +| Gate family | Current status | Evidence | +| ----------- | -------------- | ---------------------------------- | +| Static | pending | Bootstrap inspection follows. | +| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | +| Runtime | N/A | Docs-only RFC run. | +| Consumer | in progress | RFC authorship unblocked. | ## Open Questions -- All public architecture decisions remain open until research is complete. +- No must-resolve-now architecture decision remains; pre-implementation decisions stay assigned to + their W1/W3/W4/W5/W7/W10 gates. ## Drift and Debt diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md index 6b6e647e47..75a68fee5b 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md @@ -1,180 +1,195 @@ -# PLAN-EVAL — docs-database-architecture-rfc--prisma-8-rfc +# PLAN-EVAL — docs-database-architecture-rfc--prisma-8-rfc (cycle 2) - Plan evaluator session: native Claude Code, observed model `claude-fable-5`, effort `medium`, - session `dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`, 2026-08-13 (UTC) + session `f3286656-7d0f-4da2-a22d-32897a5e6482`, 2026-08-13 (UTC) - Route: matches the required lane (`formal_plan_evaluation` — Anthropic · Fable 5 · medium); fresh - session, separate from the Codex supervisor, Opus research lane, Qwen review, and all delegated - research/synthesis agents + session, separate from cycle 1 (`dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`), the Codex supervisor, the + Opus research lane, the Qwen review, and every delegated research/synthesis agent - Run: `docs-database-architecture-rfc--prisma-8-rfc` - Worktree: `/home/codex/repos/netscript-db-rfc` -- Branch / evaluated commit: `docs/database-architecture-rfc` @ `3cbcfcec8` - (`docs(rfc): lock database architecture plan`) +- Branch / evaluated commit: `docs/database-architecture-rfc` @ `383170bbc` + (`docs(rfc): record plan evaluation correction`) - Surface / archetype: docs-only RFC plan under `SCOPE-docs.md`, describing future A1/A2/A3/A4/A5/A6 surfaces - Scope overlays: `SCOPE-docs.md`; future packages evaluated against `gates/archetype-gate-matrix.md` - Canonical RFC file `rfcs/0000-database-architecture.md`: **absent — correct** (verified by listing - `rfcs/`; only `0000-template.md`, `0001`–`0005`, `README.md` exist) - -## Rebaseline verification - -- `research.md` lines 4–9 explicitly rebaseline to - `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf`, date 2026-08-13, with Prisma pins RC1 - `a76a6c5` and post-RC object `71e2e0d9…`. Verified: `cd720529` is an ancestor of HEAD and of - `origin/main`; the pinned Prisma checkout at `.llm/tmp/prisma-v8-rc1` resolves HEAD + `rfcs/`; only `0000-template.md`, `0001`–`0005`, `README.md` exist). The planned draft filename + matches the RFC process rule "keep `0000` while drafting" (`rfcs/README.md` § Lifecycle). + +## Cycle 1 disposition + +Cycle 1 (session `dd3cfbee`, evaluated commit `3cbcfcec8`) returned `FAIL_PLAN` with seven passing +boxes and one required fix: the load-bearing claim of exactly 30 generated `db:*` tasks, copied from +the Qwen independent report into `research.md`, the synthesis, and `plan.md`. The cycle 1 artifact +is preserved in commit `383170bbc` (which added it alongside the corrections) and remains audit +evidence; this file replaces it as the current verdict per the harness single-artifact contract. + +## Required-fix verification (independent) + +- **Re-executed the generator myself at head `383170bbc`.** A scratch Deno script imported + `generateDatabaseDenoJson` from + `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` and each of + `postgresProvider`, `sqliteProvider`, `mysqlProvider`, `mssqlProvider` from + `packages/cli/src/kernel/adapters/database/providers/database-providers.ts`, generated each + workspace `deno.json`, and counted keys starting with `db:`. Result: **postgres 42, sqlite 42, + mysql 42, mssql 42** — the corrected value is independently confirmed. +- **Every mutable occurrence is corrected, with no cross-workspace ambiguity.** Swept the run dir + for `exactly 30`/`30 db:`/`30 task`/`30 unique`: the only remaining occurrences are (a) the + immutable Qwen report (`research/qwen-prisma-risk-review.md:64,297`), (b) the immutable Opus + review (`claude-opus-architecture-review.md:1710,1978`) and brief + (`briefs/claude-opus-report-part-2.md:34`), and (c) the preserved cycle 1 artifact itself. The + mutable records all carry the executed result phrased per-workspace, not as a total: + `research.md:34-35` ("42 `db:*` task keys in every generated engine workspace"), + `architecture-plan-synthesis.md:70` and `:682` ("42 `db:*` task keys in every generated engine + workspace" / "the 42 per-workspace generated `db:*` task keys"), and `plan.md:310` ("the 42 + per-workspace generated `db:*` task keys"). +- **Qwen F3 is dispositioned as an incorrect correction** in `research.md:61-67` ("Corrections and + conflict resolutions"), the same way the ~275-export claim was dispositioned, and the copied + premise in the immutable Opus review/briefs is explicitly marked non-authoritative there. +- **The correction commit is properly scoped.** `383170bbc` modified only the mutable records + (`plan.md`, `research.md`, `architecture-plan-synthesis.md`, `supervisor.md`, `worklog.md`) and + added the preserved evaluator artifact/brief; no independent model report was edited + (`git show --name-status 383170bbc`). + +## Rebaseline and drift verification + +- `research.md:4-9` explicitly rebaselines to `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` + with Prisma pins RC1 `a76a6c5` and post-RC object `71e2e0d9…`. Verified: `cd720529` is an ancestor + of HEAD; the pinned checkout at `.llm/tmp/prisma-v8-rc1` resolves HEAD `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` and `git cat-file -t 71e2e0d9…` returns `commit`. -- Note (non-blocking): `origin/main` has since advanced by exactly one commit, - `01e096049 ci: adopt structured check reports (#1639)`. The delta touches CI/check-report tooling - only (no `packages/database`, no scaffold DB templates, no doctrine). The plan already commits to - "a fresh pin check during RFC drafting" (plan.md § Dependencies and Drift Watch), which covers - this. - -## Spot-checks of load-bearing findings +- Fetched `origin/main`: it has advanced by **exactly one commit**, + `01e096049 ci: adopt structured check reports (#1639)`. I inspected its full file list and the + diffs to the two database-adjacent files it touches: + `packages/cli/e2e/src/application/gates/ + scaffold/database-gates.ts` changes only how the E2E + suite invokes generated-workspace type checks (gate mechanics, not scaffold output), and root + `deno.json` changes wrapper permission flags for structured check reports. It touches no + `packages/database`, no `packages/cli/src/kernel/adapters|templates/database`, no doctrine, no + `rfcs/`. It invalidates no research, plan, archetype, gate, or RFC-authoring premise; the plan's + committed "fresh pin check during RFC drafting" (plan.md § Dependencies and Drift Watch) covers + residual drift. **Non-blocking.** + +## Spot-checks of load-bearing findings (this cycle's independent set) 1. **Current NetScript facts.** - - `resolveTarget` ignores `PrimaryDatabase` and only defaults with exactly one enabled target — - **confirmed** at `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66-86`. - - AP-17 `interfaces/` rename debt for `packages/database` is stale — **confirmed**: - `packages/database/ports/` exists (no `interfaces/`) while the debt entry at - `.llm/harness/debt/arch-debt.md:316-324` remains open and still says "`interfaces/` should - become `ports/`". The composition-root half of the entry remains live, as the plan states. - - `DB-GENERATE-ASPIRE-COUPLING` is open — **confirmed** at - `.llm/harness/debt/arch-debt.md:1954-1990` (status: open; `DbOperationRunner.executeDetached` - always boots Aspire). - - Root catalog uses caret `^7.8.0` while generated templates use `^7.4.2` — **confirmed** - (`deno.json:231-235`; `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` - lines 36, 59, 122-124). - - **"the generated workspace has exactly 30 `db:*` tasks" — REFUTED.** I executed - `generateDatabaseDenoJson` from - `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` at the evaluated head for - all four providers (`postgresProvider`, `sqliteProvider`, `mysqlProvider`, `mssqlProvider`): - every engine emits **42** `db:*` task keys, not 30. The Qwen "correction" - (`research/qwen-prisma-risk-review.md:64`, F3: "Exactly 30 unique `db:*` tasks") undercounts by - omitting the twelve computed per-engine keys (`db::${provider.engine}`); its own inclusion - list (14 base ops + 12 `:all` variants + `format`/`zod`/`patch-client`/`fix-zod`) sums to 30 - only without them. The original current-state claim "more than twenty database tasks" - (`research/netscript-current-state.md:174`) was accurate. The false count was adopted as a - rebaselined load-bearing finding in `research.md:34` (finding 2), restated as **[FACT]** in - `research/architecture-plan-synthesis.md:70` and repeated at - `architecture-plan-synthesis.md:681`, and copied into the plan itself at plan.md § Clean - Cutover ("deletes the old engine workspaces, 30 tasks, …"). See Required fixes. + - `resolveTarget` defaults only with exactly one enabled target and never consults + `PrimaryDatabase` — confirmed at + `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66-91` (matching on + `configKey`/`databaseName` only; zero `PrimaryDatabase` references in the file). + - Plugin schema contribution is file copy plus regex declaration scanning — confirmed: + `packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts:13` defines the + `model|enum|type|view` header regex; `prisma-schema-writer.ts:19,100-122` performs the + collision check by scanned declaration name (research finding 3). + - Generated templates pin `npm:prisma@^7.4.2` (`generate-db-deno-json.ts:36,56,59,61,67`) while + the root catalog pins `@prisma/*` at `^7.8.0` (`deno.json:231-236`) — the version-skew claim + holds. + - AP-17 debt is stale on its rename half — `packages/database/ports/` exists while + `.llm/harness/debt/arch-debt.md:316-324` still says "`interfaces/` should become `ports/`"; + `DB-GENERATE-ASPIRE-COUPLING` remains open at `arch-debt.md:1954` and describes + `DbOperationRunner.executeDetached` always booting Aspire — matching the plan's doctrine/debt + section and D-26. 2. **Pinned Prisma RC/current-source facts.** - - Model-first authoring (D-06/D-36): **confirmed** — + - Model-first authoring (D-06/D-36): confirmed at `.llm/tmp/prisma-v8-rc1/packages/3-extensions/postgres/src/contract/define-contract.ts:91-105` - is `defineContract(scaffold, (helpers: ComposedAuthoringHelpers<…>) => { types/models/enums })` - with `const` generics preserving literal return types; no fluent target/table/column chain. - - Namespace type-map flattening (D-37): **confirmed** — - `.llm/tmp/prisma-v8-rc1/packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-690`: - comments state "the authoring path lumps every model under the default storage namespace"; - non-default namespaces receive `entries.table: Record` (empty). The audit's cited - line ranges (`typescript-schema-orpc-audit.md:629-645`) match. Withholding the `multiNamespace` - capability claim is well-founded. - - `@prisma/orm-postgres` 138 top-level export keys: pinned to the run's own audit - (`research/prisma-8-deep-dive.md:98`), correcting Qwen's ~275; direction and provenance - consistent. + — `defineContract(scaffold, factory)` with `const` generics preserving literal + types/models/enums; no fluent target/table/column chain. + - Namespace type-map flattening (D-37): confirmed at + `.llm/tmp/prisma-v8-rc1/packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691` — + comments state the authoring path "lumps every model under the default storage namespace", and + non-default namespaces receive `entries.table: Record`. Withholding the + multi-namespace capability claim is well-founded. + - `@prisma/orm-postgres` export breadth: counted `Object.keys(exports)` of + `packages/9-public/@prisma/orm-postgres/package.json` at the pin — **138**, matching + `prisma-8-deep-dive.md:98` and the synthesis's correction of Qwen's ~275. 3. **Doctrine / JSR / package-boundary facts.** - - `isolatedDeclarations: true` — **confirmed** at root `deno.json:174`. - - Slow-type exception is sanctioned only for oRPC-bound packages — **confirmed** at - `docs/architecture/doctrine/02-public-surface.md:217-239`; the plan/JSR audit's rule that no - database package inherits it is consistent. - - Doctrine codifies plain `*.prisma` plugin fragments and does not register the proposed packages - — **confirmed**: `docs/architecture/doctrine/06-archetypes.md:209`; zero hits for - `database-contract|database-runtime|database-control` in `06-archetypes.md` and - `10-codebase-verdict-and-handoff.md`. The plan's W0 doctrine-amendment obligation is correct. + - `isolatedDeclarations: true` at root `deno.json:174`. + - Slow-type exception is sanctioned only for oRPC-bound packages + (`docs/architecture/doctrine/02-public-surface.md:217-240`); the planned JSR audit's rule that + no database package inherits it (`planned-jsr-audit.md:41-45`) is consistent. + - Doctrine codifies plain `*.prisma` plugin fragments (`06-archetypes.md:209-211`) and contains + zero references to `database-contract|database-runtime|database-control` in `06-archetypes.md` + or `10-codebase-verdict-and-handoff.md` — the plan's W0 doctrine-amendment obligation is + correct and required. ## Checklist results -| Plan-Gate item | Result | Evidence / location | -| --------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Research present and current | **FAIL** | `research.md` exists, is explicitly rebaselined to `cd720529` with pinned Prisma sources, and #313 is rebaselined as historical evidence only — but load-bearing finding 2 (`research.md:34`, "exactly 30 `db:*` tasks") is false at the pinned baseline (actual: 42 per engine, generator executed), and it was copied unverified from the Qwen independent report into research.md, the synthesis ([FACT] at `architecture-plan-synthesis.md:70`), and plan.md § Clean Cutover — violating the plan's own gate "corrected claims are not copied from independent reports" (plan.md § Plan and research gates). | -| Decisions locked | PASS | plan.md § Locked Decision Ledger D-01–D-47 with rationale columns; expanded rationale in `architecture-plan-synthesis.md` §13. | -| Open-decision sweep | PASS | plan.md § Open-Decision Sweep (must-resolve-now: none; per-wave items W1/W3/W4/W5/W7/W10; safe-to-defer list). My independent sweep (below) found no unflagged rework-forcing decision. | -| Commit slices (< 30, gate + files each) | PASS | plan.md § RFC Commit Slices: eight ordered slices (0–7), each naming what it proves, its gate, and its files; mirrored in `worklog.md` § Commit Slices. | -| Risk register | PASS | plan.md § Risk Register: 20 risks each with mitigation/kill response; § Kill and Switch Criteria adds adapter/subsystem/architecture kill tiers. | -| Gate set selected | PASS | plan.md § Gate Set: current docs/RFC gates match the `SCOPE-docs.md` overlay (source alignment, link integrity, terminology, drift log, fmt/diff); future units mapped to F-1…F-19 per `gates/archetype-gate-matrix.md`, A3 runtime gates required, A5 parity, A6 F-CLI family, release-gate class (`scaffold.runtime`, `e2e-cli-prod`) at W10. | -| Deferred scope explicit | PASS | plan.md § Deferred Implementation Scope and § Open-Decision Sweep "Safe to defer"; non-scope/refusal boundary in § Non-Scope. | -| jsr-audit surface scan (pkg/plugin) | PASS | `research/planned-jsr-audit.md`: verdict `PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`; dry-run/doc-lint/packed/canary honestly `N/A` because the six packages do not exist (plan.md § Prospective JSR gates; worklog § Prospective JSR Verdict). Named risks (slow types, re-export, self-import, generated assets, duplicate Prisma components) each map to W1–W10 gates and kill criteria. | +| Plan-Gate item | Result | Evidence / location | +| --------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Research present and current | PASS | `research.md` exists, rebaselined to `cd720529` with pinned Prisma sources; #313 carried as historical evidence only; the cycle 1 false count is corrected to the executed 42-per-workspace result in every mutable record, with Qwen F3 dispositioned (`research.md:61-67`); the one-commit main delta is CI/gate tooling and invalidates nothing. | +| Decisions locked | PASS | plan.md § Locked Decision Ledger D-01–D-47 with rationale; expanded rationale in `architecture-plan-synthesis.md` §13; the two tables are coherent (statuses match; no contradiction found). | +| Open-decision sweep | PASS | plan.md § Open-Decision Sweep (must-resolve-now: none; per-wave W1/W3/W4/W5/W7/W10 items; safe-to-defer list). My independent sweep (below) found no unflagged rework-forcing decision. | +| Commit slices (< 30, gate + files each) | PASS | plan.md § RFC Commit Slices: eight ordered slices (0–7), each naming what it proves, its gate, and its files; mirrored in `worklog.md` § Commit Slices. | +| Risk register | PASS | plan.md § Risk Register: 20 risks each with mitigation/kill response; § Kill and Switch Criteria adds adapter/subsystem/architecture kill tiers. | +| Gate set selected | PASS | plan.md § Gate Set: current docs/RFC gates match `SCOPE-docs.md` (source alignment, link integrity, terminology, drift log, fmt/diff); future units mapped to F-1…F-19 per `gates/archetype-gate-matrix.md`; A3 runtime gates required (matrix: F-13 + runtime/Aspire validation required for Arch 3); release-gate class at W10. | +| Deferred scope explicit | PASS | plan.md § Deferred Implementation Scope, § Open-Decision Sweep "Safe to defer", and the § Non-Scope refusal boundary. | +| jsr-audit surface scan (pkg/plugin) | PASS | `research/planned-jsr-audit.md`: verdict `PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`; dry-run/doc-lint/packed/canary honestly **N/A** because the six packages do not exist; named risks (slow types, re-export, self-import, generated assets, duplicate Prisma components) each map to W1–W10 gates and kill criteria. | ## Directed challenges (per evaluator brief) -- **D-35 (production plan signatures, W5/W10).** Public semantics are locked (`ExecutablePlan` is a - signed/versioned value; plan-status vocabulary includes approved/signed; production requires a - signature). Only mechanism/algorithm/key custody is deferred, and W1 locks - manifest/digest-encoding format-versioning first, so a later custody choice cannot rewrite package +- **D-35 (production plan signatures, W5/W10).** Public semantics are locked: `ExecutablePlan` is a + signed/versioned value, the plan-status vocabulary includes approved/signature states, and + signature policy enters only through an explicit port ("Clock/ID/signature policy" in the + consumed-ports list). Only mechanism/algorithm/key custody is deferred, and W1 locks + manifest/digest format-versioning first, so a later custody choice cannot rewrite package boundaries. **Deferral safe.** -- **D-37 (multi-namespace withheld).** Verified against pinned source (above). The kernel keeps - `NamespaceRef` as a first-class axis; only the adapter's capability claim is withheld, with an - explicit no-cast rule and a conformance gate. If upstream never fixes it, the kernel carries an - unused axis — no rework. **Conditional classification correct.** +- **D-37 (multi-namespace withheld).** Independently re-verified against the pinned source (above). + The kernel keeps `NamespaceRef` as a first-class identity axis; only the adapter capability claim + is withheld, with an explicit no-cast rule and a conformance parity gate. If upstream never fixes + the flattening, the kernel carries an unused axis — no rework. **Conditional classification + correct.** - **D-41 (Prisma import allowlist/compat window, W3).** Adapter-local by construction: the - dependency law keeps every kernel package Prisma-free, the adapter stays experimental/unpublished - until W3 gates pass, and the kill criteria keep W1–W2 valid if the adapter dies. Post-RC path - churn is documented (`prisma-8-deep-dive.md` "Six days of post-RC churn"), which is precisely why - pinning now would be designing to a moving surface. **Deferral safe.** + dependency law keeps every kernel package Prisma-free, the adapter stays experimental until W3 + gates pass, and the kill criteria keep W1–W2 valid if the adapter dies. Post-RC path churn is + documented (`prisma-8-deep-dive.md` § "Six days of post-RC churn"), which is exactly why pinning + the spelling now would design to a moving surface. **Deferral safe.** - **D-42 (advisory vs fenced-row lock).** Public lock semantics (owner, nonce, fencing evidence - where used, timeout, force-unlock preconditions, refusal of uncertified adapters for + where used, timeout/force-unlock preconditions, refusal of uncertified adapters for concurrent-safe apply) are locked; only the per-provider mechanism is conformance-driven. **Deferral safe.** - **D-01–D-47 existence/coherence.** All 47 present in plan.md § Locked Decision Ledger; classifications match `architecture-plan-synthesis.md` §13 (Locked / Pre-implementation W3–W10 / - Conditional / Deferred). No contradiction found between the ledger, the open-decision sweep, and - the wave exits. + Conditional / Deferred) line for line. No contradiction between ledger, open-decision sweep, and + wave exits. - **Package graph.** Each unit has exactly one archetype; runtime is explicitly A3 with required - runtime gates (matrix: F-13 + runtime/Aspire validation required for Arch 3). The dependency law - forbids kernel→provider imports; concrete Prisma types are adapter-local; app-specific inferred - bindings are generated app-local (consistent with `isolatedDeclarations` and the oRPC-only - slow-type exception). No provider/query/slow-type leak path found. The testkit A6-vs-subpath - question is explicitly bounded ("reconsider before W1"), pre-publication, and cannot rework other - units. + runtime gates. The dependency law forbids kernel→provider imports; concrete Prisma types are + adapter-local; app-specific inferred bindings are generated app-local, consistent with + `isolatedDeclarations` and the oRPC-only slow-type exception. No provider/query/slow-type leak + path found. The testkit A6-vs-subpath question is explicitly bounded ("reconsider before W1"), + pre-publication, and cannot rework other units. - **Clean-break/data-safety, builder strategy, validation, lifecycle, recovery, waves, ordering.** - Adoption is marker-only (zero DDL/DML) with hard-stop on unattributed objects, rehearsal gate, and - forward-only recovery after first apply; the native-builder strategy matches the pinned source; - validation is bounded with enumerated fail-closed cases and construction-time refusal; plugin - removal guarantees only detach-and-retain; multi-target apply is a saga with `outcome_unknown` and + Adoption is marker-only (zero DDL/DML) with hard-stop on unattributed objects, a seeded + production-shaped rehearsal gate, and forward-only recovery after first apply (synthesis §11); the + native-builder strategy matches the pinned source; validation is bounded with enumerated + fail-closed `DB_VALIDATION_UNSUPPORTED` cases and construction-time refusal; plugin removal + guarantees only detach-and-retain; multi-target apply is a saga with `outcome-unknown` and inspect-before-resume; W0–W11 have explicit dependencies and exit evidence; slice 7 keeps owner-directed Fable 5 high as the absolute last substantive gate with only mechanical checks - after. All coherent; no unstated open decision found. + after. Coherent; no unstated open decision found. ## Open-decision sweep (evaluator-run) No unflagged decision that would force rework if deferred. Candidates examined and dismissed: testkit package-vs-subpath (flagged, bounded before W1, pre-publication); manifest/digest encoding -(W1-first, format-versioned); Grok 4.6 route availability for slice 5 (operational lane dependency, -live-route evidence recorded in `supervisor.md`; not an architecture decision); RFC -tracking-issue/label mechanics from `rfcs/README.md` (implementation-time process owned by -`netscript-pr`, not a plan decision). +(W1-first, format-versioned); Grok 4.6 route availability for slice 5 (operational lane dependency +with live-route evidence in `supervisor.md`, not an architecture decision); RFC +tracking-issue/label/FCP mechanics from `rfcs/README.md` (implementation-time process owned by +`netscript-pr`; the planned `0000-database-architecture.md` filename already complies with the +draft-numbering rule); context-pack staleness (artifact hygiene, not a decision — see Notes). ## Verdict -`FAIL_PLAN` - -### Required fixes - -1. **[MEDIUM — factual integrity of a load-bearing rebaselined claim]** Correct the "exactly 30 - `db:*` tasks" count to the verified value (42 `db:*` tasks per generated engine workspace at - baseline `cd720529`; counted by executing `generateDatabaseDenoJson` for all four providers) — or - drop the exact number in favor of the accurate "more than twenty/forty-odd" formulation — in - every location that carries it: - - `research.md:34` (load-bearing finding 2); - - `research/architecture-plan-synthesis.md:70` ([FACT] bullet) and `:681` (cutover step 9); - - `plan.md` § Clean Cutover ("…deletes the old engine workspaces, 30 tasks, …"); - - record the disposition of Qwen finding F3 (`research/qwen-prisma-risk-review.md:64`) as an - incorrect correction in `research.md`'s "Corrections and conflict resolutions" section, the - same way the ~275-export claim was dispositioned. Rationale: the plan's own research gate - states "Every load-bearing numeric/factual claim is pinned to NetScript baseline… corrected - claims are not copied from independent reports" (plan.md § Plan and research gates). This - number was copied from an independent report, labeled [FACT], and would be inherited by the - canonical RFC's cutover/deletion inventory in slices 3–4. No architecture decision changes; - this is a research-integrity fix only. +`PASS` ## Notes -- Non-blocking: `origin/main` advanced by one CI-only commit (`01e096049`) after the rebaseline; the - plan's committed "fresh pin check during RFC drafting" covers it. No database surface is touched - by that commit. -- All other spot-checked load-bearing claims held against the tree and the pinned Prisma source; the - architecture, decision ledger, slices, gates, risks, JSR honesty, and deferral classifications are - otherwise sound. A corrected resubmission should be a fast second cycle. -- Per the hard stop: no canonical RFC authorship until a PLAN-EVAL `PASS`. +- Non-blocking hygiene: `context-pack.md` is stale (phase still `research`; its archetype line omits + A3). It is not a Plan-Gate box, but it should be refreshed with the next slice commit so the run + stays resumable, per the harness per-slice artifact rule. +- Non-blocking: `origin/main` advanced by one CI/gate-tooling commit (`01e096049`) after the + rebaseline; independently inspected and found to touch no premise of this plan. The plan's + committed fresh pin check during RFC drafting covers it. +- Per the hard stop: canonical RFC authorship (slice 3) may begin; slices must follow the locked + order, and Fable 5 high remains the final substantive gate. -PLAN-EVAL: FAIL_PLAN +PLAN-EVAL: PASS diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md index ffa6df8f90..12d46e09e1 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -7,8 +7,8 @@ | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | | Baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | -| Phase | `plan-eval-ready` | -| Target | `rfcs/0000-database-architecture.md` plus harness provenance; no canonical RFC before PLAN-EVAL PASS | +| Phase | `rfc-authoring` | +| Target | `rfcs/0000-database-architecture.md` plus harness provenance; authorship is unblocked but not yet complete | | Current changeset | Documentation/RFC under `SCOPE-docs.md` | | Future architecture | A1 contract, A2 control/provider integrations, A3 runtime, A4 definition/plugin DSL, A5 thin plugins, A6 testkit/CLI | @@ -21,6 +21,19 @@ manually synchronized types, hand-wired clients/adapters, textual generated-sour target selection, Aspire-coupled pure work, terminal-log contracts, and hand-maintained agent instructions. +## Plan-Eval Disposition + +Cycle 1 (`dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`, commit `3cbcfcec8`) returned `FAIL_PLAN` solely for +the copied claim of 30 generated `db:*` tasks. Executing the generator established the corrected +finding: **42 `db:*` keys per generated engine workspace** for each of PostgreSQL, SQLite, MySQL, +and MSSQL. Independent reports remain immutable; mutable planning records carry the correction. + +Fresh cycle 2 used native Fable 5 medium session `f3286656-7d0f-4da2-a22d-32897a5e6482` against +commit `383170bbc` and returned **`PASS`**. Canonical RFC authorship is therefore unblocked. No +additional PLAN-EVAL cycle is requested. `origin/main` has since advanced by one nonblocking +CI/gate-tooling commit (`01e096049`); the evaluator found no architecture, database, doctrine, or +RFC premise invalidated, and the existing fresh-pin drift watch remains sufficient. + ## Scope - Current-state, failure-history, doctrine/debt, Prisma RC/current-source, market, and agent-surface @@ -340,8 +353,8 @@ marker cleanup where supported. After apply, recovery is forward via lineage and | 2 | Independent PLAN-EVAL accepts the locked plan before RFC authorship. | Fresh separate-session evaluator `PASS`. | `plan-eval.md`, planning artifacts only. | | 3 | Canonical RFC defines vocabulary, APIs, package graph, TypeScript/E2E types, validation, control, contributions, providers, and refusal boundary. | Source alignment, local-link/terminology/docs format, decision coverage. | `rfcs/0000-database-architecture.md`, run context/worklog. | | 4 | RFC completes adoption/cutover, implementation waves, exhaustive conformance/release matrix, market implications, risks, and kill/switch criteria. | Requirement/decision trace, migration safety, claim/source audit, docs gates. | Same RFC plus run context/worklog. | -| 5 | Independent Qwen/Grok/adversarial findings are resolved with no open critical/high issue. | Qwen review disposition; Grok 4.6 high observable route receipt; source audit. | RFC plus review/run artifacts. | -| 6 | Separate-session IMPL-EVAL accepts the complete RFC. | Evaluator `PASS`; no self-certification. | `evaluate.md`, RFC/run artifacts. | +| 5 | Root personal review, Qwen 3.8 Max focused review, and Grok 4.6 high whole-RFC adversarial review complete. | Review receipts, source audit, and no undispositioned critical/high finding. | RFC plus review/run artifacts. | +| 6 | Author/editor dispositions resolve every actionable post-draft finding and preserve D-01–D-47. | Finding ledger closed or reasoned decline; contradiction and decision trace rerun. | RFC plus review/run artifacts. | | 7 | Owner-directed Fable 5 high performs the absolute final substantive refinement; publish the final review state. | Fable refinement, docs static checks only afterward, commit/push/PR trail. | RFC and final run/handoff artifacts. | There are eight ordered slices, below the Plan-Gate limit. The canonical RFC does not exist before @@ -409,12 +422,13 @@ packed install cannot substitute for the remote-graph verdict. ### Review/evaluator order -1. PLAN-EVAL: fresh Fable 5 medium separate session, `PASS` before RFC. -2. Root/source/doctrine audit during drafting; no generator self-certification. -3. Independent Qwen findings disposition and Grok 4.6 high adversarial complete-RFC review. -4. IMPL-EVAL: fresh separate evaluator session. -5. Fable 5 high final in-place refinement as the absolute last substantive gate. -6. Mechanical format/link/diff checks, commit/push, and PR handoff only. +1. PLAN-EVAL: completed with fresh Fable 5 medium cycle 2 `PASS`; no further Plan-Eval cycle. +2. Root personal source/doctrine/architecture review of the complete draft. +3. Qwen 3.8 Max focused post-draft review. +4. Grok 4.6 high whole-RFC adversarial review. +5. Author/editor dispositions for every actionable finding. +6. One Fable 5 high final in-place refinement as the absolute last substantive gate. +7. Mechanical format/link/diff checks, commit/push, and PR handoff only. ## Risk Register @@ -507,5 +521,5 @@ their gates have run. - Risk, deferred scope, doctrine/debt, future package/JSR/source/consumer gates, and waves are explicit. - Prospective JSR audit is applied honestly as planning evidence, with actual dry runs N/A. -- The next action is a fresh separate-session PLAN-EVAL. Canonical RFC authorship remains blocked - until `PASS`. +- PLAN-EVAL cycle 2 passed at commit `383170bbc`; canonical RFC authorship is unblocked but has not + yet completed. The next action is Slice 3 RFC drafting. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index ace5df6988..42aa0d5871 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -21,7 +21,7 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | owner-directed architecture deep dive | Anthropic · Claude Code · Opus 5 · high | Fresh independent architecture/API review with optional native workflows | | `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | | `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | -| third-opinion architecture review | OpenRouter · Qwen 3.8 Max · max | Diversity pass over the full architecture and implementation roadmap | +| focused post-draft RFC review | OpenRouter · Qwen 3.8 Max · max | Focused review after the root's complete-draft personal review | | owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | | owner-directed final refinement | Anthropic · Fable 5 · high | Absolute final review-and-refinement gate after every other substantive gate | @@ -35,7 +35,7 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Reconcile all evidence into a decision-grade Plan-Gate proposal | Complete | | `/root/planned_jsr_audit` | OpenAI · GPT-5.6 Sol · high | Prospective publishability/slow-type review of the planned graph | Complete | -These lanes are independent research/synthesis inputs. None is the formal PLAN-EVAL, IMPL-EVAL, or +These lanes are independent research/synthesis inputs. None is the formal PLAN-EVAL or the owner-directed final Fable refinement. ## Formal plan evaluation @@ -43,14 +43,17 @@ owner-directed final Fable refinement. | Cycle | Route / model / effort | Session | Evaluated commit | Verdict | Disposition | | ----- | ---------------------------------------------- | -------------------------------------- | ---------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | Native Claude Code · `claude-fable-5` · medium | `dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22` | `3cbcfcec8` | `FAIL_PLAN` | Sole medium factual-integrity finding corrected in mutable records; cycle 2 resubmission ready, with canonical RFC authorship still blocked. | +| 2 | Native Claude Code · `claude-fable-5` · medium | `f3286656-7d0f-4da2-a22d-32897a5e6482` | `383170bbc` | `PASS` | Corrected 42-per-workspace finding confirmed; D-01–D-47 and slice/gate set accepted; RFC authorship unblocked. | Cycle 1 used the required fresh `formal_plan_evaluation` route, separate from the supervisor and all research/synthesis lanes. Its only required fix was the copied claim of 30 generated `db:*` tasks: evaluator execution of `generateDatabaseDenoJson` established 42 keys per generated engine workspace for PostgreSQL, SQLite, MySQL, and MSSQL. `research.md`, the architecture synthesis, and `plan.md` now carry the executed result and disposition Qwen F3 as an incorrect correction; independent model -reports, briefs, and `plan-eval.md` remain immutable evidence. The phase remains `plan-eval-ready`; -a fresh cycle 2 `PASS` is required before the canonical RFC is authored. +reports and briefs remain immutable evidence. Cycle 2 passed at `383170bbc`; the phase is now +`rfc-authoring`, canonical RFC authorship is unblocked but incomplete, and no further PLAN-EVAL +cycle is requested. Cycle 2 also classified current-main `01e096049` as nonblocking CI/gate-tooling +drift and independently confirmed 42 generated `db:*` keys per engine workspace. ## Recorded lane/eval overrides @@ -68,15 +71,15 @@ a fresh cycle 2 `PASS` is required before the canonical RFC is authored. - The owner explicitly requires Fable 5 **high**, not merely an adversarial review, as the final refinement gate. That owner directive overrides the ordinary `docs_polish` Fable-medium effort for this run. No substantive model gate may follow it. -- Qwen 3.8 Max is selected as an in-policy independent architecture review for intelligence-family - diversity. +- Qwen 3.8 Max is selected for the owner-clarified focused post-draft review, after the root's + personal complete-draft review and before Grok's whole-RFC adversarial pass. - The owner subsequently requires Grok 4.6 high. On 2026-08-13 the live OpenRouter models API returned `x-ai/grok-4.6` with `reasoning_effort` support. The repository's static model catalog still names Grok 4.5, so this is an explicit owner-directed route override rather than a claim that the catalog is current. Use the existing bounded OpenCode/OpenRouter runner with model `openrouter/x-ai/grok-4.6` and variant `high`, record requested/observed identity and raw receipt, - and run it after the complete RFC draft but before IMPL-EVAL. Grok is not the formal evaluator and - no substantive gate may follow the final Fable 5 high refinement. + and run it after the focused Qwen review. No substantive gate may follow the final Fable 5 high + refinement. - Qwen integration-risk launch evidence: OpenRouter evaluator guard requested `qwen/qwen3.8-max` at `max`; session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` initialized with observed model `qwen/qwen3.8-max` and provider `Alibaba`. This is a complementary falsification pass, not @@ -92,3 +95,6 @@ a fresh cycle 2 `PASS` is required before the canonical RFC is authored. architecture axis beside contract-derived validation. A separate read-only source audit must establish the exact upstream state and derive candidate end-to-end NetScript type flows before plan lock; the Opus synthesis brief now requires this subsystem explicitly. +- The owner locked the post-draft sequence: root personal review → Qwen 3.8 Max focused review → + Grok 4.6 high whole-RFC adversarial review → author/editor dispositions → one final Fable 5 high + substantive refinement → mechanical checks only. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 14a96c4f9b..ca75f12a77 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -6,22 +6,21 @@ | -------------- | ------------------------------------------------------------- | | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | -| Phase | `plan-eval-ready` | +| Phase | `rfc-authoring` | | Archetype | Docs-only RFC describing future A1/A2/A3/A4/A5/A6 surfaces | | Scope overlays | `SCOPE-docs.md`; future packages use their archetype matrices | ## Design -The Design checkpoint is **locked and ready for PLAN-EVAL cycle 2**. Cycle 1 returned `FAIL_PLAN` -solely because the copied generated-workspace task count was factually wrong; the evaluator executed -the generator for all four providers and found 42 `db:*` keys per workspace. The mutable -research/synthesis/plan records are corrected and ready for resubmission. The architecture remains -evaluator-unapproved, and no canonical RFC file may be created until a fresh separate evaluator -returns `PASS`. +The Design checkpoint is **locked and evaluator-approved**. Cycle 1 returned `FAIL_PLAN` solely +because the copied generated-workspace task count was factually wrong; evaluator execution found 42 +`db:*` keys per workspace for all four providers. After correction, native Fable 5 medium cycle 2 +session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. +Canonical RFC authorship is unblocked but not yet complete; no further PLAN-EVAL cycle is planned. ### Public Surface and Package Graph -- Planned RFC record: `rfcs/0000-database-architecture.md`; it does not exist before PLAN-EVAL. +- Planned RFC record: `rfcs/0000-database-architecture.md`; its authorship is now unblocked. - `@netscript/database-contract` (A1): plain identities, manifest/plan/receipt/diagnostic schemas, capabilities, ownership, and shared small SPIs; zero provider dependencies. - `@netscript/database` (A4): thin `defineDatabase`/target/space/policy definitions and pure @@ -99,8 +98,8 @@ outcome is inspected before resume; cross-target atomicity is never claimed. | 2 | Independent Plan-Gate verdict. | Fresh separate-session `PASS`. | `plan-eval.md`, planning artifacts only. | | 3 | Canonical architecture/API RFC body. | Source alignment, docs, decision coverage. | RFC plus run context/worklog. | | 4 | Cutover/waves/conformance/risks/market completion. | Migration safety, claim trace, docs gates. | RFC plus run context/worklog. | -| 5 | Qwen/Grok adversarial findings resolved. | No open critical/high; Grok 4.6 route receipt. | RFC plus review/run artifacts. | -| 6 | Separate-session IMPL-EVAL. | Evaluator `PASS`. | `evaluate.md`, RFC/run artifacts. | +| 5 | Root, Qwen focused, and Grok whole-RFC reviews complete. | Review receipts; no undispositioned critical/high. | RFC plus review/run artifacts. | +| 6 | Author/editor dispositions complete. | Finding ledger closed; decision/contradiction trace. | RFC plus review/run artifacts. | | 7 | Absolute final Fable 5 high refinement and publish handoff. | Fable substantive gate, then mechanical checks only. | RFC/final run/handoff artifacts. | ### Prospective JSR Verdict @@ -152,6 +151,7 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in | 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | | 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | | 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | +| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | ### PLAN-EVAL Cycle 1 @@ -162,8 +162,15 @@ decisions, slices, risks, gates, and deferrals otherwise passed. The three mutable records now use the executed 42-per-workspace result and disposition Qwen F3 as an incorrect correction while preserving independent reports and evaluator evidence. Targeted format -and full diff checks passed. Cycle 2 resubmission is ready; phase remains `plan-eval-ready` and RFC -authorship remains blocked. +and full diff checks passed. + +### PLAN-EVAL Cycle 2 + +Fresh native Fable 5 medium session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit +`383170bbc` and returned `PASS`. It re-executed the generator and confirmed 42 task keys **per +workspace**, verified D-01–D-47 and all eight slices, and found no open rework-forcing decision. It +also inspected the one-commit current-main delta (`01e096049`) and classified it as nonblocking +CI/gate-tooling drift that changes structured check invocation rather than database or RFC premises. ## Decisions @@ -183,10 +190,11 @@ authorship remains blocked. ## Drift -| Drift | Severity | Logged in drift.md | -| -------------------------------------------------------- | ------------- | ------------------ | -| #313 compatibility-first plan is no longer authoritative | architectural | yes | -| Fable 5 high is the owner-directed final refinement gate | significant | yes | +| Drift | Severity | Logged in drift.md | +| ------------------------------------------------------------ | ------------- | ------------------ | +| #313 compatibility-first plan is no longer authoritative | architectural | yes | +| Fable 5 high is the owner-directed final refinement gate | significant | yes | +| `origin/main` advanced by CI/gate-tooling commit `01e096049` | nonblocking | plan-eval evidence | ## Gate Results @@ -198,12 +206,12 @@ authorship remains blocked. ### Fitness Gates -| Gate | Result | Evidence | Notes | -| ---------------------------- | ----------------- | ------------------------------- | ------------------------------------------------------------------------------------ | -| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | -| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | -| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | -| PLAN-EVAL | FAIL_PLAN_CYCLE_1 | `plan-eval.md`; correction diff | Sole factual-integrity finding corrected; cycle 2 required before canonical RFC. | +| Gate | Result | Evidence | Notes | +| ---------------------------- | --------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | +| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | +| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | +| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | ### Runtime Gates @@ -213,17 +221,17 @@ authorship remains blocked. ### Consumer Gates -| Consumer | Result | Evidence | Notes | -| ---------------------- | -------------- | ------------------------------------------------------------- | ---------------------------------------------------------------------- | -| PLAN-EVAL reader | RESUBMIT_READY | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 1's sole factual finding is corrected; cycle 2 remains required. | -| RFC reader/implementer | NOT_RUN | RFC blocked | Canonical RFC authorship begins only after PLAN-EVAL PASS. | +| Consumer | Result | Evidence | Notes | +| ---------------------- | ----------- | ------------------------------------------------------------- | ---------------------------------- | +| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | +| RFC reader/implementer | IN_PROGRESS | RFC authorship unblocked | Canonical RFC is not yet complete. | ## Handoff Notes -- Planning is complete, not evaluator-approved. PLAN-EVAL cycle 1 returned `FAIL_PLAN` only for the - corrected generated-task count; the next action is fresh separate-session cycle 2. No - implementation or canonical RFC authorship verdict is claimed. +- Planning is complete and evaluator-approved at commit `383170bbc`. Cycle 1's failure remains + preserved; cycle 2 passed and no further PLAN-EVAL cycle is requested. - Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until packages exist and must produce implementation/release receipts later. -- After PLAN-EVAL PASS, follow the eight RFC slices and preserve Fable 5 high as the final - substantive gate. +- Continue RFC authorship, then follow the owner-locked post-draft order: root personal review, Qwen + 3.8 Max focused review, Grok 4.6 high whole-RFC adversarial review, author/editor dispositions, + one final Fable 5 high substantive refinement, and mechanical checks only. From 05e5fbac2423e8afb1eac430e00c0d4522c2e41e Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 20:25:12 +0200 Subject: [PATCH 08/19] docs(rfc): draft database architecture --- rfcs/0000-database-architecture.md | 3140 ++++++++++++++++++++++++++++ 1 file changed, 3140 insertions(+) create mode 100644 rfcs/0000-database-architecture.md diff --git a/rfcs/0000-database-architecture.md b/rfcs/0000-database-architecture.md new file mode 100644 index 0000000000..053a719384 --- /dev/null +++ b/rfcs/0000-database-architecture.md @@ -0,0 +1,3140 @@ +--- +rfc: 0000 +title: Database architecture — a provider-neutral composition and operations kernel, with Prisma 8 PostgreSQL as the first certified adapter +status: Draft +authors: ['@rickylabs'] +created: 2026-08-13 +tracking-issue: https://github.com/rickylabs/netscript/issues/313 +target-milestone: Backlog / Triage +--- + +# Database architecture — a provider-neutral composition and operations kernel, with Prisma 8 PostgreSQL as the first certified adapter + +> **Process and front-matter notes.** +> +> - This draft lives at `rfcs/0000-database-architecture.md` and keeps the `0000` number until a +> maintainer assigns one at acceptance, per [`rfcs/README.md`](./README.md) § Numbering. +> - `tracking-issue` currently points at +> [issue #313](https://github.com/rickylabs/netscript/issues/313). #313 is carried as **historical +> problem evidence only**: its compatibility-first, additive solution is explicitly superseded by +> the clean-break directive in this RFC. The companion `rfc:` tracking issue is opened together +> with the draft PR (`rfcs/README.md` § Lifecycle step 1) and replaces this field at that point. +> - `target-milestone` is `Backlog / Triage` because no release milestone is committed yet. An +> accepted RFC's tracking issue moves to a `0.0.x` milestone when the implementation program is +> scheduled. +> - This RFC is **breaking**. The tracking issue and PR carry the `breaking` label. + +## How to read this RFC + +This document proposes a replacement for NetScript's database foundation. It is written to be +implementation-grade: an implementer should be able to derive package boundaries, public types, +state transitions, test matrices, refusal behaviour, and release gates from it without inventing +architecture. + +Because the proposal sits on top of a moving upstream project, every material claim carries an +explicit evidence class. These tags are used consistently and mean exactly what they say: + +| Tag | Meaning | +| ------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `[NS-SRC]` | Current NetScript source fact, at baseline `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf`. | +| `[RC1]` | Prisma source fact at the pinned release candidate `v8.0.0-rc.1@a76a6c5` (`a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`). | +| `[POST-RC]` | Prisma source fact at the audited post-RC object `71e2e0d9ee1f306b5a11435cd1973023cb33866a`. Never a statement about RC1 or GA. | +| `[PRIMARY]` | Official primary source: an upstream release, README, ADR, scorecard, issue, pull request, or product documentation page. | +| `[EXCHANGE]` | The owner/Prisma-maintainer conversation. **Exploratory direction, not an upstream commitment.** | +| `[INFERENCE]` | Reasoning that reconciles the facts above. Not an implemented capability. | +| `[PROPOSAL]` | NetScript design proposed by this RFC. Not implemented. | +| `[COND]` | Conditional or unproven implementation capability. It is withheld until a named gate passes, and it is never claimed as shipping. | + +Three rules govern how those classes combine, and they are load-bearing rather than stylistic: + +1. **Post-RC code is never presented as RC1 behaviour, and RC1 behaviour is never presented as a GA + guarantee.** Prisma 8 RC1 is Early Access and its release notes state that RC respins may break, + remove, or rename APIs and the contract format ([RC1 release][rc1-release]) `[PRIMARY]`. +2. **Local research reports are a claim index, not an authority.** Every material external claim in + this RFC is source-linked to a primary source or to a pinned source object. The run's research + corpus under + [`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md) + is where the derivation is recorded; it is not a substitute for the upstream citation. + Independent model reports in that corpus are adversarial evidence, and where they conflict with + executed verification the executed result wins (Appendix B records both). +3. **Unknowns are labelled, and an attractive inference is never promoted to a supported + capability.** Everything that implementation must decide appears in + [Unresolved questions](#unresolved-questions) with the wave that owns it. + +## Summary + +NetScript replaces its inherited database foundation with a single provider-neutral composition and +operations kernel, and certifies exactly one adapter first: Prisma 8 on PostgreSQL. Applications and +plugins author their schema in **native Prisma TypeScript** — the current model-first +`defineContract(scaffold, callback)` form — and pass that exact native value into thin NetScript +definitions that add identity, ownership, capability, lifecycle, and policy without touching the +provider's entity vocabulary or widening its inference. A pure two-phase composition compiles those +definitions into canonical `ContractArtifact`s and one deterministic, content-addressed +`DatabaseManifest`. The manifest is the durable join point for everything downstream: generated +application-local bindings and typed sessions, bounded contract-derived Standard Schema validators, +programmatic preview/plan/apply/verify operations, provider locks and ledgers, immutable operation +receipts, and generated CLI, documentation, and agent surfaces. + +The design is a clean break. There is no compatibility API, no Prisma 7 fallback, no dual runtime, +no legacy adapter facade, and no application that composes both stacks. Data continuity is +nevertheless absolute: `netscript db adopt` is a temporary migration tool that introspects live +databases, proposes ownership, writes provider marker metadata only, and performs **zero** table or +data DDL/DML before verification. The kernel deliberately refuses to become a second ORM: it defines +no query DSL, no repository abstraction, no portable client facade, no runtime capability +negotiation, and no hosted control plane. Where a capability cannot be made sound — multi-namespace +end-to-end typing, full Prisma operation validation derived from contract data alone, destructive +plugin removal, non-PostgreSQL providers — this RFC withholds the claim and names the gate that +would release it, rather than casting around the gap. + +## Motivation + +### The problem is not a Prisma version + +NetScript does not currently have one database architecture. It has five partially-overlapping +systems whose identities and ownership rules do not line up `[NS-SRC]`: + +1. an appsettings/Aspire database-resource model; +2. a fixed CLI engine registry and operation runner; +3. a generated per-engine Prisma workspace and task graph; +4. a runtime adapter wrapper around user-constructed Prisma clients; and +5. an install-time plugin Prisma-fragment copier. + +The happy path works only when those systems agree about config keys, engine directory names, +environment variables, generated files, Prisma CLI behaviour, adapter packages, and a live Aspire +resource graph. The framework makes that agreement a developer and CI responsibility, then adds +post-generation repair scripts where upstream output does not fit Deno expectations. There is no +canonical value joining the five views, so every fix lands in one of them and the failure moves. + +Substituting Prisma 8 for Prisma 7 under that structure would preserve every one of those seams. The +missing foundation is a NetScript-owned, typed, inspectable composition from which resource +provisioning, schema composition, client construction, generated imports, migrations, validation, +plugin contributions, diagnostics, and CI plans are all derived. + +### Identity collapses into provider and engine names + +The single most consequential defect is that **provider identity has replaced target identity** +`[NS-SRC]`: + +- The generated workspace directory is computed as `join('database', provider.dirName)` from a + closed engine enum (`packages/cli/src/kernel/adapters/database/workspace-resolver.ts:51`). Two + PostgreSQL databases therefore share one schema tree, one migration history, one generated client, + and one task set. `db add postgres --name analytics` creates another configuration entry but still + renders and resolves `database/postgres/`; the public second-database guide currently claims + otherwise. +- `resolveTarget` defaults only when exactly one target is enabled and never consults + `NetScript.PrimaryDatabase` (`workspace-resolver.ts:66-91`; independently re-verified during + PLAN-EVAL cycle 2). With more than one enabled target and no `--db`, resolution throws + `Unknown database target: (default)`, which contradicts documentation stating that a bare command + targets the primary database. +- Engine selection is a `switch` over `'postgres' | 'mysql' | 'sqlite' | 'mssql'` + (`workspace-resolver.ts:96+`), which is the literal counter-example doctrine records as AP-24 + ([`09-anti-patterns-and-fitness-functions.md`](../docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md)). + +`[INFERENCE]` Every downstream artifact — output root, migration lineage, runtime binding, lock, +receipt — inherits that collapse. No amount of new tooling repairs it while the identity of a +logical database has no representation. + +### Generation is a repair pipeline, not an emission + +Executing `generateDatabaseDenoJson` for each of PostgreSQL, SQLite, MySQL, and SQL Server produces +**42 `db:*` task keys in every generated engine workspace** `[NS-SRC]` (executed by the PLAN-EVAL +evaluator at commit `383170bbc` against +`packages/cli/src/kernel/templates/database/generate-db-deno-json.ts`). The current-state audit's +description of "more than twenty database tasks" was accurate; the executed count is the precise +figure and is the one this RFC uses. Generated templates additionally pin `npm:prisma@^7.4.2` +(`generate-db-deno-json.ts:36,56,59,61,67`) while the root catalog carries caret ranges `^7.8.0` +(`deno.json:231-236`) `[NS-SRC]`. + +The nominal `db:generate` pipeline performs placeholder removal, Prisma client generation, a second +generation through a Zod wrapper, generated-import rewriting, circular-reference rewriting, +getter-pattern rewriting, decimal-compatibility rewriting, a generated CRUD alias barrel, Prisma +client renaming/facade patching, and a further repair pass `[NS-SRC]`. The result is non-atomic +generated source that NetScript mutates based on upstream textual output. A developer can edit the +schema, skip the pipeline, and keep compiling against stale types. + +### Plugin schema contribution has no ownership semantics + +Plugins ship plain `database/**/*.prisma` files. On install the CLI discovers or downloads +fragments, chooses one database target, copies each fragment into the consumer's schema tree, scans +top-level `model|enum|type|view` blocks with a regex/balanced-brace parser +(`packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts:13`), removes +byte-normalised identical declarations, and rejects same-name declarations with different bodies +(`prisma-schema-writer.ts:19,100-122`) `[NS-SRC]`. + +That model cannot express a contribution contract or schema version, supported providers or +capabilities, target selection policy, dependency ordering, declaration ownership or allowed +augmentation, migration ownership and rollout, uninstall data policy, deterministic provenance, or a +contributor test kit. Its historical failure modes are on record: dependency-mode installs reported +success while omitting every plugin table ([#1014][ns-1014]) `[PRIMARY]`, and model-name clashes +broke authentication installs until namespacing plus a custom collision guard landed +([PR #1059][ns-1059]) `[PRIMARY]`. Removal deletes the copied directory; it plans no database +migration at all. + +### The recurrent failure classes are architectural, not incidental + +| Failure class | Primary evidence | Architectural lesson | +| ---------------------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------- | +| Prisma schema-engine crash/hang on Windows | [PR #98][ns-98], [PR #145][ns-145] | NetScript CI ended up owning an upstream subprocess lifecycle and flake classification. | +| A facade compiled only against a placeholder client, then failed after a real generation | [#173][ns-173] | Stubs and generated-client contracts diverge; every capability axis needs generated proof. | +| Plugin schema silently absent in dependency installs | [#1014][ns-1014] | Source-layout discovery is not a contribution contract. | +| Plugin/base model collision | [PR #1059][ns-1059] | A global declaration namespace needs explicit ownership and conflict semantics. | +| A read-only database command killed the resident AppHost | [PR #1088][ns-1088] | Database operations lacked a stable lifecycle owner. | +| An ephemeral AppHost leaked and masked the real host | [#1196][ns-1196], [PR #1301][ns-1301] | Fixing lifecycle symptoms without one operation model moves the failure. | +| A second AppHost mounted live `PGDATA` and corrupted it | [#1310][ns-1310], [PR #1311][ns-1311] | Resource reconstruction is unsafe; operations must bind an authoritative resolved value. | +| A stale allocated PostgreSQL endpoint | [#1202][ns-1202], [PR #1393][ns-1393] | Connection provenance must be inspectable and validated against the live allocation. | +| Headless migrate returned success without producing an artifact | [#1327][ns-1327], [PR #1393][ns-1393] | An exit code is not a result; operations need typed plans and artifact/state postconditions. | +| A multi-model Zod alias hid symbols, and its repair then broke startup | [#1254][ns-1254], [#1290][ns-1290] | Generated symbol paths cannot be the framework contract. | +| Split Zod module instances broke schema interoperability | [#1295][ns-1295] | Validation needs a standards-facing contract and a controlled dependency boundary. | + +`[NS-SRC]` `[PRIMARY]` The most severe lifecycle bug cost a measured pilot several hours, two +database resets, and a privileged host scrub; the final artifact-proof repair took six serialized +`scaffold.runtime` attempts as successive harness assumptions surfaced. This RFC exists to retire +those classes structurally rather than to fix another instance of them. + +### Two recorded architecture-debt entries are closed by this design + +`[NS-SRC]` `DB-GENERATE-ASPIRE-COUPLING` is open and documents that pure code generation still boots +Aspire, so generation fails where the Aspire CLI or .NET is absent. `packages/database — AP-17` +remains open; its `interfaces/` → `ports/` rename half is stale because `packages/database/ports/` +already exists, while its composition-root finding is still current. Auth roadmap item R1 +independently requires deterministic plugin-aware schema and migration automation, which this design +must satisfy as an ordinary contribution rather than an auth-specific escape hatch. + +### Why Prisma 8 changes the calculus + +`[RC1]` `[PRIMARY]` Prisma 8 is not Prisma 7 with a new generator. Its RC source is arranged as a +canonical contract plus separate control and execution planes: PSL or a TypeScript contract builder +lowers into a canonical `contract.json` and a `contract.d.ts`, a small versioned runtime consumes +the contract, a programmatic control client exposes emit/inspect/plan/apply operations, migrations +are content-addressed graph edges with per-space markers and a ledger, and **contract spaces** make +one contributor's `(contract, migration graph, head ref)` a first-class disjoint tuple +([ADR 212][adr-212]). + +That direction attacks NetScript's pain points at the root: generated executable client source can +disappear, source-rewriting and validator repair passes can disappear, schema ownership can be +modelled instead of inferred from copied files, migrations can be planned and verified +programmatically, structured results can replace log scraping, and family/target/adapter/driver/ +extension become distinct axes instead of one `engine` string. + +It is also not yet a safe surface to expose directly, and this RFC treats that as a design input +rather than a caveat: + +- Prisma 8 RC1 is Early Access and is explicitly not recommended for production workloads + ([RC1 README][rc1-readme]) `[PRIMARY]`. PostgreSQL is the sole database intended for the 8.0 GA + target set; MongoDB is Early Access, SQLite is a proof of concept, MySQL follows later, and SQL + Server is absent from the RC feature matrix ([scorecard][rc1-scorecard]) `[PRIMARY]`. +- `@prisma/orm-postgres` — described as the one package an application installs — publishes **138** + top-level export subpath keys at the pin, spanning adapters, control internals, contract + internals, migration tooling, query ASTs, runtime, target planning, and utilities `[RC1]` + (independently recounted during PLAN-EVAL cycle 2; an earlier independent report's figure of + approximately 275 is superseded). A framework that re-exported that surface would convert upstream + Early-Access internals into NetScript public API. +- The integration seam moved materially within six days of the RC tag `[POST-RC]`: the `prisma-next` + CLI stopped being published in favour of a unified CLI ([`3dc98cb`][pn-3dc98cb]), migration and + database commands were routed through the control API ([`d0c8333`][pn-d0c8333]), config + diagnostics and a ControlClient test double landed ([`15308c6`][pn-15308c6]), contract JSON Schema + became generated from ArkType ([`92b6ee3`][pn-92b6ee3]), the PostgreSQL floor dropped from 17 to + 15 ([`5d4a4db`][pn-5d4a4db]), aggregate number semantics changed ([`a900bc1`][pn-a900bc1]), and + command output channels were made explicit ([`71e2e0d`][pn-71e2e0d]). + +`[INFERENCE]` The correct response to a good architecture on a moving surface is to adopt its +_semantics_ through a very small, allowlisted adapter, and to keep NetScript's own vocabulary, +artifacts, and operations stable across the churn. That is what this RFC specifies. + +### What it costs to not do this + +`[INFERENCE]` Without this change: two logical PostgreSQL databases remain unrepresentable; plugin +schema stays a regex file copy with no version, ownership, or removal semantics; CI keeps paying for +Aspire on pure code generation; success keeps being reported by exit code; generated source keeps +being textually repaired; and the auth roadmap's deterministic plugin-aware migration requirement +has nowhere to land except an auth-specific generator. Each of those has already produced at least +one recorded production-shaped incident in the table above. + +### What it unlocks + +`[PROPOSAL]` A developer declares targets and spaces once, authors schema in native Prisma +TypeScript, and then receives — without a copied schema, a hand-synchronised type, a hand-written +adapter, a textual repair, or an implicit target choice — query types, lifecycle-owned sessions, +Standard Schema validators at trust boundaries, migrations with plans and receipts, plugin schema +ownership with independent history, CI evidence, and a generated agent surface. Section +[Guide-level explanation](#guide-level-explanation) is that experience end to end. + +## Guide-level explanation + +This section describes the system as if it had shipped. It is the developer experience the rest of +the RFC exists to make true. + +> **Example status.** Every example whose imports are `@netscript/*` is intended to be executable +> exactly as written once the packages in [§ Package graph](#the-package-graph-and-archetypes) +> exist. Every example that imports `@prisma/*` shows the **RC1 authoring shape** `[RC1]` and its +> exact module specifier is an adapter-pinned, implementation-time decision (D-41, wave W3): treat +> those specifiers as illustrative pseudocode until the W3 spike pins them. This distinction is +> deliberate — Prisma's own public CLI package name changed six days after the RC tag `[POST-RC]`, +> so freezing an upstream specifier in a NetScript contract would be a design error. + +### The one story + +Everything in this architecture is one pipeline of distinct, separately-named values. No stage is +allowed to impersonate another: + +```text +native authored TypeScript contracts + NetScript definitions/contributions + → pure two-phase composition + → canonical ContractArtifacts + → deterministic DatabaseManifest + → generated app-local AppBinding + → runtime sessions + bounded validators + → inspected baseline + → bound ExecutablePlan + → provider apply/ledger + → immutable OperationReceipts + → verify/recovery +``` + +Read that as a promise about _confusability_: a source definition is not a resolved manifest, a +speculative preview is not an executable plan, an executable plan is not a provider ledger, and a +receipt is not desired state. Most of the operational failures in +[Motivation](#the-recurrent-failure-classes-are-architectural-not-incidental) are what happens when +two of those collapse into one thing. + +### Step 1 — author the contract natively + +Schema authoring is Prisma's job, and NetScript does not add a vocabulary in front of it. The +current authoring API is model-first: `defineContract(scaffold, callback)`, where the callback +receives a composed helper surface and returns native `types`, `models`, and `enums` `[RC1]` +(`packages/3-extensions/postgres/src/contract/define-contract.ts:46-121`; the callback overload +preserves its returned literal types at +`packages/2-sql/2-authoring/contract-ts/src/contract-builder.ts:437-462`). + +```ts +// database/app.contract.ts — provider-native authoring. Specifier pinned in W3. +import pgvector from '@prisma/orm-extension-pgvector/pack'; +import { defineContract, rel } from '@prisma/orm-postgres/contract-builder'; + +export const appContract = defineContract( + { extensions: { pgvector }, namespaces: ['app'] }, + ({ field, model, type }) => { + const types = { Embedding: type.pgvector.Vector(1536) } as const; + + const User = model('User', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + email: field.text().unique(), + createdAt: field.timestamp().defaultNow(), + }, + }); + + const Post = model('Post', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + userId: field.uuidString(), + title: field.text(), + embedding: field.namedType(types.Embedding).optional(), + }, + }); + + return { + types, + models: { + User: User.relations({ posts: rel.hasMany(Post, { by: 'userId' }) }), + Post: Post.relations({ user: rel.belongsTo(User, { from: 'userId', to: 'id' }) }), + }, + }; + }, +); +``` + +`[PROPOSAL]` Three things NetScript will **not** do to that code. It will not recreate the older +fluent `target(...).table(...).column(...)` chain — that API was real at commit `fd88abf4` but was +replaced by the model-first redesign ([PR #261][pn-261], commit [`27ccefc3`][pn-27ccefc3]) and the +legacy implementation was removed ([`e1e5ab2c`][pn-e1e5ab2c], PR #317) `[PRIMARY]`. It will not +introduce a NetScript model DSL that lowers into the same contract. And it will not vendor or +re-export Prisma's builder as though NetScript owned it. + +### Step 2 — declare targets and spaces + +NetScript's own authoring surface adds identity, ownership, capability requirements, policy, and +lifecycle around that native value — and nothing else. This is the baseline API (decision D-07, +"Candidate A"): + +```ts +// database/database.ts +import { defineDatabase, defineDatabaseSpace, defineDatabaseTarget } from '@netscript/database'; +import { fromAspire, fromEnv } from '@netscript/database/connection'; +import { prismaPostgres } from '@netscript/database-prisma-postgres'; +import { authSpace } from '@netscript/plugin-auth-core/database'; +import { appContract } from './app.contract.ts'; + +const primary = defineDatabaseTarget({ + id: 'primary', + provider: prismaPostgres({ minVersion: 15 }), + connection: fromAspire('netscript-db'), + namespaces: { app: 'public', auth: 'auth' }, + roles: { writer: {}, 'reader:reporting': { readOnly: true } }, + policy: { destructive: 'deny', defaultOwnership: 'managed' }, +}); + +const analytics = defineDatabaseTarget({ + id: 'analytics', // same provider, different database, zero shared state + provider: prismaPostgres({ minVersion: 15 }), + connection: fromEnv('ANALYTICS_DATABASE_URL'), + namespaces: { warehouse: 'warehouse' }, + policy: { destructive: 'plan-only', defaultOwnership: 'adopted' }, +}); + +export default defineDatabase({ + targets: { primary, analytics }, + spaces: { + app: defineDatabaseSpace({ + id: 'app', + ownership: 'app', + owner: 'app', + version: '1.0.0', + target: 'primary', // type error unless it is a key of `targets` + namespace: 'app', + contract: appContract, // `typeof appContract` is preserved exactly + dependencies: [], + policy: { removal: 'retain' }, + }), + auth: authSpace({ target: 'primary', namespace: 'auth' }), + }, +}); +``` + +`[PROPOSAL]` The important property is what `defineDatabaseSpace` does to `appContract`: nothing. It +stores the value and preserves `typeof appContract` unchanged. NetScript never reinterprets models, +never copies Prisma overloads, and never widens the contract into a generic record. Everything +NetScript adds — `id`, `owner`, `version`, `target`, `namespace`, `dependencies`, capability +requirements, ownership, retention — is plain data that survives a provider replacement. + +The second property is that `target: 'primary'` is checked against `keyof targets`. Misrouting a +space is a type error at the authoring site rather than an install-time surprise. Today's installer +resolves a target through a fallback chain that can end at a **disabled** target `[NS-SRC]`; under +this design there is no fallback chain anywhere in the system. + +### Step 3 — the generated binding and typed sessions + +Composition emits canonical artifacts and one manifest, and the emitter writes a small +application-local binding module. That module is where inferred Prisma types live — never inside a +published NetScript package: + +```ts +// .netscript/database/primary.binding.ts — GENERATED. Do not edit. +// manifest: nsdb1:9f3c… · contract: cs:7ab2… · provider: @prisma/orm-postgres@ +import type { AppContract } from './primary/contract.d.ts'; +import type { QueryOf } from '@netscript/database-prisma-postgres/runtime'; +import type { ProcessTargetSession } from '@netscript/database-runtime'; + +export type PrimaryQuery = QueryOf; +export type PrimarySession = ProcessTargetSession<'primary', PrimaryQuery>; +export const PRIMARY_MANIFEST_DIGEST = 'nsdb1:9f3c…' as const; +export declare const primaryBinding: AppBinding<'primary', AppContract>; +``` + +```ts +// composition-root.ts — hand-written, small, and the only place a target is bound by name +import { createDatabaseRuntime } from '@netscript/database-runtime'; +import { prismaPostgres } from '@netscript/database-prisma-postgres'; +import database from './database/database.ts'; +import { primaryBinding, type PrimarySession } from './.netscript/database/primary.binding.ts'; + +await using runtime = await createDatabaseRuntime({ + definition: database, + manifest, + providers: [prismaPostgres], + targets: ['primary'], + scope: 'process', + connections, +}); + +const primary: PrimarySession = runtime.bind(primaryBinding); +const accounts: AccountStore = new PrismaAccountStore(primary); +``` + +`[PROPOSAL]` Feature code receives `AccountStore` — an application-owned port — not the runtime. +`runtime.bind` is reachable only from declared composition-root and generated files, enforced as an +`arch:check` rule, because a database handle reachable from anywhere is a service locator with a +domain name. NetScript does not generate repositories and does not define what `AccountStore` looks +like; that is application architecture. + +Inside the session, the query surface is Prisma's own: + +```ts +const recent = await primary.query.orm.post.findMany({ + where: { userId: input.userId }, + select: { id: true, title: true }, +}); + +await primary.transaction(async (tx) => { + await tx.orm.user.create({ data: { email: input.email } }); + await tx.orm.post.create({ data: { userId: input.userId, title: 'Hello' } }); +}); +``` + +There is no NetScript query language wrapping that call, and there never will be. Interactive +transactions exist only on process-scoped sessions; a request-scoped session is `AsyncDisposable`, +carries no cached collaborators, and its type does not expose `transaction`. + +### Step 4 — validation at trust boundaries + +The same contract that types the query surface produces Standard Schema validators, without a +generated validator file anywhere in the repository: + +```ts +import { primaryBinding } from './.netscript/database/primary.binding.ts'; + +const users = primaryBinding.space('app').model('User'); + +// Whole-model values, in either public representation. +const runtimeUser = users.value({ representation: 'runtime' }); +const jsonUser = users.value({ representation: 'json' }); + +// Selection-aware results. The schema is for the shape actually selected. +const publicUser = users.result({ select: { id: true, email: true } }, { representation: 'json' }); +``` + +Those values implement `StandardSchemaV1`, so they drop into two independent consumers unchanged: + +```ts +// 1. an oRPC route contract +const createAccount = baseContract + .route({ method: 'POST', path: '/accounts' }) + .input(users.operation('create', { representation: 'json' })) + .output(publicUser); + +// 2. a Fresh form/action boundary consuming the same value +const parsed = await publicUser['~standard'].validate(payload); +if (parsed.issues) return renderFieldErrors(parsed.issues); +``` + +`[PROPOSAL]` Two honest limits are visible in that snippet, and they are enforced rather than +documented. First, `users.operation('create', …)` succeeds **only** when the provider or an +extension has contributed exact operation metadata for that operation; otherwise it throws +`DB_VALIDATION_UNSUPPORTED` while the schema is being constructed, naming the missing metadata. +Second, invalid user data never throws: it returns Standard Schema issues with a field path, a +stable code, and the contract coordinates. Construction failures and validation failures are +different events with different audiences. + +### Step 5 — a second PostgreSQL database + +```ts +// database/warehouse.contract.ts + a second space bound to `analytics` +spaces: { + app: /* … bound to 'primary' … */, + warehouse: defineDatabaseSpace({ + id: 'warehouse', + ownership: 'app', + owner: 'app', + version: '1.0.0', + target: 'analytics', + namespace: 'warehouse', + contract: warehouseContract, + dependencies: [], + policy: { removal: 'retain' }, + }), +} +``` + +`[PROPOSAL]` `primary` and `analytics` are both PostgreSQL and share nothing: separate output roots, +contract artifacts, migration lineages, provider markers, runtime bindings, locks, and receipts. A +relation from a `primary` model to an `analytics` model is refused at composition with +`db.compose.cross-target-relation`, and no multi-target operation is ever described as atomic. Those +are not limitations of the adapter; they are honest statements about two separate databases. + +### Step 6 — install a plugin that owns its schema + +```ts +// consumer side: one line, and an explicit target +spaces: { + auth: authSpace({ target: 'primary', namespace: 'auth' }); +} +``` + +```ts +// plugins/auth/core: the plugin owns a full space, not a fragment +import { defineDatabaseSpace } from '@netscript/plugin/database'; +import { CAP } from '@netscript/database-contract/capabilities'; + +export const authSpace = defineDatabaseSpace.factory({ + id: 'plugin:@netscript/plugin-auth', + owner: '@netscript/plugin-auth', + version: '0.0.7', + ownership: 'space', + contractFormat: '>=1 <2', + requires: [CAP.sqlFamily, CAP.nativeUuid], + dependencies: [], + owns: { entries: ['user', 'session', 'account', 'verification'] }, + augmentation: { + grants: [{ entry: 'user', kind: 'add-optional-column', prefix: 'x_' }], + denies: ['drop-column', 'change-type', 'add-required-column'], + }, + policy: { removal: 'retain', allowed: ['retain'] }, + artifact: pinnedArtifactRef('./artifacts/contract.json'), +}); +``` + +`[PROPOSAL]` The `SpaceId` is the plugin's stable **published plugin identity** +(`plugin:@netscript/plugin-auth`), while the authoring module and generated artifacts ship from that +plugin's `-core` package — identity never follows an install path or a package layout. + +Installing that plugin copies nothing into the application's schema. It writes a **pinned mirror** +under the application's generated root containing the descriptor snapshot, the space's canonical +contract artifact, its lineage, and its provenance. Production apply and verify read the mirror, so +a deployment does not need the plugin's package graph resolvable at all. Two plugins that both +define a `User` table do not collide, because ownership is checked over +`(target, namespace, entryKind, name)` rather than over declaration text, and namespaces make the +separation physical. + +Uninstalling is a planned operation, not a directory delete. The guaranteed behaviour in the first +release is **detach-and-retain**: the runtime binding goes away, the data and the marker stay, a +tombstone records the history, and the objects' ownership is downgraded from `managed` to `adopted` +so that `verify` keeps noticing drift instead of going blind. Archiving and dropping are defined in +this RFC but are `[COND]` capabilities that ship only if provider conformance proves them. + +### Step 7 — one extension, registered once + +`[RC1]` Today a single logical extension such as pgvector must be registered independently in schema +authoring (`/pack`), in control/config (`/control`), and at runtime construction (`/runtime`) +(`examples/prisma-8-demo/prisma/contract.ts:1,18`, `prisma-next.config.ts:1-10`, +`src/prisma-no-emit/context.ts:1-11`). Half-registering it is silent until something fails. + +```ts +// one bundle, one identity, four facets +export const pgvectorExtension = defineDatabaseExtension({ + id: 'pgvector', + version: '0.4.0', + provider: 'prisma-postgres', + authoring: pgvectorPack, + control: pgvectorControl, + runtime: pgvectorRuntime, + validation: pgvectorValidation, +}); +``` + +`[PROPOSAL]` The generated composition root fans that single declaration into every phase. A +missing, mismatched, or half-installed facet is a composition error naming the facet and both +versions. + +### Step 8 — the operational journey + +Every operation is a typed programmatic call first. The CLI is a projection of the same catalog, and +so are the docs and the agent surface. + +```ts +import { createDatabaseControl } from '@netscript/database-control'; + +const control = createDatabaseControl({ manifest, providers: [prismaPostgres], connections }); + +const emitted = await control.emit({ targets: ['primary'], runId }); // pure: no connection at all +const baseline = await control.inspect({ targets: ['primary'], runId }); // live-read +const plan = await control.plan({ targets: ['primary'], baseline, policy, runId }); +const applied = await control.apply({ plan, policy, runId }); // mutating: lock + revalidate +const verified = await control.verify({ targets: ['primary'], runId }); +``` + +```console +$ netscript db plan --target primary --json +{ + "operation": "plan", + "runId": "01JYZ…", + "outcome": "succeeded", + "perTarget": [ + { + "target": "primary", + "status": "succeeded", + "spaces": [ + { "space": "app", "status": "planned", "steps": 3, "destructive": 0 }, + { "space": "plugin:@netscript/plugin-auth", "status": "planned", "steps": 1, "destructive": 0 } + ], + "plan": { "planId": "plan:4c19…", "expiresAt": "2026-08-13T18:42:00Z" } + } + ], + "diagnostics": [], + "nextAction": { "operation": "apply", "args": { "plan": "plan:4c19…" } } +} +``` + +`[PROPOSAL]` Four properties are guaranteed by the shape of that output. Every requested target +appears with a status — there is no silent skip and no implicit "all". `nextAction` is structured +data, so the CLI, CI annotations, and an agent render the same remediation without any of them +parsing prose. Human text is never a contract; gates assert on codes. And the exit code is a +projection of `outcome` (`succeeded` → 0, `refused`/`failed` → non-zero, `partial-success` → +non-zero with a resume token), never the result itself. + +When something goes wrong, the vocabulary is equally explicit: + +```console +$ netscript db apply --plan plan:4c19… +error db.plan.stale: plan plan:4c19… was bound to manifest nsdb1:9f3c…, current manifest is nsdb1:12ab… + target: primary + next: netscript db plan --target primary +``` + +### What you stop doing + +`[PROPOSAL]` Under this architecture the following stop existing as developer-visible work: copying +a plugin's `.prisma` file into your schema; running a generate pipeline whose later steps repair the +output of its earlier steps; keeping a generated Zod mirror in sync; importing a client by its +generated filesystem path; discovering that a command silently used the first target; starting +Aspire in order to compile; reading terminal logs to find out whether a migration produced an +artifact; and hand-maintaining an agent instruction file that describes commands that have since +changed. + +### What you will be refused + +`[PROPOSAL]` Equally important is what the system declines to do, loudly and early: + +| You try to… | You get | +| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| Bind a space to a target that does not exist | A **type error** at the authoring site | +| Declare a relation between models in two different targets | `db.compose.cross-target-relation` at composition | +| Let two spaces manage the same object | `db.compose.ownership.conflict`, naming both spaces | +| Use a capability the bound target does not declare | `db.compose.capability.missing`, naming capability, space, and target | +| Apply a speculative preview | Refusal: a preview has no `planId` and `apply` accepts only bound plans | +| Apply a plan after the manifest, baseline, provider set, or policy changed | `db.plan.stale`; after its expiry, `db.plan.expired` | +| Migrate a read replica | Refusal: replicas are roles, and no migration operation can address a role | +| Run a destructive step in production with an interactive "yes" | Refusal: production requires an approved, signed plan | +| Build a validator for an operation with no contributed grammar | `DB_VALIDATION_UNSUPPORTED` while constructing the schema | +| Target Prisma SQLite, MongoDB, MySQL, or SQL Server | `db.target.unsupported` — structured, with no fallback and no Prisma 7 path | +| Use multiple PostgreSQL namespaces with end-to-end typing | The kernel accepts the namespace axis; the adapter withholds the capability claim (see D-37) | +| Drop a plugin's tables on uninstall in v1 | Refusal: `retain` is the guaranteed mode; `archive`/`drop` are conditional on conformance | + +## Reference-level explanation + +### Locked vocabulary + +`[PROPOSAL]` These terms are used with exactly these meanings throughout the implementation program. +Similar-looking values are intentionally distinct, and conflating any two of them is a review +finding. + +| Term | Kind and owner | Locked meaning and invariant | +| ----------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Public TypeScript value · NetScript | Authored composition of targets, spaces, connection-source references, capability requirements, and policy. Pure; performs no IO. Not a manifest. | +| `NativeContract` | Provider-native authored value | A Prisma `defineContract` result, or another provider's equivalent. NetScript never translates its entity/query vocabulary. | +| `SpaceContribution` | Public declarative record | Owner, version, target binding, dependencies, ownership, capabilities, artifact refs, provenance, and retention policy for one contract space. | +| `ContractArtifact` | Versioned generated data · provider | Canonical provider contract data plus declaration and lineage artifacts, pinned per space and content-addressed. | +| `DatabaseManifest` | Public generated data · NetScript | The deterministic, versioned, content-addressed resolved snapshot. **The durable join point.** A graph exists only as private compiler IR. | +| `AppBinding` | App-local generated TypeScript | Minimal inferred bridge from native contract declarations to sessions, validators, and consumers. Never a published framework export. | +| `TargetRef` / `TargetSession` | Public value/handle · NetScript | Explicit target reference and process/request lifecycle shell. The concrete query type is an application-local generic argument. | +| `SpeculativePreview` | Public structured value · control | Advisory offline or live preview. **Cannot be approved or applied.** | +| `ExecutablePlan` | Public versioned value · control | Expiring plan bound to manifest digest, target/space closure, live baseline, provider pins, policy, environment, and secret references. | +| `ProviderMarker` / `ProviderLedger` | Provider-owned database state | The authoritative record of applied space heads and edges. NetScript reads and cites it and never maintains a second mutable copy. | +| `OperationReceipt` | Immutable append-only evidence | What was attempted, observed, checkpointed, verified, skipped, refused, failed, or left uncertain. Never desired state. | +| `OperationCatalog` | Public machine-readable data | Operation names, classes, request/result/diagnostic schemas, and next actions. CLI, help, docs, and agent surfaces are projections of it. | +| `ValidationIR` | **Internal** bounded algebra · runtime | Provider-decoded value/selection algebra used to produce Standard Schema values. Never a second entity or query model, never public. | + +### Identity model + +`[PROPOSAL]` Identity is declared, never derived. Provider names, engine names, filesystem paths, +configuration aliases, array order, traversal order, and discovery order are **never** identities +and never dependency edges. + +| Identity | Shape | Stability | Notes | +| --------------------- | -------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------- | +| `TargetId` | `'primary'`, `'analytics'` | Permanent; renaming is a migration | Author's choice. Owns connection, output root, runtime binding, lineage, locks, and receipts. | +| `RoleRef` | `(TargetId, 'writer' \| 'reader:')` | Derived | A replica is a role of a target, never a target. No migration operation can address a role. | +| `NamespaceRef` | `(TargetId, namespace)` | Permanent | A physical namespace inside one target. A kernel identity axis (see D-37 for the adapter). | +| `SpaceId` | `'app'`, `'plugin:@netscript/plugin-auth'` | Permanent per contributor | One schema owner. | +| `ObjectKey` | `(TargetId, namespace, entryKind, name)` | Derived | The unit of ownership. Exactly one `managed` owner. | +| `ContractSnapshotId` | Content hash of one space's canonical contract | Derived | Addresses one `ContractArtifact`. | +| `ManifestDigest` | Content hash over the canonical manifest | Derived | The determinism anchor. Distinct from any provider hash. | +| `PlanId` | Hash of manifest digest, closure, baseline, pins, policy | Derived | Binds a plan to everything that could invalidate it. | +| `RunId` / `ReceiptId` | Sortable unique ids supplied at the edge | Per execution | Receipts are addressable and resumable. | + +`[NS-SRC]` This directly repairs the observed collapse: +`workspaceDir = join('database', provider.dirName)` made `TargetId` inexpressible, `resolveTarget` +made the default target ambiguous, and the plugin installer's target chain could select a disabled +target. + +### The package graph and archetypes + +`[PROPOSAL]` Six new units and four changed existing units. Each has exactly one doctrine archetype, +per the one-archetype-per-package law +([`.llm/harness/archetypes/README.md`](../.llm/harness/archetypes/README.md)); where two archetypes +genuinely apply, the remedy is two packages, not one package with two shapes. + +```text + @netscript/database-contract (A1, leaf, zero dependencies) + ^ ^ ^ ^ + | | | | + @netscript/database -runtime -control @netscript/plugin + (A4) (A3) (A2) (A4) + ^ ^ ^ + | | | + +----------+------------+ + | + @netscript/database-prisma-postgres (A2, sole Prisma boundary) + ^ + | + @netscript/database-testkit (A6, depends on all; nothing depends on it) + +application composition root -> definition + runtime + control + one provider + generated AppBinding +application/plugin build input -> Prisma public authoring builder (controlled build phase only) +@netscript/aspire -> ConnectionSource SPI only +@netscript/cli -> OperationCatalog + control only +first-party plugin -> @netscript/plugin + @netscript/database-contract only +``` + +Dependency law, each clause mechanically checkable: + +1. `@netscript/database-contract` imports nothing from this family and no provider. Every other + member may depend on it. +2. `@netscript/database` depends on `-contract` only. +3. `-runtime` and `-control` depend on `-contract`, and on `-database` for definition types they + must not redeclare. They never import each other and never import a provider. +4. Provider packages depend on `-contract` (and on `-database`/`-runtime`/`-control` types they + implement) plus upstream. **No framework package depends on a provider.** A provider is a value + supplied at the application composition root. +5. `@netscript/plugin` depends on `-contract` only. This is the rule that keeps a database driver + out of every plugin's dependency graph. +6. The testkit may depend on every public surface; no runtime package may depend on the testkit. +7. **No framework package re-exports Prisma.** Only `@netscript/database-prisma-postgres` may import + Prisma runtime or control modules, through a single `upstream.ts` facade module and an explicit + import allowlist. Application and plugin schema-authoring modules may import Prisma's **public + authoring builder** directly during the controlled build phase; that is provider-native + authoring, not a NetScript re-export, and it may not reach Prisma runtime or control internals. + +#### `@netscript/database-contract` — Archetype 1 (small contract) + +| Property | Value | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Owns | Branded identities; `DatabaseManifest`, `ContractArtifact`, `SpaceContribution`, `SpeculativePreview`, `ExecutablePlan`, `OperationReceipt`, `OperationCatalog`, diagnostics; capability and ownership vocabularies; provider pins; the small SPIs shared by more than one consumer. | +| Must not own | Any IO, any lifecycle, any query type, any provider import, any inferred contract generic. | +| Dependencies | None. `@standard-schema/spec` only if a schema type is genuinely needed at this layer. | +| Public vs adapter-local | Everything here is public plain data. No adapter-local concept appears. | +| Runtime permissions | None. The package must be importable with zero Deno permissions. | +| Publication | Public on JSR from W1. | +| Archetype gates | A1 profile of F-1…F-19 per [`archetype-gate-matrix.md`](../.llm/harness/gates/archetype-gate-matrix.md); root export surface within the F-5 symbol cap; `deno publish --dry-run` **without** `--allow-slow-types`; `deno doc --lint` clean. | +| Kill / split criteria | Split into focused subpaths if the root surface approaches the F-5 cap. If any symbol here requires a provider generic, it belongs in the adapter instead. | + +#### `@netscript/database` — Archetype 4 (public DSL/builder) + +| Property | Value | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Owns | `defineDatabase`, `defineDatabaseTarget`, `defineDatabaseSpace`, `defineDatabaseExtension`, fragment definition, connection-source references, policy types, and the **pure** compiler that resolves a definition into a `DatabaseManifest` with total `Result` semantics. | +| Must not own | Connections, Aspire, Docker, network, provider imports, migration execution, any live state. | +| Dependencies | `-contract`. | +| Public vs adapter-local | Public: definitions, compiler, diagnostics. Internal: the compiler's graph IR, resolution order, and digest computation. | +| Runtime permissions | Source reads only through an injected `ContractArtifactSource`; the package itself declares no ambient filesystem or network access. | +| Publication | Public on JSR from W2. | +| Archetype gates | A4 profile; `defineX` returns frozen definitions; determinism/property tests; an AP-25 scan proving no IO is reachable from a pure path. | +| Kill / split criteria | If the compiler needs live state to resolve a manifest, the architecture — not the package — is wrong (see [Kill criteria](#kill-and-switch-criteria)). | + +#### `@netscript/database-runtime` — Archetype 3 (runtime/behaviour) + +| Property | Value | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Owns | Process and request scope; binding a manifest plus a provider to live connections; connection ownership and graceful close ordering; health/readiness; `AbortSignal` propagation; `{ stop() }` handles; validation cache and interpreter coordination; small session handles. | +| Must not own | Migration orchestration, plan/apply logic, CLI rendering, provider query vocabulary, any Prisma import. | +| Dependencies | `-contract`, `-database` (definition/manifest types). | +| Public vs adapter-local | Public: scope types, lifecycle, health, cancellation, transaction capability markers, validation requests. Adapter-local: `sql`/`orm`/`raw`/`prepare`, driver and pool types. | +| Runtime permissions | Network at bind time only, through a `ConnectionSource`. No filesystem writes. | +| Publication | Public on JSR from W4. | +| Archetype gates | **All F-1…F-19 and the required runtime gates** — A3 makes the runtime column mandatory, which is why runtime is its own package. Leak tests across repeated start/stop and request lifecycles; cancellation and scope tests. | +| Kill / split criteria | If a session type must name a provider type to be useful, the design has failed the app-local binding rule and must be reworked before publication. | + +#### `@netscript/database-control` — Archetype 2 (integration) + +| Property | Value | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Owns | The `OperationCatalog` and the programmatic operations classify/compose/emit/preview/inspect/plan/apply/verify/resume/adopt/inventory; provider ports; policy evaluation; lock coordination; receipts; recovery; cross-target saga sequencing; diagnostic translation. | +| Must not own | Provider SQL, ASTs, or migration diff mechanics; terminal text; CLI rendering; any Prisma import. | +| Dependencies | `-contract`, `-database`. | +| Public vs adapter-local | Public: operation classes, plan binding, policy, lock requirements, results, receipts, diagnostics. Adapter-local: upstream control client paths/options, upstream plan and progress representations. | +| Runtime permissions | `pure` operations receive no connection resolver at all. `live-read`/`mutating` receive an explicit connection; `resident` additionally receives an orchestration binding. | +| Publication | Public on JSR from W5. | +| Archetype gates | A2 profile; exhaustive negative/failure-injection matrix; atomic emission test; an offline test proving a `pure` operation cannot reach an orchestrator. | +| Kill / split criteria | If a port grows past four cohesive methods it is an AP-3 god port and must be split (see [Ports](#consumed-ports)). | + +#### `@netscript/database-prisma-postgres` — Archetype 2 (integration) + +| Property | Value | +| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Owns | The **only** framework runtime/control Prisma import boundary; the PostgreSQL capability descriptor; the native-contract/artifact adapter; the control adapter; the runtime factory; the `ValidationIR` decoder; the upstream compatibility allowlist and window. | +| Must not own | Re-exporting Prisma as NetScript's generic API; exposing upstream private or deep-import types in a public declaration; a hand-written low-level driver adapter. | +| Dependencies | `-contract`, `-database`, `-runtime`, `-control`, and exactly one resolved Prisma component set. | +| Public vs adapter-local | Public: capability descriptor, provider value for the composition root, `QueryOf`-style app-binding helpers. Adapter-local: every concrete Prisma contract, control, runtime, codec, and AST type. | +| Runtime permissions | Network and environment through the ports it is given; no ambient filesystem writes outside the artifact publisher. | +| Publication | **Experimental and unpublished until every W3 gate passes.** Independently versioned so an upstream break is a provider patch release, not a framework break. | +| Archetype gates | A2 profile plus runtime gates; import allowlist; exactly one resolved Prisma component set in a packed consumer; Deno import purity; real PostgreSQL conformance; no `--allow-slow-types`. | +| Kill / switch criteria | The provider-specific criteria in [Kill and switch criteria](#kill-and-switch-criteria). Killing this package costs an adapter, not the architecture. | + +#### `@netscript/database-testkit` — Archetype 6 (CLI/tooling) + +| Property | Value | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| Owns | Runnable provider **and space** conformance certification against real services, negative fixtures, and machine-readable conformance reports. | +| Must not own | Any application runtime responsibility. | +| Dependencies | All public SPIs. | +| Public vs adapter-local | Public: fixtures, suites, report schema. | +| Runtime permissions | Whatever a certification run needs, declared explicitly and never inherited by consumers. | +| Publication | Public tooling; **conditional on a justified binary.** | +| Archetype gates | A6 profile plus the F-CLI family; deliberately broken fixtures must fail. | +| Kill / split criteria | If implementation proves no runnable binary is needed, fold it into `./testing` subpaths — **decided before W1 and never after public release.** | + +#### Changed existing units + +| Unit | Archetype | Change | Constraint | +| ----------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `@netscript/plugin` | A4 | Adds a `defineDatabaseSpace` contribution seam typed only by `-contract`; **removes** the hollow legacy database/migration contribution abstracts and their contribution-axis members `[NS-SRC]`. | Plain descriptor types only; no runtime/control/provider dependency; breaking-surface accounting required at W7. | +| First-party `plugins/*` | A5 | Thin descriptors plus pinned generated contract/lineage/provenance assets sourced from their `-core` package. | No copied application schema; no convention-bearing database implementation; provider requirements declared. | +| `@netscript/aspire` | A2 | Adds one narrow `ConnectionSource`/provisioning adapter and a resource projection from the manifest. | **Must never be required by a `pure` operation.** This is what closes `DB-GENERATE-ASPIRE-COUPLING`. | +| `@netscript/cli` | A6 | Projects the `OperationCatalog`; hosts the adoption codemod and generated help/agent assets. | No database or provider business logic; no engine switch. | + +#### Doctrine obligations + +`[NS-SRC]` Doctrine currently codifies the model this RFC removes: Archetype 5 states that plugin +database contributions are plain `*.prisma` files referenced from `database/` +([`06-archetypes.md`](../docs/architecture/doctrine/06-archetypes.md)), and neither +`06-archetypes.md` nor +[`10-codebase-verdict-and-handoff.md`](../docs/architecture/doctrine/10-codebase-verdict-and-handoff.md) +contains any of the proposed packages — and the verdict table is what gates a path at all. + +`[PROPOSAL]` Wave W0 therefore amends both files, registers every new unit in the gated denominator, +replaces the plain-fragment rule, and records the archetype-count consequence. This RFC records that +obligation; it does not mutate doctrine before acceptance. No database package inherits the +oRPC-only `--allow-slow-types` carve-out +([`02-public-surface.md`](../docs/architecture/doctrine/02-public-surface.md)) — see +[Type propagation](#end-to-end-type-propagation). + +### The definition layer: exact public signatures + +`[PROPOSAL]` Every signature below is written to satisfy repo-wide `isolatedDeclarations` +`[NS-SRC]`: each exported symbol has an explicit type, and no published declaration names a provider +type. + +```ts +// @netscript/database + +/** Author-chosen target. `TId` is preserved as a literal by the `const` type parameter. */ +export declare function defineDatabaseTarget( + input: DatabaseTargetInput, +): DatabaseTargetDefinition; + +/** + * Wraps an already-authored native contract. `TContract` is inferred from the passed value and is + * never widened, re-keyed, or re-interpreted: `SpaceDefinition['contract']` has type `TContract`. + */ +export declare function defineDatabaseSpace< + const TId extends string, + const TTarget extends string, + TContract, +>( + input: DatabaseSpaceInput, +): DatabaseSpaceDefinition; + +/** Composes targets and spaces into a frozen definition. Pure; performs no IO. */ +export declare function defineDatabase< + const TTargets extends Readonly>>, + const TSpaces extends Readonly>>, +>( + input: DatabaseInput, +): DatabaseDefinition; + +/** One extension bundle with a single verified identity and four phase facets. */ +export declare function defineDatabaseExtension( + input: DatabaseExtensionInput, +): DatabaseExtension; + +/** Pure resolution. Total: it returns diagnostics, it does not throw for authoring mistakes. */ +export declare function compileDatabase( + definition: DatabaseDefinition< + Readonly>>, + Readonly>> + >, + sources: ContractArtifactSource, +): Promise; + +export type CompileResult = + | { + readonly ok: true; + readonly manifest: DatabaseManifest; + readonly warnings: readonly Diagnostic[]; + } + | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] }; +``` + +The input types carry the checked relationships: + +```ts +export interface DatabaseSpaceInput { + readonly id: TId; + /** `'app'` composes into the application's contract; `'space'` owns a full contract space. */ + readonly ownership: SpaceOwnershipMode; + /** Stable owner identity: `'app'` or a package identity. Never a path. */ + readonly owner: string; + readonly version: string; + /** Checked against `keyof DatabaseInput['targets']` by `defineDatabase`. */ + readonly target: TTarget; + readonly namespace: string; + /** The exact native value. Stored as-is; never widened. */ + readonly contract: TContract; + readonly requires?: readonly CapabilityId[]; + readonly dependencies?: readonly string[]; + readonly extensions?: readonly DatabaseExtensionRef[]; + readonly augmentation?: AugmentationPolicy; + readonly policy?: SpacePolicy; + readonly provenance?: ProvenanceRef; +} + +export interface DatabaseInput< + TTargets extends Readonly>>, + TSpaces extends Readonly< + Record, unknown>> + >, +> { + readonly targets: TTargets; + readonly spaces: TSpaces; + readonly policy?: DatabasePolicy; +} +``` + +#### Inference law + +`[PROPOSAL]` Four rules, each with a conformance fixture: + +1. **Literal preservation.** `TId`, `TTarget`, and namespace keys stay literal through `const` type + parameters. `keyof definition['targets']` is a union of literals, which is what makes + `target: 'primary'` a type error when `primary` is not declared. +2. **Contract identity.** `typeof definition.spaces.app.contract` is exactly `typeof appContract`. A + fixture asserts the two are mutually assignable and that no property was added, removed, or + widened. +3. **No structural widening.** No NetScript signature accepts a contract as + `Record` or reduces a collection of contracts through `Array.reduce`. A + deliberately-widened fixture must **fail** its type-soundness gate. +4. **No upstream leakage.** No published NetScript declaration names a Prisma type. `TContract` is + an opaque type parameter inside the kernel; only the application-local binding resolves it. + +#### The oRPC precedent, transferred precisely + +`[NS-SRC]` NetScript has already solved a structurally identical problem for oRPC: start from the +real upstream builder (`packages/contracts/src/application/contract-primitives.ts`), apply NetScript +policy around it, let precise types flow from the upstream value into implementation +(`implement()`), consume Standard Schema structurally through `~standard` +(`packages/contracts/src/domain/schema-types.ts`), and fan one const-generic root into several +surfaces (`packages/sdk/src/presets/define-services.ts`), with compile-failure soundness tests +(`plugins/workers/services/src/routers/workers-contract-soundness_test.ts`). + +`[PROPOSAL]` What transfers: the `defineX` → frozen definition → composition-root binding pattern; +versioned contribution with skew detection; Standard Schema as the interop boundary; and per-package +subpath discipline. + +What must **not** transfer, stated so it cannot be reintroduced by analogy: + +| oRPC mechanism | Why it must not transfer | +| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| The `--allow-slow-types` carve-out | The oRPC carve-out is defensible because the inferred contract **is the product** of those packages. A database contract is derived from the _application's_ own schema, so no framework package ever needs to export it. Extending the carve-out converts an app-local inference problem into permanent framework publish debt. | +| Global builder ownership / a `baseContract` equivalent | NetScript must not own the entry point into Prisma's builder; the application imports it directly. | +| Transport concepts (routes, methods, links, error maps) | A database space has no transport. Importing that vocabulary would be the first step of a portable client facade. | +| Upstream re-export from a kernel package | Doctrine AP-14, and the publish constraint above. | +| Cross-package implementation inheritance (a base contract class) | AP-4. Spaces **register** against an extension axis; they do not subclass. | +| Type-erasure workarounds with phantom markers | The erasure that CRUD contracts had to repair is exactly what rule 3 above forbids up front. | + +#### Two contribution modes + +`[PROPOSAL]` The mode decides migration ownership, and it is explicit: + +| Mode | Who owns migrations | Shape | Default for | +| -------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | +| `ownership: 'app'` | The application | A fragment function receiving the exact composed native helpers and returning const-preserved native `types`/`models`/`enums`/`entities`. | Application-owned schema, including schema an application chooses to own outright. | +| `ownership: 'space'` | The contributor | A complete native contract, canonical artifact, migration lineage, and head, published as pinned data. | **All plugin-owned tables** (D-38). | + +```ts +// @netscript/database — app-owned fragment, application-local by construction +export interface ContractFragment { + readonly id: TId; + readonly ownership: 'app'; + readonly requires: readonly DatabaseExtensionRef[]; + readonly dependencies: readonly string[]; + readonly build: (helpers: THelpers, deps: FragmentDependencies) => TResult; +} + +export declare function defineContractFragment< + const TId extends string, + THelpers, + TResult, +>(input: ContractFragmentInput): ContractFragment; +``` + +`[PROPOSAL]` **Publication rule for fragments.** A fragment's `build` parameter necessarily names +the provider's composed helper type. Under `isolatedDeclarations` and the no-slow-types rule, a +**published** package therefore cannot export a fragment: doing so would put a Prisma type in a +published declaration. Fragments are an application-local facility, and this is the concrete reason +plugin-owned tables default to full spaces whose published surface is plain data plus pinned +artifacts. A published package exporting a fragment is a gate failure, not a style preference. + +#### Two-phase composition + +`[RC1]` Extension packs are part of the scaffold and determine the composed helper object's static +and runtime shape **before** Prisma invokes the callback +(`packages/2-sql/2-authoring/contract-ts/src/composed-authoring-helpers.ts:43-102,132-154`, with +collision checks at `:214-233,272-306`). `[INFERENCE]` "Register an extension while a fragment is +executing" therefore cannot be sound. + +`[PROPOSAL]` Composition is two-phase, and the phases are named operations: + +```text +Phase 1 — collect (pure, no helpers exist yet) + contribution manifests · required extension bundles · dependency edges + · target/namespace requirements · ownership · capability requirements + │ resolve extension identity/version, detect facet mismatch, + │ topologically order fragments, refuse cycles and overlaps + ▼ +Phase 2 — build (pure, helpers now fully composed) + one scaffold → exact composed native helper surface + → invoke app-owned fragments in dependency order with explicit calls + → canonicalize → atomically publish ContractArtifacts +``` + +The generated composition root is explicit and const-preserving: + +```ts +// .netscript/database/primary.contract-root.ts — GENERATED. Do not edit. +export const primaryContract = defineContract(scaffold, (h) => { + const auth = authFragment.build(h, {}); + const app = appFragment.build(h, { auth }); + + return { + types: { ...auth.types, ...app.types }, + models: { ...auth.models, ...app.models }, + enums: { ...auth.enums, ...app.enums }, + } as const; +}); +``` + +`[PROPOSAL]` Explicit calls and object spreads, in a deterministic order the generator computes from +declared dependencies. Never a runtime registry, never `Array.reduce`, never a value typed +`Record`. Fragment order must not change the canonical contract digest; that is a +conformance case, not an aspiration. + +#### The optional policy factory, and its kill criterion + +`[PROPOSAL]` A convenience factory that pre-applies NetScript policy (naming strategy, default +control policy, a fixed extension set) and then forwards Prisma's exact composed helpers **may** +exist: + +```ts +const postgresContract = createPrismaContractFactory({ + naming: { tables: 'snake_case', columns: 'snake_case' }, + defaultControlPolicy: 'managed', + extensions: [pgvectorExtension], +}); + +export const appContract = postgresContract.define((h) => {/* `h` is Prisma's exact surface */}); +``` + +**Kill criterion, stated directly:** this factory is deleted if implementing it requires copying +Prisma's overloads, importing a private or deep upstream path, re-declaring its generic model/type +machinery, inserting a cast, or widening inference in any measurable way. In that case Candidate A — +native `defineContract` plus a thin `defineDatabaseSpace` — is the complete public authoring API, +and it is already sufficient. The factory is a convenience, never a foundation, and no other part of +this design depends on it. + +### End-to-end type propagation + +```text +native defineContract(...) value ← application/plugin build input + │ typeof contract (editor + compiler inference; never crosses a published boundary) + ▼ +defineDatabaseSpace({ contract, ownership, target, … }) ← NetScript identity/policy, inference intact + ▼ +DatabaseDefinition ──compileDatabase──▶ DatabaseManifest + pinned contract.json / contract.d.ts + │ │ + │ └─▶ bounded ValidationIR ─▶ StandardSchemaV1 + ▼ +generated app-local AppBinding<'primary', AppContract> + ├─▶ ProcessTargetSession<'primary', QueryOf> (queries, transactions) + ├─▶ RequestTargetSession<'primary', QueryOf> (disposable, no cached collaborators) + ├─▶ model value / operation input / selection-aware result schemas + ├─▶ oRPC procedures, Fresh routes and actions, form adapters, SSR payload checks + └─▶ application-owned stores bound at the composition root +``` + +`[PROPOSAL]` Two tracks run in parallel and must never be merged: + +- **The inference track** is `typeof contract`. It may contain complex provider generics, it is only + valid inside the application's own compilation, and it terminates in generated app-local files. +- **The identity track** is `ContractSnapshotId` and `ManifestDigest`. It is plain data used by + plans, markers, receipts, validators, caches, agents, and stale-artifact checks, and it crosses + every boundary freely. + +Conflating them is how a system ends up unable to answer "is this database consistent with this +build?" without type-checking. Every generated binding records the manifest digest and the exact +provider pin; runtime startup refuses a binding/manifest/contract mismatch with `db.artifact.stale` +or `db.contract.version-mismatch` and a structured `nextAction`. + +#### The acceptance condition + +`[PROPOSAL]` This is the condition on which both primary axes of this RFC stand or fall, and it is +binding on implementation: + +> Accept the native integration only if it preserves Prisma's exact contract inference without +> private imports, copied overloads, casts, or declaration widening, and accept contract-derived +> validation only where the canonical contract plus contributed codec, operation, and selection +> metadata can produce sound fail-closed Standard Schema validators; otherwise narrow or kill the +> affected layer rather than pretending parity. + +Stronger, operationally: each clause has a conformance fixture and a named owner wave. A failure of +the first clause kills the affected authoring convenience and, in the limit, the Prisma adapter — it +never authorises a cast. A failure of the second clause narrows the validation algebra to the subset +that remains sound — it never authorises a pass-through or an `unknown`. + +#### The one deliberate soundness seam + +`[PROPOSAL]` Honesty requires naming the single place where the kernel cannot check what it is +given. `runtime.bind` returns a session whose query type is supplied by generated code: + +```ts +export interface DatabaseRuntime { + bind( + binding: AppBinding, + ): ProcessTargetSession; + bindRequest( + binding: AppBinding, + ): RequestTargetSession; + health(signal: AbortSignal): Promise; + stop(): Promise; +} +``` + +The kernel cannot prove that the runtime value the provider constructs matches `TQuery`, because +`TQuery` is erased. Three mitigations make that seam safe, and all three are gates rather than +conventions: the `AppBinding` value is **generated** from the same manifest and provider declaration +artifact that produced the session (hand-writing one is an `arch:check` failure); the binding +carries `ManifestDigest` and `ContractSnapshotId`, which the provider verifies at bind time and +refuses on mismatch; and a conformance case asserts that a deliberately mismatched binding fails at +bind rather than at first query. This seam is preferred over the alternative — publishing a +contract-typed value from a framework package — which `isolatedDeclarations` and the slow-types rule +forbid outright. + +### Artifacts and public contracts + +#### Identities + +```ts +// @netscript/database-contract +export type TargetId = string & { readonly __targetId: unique symbol }; +export type SpaceId = string & { readonly __spaceId: unique symbol }; +export type CapabilityId = string & { readonly __capability: unique symbol }; +export type ContractSnapshotId = string & { readonly __snapshot: unique symbol }; +export type ManifestDigest = string & { readonly __manifestDigest: unique symbol }; +export type PlanId = string & { readonly __planId: unique symbol }; +export type RunId = string & { readonly __runId: unique symbol }; +export type ReceiptId = string & { readonly __receiptId: unique symbol }; + +export interface RoleRef { + readonly target: TargetId; + readonly role: 'writer' | `reader:${string}`; +} +export interface NamespaceRef { + readonly target: TargetId; + readonly namespace: string; +} +export interface ObjectKey { + readonly target: TargetId; + readonly namespace: string; + /** Open provider/pack entry kind: `table`, `native_enum`, `value_set`, a pack-contributed kind. */ + readonly entryKind: string; + readonly name: string; +} + +export type OwnershipPolicy = 'managed' | 'adopted' | 'external' | 'ignored'; +export type SpaceOwnershipMode = 'app' | 'space'; +export type RuntimeScope = 'process' | 'request'; +export type ValidationRepresentation = 'runtime' | 'json'; +export type OperationClass = 'pure' | 'live-read' | 'mutating' | 'resident'; +``` + +#### The artifact contract, at a glance + +| Artifact | Producer | Consumers | Authority for | Identity / digest inputs | Encoding & persistence | Atomicity | Provenance & redaction | Stale / mismatch behaviour | +| ----------------------------------- | -------------------------------- | ----------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------ | -------------------------------------------------------------- | +| `DatabaseDefinition` | Author (TypeScript) | Compiler only | Intent | None — it is source | TypeScript in the repository | n/a | Git history | Compile diagnostics | +| `ContractArtifact` | Provider emit (controlled build) | Compiler, control, runtime, validation, mirrors | Provider contract content | `ContractSnapshotId` = hash of the canonicalized provider contract | Canonical JSON + declaration file, per space, per output root | Staged then atomically committed | Emitting provider pin, source space, emit run id | `db.artifact.stale`; refuse to plan or bind | +| `DatabaseManifest` | `compileDatabase` (pure) | Control, runtime, CLI, agents, CI | Resolved desired composition | `ManifestDigest` = hash of the full canonical manifest incl. provider pins and snapshot ids | Canonical JSON, format-versioned, in the generated root | Written by the same atomic publisher | Definition source refs, contributor provenance | Any consumer with a different digest refuses and names both | +| `AppBinding` | Emitter (generated TS) | Application composition root | App-local inferred types | Records `ManifestDigest` + `ContractSnapshotId` | Generated TypeScript, never hand-edited, never text-patched | Replaced atomically with its artifact root | Header comment carries digests and provider pin | Bind-time refusal `db.artifact.stale` | +| `SpeculativePreview` | Control (`pure`/`live-read`) | Humans, CI comments | Nothing | Advisory id only; **never** a `PlanId` | JSON result; not persisted as an apply input | n/a | Records whether a baseline was read | Cannot be applied — there is no code path that accepts it | +| `ExecutablePlan` | Control (`live-read`) | Policy, approval, `apply` | What will be executed | `PlanId` = hash(manifest digest, closure, baseline fingerprint, provider pins, policy) | JSON, versioned, storable, reviewable | Immutable once created | Environment, policy decision, signature, **secret refs only** | `db.plan.stale`, `db.plan.expired`, `db.plan.revoked` | +| `ProviderMarker` / `ProviderLedger` | Provider (in the database) | Control (read), verify, resume | **Applied state — the authority** | Provider-owned; NetScript records it as opaque versioned attributes | Provider tables in the target database | Provider's own transactional coupling | Provider version, space, head | Divergence from the manifest is drift, classified by ownership | +| `OperationReceipt` | Control (`ReceiptSink`) | Humans, CI, resume, audit | Evidence of attempts and observations | `ReceiptId` per run, checkpoints ordered | Append-only atomic JSON per checkpoint | Each checkpoint written atomically | Tool versions, environment, run id; **redacted** connection values | Never used as desired state; a resume reads it plus live state | +| `OperationCatalog` | Control (generated data) | CLI, docs, agents, tests | The operation surface | Versioned with the control package | Checked-in deterministic TypeScript constants | Regenerated and diffed in CI | Package version | A freshness gate fails the build on drift | + +#### `DatabaseManifest` + +```ts +export interface DatabaseManifest { + /** Public format version. Evolution policy is a W1 decision; the field is not optional. */ + readonly formatVersion: 1; + readonly digest: ManifestDigest; + readonly targets: readonly ManifestTarget[]; + readonly spaces: readonly ManifestSpace[]; + /** Topological order over spaces, recorded so review sees it rather than inferring it. */ + readonly spaceOrder: readonly SpaceId[]; + readonly providerPins: readonly ProviderPin[]; + readonly policy: DatabasePolicy; + readonly provenance: ManifestProvenance; +} + +export interface ManifestTarget { + readonly id: TargetId; + readonly family: string; + readonly provider: ProviderPin; + readonly namespaces: readonly string[]; + readonly roles: readonly RoleRef[]; + readonly capabilities: readonly CapabilityId[]; + /** Reference only. A resolved connection value never participates in manifest identity. */ + readonly connection: ConnectionSourceRef; + readonly outputRoot: string; + readonly migrationRoot: string; + readonly policy: TargetPolicy; +} + +export interface ManifestSpace { + readonly id: SpaceId; + readonly owner: string; + readonly version: string; + readonly mode: SpaceOwnershipMode; + readonly target: TargetId; + readonly namespace: string; + readonly ownership: OwnershipPolicy; + readonly requires: readonly CapabilityId[]; + readonly dependencies: readonly SpaceId[]; + readonly owns: readonly ObjectKey[]; + readonly augmentation: AugmentationPolicy; + readonly snapshot: ContractSnapshotId; + readonly extensions: readonly DatabaseExtensionPin[]; + readonly removal: RemovalPolicy; + readonly provenance: ProvenanceRef; +} +``` + +| Field | Contract | +| ------------------------ | ----------------------------------------------------------------------------------------------------------------- | +| `formatVersion` | Public. A consumer that does not understand the version refuses rather than best-effort parsing. | +| `digest` | Hash over the full canonical manifest **including** provider pins and contract snapshot ids. Not a provider hash. | +| `targets[].connection` | A **reference**. Environment values, URLs, and secrets never enter the manifest or its digest. | +| `targets[].capabilities` | Static declared data from the provider descriptor. Never negotiated at runtime. | +| `spaces[].owns` | The complete owned `ObjectKey` set. Exactly one `managed` owner per key across the whole manifest. | +| `spaces[].dependencies` | Declared semantic edges. Array position, file path, and discovery order are never edges. | +| `spaceOrder` | The topological order actually used by planning and apply, recorded for review. | +| `provenance` | Which definition sources, contributor packages, mirrors, and emit runs produced this snapshot. | + +#### `ExecutablePlan` and `SpeculativePreview` + +```ts +export interface SpeculativePreview { + readonly kind: 'speculative'; + readonly manifestDigest: ManifestDigest; + readonly targets: readonly TargetId[]; + readonly summary: readonly PreviewStep[]; + /** True when a live baseline was read; still not applicable either way. */ + readonly baselineObserved: boolean; + readonly diagnostics: readonly Diagnostic[]; +} + +export interface ExecutablePlan { + readonly kind: 'executable'; + readonly planId: PlanId; + readonly manifestDigest: ManifestDigest; + readonly target: TargetId; + readonly spaceClosure: readonly SpaceId[]; + readonly baseline: BaselineFingerprint; + readonly providerPins: readonly ProviderPin[]; + readonly steps: readonly PlanStep[]; + readonly destructive: readonly DestructiveOperation[]; + readonly capabilitiesUsed: readonly CapabilityId[]; + readonly policy: PolicyDecision; + readonly environment: string; + /** References only; a plan never contains a secret value. */ + readonly secretRefs: readonly SecretRef[]; + readonly createdAt: string; + readonly expiresAt: string; + readonly signature?: PlanSignature; +} + +export interface DestructiveOperation { + readonly kind: + | 'drop-entry' + | 'drop-column' + | 'narrow-type' + | 'add-required-without-default' + | 'unique-over-existing-data' + | 'namespace-drop'; + readonly object: ObjectKey; + readonly dataLossRisk: 'certain' | 'possible' | 'none'; + /** Present only when the provider proved it. Absence is not evidence of safety. */ + readonly observedRowCount?: number; +} +``` + +| Field | Contract | +| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| `kind` | The type-level separation of preview and plan. `apply` accepts `'executable'` only; there is no coercion. | +| `planId` | Binds manifest digest, space closure, baseline fingerprint, provider pins, and policy. Any change invalidates the plan. | +| `baseline` | A fingerprint of the inspected live state and provider ledger at planning time. Re-checked under the lock before mutation. | +| `secretRefs` | References only, so a plan is safe to commit, attach to a PR, and archive. | +| `expiresAt` | Mandatory. Applying after it yields `db.plan.expired`. | +| `signature` | Required in production. Algorithm and key custody are a pre-implementation decision (D-35, W5/W10); the field and the policy port are locked now. | + +#### `OperationReceipt` + +```ts +export interface OperationReceipt { + readonly receiptId: ReceiptId; + readonly runId: RunId; + readonly operation: OperationName; + readonly manifestDigest: ManifestDigest; + readonly startedAt: string; + readonly finishedAt?: string; + readonly phases: readonly ReceiptPhase[]; + readonly artifacts: readonly ArtifactAssertion[]; + readonly environment: string; + readonly toolVersions: readonly ProviderPin[]; + readonly outcome: ReceiptOutcome; +} + +export type ReceiptOutcome = + | 'succeeded' + | 'refused' + | 'skipped' + | 'failed' + | 'partial-success' + | 'cleanup-required' + | 'outcome-unknown' + | 'cancelled'; + +/** A postcondition the operation proved — not a log line claiming it. */ +export interface ArtifactAssertion { + readonly path: string; + readonly expected: 'created' | 'unchanged' | 'replaced' | 'absent'; + readonly digestBefore?: string; + readonly digestAfter?: string; +} +``` + +`[PROPOSAL]` A receipt is append-only evidence. It is never consulted as desired state, never +compared against instead of the provider ledger, and never repaired. `cleanup-required` and +`outcome-unknown` are separate outcomes from `failed` precisely because "the ledger was repaired" +must never be read as "the database was repaired" — a lesson Flyway's `repair` documents explicitly +([Flyway repair][flyway-repair]) `[PRIMARY]`. + +#### `SpaceContribution` + +```ts +export interface SpaceContribution { + readonly id: SpaceId; + readonly owner: string; + readonly version: string; + readonly contractFormat: string; + readonly mode: SpaceOwnershipMode; + readonly requires: readonly CapabilityId[]; + readonly dependencies: readonly SpaceId[]; + readonly owns: readonly ObjectKeyPattern[]; + readonly augmentation: AugmentationPolicy; + readonly artifact: ContractArtifactRef; + readonly extensions: readonly DatabaseExtensionPin[]; + readonly validation: readonly ValidationContributionRef[]; + readonly executablePhases: readonly ExecutablePhase[]; + readonly removal: RemovalPolicy; + readonly provenance: ProvenanceRef; +} +``` + +| Field | Contract | +| ------------------ | ---------------------------------------------------------------------------------------------------------------------- | +| `id` / `owner` | Logical and stable. **Never** derived from an install path, a package directory, or include order. | +| `contractFormat` | The provider contract-format range the contribution supports. A mismatch is a refusal, not a warning. | +| `owns` | What this space owns, and therefore what no other space may manage. | +| `augmentation` | Owner-granted permission for others to extend its objects, with an explicit deny list. Absence of a grant is a denial. | +| `executablePhases` | Which build phases may execute this contributor's code. Composition consumes declarative records by default. | +| `removal` | Default `retain`. `archive`/`drop` appear only when the provider capability and conformance evidence exist. | +| `provenance` | Package identity, resolved version, integrity hash, and mirror digest — the inputs to skew detection. | + +#### Diagnostics and results + +```ts +export type DiagnosticCode = + | 'db.compose.ownership.conflict' + | 'db.compose.capability.missing' + | 'db.compose.dependency.cycle' + | 'db.compose.cross-target-relation' + | 'db.compose.extension.facet-mismatch' + | 'db.space.skew' + | 'db.space.dependent-installed' + | 'db.contract.version-mismatch' + | 'db.artifact.stale' + | 'db.plan.stale' + | 'db.plan.expired' + | 'db.plan.revoked' + | 'db.apply.destructive.refused' + | 'db.apply.lock.held' + | 'db.apply.outcome-unknown' + | 'db.verify.drift' + | 'db.target.unsupported' + | 'db.target.ambiguous' + | 'db.validation.unsupported'; + +export interface Diagnostic { + readonly code: DiagnosticCode; + readonly severity: 'error' | 'warning' | 'info'; + readonly subject: ObjectKey | TargetId | SpaceId; + /** Human text. Never parsed by anything — no gate may assert on it. */ + readonly message: string; + /** Structured remediation: an operation name plus arguments, not prose. */ + readonly nextAction: NextAction; +} + +export interface OperationResult { + readonly runId: RunId; + readonly outcome: 'succeeded' | 'partial-success' | 'failed' | 'refused'; + readonly perTarget: readonly TargetOutcome[]; + readonly diagnostics: readonly Diagnostic[]; + readonly receipt: OperationReceipt; + readonly resume?: ResumeToken; +} + +export interface TargetOutcome { + readonly target: TargetId; + readonly status: 'succeeded' | 'failed' | 'skipped' | 'not-attempted' | 'refused'; + /** Why a target was skipped or not attempted. There are no silent omissions. */ + readonly reason?: DiagnosticCode; + readonly spaces: readonly SpaceOutcome[]; + readonly value?: TOutcome; +} +``` + +`[NS-SRC]` This replaces an operation surface whose entire result type is an exit code +(`packages/cli/src/kernel/adapters/database/operation-runner.ts:85`), under which `--db all` is +sequential and fail-fast with no per-target record and `studio` executes only the first resolved +target (`:90-105,116-117`). `[INFERENCE]` That is why receipts cannot be an additive later slice: +the return type makes structured reporting impossible, so the operation contract is the thing being +replaced. + +#### Consumed ports + +`[PROPOSAL]` Each port stays at three or four cohesive methods — AP-3 names "a port with every +operation the backend can perform" as the integration-package failure mode, and the current +`DatabaseAdapter` (client lifecycle plus health plus status plus raw query plus +`setClient`) is that anti-pattern in shipped code `[NS-SRC]`. + +```ts +export interface ContractArtifactSource { + read(space: SpaceId, snapshot: ContractSnapshotId): Promise; + resolveHead(space: SpaceId): Promise; + list(): Promise; +} + +/** Atomic publication: stage into a temporary root, then commit or abort. Never patch in place. */ +export interface ArtifactPublisher { + stage(root: ArtifactRootRef): Promise; + commit(staged: StagedRoot): Promise; + abort(staged: StagedRoot): Promise; +} + +export interface ProviderRuntimeFactory { + capabilities(): ProviderCapabilityDescriptor; + createProcessRuntime( + input: RuntimeBindInput, + signal: AbortSignal, + ): Promise; + createRequestRuntime( + input: RuntimeBindInput, + signal: AbortSignal, + ): Promise; +} + +export interface ProviderControl { + emit(request: EmitRequest, signal: AbortSignal): Promise; + /** Returns the live baseline **including** provider marker/ledger state. */ + inspect(request: InspectRequest, signal: AbortSignal): Promise; + plan(request: ProviderPlanRequest, signal: AbortSignal): Promise; + apply(plan: BoundProviderPlan, signal: AbortSignal): Promise; +} + +export interface ConnectionSource { + describe(target: TargetId): ConnectionDescription; + resolve(target: TargetId, role: RoleRef, signal: AbortSignal): Promise; +} + +export interface MigrationLock { + acquire(scope: LockScope, owner: LockOwner, ttlMs: number): Promise; + renew(lease: LockLease): Promise; + release(lease: LockLease): Promise; + inspect(scope: LockScope): Promise; +} + +export interface ReceiptSink { + open(run: ReceiptOpenInput): Promise; + checkpoint(handle: ReceiptHandle, phase: ReceiptPhase): Promise; + close(handle: ReceiptHandle, outcome: ReceiptOutcome): Promise; +} +``` + +`[PROPOSAL]` Deterministic-testing and production-approval seams exist only where they are +justified: a `Clock` (`now()`), an `IdSource` (`newId(kind)`), and a `SignaturePolicy` (`sign(plan)` +/ `verify(plan, signature)`). **Verify is not a provider method.** It is a NetScript operation +composed from `ProviderControl.inspect` plus a manifest comparison plus ownership classification — +which is what keeps drift semantics identical across providers. + +Provider registries are immutable composition-root **data**. There is no global registry, no +`register()` call, and no lookup by string from arbitrary code: + +```ts +const control = createDatabaseControl({ manifest, providers: [prismaPostgres], connections }); +``` + +### The runtime layer + +```ts +// @netscript/database-runtime +export interface TargetRef { + readonly target: TId; + readonly manifestDigest: ManifestDigest; +} + +export interface TargetSession { + readonly target: TId; + readonly scope: TScope; + readonly snapshot: ContractSnapshotId; + /** The provider's own surface, supplied by generated app-local code. NetScript never names it. */ + readonly query: TQuery; + health(signal: AbortSignal): Promise; +} + +export interface ProcessTargetSession + extends TargetSession { + transaction(run: (tx: TQuery) => Promise, options?: TransactionOptions): Promise; +} + +/** Request scope is disposable and caches no collaborators. It has no `transaction`. */ +export interface RequestTargetSession + extends TargetSession, AsyncDisposable {} + +export declare function createDatabaseRuntime( + options: DatabaseRuntimeOptions, +): Promise; +``` + +`[PROPOSAL]` Scope is a **type**, not a configuration flag. `[RC1]` This mirrors an upstream design +precedent rather than inventing one: the Prisma serverless facade deliberately creates an +async-disposable runtime per request and omits the closure-cached `orm`, `runtime()`, and +`transaction()` surfaces that would be unsafe in that lifecycle. Making the asymmetry a type +prevents the class of bug where a closure caches a per-request handle. + +Runtime lifecycle: + +```mermaid +stateDiagram-v2 + [*] --> created: createDatabaseRuntime(manifest, providers, targets, scope) + created --> binding: resolve ConnectionSource per target/role + binding --> refused: digest/snapshot mismatch, capability gap, unsupported target + binding --> ready: provider runtime constructed, health probe passes + ready --> degraded: health probe fails + degraded --> ready: health probe recovers + ready --> stopping: stop() or AbortSignal + degraded --> stopping: stop() or AbortSignal + stopping --> stopped: sessions drained, connections closed in reverse bind order + refused --> [*] + stopped --> [*] +``` + +`[PROPOSAL]` Guarantees that must be proven by A3 runtime gates: + +- **One lifecycle owner.** The runtime constructs the provider runtime; there is no `setClient` and + no circular assembly in which the caller builds a driver, builds a client, and hands it back + `[NS-SRC]`. +- **Close ordering.** Sessions drain before connections close, and connections close in reverse bind + order. Repeated start/stop and request lifecycles are leak-free under test. +- **Cancellation.** Every long-running call takes an `AbortSignal`; cancellation is observable in + the receipt and never leaves an orphaned connection. +- **Readers cannot migrate.** A `reader:*` role produces a read-only session type and is not + addressable by any control operation. +- **Redaction.** Connection strings, passwords, and secret references never appear in diagnostics, + receipts, or logs. This is a conformance case, not a convention. +- **Bind refuses mismatch.** `ManifestDigest` and `ContractSnapshotId` are checked at bind time. + +### The runtime validation subsystem + +This is the second primary axis of the RFC, and it is the one where an attractive inference is +easiest to over-sell. The design is deliberately bounded and fails closed. + +#### What the evidence actually supports + +`[EXCHANGE]` The owner/maintainer exchange (public `#prisma-next` channel, 2026-03-05/06) proposed +deriving Standard Schema validation from Prisma's machine-readable contract, and the maintainer's +reply sharpened it toward deriving validators **at runtime** rather than through a generation step. +This is exploratory direction. It is not an upstream roadmap commitment and it is not evidence that +a stable public validation API ships in Prisma 8. + +`[RC1]` The pinned source both supports and limits that direction: + +- The contract carries a bounded runtime value algebra: scalar codec references, value objects, + unions, mandatory nullability, `many`, `dict`, and value-set references + (`packages/1-framework/0-foundation/contract/src/domain-types.ts:5-39`), with relations and + cross-space coordinates explicit (`:41-75`, + `packages/1-framework/0-foundation/contract/src/cross-reference.ts:5-14`). SQL storage adds native + type, codec parameters/references, defaults, nullability, and value sets + (`packages/2-sql/1-core/contract/src/ir/storage-column.ts:15-25`). +- **The complete operation/result type universe is not runtime data.** SQL field, operation, codec, + and aggregate type maps are installed under an optional phantom key + (`packages/2-sql/1-core/contract/src/types.ts:90-139,207-215`) and are emitted into + `contract.d.ts` (`packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts:179-221`). + They are erased at runtime. This is the decisive evidence against "the contract alone has all of + Prisma's type semantics." +- Plans retain enough for **direct** projections and not more: SQL projections carry alias, + expression, and an optional codec reference, and the source states outright that the codec is + absent for computed expressions, subqueries, and raw aliases + (`packages/2-sql/4-lanes/relational-core/src/ast/types.ts:1480-1505`). +- Prisma's existing Standard Schema usage validates **codec parameters**, not model values + (`packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts:27-54`); a + `Codec` itself carries conversions only (`shared/codec.ts:16-32,34-51`). +- There are **three** representations, not two: application runtime, database-driver wire, and + target JSON (`shared/codec.ts:16-30,44-51`). +- Contract spaces are separate identities: the migration aggregate exposes app and extension + contracts per space rather than merging them + (`packages/1-framework/3-tooling/migration/src/aggregate/types.ts:32-79,81-123`), and cross-space + domain checks are deferred to aggregate deployment + (`packages/1-framework/0-foundation/contract/src/validate-domain.ts:140-147`). +- No existing section hash is a sufficient validator identity: hashing separately covers storage, + execution, and capability profile + (`packages/1-framework/0-foundation/contract/src/hashing.ts:74-106`) while domain, roots, and + extensions can change independently. + +`[POST-RC]` The post-RC object adds a generated contract JSON Schema that the source labels +lossy/advisory with ArkType authoritative +(`packages/2-sql/2-authoring/contract-ts/src/data-contract-json-schema.ts:10-15,31-38,68-110`). That +improves validation of `contract.json`. It adds no model-data schemas, no codec value predicates, +and no universal result-shape metadata. It corroborates direction; it does not change RC1 +capability. + +#### The public API + +```ts +// app-local, via the generated AppBinding +const users = binding.space('app').model('User'); + +/** Whole-model value in a public representation. */ +users.value(options: { representation: ValidationRepresentation }): StandardSchemaV1; + +/** Operation input. Available only with contributed exact operation metadata. */ +users.operation(op: string, options: { representation: ValidationRepresentation }): StandardSchemaV1; + +/** Selection-aware result. Available only when every leaf is fully known. */ +users.result(selection: SelectionInput, options: { representation: ValidationRepresentation }): StandardSchemaV1; +``` + +`[PROPOSAL]` The only public representations are `runtime` and `json`. **Driver wire is +adapter-internal** and is never a public option, because calling JSON "wire" is ambiguous against a +codec layer that genuinely has three channels. + +#### Three schema classes with different guarantees + +| Class | Guarantee | Refusal boundary | +| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Model value | Validate a named model, value object, or enum in `runtime` or `json` with an explicit object-presence policy. | Never implies that database uniqueness, foreign keys, or check constraints are locally satisfied. | +| Operation input | Available **only** when the provider or an extension contributes runtime operation grammar and a typed binding for that exact operation. | Prisma create/update/filter/nested-write/polymorphic semantics absent from runtime contract data fail at construction. | +| Result | Validate a whole model, or a fully-known direct projection whose alias, codec, nullability, and representation are all known. | Computed, subquery, raw, aggregate, include, and unknown leaves require an explicitly contributed result schema or fail at construction. | + +Hiding those three behind one `input()` method would hide materially different guarantees, so the +API does not. + +#### The supported `ValidationIR` algebra + +`[PROPOSAL]` `ValidationIR` is **internal** — it is never exported, and it is never a second entity +or query model. It is closed per interpreter ABI and supports exactly: + +- registered scalar codec leaves; +- nullability; +- `many` lists and `dict` values; +- value objects; +- value sets, domain enums, and resolvable provider native enums (membership resolved from the value + set or native-enum entity, **not** inferred from a codec id — `[RC1]` the PostgreSQL native-enum + codec is a string pass-through that does not carry members, + `packages/3-targets/3-targets/postgres/src/core/codecs.ts:374-388`); +- unions only where branch identity is deterministically discriminable; +- model fields and relations whose cross-space references resolve through an integrity-verified + aggregate; +- whole-model values with an explicit presence policy; and +- direct-column selection/returning projections with complete alias, codec, nullability, and + representation metadata. + +#### Mandatory fail-closed cases + +`[PROPOSAL]` Schema **construction** throws a deterministic `DB_VALIDATION_UNSUPPORTED` with stable +coordinates (target, space, snapshot, model, operation or selection, representation, and the missing +metadata) for at least: + +1. an unknown codec, or a codec with no representation-specific value schema; +2. an unknown provider pack entity kind; +3. a corrupt or missing aggregate space, head, hash, cross-space reference, or value set; +4. ambiguous unions, or model variants/discriminators that cannot be resolved for the request; +5. Prisma operation grammar that is absent from runtime data: filters, relation traversal, nested + writes, polymorphic narrowing, and default/presence semantics with no contributor; +6. computed, subquery, raw, aggregate, include, or unknown result leaves with no explicit result + shape; +7. opaque SQL index or check expressions, which are information-losing rather than validatable; +8. database-state constraints — uniqueness, foreign keys, exclusion — which are not local value + validation and are never advertised as such; +9. asynchronous or non-deterministic value predicates where the requested Standard Schema mode + promises synchronous validation. + +No unsupported case becomes `unknown`, a pass-through, or a warning. `[RC1]` This is deliberately +**stricter** than the provider's own decoders, which accept missing codecs and pass through unknown +shapes (`packages/2-sql/5-runtime/src/codecs/decoding.ts:164-186,198-223`) — a decoder's job is +decoding, and a validator's job is refusing. + +Invalid **values** behave differently and never throw: they return Standard Schema issues carrying a +stable code, target, space, contract digest, model/operation/selection, representation, field path, +expected class, and observed value class. + +#### Codec contributions + +`[PROPOSAL]` A built-in or custom codec is supported only when its contributor supplies a +deterministic value schema for **every** advertised public representation: + +```ts +defineValidationCodec({ + codecId: 'pgvector.vector@1', + representations: { + runtime: vectorRuntimeSchema, // StandardSchemaV1 + json: vectorJsonSchema, // StandardSchemaV1 + }, +}); +``` + +`[RC1]` Encode/decode functions are **not** validation: a custom codec requires conversion functions +and a JSON round trip but no value predicate (`mongo-codec/src/codecs.ts:23-42,44-82`), and +conversion success is compatible with arbitrary coercion. The ArkType JSON extension documents the +consequence directly — its no-emit type may be `unknown` and encoding does not validate, so an +invalid write can reach the database and fail only on `RETURNING` decode +(`packages/3-extensions/arktype-json/README.md:7-17,40,74-87`) `[RC1]`. A codec without +representation-specific schemas is unsupported and fails closed. + +#### Cache identity + +`[PROPOSAL]` A derived validator's cache key is: + +```text +digest(canonical full-contract snapshot) + + contract schema version + + spaceId + + target / family + + operation name or normalized selection shape + + representation + + interpreter ABI version + + codec/pack contributor id and version + + execution identity where defaults matter +``` + +`[RC1]` Storage hash alone is insufficient: domain, roots, and extension semantics can change +without storage changing, and the plan metadata carries only storage and profile hashes +(`contract/src/types.ts:223-232`). Invalidation is by construction — the key contains contract +identity, so a contract change produces new keys rather than a stale hit. Plugin spaces cache under +their own `SpaceId`, so upgrading one plugin does not evict the application's schemas. + +#### Trust-boundary policy + +`[PROPOSAL]` + +- Input/model-value validation is **mandatory** at external mutation boundaries wherever a supported + schema exists. +- Output validation is **mandatory** for declared API/RPC responses, SSR/hydration payloads, and + external-service messages, and **opt-in** for internal query loops. Validating every row on every + read is a real cost, and a design that validates everything by default gets disabled wholesale, + which is worse than one that validates precisely at boundaries. +- An input failure is a client error with field paths. An output failure is a server/contract error + **and** a drift signal, because the database and the contract have diverged. +- Contract-space plugin fields participate automatically once aggregate integrity is verified. +- oRPC, Fresh, forms, and SSR consume the same Standard Schema values. Adapters must not regenerate + library-specific mirrors, and NetScript does not re-export Zod, Valibot, ArkType, or Prisma's + contract-document validators. + +#### Optional ahead-of-time projection + +`[COND]` An AOT projection **may** ship, under three conditions that keep it an optimisation rather +than a second source of truth: it is content-addressed, target-scoped, atomically replaced, and +never patched; it passes the identical semantic corpus as the runtime interpreter across successes, +issue paths, representation behaviour, unsupported-construction failures, contract-space resolution, +and cache invalidation; and no code path requires it. If mechanical equivalence cannot be +demonstrated, AOT is a mirror validator wearing a different name and is dropped (D-25, D-43). +Nothing in this RFC claims AOT validation exists. + +#### What is explicitly not claimed + +`[PROPOSAL]` NetScript does **not** claim full Prisma create/update/filter/nested-write/result +parity derived from contract data. Supporting all of it would mean rebuilding Prisma's operation +type system in the validator, which is the "second ORM" failure this architecture exists to avoid. +The supported subset is stated above; everything outside it fails closed. + +### The control plane + +#### The operation catalog is the source; everything else is a projection + +```ts +export interface OperationCatalog { + readonly version: string; + readonly operations: readonly OperationDescriptor[]; + readonly diagnostics: readonly DiagnosticDescriptor[]; +} + +export interface OperationDescriptor { + readonly name: OperationName; + readonly class: OperationClass; + readonly summary: string; + readonly request: StandardSchemaV1; + readonly result: StandardSchemaV1; + /** Serialisable projection used to generate CLI flags, help, docs, and agent instructions. */ + readonly jsonSchema: JsonSchemaDocument; + readonly diagnostics: readonly DiagnosticCode[]; + readonly nextActions: readonly NextActionDescriptor[]; + readonly examples: readonly ExecutableExample[]; +} + +export type OperationName = + | 'classify' + | 'compose' + | 'emit' + | 'inventory' + | 'preview' + | 'inspect' + | 'plan' + | 'sign' + | 'apply' + | 'verify' + | 'resume' + | 'seed' + | 'adopt' + | 'studio'; +``` + +`[PROPOSAL]` CLI commands, `--help`, generated documentation, and agent instructions are generated +projections of this catalog. A freshness gate regenerates them and fails on any diff, and a +conformance case executes every `ExecutableExample`. `[PRIMARY]` The upstream project's own RC-era +agent skill demonstrates why: it shipped with legacy internal import paths and obsolete error-code +vocabulary, and its references contradict the runtime surface on whether raw SQL and prepared +statements are available. Hand-maintained agent instructions decay within a release; generated ones +cannot. + +#### Operation classes + +| Class | Examples | May resolve | Lock | Receipt | +| ----------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | -------- | ---------------- | +| `pure` | `classify`, `compose`, `emit`, `inventory`, offline `preview` | Source/artifact readers and the atomic publisher only. **Never** a connection, Aspire, Docker, secrets, or the network. | No | Artifact receipt | +| `live-read` | `inspect`, live `preview`, `plan`, `verify` | An explicit target connection | No | Yes | +| `mutating` | `apply`, `seed`, `sign`, `adopt` baseline, space retirement | An explicit target connection, provider lock/fencing, and a bound plan where applicable | Yes | Yes | +| `resident` | `studio`, and any operation whose connection exists only inside a running host | An explicit target and an orchestration binding | Advisory | Yes | + +`[PROPOSAL]` **Aspire is a property of a target's connection source, never an operation class.** The +structural closure of `DB-GENERATE-ASPIRE-COUPLING` is that a `pure` operation is never given a +connection resolver at all, so it cannot reach an orchestrator even by mistake. + +#### Composition + +```mermaid +stateDiagram-v2 + [*] --> authored + authored --> resolving: compileDatabase(definition, sources) + resolving --> refused: diagnostics (total Result, never a throw) + resolving --> resolved: manifest + warnings + refused --> [*] + resolved --> [*] +``` + +Resolution is pure and total. It validates declared identities; output/migration root isolation; +provider pins; target binding of every space; capability subsets; ownership disjointness; dependency +closure and acyclicity; cross-target reference refusal; contribution provenance and contract format; +extension-bundle facet identity; and mirror integrity. Composition invariants, each with a +diagnostic and a negative test: + +| ID | Invariant | Diagnostic | +| --- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | +| V-1 | Every space binds to exactly one target. A space never spans databases. | type error / `db.target.ambiguous` | +| V-2 | Every `ObjectKey` has exactly one `managed` owner; a managed owner overlapping an `external` declaration fails. | `db.compose.ownership.conflict` | +| V-3 | Cross-space references are legal only inside one target and only along a declared dependency edge. | `db.compose.cross-target-relation` | +| V-4 | The space dependency graph is acyclic; its topological order is recorded in the manifest. | `db.compose.dependency.cycle` | +| V-5 | Every space's required capabilities are a subset of its target's declared capabilities. | `db.compose.capability.missing` | +| V-6 | No two targets share an output root, a migration root, or a runtime binding key. | `db.compose.ownership.conflict` | +| V-7 | `ManifestDigest` is a pure function of definition + resolved snapshots + provider pins. Nothing environmental participates. | determinism gate | +| V-8 | Every emitted artifact root records the digest that produced it; a mismatch is detectable without a database. | `db.artifact.stale` | +| V-9 | Every extension facet shares one identity and version. | `db.compose.extension.facet-mismatch` | + +#### Preview, plan, policy, approval + +```mermaid +stateDiagram-v2 + [*] --> resolved + resolved --> speculative: preview (pure or live-read) + speculative --> not_applicable: no planId is ever issued + resolved --> inspected: inspect baseline (live-read) + inspected --> planned: ExecutablePlan created and bound + planned --> policy_refused: destructive policy / environment refusal + planned --> policy_allowed: policy decision recorded in the plan + policy_allowed --> approved: signature required by environment + policy_allowed --> ready: signature not required + approved --> ready + ready --> expired: expiresAt passed + ready --> stale: manifest, baseline, pins, or policy changed + ready --> revoked: explicitly revoked + ready --> apply + policy_refused --> [*] + not_applicable --> [*] +``` + +`[PROPOSAL]` A speculative preview is **never** accepted by `apply`; the type has no `planId` and no +code path coerces it. Consent is not an interactive prompt: in CI and production the policy must be +`allow-with-approval` **and** the plan must carry a signature. An interactive "yes" is a development +affordance only. + +#### Apply, checkpoints, and recovery + +```mermaid +stateDiagram-v2 + [*] --> planned + planned --> acquiring_lock + acquiring_lock --> refused: db.apply.lock.held (owner, nonce, TTL reported) + acquiring_lock --> locked + locked --> revalidating: re-check manifest, baseline, pins, policy, expiry + revalidating --> refused: db.plan.stale / db.plan.expired / db.plan.revoked + revalidating --> started + started --> applying + applying --> applying: atomic receipt checkpoint per irreversible step or provider transaction group + applying --> outcome_unknown: transport lost after dispatch + applying --> failed + applying --> cancelled: AbortSignal + applying --> applied + applied --> verifying + verifying --> verified + verified --> succeeded + failed --> cleanup_required: non-transactional step left objects behind + outcome_unknown --> inspect_before_resume + cleanup_required --> inspect_before_resume + cancelled --> inspect_before_resume + inspect_before_resume --> revalidating: resume, only for steps whose outcome is known and unfinished + succeeded --> [*] + refused --> [*] +``` + +`[PROPOSAL]` The rules that give this diagram teeth: + +- **Loss of transport after dispatch produces `outcome-unknown`, never `failed`.** `[PRIMARY]` This + is Pulumi's documented `pending operation` lesson: the engine cannot know whether the provider + completed the work, and recovery requires inspecting the provider before acting + ([interrupted updates][pulumi-interrupted]). +- **Resume always inspects live state and the provider ledger first**, revalidates the plan + bindings, and then continues only operations whose outcome is known and unfinished. It never + blindly replays non-idempotent DDL or a data transform. +- **Checkpoint granularity is per irreversible operation or provider transaction group**, never only + at end-of-target. +- **A ledger repair is not a database repair.** `cleanup-required` is a distinct outcome for exactly + the case Flyway documents, where a failed non-transactional migration leaves user objects that no + ledger operation removes `[PRIMARY]`. +- **Lock scope is `(target, physical database)`**, with an owner identity, a nonce, fencing evidence + where the provider supports it, a TTL, a heartbeat, documented stale-lock inspection, and explicit + safe force-unlock preconditions. A provider that cannot supply a certified lock is **refused for + concurrent-safe apply** rather than silently racing. Native advisory versus fenced-row mechanism + is certified per provider (D-42). +- **No shared stateful runner across targets.** Each target has its own runner instance, so the + unsupported configuration is unrepresentable rather than documented. + +#### Multi-target execution is a saga + +```mermaid +stateDiagram-v2 + [*] --> selection: explicit target/space set + selection --> closure: expand dependency closure, record every omission with a reason code + closure --> ordering: deterministic topological order + ordering --> per_target: separate runner, separate lock, separate receipt per target + per_target --> all_succeeded + per_target --> partial_success: at least one target failed, refused, or is outcome-unknown + partial_success --> resume_after_inspection + all_succeeded --> whole_manifest_verify + resume_after_inspection --> whole_manifest_verify + whole_manifest_verify --> [*] +``` + +`[PROPOSAL]` **Cross-target apply is never atomic and is never described as atomic.** There is no +cross-database transaction and no automatic rollback claim. Selective target/space execution is +recovery machinery, not the normal deployment path: it requires dependency closure, records omitted +work with reason codes, and mandates a subsequent whole-manifest verification. `[PRIMARY]` This is +Terraform's own documented position on `-target` — explicitly exceptional recovery, not a routine +selector ([resource targeting][tf-targeting]). + +### Targets, providers, namespaces, ownership, and spaces + +| Case | Kernel | Prisma 8 PostgreSQL adapter, first release | +| ---------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------- | +| Two PostgreSQL databases | Named targets, fully isolated | **Required.** Distinct artifacts, runtime, ledger, locks, receipts. | +| Multiple namespaces in one target | First-class kernel identity axis | **Withheld** `[COND]` — see D-37 below. | +| Writer / read replicas | Roles on one target | Conditional runtime capability; a reader is read-only and never migrates. | +| App plus independently versioned plugin spaces | Required | **Required.** Independent artifacts, heads, dependency order, package-free apply/verify. | +| `managed` / `adopted` / `external` / `ignored` | Required | **Required.** Ownership-aware plan, verify, and drift. | +| Process / request scope | Distinct types and lifecycles | **Required.** | +| Prisma SQLite / MongoDB / MySQL / SQL Server | Provider and family axes remain open | **Explicitly unsupported.** `db.target.unsupported`; no fallback, no Prisma 7 path. | +| Cross-target relation or transaction | Not representable | Structured composition refusal. | +| Provider-specific query features | Capability-visible | Native provider surface, app-local. No portable wrapper. | + +#### The namespace capability is withheld, and why + +`[RC1]` Prisma's runtime lowering honours per-model namespaces, but the authoring type maps do not: +the source states that the authoring path lumps every model under the default storage namespace and +leaves additional namespace maps empty +(`packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691`; independently re-verified +during PLAN-EVAL cycle 2). `[POST-RC]` The audited post-RC object retains the limitation. + +`[PROPOSAL]` `NamespaceRef` therefore stays a first-class **kernel** identity axis — manifests, +ownership, object keys, and plans all carry it — while the adapter **must not advertise a +multi-namespace capability** until exact type/runtime parity passes with **no casts, no private +imports, and no flattening workaround**. If upstream never fixes it, the kernel carries an unused +axis and nothing else needs rework. This is a withheld claim, not a blocked architecture (D-37). + +#### Ownership + +| Policy | Planned | Mutated | Verified | Typical source | +| ---------- | ------- | ------- | ------------------------------------- | -------------------------------------------------------------------- | +| `managed` | Yes | Yes | Fully | An app or plugin space that owns the objects. | +| `adopted` | Yes | Yes | Against an explicit reviewed baseline | Objects brought under management by `db adopt` or retention. | +| `external` | No | No | Against declared assertions only | Hosted platforms and upstream extensions that own their own objects. | +| `ignored` | No | No | No | Deliberate exclusion with an auditable recorded reason. | + +`[PROPOSAL]` Rules: exactly one `managed` owner per `ObjectKey`; identical declaration text from two +contributors is still an ownership conflict; namespaces prevent lexical collisions but never replace +ownership checks; cross-space references require the same target plus a declared dependency edge; +and augmentation is an **owner-granted closed permission**, never an implicit merge — the absence of +a grant is a denial, and unsupported modification either asks the owner or becomes an app-owned +migration. `[PRIMARY]` The `external` policy is not an edge case: a hosted database whose tables +evolve outside the framework's knowledge is the normal shape of a managed service, and upstream has +a recorded instance of a pinned extension contract diverging from an externally-evolving database +and failing verification ([prisma#29896][pn-29896]). + +#### Plugin and contract-space lifecycle + +```mermaid +stateDiagram-v2 + [*] --> declared + declared --> installed: capabilities, dependencies, ownership, provenance validated; mirror pinned + declared --> install_refused: overlap, missing/cyclic dependency, contract-format skew, unsupported capability + installed --> upgraded: lineage path from the pinned head resolves + upgraded --> installed + installed --> upgrade_refused: ownership widening, incompatible contract format, capability regression, ambiguous branch + upgrade_refused --> installed + installed --> skew_refused: installed package digest != mirror digest (db.space.skew) + skew_refused --> installed: resynchronise the mirror + installed --> detached: runtime/package binding removed + detached --> retained: data, marker, tombstone, and ownership history preserved; managed downgraded to adopted + detached --> detach_refused: a dependent space is still installed + retained --> archived: conditional on provider capability and conformance + retained --> dropped: conditional on destructive policy, approval, dependent closure, verified lineage + retained --> [*] +``` + +| Transition | Guarantee in the first release | Status | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| Install | Validate target, capabilities, dependencies, ownership, provenance; pin the mirror; recompile; produce a plan. | Required | +| Upgrade | Require a lineage path from the pinned head; pin the new mirror; plan each changed edge. | Required | +| Skew | Refuse mutation whenever package, mirror, manifest, and marker identities disagree; the diagnostic names every identity. | Required | +| Detach + retain | **The only guaranteed removal.** Data, marker, mirror tombstone, and ownership history are preserved; ownership is downgraded `managed → adopted` so verify keeps seeing the objects. | Required | +| Archive | Planned relocation to a quarantine namespace with a restoration path. | `[COND]` — conditional on provider capability + conformance (D-46) | +| Drop | Destructive plan with explicit policy/approval, dependent closure, and verified lineage. | `[COND]` — never a directory delete, never claimed for v1 | + +`[PRIMARY]` Contract spaces solve ownership and history; they do not solve removal — extension +removal is not a supported RC capability. This RFC defines the whole vocabulary now and guarantees +only `retain`. + +#### The pinned mirror + +```text +.netscript/database/spaces/plugin--netscript--plugin-auth/ + space.json # descriptor snapshot: id, owner, version, requires, dependencies, owns, ownership + contract.json # the space's canonical contract artifact at the pinned version + contract.d.ts # the space's declaration artifact + lineage/ # the space's own migration lineage nodes + PROVENANCE # package identity, resolved version, integrity hash, mirror digest +``` + +`[PROPOSAL]` Production apply and verify read the mirror, never the installed package graph, so a +deployment does not need plugin packages resolvable. The mirror digest is comparable against the +installed package digest, which makes version skew detectable rather than latent. Half-installation +— a schema contribution present without its runtime/codec half, or the reverse — is a composition +error, because both halves are named by one contribution record. + +### CLI, agents, and CI + +`[PROPOSAL]` The CLI is a rendering layer over the operation catalog. It owns argument parsing, +human-readable output, and exit-code projection, and it owns no database logic. Machine output is +the contract; human text never is, and no gate may assert on a message string. `[NS-SRC]` The +current merge-readiness migration fixture asserts on a literal message and refuses to run outside +Linux — both are removed by this design, and Windows coverage becomes a required conformance row. + +Exit-code projection is fixed: `succeeded` → 0; `refused` and `failed` → non-zero; `partial-success` +→ non-zero **with** a resume token in the machine result. An exit code is never the result. + +How this shortens and stabilises CI: + +| Mechanism | Effect | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | +| `pure` compilation and emission with no connection, Aspire, Docker, or network | The most common CI database step stops needing an orchestrator at all. | +| Content-addressed `ManifestDigest` as a cache key | A job that already emitted for a digest asserts the recorded digest instead of re-emitting. | +| Atomic staged-then-committed artifact roots | An interrupted job leaves a fully old or fully new root; no half-patched tree to diagnose. | +| Real-service stages bounded to named gates | Expensive PostgreSQL work runs where it is required, not on every step. | +| Structured receipts reused across jobs | Evidence is machine-readable and survives log loss. | +| Removal of hand-patching and repair workflows | An entire class of order-dependent, non-idempotent CI steps disappears. | + +`[PROPOSAL]` **No unmeasured CI reduction is promised.** The implementation program defines the +measurements and their release thresholds instead: wall-clock and orchestrator-start count for the +pure emission path (target: zero orchestrator starts, enforced as a hard gate rather than a +threshold); cache-hit rate for unchanged manifest digests; flake rate of the database gates over a +rolling window; and the number of gates asserting on message strings (target: zero, enforced). A +percentage improvement claim would be a guess, and this RFC does not make one. + +### The consolidated refusal boundary + +`[PROPOSAL]` These refusals are the architecture. Each is mechanically checkable, and each has a +conformance row in [Appendix D](#appendix-d-conformance-matrix). + +1. **No query DSL, repository, ORM, or portable client facade.** The kernel packages contain zero + query types; the provider's query surface reaches the application as a generic argument. +2. **No compatibility layer.** No Prisma 7 facade, legacy generated module, dual client, `setClient` + lifecycle, alias barrel, copied schema bridge, dual migration history, or runtime shim. +3. **No false portability.** Capabilities are visible and statically checked; unsupported targets + and operations fail explicitly rather than degrading. +4. **No runtime capability negotiation.** Capabilities are open namespaced **static declared data**. +5. **No global mutable provider registry and no service locator.** Provider registries are + composition-root values; `bind` is reachable only from composition roots and generated code. +6. **No hosted control plane.** No RBAC, approval service, registry/promotion, fleet scheduler, + continuous-drift agent, KMS, notification service, or permanent audit server. +7. **No validation overclaim.** The bounded algebra above, failing closed at construction. +8. **No upstream re-export.** Only the PostgreSQL adapter imports Prisma runtime/control modules, + through one facade module and an allowlist. +9. **No text-patched generated source.** Artifacts are produced from an IR and replaced atomically, + or they are not produced. +10. **No implicit target selection.** No primary-ish fallback, no first-available fallback, no + silent single-target execution of a multi-target command. +11. **No arbitrary TypeScript during production apply.** CI and production consume canonical + verified artifacts (D-40). +12. **No cross-target atomicity, cross-database relation, or cross-database transaction.** + +## Drawbacks + +`[INFERENCE]` The honest costs of this proposal, stated without softening. + +**It is a large program, and it lands as a break.** Twelve waves, six new packages, changes to four +existing ones, a doctrine amendment, a first-party plugin conversion, and a cutover. No individual +wave is exotic, but the sequence is long, and until W10 the repository carries both the old and the +new foundation (on separate branches or release lines). Anyone who wants a small change here will +find that the smallest coherent unit is still substantial, because the operation contract — not a +missing feature — is what is being replaced. + +**It bets on an Early-Access upstream.** Prisma 8 RC1 is explicitly not recommended for production, +its release notes warn that RC respins may break APIs and the contract format, and the integration +seam demonstrably moved within six days of the tag `[PRIMARY]` `[POST-RC]`. The mitigation — one +adapter package, one facade module, an import allowlist, independent versioning, and a kill switch +that costs a provider rather than the architecture — is real but not free: it adds a package +boundary and a translation layer that a direct dependency would not need. + +**It adds indirection where a direct call used to be.** A definition compiles to a manifest, which +binds a plan, which yields a receipt. For a solo developer running one PostgreSQL database, this is +more moving parts than `prisma migrate dev`. The pay-off arrives with the second target, the first +plugin space, the first partial failure, and the first production apply — not on day one. + +**Six new published packages is a real maintenance surface.** Each carries JSR obligations: export +maps, include lists, module docs, runnable examples, isolated declarations, doc-lint, dry-run, +publish-list inspection, and packed-consumer install. Splitting definition from runtime from control +is correct by archetype and gate profile, but it is four packages where a less disciplined design +would ship one. + +**The typed binding is generated, and generation is a step.** `isolatedDeclarations` and the +oRPC-only slow-types carve-out mean the inferred contract type cannot be published from a framework +package `[NS-SRC]`, so it terminates in a generated application-local module. That is a build step, +and a stale one is refused rather than tolerated — correct, but it does mean a developer can be told +"re-emit" at an inconvenient moment. The alternative was a permanent framework publish debt. + +**Validation is deliberately narrower than users will initially want.** "Derive all my validators +from the schema" is the intuitive expectation, and this design refuses it for filters, nested +writes, polymorphic narrowing, and computed/raw/aggregate results unless exact metadata is +contributed. Some users will experience `DB_VALIDATION_UNSUPPORTED` as a missing feature. It is a +correct refusal, and the RFC would rather explain it than silently return a schema that accepts +wrong data. + +**Some capabilities regress relative to today.** Prisma SQLite, MongoDB, MySQL, and SQL Server are +not carried forward; multi-namespace end-to-end typing is withheld; destructive plugin removal is +not guaranteed. These are deliberate (D-34, D-37, D-46) and each names the gate that would release +it, but a user who has a MySQL target today has no migration path inside this design other than +staying on the old release line until a certified provider exists. + +**One soundness seam is accepted rather than eliminated.** `runtime.bind` cannot prove that the +provider's runtime value matches the erased `TQuery`; three gates mitigate it (generation, digest +verification, a mismatch conformance case) but the seam is real and is named in +[the type propagation section](#the-one-deliberate-soundness-seam) rather than hidden. + +**The conformance matrix is expensive.** Real PostgreSQL, Windows and Linux, failure injection, +crash and unknown-outcome recovery, packed consumer installs, and a two-consumer Standard Schema +corpus are all required before the adapter is advertised. That cost is the point — it is what turns +"upstream says it is supported" into "NetScript proved it" — but it is a standing CI bill. + +## Rationale and alternatives + +### Why this shape + +`[INFERENCE]` The design follows from four observations that the evidence forces: + +1. **The five current systems fail because nothing joins them.** A join point is therefore + mandatory. It must be a _value_ rather than a live object, because everything the design needs + from it — inspection, diffing, hashing, review, transport to CI, agent consumption, stale + detection — are properties of a serialisable value, and a live graph reachable from feature code + is a service locator with a domain name (D-03). +2. **Provider identity replaced target identity**, so identity must be declared and + provider-neutral, and every artifact must key off it (D-14, D-15, D-16). +3. **Prisma's contract/space/lineage semantics are genuinely good and its operational layer has + gaps** — no mature reset/resolve/diff/squash workflow, no general shadow-database workflow, no + complete advisory-lock story, no row-count-aware data-loss analysis, and no extension removal + `[PRIMARY]`. Waiting for upstream to close those gates adoption on someone else's roadmap; owning + them means NetScript keeps them when a second provider arrives (D-29). +4. **The publish constraint decides where types live.** `isolatedDeclarations` plus the oRPC-only + carve-out is not a style rule; it determines that the inferred binding is generated app-side + (D-08). + +### Alternatives considered and rejected + +| Alternative | Why rejected | +| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Keep Prisma 7 and add Prisma 8 as an opt-in pilot** (issue #313's shape) | It preserves every seam in [Motivation](#the-problem-is-not-a-prisma-version). The current architecture is what a compatibility-first constraint produced; repeating the constraint reproduces the outcome. Owner directive is explicit. | +| **A one-to-one migration of the current design onto Prisma 8** | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are all independent of the Prisma major version. | +| **A proprietary NetScript schema DSL that lowers to the provider contract** | A third schema language that must track every native type, index kind, constraint, and default; permanently lagging; error messages become a translation of a translation. This is the clearest instance of the second-ORM failure. | +| **Recreate the deleted fluent `target/table/column` builder** | It was real at `fd88abf4` and was deliberately removed upstream `[PRIMARY]`. Recreating it for familiarity would mean maintaining a dead API against a live one. | +| **A live `DatabaseGraph` as the public artifact** | A runtime graph accretes traversal APIs and becomes a lookup surface. The manifest gives every property the graph was wanted for, and a graph survives only as private compiler IR (D-03). | +| **A global mutable provider registry** | Publishing a mutable registry is how a service locator is born. Registries are composition-root data (D-13). | +| **Re-export Prisma from a NetScript package** | Doctrine AP-14, plus the publish constraint, plus 138 upstream export keys at the pin `[RC1]` — a re-export converts Early-Access internals into NetScript public API. | +| **A portable query client across providers** | A lowest-common-denominator surface weakens every provider and hides real semantics. Provider-specific queries stay native and app-local (D-05). | +| **Generated mirror validators (a schema file per model/input/output)** | Combinatorially wrong for selection-aware output validation, and it recreates the import-rewriting/circular-reference/getter/decimal repair pipeline that already failed here `[NS-SRC]`. | +| **Claim full operation/result validation from contract data** | The pinned source shows the operation and result type maps are phantom and erased at runtime `[RC1]`. The claim would be false. | +| **Copy plugin schema fragments (status quo)** | No version, ownership, capability guard, dependency order, provenance, or safe removal — with two recorded production failures. | +| **CLI as the business logic (status quo)** | An exit-code result type makes structured reporting impossible; the CLI must be a projection (D-27). | +| **Build a hosted control plane (registry, RBAC, approvals, drift agents)** | Those are persistent products with operators, not local primitives. Atlas Cloud, Pulumi Cloud, and Bytebase demonstrate the value **and** the required services `[PRIMARY]` (D-31, D-47). | +| **Pre-build a direct-SQL contingency provider to prove the SPI** | It would recreate low-level database machinery to prove a hypothesis. A second **real** provider certifies the SPI when demand and maturity exist (D-44, W11). | +| **Extend the `--allow-slow-types` carve-out to database packages** | It converts an application-local inference problem into permanent framework-wide publish debt, and doctrine records any other package setting it as a finding `[NS-SRC]`. | + +### Market lessons, as architecture rather than a feature list + +`[PRIMARY]` Seventeen comparators were examined. What matters is not their feature lists but the +architectural pressure each one applies. The full comparison is in [Prior art](#prior-art); the +lessons that changed this design are: + +- **One resolved manifest, not many config files.** Named connections in Adonis, Rails, and Django + are legible; Atlas proves multiple schema sources can compose. Neither gives a deterministic, + content-addressed resolved value, and Atlas's composite ordering is load order rather than + declared semantic edges. +- **Contributor-owned migration spaces.** Django's per-app graphs with declared cross-app + dependencies and Prisma's contract spaces are the two strong ownership models. Flyway locations + and Liquibase changelogs merge into one shared history, which is why they cannot express + contributor isolation regardless of their tooling quality. +- **Native authoring with framework policy around it.** ZenStack v3 is the closest comparator for + schema/runtime composition and runtime-derived, selection-shaped validators — and its plugin + surface is preview, its validators are Zod-specific, and schema-time and runtime installation can + diverge. NetScript binds both halves in one contribution record and keeps Standard Schema as the + boundary. +- **Apply-bound plans.** Atlas's develop → review → deliver → apply model is the right process + shape; Terraform and Pulumi add the harder lesson that a preview is not an executable plan and + that applying a valid plan is not an atomic transaction. +- **Managed versus external ownership.** Rails' `database_tasks: false`, Drizzle's filters, Atlas's + external sources, and the upstream Supabase drift incident all point the same way: a framework + that treats every visible object as its own reports permanent false drift. +- **Capability-specific behaviour instead of false portability.** MikroORM and Django document + provider differences rather than hiding them; Kysely exposes dialect behaviour honestly. +- **A programmatic core with CLI and agent projections.** Adonis, MikroORM, Kysely, and Atlas all + expose programmatic runners. The CLI should be the thin layer, not the seat of the logic. +- **Separate source, manifest, plan, ledger, and receipt.** Terraform's four-way separation of + configuration, saved plan, mutable state, and backend is the clearest prior art — and its mutable + state is precisely what NetScript must **not** build. + +`[PROPOSAL]` What a **local** meta-framework must not rebuild, stated as scope law: hosted RBAC; +organisation, workspace, and fleet management; remote schema registries and environment promotion; +policy-as-a-service; approval and issue-tracking engines; and continuous drift control planes. Each +of those is a persistent service with operators and an availability budget. NetScript exposes stable +artifacts and integration events so such a system can be added as an adapter, and integrates with +Bytebase or Atlas optionally rather than reimplementing them (D-31, D-47). + +### The impact of not doing this + +`[INFERENCE]` Covered in [Motivation](#what-it-costs-to-not-do-this): two same-provider databases +stay unrepresentable, plugin schema stays a regex copy, CI keeps paying for an orchestrator on pure +generation, success keeps being an exit code, generated source keeps being repaired textually, and +the auth roadmap's deterministic plugin-aware migration requirement has nowhere to land. + +## Breaking changes and migration + +**This is a breaking change.** The tracking issue and the RFC PR carry the `breaking` label. + +### The no-compatibility law + +`[PROPOSAL]` No backwards compatibility is allowed, and the prohibition is specific so that it +cannot be eroded one convenience at a time. None of the following survives: a Prisma 7 client or +facade; a legacy generated module or alias barrel; a dual client or `setClient` lifecycle; a +deprecated re-export; a dual migration history; a copied schema bridge; a runtime shim; or any code +path that selects between the old and new stacks. + +Old and new stacks may coexist **in the repository**, on separate branches or release lines, while +features are developed. A single application composition may never load both. That is a branch +strategy, not a public API, and it does not authorise a dual runtime. + +### What breaks + +| Surface | Break | +| -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database` (current adapters, `setClient`, scripts) | Replaced wholesale by the new package graph. Removed at W10. | +| `@netscript/prisma-adapter-mysql` | Retired. A hand-written low-level driver adapter is exactly the maintenance surface the redesign removes. | +| Generated engine workspaces `database//` | Deleted, along with the **42** generated `db:*` task keys per workspace, the repair scripts, and the generated Zod pipeline `[NS-SRC]`. | +| Generated client deep imports | Removed. Applications consume the generated `AppBinding`, never a filesystem path into generated output. | +| `@netscript/plugin` legacy database/migration contribution abstracts and their contribution-axis members | Removed at W7 with breaking-surface accounting; the seam is replaced by `defineDatabaseSpace` `[NS-SRC]`. | +| Plugin `database/**/*.prisma` fragments | Replaced by plugin-owned spaces with pinned artifacts. Copying stops. | +| The fourteen `db` CLI verbs | Replaced by operation-catalog projections; see the disposition table below. | +| Implicit target defaulting and silent single-target execution | **Deliberately removed.** There is no fallback chain anywhere. | +| Prisma SQLite / MySQL / SQL Server targets | Not carried forward (D-34). Structured `db.target.unsupported`, no fallback. | + +### The adoption protocol + +`[PROPOSAL]` `netscript db adopt` is a temporary migration codemod and tool. It is **not** a +compatibility layer, it is not a permanent command, and it is deleted after the migration window. + +| Step | Operation | Mutates the database? | Failure behaviour | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------- | ----------------------------------------------------------------------------------------------- | +| 1 | Read legacy configuration and generated layout (`appsettings.json` targets, engine mapping, workspace layout) | No | Refuse on ambiguous or duplicate config keys | +| 2 | Generate explicit target identities — **`TargetId` comes from config keys, never from provider or engine names** | No | Refuse when two config keys resolved to the same engine directory; the author must name them | +| 3 | Introspect every reachable target | No | Report unreachable targets; adoption proceeds for reachable ones only | +| 4 | Propose object ownership: one space per attributable owner (`app`, one per installed plugin) plus `external`/`adopted` classifications | No | Objects that cannot be attributed are reported, never guessed | +| 5 | **Hard-stop on unattributed or conflicting objects** | No | The author must resolve every unattributed object before continuing | +| 6 | Compile the manifest and atomically emit canonical artifacts and bindings | No | Standard composition diagnostics | +| 7 | Establish one baseline/root lineage node per space, matching the **observed** live state | No | Pure artifact work | +| 8 | Write provider marker metadata **only** — zero table or data DDL/DML | **Yes, markers only** | Idempotent and re-runnable; produces a receipt | +| 9 | Verify live state against the manifest and baseline; require zero drift | No | Any diff here is a genuine finding: an unattributed object or an incorrect ownership assignment | +| 10 | Delete legacy engine workspaces, the 42 per-workspace generated `db:*` task keys, copied plugin fragments, repair scripts, old adapters, and old dependencies — **only after verified adoption** | No | Reversible by reverting the commit | + +`[PROPOSAL]` The load-bearing property is step 8: **no table is created, altered, or dropped during +adoption.** That is what makes the migration safe on production data, and it is what makes step 10 +the only irreversible-looking step — while in fact touching only the repository. + +### Data-safety gates + +Every one of these is required before a release-class cutover: + +| Gate | Requirement | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Rehearsal | A seeded, production-shaped rehearsal proves adoption performs zero schema/data mutation, with the receipt as evidence. | +| Backup | A verified restorable backup exists before the first `mutating` operation in each environment. | +| Ownership preflight | A committed CI artifact listing every target with reachability and provider version, every `ObjectKey` with owner and policy, every unattributable object, every required capability against what each target declares, and every plugin fragment that cannot be attributed to an installed package. Unattributed objects are a hard stop. | +| Destructive consent | Destructive operations require a policy decision; in CI and production, an approved and signed plan. An interactive "yes" is never sufficient outside development. | +| Partial outcome | Multi-target adoption records per-target and per-space outcomes; `partial-success` is first class and carries a resume token. | +| Crash | A crash-fault injection run proves checkpoints, `outcome-unknown`, and inspect-before-resume behave as specified. | +| Marker | Marker writes are idempotent and independently removable before the first new `apply`. | +| Secret | No secret value appears in any plan, receipt, diagnostic, or log; a redaction conformance case proves it. | +| Lock | Lock acquisition, contention, TTL expiry, holder death, and safe force-unlock preconditions are exercised. | +| Release window | The migration window, the legacy release-line end date, and the rollback runbook are agreed before W10 begins. | + +### Rollback boundaries + +| Point | Rollback | Cost | +| ------------------------------------------------------ | ---------------------------------------------------------------------- | --------------------------------------------------------------------------- | +| Before step 8 | Delete generated artifacts | None; nothing was written to any database | +| After step 8, before the cutover commit | Remove the adopted spaces' marker rows where provider semantics permit | Trivial; markers are metadata | +| After the cutover commit, before the first new `apply` | Revert the commit | Repository-only; the database is untouched | +| After the first new `apply` | **Forward only** — through lineage, the provider ledger, and receipts | Ordinary migration recovery; the receipt identifies exactly which steps ran | + +`[PROPOSAL]` There is deliberately no "run both stacks" rollback. It would require the compatibility +layer this design refuses, and it would double the failure surface during precisely the window when +the system is least understood. + +### Verb disposition + +`[NS-SRC]` The fourteen current verbs map as follows. Parity is claimed only where the new operation +is a superset; everything else is stated as a deliberate removal or a behaviour change. + +| Current verb | Disposition | +| ------------ | --------------------------------------------------------------------------------------------------------------------------- | +| `add` | Replaced by editing the definition file. Scaffolding becomes a codemod, not a config rewrite plus helper regeneration. | +| `list` | `inventory` — superset: targets, spaces, ownership, capabilities, heads, and drift status as structured output. | +| `remove` | Replaced by the space retirement protocol. **Behaviour change:** removal produces a plan; it no longer deletes a directory. | +| `init` | `apply` against an empty baseline. | +| `generate` | `emit` — **now `pure`**, and structurally unable to reach an orchestrator. This closes `DB-GENERATE-ASPIRE-COUPLING`. | +| `migrate` | `plan` + `apply`, separated. **Behaviour change:** planning and applying are distinct operations with distinct policies. | +| `seed` | `seed`, a `mutating` operation with a receipt. | +| `status` | `verify` + `inventory`, structured. | +| `studio` | Retained as `resident`, but **must take an explicit target**; the silent first-target selection is removed. | +| `introspect` | `introspect`, feeding `adopt`. | +| `reset` | Retained, `mutating`, destructive-policy gated; refused in production regardless of consent. | +| `deploy` | `apply` with a signed plan and a production environment. | +| `validate` | `compose` — a `pure` operation returning complete diagnostics rather than a first error. | +| `resolve` | Replaced by explicit lineage operations against named nodes. | + +Two capabilities are removed on purpose and are stated as removals rather than gaps: **implicit +target defaulting**, and **silent single-target execution of a multi-target command**. + +## Prior art + +`[PRIMARY]` Seventeen comparators, examined for the framework-level problem rather than for ORM +popularity. Each row states the strongest transferable idea and the limitation that stops it being a +template. + +| Product | Strongest relevant idea | Limitation for NetScript | +| --------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| [Wasp][wasp] | Framework-owned commands and generated auth schema produce a coherent happy path | One framework-managed schema/client; schema combination is a special case, not an ownership protocol | +| [RedwoodJS][redwood] | Structural and data migrations are recognised as different concerns, with a data-migration ledger | Two sequences the developer must coordinate; replay ordering is a known hazard | +| [Payload][payload] | A thin internal database contract with official adapters in separate packages | The adapter is shaped around CMS collections; third-party schema gets no independent migration ownership | +| [Better Auth][better-auth] | Typed plugin schema declarations plus an adapter factory that centralises mechanics | With Prisma or Drizzle the user still generates ORM schema and merges/migrates it manually | +| [AdonisJS Lucid][lucid] | Named typed connections, framework-owned lifecycle, a programmatic runner, locks, dry runs | Ownership is configuration, not versioned contributor spaces; cross-connection apply is not atomic | +| [Drizzle][drizzle] | Broad dialects, inspectable SQL, schema filters that exclude externally-managed objects | Multiple configs are the composition mechanism; exported-declaration aggregation is a convention | +| [MikroORM][mikroorm] | Clean core/driver/extension split; programmable migration runner; documented provider caveats | One instance does not span independent connections; schema fan-out has stateful caveats | +| [Kysely][kysely] | Small open dialect/driver/plugin interfaces; honest typed raw SQL; migration-lock hooks | Type generation, schema source, and migration authoring are intentionally external and can drift | +| [Flyway][flyway] | Mature history states, checksum validation, database locks, structured repair, programmatic runner | Locations merge into one history; **repair does not clean objects left by a failed non-transactional migration** | +| [Liquibase][liquibase] | Changeset ledger and lock, preview, rollback, a broad extension surface | Path/order composition and one shared ledger; `update-sql` explicitly does not prove correctness | +| [Terraform][tf-state] | Explicit separation of configuration, saved plan, mutable state, and backend; honest partial-apply recovery | State is a mutable binding database, not a manifest or a receipt; saved plans are opaque and can carry secrets; targeting is exceptional | +| [Pulumi][pulumi-state] | Frequent checkpoints and first-class recovery for interrupted, outcome-unknown operations | Plan completeness is weakened by arbitrary program execution; robust checkpoint backends are a hosted concern | +| [Atlas][atlas-projects] | Composite schema sources, semantic lint, plan/review/deliver/apply, destructive-change policy | Composition is load order; registry, promotion, fleet history, and continuous drift are Cloud services | +| [Bytebase][bytebase-plan] | Plan → issue → rollout with stages, per-database tasks, SQL review, explicit skip reasons | A persistent control plane; **automatic schema drift detection was removed in 3.14.0** ([changelog][bytebase-3140]) | +| [ZenStack v3][zenstack-multifile] | Explicit schema imports, schema/CLI/runtime plugins, [runtime-derived selection-shaped validators][zenstack-zod] | One aggregate history; plugins are preview; validators are Zod-specific; schema-time and runtime installation can diverge | +| [Django][django-multidb] | Per-app migration graphs with declared cross-app dependencies; routing as a policy surface | Multiple databases are operated one at a time; router mistakes can silently skip migrations | +| [Rails][rails-multidb] | Named databases, per-database migration roots, role/shard switching, `database_tasks: false` | Ownership is configuration and folder convention, not a typed contribution protocol | + +`[INFERENCE]` No product is a template to copy. The distinctive combination this RFC proposes — one +deterministic resolved manifest, contributor-owned spaces with independent lineage, native upstream +authoring with framework policy around it, apply-bound plans with receipts and +inspect-before-resume, ownership-aware drift, capability-specific behaviour, a programmatic core +with CLI/agent projections, and a runtime Standard Schema boundary — does not exist as a single +local product today. ZenStack v3 is the closest on schema/runtime composition and validator +ergonomics; Atlas and Bytebase are closest on delivery, and both put the interesting parts in a +hosted service. + +### NetScript's own prior art + +`[NS-SRC]` The oRPC integration is the internal precedent for composing an upstream type system: +real upstream builder, NetScript policy around it, precise types flowing from upstream values, +Standard Schema consumed structurally, one const-generic root fanning into several surfaces, and +compile-failure soundness tests. [The transfer analysis](#the-orpc-precedent-transferred-precisely) +states exactly which parts transfer and which must not. The contribution-axis pattern with versioned +contributions and skew detection is the precedent for pinned mirrors and `db.space.skew`. + +## Unresolved questions + +`[PROPOSAL]` These are recorded honestly and by category. **No must-resolve-now architecture +question remains**; the plan gate verified that independently. Nothing below can force a +package-boundary rewrite. + +### Locked — not open + +For the avoidance of doubt: the vocabulary, identity model, package graph and archetypes, artifact +taxonomy, refusal boundary, ownership model, plan/apply/recovery semantics, validation bounds, and +clean-break law are **locked** by decisions D-01–D-40 (Appendix A). Reopening one requires the +architecture kill criteria in [Kill and switch criteria](#kill-and-switch-criteria), not a +preference. + +### Implementation-time decisions, by owning wave + +| ID | Question | Wave | Why deferral is safe | +| ---- | ----------------------------------------------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------- | +| U-1 | Canonical manifest/digest encoding and the public format-version evolution policy | W1 | `formatVersion` exists and consumers refuse unknown versions; the encoding is internal to that contract. | +| U-2 | Exact Prisma import allowlist, module specifiers, and the supported compatibility window (D-41) | W3 | Adapter-local by construction; pinning a specifier now would design against a surface that moved post-RC. | +| U-3 | Whether the multi-namespace capability can be claimed at all (D-37) | W3 | Withholds a claim, not a boundary. If upstream never fixes it, the kernel carries an unused axis. | +| U-4 | Extension facet mapping onto the provider's authoring/control/runtime/validation locations | W3 | The bundle identity contract is fixed; only the mapping is version-specific. | +| U-5 | Concrete request/process scope shapes and transaction capability types | W4 | The scope split and its guarantees are locked; the concrete option shapes are adapter-facing. | +| U-6 | Plan signature format and production key custody (D-35) | W5 / W10 | The `SignaturePolicy` port and the signed-plan requirement are locked now; only the mechanism is open. | +| U-7 | Provider lock mechanism: native advisory versus fenced row (D-42) | W5, per provider | Public lock semantics — owner, nonce, fencing evidence, TTL, force-unlock preconditions — are locked. | +| U-8 | Receipt storage location and retention policy, and the crash-fault harness | W5 | The receipt contract and outcomes are locked; where they are stored is operational. | +| U-9 | The initial augmentation grant vocabulary and the executable contribution-phase allowlist | W7 | Grants are already closed-by-default; adding a grant kind is additive. | +| U-10 | Whether the testkit needs a runnable binary, or folds into `./testing` subpaths | Before W1 | Explicitly bounded and pre-publication. It cannot rework another unit. | +| U-11 | Migration window, legacy release-line end date, rollback runbook, and remote release evidence | W10 | Release operations, not architecture. | + +### Conditional on upstream + +| ID | Question | Status | +| --- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | +| C-1 | Does Prisma's namespace type map stop flattening non-default namespaces? | `[COND]` Blocks the multi-namespace **capability claim** only. No cast workaround is permitted. | +| C-2 | Do prepared-statement, transaction, raw-SQL, and numeric/aggregate semantics settle by GA? | `[COND]` `[POST-RC]` Aggregate number semantics already changed after RC1. No public NetScript guarantee until proven per pin. | +| C-3 | Does upstream ship an extension/space removal primitive? | `[COND]` If not, `retain` is the product behaviour and archive/drop stay unclaimed (D-46). | +| C-4 | Does the contract format stabilise across releases? | `[COND]` NetScript records its own digest meanwhile; more than one format break without a migration path is a kill trigger. | +| C-5 | Is the Deno platform matrix clean without vendoring or patching? | `[COND]` A named W3 gate. Failure kills the adapter, not the kernel. | +| C-6 | Is the runtime-derived validation direction sustained upstream? | `[EXCHANGE]` Exploratory only. NetScript's bounded interpreter does not depend on an upstream commitment. | + +### Safe to defer + +Second provider; Prisma SQLite, MongoDB, MySQL, and SQL Server; runtime capability negotiation +(rejected until a concrete case exists); AOT validation; archive/drop removal beyond retain; public +raw/prepared/aggregate conveniences; hosted approval, registry, promotion, fleet, drift, and secret +services. Cross-database relations and transactions are **explicitly unsupported**, not deferred +parity debt (D-43–D-47). + +### Discussion questions for reviewers + +1. Is `retain` as the only guaranteed removal acceptable for the first release, given that + archive/drop are specified but unclaimed? +2. Is the generated-`AppBinding` seam the right trade against the alternative of a + framework-published contract-typed value, which the publish constraint forbids? +3. Should the optional policy factory be specified at all, or should Candidate A be the entire + authoring API from the start? +4. Is `@netscript/database-testkit` a package or a subpath — decided before W1 and never after + publication? + +## Future possibilities + +`[PROPOSAL]` Natural extensions this architecture enables and this RFC deliberately excludes: + +- **A second certified provider (W11).** The narrow provider SPI is proven by a real second adapter + when demand and maturity exist — never by a speculative fallback built to prove a port. +- **The multi-namespace capability**, released by the parity gate rather than by a workaround. +- **AOT validation**, released only by mechanical corpus equivalence with the runtime interpreter. +- **Archive and drop retirement**, released by provider conformance and a destructive-plan policy. +- **Delivery-backend adapters** that export plans, receipts, and diagnostics to Atlas, Bytebase, or + a hosted approval system — as adapters over stable artifacts, never as a local reimplementation. +- **Richer data-transform authoring** on top of invariant-guarded transitions, with descriptor + wiring generated from the manifest rather than left as planner placeholders. +- **Deeper agent capability**: an allowlisted operation surface with policy metadata, derived from + the operation catalog, so an agent gets structured operations rather than unrestricted query + access. +- **Additional first-party spaces** beyond auth, workers, sagas, triggers, and streams, once the + contribution seam is certified. +- **Read-replica-aware routing helpers**, if a concrete need appears — as an application-composition + affordance, never as a hidden runtime router that could silently send a write to a reader. + +## Appendix A: decision trace D-01–D-47 + +`[PROPOSAL]` Every locked decision and its definitive section in this RFC. Nothing is silently +dropped or weakened; where a decision is conditional or deferred, the status column says so and the +gate is named in Appendix F or in [Unresolved questions](#unresolved-questions). + +### Clean break, data continuity, artifact separation, no query abstraction (D-01–D-05) + +| ID | Decision | Status | Definitive section | +| ---- | ---------------------------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------ | +| D-01 | Clean break; no backward-compatibility API or runtime surface. | Locked | Breaking changes and migration → The no-compatibility law; Refusal boundary §2 | +| D-02 | Data continuity and mechanical migration are mandatory. | Locked | Breaking changes and migration → The adoption protocol; Data-safety gates | +| D-03 | The durable join point is `DatabaseManifest`; a graph is private compiler IR only. | Locked | Locked vocabulary; Artifacts → `DatabaseManifest` | +| D-04 | Definition, manifest, executable plan, provider ledger, and receipt stay separate. | Locked | The one story; Artifacts → The artifact contract, at a glance | +| D-05 | NetScript defines no query DSL, repository, or portable client facade. | Locked | Refusal boundary §1; Runtime layer | + +### Native authoring, Candidate A, inference, app-local binding (D-06–D-08, D-36) + +| ID | Decision | Status | Definitive section | +| ---- | --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------- | +| D-06 | Current model-first native Prisma authoring is primary; the obsolete fluent chain is not recreated. | Locked; import spelling adapter-pinned | Guide § Step 1; Rationale → Alternatives rejected | +| D-07 | Candidate A (native contract + thin definition) is the baseline; the optional factory dies on private imports, copied overloads, or widening. | Locked | The definition layer; The optional policy factory, and its kill criterion | +| D-08 | The app-specific inferred binding is generated app-local, never a kernel export. | Locked | End-to-end type propagation; Package graph (`-runtime`) | +| D-36 | Model-first callback, Candidate A, two-phase collection, const-preserving root, no re-export. | Locked; exact RC/GA path in W3 | The definition layer; Two-phase composition | + +### Packages, provider boundary, targets, replicas, capabilities (D-09–D-16) + +| ID | Decision | Status | Definitive section | +| ---- | ----------------------------------------------------------------------------------- | ------ | --------------------------------------------------------- | +| D-09 | The package/archetype graph is exact; runtime is A3. | Locked | The package graph and archetypes | +| D-10 | The kernel is provider-neutral; the first certified adapter is Prisma 8 PostgreSQL. | Locked | Package graph (`-prisma-postgres`); Targets and providers | +| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | Locked | Targets and providers; Refusal boundary §3 | +| D-12 | Capabilities are static declared tags, never runtime negotiation. | Locked | Identity model; Refusal boundary §4 | +| D-13 | The provider registry is composition-root data, never global mutable state. | Locked | Consumed ports (closing note) | +| D-14 | A stable target id owns connection, output, runtime, migrations, locks, receipts. | Locked | Identity model | +| D-15 | Target selection is explicit and dependency-closed, and records every omission. | Locked | Multi-target execution is a saga | +| D-16 | Replicas are roles of a target, never migration targets. | Locked | Identity model; Runtime layer guarantees | + +### Spaces, ownership, extensions, mirrors, lifecycle (D-17–D-20, D-38–D-40) + +| ID | Decision | Status | Definitive section | +| ---- | ------------------------------------------------------------------------------------------- | ------ | ----------------------------------------------------- | +| D-17 | Provider-native contract spaces plus NetScript policy replace copied fragments. | Locked | Plugin and contract-space lifecycle; Guide § Step 6 | +| D-18 | One `managed` owner per `ObjectKey`; augmentation requires an owner grant. | Locked | Ownership | +| D-19 | Pinned mirrors make apply/verify independent of installed plugin code. | Locked | The pinned mirror | +| D-20 | Detach-and-retain is the guaranteed removal; archive/drop are conditional. | Locked | Plugin and contract-space lifecycle | +| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin tables default to a space. | Locked | Two contribution modes; the fragment publication rule | +| D-39 | One extension bundle supplies identity-matched authoring/control/runtime/validation facets. | Locked | Guide § Step 7; Two-phase composition; V-9 | +| D-40 | CI and production consume canonical verified artifacts, never arbitrary schema TypeScript. | Locked | Two-phase composition; Refusal boundary §11 | + +### Bounded Standard Schema interpretation (D-21–D-25) + +| ID | Decision | Status | Definitive section | +| ---- | ------------------------------------------------------------------------------------ | ------ | ---------------------------------------------------- | +| D-21 | Standard Schema is public; bounded runtime interpretation is the default. | Locked | The runtime validation subsystem → The public API | +| D-22 | Public representations are `runtime` and `json`; driver wire is adapter-internal. | Locked | The public API | +| D-23 | Full Prisma operation validation is not contract-derived; contributors are required. | Locked | Three schema classes; What is explicitly not claimed | +| D-24 | Unknown validation metadata fails at schema construction. | Locked | Mandatory fail-closed cases | +| D-25 | Optional AOT validation is corpus-equivalent only and never required. | Locked | Optional ahead-of-time projection | + +### Operations, catalog, plans, control ownership, receipts, artifacts, agents (D-26–D-33) + +| ID | Decision | Status | Definitive section | +| ---- | ------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------------ | +| D-26 | Pure operations cannot resolve connections, Aspire, Docker, secrets, or the network. | Locked | Operation classes | +| D-27 | The programmatic operation catalog is primary; CLI, docs, and agents are projections. | Locked | The operation catalog; CLI, agents, and CI | +| D-28 | A preview is not an executable plan; `apply` accepts only bound, revalidated plans. | Locked | Preview, plan, policy, approval | +| D-29 | NetScript owns policy, locks, recovery, receipts, and the saga; the provider owns diff/lineage/marker. | Locked | Consumed ports; Apply, checkpoints, and recovery | +| D-30 | Cross-target apply is never atomic; partial and unknown outcomes are first class. | Locked | Multi-target execution is a saga | +| D-31 | The local kernel does not rebuild hosted registry/RBAC/fleet/drift products. | Locked | Refusal boundary §6; Market lessons | +| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | Locked | The artifact contract; Refusal boundary §9 | +| D-33 | Agent instructions and catalogs are generated, and every example executes. | Locked | The operation catalog; CLI, agents, and CI | + +### Legacy provider parity and signed production plans (D-34–D-35) + +| ID | Decision | Status | Definitive section | +| ---- | ----------------------------------------------------------------------------------- | ------------------------- | ---------------------------------------------- | +| D-34 | Existing MySQL/SQL Server/SQLite support is not carried through compatibility code. | Locked | Breaking changes → What breaks; Targets matrix | +| D-35 | Production plans require signatures; mechanism and key custody are chosen later. | Pre-implementation W5/W10 | `ExecutablePlan`; Unresolved U-6 | + +### Withheld capability (D-37) + +| ID | Decision | Status | Definitive section | +| ---- | ---------------------------------------------------------------------------------------------------------- | -------------------------- | --------------------------------------------- | +| D-37 | The multi-namespace adapter capability is withheld while type maps flatten namespaces; no cast workaround. | Conditional upstream block | The namespace capability is withheld, and why | + +### Implementation-time pin, import, and lock choices (D-41–D-42) + +| ID | Decision | Status | Definitive section | +| ---- | --------------------------------------------------------------------------- | -------------------------------- | --------------------------------------- | +| D-41 | The exact Prisma control/runtime import allowlist and compatibility window. | Pre-implementation W3 | Package graph (`-prisma-postgres`); U-2 | +| D-42 | Native advisory versus fenced-row lock is certified per provider. | Pre-implementation, per provider | Apply, checkpoints, and recovery; U-7 | + +### Explicitly deferred optional capabilities (D-43–D-47) + +| ID | Decision | Status | Definitive section | +| ---- | -------------------------------------------------------------------------- | -------- | ------------------------------------------------------- | +| D-43 | Whether AOT validation ships at all. | Deferred | Optional ahead-of-time projection; Future possibilities | +| D-44 | A real second provider. | Deferred | Alternatives rejected; Appendix C wave W11 | +| D-45 | Public raw/prepared/aggregate conveniences stay deferred or adapter-local. | Deferred | Unresolved → Safe to defer; C-2 | +| D-46 | Archive/drop plugin retirement in v1. | Deferred | Plugin and contract-space lifecycle | +| D-47 | Remote approval, registry, and continuous-drift integrations. | Deferred | Refusal boundary §6; Future possibilities | + +## Appendix B: claim and source trace + +`[PROPOSAL]` Every load-bearing fact this RFC relies on, with its class, its pin, and its +verification status. This table is the RFC's own claim ledger; a reviewer should be able to falsify +any row from the cited source alone. + +| # | Claim | Class | Pin / source | Verification | +| -- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Executing `generateDatabaseDenoJson` for PostgreSQL, SQLite, MySQL, and SQL Server yields **42 `db:*` task keys per generated engine workspace** | `[NS-SRC]` | `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` at `383170bbc` | **Executed** by the PLAN-EVAL evaluator for all four providers. Supersedes an independent report's figure of 30. | +| 2 | The current-state audit's phrase "more than twenty database tasks" was **accurate** | `[NS-SRC]` | Same generator | Confirmed: 42 > 20. An independent report's "correction" to exactly 30 was itself wrong and is dispositioned. | +| 3 | `@prisma/orm-postgres` publishes **138** top-level export subpath keys | `[RC1]` | `packages/9-public/@prisma/orm-postgres/package.json` at `a76a6c5` | Recounted independently during PLAN-EVAL cycle 2. Supersedes an independent report's "~275". | +| 4 | `resolveTarget` defaults only with exactly one enabled target and never consults `PrimaryDatabase` | `[NS-SRC]` | `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66-91` | Re-verified during PLAN-EVAL cycle 2. | +| 5 | The generated workspace directory is `join('database', provider.dirName)` | `[NS-SRC]` | `workspace-resolver.ts:51` | Re-verified. | +| 6 | Plugin schema contribution is file copy plus regex declaration scanning | `[NS-SRC]` | `prisma-declaration-scanner.ts:13`; `prisma-schema-writer.ts:19,100-122` | Re-verified during PLAN-EVAL cycle 2. | +| 7 | Generated templates pin `npm:prisma@^7.4.2` while the root catalog uses caret ranges `^7.8.0` | `[NS-SRC]` | `generate-db-deno-json.ts:36,56,59,61,67`; root `deno.json:231-236` | Re-verified during PLAN-EVAL cycle 2. | +| 8 | The operation runner's result type is `Promise`; `studio` uses the first target; `--db all` is fail-fast | `[NS-SRC]` | `operation-runner.ts:85,90-105,116-117` | Verified by the independent architecture review; consistent with the current-state audit. | +| 9 | `isolatedDeclarations: true` is repo-wide and the slow-types carve-out is oRPC-only | `[NS-SRC]` | root `deno.json:174`; `docs/architecture/doctrine/02-public-surface.md:217-240` | Re-verified during PLAN-EVAL cycle 2. | +| 10 | Doctrine codifies plain `*.prisma` plugin fragments and does not register the proposed packages | `[NS-SRC]` | `06-archetypes.md:209-211`; `10-codebase-verdict-and-handoff.md` | Re-verified during PLAN-EVAL cycle 2; the W0 amendment obligation follows. | +| 11 | `DB-GENERATE-ASPIRE-COUPLING` is open; `packages/database — AP-17` is open with a stale rename half | `[NS-SRC]` | `.llm/harness/debt/arch-debt.md` | Re-verified during PLAN-EVAL cycle 2 (`packages/database/ports/` exists). | +| 12 | Prisma 8 RC1 is Early Access and not recommended for production; RC respins may break or rename APIs | `[PRIMARY]` | [RC1 release][rc1-release]; [RC1 README][rc1-readme] | Primary source. | +| 13 | PostgreSQL is the sole database intended for the 8.0 GA target set; MongoDB EA, SQLite proof-of-concept, MySQL later, SQL Server absent | `[PRIMARY]` | [scorecard][rc1-scorecard]; [supported versions][rc1-versions] | Primary source. | +| 14 | Authoring is model-first `defineContract(scaffold, callback)` with literal-preserving overloads | `[RC1]` | `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121`; `contract-builder.ts:437-462` | Re-verified during PLAN-EVAL cycle 2. | +| 15 | The fluent `target/table/column` builder existed at `fd88abf4`, was replaced by PR #261 / `27ccefc3`, and removed by `e1e5ab2c` | `[PRIMARY]` | [PR #261][pn-261]; [`27ccefc3`][pn-27ccefc3]; [`e1e5ab2c`][pn-e1e5ab2c] | Primary source. | +| 16 | Authoring type maps flatten non-default namespaces while runtime lowering honours them | `[RC1]` | `packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691` | Re-verified during PLAN-EVAL cycle 2. Retained `[POST-RC]` at `71e2e0d9…`. | +| 17 | Operation/result type maps are phantom and emitted to `contract.d.ts`, not retained as runtime data | `[RC1]` | `packages/2-sql/1-core/contract/src/types.ts:90-139,207-215`; `generate-contract-dts.ts:179-221` | Pinned-source audit. | +| 18 | SQL projections carry no codec for computed, subquery, and raw aliases | `[RC1]` | `packages/2-sql/4-lanes/relational-core/src/ast/types.ts:1480-1505` | Pinned-source audit. | +| 19 | Codecs have three representations: application runtime, driver wire, target JSON | `[RC1]` | `framework-components/src/shared/codec.ts:16-30,44-51` | Pinned-source audit. Public NetScript representations are therefore `runtime` and `json`. | +| 20 | Prisma's Standard Schema slot validates codec **parameters**, not model values | `[RC1]` | `shared/codec-descriptor.ts:27-54` | Pinned-source audit. | +| 21 | Contract hashing covers storage, execution, and profile separately; domain/roots/extensions are excluded | `[RC1]` | `contract/src/hashing.ts:74-106`; `canonicalization.ts:250-277` | Pinned-source audit — the reason for the full-contract validator cache key. | +| 22 | The migration aggregate keeps spaces separate and defers cross-space domain checks | `[RC1]` | `migration/src/aggregate/types.ts:32-79,81-123`; `validate-domain.ts:140-147` | Pinned-source audit. | +| 23 | A custom codec requires conversions and a JSON round trip but no value predicate; encoding does not validate | `[RC1]` | `mongo-codec/src/codecs.ts:23-42,44-82`; `arktype-json/README.md:7-17,40,74-87` | Pinned-source audit — the reason codec contributions must carry value schemas. | +| 24 | Contract spaces define one `(contract, migration graph, head ref)` tuple per contributor | `[PRIMARY]` | [ADR 212][adr-212] | Primary source. | +| 25 | Data transforms are invariant-guarded transitions | `[PRIMARY]` | [ADR 176][adr-176] | Primary source. | +| 26 | The integration seam moved materially within six days of the RC tag | `[POST-RC]` | [`3dc98cb`][pn-3dc98cb], [`d0c8333`][pn-d0c8333], [`15308c6`][pn-15308c6], [`92b6ee3`][pn-92b6ee3], [`c4a5875`][pn-c4a5875], [`5d4a4db`][pn-5d4a4db], [`a900bc1`][pn-a900bc1], [`71e2e0d`][pn-71e2e0d] | All eight verified as descendants of the RC tag by an independent review. | +| 27 | Generated contract JSON Schema is labelled lossy/advisory with ArkType authoritative | `[POST-RC]` | `data-contract-json-schema.ts:10-15,31-38,68-110` at `71e2e0d9…` | Pinned-source audit. Corroborates direction; changes no RC1 capability. | +| 28 | An externally-evolving hosted database can break `db verify` against a pinned extension contract | `[PRIMARY]` | [prisma#29896][pn-29896] | Primary source — the motivation for `external`/`adopted` ownership. | +| 29 | A published type can be accepted and then ignored at runtime | `[PRIMARY]` | [prisma#29932][pn-29932] | Primary source — the reason conformance rows must cross type → plan → SQL → result. | +| 30 | An introspection schema selector could be silently ignored | `[PRIMARY]` | [prisma#29923][pn-29923] / [PR #29944][pn-29944] | Primary source — the reason a silently-ignored namespace selector is a conformance failure. | +| 31 | An exact CLI-engine peer is needed to prevent duplicate engine copies | `[PRIMARY]` | [PR #30009][pn-30009] | Primary source — the reason for the one-resolved-component-set gate. | +| 32 | Upstream "proven" for PostgreSQL includes PGlite-backed integration tests | `[PRIMARY]` | [scorecard][rc1-scorecard] | Reported by an independent review against the RC scorecard; **re-verify at W3**. It is why "one real PostgreSQL service, not only PGlite" is a NetScript gate. | +| 33 | Flyway's `repair` realigns the ledger and does not clean objects left by a failed non-transactional migration | `[PRIMARY]` | [Flyway repair][flyway-repair] | Primary source — the reason `cleanup-required` is a distinct outcome. | +| 34 | Pulumi cannot know whether an interrupted create completed, and recovery inspects the provider first | `[PRIMARY]` | [interrupted updates][pulumi-interrupted] | Primary source — the reason for `outcome-unknown` and inspect-before-resume. | +| 35 | Terraform targeting is documented as exceptional recovery, not a routine selector | `[PRIMARY]` | [resource targeting][tf-targeting] | Primary source. | +| 36 | Bytebase removed automatic schema drift detection in 3.14.0 | `[PRIMARY]` | [Bytebase 3.14.0 changelog][bytebase-3140] | Primary source — no current Bytebase drift capability is claimed here. | +| 37 | ZenStack v3 derives selection-shaped validators from its runtime schema, Zod-specific | `[PRIMARY]` | [ZenStack Zod factory][zenstack-zod] | Primary source — prior art for ergonomics, not for choosing Zod as the boundary. | + +### Claims deliberately **not** used as evidence + +| Claim | Why it is excluded | +| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Counts of legacy `@internal/*` roots or `PN-*` error codes in the upstream agent skill | Two independent measurements disagreed materially and the totals vary with the counting pattern. The qualitative conclusion (a hand-maintained agent surface decays) is used; no count is. | +| "Approximately 275 `@prisma/orm-postgres` export keys" | Superseded by the recounted 138 (row 3). | +| "Exactly 30 generated `db:*` tasks" | Superseded by the executed 42 per workspace (row 1). | +| Exact upstream scorecard verdict tallies | The methodology is cited (row 32); the tallies are not load-bearing and are re-measured at W3 rather than argued. | +| A live `DatabaseGraph` as the public join point | Rejected in favour of a durable plain `DatabaseManifest` (D-03). | +| Broad "derive all validation from the contract" claims | Narrowed by the pinned-source audit (rows 17–23). | +| Provider re-export proposals | Rejected; only the adapter imports Prisma, and applications import the public authoring builder directly. | +| "Contract spaces solve plugin removal" | Overclaim. Spaces solve ownership and history; removal beyond `retain` stays conditional (D-20, D-46). | + +## Appendix C: implementation and release plan (W0–W11) + +`[PROPOSAL]` Each wave lands independently, has a gate that can fail, and depends only on earlier +waves. No production code, doctrine mutation, package publication, provider certification, plugin +conversion, legacy deletion, or release operation is authorised by this RFC; acceptance authorises +the program. + +| Wave | Scope | Depends on | Exit evidence | +| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| W0 | RFC acceptance; doctrine amendments to `06-archetypes.md` and `10-codebase-verdict-and-handoff.md`; register every new unit in the gated denominator; replace the plain-fragment rule | — | Accepted RFC; `arch:check` discovers the new roots; the archetype-count consequence resolved or carried as an explicit debt entry | +| W1 | `@netscript/database-contract` (A1): identities, artifact schemas, capability/ownership vocabularies, diagnostics, operation/receipt types, space descriptor, ports | W0 | A1 gates; zero dependencies; `deno doc --lint` clean; `deno publish --dry-run` **without** `--allow-slow-types`; packed consumer install | +| W2 | `@netscript/database` (A4): definitions, two-phase composition, the pure compiler, invariants V-1…V-9, diagnostics | W1 | A4 gates; determinism/property tests; every invariant has a negative test with the right code; an AP-25 scan proving no IO is reachable | +| W3 | **Experimental** `@netscript/database-prisma-postgres` (A2) spike: native builder integration, artifacts, control adapter, runtime factory, spaces, extension bundles, `ValidationIR` decoder, Deno matrix, namespace parity check | W1, W2 | Real PostgreSQL (**not** PGlite only); packed Deno consumer; import allowlist; exactly one resolved Prisma component set; a recorded kill/switch review; **no public stability claim** | +| W4 | `@netscript/database-runtime` (A3) and the Aspire `ConnectionSource` adapter | W1–W3 | **All F-1…F-19 plus required runtime gates**; lifecycle, leak, cancellation, and scope tests; redaction case; bind-mismatch refusal | +| W5 | `@netscript/database-control` (A2): catalog, preview/plan/apply/verify, locks, receipts, recovery, cross-target saga | W1–W4 | A2 gates; failure-injection matrix; atomic emission; an offline test proving a `pure` operation cannot reach an orchestrator | +| W6 | `@netscript/database-testkit` (A6): provider **and** space conformance suites with machine reports | W1–W5 | A6 + F-CLI gates; deliberately broken provider and space fixtures must fail; real-service machine report | +| W7 | `@netscript/plugin` contribution seam; remove the legacy contribution abstracts; first plugin-core fixture | W1–W6 | Breaking-surface accounting for a published package; plugin thinness/seam gates; a contribution that carries no provider dependency | +| W8 | CLI, agent surface, and adoption codemod as projections | W2, W5–W7 | Generated example and catalog freshness; every generated example compiles and runs; a populated adoption preflight; zero text-log assertions | +| W9 | First-party spaces: auth, workers, sagas, triggers, streams | W7–W8 | Each space certified by the space conformance kit; package-free apply/verify; runtime parity in a generated project | +| W10 | Clean cutover and legacy deletion | W1–W9 | Full release-gate class; Windows and Linux; production-shaped adoption rehearsal on seeded data; remote published E2E against exact JSR versions; no compatibility remnant | +| W11 | A second real provider — only on demonstrated demand and maturity | W10 | The same provider conformance suite passes; **no kernel or public manifest rewrite** | + +`[PROPOSAL]` W3 is deliberately a spike **before** public runtime/control stabilisation, so that a +failed Prisma adapter does not invalidate W1–W2. No old package is deleted before W10, and that +temporary repository coexistence never authorises a dual runtime composition. + +## Appendix D: conformance matrix + +`[PROPOSAL]` Every behavioural feature must cross **type → composition/plan → provider artifact or +SQL → result → lifecycle/evidence**. A type-only pass or an exit-code-only pass is never evidence. +Negative paths are first-class rows. + +### D.1 Archetype and package gates + +| Row | Requirement | +| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| A-1 | Each new unit passes the F-1…F-19 subset its archetype requires, per the archetype gate matrix. | +| A-2 | `@netscript/database-runtime` (A3) passes **all** F-1…F-19 and the **required** runtime gates. | +| A-3 | First-party plugins (A5) pass thinness, base-seam, golden-emitter, doctor, contract-soundness, and `scaffold.runtime` parity. | +| A-4 | The testkit (A6) passes the F-CLI family. | +| A-5 | Scoped check, lint, and format wrappers; `quality:scan`; `arch:check`; public surface and subpath audit; naming/folder/layering/inheritance/upstream-re-export/permission/test-shape gates. | + +### D.2 Composition, typing, and artifacts + +| Row | Case | Passes when | +| ---- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| T-1 | A space requires a capability its bound target lacks | Composition fails with `db.compose.capability.missing`, naming capability, space, target | +| T-2 | A space is bound to an undeclared target | **Type error** at the authoring site, not a runtime diagnostic | +| T-3 | Two spaces manage one `ObjectKey` | `db.compose.ownership.conflict`, naming both spaces | +| T-4 | A cyclic dependency between spaces | `db.compose.dependency.cycle`, with the cycle path | +| T-5 | A cross-target relation is declared | Refused at composition, never emitted | +| T-6 | Native contract inference survives to the app binding | Model, query, and result types are preserved end to end | +| T-7 | App fragment composition under reordering | Literal model/field/relation names preserved; the canonical digest is unchanged | +| T-8 | A deliberately widened fragment registry fixture | **Fails** its type-soundness gate | +| T-9 | No private import, cast, copied overload, or declaration widening in the adapter | An allowlist and a source scan prove it; a violation fails the build | +| T-10 | Namespace type/runtime parity | Either exact parity with no casts, or the capability remains unclaimed — never a workaround | +| T-11 | A 500-model representative application | Type-check and editor latency inside the agreed budget | +| T-12 | A published package exports a fragment naming provider helper types | **Fails** the publish gate | +| T-13 | Extension bundle facet identity | Identical id/version across all four facets; a missing or mismatched facet fails composition | + +### D.3 Deterministic and atomic emission + +| Row | Case | Passes when | +| --- | -------------------------------------------------------------- | ---------------------------------------------------------------- | +| E-1 | Emit twice from clean inputs | Byte-identical artifacts and an identical `ManifestDigest` | +| E-2 | Emit two targets concurrently into distinct roots | Both succeed with no interleaving | +| E-3 | Emit interrupted mid-write | The artifact root is fully old or fully new — never half-written | +| E-4 | Schema edited without re-emitting | `db.artifact.stale` at bind time, naming the exact command | +| E-5 | Every artifact root records its manifest digest | Present and matching | +| E-6 | CI re-run with an unchanged digest | Emission skipped; the recorded digest asserted instead | +| E-7 | Migration apply with application/plugin TypeScript unavailable | Succeeds from canonical artifacts alone | + +### D.4 Runtime, platform, and validation + +| Row | Case | Passes when | +| --- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| R-1 | Full runtime suite against a **real** PostgreSQL service | Connect, query, relations, raw, codecs, transactions, prepared statements, streaming, cancellation, close — never satisfied by PGlite alone | +| R-2 | Connection injection and an external pool | Correct behaviour under concurrency | +| R-3 | Error mapping and redaction | No connection string, password, or secret in any diagnostic, receipt, or log | +| R-4 | Repeated start/stop and request lifecycles | Leak-free; close ordering respected | +| R-5 | Request-scoped session used after disposal | Prevented by type where possible; a runtime error otherwise | +| R-6 | A transaction handle escaping its callback | Rejected; a transaction handle does not expose transaction-opening members | +| D-1 | Deno import graph of runtime paths | No undeclared Node globals; no CLI or toolchain module reachable | +| D-2 | Packed-artifact install into a blank fixture | Every used export and peer resolves exactly once; exactly one Prisma component set | +| D-3 | Upstream deep-import allowlist | Any newly-introduced off-allowlist import fails the build | +| V-1 | `runtime`/`json` corpus | Strings, numbers, booleans, `Date`, bigint, numeric string, bytes, JSON, domain enum, value set, native enum, null, list, dict, value object, union, and one custom codec — each representation tested separately with round trips and malformed cases | +| V-2 | Every mandatory unsupported case | Fails at **schema construction** with stable coordinates; never `unknown`, never pass-through | +| V-3 | Invalid values | Return path-rich Standard Schema issues; never throw | +| V-4 | Direct selection/result shapes | Strict; computed, raw, aggregate, include, and unknown leaves never pass through | +| V-5 | App plus two extension spaces | Aggregate resolution correct; duplicate model names across spaces never collide | +| V-6 | Two independent Standard Schema consumers | The same schema values consumed by two integrations with no generated mirror files | +| V-7 | Cache invalidation | Domain-only, extension-only, execution-default, codec-version, representation, selection, and space changes each invalidate correctly | +| V-8 | Custom codec without representation schemas | Unsupported, fails closed | +| V-9 | AOT projection, **if it exists** | Passes the identical semantic corpus and invalidation suite; otherwise it does not ship | + +### D.5 Control, migration, ownership, and recovery + +| Row | Case | Passes when | +| ---- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | +| M-1 | Offline emit with no Aspire, .NET, Docker, or network | Succeeds | +| M-2 | Greenfield apply | Succeeds with a complete receipt | +| M-3 | Adoption of a populated database | Marker rows only; **zero DDL/DML**; `verify` clean | +| M-4 | Externally-introduced drift | `db.verify.drift` classifies managed, adopted, external, and ignored correctly | +| M-5 | Destructive change under a deny policy | Refused with the destructive operation list | +| M-6 | Destructive change in production with an unsigned plan | Refused regardless of interactive consent | +| M-7 | Apply after the manifest, baseline, pins, or policy changed | `db.plan.stale` | +| M-8 | Apply after plan expiry | `db.plan.expired` | +| M-9 | Apply fails mid-run | The receipt names the exact failed step; resume revalidates the baseline before continuing | +| M-10 | Transport lost after dispatch | `outcome-unknown`; resume inspects marker and live state before acting | +| M-11 | Two concurrent applies on one target | The second receives `db.apply.lock.held` with owner and TTL; no interleaved DDL | +| M-12 | The lock holder dies | TTL/fencing releases it; no permanent wedge; force-unlock preconditions enforced | +| M-13 | A data transform with an unsatisfied invariant | Fails, reports remaining work, and does not advance the head | +| M-14 | A non-default namespace selector | Honoured; a silently ignored selector is a **failure** | +| M-15 | Two same-provider targets | Fully isolated output, lineage, markers, locks, receipts, and runtime bindings | +| M-16 | Cross-target failure | Complete per-target and per-space outcomes; `partial-success`; resume continues only unfinished work | +| M-17 | Selective target/space execution | Dependency closure expanded, omissions recorded with reasons, whole-manifest verification afterwards | +| M-18 | Migration on Windows **and** Linux | Both run; no gate asserts on a human message string | +| P-1 | Two plugin spaces with declared ordering | Applied in the manifest's recorded topological order | +| P-2 | Plugin object-name collision across spaces | Namespaced and non-conflicting; no lexical prefix convention required | +| P-3 | Cross-space reference along a declared edge | Allowed; refused without the edge | +| P-4 | Plugin upgrade with a lineage step | Only that space's head advances | +| P-5 | Installed package digest ≠ mirror digest | `db.space.skew`, naming both digests and the sync action | +| P-6 | Apply/verify with **no plugin package installed** | Succeeds from the pinned mirror alone | +| P-7 | Uninstall with retention | Objects retained; ownership downgraded to `adopted`; verify still sees them | +| P-8 | Uninstall with a dependent space installed | Refused, naming the dependent | +| P-9 | Archive or drop | **Excluded** until individually certified; never claimed by default | +| P-10 | A plugin requiring a capability its target lacks | Install refused at composition | +| P-11 | Augmentation outside a granted axis | Refused, naming the grant that would be required | +| P-12 | An upstream extension owning its own space | Recorded as `external`; never reported as drift | + +### D.6 Journeys, generated surfaces, and release + +| Row | Case | Passes when | +| --- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| J-1 | Scaffold → add a second same-provider target → add two plugin spaces → plan → apply → deploy | No manual step and no hand-edited generated file | +| J-2 | Adopt a populated legacy project | Preflight clean; zero DDL; verify clean | +| J-3 | Generated project type-checks and starts | Unattended | +| G-1 | Generated CLI, help, docs, and agent catalogs | Exactly match the machine operation and diagnostic schemas | +| G-2 | Every generated example | Compiles and runs in CI | +| G-3 | Every diagnostic code | Reachable by a negative test and carries a structured `nextAction` | +| G-4 | No gate asserts on human-readable message text | Enforced | +| C-1 | Full `scaffold.runtime` E2E at cutover | Green | +| C-2 | No legacy remnant | No legacy adapter, generated task, copied fragment, repair script, deep generated import, or compatibility alias remains | +| C-3 | Release-class adoption rehearsal on seeded, production-shaped data | Zero schema/data mutation, with the receipt as evidence | + +## Appendix E: publishability and JSR gates + +`[PROPOSAL]` The prospective audit verdict for the planned surface is +**`PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`**. The six new packages **do not exist**, so +`deno publish --dry-run`, `deno doc --lint`, publish-file inspection, packed install, canary, and +remote-consumer results are currently **N/A** — never recorded as PASS. + +At implementation, each unit requires: + +- one manifest with a scoped name, synchronised version, license, and a concise description; +- an **explicit export map** and an `include` whitelist, with test and fixture exclusions; +- `@module` documentation, a runnable example per entrypoint, and full symbol JSDoc against a 100% + documentation-score target for stable surfaces; +- explicit public declarations satisfying root `isolatedDeclarations`, and **no `--allow-slow-types` + waiver** — no database package inherits the oRPC-only carve-out; +- relative imports within a package (preventing JSR self-referential subpath resolution against an + older published version) and declared specifiers across packages; +- ESM and Deno purity: no CommonJS, no HTTP imports, no top-level filesystem assumptions; +- publishable generated assets as checked-in deterministic TypeScript constants with + regenerate-and-diff freshness gates — runtime file reads and text/JSON import attributes stay + forbidden until an authenticated registry canary proves the limitation resolved; +- `deno doc --lint` with zero diagnostics, `deno publish --dry-run` without slow types, an inspected + publish file list, public import tests, a clean packed consumer install, `quality:scan`, and + `arch:check`. + +W3 additionally requires the exact Prisma import allowlist, exactly one resolved component set, Deno +import purity, and real PostgreSQL conformance before the provider package is advertised at all. W10 +additionally requires release preflight, GitHub OIDC/SLSA provenance, an authenticated canary, +registry settings reconciliation, and the production E2E path against **exact published JSR +versions**. A local dry run or packed install cannot substitute for that remote-graph verdict. + +**Kill or split a surface** if Prisma types leak into a public declaration; if app inference +requires a published slow type; if any unit needs `--allow-slow-types`; if the provider requires +private or deep imports or an upstream re-export; if internal bare self-imports appear; if generated +assets need runtime filesystem access; if a package combines two archetypes; or if a clean remote +consumer resolves duplicate or off-allowlist Prisma components. + +## Appendix F: risk register, kill criteria, and switch criteria + +### Risk register + +| Risk | Mitigation and kill response | +| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| Designing to RC marketing or a stale builder screenshot | Pin the source; use the current model-first API; keep exact module paths adapter-local; prove them in the W3 spike. | +| Upstream changes during the RFC or the implementation program | RC/post-RC separation; an exact provider pin and import allowlist; independent provider release cadence; a compatibility-window gate. | +| Replacing glue with a second ORM or a control plane | No query or model DSL; no runtime negotiation; no hosted services; small ports; an explicit refusal boundary. | +| Published slow types or Prisma leakage | App-local inference; no re-export or private imports; isolated declarations; no slow-types waiver; the JSR gates in Appendix E. | +| Native fragment composition widens inference | Two-phase explicit const-preserving generated root; compile-failure soundness fixtures; an editor/type-check budget. | +| A false multi-namespace claim | Withhold the capability until type/runtime parity passes with no casts (D-37). | +| Contract-derived validation overclaims full operations | A bounded algebra, explicit contributors, the runtime/JSON split, and failure at schema construction. | +| A custom codec accepts invalid values | Mandatory representation-specific value schemas; encode/decode is not validation. | +| Stale or half-published artifacts | Full canonical digest; atomic staged publication; facet identity; runtime and apply mismatch refusal. | +| Plugin removal destroys data | `retain` by default; archive/drop only through a conditional destructive plan; no directory-delete semantics anywhere. | +| Provider spaces mistaken for portability | PostgreSQL-only certification; explicit unsupported targets; a native capability surface. | +| An apply exit code masks partial work | Typed per-target and per-space outcomes; immutable checkpoints; `outcome-unknown`; inspect-before-resume. | +| Cross-target atomicity or rollback implied | Saga language only; no global transaction; complete partial-success receipts. | +| Mutable receipts become shadow state | The provider ledger remains the authority; receipts are append-only evidence. | +| A no-compatibility cutover causes data loss | Ownership preflight; marker-only adoption; a zero-DDL rehearsal; forward recovery; a parallel release line only. | +| The JSR plan is mistaken for readiness | Explicit `N/A` now; per-package dry-run, docs, packed, canary, and remote E2E receipts required later. | +| The RFC's breadth becomes unimplementable | Exact packages; W0–W11 dependencies; per-wave exits; kill and switch criteria. | +| Agent and documentation drift | Generate from the operation catalog and manifest; execute every example in CI. | +| CI stays long or flaky | Pure offline paths; digest caching; bounded real-service stages; atomic structured receipts; defined measurements instead of promised percentages. | +| The upstream seam moves during the RFC's own authoring window | Already observed `[POST-RC]`. Contained structurally by the one-package, one-facade, allowlisted, independently-versioned adapter. | +| An implementation-time decision silently widens support | Every withheld capability names its gate; a claim without a passing conformance row is a conformance failure. | + +### Kill and switch criteria + +#### Kill only the Prisma adapter + +`[PROPOSAL]` Keep the provider-neutral kernel and do not publish or switch to Prisma 8 if, at the +adoption pin, any of these hold: + +- Deno runtime or import purity requires vendoring or textually patching upstream. +- Packed provider artifacts cannot publish or install without slow-type or duplicate-component + failures. +- Native TypeScript authoring cannot preserve app-local inference through a stable public builder + seam without casts, private imports, or copied overloads. +- Contract emission cannot be deterministic and atomically installed. +- Programmatic control cannot produce enough structured information to bind plans, verify outcomes, + and avoid terminal-text parsing. +- PostgreSQL marker and ledger advancement cannot be proven safe with migration effects. +- Contract spaces cannot prove disjoint ownership and package-free apply for an app plus plugins. +- Required runtime lifecycle, transaction, error, or cancellation behaviour fails against real + PostgreSQL. +- Upstream changes the contract format without a viable migration path more than once before + NetScript's first stable adapter release. + +Switching to a different provider adapter happens only after it passes the same conformance suite. +**Prisma 7 compatibility is never reopened.** + +#### Narrow or kill a subsystem + +- If full-operation Standard Schema derivation would require reproducing Prisma's phantom type + system, keep only model-value and known-result validation plus explicit contributors. This + narrowing is already the plan, not a failure. +- If runtime interpretation misses cold-start budgets, test AOT equivalence; if equivalence fails, + retain runtime interpretation and require explicit schemas at the affected boundary rather than + shipping a divergent mirror. +- If provider-generic capability types start growing into query abstractions or negotiation, delete + them and keep literal static tags. +- If contribution archive or drop cannot be verified, ship detach-and-retain only. +- If the public provider SPI starts changing to accommodate hypothetical providers before a second + adapter exists, revert to the smallest Prisma-exercised seam and defer generalisation. +- If the optional policy factory needs a cast, a private import, or a copied overload, delete it and + keep Candidate A. + +#### Reopen the architecture + +`[PROPOSAL]` Reopen this RFC — not merely an adapter — only if implementation proves that a +deterministic manifest cannot express one target/space composition without depending on live state; +that app-local type binding necessarily becomes a published framework slow type; that target +identity cannot remain provider-independent; or that ownership and history cannot remain separate +from query and runtime types. + +## Appendix G: run provenance, slice trace, and review surface + +### Provenance + +| Field | Value | +| ------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Run | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| NetScript baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | +| Prisma RC pin | `v8.0.0-rc.1` @ `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` | +| Prisma post-RC pin | `71e2e0d9ee1f306b5a11435cd1973023cb33866a` | +| Research index | [`research.md`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md) | +| Plan and decisions | [`plan.md`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md) | +| Plan gate | [`plan-eval.md`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md) — cycle 2 `PASS` at commit `383170bbc` | +| Historical evidence | [issue #313](https://github.com/rickylabs/netscript/issues/313), carried as problem evidence only | + +### Eight-slice trace + +| Slice | Scope | State in this document | +| ----- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| 0 | Harness bootstrap and draft review surface | Summarised in this appendix; not rewritten here | +| 1 | Research corpus, current-main rebaseline, prospective JSR audit, plan lock | Summarised; the corpus is cited as a claim index, with primary sources carried into Appendix B | +| 2 | Independent PLAN-EVAL accepts the locked plan | Cycle 1 `FAIL_PLAN` on one factual-integrity defect (the generated-task count); cycle 2 `PASS`. **Final Plan-Gate cycle; no further PLAN-EVAL.** | +| 3 | Vocabulary, package graph, public APIs, TypeScript/E2E types, validation, operations, spaces, targets, state machines, refusal boundaries | [Reference-level explanation](#reference-level-explanation) and its subsections | +| 4 | Adoption, clean cutover, data safety, waves, conformance, CI/JSR/release gates, market implications, risks, kill/switch criteria | Breaking changes and migration; Prior art; Appendices C–F | +| 5 | Focused and adversarial post-draft reviews | The disposition surface below | +| 6 | Implementation-grade completeness review and author/editor dispositions | Recorded in the same disposition surface. **Not another PLAN-EVAL, and it does not restart planning.** | +| 7 | One final substantive refinement, then mechanical checks only | Reserved; the reviewer is named below | + +### Post-draft review and disposition surface + +`[PROPOSAL]` The post-draft sequence is fixed and ordered. There is no generic additional +focused-review party and there are no further plan-evaluation cycles. + +| Order | Reviewer | Scope | State at draft time | +| ----- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | +| 1 | Root (personal review) | Source, doctrine, and API review of the complete draft | Pending | +| 2 | Qwen 3.8 Max | Focused review across TypeScript inference, Standard Schema, control and recovery, migration safety, package/JSR surfaces, and market claims | Pending | +| 3 | Grok 4.6 high | Whole-RFC adversarial review | Pending | +| 4 | Author/editor | Explicit disposition of every finding, then revision | Pending | +| 5 | Fable 5 high | The absolute final substantive review and refinement. **Nothing substantive follows it** — only mechanical checks and publication. | Pending | + +Findings are recorded here as they arrive, one row each, and no finding is closed without an +explicit disposition: + +| Finding | Reviewer | Severity | Claim | Disposition | Section changed | +| ------------------------------------------------------- | -------- | -------- | ----- | ----------- | --------------- | +| _None recorded yet — this draft has not been reviewed._ | — | — | — | — | — | + +Disposition vocabulary: **accepted** (the RFC changed, and the section is named), **narrowed** (a +capability was withheld or a claim weakened), **declined with reason** (the RFC did not change, and +the reason is recorded), or **deferred to a wave** (the question is real but is an +implementation-time decision, and it is added to [Unresolved questions](#unresolved-questions) with +its owning wave). A declined finding still records the reviewer's claim verbatim. + + + +[ns-98]: https://github.com/rickylabs/netscript/pull/98 +[ns-145]: https://github.com/rickylabs/netscript/pull/145 +[ns-173]: https://github.com/rickylabs/netscript/issues/173 +[ns-1014]: https://github.com/rickylabs/netscript/issues/1014 +[ns-1059]: https://github.com/rickylabs/netscript/pull/1059 +[ns-1088]: https://github.com/rickylabs/netscript/pull/1088 +[ns-1196]: https://github.com/rickylabs/netscript/issues/1196 +[ns-1202]: https://github.com/rickylabs/netscript/issues/1202 +[ns-1254]: https://github.com/rickylabs/netscript/issues/1254 +[ns-1290]: https://github.com/rickylabs/netscript/issues/1290 +[ns-1295]: https://github.com/rickylabs/netscript/issues/1295 +[ns-1301]: https://github.com/rickylabs/netscript/pull/1301 +[ns-1310]: https://github.com/rickylabs/netscript/issues/1310 +[ns-1311]: https://github.com/rickylabs/netscript/pull/1311 +[ns-1327]: https://github.com/rickylabs/netscript/issues/1327 +[ns-1393]: https://github.com/rickylabs/netscript/pull/1393 + + + +[rc1-release]: https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1 +[rc1-readme]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/README.md +[rc1-scorecard]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/scorecard.md +[rc1-versions]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/Supported%20Versions.md +[adr-176]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20176%20-%20Data%20migrations%20as%20invariant-guarded%20transitions.md +[adr-212]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20212%20-%20Contract%20spaces.md +[pn-261]: https://github.com/prisma/prisma-next/pull/261 +[pn-27ccefc3]: https://github.com/prisma/prisma-next/commit/27ccefc3 +[pn-e1e5ab2c]: https://github.com/prisma/prisma-next/commit/e1e5ab2c +[pn-3dc98cb]: https://github.com/prisma/prisma/commit/3dc98cb +[pn-d0c8333]: https://github.com/prisma/prisma/commit/d0c8333 +[pn-15308c6]: https://github.com/prisma/prisma/commit/15308c6 +[pn-92b6ee3]: https://github.com/prisma/prisma/commit/92b6ee3 +[pn-c4a5875]: https://github.com/prisma/prisma/commit/c4a5875 +[pn-5d4a4db]: https://github.com/prisma/prisma/commit/5d4a4db +[pn-a900bc1]: https://github.com/prisma/prisma/commit/a900bc1 +[pn-71e2e0d]: https://github.com/prisma/prisma/commit/71e2e0d9ee1f306b5a11435cd1973023cb33866a +[pn-29896]: https://github.com/prisma/prisma/issues/29896 +[pn-29923]: https://github.com/prisma/prisma/issues/29923 +[pn-29932]: https://github.com/prisma/prisma/issues/29932 +[pn-29944]: https://github.com/prisma/prisma/pull/29944 +[pn-30009]: https://github.com/prisma/prisma/pull/30009 + + + +[wasp]: https://wasp.sh/docs/data-model/databases +[redwood]: https://docs.redwoodjs.com/docs/data-migrations +[payload]: https://payloadcms.com/docs/database/overview +[better-auth]: https://better-auth.com/docs/beta/guides/create-a-db-adapter +[lucid]: https://lucid.adonisjs.com/docs/migrations +[drizzle]: https://orm.drizzle.team/docs/migrations +[mikroorm]: https://mikro-orm.io/docs/architecture +[kysely]: https://www.kysely.dev/ +[flyway]: https://documentation.red-gate.com/flyway/reference/commands +[flyway-repair]: https://documentation.red-gate.com/flyway/reference/commands/repair +[liquibase]: https://docs.liquibase.com/community/user-guide-5-0-2/what-is-the-databasechangelog-table +[tf-state]: https://developer.hashicorp.com/terraform/language/state +[tf-targeting]: https://developer.hashicorp.com/terraform/tutorials/state/resource-targeting +[pulumi-state]: https://www.pulumi.com/docs/iac/concepts/state-and-backends/ +[pulumi-interrupted]: https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/ +[atlas-projects]: https://atlasgo.io/atlas-schema/projects +[bytebase-plan]: https://docs.bytebase.com/change-database/plan +[bytebase-3140]: https://docs.bytebase.com/changelog/bytebase-3-14-0 +[zenstack-multifile]: https://zenstack.dev/docs/modeling/multi-file +[zenstack-zod]: https://zenstack.dev/docs/utilities/zod +[django-multidb]: https://docs.djangoproject.com/en/5.2/topics/db/multi-db/ +[rails-multidb]: https://guides.rubyonrails.org/active_record_multiple_databases.html From ffd654fb038937a0f96fa1502e65e029f1c19143 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 20:31:54 +0200 Subject: [PATCH 09/19] docs(rfc): require a concise reader-first draft --- .../briefs/claude-opus-rfc-consolidate.md | 161 +++++++++++++ .../context-pack.md | 29 ++- .../drift.md | 17 ++ .../reviews/root-rfc-review.md | 215 ++++++++++++++++++ .../worklog.md | 42 ++-- 5 files changed, 433 insertions(+), 31 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-consolidate.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-consolidate.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-consolidate.md new file mode 100644 index 0000000000..ad23acb4ea --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-consolidate.md @@ -0,0 +1,161 @@ +# Claude Code Opus 5 high brief: consolidate the database architecture RFC + +use harness + +## SKILL + +Read and follow: + +1. `AGENTS.md` +2. `.agents/skills/netscript-harness/SKILL.md` +3. `.agents/skills/netscript-doctrine/SKILL.md` +4. `.llm/harness/workflow/activation.md` +5. `.llm/harness/workflow/run-loop.md` +6. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md` + +This is an RFC editor lane, not a new architecture-planning lane. PLAN-EVAL cycle 2 already passed. + +## Objective + +Rewrite the evidence-complete raw draft into a concise, decision-grade RFC. The owner will not read +an 18,000-word document, and the current draft is 28,194 words. Target **8,000–10,000 words** with a +hard ceiling of **12,000 words**. + +The RFC must focus on the end-state API surface, developer experience, end-to-end type safety, +contract-first architecture, plugin contribution model, bounded Standard Schema validation, and safe +operational control. Link the research rather than duplicating it. + +## Edit authority + +Edit exactly one file: + +- `rfcs/0000-database-architecture.md` + +Do not edit run artifacts, research, plans, worklogs, doctrine, source code, or any other file. Do +not commit or push. The root supervisor owns review, sign-off, commit, and publication. + +## Required reading + +Read completely before editing: + +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +- `rfcs/0000-database-architecture.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` + +Use the root review as the editing contract. Its ten technical corrections are blocking. + +## Reader promise + +The consolidated RFC should let a contributor understand, in one pass: + +- native Prisma TypeScript schema authoring without a cloned NetScript ORM DSL; +- the thin NetScript definition around native contracts; +- deterministic composition into a manifest and generated app-local inferred binding; +- native provider query types reaching application-owned ports without Prisma leaking through the + provider-neutral kernel; +- `StandardSchemaV1` input/output schemas derived from contract and operation/selection metadata, + with explicit fail-closed limits; +- plugin-owned spaces, controlled augmentation, and one extension registration fanning into + authoring/control/runtime/validation facets; +- explicit targets, ownership, artifacts, plan/apply/receipt/recovery, and safe multi-target saga + semantics; +- a clean break from the old stack plus a production-data-safe adoption path. + +## Editorial constraints + +- Preserve the repository RFC template headings: Summary, Motivation, Guide-level explanation, + Reference-level explanation, Drawbacks, Rationale and alternatives, Breaking changes and + migration, Prior art, Unresolved questions, and Future possibilities. +- Shorten the title. +- Lead with the outcome and end-state developer journey. Do not lead with harness process, + provenance, or evidence categories. +- Delete Appendices A–G. Link the approved plan and focused research artifacts instead. +- Remove inline evidence tokens such as `[PROPOSAL]`, `[RC1]`, `[NS-SRC]`, and `[INFERENCE]`. Retain + direct links near the small number of important upstream claims. +- Prefer one strong example over several variations. Every example must use one consistent proposed + import and naming surface. +- Keep only the interfaces necessary to lock public behavior. Do not reproduce every internal type, + state machine, gate, package permission, or operation catalog record. +- Keep at most one Mermaid diagram. +- Replace market feature matrices with a few lessons plus the market-analysis link. +- Avoid exact current-state counts unless they materially explain a decision. +- Avoid review-process, wave-gate, JSR-publish, and session details in the public RFC. Those remain + in run artifacts. +- Do not introduce compatibility, a dual runtime, a NetScript query DSL, runtime capability + negotiation, a hosted control plane, or unsupported multi-namespace claims. + +## Public API direction + +The examples should converge on a minimal and coherent surface, not preserve every raw-draft name. +Use the current native model-first Prisma `defineContract` builder as the schema foundation, and a +thin NetScript `defineDatabase` composition around native contract values. + +For validation, prefer this vocabulary unless source constraints force a better, equally small +alternative: + +```ts +const users = primaryBinding.ref({ space: 'app' }).model('User'); +const createUser = users.input('create', { representation: 'json' }); +const publicUser = users.output( + { select: { id: true, email: true } }, + { representation: 'json' }, +); +``` + +State the combined acceptance promise explicitly: exact native contract inference survives into the +app-local query binding, while runtime validation is intentionally bounded and fails closed whenever +the contract plus registered operation, selection, codec, or extension metadata cannot prove the +schema. + +## Technical corrections + +Apply every finding R1–R10 in `reviews/root-rfc-review.md`. In particular: + +- The first Prisma PostgreSQL adapter does not demonstrate or claim certified multi-namespace + support. Logical spaces do not magically prevent physical name collisions. +- Target-key checking occurs at `defineDatabase` composition unless a contextual API can actually + prove an earlier check. +- Pure compile/emit construction cannot receive live connection dependencies. +- Signing is not a database mutation. +- The generated binding uses one consistent generic/type association. +- Validation examples distinguish input schemas from selected output schemas. +- Persistent plugin tables default to full independent spaces; app-local native fragments and + published contribution mechanisms are not conflated. +- Transaction and import surfaces do not overclaim unproven types or package subpaths. +- Recovery has a receipt lookup path. +- Adoption never silently skips an intended target, and marker rollback is capability-qualified. + +## Evidence links to preserve + +Use relative links from the RFC to these artifacts instead of copying their contents: + +- approved architecture: `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +- Prisma source deep dive: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- native TypeScript schema/oRPC audit: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md` +- runtime-validation source audit: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md` +- market analysis: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` +- current-state audit: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md` + +Keep primary GitHub/source links where they substantiate a load-bearing upstream fact. + +## Completion report + +Before returning: + +1. Run `deno fmt rfcs/0000-database-architecture.md`. +2. Run `deno fmt --check rfcs/0000-database-architecture.md`. +3. Run `git diff --check -- rfcs/0000-database-architecture.md`. +4. Report the final word count, line count, and changed file list. +5. Confirm all R1–R10 findings were applied, naming any disposition that was not a direct edit. + +Do not claim final acceptance. Qwen 3.8 Max, Grok 4.6 high, author/editor disposition, and the one +absolute-final Fable 5 high refinement still follow. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index e8240b94b9..a20a922951 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -14,9 +14,11 @@ A clean-break database architecture RFC run is active. Issue #313 is historical evidence; its compatibility-first solution is superseded. Native Fable 5 medium PLAN-EVAL cycle 2 session -`f3286656-7d0f-4da2-a22d-32897a5e6482` passed commit `383170bbc`. Canonical RFC authorship is -unblocked but not yet complete. Current-main commit `01e096049` is recorded as nonblocking -CI/gate-tooling drift. +`f3286656-7d0f-4da2-a22d-32897a5e6482` passed commit `383170bbc`. Native Claude Code Opus 5 high +authored an evidence-complete 28,194-word raw draft, pushed as `05e5fbac2`. Root substantive review +returned `REVISE_CONSOLIDATE`: the reader-facing RFC must be reduced to 8,000–10,000 words (12,000 +hard ceiling) and apply findings R1–R10 before external post-draft review. Current-main commit +`01e096049` remains nonblocking CI/gate-tooling drift. ## Completed @@ -27,15 +29,18 @@ CI/gate-tooling drift. - Completed the research corpus, D-01–D-47 lock, prospective JSR audit, and architecture synthesis. - Preserved cycle 1 `FAIL_PLAN`, corrected the task finding to 42 keys per generated engine workspace, and obtained cycle 2 `PASS`. +- Authored and pushed the evidence-complete raw RFC draft. +- Completed root personal source/doctrine/API review and wrote the Opus consolidation contract. ## In Progress -- Slice 3 canonical RFC authorship from the evaluator-approved architecture. +- Slice 3 canonical RFC consolidation and technical correction by a fresh Opus 5 high authoring + session. ## Next Steps -1. Author the complete canonical RFC from D-01–D-47 and the W0–W11 implementation waves. -2. Perform the root personal source/doctrine/architecture review. +1. Consolidate the raw RFC to 8,000–10,000 words and resolve root findings R1–R10. +2. Root reviews and signs off the consolidated reader-facing draft. 3. Run Qwen 3.8 Max as the focused post-draft review. 4. Run Grok 4.6 high as the whole-RFC adversarial review. 5. Apply author/editor dispositions for every actionable finding. @@ -59,12 +64,12 @@ CI/gate-tooling drift. ## Gates -| Gate family | Current status | Evidence | -| ----------- | -------------- | ---------------------------------- | -| Static | pending | Bootstrap inspection follows. | -| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | -| Runtime | N/A | Docs-only RFC run. | -| Consumer | in progress | RFC authorship unblocked. | +| Gate family | Current status | Evidence | +| ----------- | -------------- | ----------------------------------- | +| Static | pending | Bootstrap inspection follows. | +| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | +| Runtime | N/A | Docs-only RFC run. | +| Consumer | revise | Root review requires consolidation. | ## Open Questions diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md index e66f694f1f..ae6802d21a 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -163,3 +163,20 @@ documentation. - **Action:** accept as a research input; reconcile its broader validation assumptions against the later pinned-source validation audit before plan lock. - **Evidence:** report section index and native turn receipts for parts 1–3. + +## 2026-08-13 — Raw RFC requires owner-directed consolidation + +- **What:** The evidence-complete authoring pass produced a 28,194-word RFC, while the owner + requires a short, specific decision document focused on API, DX, type safety, contract-first + composition, and plugin contribution. +- **Source:** Raw RFC commit `05e5fbac2`; owner direction in the active session; root review + `reviews/root-rfc-review.md`. +- **Expected:** The author brief required complete coverage but did not impose a reader-facing word + ceiling. +- **Actual:** The draft correctly preserves research and decisions but duplicates run evidence, + gates, process, and source traces that belong behind links. +- **Severity:** editorial/significant. +- **Action:** accept the raw document only as an evidence draft; resume Opus 5 high with a strict + 8,000–10,000-word target and 12,000-word hard ceiling, apply root findings R1–R10, then continue + Qwen → Grok → dispositions → final Fable review order. +- **Evidence:** `briefs/claude-opus-rfc-consolidate.md`; no architecture decision is reopened. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md new file mode 100644 index 0000000000..ee40f5bee9 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md @@ -0,0 +1,215 @@ +# Root review: raw database architecture RFC + +## Review receipt + +| Field | Value | +| ---------------- | ------------------------------------ | +| Reviewer | Root Codex supervisor | +| Date | 2026-08-13 | +| Evaluated commit | `05e5fbac2` | +| Evaluated file | `rfcs/0000-database-architecture.md` | +| Raw size | 28,194 words; 3,140 lines | +| Verdict | `REVISE_CONSOLIDATE` | + +The draft is evidence-complete and contains the approved architecture, but it is not an acceptable +reader-facing RFC. The owner explicitly rejected a book-length result. The next version must be a +specific architectural decision document whose center of gravity is the end-state API and developer +experience. Research, source traces, implementation gates, and review provenance should be linked, +not recopied. + +Target **8,000–10,000 words**. Hard ceiling **12,000 words**. The final document should be useful to +an implementer who reads it once and to an owner who wants to decide whether the proposed database +story is the right one. + +## What the RFC must make obvious + +After reading the RFC, a contributor should be able to answer these questions without opening the +research corpus: + +1. What does an application author write to define a database contract, target, and space? +2. How do native Prisma TypeScript contract types flow into an application-local typed binding? +3. How does a plugin contribute an independently owned database space or a permitted augmentation? +4. How does one extension registration supply authoring, control, runtime, and validation facets? +5. How are `StandardSchemaV1` input and output validators obtained, and where does validation fail + closed? +6. What is pure and deterministic, what needs a live database, and what is mutating? +7. What artifacts exist, who owns each artifact, and how do plan, apply, receipt, and recovery + differ? +8. What is deliberately removed, and how can existing production data be adopted without a dual + runtime or schema mutation? + +The document should lead with one coherent end-to-end journey and a small number of executable-shape +API examples. Reference details should exist only when they constrain implementation or prevent an +unsafe interpretation. + +## Required editorial changes + +### Keep and sharpen + +- The native, model-first Prisma `defineContract` example. State plainly that NetScript wraps the + contract with identity, ownership, policy, and lifecycle; it neither clones nor re-exports the + Prisma builder. +- One `defineDatabase` composition example, one generated binding/runtime example, one validation + example, one plugin-space/extension example, and one plan/apply example. +- The contract-first type-flow promise: authored contract → manifest → app-local binding → native + query types → boundary schemas → operation artifacts. +- The five distinct artifact roles: definition, manifest, executable plan, provider ledger/marker, + immutable receipt. Prefer a compact authority table to full interface declarations. +- The bounded, fail-closed Standard Schema decision and the `runtime | json` representation split. +- The ownership/removal rule, explicit target identity, no silent omission, and multi-target saga + semantics. +- The clean-break law and data-safe adoption protocol. +- The major refusals: no query DSL, no compatibility stack, no global registry/service locator, no + false portability, and no hosted control plane in this RFC. + +### Replace with links or remove + +- Remove process front matter, evidence-tag vocabulary, “how to read” mechanics, reviewer order, + session identifiers, and claim-by-claim provenance from the public RFC. +- Remove Appendices A–G. D-01–D-47, W0–W11, the conformance matrix, JSR audit, risk register, claim + ledger, and review trace already have canonical run artifacts. +- Replace per-package ownership/dependency/permission/publication/gate subsections with one package + graph table that says why each boundary exists. +- Remove the optional policy factory from v1. The thin Candidate-A surface is the decision; a future + factory need not compete with it in the main narrative. +- Replace large TypeScript declarations for every artifact, diagnostic, port, and operation with the + smallest signatures necessary to lock the public contract. +- Keep at most one lifecycle diagram. Summarize the other state machines as invariants or short + transition lines. +- Replace the large market matrix with four to six lessons and link `research/market-analysis.md` + for the evidence. +- Move exact current-state counts, verb-by-verb disposition, exhaustive gates, kill criteria, and + publication mechanics to the linked research/plan unless a number is essential to the decision. +- Eliminate repeated statements of the same refusal or clean-break rule. +- Replace `[RC1]`, `[PROPOSAL]`, `[NS-SRC]`, and similar inline tags with normal prose and direct + links near the few claims for which stability or evidence class matters. + +## Required technical corrections + +These are blocking findings for the consolidated draft. + +### R1 — first-adapter namespace contradiction + +The guide maps `app` and `auth` to separate physical namespaces and claims namespaces prevent plugin +table collisions, while the reference section withholds Prisma multi-namespace certification. The +first certified PostgreSQL adapter examples must use its one supported physical namespace. Logical +`SpaceId` and ownership coordinates prevent silent merging; they do not make identical physical +table names coexist. Until upstream type/runtime parity is proven, composition must refuse physical +name collisions and non-default namespace requests. + +### R2 — target-key type-check location + +An independently evaluated `defineDatabaseSpace({ target: 'primary' })` call cannot know the keys of +a later `targets` object. State that the mismatch is rejected when the space is composed by +`defineDatabase`, unless implementation proves a contextual factory signature. Do not promise a type +error at the standalone space call site. + +### R3 — pure control must be structurally offline + +The guide constructs `createDatabaseControl` with `connections` and then calls `emit` “with no +connection.” Make the API boundary prove that claim: construct the pure compiler/control catalog +without live connections, and pass explicit live dependencies only to `inspect`, `plan` when live +state is needed, `apply`, and `verify`; or expose distinct pure and live executors. The public +example must not rely on a promise that an injected connection resolver simply goes unused. + +### R4 — operation classification + +Signing an artifact is not a target-database mutation and must not require a migration lock. Keep +artifact-side policy/signature work separate from live database mutation. Operation classes should +be intuitive from the API rather than supported by an exhaustive catalog declaration. + +### R5 — one binding generic model + +The draft alternates between `AppBinding<'primary', AppContract>` and a runtime `bind` signature +whose second generic acts like a query type. Choose one model and show it consistently. The +generated application-local binding should own the contract-to-query association, while +provider-specific `QueryOf` remains inside generated/provider code and does not leak into +framework packages. + +### R6 — validation API and example semantics + +Choose one small public vocabulary. Recommended reader-facing shape: + +```ts +const users = primaryBinding.ref({ space: 'app' }).model('User'); + +const createUser = users.input('create', { representation: 'json' }); +const publicUser = users.output( + { select: { id: true, email: true } }, + { representation: 'json' }, +); +``` + +An explicit whole-model form may be `users.output('model', options)` if needed. Avoid competing +`value`/`operation`/`result` and `input`/`output` vocabularies. Reuse the create-input schema at an +input boundary and the selected-output schema at output boundaries; do not validate an arbitrary +Fresh payload with a query-result schema. Preserve the decisive limitation: unsupported operation or +selection metadata throws `DB_VALIDATION_UNSUPPORTED` at schema construction, while invalid user +data produces path-rich Standard Schema issues. + +### R7 — plugin contribution modes must be implementable + +The RFC both forbids published app fragments because provider helper types cannot cross a stable +published boundary and shows a generated `authFragment`-style contribution. Define the v1 modes +without contradiction: + +- persistent plugins contribute full independently versioned spaces with pinned artifacts by + default; +- application-local composition may use const-preserving, two-phase native fragments; +- cross-space augmentation is explicit, capability-limited, and ownership-checked; +- a published package may not masquerade as an app-local native fragment unless W3 proves a + generated-source or provider-specific package mechanism that preserves exact inference. + +### R8 — transaction and import surfaces must not overclaim + +Do not assert that a transaction exposes exactly the ordinary `TQuery` surface until W4 proves it; +use a distinct inferred transaction query type or keep the example illustrative. Use one coherent +package/subpath import story throughout. Do not introduce `@netscript/database/connection` unless +the package graph explicitly owns that public subpath. + +### R9 — receipts need a recovery read path + +A write-only `ReceiptSink` cannot by itself support resume and evidence lookup. The concise RFC need +not lock every port method, but it must state that the immutable receipt store supports append and +lookup by `RunId`/resume token, or name separate source and sink roles. + +### R10 — adoption cannot silently proceed on a subset + +“Proceed for reachable targets only” conflicts with explicit target closure and no silent omission. +Adoption may operate on an explicitly selected target set and must return a status for every +selected target. Full cutover is blocked until all intended targets are reachable, attributed, +baselined, and verified. Marker removal should be promised only where provider semantics prove it. + +## Recommended final structure and budget + +Preserve the repository RFC template headings, with roughly this allocation: + +| Section | Purpose | Budget | +| ------------------------------ | -------------------------------------------------------------------------- | ----------: | +| Summary | Decision, scope, non-goals, one architecture flow | 500–700 | +| Motivation | Manual surface and why Prisma 8 changes the opportunity | 700–1,000 | +| Guide-level explanation | End-state authoring, composition, binding, validation, plugins, operations | 3,000–3,800 | +| Reference-level explanation | Concepts, package boundaries, artifacts, invariants, capabilities | 2,000–2,800 | +| Drawbacks | Real costs and upstream coupling | 400–700 | +| Rationale and alternatives | Why this layer, why not the rejected shapes, short market lessons | 700–1,000 | +| Breaking changes and migration | Clean break, safe adoption, parallel branch strategy | 700–1,100 | +| Prior art | Links and the lessons actually adopted | 300–500 | +| Unresolved questions | Only decisions genuinely left to implementation or upstream proof | 250–500 | +| Future possibilities | Explicitly deferred capabilities | 200–400 | + +The section budgets are guidance; the 12,000-word ceiling is mandatory. + +## Acceptance for the next draft + +- 8,000–10,000 words preferred; no more than 12,000. +- Template headings remain and the title is shortened. +- The first two pages expose the decision and the end-state API/DX, not process metadata. +- Every code sample participates in one coherent API and respects the first adapter's actual + capabilities. +- The native contract type is preserved through composition and an app-local binding without a + NetScript query DSL or Prisma type leakage into provider-neutral packages. +- Plugin space, extension bundle, validation, control, and adoption stories each fit in one focused + subsection. +- All ten technical findings above are corrected or explicitly dispositioned in this review file. +- Exhaustive evidence remains reachable through direct links to the run research and approved plan. +- No compatibility shim, dual runtime, or false multi-provider claim is reintroduced while editing. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index ca75f12a77..5ab55e0f48 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -140,18 +140,20 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in ## Progress Log -| Time | Slice | Step | Notes | -| ---------- | ----- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | -| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | -| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | -| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | -| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | -| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | -| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | -| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | -| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | -| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | +| Time | Slice | Step | Notes | +| ---------- | ----- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | +| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | +| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | +| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | +| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | +| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | +| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | +| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | +| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | +| 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | +| 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | ### PLAN-EVAL Cycle 1 @@ -221,10 +223,10 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ### Consumer Gates -| Consumer | Result | Evidence | Notes | -| ---------------------- | ----------- | ------------------------------------------------------------- | ---------------------------------- | -| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | -| RFC reader/implementer | IN_PROGRESS | RFC authorship unblocked | Canonical RFC is not yet complete. | +| Consumer | Result | Evidence | Notes | +| ---------------------- | ------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | +| RFC reader/implementer | REVISE | `reviews/root-rfc-review.md`; raw draft commit `05e5fbac2` | Evidence is complete; the reader-facing RFC must now be consolidated and technically corrected. | ## Handoff Notes @@ -232,6 +234,8 @@ CI/gate-tooling drift that changes structured check invocation rather than datab preserved; cycle 2 passed and no further PLAN-EVAL cycle is requested. - Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until packages exist and must produce implementation/release receipts later. -- Continue RFC authorship, then follow the owner-locked post-draft order: root personal review, Qwen - 3.8 Max focused review, Grok 4.6 high whole-RFC adversarial review, author/editor dispositions, - one final Fable 5 high substantive refinement, and mechanical checks only. +- Resume the Opus 5 high authoring family with `briefs/claude-opus-rfc-consolidate.md` and reduce + the canonical RFC to 8,000–10,000 words (12,000 hard ceiling), applying root findings R1–R10. +- After root accepts the consolidated draft, continue the owner-locked order: Qwen 3.8 Max focused + review, Grok 4.6 high whole-RFC adversarial review, author/editor dispositions, one final Fable 5 + high substantive refinement, and mechanical checks only. From 5dfc4e8eb3988818fc81c6f5dc2856d551443249 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 21:07:59 +0200 Subject: [PATCH 10/19] docs(rfc): consolidate database architecture draft --- rfcs/0000-database-architecture.md | 3672 +++++++--------------------- 1 file changed, 914 insertions(+), 2758 deletions(-) diff --git a/rfcs/0000-database-architecture.md b/rfcs/0000-database-architecture.md index 053a719384..f46040d8b8 100644 --- a/rfcs/0000-database-architecture.md +++ b/rfcs/0000-database-architecture.md @@ -1,6 +1,6 @@ --- rfc: 0000 -title: Database architecture — a provider-neutral composition and operations kernel, with Prisma 8 PostgreSQL as the first certified adapter +title: Database architecture — a provider-neutral kernel with a Prisma 8 PostgreSQL adapter status: Draft authors: ['@rickylabs'] created: 2026-08-13 @@ -8,316 +8,190 @@ tracking-issue: https://github.com/rickylabs/netscript/issues/313 target-milestone: Backlog / Triage --- -# Database architecture — a provider-neutral composition and operations kernel, with Prisma 8 PostgreSQL as the first certified adapter - -> **Process and front-matter notes.** -> -> - This draft lives at `rfcs/0000-database-architecture.md` and keeps the `0000` number until a -> maintainer assigns one at acceptance, per [`rfcs/README.md`](./README.md) § Numbering. -> - `tracking-issue` currently points at -> [issue #313](https://github.com/rickylabs/netscript/issues/313). #313 is carried as **historical -> problem evidence only**: its compatibility-first, additive solution is explicitly superseded by -> the clean-break directive in this RFC. The companion `rfc:` tracking issue is opened together -> with the draft PR (`rfcs/README.md` § Lifecycle step 1) and replaces this field at that point. -> - `target-milestone` is `Backlog / Triage` because no release milestone is committed yet. An -> accepted RFC's tracking issue moves to a `0.0.x` milestone when the implementation program is -> scheduled. -> - This RFC is **breaking**. The tracking issue and PR carry the `breaking` label. - -## How to read this RFC - -This document proposes a replacement for NetScript's database foundation. It is written to be -implementation-grade: an implementer should be able to derive package boundaries, public types, -state transitions, test matrices, refusal behaviour, and release gates from it without inventing -architecture. - -Because the proposal sits on top of a moving upstream project, every material claim carries an -explicit evidence class. These tags are used consistently and mean exactly what they say: - -| Tag | Meaning | -| ------------- | --------------------------------------------------------------------------------------------------------------------------------- | -| `[NS-SRC]` | Current NetScript source fact, at baseline `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf`. | -| `[RC1]` | Prisma source fact at the pinned release candidate `v8.0.0-rc.1@a76a6c5` (`a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`). | -| `[POST-RC]` | Prisma source fact at the audited post-RC object `71e2e0d9ee1f306b5a11435cd1973023cb33866a`. Never a statement about RC1 or GA. | -| `[PRIMARY]` | Official primary source: an upstream release, README, ADR, scorecard, issue, pull request, or product documentation page. | -| `[EXCHANGE]` | The owner/Prisma-maintainer conversation. **Exploratory direction, not an upstream commitment.** | -| `[INFERENCE]` | Reasoning that reconciles the facts above. Not an implemented capability. | -| `[PROPOSAL]` | NetScript design proposed by this RFC. Not implemented. | -| `[COND]` | Conditional or unproven implementation capability. It is withheld until a named gate passes, and it is never claimed as shipping. | - -Three rules govern how those classes combine, and they are load-bearing rather than stylistic: - -1. **Post-RC code is never presented as RC1 behaviour, and RC1 behaviour is never presented as a GA - guarantee.** Prisma 8 RC1 is Early Access and its release notes state that RC respins may break, - remove, or rename APIs and the contract format ([RC1 release][rc1-release]) `[PRIMARY]`. -2. **Local research reports are a claim index, not an authority.** Every material external claim in - this RFC is source-linked to a primary source or to a pinned source object. The run's research - corpus under - [`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md) - is where the derivation is recorded; it is not a substitute for the upstream citation. - Independent model reports in that corpus are adversarial evidence, and where they conflict with - executed verification the executed result wins (Appendix B records both). -3. **Unknowns are labelled, and an attractive inference is never promoted to a supported - capability.** Everything that implementation must decide appears in - [Unresolved questions](#unresolved-questions) with the wave that owns it. +# Database architecture — a provider-neutral kernel with a Prisma 8 PostgreSQL adapter ## Summary -NetScript replaces its inherited database foundation with a single provider-neutral composition and -operations kernel, and certifies exactly one adapter first: Prisma 8 on PostgreSQL. Applications and -plugins author their schema in **native Prisma TypeScript** — the current model-first -`defineContract(scaffold, callback)` form — and pass that exact native value into thin NetScript -definitions that add identity, ownership, capability, lifecycle, and policy without touching the -provider's entity vocabulary or widening its inference. A pure two-phase composition compiles those -definitions into canonical `ContractArtifact`s and one deterministic, content-addressed -`DatabaseManifest`. The manifest is the durable join point for everything downstream: generated -application-local bindings and typed sessions, bounded contract-derived Standard Schema validators, -programmatic preview/plan/apply/verify operations, provider locks and ledgers, immutable operation -receipts, and generated CLI, documentation, and agent surfaces. - -The design is a clean break. There is no compatibility API, no Prisma 7 fallback, no dual runtime, -no legacy adapter facade, and no application that composes both stacks. Data continuity is -nevertheless absolute: `netscript db adopt` is a temporary migration tool that introspects live -databases, proposes ownership, writes provider marker metadata only, and performs **zero** table or -data DDL/DML before verification. The kernel deliberately refuses to become a second ORM: it defines -no query DSL, no repository abstraction, no portable client facade, no runtime capability -negotiation, and no hosted control plane. Where a capability cannot be made sound — multi-namespace -end-to-end typing, full Prisma operation validation derived from contract data alone, destructive -plugin removal, non-PostgreSQL providers — this RFC withholds the claim and names the gate that -would release it, rather than casting around the gap. +NetScript replaces its inherited database foundation with one provider-neutral composition and +operations kernel, and certifies exactly one adapter first: Prisma 8 on PostgreSQL. -## Motivation +Applications and plugins author schema in **native Prisma TypeScript** — the current model-first +`defineContract(scaffold, callback)` form — and pass that exact native value into a thin NetScript +definition that adds identity, ownership, capability requirements, policy, and lifecycle. NetScript +adds no schema vocabulary of its own: no query DSL, no model language, no re-exported builder. A +pure compiler resolves those definitions into canonical contract artifacts and one deterministic, +content-addressed `DatabaseManifest`. The manifest is the durable join point for everything +downstream: a generated application-local binding whose types are inferred from the native contract, +typed process/request sessions, bounded `StandardSchemaV1` validators at trust boundaries, +programmatic emit/inspect/plan/apply/verify operations, provider markers and ledgers, immutable +operation receipts, and generated CLI, documentation, and agent surfaces. -### The problem is not a Prisma version +The end-to-end flow is one pipeline of separately named values, and no stage may impersonate +another: -NetScript does not currently have one database architecture. It has five partially-overlapping -systems whose identities and ownership rules do not line up `[NS-SRC]`: +```text +native contracts + NetScript definitions + → pure composition → ContractArtifacts → DatabaseManifest + → generated app-local binding → sessions + bounded validators + → inspected baseline → ExecutablePlan → provider apply/ledger + → immutable OperationReceipts → verify / resume +``` -1. an appsettings/Aspire database-resource model; -2. a fixed CLI engine registry and operation runner; -3. a generated per-engine Prisma workspace and task graph; -4. a runtime adapter wrapper around user-constructed Prisma clients; and -5. an install-time plugin Prisma-fragment copier. +This is a clean break. There is no compatibility API, no Prisma 7 fallback, no dual runtime, no +legacy adapter facade, and no application that composes both stacks. Data continuity is nevertheless +absolute: `netscript db adopt` introspects live databases, proposes ownership, writes provider +marker metadata only, and performs **zero** table or data DDL/DML before verification. -The happy path works only when those systems agree about config keys, engine directory names, -environment variables, generated files, Prisma CLI behaviour, adapter packages, and a live Aspire -resource graph. The framework makes that agreement a developer and CI responsibility, then adds -post-generation repair scripts where upstream output does not fit Deno expectations. There is no -canonical value joining the five views, so every fix lands in one of them and the failure moves. - -Substituting Prisma 8 for Prisma 7 under that structure would preserve every one of those seams. The -missing foundation is a NetScript-owned, typed, inspectable composition from which resource -provisioning, schema composition, client construction, generated imports, migrations, validation, -plugin contributions, diagnostics, and CI plans are all derived. - -### Identity collapses into provider and engine names - -The single most consequential defect is that **provider identity has replaced target identity** -`[NS-SRC]`: - -- The generated workspace directory is computed as `join('database', provider.dirName)` from a - closed engine enum (`packages/cli/src/kernel/adapters/database/workspace-resolver.ts:51`). Two - PostgreSQL databases therefore share one schema tree, one migration history, one generated client, - and one task set. `db add postgres --name analytics` creates another configuration entry but still - renders and resolves `database/postgres/`; the public second-database guide currently claims - otherwise. -- `resolveTarget` defaults only when exactly one target is enabled and never consults - `NetScript.PrimaryDatabase` (`workspace-resolver.ts:66-91`; independently re-verified during - PLAN-EVAL cycle 2). With more than one enabled target and no `--db`, resolution throws - `Unknown database target: (default)`, which contradicts documentation stating that a bare command - targets the primary database. -- Engine selection is a `switch` over `'postgres' | 'mysql' | 'sqlite' | 'mssql'` - (`workspace-resolver.ts:96+`), which is the literal counter-example doctrine records as AP-24 - ([`09-anti-patterns-and-fitness-functions.md`](../docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md)). - -`[INFERENCE]` Every downstream artifact — output root, migration lineage, runtime binding, lock, -receipt — inherits that collapse. No amount of new tooling repairs it while the identity of a -logical database has no representation. - -### Generation is a repair pipeline, not an emission - -Executing `generateDatabaseDenoJson` for each of PostgreSQL, SQLite, MySQL, and SQL Server produces -**42 `db:*` task keys in every generated engine workspace** `[NS-SRC]` (executed by the PLAN-EVAL -evaluator at commit `383170bbc` against -`packages/cli/src/kernel/templates/database/generate-db-deno-json.ts`). The current-state audit's -description of "more than twenty database tasks" was accurate; the executed count is the precise -figure and is the one this RFC uses. Generated templates additionally pin `npm:prisma@^7.4.2` -(`generate-db-deno-json.ts:36,56,59,61,67`) while the root catalog carries caret ranges `^7.8.0` -(`deno.json:231-236`) `[NS-SRC]`. - -The nominal `db:generate` pipeline performs placeholder removal, Prisma client generation, a second -generation through a Zod wrapper, generated-import rewriting, circular-reference rewriting, -getter-pattern rewriting, decimal-compatibility rewriting, a generated CRUD alias barrel, Prisma -client renaming/facade patching, and a further repair pass `[NS-SRC]`. The result is non-atomic -generated source that NetScript mutates based on upstream textual output. A developer can edit the -schema, skip the pipeline, and keep compiling against stale types. - -### Plugin schema contribution has no ownership semantics - -Plugins ship plain `database/**/*.prisma` files. On install the CLI discovers or downloads -fragments, chooses one database target, copies each fragment into the consumer's schema tree, scans -top-level `model|enum|type|view` blocks with a regex/balanced-brace parser -(`packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts:13`), removes -byte-normalised identical declarations, and rejects same-name declarations with different bodies -(`prisma-schema-writer.ts:19,100-122`) `[NS-SRC]`. - -That model cannot express a contribution contract or schema version, supported providers or -capabilities, target selection policy, dependency ordering, declaration ownership or allowed -augmentation, migration ownership and rollout, uninstall data policy, deterministic provenance, or a -contributor test kit. Its historical failure modes are on record: dependency-mode installs reported -success while omitting every plugin table ([#1014][ns-1014]) `[PRIMARY]`, and model-name clashes -broke authentication installs until namespacing plus a custom collision guard landed -([PR #1059][ns-1059]) `[PRIMARY]`. Removal deletes the copied directory; it plans no database -migration at all. - -### The recurrent failure classes are architectural, not incidental - -| Failure class | Primary evidence | Architectural lesson | -| ---------------------------------------------------------------------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------------- | -| Prisma schema-engine crash/hang on Windows | [PR #98][ns-98], [PR #145][ns-145] | NetScript CI ended up owning an upstream subprocess lifecycle and flake classification. | -| A facade compiled only against a placeholder client, then failed after a real generation | [#173][ns-173] | Stubs and generated-client contracts diverge; every capability axis needs generated proof. | -| Plugin schema silently absent in dependency installs | [#1014][ns-1014] | Source-layout discovery is not a contribution contract. | -| Plugin/base model collision | [PR #1059][ns-1059] | A global declaration namespace needs explicit ownership and conflict semantics. | -| A read-only database command killed the resident AppHost | [PR #1088][ns-1088] | Database operations lacked a stable lifecycle owner. | -| An ephemeral AppHost leaked and masked the real host | [#1196][ns-1196], [PR #1301][ns-1301] | Fixing lifecycle symptoms without one operation model moves the failure. | -| A second AppHost mounted live `PGDATA` and corrupted it | [#1310][ns-1310], [PR #1311][ns-1311] | Resource reconstruction is unsafe; operations must bind an authoritative resolved value. | -| A stale allocated PostgreSQL endpoint | [#1202][ns-1202], [PR #1393][ns-1393] | Connection provenance must be inspectable and validated against the live allocation. | -| Headless migrate returned success without producing an artifact | [#1327][ns-1327], [PR #1393][ns-1393] | An exit code is not a result; operations need typed plans and artifact/state postconditions. | -| A multi-model Zod alias hid symbols, and its repair then broke startup | [#1254][ns-1254], [#1290][ns-1290] | Generated symbol paths cannot be the framework contract. | -| Split Zod module instances broke schema interoperability | [#1295][ns-1295] | Validation needs a standards-facing contract and a controlled dependency boundary. | - -`[NS-SRC]` `[PRIMARY]` The most severe lifecycle bug cost a measured pilot several hours, two -database resets, and a privileged host scrub; the final artifact-proof repair took six serialized -`scaffold.runtime` attempts as successive harness assumptions surfaced. This RFC exists to retire -those classes structurally rather than to fix another instance of them. - -### Two recorded architecture-debt entries are closed by this design - -`[NS-SRC]` `DB-GENERATE-ASPIRE-COUPLING` is open and documents that pure code generation still boots -Aspire, so generation fails where the Aspire CLI or .NET is absent. `packages/database — AP-17` -remains open; its `interfaces/` → `ports/` rename half is stale because `packages/database/ports/` -already exists, while its composition-root finding is still current. Auth roadmap item R1 -independently requires deterministic plugin-aware schema and migration automation, which this design -must satisfy as an ordinary contribution rather than an auth-specific escape hatch. +Two acceptance conditions bind implementation, and the design is narrowed rather than softened if +either fails: -### Why Prisma 8 changes the calculus +> **Exact native contract inference survives into the app-local query binding** — no private +> imports, no copied overloads, no casts, no declaration widening. +> +> **Runtime validation is intentionally bounded and fails closed** — a schema is produced only where +> the contract plus registered operation, selection, codec, and extension metadata can prove it; +> everything else raises `DB_VALIDATION_UNSUPPORTED` at schema construction. + +Explicit non-goals: no query DSL or repository layer, no portable client facade, no runtime +capability negotiation, no global provider registry, no hosted control plane, and no capability +claimed before a conformance gate proves it. Where a capability cannot be made sound today — +multi-namespace end-to-end typing, full Prisma operation validation from contract data, destructive +plugin removal, non-PostgreSQL providers — this RFC withholds the claim and names the gate that +would release it. -`[RC1]` `[PRIMARY]` Prisma 8 is not Prisma 7 with a new generator. Its RC source is arranged as a -canonical contract plus separate control and execution planes: PSL or a TypeScript contract builder -lowers into a canonical `contract.json` and a `contract.d.ts`, a small versioned runtime consumes -the contract, a programmatic control client exposes emit/inspect/plan/apply operations, migrations -are content-addressed graph edges with per-space markers and a ledger, and **contract spaces** make -one contributor's `(contract, migration graph, head ref)` a first-class disjoint tuple -([ADR 212][adr-212]). - -That direction attacks NetScript's pain points at the root: generated executable client source can -disappear, source-rewriting and validator repair passes can disappear, schema ownership can be -modelled instead of inferred from copied files, migrations can be planned and verified -programmatically, structured results can replace log scraping, and family/target/adapter/driver/ -extension become distinct axes instead of one `engine` string. - -It is also not yet a safe surface to expose directly, and this RFC treats that as a design input -rather than a caveat: - -- Prisma 8 RC1 is Early Access and is explicitly not recommended for production workloads - ([RC1 README][rc1-readme]) `[PRIMARY]`. PostgreSQL is the sole database intended for the 8.0 GA - target set; MongoDB is Early Access, SQLite is a proof of concept, MySQL follows later, and SQL - Server is absent from the RC feature matrix ([scorecard][rc1-scorecard]) `[PRIMARY]`. -- `@prisma/orm-postgres` — described as the one package an application installs — publishes **138** - top-level export subpath keys at the pin, spanning adapters, control internals, contract - internals, migration tooling, query ASTs, runtime, target planning, and utilities `[RC1]` - (independently recounted during PLAN-EVAL cycle 2; an earlier independent report's figure of - approximately 275 is superseded). A framework that re-exported that surface would convert upstream - Early-Access internals into NetScript public API. -- The integration seam moved materially within six days of the RC tag `[POST-RC]`: the `prisma-next` - CLI stopped being published in favour of a unified CLI ([`3dc98cb`][pn-3dc98cb]), migration and - database commands were routed through the control API ([`d0c8333`][pn-d0c8333]), config - diagnostics and a ControlClient test double landed ([`15308c6`][pn-15308c6]), contract JSON Schema - became generated from ArkType ([`92b6ee3`][pn-92b6ee3]), the PostgreSQL floor dropped from 17 to - 15 ([`5d4a4db`][pn-5d4a4db]), aggregate number semantics changed ([`a900bc1`][pn-a900bc1]), and - command output channels were made explicit ([`71e2e0d`][pn-71e2e0d]). - -`[INFERENCE]` The correct response to a good architecture on a moving surface is to adopt its -_semantics_ through a very small, allowlisted adapter, and to keep NetScript's own vocabulary, -artifacts, and operations stable across the churn. That is what this RFC specifies. - -### What it costs to not do this - -`[INFERENCE]` Without this change: two logical PostgreSQL databases remain unrepresentable; plugin -schema stays a regex file copy with no version, ownership, or removal semantics; CI keeps paying for -Aspire on pure code generation; success keeps being reported by exit code; generated source keeps -being textually repaired; and the auth roadmap's deterministic plugin-aware migration requirement -has nowhere to land except an auth-specific generator. Each of those has already produced at least -one recorded production-shaped incident in the table above. - -### What it unlocks - -`[PROPOSAL]` A developer declares targets and spaces once, authors schema in native Prisma -TypeScript, and then receives — without a copied schema, a hand-synchronised type, a hand-written -adapter, a textual repair, or an implicit target choice — query types, lifecycle-owned sessions, -Standard Schema validators at trust boundaries, migrations with plans and receipts, plugin schema -ownership with independent history, CI evidence, and a generated agent surface. Section -[Guide-level explanation](#guide-level-explanation) is that experience end to end. +The approved architecture, the locked decision ledger (D-01–D-47), the implementation waves +(W0–W11), and the conformance and publishability matrices live in the +[approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md); the evidence +behind every upstream claim lives in the linked research artifacts. This document is the decision +and the developer experience. -## Guide-level explanation +## Motivation -This section describes the system as if it had shipped. It is the developer experience the rest of -the RFC exists to make true. +### The problem is not a Prisma version -> **Example status.** Every example whose imports are `@netscript/*` is intended to be executable -> exactly as written once the packages in [§ Package graph](#the-package-graph-and-archetypes) -> exist. Every example that imports `@prisma/*` shows the **RC1 authoring shape** `[RC1]` and its -> exact module specifier is an adapter-pinned, implementation-time decision (D-41, wave W3): treat -> those specifiers as illustrative pseudocode until the W3 spike pins them. This distinction is -> deliberate — Prisma's own public CLI package name changed six days after the RC tag `[POST-RC]`, -> so freezing an upstream specifier in a NetScript contract would be a design error. +NetScript does not have one database architecture. It has five partially overlapping systems whose +identities and ownership rules do not line up: an appsettings/Aspire resource model, a fixed CLI +engine registry and operation runner, a generated per-engine Prisma workspace and task graph, a +runtime adapter wrapping a user-constructed Prisma client, and an install-time plugin fragment +copier. The happy path works only when all five agree about config keys, engine directory names, +environment variables, generated files, Prisma CLI behaviour, adapter packages, and a live Aspire +resource graph — an agreement the framework makes a developer and CI responsibility. There is no +canonical value joining the five views, so every fix lands in one of them and the failure moves +([current-state audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md)). + +Three defects are structural rather than incidental. + +**Provider identity has replaced target identity.** The generated workspace directory is computed as +`join('database', provider.dirName)` from a closed engine enum +(`packages/cli/src/kernel/adapters/database/workspace-resolver.ts:51`), so two PostgreSQL databases +share one schema tree, one migration history, one generated client, and one task set: +`db add postgres --name analytics` writes another configuration entry but still resolves +`database/postgres/`. `resolveTarget` defaults only when exactly one target is enabled and never +consults `NetScript.PrimaryDatabase` (`:66-91`), so a bare command with two enabled targets throws +`Unknown database target: (default)`, contradicting the documentation. Engine selection is a +`switch` over `'postgres' | 'mysql' | 'sqlite' | 'mssql'` — the literal counter-example doctrine +records as AP-24 +([anti-patterns](../docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md)) — and +every downstream artifact inherits that collapse. + +**Generation is a repair pipeline, not an emission.** The nominal `db:generate` path performs +placeholder removal, client generation, a second generation through a Zod wrapper, four kinds of +source rewriting, a generated CRUD alias barrel, client renaming and facade patching, and a further +repair pass. The result is non-atomic generated source that NetScript mutates from upstream textual +output, and a developer can edit the schema, skip the pipeline, and keep compiling against stale +types. Pure code generation also boots Aspire — the open `DB-GENERATE-ASPIRE-COUPLING` debt entry. + +**Plugin schema contribution has no ownership semantics.** Plugins ship plain `database/**/*.prisma` +files; on install the CLI copies each fragment into the consumer's schema tree, scans top-level +blocks with a regex/balanced-brace parser, removes byte-identical declarations, and rejects +same-name declarations with different bodies. That cannot express a contribution contract, schema +version, capability requirement, dependency order, declaration or migration ownership, uninstall +data policy, or provenance, and its failure modes are on record: dependency-mode installs reported +success while omitting every plugin table ([#1014][ns-1014]), and model-name clashes broke +authentication installs until namespacing plus a collision guard landed ([PR #1059][ns-1059]). +Removal deletes a directory; it plans no migration at all. + +The operational history says the same thing from a different angle. Each row below cost real +recovery time, and each is a missing architectural concept rather than a missing feature: + +| Incident | Lesson the architecture must encode | +| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| A read-only command killed the resident AppHost | Operations need one lifecycle owner and an operation class | +| A second AppHost mounted live `PGDATA` and corrupted it | Operations must bind an authoritative resolved value, not rebuild it | +| Headless migrate returned success with no artifact | An exit code is not a result; operations need typed postconditions | +| A generated Zod alias hid symbols; its repair broke boot | Generated symbol paths cannot be the framework contract, and validation needs a standards-facing boundary | + +Substituting Prisma 8 for Prisma 7 under this structure would preserve every one of those seams. -### The one story +### Why Prisma 8 changes the calculus -Everything in this architecture is one pipeline of distinct, separately-named values. No stage is -allowed to impersonate another: +Prisma 8 is not Prisma 7 with a new generator. Its source is arranged as a canonical contract plus +separate control and execution planes: PSL or a TypeScript contract builder lowers into a canonical +`contract.json` and a `contract.d.ts`, a small versioned runtime consumes the contract, a +programmatic control client exposes emit/inspect/plan/apply, migrations are content-addressed graph +edges with per-space markers and a ledger, and **contract spaces** make one contributor's +`(contract, migration graph, head ref)` a first-class disjoint tuple ([ADR 212][adr-212]). That +attacks NetScript's pain points at the root: generated executable client source disappears, +source-rewriting and validator repair passes disappear, schema ownership is modelled instead of +inferred from copied files, migrations are planned and verified programmatically, structured results +replace log scraping, and family/target/adapter/driver/extension become distinct axes instead of one +`engine` string +([deep dive](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md)). + +It is also not a safe surface to expose directly, and this RFC treats that as a design input: + +- Prisma 8 RC1 is Early Access and explicitly not recommended for production ([README][rc1-readme]); + its release notes warn that RC respins may break, remove, or rename APIs and the contract format + ([release][rc1-release]). PostgreSQL is the sole database intended for the 8.0 GA target set; + MongoDB is Early Access, SQLite a proof of concept, MySQL later, SQL Server absent + ([scorecard][rc1-scorecard]). +- `@prisma/orm-postgres` — the one package an application installs — publishes 138 top-level export + subpath keys at the pin, spanning adapters, control internals, contract internals, migration + tooling, query ASTs, runtime, target planning, and utilities. A framework that re-exported that + surface would convert upstream Early-Access internals into NetScript public API. +- The integration seam moved materially within six days of the RC tag: the `prisma-next` CLI stopped + being published in favour of a unified CLI ([`3dc98cb`][pn-3dc98cb]), migration and database + commands were routed through the control API, contract JSON Schema became generated, the + PostgreSQL floor dropped from 17 to 15, and aggregate number semantics changed. + +The correct response to a good architecture on a moving surface is to adopt its _semantics_ through +one small allowlisted adapter, and keep NetScript's own vocabulary, artifacts, and operations stable +across the churn. What that unlocks: a developer declares targets and spaces once, authors schema in +native Prisma TypeScript, and receives query types, lifecycle-owned sessions, boundary validators, +migrations with plans and receipts, plugin schema ownership with independent history, structured CI +evidence, and a generated agent surface — without a copied schema, a hand-synchronised type, a +hand-written adapter, a textual repair, or an implicit target choice. -```text -native authored TypeScript contracts + NetScript definitions/contributions - → pure two-phase composition - → canonical ContractArtifacts - → deterministic DatabaseManifest - → generated app-local AppBinding - → runtime sessions + bounded validators - → inspected baseline - → bound ExecutablePlan - → provider apply/ledger - → immutable OperationReceipts - → verify/recovery -``` +## Guide-level explanation + +This section describes the system as if it had shipped. -Read that as a promise about _confusability_: a source definition is not a resolved manifest, a -speculative preview is not an executable plan, an executable plan is not a provider ledger, and a -receipt is not desired state. Most of the operational failures in -[Motivation](#the-recurrent-failure-classes-are-architectural-not-incidental) are what happens when -two of those collapse into one thing. +> **Example status.** Examples importing `@netscript/*` are intended to be executable exactly as +> written once the packages in [§ The package graph](#the-package-graph) exist. Examples importing +> `@prisma/*` show the current RC1 authoring shape; the exact module specifier is an adapter-pinned, +> implementation-time decision (wave W3). Prisma's own public CLI package name changed six days +> after the RC tag, so freezing an upstream specifier into a NetScript contract would be a design +> error. ### Step 1 — author the contract natively -Schema authoring is Prisma's job, and NetScript does not add a vocabulary in front of it. The -current authoring API is model-first: `defineContract(scaffold, callback)`, where the callback -receives a composed helper surface and returns native `types`, `models`, and `enums` `[RC1]` +Schema authoring is Prisma's job and NetScript does not put a vocabulary in front of it. The current +authoring API is model-first: `defineContract(scaffold, callback)`, where the callback receives a +composed helper surface and returns native `types`, `models`, and `enums` (`packages/3-extensions/postgres/src/contract/define-contract.ts:46-121`; the callback overload -preserves its returned literal types at -`packages/2-sql/2-authoring/contract-ts/src/contract-builder.ts:437-462`). +preserves its returned literal types). ```ts -// database/app.contract.ts — provider-native authoring. Specifier pinned in W3. +// database/app.contract.ts — provider-native authoring; specifier pinned in W3 import pgvector from '@prisma/orm-extension-pgvector/pack'; import { defineContract, rel } from '@prisma/orm-postgres/contract-builder'; export const appContract = defineContract( - { extensions: { pgvector }, namespaces: ['app'] }, + { extensions: { pgvector } }, ({ field, model, type }) => { const types = { Embedding: type.pgvector.Vector(1536) } as const; const User = model('User', { - namespace: 'app', fields: { id: field.id.uuidv4String(), email: field.text().unique(), @@ -326,7 +200,6 @@ export const appContract = defineContract( }); const Post = model('Post', { - namespace: 'app', fields: { id: field.id.uuidv4String(), userId: field.uuidString(), @@ -346,23 +219,25 @@ export const appContract = defineContract( ); ``` -`[PROPOSAL]` Three things NetScript will **not** do to that code. It will not recreate the older -fluent `target(...).table(...).column(...)` chain — that API was real at commit `fd88abf4` but was -replaced by the model-first redesign ([PR #261][pn-261], commit [`27ccefc3`][pn-27ccefc3]) and the -legacy implementation was removed ([`e1e5ab2c`][pn-e1e5ab2c], PR #317) `[PRIMARY]`. It will not -introduce a NetScript model DSL that lowers into the same contract. And it will not vendor or -re-export Prisma's builder as though NetScript owned it. +Three things NetScript will **not** do to that code. It will not recreate the older fluent +`target(...).table(...).column(...)` chain — that API was real but was replaced by the model-first +redesign and then removed upstream. It will not introduce a NetScript model DSL that lowers into the +same contract. And it will not vendor or re-export Prisma's builder as though NetScript owned it. ### Step 2 — declare targets and spaces NetScript's own authoring surface adds identity, ownership, capability requirements, policy, and -lifecycle around that native value — and nothing else. This is the baseline API (decision D-07, -"Candidate A"): +lifecycle around that native value — and nothing else. ```ts // database/database.ts -import { defineDatabase, defineDatabaseSpace, defineDatabaseTarget } from '@netscript/database'; -import { fromAspire, fromEnv } from '@netscript/database/connection'; +import { + defineDatabase, + defineDatabaseSpace, + defineDatabaseTarget, + fromAspire, + fromEnv, +} from '@netscript/database'; import { prismaPostgres } from '@netscript/database-prisma-postgres'; import { authSpace } from '@netscript/plugin-auth-core/database'; import { appContract } from './app.contract.ts'; @@ -371,7 +246,6 @@ const primary = defineDatabaseTarget({ id: 'primary', provider: prismaPostgres({ minVersion: 15 }), connection: fromAspire('netscript-db'), - namespaces: { app: 'public', auth: 'auth' }, roles: { writer: {}, 'reader:reporting': { readOnly: true } }, policy: { destructive: 'deny', defaultOwnership: 'managed' }, }); @@ -380,7 +254,6 @@ const analytics = defineDatabaseTarget({ id: 'analytics', // same provider, different database, zero shared state provider: prismaPostgres({ minVersion: 15 }), connection: fromEnv('ANALYTICS_DATABASE_URL'), - namespaces: { warehouse: 'warehouse' }, policy: { destructive: 'plan-only', defaultOwnership: 'adopted' }, }); @@ -389,59 +262,68 @@ export default defineDatabase({ spaces: { app: defineDatabaseSpace({ id: 'app', - ownership: 'app', owner: 'app', version: '1.0.0', - target: 'primary', // type error unless it is a key of `targets` - namespace: 'app', + target: 'primary', contract: appContract, // `typeof appContract` is preserved exactly - dependencies: [], policy: { removal: 'retain' }, }), - auth: authSpace({ target: 'primary', namespace: 'auth' }), + auth: authSpace({ target: 'primary' }), }, }); ``` -`[PROPOSAL]` The important property is what `defineDatabaseSpace` does to `appContract`: nothing. It -stores the value and preserves `typeof appContract` unchanged. NetScript never reinterprets models, -never copies Prisma overloads, and never widens the contract into a generic record. Everything -NetScript adds — `id`, `owner`, `version`, `target`, `namespace`, `dependencies`, capability -requirements, ownership, retention — is plain data that survives a provider replacement. - -The second property is that `target: 'primary'` is checked against `keyof targets`. Misrouting a -space is a type error at the authoring site rather than an install-time surprise. Today's installer -resolves a target through a fallback chain that can end at a **disabled** target `[NS-SRC]`; under -this design there is no fallback chain anywhere in the system. +The important property is what `defineDatabaseSpace` does to `appContract`: nothing. It stores the +value and preserves `typeof appContract` unchanged. NetScript never reinterprets models, never +copies Prisma overloads, and never widens the contract into a generic record. Everything NetScript +adds — `id`, `owner`, `version`, `target`, `dependencies`, capability requirements, ownership, +retention — is plain data that survives a provider replacement. + +The second property is where the target key is checked. `defineDatabaseSpace` is evaluated on its +own and cannot know the keys of a `targets` object that does not exist yet, so it does **not** +promise a type error at its own call site. The check happens where both halves are visible: the +`spaces` parameter of `defineDatabase` requires every space's target to be a key of `targets`, so +`target: 'primry'` is a type error at the `defineDatabase` call. If the type check is bypassed — +JavaScript callers, generated input, `as` casts — composition refuses with +`db.compose.target.unknown` rather than falling back. Today's installer resolves a target through a +fallback chain that can end at a **disabled** target; under this design there is no fallback chain +anywhere in the system. ### Step 3 — the generated binding and typed sessions Composition emits canonical artifacts and one manifest, and the emitter writes a small -application-local binding module. That module is where inferred Prisma types live — never inside a -published NetScript package: +application-local binding module. That module is where inferred provider types live — never inside a +published NetScript package. ```ts // .netscript/database/primary.binding.ts — GENERATED. Do not edit. -// manifest: nsdb1:9f3c… · contract: cs:7ab2… · provider: @prisma/orm-postgres@ +// manifest nsdb1:9f3c… · contract cs:7ab2… · provider @prisma/orm-postgres@ +import type { QueryOf, TransactionQueryOf } from '@netscript/database-prisma-postgres/binding'; +import type { AppBinding, ProcessTargetSession } from '@netscript/database-runtime'; import type { AppContract } from './primary/contract.d.ts'; -import type { QueryOf } from '@netscript/database-prisma-postgres/runtime'; -import type { ProcessTargetSession } from '@netscript/database-runtime'; export type PrimaryQuery = QueryOf; -export type PrimarySession = ProcessTargetSession<'primary', PrimaryQuery>; -export const PRIMARY_MANIFEST_DIGEST = 'nsdb1:9f3c…' as const; -export declare const primaryBinding: AppBinding<'primary', AppContract>; +export type PrimaryTxQuery = TransactionQueryOf; +export type PrimarySession = ProcessTargetSession<'primary', PrimaryQuery, PrimaryTxQuery>; + +export declare const primaryBinding: AppBinding<'primary', PrimaryQuery, PrimaryTxQuery>; +export declare const PRIMARY_MANIFEST_DIGEST: 'nsdb1:9f3c…'; ``` +One generic model is used everywhere: a binding carries +`(target id, query type, transaction query +type)`, and every session type is parameterised by +exactly those three. `QueryOf` and `TransactionQueryOf` are provider-specific helpers exported by +the adapter for generated code only; no provider-neutral package ever names them. + ```ts -// composition-root.ts — hand-written, small, and the only place a target is bound by name +// composition-root.ts — hand-written, and the only place a target is bound by name import { createDatabaseRuntime } from '@netscript/database-runtime'; import { prismaPostgres } from '@netscript/database-prisma-postgres'; -import database from './database/database.ts'; +import { manifest } from './.netscript/database/manifest.ts'; import { primaryBinding, type PrimarySession } from './.netscript/database/primary.binding.ts'; await using runtime = await createDatabaseRuntime({ - definition: database, manifest, providers: [prismaPostgres], targets: ['primary'], @@ -453,11 +335,11 @@ const primary: PrimarySession = runtime.bind(primaryBinding); const accounts: AccountStore = new PrismaAccountStore(primary); ``` -`[PROPOSAL]` Feature code receives `AccountStore` — an application-owned port — not the runtime. -`runtime.bind` is reachable only from declared composition-root and generated files, enforced as an -`arch:check` rule, because a database handle reachable from anywhere is a service locator with a -domain name. NetScript does not generate repositories and does not define what `AccountStore` looks -like; that is application architecture. +Feature code receives `AccountStore` — an application-owned port — not the runtime. `runtime.bind` +is reachable only from declared composition-root and generated files, enforced as an `arch:check` +rule, because a database handle reachable from anywhere is a service locator with a domain name. +NetScript does not generate repositories and does not define what `AccountStore` looks like; that is +application architecture. Inside the session, the query surface is Prisma's own: @@ -473,135 +355,141 @@ await primary.transaction(async (tx) => { }); ``` -There is no NetScript query language wrapping that call, and there never will be. Interactive +There is no NetScript query language wrapping those calls, and there never will be. The transaction +callback receives the binding's `PrimaryTxQuery`, which is inferred from the same contract but is a +**distinct** type: whether an interactive transaction can expose exactly the ordinary query surface +is an upstream behaviour W4 must prove, so the design does not assert it in advance. Interactive transactions exist only on process-scoped sessions; a request-scoped session is `AsyncDisposable`, -carries no cached collaborators, and its type does not expose `transaction`. +caches no collaborators, and its type has no `transaction` member at all. ### Step 4 — validation at trust boundaries -The same contract that types the query surface produces Standard Schema validators, without a +The same contract that types the query surface produces Standard Schema validators, with no generated validator file anywhere in the repository: ```ts import { primaryBinding } from './.netscript/database/primary.binding.ts'; -const users = primaryBinding.space('app').model('User'); +const users = primaryBinding.ref({ space: 'app' }).model('User'); -// Whole-model values, in either public representation. -const runtimeUser = users.value({ representation: 'runtime' }); -const jsonUser = users.value({ representation: 'json' }); - -// Selection-aware results. The schema is for the shape actually selected. -const publicUser = users.result({ select: { id: true, email: true } }, { representation: 'json' }); +const createUser = users.input('create', { representation: 'json' }); +const publicUser = users.output( + { select: { id: true, email: true } }, + { representation: 'json' }, +); +const wholeUser = users.output('model', { representation: 'json' }); ``` -Those values implement `StandardSchemaV1`, so they drop into two independent consumers unchanged: +Two methods and two representations, and the two methods mean materially different things. `input` +produces an **operation input** schema and exists only where the provider or an extension has +contributed exact metadata for that operation. `output` produces a **selected result** schema for +the shape actually requested, or the whole-model shape under the explicit `'model'` form. The only +public representations are `runtime` and `json`; the database-driver wire representation is a third +channel upstream and stays adapter-internal, because calling JSON "wire" would be ambiguous. + +Those values implement `StandardSchemaV1`, so they drop into independent consumers unchanged — and +each boundary uses the schema that actually describes it: ```ts -// 1. an oRPC route contract +// an oRPC route contract: create-input in, selected output out const createAccount = baseContract .route({ method: 'POST', path: '/accounts' }) - .input(users.operation('create', { representation: 'json' })) + .input(createUser) .output(publicUser); -// 2. a Fresh form/action boundary consuming the same value -const parsed = await publicUser['~standard'].validate(payload); +// a Fresh action consuming the same input schema for the same payload shape +const parsed = await createUser['~standard'].validate(formPayload); if (parsed.issues) return renderFieldErrors(parsed.issues); ``` -`[PROPOSAL]` Two honest limits are visible in that snippet, and they are enforced rather than -documented. First, `users.operation('create', …)` succeeds **only** when the provider or an -extension has contributed exact operation metadata for that operation; otherwise it throws -`DB_VALIDATION_UNSUPPORTED` while the schema is being constructed, naming the missing metadata. -Second, invalid user data never throws: it returns Standard Schema issues with a field path, a -stable code, and the contract coordinates. Construction failures and validation failures are -different events with different audiences. +Validating an inbound payload with a query-result schema is a category error, and the API's shape +makes it visible rather than merely discouraged. + +Two honest limits are enforced rather than documented. First, `users.input('create', …)` succeeds +**only** when exact operation metadata exists; otherwise it throws `DB_VALIDATION_UNSUPPORTED` while +the schema is being constructed, naming the missing metadata. The same applies to an `output` +selection whose leaves are computed, raw, aggregated, or otherwise unprovable. Second, invalid user +data never throws: it returns Standard Schema issues with a field path, a stable code, and the +contract coordinates. Construction failures and validation failures are different events with +different audiences. ### Step 5 — a second PostgreSQL database ```ts -// database/warehouse.contract.ts + a second space bound to `analytics` spaces: { app: /* … bound to 'primary' … */, warehouse: defineDatabaseSpace({ id: 'warehouse', - ownership: 'app', owner: 'app', version: '1.0.0', target: 'analytics', - namespace: 'warehouse', contract: warehouseContract, - dependencies: [], policy: { removal: 'retain' }, }), } ``` -`[PROPOSAL]` `primary` and `analytics` are both PostgreSQL and share nothing: separate output roots, -contract artifacts, migration lineages, provider markers, runtime bindings, locks, and receipts. A -relation from a `primary` model to an `analytics` model is refused at composition with +`primary` and `analytics` are both PostgreSQL and share nothing: separate output roots, contract +artifacts, migration lineages, provider markers, runtime bindings, locks, and receipts. A relation +from a `primary` model to an `analytics` model is refused at composition with `db.compose.cross-target-relation`, and no multi-target operation is ever described as atomic. Those -are not limitations of the adapter; they are honest statements about two separate databases. +are not adapter limitations; they are honest statements about two separate databases. ### Step 6 — install a plugin that owns its schema -```ts -// consumer side: one line, and an explicit target -spaces: { - auth: authSpace({ target: 'primary', namespace: 'auth' }); -} -``` +A plugin whose tables outlive an install — auth, workers, sagas — contributes a **full space**: its +own native contract, its own canonical artifact, its own migration lineage and head, versioned +independently of the application. ```ts -// plugins/auth/core: the plugin owns a full space, not a fragment -import { defineDatabaseSpace } from '@netscript/plugin/database'; -import { CAP } from '@netscript/database-contract/capabilities'; +// plugins/auth/core: the plugin owns a space, not a fragment +import { definePluginSpace } from '@netscript/plugin'; +import { CAP, pinnedArtifact } from '@netscript/database-contract'; -export const authSpace = defineDatabaseSpace.factory({ +export const authSpace = definePluginSpace({ id: 'plugin:@netscript/plugin-auth', owner: '@netscript/plugin-auth', version: '0.0.7', - ownership: 'space', contractFormat: '>=1 <2', requires: [CAP.sqlFamily, CAP.nativeUuid], - dependencies: [], - owns: { entries: ['user', 'session', 'account', 'verification'] }, + owns: { tables: ['auth_user', 'auth_session', 'auth_account', 'auth_verification'] }, augmentation: { - grants: [{ entry: 'user', kind: 'add-optional-column', prefix: 'x_' }], + grants: [{ object: 'auth_user', kind: 'add-optional-column', prefix: 'x_' }], denies: ['drop-column', 'change-type', 'add-required-column'], }, - policy: { removal: 'retain', allowed: ['retain'] }, - artifact: pinnedArtifactRef('./artifacts/contract.json'), + policy: { removal: 'retain' }, + artifact: pinnedArtifact('./artifacts/contract.json'), }); ``` -`[PROPOSAL]` The `SpaceId` is the plugin's stable **published plugin identity** -(`plugin:@netscript/plugin-auth`), while the authoring module and generated artifacts ship from that -plugin's `-core` package — identity never follows an install path or a package layout. - -Installing that plugin copies nothing into the application's schema. It writes a **pinned mirror** -under the application's generated root containing the descriptor snapshot, the space's canonical -contract artifact, its lineage, and its provenance. Production apply and verify read the mirror, so -a deployment does not need the plugin's package graph resolvable at all. Two plugins that both -define a `User` table do not collide, because ownership is checked over -`(target, namespace, entryKind, name)` rather than over declaration text, and namespaces make the -separation physical. - -Uninstalling is a planned operation, not a directory delete. The guaranteed behaviour in the first -release is **detach-and-retain**: the runtime binding goes away, the data and the marker stay, a -tombstone records the history, and the objects' ownership is downgraded from `managed` to `adopted` -so that `verify` keeps noticing drift instead of going blind. Archiving and dropping are defined in -this RFC but are `[COND]` capabilities that ship only if provider conformance proves them. +The consumer writes one line — `auth: authSpace({ target: 'primary' })` — and installation copies +nothing into the application's schema. It writes a **pinned mirror** under the application's +generated root containing the descriptor snapshot, the space's canonical contract artifact, its +lineage, and its provenance. Production apply and verify read the mirror, so a deployment does not +need the plugin's package graph resolvable at all, and a mirror digest that disagrees with the +installed package digest is `db.space.skew` rather than a latent divergence. + +Ownership is checked over `(target, namespace, object kind, name)`, not over declaration text. Two +spaces that both want a table named `user` are an ownership conflict naming both spaces — and while +the first adapter supports only one physical namespace per target (see +[§ The withheld namespace capability](#the-withheld-namespace-capability)), physical name collisions +between spaces are refused at composition. A published space therefore names its objects so they +cannot collide; namespaces will relax that requirement when the capability is released, and will +never replace the ownership check. + +Uninstalling is a planned operation, not a directory delete. The guaranteed behaviour is +**detach-and-retain**: the runtime binding goes away, the data and the marker stay, a tombstone +records the history, and ownership is downgraded from `managed` to `adopted` so `verify` keeps +noticing drift instead of going blind. Archiving and dropping are specified in this RFC but ship +only if provider conformance proves them. ### Step 7 — one extension, registered once -`[RC1]` Today a single logical extension such as pgvector must be registered independently in schema -authoring (`/pack`), in control/config (`/control`), and at runtime construction (`/runtime`) -(`examples/prisma-8-demo/prisma/contract.ts:1,18`, `prisma-next.config.ts:1-10`, -`src/prisma-no-emit/context.ts:1-11`). Half-registering it is silent until something fails. +Today a single logical extension such as pgvector must be registered independently in schema +authoring (`/pack`), in control/config (`/control`), and at runtime construction (`/runtime`). +Half-registering it is silent until something fails. ```ts -// one bundle, one identity, four facets export const pgvectorExtension = defineDatabaseExtension({ id: 'pgvector', version: '0.4.0', @@ -613,27 +501,40 @@ export const pgvectorExtension = defineDatabaseExtension({ }); ``` -`[PROPOSAL]` The generated composition root fans that single declaration into every phase. A -missing, mismatched, or half-installed facet is a composition error naming the facet and both -versions. +One bundle, one identity, four facets. The generated composition root fans that single declaration +into every phase, and a missing, mismatched, or half-installed facet is a composition error naming +the facet and both versions. ### Step 8 — the operational journey -Every operation is a typed programmatic call first. The CLI is a projection of the same catalog, and -so are the docs and the agent surface. +Every operation is a typed programmatic call first; the CLI, the docs, and the agent surface are +projections of the same catalog. The API boundary — not a promise in prose — is what proves that +pure work cannot reach a database: ```ts import { createDatabaseControl } from '@netscript/database-control'; -const control = createDatabaseControl({ manifest, providers: [prismaPostgres], connections }); +// Pure control: artifacts and policy only. It has no connection resolver to reach. +const control = createDatabaseControl({ manifest, providers: [prismaPostgres] }); + +const emitted = await control.emit({ targets: ['primary'], runId }); +const advisory = await control.preview({ targets: ['primary'], runId }); + +// Live control: constructed from the pure catalog by supplying explicit live dependencies. +await using live = await control.connect({ connections }); + +const baseline = await live.inspect({ targets: ['primary'], runId }); +const plan = await live.plan({ targets: ['primary'], baseline, policy, runId }); -const emitted = await control.emit({ targets: ['primary'], runId }); // pure: no connection at all -const baseline = await control.inspect({ targets: ['primary'], runId }); // live-read -const plan = await control.plan({ targets: ['primary'], baseline, policy, runId }); -const applied = await control.apply({ plan, policy, runId }); // mutating: lock + revalidate -const verified = await control.verify({ targets: ['primary'], runId }); +const signed = await control.sign(plan); // artifact-side: no database, no lock +const applied = await live.apply({ plan: signed, runId }); +const verified = await live.verify({ targets: ['primary'], runId }); ``` +`emit` is offline because there is no connection in scope, not because an injected resolver happens +to go unused. This is the structural closure of the `DB-GENERATE-ASPIRE-COUPLING` debt entry: Aspire +is a property of a target's connection source, and a pure operation never receives one. + ```console $ netscript db plan --target primary --json { @@ -656,1338 +557,259 @@ $ netscript db plan --target primary --json } ``` -`[PROPOSAL]` Four properties are guaranteed by the shape of that output. Every requested target -appears with a status — there is no silent skip and no implicit "all". `nextAction` is structured -data, so the CLI, CI annotations, and an agent render the same remediation without any of them -parsing prose. Human text is never a contract; gates assert on codes. And the exit code is a -projection of `outcome` (`succeeded` → 0, `refused`/`failed` → non-zero, `partial-success` → -non-zero with a resume token), never the result itself. +Four properties are guaranteed by the shape of that output. Every requested target appears with a +status — there is no silent skip and no implicit "all". `nextAction` is structured data, so the CLI, +CI annotations, and an agent render the same remediation without any of them parsing prose. Human +text is never a contract; gates assert on codes. And the exit code is a projection of `outcome` +(`succeeded` → 0, `refused`/`failed` → non-zero, `partial-success` → non-zero with a resume token), +never the result itself. When something goes wrong, the vocabulary is equally explicit: ```console $ netscript db apply --plan plan:4c19… -error db.plan.stale: plan plan:4c19… was bound to manifest nsdb1:9f3c…, current manifest is nsdb1:12ab… +error db.plan.stale: plan plan:4c19… was bound to manifest nsdb1:9f3c…, current is nsdb1:12ab… target: primary next: netscript db plan --target primary ``` -### What you stop doing - -`[PROPOSAL]` Under this architecture the following stop existing as developer-visible work: copying -a plugin's `.prisma` file into your schema; running a generate pipeline whose later steps repair the -output of its earlier steps; keeping a generated Zod mirror in sync; importing a client by its -generated filesystem path; discovering that a command silently used the first target; starting -Aspire in order to compile; reading terminal logs to find out whether a migration produced an -artifact; and hand-maintaining an agent instruction file that describes commands that have since -changed. - -### What you will be refused - -`[PROPOSAL]` Equally important is what the system declines to do, loudly and early: - -| You try to… | You get | -| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -| Bind a space to a target that does not exist | A **type error** at the authoring site | -| Declare a relation between models in two different targets | `db.compose.cross-target-relation` at composition | -| Let two spaces manage the same object | `db.compose.ownership.conflict`, naming both spaces | -| Use a capability the bound target does not declare | `db.compose.capability.missing`, naming capability, space, and target | -| Apply a speculative preview | Refusal: a preview has no `planId` and `apply` accepts only bound plans | -| Apply a plan after the manifest, baseline, provider set, or policy changed | `db.plan.stale`; after its expiry, `db.plan.expired` | -| Migrate a read replica | Refusal: replicas are roles, and no migration operation can address a role | -| Run a destructive step in production with an interactive "yes" | Refusal: production requires an approved, signed plan | -| Build a validator for an operation with no contributed grammar | `DB_VALIDATION_UNSUPPORTED` while constructing the schema | -| Target Prisma SQLite, MongoDB, MySQL, or SQL Server | `db.target.unsupported` — structured, with no fallback and no Prisma 7 path | -| Use multiple PostgreSQL namespaces with end-to-end typing | The kernel accepts the namespace axis; the adapter withholds the capability claim (see D-37) | -| Drop a plugin's tables on uninstall in v1 | Refusal: `retain` is the guaranteed mode; `archive`/`drop` are conditional on conformance | +### What you stop doing, and what you are refused + +The following stop existing as developer-visible work: copying a plugin's `.prisma` file into your +schema; running a generate pipeline whose later steps repair the output of its earlier steps; +keeping a generated Zod mirror in sync; importing a client by its generated filesystem path; +discovering that a command silently used the first target; starting Aspire in order to compile; +reading logs to learn whether a migration produced an artifact; and hand-maintaining an agent +instruction file describing commands that have since changed. Equally important is what the system +declines to do, loudly and early: + +| You try to… | You get | +| --------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| Bind a space to a target that does not exist | A **type error** at the `defineDatabase` call; `db.compose.target.unknown` if bypassed | +| Declare a relation between models in two different targets | `db.compose.cross-target-relation` at composition | +| Let two spaces manage the same object, or claim the same table name | `db.compose.ownership.conflict` / `db.compose.object-name.conflict`, naming both | +| Use a capability the bound target does not declare | `db.compose.capability.missing`, naming capability, space, and target | +| Request a non-default physical namespace on the first adapter | `db.target.namespace-unsupported` — the capability is withheld, not faked | +| Apply a speculative preview | Refusal: a preview has no `planId` and `apply` accepts only bound plans | +| Apply a plan after the manifest, baseline, pins, or policy changed | `db.plan.stale`; after its expiry, `db.plan.expired` | +| Migrate a read replica | Refusal: replicas are roles, and no control operation can address a role | +| Run a destructive step in production with an interactive "yes" | Refusal: production requires an approved, signed plan | +| Build a validator with no contributed operation or selection metadata | `DB_VALIDATION_UNSUPPORTED` while constructing the schema | +| Target Prisma SQLite, MongoDB, MySQL, or SQL Server | `db.target.unsupported` — structured, with no fallback and no Prisma 7 path | +| Drop a plugin's tables on uninstall | Refusal: `retain` is the guaranteed mode; `archive`/`drop` await conformance | ## Reference-level explanation -### Locked vocabulary - -`[PROPOSAL]` These terms are used with exactly these meanings throughout the implementation program. -Similar-looking values are intentionally distinct, and conflating any two of them is a review -finding. - -| Term | Kind and owner | Locked meaning and invariant | -| ----------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| `DatabaseDefinition` | Public TypeScript value · NetScript | Authored composition of targets, spaces, connection-source references, capability requirements, and policy. Pure; performs no IO. Not a manifest. | -| `NativeContract` | Provider-native authored value | A Prisma `defineContract` result, or another provider's equivalent. NetScript never translates its entity/query vocabulary. | -| `SpaceContribution` | Public declarative record | Owner, version, target binding, dependencies, ownership, capabilities, artifact refs, provenance, and retention policy for one contract space. | -| `ContractArtifact` | Versioned generated data · provider | Canonical provider contract data plus declaration and lineage artifacts, pinned per space and content-addressed. | -| `DatabaseManifest` | Public generated data · NetScript | The deterministic, versioned, content-addressed resolved snapshot. **The durable join point.** A graph exists only as private compiler IR. | -| `AppBinding` | App-local generated TypeScript | Minimal inferred bridge from native contract declarations to sessions, validators, and consumers. Never a published framework export. | -| `TargetRef` / `TargetSession` | Public value/handle · NetScript | Explicit target reference and process/request lifecycle shell. The concrete query type is an application-local generic argument. | -| `SpeculativePreview` | Public structured value · control | Advisory offline or live preview. **Cannot be approved or applied.** | -| `ExecutablePlan` | Public versioned value · control | Expiring plan bound to manifest digest, target/space closure, live baseline, provider pins, policy, environment, and secret references. | -| `ProviderMarker` / `ProviderLedger` | Provider-owned database state | The authoritative record of applied space heads and edges. NetScript reads and cites it and never maintains a second mutable copy. | -| `OperationReceipt` | Immutable append-only evidence | What was attempted, observed, checkpointed, verified, skipped, refused, failed, or left uncertain. Never desired state. | -| `OperationCatalog` | Public machine-readable data | Operation names, classes, request/result/diagnostic schemas, and next actions. CLI, help, docs, and agent surfaces are projections of it. | -| `ValidationIR` | **Internal** bounded algebra · runtime | Provider-decoded value/selection algebra used to produce Standard Schema values. Never a second entity or query model, never public. | - -### Identity model - -`[PROPOSAL]` Identity is declared, never derived. Provider names, engine names, filesystem paths, -configuration aliases, array order, traversal order, and discovery order are **never** identities -and never dependency edges. - -| Identity | Shape | Stability | Notes | -| --------------------- | -------------------------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------------------- | -| `TargetId` | `'primary'`, `'analytics'` | Permanent; renaming is a migration | Author's choice. Owns connection, output root, runtime binding, lineage, locks, and receipts. | -| `RoleRef` | `(TargetId, 'writer' \| 'reader:')` | Derived | A replica is a role of a target, never a target. No migration operation can address a role. | -| `NamespaceRef` | `(TargetId, namespace)` | Permanent | A physical namespace inside one target. A kernel identity axis (see D-37 for the adapter). | -| `SpaceId` | `'app'`, `'plugin:@netscript/plugin-auth'` | Permanent per contributor | One schema owner. | -| `ObjectKey` | `(TargetId, namespace, entryKind, name)` | Derived | The unit of ownership. Exactly one `managed` owner. | -| `ContractSnapshotId` | Content hash of one space's canonical contract | Derived | Addresses one `ContractArtifact`. | -| `ManifestDigest` | Content hash over the canonical manifest | Derived | The determinism anchor. Distinct from any provider hash. | -| `PlanId` | Hash of manifest digest, closure, baseline, pins, policy | Derived | Binds a plan to everything that could invalidate it. | -| `RunId` / `ReceiptId` | Sortable unique ids supplied at the edge | Per execution | Receipts are addressable and resumable. | - -`[NS-SRC]` This directly repairs the observed collapse: -`workspaceDir = join('database', provider.dirName)` made `TargetId` inexpressible, `resolveTarget` -made the default target ambiguous, and the plugin installer's target chain could select a disabled -target. - -### The package graph and archetypes - -`[PROPOSAL]` Six new units and four changed existing units. Each has exactly one doctrine archetype, -per the one-archetype-per-package law -([`.llm/harness/archetypes/README.md`](../.llm/harness/archetypes/README.md)); where two archetypes -genuinely apply, the remedy is two packages, not one package with two shapes. - -```text - @netscript/database-contract (A1, leaf, zero dependencies) - ^ ^ ^ ^ - | | | | - @netscript/database -runtime -control @netscript/plugin - (A4) (A3) (A2) (A4) - ^ ^ ^ - | | | - +----------+------------+ - | - @netscript/database-prisma-postgres (A2, sole Prisma boundary) - ^ - | - @netscript/database-testkit (A6, depends on all; nothing depends on it) - -application composition root -> definition + runtime + control + one provider + generated AppBinding -application/plugin build input -> Prisma public authoring builder (controlled build phase only) -@netscript/aspire -> ConnectionSource SPI only -@netscript/cli -> OperationCatalog + control only -first-party plugin -> @netscript/plugin + @netscript/database-contract only -``` - -Dependency law, each clause mechanically checkable: - -1. `@netscript/database-contract` imports nothing from this family and no provider. Every other - member may depend on it. -2. `@netscript/database` depends on `-contract` only. -3. `-runtime` and `-control` depend on `-contract`, and on `-database` for definition types they - must not redeclare. They never import each other and never import a provider. -4. Provider packages depend on `-contract` (and on `-database`/`-runtime`/`-control` types they - implement) plus upstream. **No framework package depends on a provider.** A provider is a value - supplied at the application composition root. -5. `@netscript/plugin` depends on `-contract` only. This is the rule that keeps a database driver - out of every plugin's dependency graph. -6. The testkit may depend on every public surface; no runtime package may depend on the testkit. -7. **No framework package re-exports Prisma.** Only `@netscript/database-prisma-postgres` may import - Prisma runtime or control modules, through a single `upstream.ts` facade module and an explicit - import allowlist. Application and plugin schema-authoring modules may import Prisma's **public - authoring builder** directly during the controlled build phase; that is provider-native - authoring, not a NetScript re-export, and it may not reach Prisma runtime or control internals. - -#### `@netscript/database-contract` — Archetype 1 (small contract) - -| Property | Value | -| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Owns | Branded identities; `DatabaseManifest`, `ContractArtifact`, `SpaceContribution`, `SpeculativePreview`, `ExecutablePlan`, `OperationReceipt`, `OperationCatalog`, diagnostics; capability and ownership vocabularies; provider pins; the small SPIs shared by more than one consumer. | -| Must not own | Any IO, any lifecycle, any query type, any provider import, any inferred contract generic. | -| Dependencies | None. `@standard-schema/spec` only if a schema type is genuinely needed at this layer. | -| Public vs adapter-local | Everything here is public plain data. No adapter-local concept appears. | -| Runtime permissions | None. The package must be importable with zero Deno permissions. | -| Publication | Public on JSR from W1. | -| Archetype gates | A1 profile of F-1…F-19 per [`archetype-gate-matrix.md`](../.llm/harness/gates/archetype-gate-matrix.md); root export surface within the F-5 symbol cap; `deno publish --dry-run` **without** `--allow-slow-types`; `deno doc --lint` clean. | -| Kill / split criteria | Split into focused subpaths if the root surface approaches the F-5 cap. If any symbol here requires a provider generic, it belongs in the adapter instead. | - -#### `@netscript/database` — Archetype 4 (public DSL/builder) - -| Property | Value | -| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Owns | `defineDatabase`, `defineDatabaseTarget`, `defineDatabaseSpace`, `defineDatabaseExtension`, fragment definition, connection-source references, policy types, and the **pure** compiler that resolves a definition into a `DatabaseManifest` with total `Result` semantics. | -| Must not own | Connections, Aspire, Docker, network, provider imports, migration execution, any live state. | -| Dependencies | `-contract`. | -| Public vs adapter-local | Public: definitions, compiler, diagnostics. Internal: the compiler's graph IR, resolution order, and digest computation. | -| Runtime permissions | Source reads only through an injected `ContractArtifactSource`; the package itself declares no ambient filesystem or network access. | -| Publication | Public on JSR from W2. | -| Archetype gates | A4 profile; `defineX` returns frozen definitions; determinism/property tests; an AP-25 scan proving no IO is reachable from a pure path. | -| Kill / split criteria | If the compiler needs live state to resolve a manifest, the architecture — not the package — is wrong (see [Kill criteria](#kill-and-switch-criteria)). | - -#### `@netscript/database-runtime` — Archetype 3 (runtime/behaviour) - -| Property | Value | -| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Owns | Process and request scope; binding a manifest plus a provider to live connections; connection ownership and graceful close ordering; health/readiness; `AbortSignal` propagation; `{ stop() }` handles; validation cache and interpreter coordination; small session handles. | -| Must not own | Migration orchestration, plan/apply logic, CLI rendering, provider query vocabulary, any Prisma import. | -| Dependencies | `-contract`, `-database` (definition/manifest types). | -| Public vs adapter-local | Public: scope types, lifecycle, health, cancellation, transaction capability markers, validation requests. Adapter-local: `sql`/`orm`/`raw`/`prepare`, driver and pool types. | -| Runtime permissions | Network at bind time only, through a `ConnectionSource`. No filesystem writes. | -| Publication | Public on JSR from W4. | -| Archetype gates | **All F-1…F-19 and the required runtime gates** — A3 makes the runtime column mandatory, which is why runtime is its own package. Leak tests across repeated start/stop and request lifecycles; cancellation and scope tests. | -| Kill / split criteria | If a session type must name a provider type to be useful, the design has failed the app-local binding rule and must be reworked before publication. | - -#### `@netscript/database-control` — Archetype 2 (integration) - -| Property | Value | -| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Owns | The `OperationCatalog` and the programmatic operations classify/compose/emit/preview/inspect/plan/apply/verify/resume/adopt/inventory; provider ports; policy evaluation; lock coordination; receipts; recovery; cross-target saga sequencing; diagnostic translation. | -| Must not own | Provider SQL, ASTs, or migration diff mechanics; terminal text; CLI rendering; any Prisma import. | -| Dependencies | `-contract`, `-database`. | -| Public vs adapter-local | Public: operation classes, plan binding, policy, lock requirements, results, receipts, diagnostics. Adapter-local: upstream control client paths/options, upstream plan and progress representations. | -| Runtime permissions | `pure` operations receive no connection resolver at all. `live-read`/`mutating` receive an explicit connection; `resident` additionally receives an orchestration binding. | -| Publication | Public on JSR from W5. | -| Archetype gates | A2 profile; exhaustive negative/failure-injection matrix; atomic emission test; an offline test proving a `pure` operation cannot reach an orchestrator. | -| Kill / split criteria | If a port grows past four cohesive methods it is an AP-3 god port and must be split (see [Ports](#consumed-ports)). | - -#### `@netscript/database-prisma-postgres` — Archetype 2 (integration) - -| Property | Value | -| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Owns | The **only** framework runtime/control Prisma import boundary; the PostgreSQL capability descriptor; the native-contract/artifact adapter; the control adapter; the runtime factory; the `ValidationIR` decoder; the upstream compatibility allowlist and window. | -| Must not own | Re-exporting Prisma as NetScript's generic API; exposing upstream private or deep-import types in a public declaration; a hand-written low-level driver adapter. | -| Dependencies | `-contract`, `-database`, `-runtime`, `-control`, and exactly one resolved Prisma component set. | -| Public vs adapter-local | Public: capability descriptor, provider value for the composition root, `QueryOf`-style app-binding helpers. Adapter-local: every concrete Prisma contract, control, runtime, codec, and AST type. | -| Runtime permissions | Network and environment through the ports it is given; no ambient filesystem writes outside the artifact publisher. | -| Publication | **Experimental and unpublished until every W3 gate passes.** Independently versioned so an upstream break is a provider patch release, not a framework break. | -| Archetype gates | A2 profile plus runtime gates; import allowlist; exactly one resolved Prisma component set in a packed consumer; Deno import purity; real PostgreSQL conformance; no `--allow-slow-types`. | -| Kill / switch criteria | The provider-specific criteria in [Kill and switch criteria](#kill-and-switch-criteria). Killing this package costs an adapter, not the architecture. | - -#### `@netscript/database-testkit` — Archetype 6 (CLI/tooling) - -| Property | Value | -| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| Owns | Runnable provider **and space** conformance certification against real services, negative fixtures, and machine-readable conformance reports. | -| Must not own | Any application runtime responsibility. | -| Dependencies | All public SPIs. | -| Public vs adapter-local | Public: fixtures, suites, report schema. | -| Runtime permissions | Whatever a certification run needs, declared explicitly and never inherited by consumers. | -| Publication | Public tooling; **conditional on a justified binary.** | -| Archetype gates | A6 profile plus the F-CLI family; deliberately broken fixtures must fail. | -| Kill / split criteria | If implementation proves no runnable binary is needed, fold it into `./testing` subpaths — **decided before W1 and never after public release.** | - -#### Changed existing units - -| Unit | Archetype | Change | Constraint | -| ----------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | -| `@netscript/plugin` | A4 | Adds a `defineDatabaseSpace` contribution seam typed only by `-contract`; **removes** the hollow legacy database/migration contribution abstracts and their contribution-axis members `[NS-SRC]`. | Plain descriptor types only; no runtime/control/provider dependency; breaking-surface accounting required at W7. | -| First-party `plugins/*` | A5 | Thin descriptors plus pinned generated contract/lineage/provenance assets sourced from their `-core` package. | No copied application schema; no convention-bearing database implementation; provider requirements declared. | -| `@netscript/aspire` | A2 | Adds one narrow `ConnectionSource`/provisioning adapter and a resource projection from the manifest. | **Must never be required by a `pure` operation.** This is what closes `DB-GENERATE-ASPIRE-COUPLING`. | -| `@netscript/cli` | A6 | Projects the `OperationCatalog`; hosts the adoption codemod and generated help/agent assets. | No database or provider business logic; no engine switch. | - -#### Doctrine obligations - -`[NS-SRC]` Doctrine currently codifies the model this RFC removes: Archetype 5 states that plugin -database contributions are plain `*.prisma` files referenced from `database/` -([`06-archetypes.md`](../docs/architecture/doctrine/06-archetypes.md)), and neither -`06-archetypes.md` nor -[`10-codebase-verdict-and-handoff.md`](../docs/architecture/doctrine/10-codebase-verdict-and-handoff.md) -contains any of the proposed packages — and the verdict table is what gates a path at all. - -`[PROPOSAL]` Wave W0 therefore amends both files, registers every new unit in the gated denominator, -replaces the plain-fragment rule, and records the archetype-count consequence. This RFC records that -obligation; it does not mutate doctrine before acceptance. No database package inherits the -oRPC-only `--allow-slow-types` carve-out -([`02-public-surface.md`](../docs/architecture/doctrine/02-public-surface.md)) — see -[Type propagation](#end-to-end-type-propagation). - -### The definition layer: exact public signatures - -`[PROPOSAL]` Every signature below is written to satisfy repo-wide `isolatedDeclarations` -`[NS-SRC]`: each exported symbol has an explicit type, and no published declaration names a provider -type. +### Vocabulary and identity + +Similar-looking values are intentionally distinct; conflating any two is a review finding. + +| Term | Meaning and invariant | +| -------------------- | ------------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Authored targets, spaces, connections, capabilities, and policy. Pure; performs no IO. Not a manifest. | +| `NativeContract` | A Prisma `defineContract` result. NetScript never translates its entity or query vocabulary. | +| `AppBinding` | App-local generated bridge from the native contract to sessions and validators. Never a published framework export. | +| `SpeculativePreview` | Advisory preview. **Cannot be approved or applied**, and has no `PlanId`. | + +A `SpaceContribution` carries a space's owner, version, target, dependencies, ownership, +capabilities, artifact refs, and retention; `ValidationIR` is the internal, never-exported +value/selection algebra behind the validators. The control flow keeps five values separate: +`DatabaseDefinition`, `DatabaseManifest`, `ExecutablePlan`, `ProviderMarker`/`ProviderLedger`, and +`OperationReceipt`. A provider-owned `ContractArtifact` is pinned per space and remains distinct +from all five. + +Identity is declared, never derived: provider names, engine names, filesystem paths, config aliases, +and traversal order are never identities and never dependency edges. + +| Identity | Notes | +| --------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `TargetId` | Author-chosen (`'primary'`). Owns connection, output root, runtime binding, lineage, locks, receipts. | +| `RoleRef` | `(TargetId, 'writer' \| 'reader:')`. A replica is a role, never a target, and no control operation addresses one. | +| `NamespaceRef` | `(TargetId, namespace)`. A kernel axis; the first adapter declares only the default namespace. | +| `SpaceId` | `'app'`, `'plugin:@netscript/plugin-auth'`. One schema owner; a published identity, never an install path. | +| `ObjectKey` | `(TargetId, namespace, objectKind, name)`. The unit of ownership; exactly one `managed` owner. | +| `RunId` / `ReceiptId` | Sortable unique ids supplied at the edge, so receipts are addressable and resumable. | + +`ContractSnapshotId`, `ManifestDigest`, and `PlanId` are content hashes, described with the +artifacts they address. + +### The package graph + +Six new units and four changed ones. Each has exactly one doctrine archetype; where two genuinely +apply, the remedy is two packages, not one package with two shapes. + +| Unit | Archetype | Why this boundary exists | +| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------ | +| `@netscript/database-contract` | A1 | Identities, artifacts, diagnostics, vocabularies, SPIs. Zero dependencies and permissions, so everything can depend on it. | +| `@netscript/database` | A4 | `defineX` builders plus the **pure** compiler. Separation from control keeps composition total and IO-free. | +| `@netscript/database-runtime` | A3 | Scope, connection ownership, close ordering, health, cancellation, sessions. A3 makes the runtime gate column mandatory. | +| `@netscript/database-control` | A2 | Operation catalog, plan/apply/verify, policy, locks, receipts, recovery, saga — integration work with failure-injection gates. | +| `@netscript/database-prisma-postgres` | A2 | The **only** framework Prisma import boundary. Independently versioned, so an upstream break is a provider patch. | +| `@netscript/database-testkit` | A6 | Runnable provider **and space** conformance certification with machine-readable reports. | + +Four existing units change. `@netscript/plugin` (A4) gains `definePluginSpace`, typed only by +`-contract`, and loses the hollow legacy database abstracts, keeping a driver out of every plugin's +dependency graph; first-party `plugins/*` (A5) become thin descriptors plus pinned artifacts from +their `-core` package; `@netscript/aspire` (A2) narrows to one `ConnectionSource` adapter and a +resource projection, **never required by a pure operation**; and `@netscript/cli` (A6) projects the +operation catalog and hosts the adoption codemod, with no database logic and no engine switch. + +Dependency law, each clause mechanically checkable. `-contract` imports nothing from this family and +no provider. `-runtime` and `-control` depend on `-contract` and on `-database` for definition types +they must not redeclare, and never import each other or a provider. **No framework package depends +on a provider**: providers are composition-root values, so there is no global registry and no lookup +by string. Nothing depends on the testkit at runtime. And **no framework package re-exports Prisma** +— only the adapter imports Prisma runtime or control modules, while application and plugin authoring +modules import Prisma's public authoring builder directly during the controlled build phase, which +is provider-native authoring, not a re-export. Public subpaths are part of that contract: the +adapter owns exactly two, its root and `/binding`. + +Doctrine currently codifies the model this RFC removes — Archetype 5 makes plugin database +contributions plain `*.prisma` files ([archetypes](../docs/architecture/doctrine/06-archetypes.md)) +— so wave W0 amends it and registers every new unit in the gated denominator. No database package +inherits the oRPC-only `--allow-slow-types` carve-out +([public surface](../docs/architecture/doctrine/02-public-surface.md)). + +### The definition layer and type propagation + +`defineDatabaseSpace` wraps an already-authored native contract: `TContract` is inferred from the +passed value and never widened, re-keyed, or re-interpreted, so `SpaceDefinition['contract']` has +type `TContract`. The target key is checked one level up, where both halves are visible: ```ts // @netscript/database -/** Author-chosen target. `TId` is preserved as a literal by the `const` type parameter. */ -export declare function defineDatabaseTarget( - input: DatabaseTargetInput, -): DatabaseTargetDefinition; - -/** - * Wraps an already-authored native contract. `TContract` is inferred from the passed value and is - * never widened, re-keyed, or re-interpreted: `SpaceDefinition['contract']` has type `TContract`. - */ -export declare function defineDatabaseSpace< - const TId extends string, - const TTarget extends string, - TContract, ->( - input: DatabaseSpaceInput, -): DatabaseSpaceDefinition; - -/** Composes targets and spaces into a frozen definition. Pure; performs no IO. */ +/** Composes targets and spaces into a frozen definition; the target keys are checked here. */ export declare function defineDatabase< const TTargets extends Readonly>>, - const TSpaces extends Readonly>>, + const TSpaces extends Readonly< + Record, unknown>> + >, >( - input: DatabaseInput, + input: { targets: TTargets; spaces: TSpaces; policy?: DatabasePolicy }, ): DatabaseDefinition; -/** One extension bundle with a single verified identity and four phase facets. */ -export declare function defineDatabaseExtension( - input: DatabaseExtensionInput, -): DatabaseExtension; - -/** Pure resolution. Total: it returns diagnostics, it does not throw for authoring mistakes. */ +/** Pure resolution. Total: it returns diagnostics; it does not throw for authoring mistakes. */ export declare function compileDatabase( - definition: DatabaseDefinition< - Readonly>>, - Readonly>> - >, + definition: AnyDatabaseDefinition, sources: ContractArtifactSource, -): Promise; - -export type CompileResult = - | { - readonly ok: true; - readonly manifest: DatabaseManifest; - readonly warnings: readonly Diagnostic[]; - } - | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] }; -``` - -The input types carry the checked relationships: - -```ts -export interface DatabaseSpaceInput { - readonly id: TId; - /** `'app'` composes into the application's contract; `'space'` owns a full contract space. */ - readonly ownership: SpaceOwnershipMode; - /** Stable owner identity: `'app'` or a package identity. Never a path. */ - readonly owner: string; - readonly version: string; - /** Checked against `keyof DatabaseInput['targets']` by `defineDatabase`. */ - readonly target: TTarget; - readonly namespace: string; - /** The exact native value. Stored as-is; never widened. */ - readonly contract: TContract; - readonly requires?: readonly CapabilityId[]; - readonly dependencies?: readonly string[]; - readonly extensions?: readonly DatabaseExtensionRef[]; - readonly augmentation?: AugmentationPolicy; - readonly policy?: SpacePolicy; - readonly provenance?: ProvenanceRef; -} - -export interface DatabaseInput< - TTargets extends Readonly>>, - TSpaces extends Readonly< - Record, unknown>> - >, -> { - readonly targets: TTargets; - readonly spaces: TSpaces; - readonly policy?: DatabasePolicy; -} -``` - -#### Inference law - -`[PROPOSAL]` Four rules, each with a conformance fixture: - -1. **Literal preservation.** `TId`, `TTarget`, and namespace keys stay literal through `const` type - parameters. `keyof definition['targets']` is a union of literals, which is what makes - `target: 'primary'` a type error when `primary` is not declared. -2. **Contract identity.** `typeof definition.spaces.app.contract` is exactly `typeof appContract`. A - fixture asserts the two are mutually assignable and that no property was added, removed, or - widened. -3. **No structural widening.** No NetScript signature accepts a contract as - `Record` or reduces a collection of contracts through `Array.reduce`. A - deliberately-widened fixture must **fail** its type-soundness gate. -4. **No upstream leakage.** No published NetScript declaration names a Prisma type. `TContract` is - an opaque type parameter inside the kernel; only the application-local binding resolves it. - -#### The oRPC precedent, transferred precisely - -`[NS-SRC]` NetScript has already solved a structurally identical problem for oRPC: start from the -real upstream builder (`packages/contracts/src/application/contract-primitives.ts`), apply NetScript -policy around it, let precise types flow from the upstream value into implementation -(`implement()`), consume Standard Schema structurally through `~standard` -(`packages/contracts/src/domain/schema-types.ts`), and fan one const-generic root into several -surfaces (`packages/sdk/src/presets/define-services.ts`), with compile-failure soundness tests -(`plugins/workers/services/src/routers/workers-contract-soundness_test.ts`). - -`[PROPOSAL]` What transfers: the `defineX` → frozen definition → composition-root binding pattern; -versioned contribution with skew detection; Standard Schema as the interop boundary; and per-package -subpath discipline. - -What must **not** transfer, stated so it cannot be reintroduced by analogy: - -| oRPC mechanism | Why it must not transfer | -| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| The `--allow-slow-types` carve-out | The oRPC carve-out is defensible because the inferred contract **is the product** of those packages. A database contract is derived from the _application's_ own schema, so no framework package ever needs to export it. Extending the carve-out converts an app-local inference problem into permanent framework publish debt. | -| Global builder ownership / a `baseContract` equivalent | NetScript must not own the entry point into Prisma's builder; the application imports it directly. | -| Transport concepts (routes, methods, links, error maps) | A database space has no transport. Importing that vocabulary would be the first step of a portable client facade. | -| Upstream re-export from a kernel package | Doctrine AP-14, and the publish constraint above. | -| Cross-package implementation inheritance (a base contract class) | AP-4. Spaces **register** against an extension axis; they do not subclass. | -| Type-erasure workarounds with phantom markers | The erasure that CRUD contracts had to repair is exactly what rule 3 above forbids up front. | - -#### Two contribution modes - -`[PROPOSAL]` The mode decides migration ownership, and it is explicit: - -| Mode | Who owns migrations | Shape | Default for | -| -------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -| `ownership: 'app'` | The application | A fragment function receiving the exact composed native helpers and returning const-preserved native `types`/`models`/`enums`/`entities`. | Application-owned schema, including schema an application chooses to own outright. | -| `ownership: 'space'` | The contributor | A complete native contract, canonical artifact, migration lineage, and head, published as pinned data. | **All plugin-owned tables** (D-38). | - -```ts -// @netscript/database — app-owned fragment, application-local by construction -export interface ContractFragment { - readonly id: TId; - readonly ownership: 'app'; - readonly requires: readonly DatabaseExtensionRef[]; - readonly dependencies: readonly string[]; - readonly build: (helpers: THelpers, deps: FragmentDependencies) => TResult; -} - -export declare function defineContractFragment< - const TId extends string, - THelpers, - TResult, ->(input: ContractFragmentInput): ContractFragment; +): Promise< + | { readonly ok: true; readonly manifest: DatabaseManifest } + | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] } +>; ``` -`[PROPOSAL]` **Publication rule for fragments.** A fragment's `build` parameter necessarily names -the provider's composed helper type. Under `isolatedDeclarations` and the no-slow-types rule, a -**published** package therefore cannot export a fragment: doing so would put a Prisma type in a -published declaration. Fragments are an application-local facility, and this is the concrete reason -plugin-owned tables default to full spaces whose published surface is plain data plus pinned -artifacts. A published package exporting a fragment is a gate failure, not a style preference. - -#### Two-phase composition - -`[RC1]` Extension packs are part of the scaffold and determine the composed helper object's static -and runtime shape **before** Prisma invokes the callback -(`packages/2-sql/2-authoring/contract-ts/src/composed-authoring-helpers.ts:43-102,132-154`, with -collision checks at `:214-233,272-306`). `[INFERENCE]` "Register an extension while a fragment is -executing" therefore cannot be sound. - -`[PROPOSAL]` Composition is two-phase, and the phases are named operations: - -```text -Phase 1 — collect (pure, no helpers exist yet) - contribution manifests · required extension bundles · dependency edges - · target/namespace requirements · ownership · capability requirements - │ resolve extension identity/version, detect facet mismatch, - │ topologically order fragments, refuse cycles and overlaps - ▼ -Phase 2 — build (pure, helpers now fully composed) - one scaffold → exact composed native helper surface - → invoke app-owned fragments in dependency order with explicit calls - → canonicalize → atomically publish ContractArtifacts -``` - -The generated composition root is explicit and const-preserving: +Four inference rules, each with a conformance fixture: literal preservation through `const` type +parameters; **contract identity**, so `typeof definition.spaces.app.contract` is exactly +`typeof appContract`; **no structural widening**, so no signature accepts a contract as +`Record` and a deliberately widened fixture must _fail_ its soundness gate; and +**no upstream leakage**, so no published NetScript declaration names a Prisma type. + +Two tracks run in parallel and must never be merged. The **inference track** is `typeof contract`: +provider generics, valid only inside the application's own compilation, terminating in generated +app-local files. The **identity track** is `ContractSnapshotId` and `ManifestDigest`: plain data +used by plans, markers, receipts, validators, and agents, crossing every boundary freely. Conflating +them is how a system ends up unable to answer "is this database consistent with this build?" without +type-checking, so every generated binding records the manifest digest and provider pin and startup +refuses a mismatch with `db.artifact.stale`. + +**The one deliberate soundness seam.** `runtime.bind` returns a session whose query types come from +generated code, and the kernel cannot prove the runtime value the provider constructs matches them, +because those type parameters are erased. Three gates make the seam safe: the binding is _generated_ +from the same manifest and provider declaration artifact that produced the session (hand-writing one +is an `arch:check` failure); it carries the digests the provider verifies at bind time; and a +conformance case asserts that a mismatched binding fails at bind rather than at first query. The +alternative — publishing a contract-typed value from a framework package — `isolatedDeclarations` +and the no-slow-types rule forbid outright. + +### Contribution modes + +The mode decides migration ownership, and it is explicit. + +| Mode | Owns migrations | Used for | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------- | +| Space (`definePluginSpace`, `defineDatabaseSpace`) — a complete native contract, canonical artifact, migration lineage, and head, published as pinned data | The contributor | **All persistent plugin-owned tables**, and application schema | +| App-local fragment (`defineContractFragment`) — a function receiving the exact composed native helpers and returning const-preserved `types`/`models`/`enums` | The application | Application schema an app chooses to split across modules | + +A fragment's `build` parameter necessarily names the provider's composed helper type, so under +`isolatedDeclarations` a **published** package cannot export one without putting a Prisma type in a +published declaration. Fragments are therefore application-local and a published fragment is a gate +failure — which is why persistent plugin tables default to full spaces, whose published surface is +plain data plus pinned artifacts. If W3 proves a mechanism that preserves exact inference across a +published boundary, a published fragment mode may be added then. + +Composition is two-phase because extension packs determine the composed helper object's shape +_before_ Prisma invokes the callback, so "register an extension while a fragment is executing" +cannot be sound. Phase 1 collects contribution manifests, extension bundles, dependency edges, and +capability requirements, resolving extension identity and version, detecting facet mismatch, +ordering fragments, and refusing cycles; phase 2 builds one scaffold into the exact composed helper +surface, invokes fragments in dependency order, canonicalizes, and atomically publishes the +artifacts. Both phases are pure, and the generated root is explicit calls and spreads in dependency +order — never a runtime registry, never `Array.reduce`, never a value typed +`Record`: ```ts // .netscript/database/primary.contract-root.ts — GENERATED. Do not edit. export const primaryContract = defineContract(scaffold, (h) => { - const auth = authFragment.build(h, {}); - const app = appFragment.build(h, { auth }); + const billing = billingFragment.build(h, {}); + const app = appFragment.build(h, { billing }); return { - types: { ...auth.types, ...app.types }, - models: { ...auth.models, ...app.models }, - enums: { ...auth.enums, ...app.enums }, + types: { ...billing.types, ...app.types }, + models: { ...billing.models, ...app.models }, + enums: { ...billing.enums, ...app.enums }, } as const; }); ``` -`[PROPOSAL]` Explicit calls and object spreads, in a deterministic order the generator computes from -declared dependencies. Never a runtime registry, never `Array.reduce`, never a value typed -`Record`. Fragment order must not change the canonical contract digest; that is a -conformance case, not an aspiration. - -#### The optional policy factory, and its kill criterion - -`[PROPOSAL]` A convenience factory that pre-applies NetScript policy (naming strategy, default -control policy, a fixed extension set) and then forwards Prisma's exact composed helpers **may** -exist: - -```ts -const postgresContract = createPrismaContractFactory({ - naming: { tables: 'snake_case', columns: 'snake_case' }, - defaultControlPolicy: 'managed', - extensions: [pgvectorExtension], -}); - -export const appContract = postgresContract.define((h) => {/* `h` is Prisma's exact surface */}); -``` - -**Kill criterion, stated directly:** this factory is deleted if implementing it requires copying -Prisma's overloads, importing a private or deep upstream path, re-declaring its generic model/type -machinery, inserting a cast, or widening inference in any measurable way. In that case Candidate A — -native `defineContract` plus a thin `defineDatabaseSpace` — is the complete public authoring API, -and it is already sufficient. The factory is a convenience, never a foundation, and no other part of -this design depends on it. - -### End-to-end type propagation - -```text -native defineContract(...) value ← application/plugin build input - │ typeof contract (editor + compiler inference; never crosses a published boundary) - ▼ -defineDatabaseSpace({ contract, ownership, target, … }) ← NetScript identity/policy, inference intact - ▼ -DatabaseDefinition ──compileDatabase──▶ DatabaseManifest + pinned contract.json / contract.d.ts - │ │ - │ └─▶ bounded ValidationIR ─▶ StandardSchemaV1 - ▼ -generated app-local AppBinding<'primary', AppContract> - ├─▶ ProcessTargetSession<'primary', QueryOf> (queries, transactions) - ├─▶ RequestTargetSession<'primary', QueryOf> (disposable, no cached collaborators) - ├─▶ model value / operation input / selection-aware result schemas - ├─▶ oRPC procedures, Fresh routes and actions, form adapters, SSR payload checks - └─▶ application-owned stores bound at the composition root -``` - -`[PROPOSAL]` Two tracks run in parallel and must never be merged: - -- **The inference track** is `typeof contract`. It may contain complex provider generics, it is only - valid inside the application's own compilation, and it terminates in generated app-local files. -- **The identity track** is `ContractSnapshotId` and `ManifestDigest`. It is plain data used by - plans, markers, receipts, validators, caches, agents, and stale-artifact checks, and it crosses - every boundary freely. - -Conflating them is how a system ends up unable to answer "is this database consistent with this -build?" without type-checking. Every generated binding records the manifest digest and the exact -provider pin; runtime startup refuses a binding/manifest/contract mismatch with `db.artifact.stale` -or `db.contract.version-mismatch` and a structured `nextAction`. - -#### The acceptance condition - -`[PROPOSAL]` This is the condition on which both primary axes of this RFC stand or fall, and it is -binding on implementation: - -> Accept the native integration only if it preserves Prisma's exact contract inference without -> private imports, copied overloads, casts, or declaration widening, and accept contract-derived -> validation only where the canonical contract plus contributed codec, operation, and selection -> metadata can produce sound fail-closed Standard Schema validators; otherwise narrow or kill the -> affected layer rather than pretending parity. - -Stronger, operationally: each clause has a conformance fixture and a named owner wave. A failure of -the first clause kills the affected authoring convenience and, in the limit, the Prisma adapter — it -never authorises a cast. A failure of the second clause narrows the validation algebra to the subset -that remains sound — it never authorises a pass-through or an `unknown`. - -#### The one deliberate soundness seam - -`[PROPOSAL]` Honesty requires naming the single place where the kernel cannot check what it is -given. `runtime.bind` returns a session whose query type is supplied by generated code: - -```ts -export interface DatabaseRuntime { - bind( - binding: AppBinding, - ): ProcessTargetSession; - bindRequest( - binding: AppBinding, - ): RequestTargetSession; - health(signal: AbortSignal): Promise; - stop(): Promise; -} -``` - -The kernel cannot prove that the runtime value the provider constructs matches `TQuery`, because -`TQuery` is erased. Three mitigations make that seam safe, and all three are gates rather than -conventions: the `AppBinding` value is **generated** from the same manifest and provider declaration -artifact that produced the session (hand-writing one is an `arch:check` failure); the binding -carries `ManifestDigest` and `ContractSnapshotId`, which the provider verifies at bind time and -refuses on mismatch; and a conformance case asserts that a deliberately mismatched binding fails at -bind rather than at first query. This seam is preferred over the alternative — publishing a -contract-typed value from a framework package — which `isolatedDeclarations` and the slow-types rule -forbid outright. - -### Artifacts and public contracts - -#### Identities - -```ts -// @netscript/database-contract -export type TargetId = string & { readonly __targetId: unique symbol }; -export type SpaceId = string & { readonly __spaceId: unique symbol }; -export type CapabilityId = string & { readonly __capability: unique symbol }; -export type ContractSnapshotId = string & { readonly __snapshot: unique symbol }; -export type ManifestDigest = string & { readonly __manifestDigest: unique symbol }; -export type PlanId = string & { readonly __planId: unique symbol }; -export type RunId = string & { readonly __runId: unique symbol }; -export type ReceiptId = string & { readonly __receiptId: unique symbol }; - -export interface RoleRef { - readonly target: TargetId; - readonly role: 'writer' | `reader:${string}`; -} -export interface NamespaceRef { - readonly target: TargetId; - readonly namespace: string; -} -export interface ObjectKey { - readonly target: TargetId; - readonly namespace: string; - /** Open provider/pack entry kind: `table`, `native_enum`, `value_set`, a pack-contributed kind. */ - readonly entryKind: string; - readonly name: string; -} - -export type OwnershipPolicy = 'managed' | 'adopted' | 'external' | 'ignored'; -export type SpaceOwnershipMode = 'app' | 'space'; -export type RuntimeScope = 'process' | 'request'; -export type ValidationRepresentation = 'runtime' | 'json'; -export type OperationClass = 'pure' | 'live-read' | 'mutating' | 'resident'; -``` - -#### The artifact contract, at a glance - -| Artifact | Producer | Consumers | Authority for | Identity / digest inputs | Encoding & persistence | Atomicity | Provenance & redaction | Stale / mismatch behaviour | -| ----------------------------------- | -------------------------------- | ----------------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------ | ------------------------------------------------------------------ | -------------------------------------------------------------- | -| `DatabaseDefinition` | Author (TypeScript) | Compiler only | Intent | None — it is source | TypeScript in the repository | n/a | Git history | Compile diagnostics | -| `ContractArtifact` | Provider emit (controlled build) | Compiler, control, runtime, validation, mirrors | Provider contract content | `ContractSnapshotId` = hash of the canonicalized provider contract | Canonical JSON + declaration file, per space, per output root | Staged then atomically committed | Emitting provider pin, source space, emit run id | `db.artifact.stale`; refuse to plan or bind | -| `DatabaseManifest` | `compileDatabase` (pure) | Control, runtime, CLI, agents, CI | Resolved desired composition | `ManifestDigest` = hash of the full canonical manifest incl. provider pins and snapshot ids | Canonical JSON, format-versioned, in the generated root | Written by the same atomic publisher | Definition source refs, contributor provenance | Any consumer with a different digest refuses and names both | -| `AppBinding` | Emitter (generated TS) | Application composition root | App-local inferred types | Records `ManifestDigest` + `ContractSnapshotId` | Generated TypeScript, never hand-edited, never text-patched | Replaced atomically with its artifact root | Header comment carries digests and provider pin | Bind-time refusal `db.artifact.stale` | -| `SpeculativePreview` | Control (`pure`/`live-read`) | Humans, CI comments | Nothing | Advisory id only; **never** a `PlanId` | JSON result; not persisted as an apply input | n/a | Records whether a baseline was read | Cannot be applied — there is no code path that accepts it | -| `ExecutablePlan` | Control (`live-read`) | Policy, approval, `apply` | What will be executed | `PlanId` = hash(manifest digest, closure, baseline fingerprint, provider pins, policy) | JSON, versioned, storable, reviewable | Immutable once created | Environment, policy decision, signature, **secret refs only** | `db.plan.stale`, `db.plan.expired`, `db.plan.revoked` | -| `ProviderMarker` / `ProviderLedger` | Provider (in the database) | Control (read), verify, resume | **Applied state — the authority** | Provider-owned; NetScript records it as opaque versioned attributes | Provider tables in the target database | Provider's own transactional coupling | Provider version, space, head | Divergence from the manifest is drift, classified by ownership | -| `OperationReceipt` | Control (`ReceiptSink`) | Humans, CI, resume, audit | Evidence of attempts and observations | `ReceiptId` per run, checkpoints ordered | Append-only atomic JSON per checkpoint | Each checkpoint written atomically | Tool versions, environment, run id; **redacted** connection values | Never used as desired state; a resume reads it plus live state | -| `OperationCatalog` | Control (generated data) | CLI, docs, agents, tests | The operation surface | Versioned with the control package | Checked-in deterministic TypeScript constants | Regenerated and diffed in CI | Package version | A freshness gate fails the build on drift | - -#### `DatabaseManifest` - -```ts -export interface DatabaseManifest { - /** Public format version. Evolution policy is a W1 decision; the field is not optional. */ - readonly formatVersion: 1; - readonly digest: ManifestDigest; - readonly targets: readonly ManifestTarget[]; - readonly spaces: readonly ManifestSpace[]; - /** Topological order over spaces, recorded so review sees it rather than inferring it. */ - readonly spaceOrder: readonly SpaceId[]; - readonly providerPins: readonly ProviderPin[]; - readonly policy: DatabasePolicy; - readonly provenance: ManifestProvenance; -} - -export interface ManifestTarget { - readonly id: TargetId; - readonly family: string; - readonly provider: ProviderPin; - readonly namespaces: readonly string[]; - readonly roles: readonly RoleRef[]; - readonly capabilities: readonly CapabilityId[]; - /** Reference only. A resolved connection value never participates in manifest identity. */ - readonly connection: ConnectionSourceRef; - readonly outputRoot: string; - readonly migrationRoot: string; - readonly policy: TargetPolicy; -} - -export interface ManifestSpace { - readonly id: SpaceId; - readonly owner: string; - readonly version: string; - readonly mode: SpaceOwnershipMode; - readonly target: TargetId; - readonly namespace: string; - readonly ownership: OwnershipPolicy; - readonly requires: readonly CapabilityId[]; - readonly dependencies: readonly SpaceId[]; - readonly owns: readonly ObjectKey[]; - readonly augmentation: AugmentationPolicy; - readonly snapshot: ContractSnapshotId; - readonly extensions: readonly DatabaseExtensionPin[]; - readonly removal: RemovalPolicy; - readonly provenance: ProvenanceRef; -} -``` - -| Field | Contract | -| ------------------------ | ----------------------------------------------------------------------------------------------------------------- | -| `formatVersion` | Public. A consumer that does not understand the version refuses rather than best-effort parsing. | -| `digest` | Hash over the full canonical manifest **including** provider pins and contract snapshot ids. Not a provider hash. | -| `targets[].connection` | A **reference**. Environment values, URLs, and secrets never enter the manifest or its digest. | -| `targets[].capabilities` | Static declared data from the provider descriptor. Never negotiated at runtime. | -| `spaces[].owns` | The complete owned `ObjectKey` set. Exactly one `managed` owner per key across the whole manifest. | -| `spaces[].dependencies` | Declared semantic edges. Array position, file path, and discovery order are never edges. | -| `spaceOrder` | The topological order actually used by planning and apply, recorded for review. | -| `provenance` | Which definition sources, contributor packages, mirrors, and emit runs produced this snapshot. | - -#### `ExecutablePlan` and `SpeculativePreview` - -```ts -export interface SpeculativePreview { - readonly kind: 'speculative'; - readonly manifestDigest: ManifestDigest; - readonly targets: readonly TargetId[]; - readonly summary: readonly PreviewStep[]; - /** True when a live baseline was read; still not applicable either way. */ - readonly baselineObserved: boolean; - readonly diagnostics: readonly Diagnostic[]; -} - -export interface ExecutablePlan { - readonly kind: 'executable'; - readonly planId: PlanId; - readonly manifestDigest: ManifestDigest; - readonly target: TargetId; - readonly spaceClosure: readonly SpaceId[]; - readonly baseline: BaselineFingerprint; - readonly providerPins: readonly ProviderPin[]; - readonly steps: readonly PlanStep[]; - readonly destructive: readonly DestructiveOperation[]; - readonly capabilitiesUsed: readonly CapabilityId[]; - readonly policy: PolicyDecision; - readonly environment: string; - /** References only; a plan never contains a secret value. */ - readonly secretRefs: readonly SecretRef[]; - readonly createdAt: string; - readonly expiresAt: string; - readonly signature?: PlanSignature; -} - -export interface DestructiveOperation { - readonly kind: - | 'drop-entry' - | 'drop-column' - | 'narrow-type' - | 'add-required-without-default' - | 'unique-over-existing-data' - | 'namespace-drop'; - readonly object: ObjectKey; - readonly dataLossRisk: 'certain' | 'possible' | 'none'; - /** Present only when the provider proved it. Absence is not evidence of safety. */ - readonly observedRowCount?: number; -} -``` - -| Field | Contract | -| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | -| `kind` | The type-level separation of preview and plan. `apply` accepts `'executable'` only; there is no coercion. | -| `planId` | Binds manifest digest, space closure, baseline fingerprint, provider pins, and policy. Any change invalidates the plan. | -| `baseline` | A fingerprint of the inspected live state and provider ledger at planning time. Re-checked under the lock before mutation. | -| `secretRefs` | References only, so a plan is safe to commit, attach to a PR, and archive. | -| `expiresAt` | Mandatory. Applying after it yields `db.plan.expired`. | -| `signature` | Required in production. Algorithm and key custody are a pre-implementation decision (D-35, W5/W10); the field and the policy port are locked now. | - -#### `OperationReceipt` - -```ts -export interface OperationReceipt { - readonly receiptId: ReceiptId; - readonly runId: RunId; - readonly operation: OperationName; - readonly manifestDigest: ManifestDigest; - readonly startedAt: string; - readonly finishedAt?: string; - readonly phases: readonly ReceiptPhase[]; - readonly artifacts: readonly ArtifactAssertion[]; - readonly environment: string; - readonly toolVersions: readonly ProviderPin[]; - readonly outcome: ReceiptOutcome; -} - -export type ReceiptOutcome = - | 'succeeded' - | 'refused' - | 'skipped' - | 'failed' - | 'partial-success' - | 'cleanup-required' - | 'outcome-unknown' - | 'cancelled'; - -/** A postcondition the operation proved — not a log line claiming it. */ -export interface ArtifactAssertion { - readonly path: string; - readonly expected: 'created' | 'unchanged' | 'replaced' | 'absent'; - readonly digestBefore?: string; - readonly digestAfter?: string; -} -``` - -`[PROPOSAL]` A receipt is append-only evidence. It is never consulted as desired state, never -compared against instead of the provider ledger, and never repaired. `cleanup-required` and -`outcome-unknown` are separate outcomes from `failed` precisely because "the ledger was repaired" -must never be read as "the database was repaired" — a lesson Flyway's `repair` documents explicitly -([Flyway repair][flyway-repair]) `[PRIMARY]`. - -#### `SpaceContribution` - -```ts -export interface SpaceContribution { - readonly id: SpaceId; - readonly owner: string; - readonly version: string; - readonly contractFormat: string; - readonly mode: SpaceOwnershipMode; - readonly requires: readonly CapabilityId[]; - readonly dependencies: readonly SpaceId[]; - readonly owns: readonly ObjectKeyPattern[]; - readonly augmentation: AugmentationPolicy; - readonly artifact: ContractArtifactRef; - readonly extensions: readonly DatabaseExtensionPin[]; - readonly validation: readonly ValidationContributionRef[]; - readonly executablePhases: readonly ExecutablePhase[]; - readonly removal: RemovalPolicy; - readonly provenance: ProvenanceRef; -} -``` - -| Field | Contract | -| ------------------ | ---------------------------------------------------------------------------------------------------------------------- | -| `id` / `owner` | Logical and stable. **Never** derived from an install path, a package directory, or include order. | -| `contractFormat` | The provider contract-format range the contribution supports. A mismatch is a refusal, not a warning. | -| `owns` | What this space owns, and therefore what no other space may manage. | -| `augmentation` | Owner-granted permission for others to extend its objects, with an explicit deny list. Absence of a grant is a denial. | -| `executablePhases` | Which build phases may execute this contributor's code. Composition consumes declarative records by default. | -| `removal` | Default `retain`. `archive`/`drop` appear only when the provider capability and conformance evidence exist. | -| `provenance` | Package identity, resolved version, integrity hash, and mirror digest — the inputs to skew detection. | - -#### Diagnostics and results - -```ts -export type DiagnosticCode = - | 'db.compose.ownership.conflict' - | 'db.compose.capability.missing' - | 'db.compose.dependency.cycle' - | 'db.compose.cross-target-relation' - | 'db.compose.extension.facet-mismatch' - | 'db.space.skew' - | 'db.space.dependent-installed' - | 'db.contract.version-mismatch' - | 'db.artifact.stale' - | 'db.plan.stale' - | 'db.plan.expired' - | 'db.plan.revoked' - | 'db.apply.destructive.refused' - | 'db.apply.lock.held' - | 'db.apply.outcome-unknown' - | 'db.verify.drift' - | 'db.target.unsupported' - | 'db.target.ambiguous' - | 'db.validation.unsupported'; - -export interface Diagnostic { - readonly code: DiagnosticCode; - readonly severity: 'error' | 'warning' | 'info'; - readonly subject: ObjectKey | TargetId | SpaceId; - /** Human text. Never parsed by anything — no gate may assert on it. */ - readonly message: string; - /** Structured remediation: an operation name plus arguments, not prose. */ - readonly nextAction: NextAction; -} - -export interface OperationResult { - readonly runId: RunId; - readonly outcome: 'succeeded' | 'partial-success' | 'failed' | 'refused'; - readonly perTarget: readonly TargetOutcome[]; - readonly diagnostics: readonly Diagnostic[]; - readonly receipt: OperationReceipt; - readonly resume?: ResumeToken; -} - -export interface TargetOutcome { - readonly target: TargetId; - readonly status: 'succeeded' | 'failed' | 'skipped' | 'not-attempted' | 'refused'; - /** Why a target was skipped or not attempted. There are no silent omissions. */ - readonly reason?: DiagnosticCode; - readonly spaces: readonly SpaceOutcome[]; - readonly value?: TOutcome; -} -``` - -`[NS-SRC]` This replaces an operation surface whose entire result type is an exit code -(`packages/cli/src/kernel/adapters/database/operation-runner.ts:85`), under which `--db all` is -sequential and fail-fast with no per-target record and `studio` executes only the first resolved -target (`:90-105,116-117`). `[INFERENCE]` That is why receipts cannot be an additive later slice: -the return type makes structured reporting impossible, so the operation contract is the thing being -replaced. - -#### Consumed ports - -`[PROPOSAL]` Each port stays at three or four cohesive methods — AP-3 names "a port with every -operation the backend can perform" as the integration-package failure mode, and the current -`DatabaseAdapter` (client lifecycle plus health plus status plus raw query plus -`setClient`) is that anti-pattern in shipped code `[NS-SRC]`. - -```ts -export interface ContractArtifactSource { - read(space: SpaceId, snapshot: ContractSnapshotId): Promise; - resolveHead(space: SpaceId): Promise; - list(): Promise; -} - -/** Atomic publication: stage into a temporary root, then commit or abort. Never patch in place. */ -export interface ArtifactPublisher { - stage(root: ArtifactRootRef): Promise; - commit(staged: StagedRoot): Promise; - abort(staged: StagedRoot): Promise; -} - -export interface ProviderRuntimeFactory { - capabilities(): ProviderCapabilityDescriptor; - createProcessRuntime( - input: RuntimeBindInput, - signal: AbortSignal, - ): Promise; - createRequestRuntime( - input: RuntimeBindInput, - signal: AbortSignal, - ): Promise; -} - -export interface ProviderControl { - emit(request: EmitRequest, signal: AbortSignal): Promise; - /** Returns the live baseline **including** provider marker/ledger state. */ - inspect(request: InspectRequest, signal: AbortSignal): Promise; - plan(request: ProviderPlanRequest, signal: AbortSignal): Promise; - apply(plan: BoundProviderPlan, signal: AbortSignal): Promise; -} - -export interface ConnectionSource { - describe(target: TargetId): ConnectionDescription; - resolve(target: TargetId, role: RoleRef, signal: AbortSignal): Promise; -} - -export interface MigrationLock { - acquire(scope: LockScope, owner: LockOwner, ttlMs: number): Promise; - renew(lease: LockLease): Promise; - release(lease: LockLease): Promise; - inspect(scope: LockScope): Promise; -} - -export interface ReceiptSink { - open(run: ReceiptOpenInput): Promise; - checkpoint(handle: ReceiptHandle, phase: ReceiptPhase): Promise; - close(handle: ReceiptHandle, outcome: ReceiptOutcome): Promise; -} -``` - -`[PROPOSAL]` Deterministic-testing and production-approval seams exist only where they are -justified: a `Clock` (`now()`), an `IdSource` (`newId(kind)`), and a `SignaturePolicy` (`sign(plan)` -/ `verify(plan, signature)`). **Verify is not a provider method.** It is a NetScript operation -composed from `ProviderControl.inspect` plus a manifest comparison plus ownership classification — -which is what keeps drift semantics identical across providers. - -Provider registries are immutable composition-root **data**. There is no global registry, no -`register()` call, and no lookup by string from arbitrary code: - -```ts -const control = createDatabaseControl({ manifest, providers: [prismaPostgres], connections }); -``` - -### The runtime layer - -```ts -// @netscript/database-runtime -export interface TargetRef { - readonly target: TId; - readonly manifestDigest: ManifestDigest; -} - -export interface TargetSession { - readonly target: TId; - readonly scope: TScope; - readonly snapshot: ContractSnapshotId; - /** The provider's own surface, supplied by generated app-local code. NetScript never names it. */ - readonly query: TQuery; - health(signal: AbortSignal): Promise; -} - -export interface ProcessTargetSession - extends TargetSession { - transaction(run: (tx: TQuery) => Promise, options?: TransactionOptions): Promise; -} - -/** Request scope is disposable and caches no collaborators. It has no `transaction`. */ -export interface RequestTargetSession - extends TargetSession, AsyncDisposable {} - -export declare function createDatabaseRuntime( - options: DatabaseRuntimeOptions, -): Promise; -``` - -`[PROPOSAL]` Scope is a **type**, not a configuration flag. `[RC1]` This mirrors an upstream design -precedent rather than inventing one: the Prisma serverless facade deliberately creates an -async-disposable runtime per request and omits the closure-cached `orm`, `runtime()`, and -`transaction()` surfaces that would be unsafe in that lifecycle. Making the asymmetry a type -prevents the class of bug where a closure caches a per-request handle. - -Runtime lifecycle: - -```mermaid -stateDiagram-v2 - [*] --> created: createDatabaseRuntime(manifest, providers, targets, scope) - created --> binding: resolve ConnectionSource per target/role - binding --> refused: digest/snapshot mismatch, capability gap, unsupported target - binding --> ready: provider runtime constructed, health probe passes - ready --> degraded: health probe fails - degraded --> ready: health probe recovers - ready --> stopping: stop() or AbortSignal - degraded --> stopping: stop() or AbortSignal - stopping --> stopped: sessions drained, connections closed in reverse bind order - refused --> [*] - stopped --> [*] -``` - -`[PROPOSAL]` Guarantees that must be proven by A3 runtime gates: - -- **One lifecycle owner.** The runtime constructs the provider runtime; there is no `setClient` and - no circular assembly in which the caller builds a driver, builds a client, and hands it back - `[NS-SRC]`. -- **Close ordering.** Sessions drain before connections close, and connections close in reverse bind - order. Repeated start/stop and request lifecycles are leak-free under test. -- **Cancellation.** Every long-running call takes an `AbortSignal`; cancellation is observable in - the receipt and never leaves an orphaned connection. -- **Readers cannot migrate.** A `reader:*` role produces a read-only session type and is not - addressable by any control operation. -- **Redaction.** Connection strings, passwords, and secret references never appear in diagnostics, - receipts, or logs. This is a conformance case, not a convention. -- **Bind refuses mismatch.** `ManifestDigest` and `ContractSnapshotId` are checked at bind time. - -### The runtime validation subsystem - -This is the second primary axis of the RFC, and it is the one where an attractive inference is -easiest to over-sell. The design is deliberately bounded and fails closed. - -#### What the evidence actually supports - -`[EXCHANGE]` The owner/maintainer exchange (public `#prisma-next` channel, 2026-03-05/06) proposed -deriving Standard Schema validation from Prisma's machine-readable contract, and the maintainer's -reply sharpened it toward deriving validators **at runtime** rather than through a generation step. -This is exploratory direction. It is not an upstream roadmap commitment and it is not evidence that -a stable public validation API ships in Prisma 8. - -`[RC1]` The pinned source both supports and limits that direction: - -- The contract carries a bounded runtime value algebra: scalar codec references, value objects, - unions, mandatory nullability, `many`, `dict`, and value-set references - (`packages/1-framework/0-foundation/contract/src/domain-types.ts:5-39`), with relations and - cross-space coordinates explicit (`:41-75`, - `packages/1-framework/0-foundation/contract/src/cross-reference.ts:5-14`). SQL storage adds native - type, codec parameters/references, defaults, nullability, and value sets - (`packages/2-sql/1-core/contract/src/ir/storage-column.ts:15-25`). -- **The complete operation/result type universe is not runtime data.** SQL field, operation, codec, - and aggregate type maps are installed under an optional phantom key - (`packages/2-sql/1-core/contract/src/types.ts:90-139,207-215`) and are emitted into - `contract.d.ts` (`packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts:179-221`). - They are erased at runtime. This is the decisive evidence against "the contract alone has all of - Prisma's type semantics." -- Plans retain enough for **direct** projections and not more: SQL projections carry alias, - expression, and an optional codec reference, and the source states outright that the codec is - absent for computed expressions, subqueries, and raw aliases - (`packages/2-sql/4-lanes/relational-core/src/ast/types.ts:1480-1505`). -- Prisma's existing Standard Schema usage validates **codec parameters**, not model values - (`packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts:27-54`); a - `Codec` itself carries conversions only (`shared/codec.ts:16-32,34-51`). -- There are **three** representations, not two: application runtime, database-driver wire, and - target JSON (`shared/codec.ts:16-30,44-51`). -- Contract spaces are separate identities: the migration aggregate exposes app and extension - contracts per space rather than merging them - (`packages/1-framework/3-tooling/migration/src/aggregate/types.ts:32-79,81-123`), and cross-space - domain checks are deferred to aggregate deployment - (`packages/1-framework/0-foundation/contract/src/validate-domain.ts:140-147`). -- No existing section hash is a sufficient validator identity: hashing separately covers storage, - execution, and capability profile - (`packages/1-framework/0-foundation/contract/src/hashing.ts:74-106`) while domain, roots, and - extensions can change independently. - -`[POST-RC]` The post-RC object adds a generated contract JSON Schema that the source labels -lossy/advisory with ArkType authoritative -(`packages/2-sql/2-authoring/contract-ts/src/data-contract-json-schema.ts:10-15,31-38,68-110`). That -improves validation of `contract.json`. It adds no model-data schemas, no codec value predicates, -and no universal result-shape metadata. It corroborates direction; it does not change RC1 -capability. - -#### The public API - -```ts -// app-local, via the generated AppBinding -const users = binding.space('app').model('User'); - -/** Whole-model value in a public representation. */ -users.value(options: { representation: ValidationRepresentation }): StandardSchemaV1; - -/** Operation input. Available only with contributed exact operation metadata. */ -users.operation(op: string, options: { representation: ValidationRepresentation }): StandardSchemaV1; - -/** Selection-aware result. Available only when every leaf is fully known. */ -users.result(selection: SelectionInput, options: { representation: ValidationRepresentation }): StandardSchemaV1; -``` - -`[PROPOSAL]` The only public representations are `runtime` and `json`. **Driver wire is -adapter-internal** and is never a public option, because calling JSON "wire" is ambiguous against a -codec layer that genuinely has three channels. - -#### Three schema classes with different guarantees - -| Class | Guarantee | Refusal boundary | -| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -| Model value | Validate a named model, value object, or enum in `runtime` or `json` with an explicit object-presence policy. | Never implies that database uniqueness, foreign keys, or check constraints are locally satisfied. | -| Operation input | Available **only** when the provider or an extension contributes runtime operation grammar and a typed binding for that exact operation. | Prisma create/update/filter/nested-write/polymorphic semantics absent from runtime contract data fail at construction. | -| Result | Validate a whole model, or a fully-known direct projection whose alias, codec, nullability, and representation are all known. | Computed, subquery, raw, aggregate, include, and unknown leaves require an explicitly contributed result schema or fail at construction. | - -Hiding those three behind one `input()` method would hide materially different guarantees, so the -API does not. - -#### The supported `ValidationIR` algebra - -`[PROPOSAL]` `ValidationIR` is **internal** — it is never exported, and it is never a second entity -or query model. It is closed per interpreter ABI and supports exactly: - -- registered scalar codec leaves; -- nullability; -- `many` lists and `dict` values; -- value objects; -- value sets, domain enums, and resolvable provider native enums (membership resolved from the value - set or native-enum entity, **not** inferred from a codec id — `[RC1]` the PostgreSQL native-enum - codec is a string pass-through that does not carry members, - `packages/3-targets/3-targets/postgres/src/core/codecs.ts:374-388`); -- unions only where branch identity is deterministically discriminable; -- model fields and relations whose cross-space references resolve through an integrity-verified - aggregate; -- whole-model values with an explicit presence policy; and -- direct-column selection/returning projections with complete alias, codec, nullability, and - representation metadata. - -#### Mandatory fail-closed cases - -`[PROPOSAL]` Schema **construction** throws a deterministic `DB_VALIDATION_UNSUPPORTED` with stable -coordinates (target, space, snapshot, model, operation or selection, representation, and the missing -metadata) for at least: - -1. an unknown codec, or a codec with no representation-specific value schema; -2. an unknown provider pack entity kind; -3. a corrupt or missing aggregate space, head, hash, cross-space reference, or value set; -4. ambiguous unions, or model variants/discriminators that cannot be resolved for the request; -5. Prisma operation grammar that is absent from runtime data: filters, relation traversal, nested - writes, polymorphic narrowing, and default/presence semantics with no contributor; -6. computed, subquery, raw, aggregate, include, or unknown result leaves with no explicit result - shape; -7. opaque SQL index or check expressions, which are information-losing rather than validatable; -8. database-state constraints — uniqueness, foreign keys, exclusion — which are not local value - validation and are never advertised as such; -9. asynchronous or non-deterministic value predicates where the requested Standard Schema mode - promises synchronous validation. - -No unsupported case becomes `unknown`, a pass-through, or a warning. `[RC1]` This is deliberately -**stricter** than the provider's own decoders, which accept missing codecs and pass through unknown -shapes (`packages/2-sql/5-runtime/src/codecs/decoding.ts:164-186,198-223`) — a decoder's job is -decoding, and a validator's job is refusing. - -Invalid **values** behave differently and never throw: they return Standard Schema issues carrying a -stable code, target, space, contract digest, model/operation/selection, representation, field path, -expected class, and observed value class. - -#### Codec contributions - -`[PROPOSAL]` A built-in or custom codec is supported only when its contributor supplies a -deterministic value schema for **every** advertised public representation: - -```ts -defineValidationCodec({ - codecId: 'pgvector.vector@1', - representations: { - runtime: vectorRuntimeSchema, // StandardSchemaV1 - json: vectorJsonSchema, // StandardSchemaV1 - }, -}); -``` - -`[RC1]` Encode/decode functions are **not** validation: a custom codec requires conversion functions -and a JSON round trip but no value predicate (`mongo-codec/src/codecs.ts:23-42,44-82`), and -conversion success is compatible with arbitrary coercion. The ArkType JSON extension documents the -consequence directly — its no-emit type may be `unknown` and encoding does not validate, so an -invalid write can reach the database and fail only on `RETURNING` decode -(`packages/3-extensions/arktype-json/README.md:7-17,40,74-87`) `[RC1]`. A codec without -representation-specific schemas is unsupported and fails closed. - -#### Cache identity - -`[PROPOSAL]` A derived validator's cache key is: - -```text -digest(canonical full-contract snapshot) - + contract schema version - + spaceId - + target / family - + operation name or normalized selection shape - + representation - + interpreter ABI version - + codec/pack contributor id and version - + execution identity where defaults matter -``` - -`[RC1]` Storage hash alone is insufficient: domain, roots, and extension semantics can change -without storage changing, and the plan metadata carries only storage and profile hashes -(`contract/src/types.ts:223-232`). Invalidation is by construction — the key contains contract -identity, so a contract change produces new keys rather than a stale hit. Plugin spaces cache under -their own `SpaceId`, so upgrading one plugin does not evict the application's schemas. - -#### Trust-boundary policy - -`[PROPOSAL]` - -- Input/model-value validation is **mandatory** at external mutation boundaries wherever a supported - schema exists. -- Output validation is **mandatory** for declared API/RPC responses, SSR/hydration payloads, and - external-service messages, and **opt-in** for internal query loops. Validating every row on every - read is a real cost, and a design that validates everything by default gets disabled wholesale, - which is worse than one that validates precisely at boundaries. -- An input failure is a client error with field paths. An output failure is a server/contract error - **and** a drift signal, because the database and the contract have diverged. -- Contract-space plugin fields participate automatically once aggregate integrity is verified. -- oRPC, Fresh, forms, and SSR consume the same Standard Schema values. Adapters must not regenerate - library-specific mirrors, and NetScript does not re-export Zod, Valibot, ArkType, or Prisma's - contract-document validators. - -#### Optional ahead-of-time projection - -`[COND]` An AOT projection **may** ship, under three conditions that keep it an optimisation rather -than a second source of truth: it is content-addressed, target-scoped, atomically replaced, and -never patched; it passes the identical semantic corpus as the runtime interpreter across successes, -issue paths, representation behaviour, unsupported-construction failures, contract-space resolution, -and cache invalidation; and no code path requires it. If mechanical equivalence cannot be -demonstrated, AOT is a mirror validator wearing a different name and is dropped (D-25, D-43). -Nothing in this RFC claims AOT validation exists. - -#### What is explicitly not claimed - -`[PROPOSAL]` NetScript does **not** claim full Prisma create/update/filter/nested-write/result -parity derived from contract data. Supporting all of it would mean rebuilding Prisma's operation -type system in the validator, which is the "second ORM" failure this architecture exists to avoid. -The supported subset is stated above; everything outside it fails closed. - -### The control plane - -#### The operation catalog is the source; everything else is a projection - -```ts -export interface OperationCatalog { - readonly version: string; - readonly operations: readonly OperationDescriptor[]; - readonly diagnostics: readonly DiagnosticDescriptor[]; -} - -export interface OperationDescriptor { - readonly name: OperationName; - readonly class: OperationClass; - readonly summary: string; - readonly request: StandardSchemaV1; - readonly result: StandardSchemaV1; - /** Serialisable projection used to generate CLI flags, help, docs, and agent instructions. */ - readonly jsonSchema: JsonSchemaDocument; - readonly diagnostics: readonly DiagnosticCode[]; - readonly nextActions: readonly NextActionDescriptor[]; - readonly examples: readonly ExecutableExample[]; -} - -export type OperationName = - | 'classify' - | 'compose' - | 'emit' - | 'inventory' - | 'preview' - | 'inspect' - | 'plan' - | 'sign' - | 'apply' - | 'verify' - | 'resume' - | 'seed' - | 'adopt' - | 'studio'; -``` - -`[PROPOSAL]` CLI commands, `--help`, generated documentation, and agent instructions are generated -projections of this catalog. A freshness gate regenerates them and fails on any diff, and a -conformance case executes every `ExecutableExample`. `[PRIMARY]` The upstream project's own RC-era -agent skill demonstrates why: it shipped with legacy internal import paths and obsolete error-code -vocabulary, and its references contradict the runtime surface on whether raw SQL and prepared -statements are available. Hand-maintained agent instructions decay within a release; generated ones -cannot. - -#### Operation classes - -| Class | Examples | May resolve | Lock | Receipt | -| ----------- | ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | -------- | ---------------- | -| `pure` | `classify`, `compose`, `emit`, `inventory`, offline `preview` | Source/artifact readers and the atomic publisher only. **Never** a connection, Aspire, Docker, secrets, or the network. | No | Artifact receipt | -| `live-read` | `inspect`, live `preview`, `plan`, `verify` | An explicit target connection | No | Yes | -| `mutating` | `apply`, `seed`, `sign`, `adopt` baseline, space retirement | An explicit target connection, provider lock/fencing, and a bound plan where applicable | Yes | Yes | -| `resident` | `studio`, and any operation whose connection exists only inside a running host | An explicit target and an orchestration binding | Advisory | Yes | - -`[PROPOSAL]` **Aspire is a property of a target's connection source, never an operation class.** The -structural closure of `DB-GENERATE-ASPIRE-COUPLING` is that a `pure` operation is never given a -connection resolver at all, so it cannot reach an orchestrator even by mistake. - -#### Composition - -```mermaid -stateDiagram-v2 - [*] --> authored - authored --> resolving: compileDatabase(definition, sources) - resolving --> refused: diagnostics (total Result, never a throw) - resolving --> resolved: manifest + warnings - refused --> [*] - resolved --> [*] -``` - -Resolution is pure and total. It validates declared identities; output/migration root isolation; -provider pins; target binding of every space; capability subsets; ownership disjointness; dependency -closure and acyclicity; cross-target reference refusal; contribution provenance and contract format; -extension-bundle facet identity; and mirror integrity. Composition invariants, each with a -diagnostic and a negative test: - -| ID | Invariant | Diagnostic | -| --- | --------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -| V-1 | Every space binds to exactly one target. A space never spans databases. | type error / `db.target.ambiguous` | -| V-2 | Every `ObjectKey` has exactly one `managed` owner; a managed owner overlapping an `external` declaration fails. | `db.compose.ownership.conflict` | -| V-3 | Cross-space references are legal only inside one target and only along a declared dependency edge. | `db.compose.cross-target-relation` | -| V-4 | The space dependency graph is acyclic; its topological order is recorded in the manifest. | `db.compose.dependency.cycle` | -| V-5 | Every space's required capabilities are a subset of its target's declared capabilities. | `db.compose.capability.missing` | -| V-6 | No two targets share an output root, a migration root, or a runtime binding key. | `db.compose.ownership.conflict` | -| V-7 | `ManifestDigest` is a pure function of definition + resolved snapshots + provider pins. Nothing environmental participates. | determinism gate | -| V-8 | Every emitted artifact root records the digest that produced it; a mismatch is detectable without a database. | `db.artifact.stale` | -| V-9 | Every extension facet shares one identity and version. | `db.compose.extension.facet-mismatch` | - -#### Preview, plan, policy, approval - -```mermaid -stateDiagram-v2 - [*] --> resolved - resolved --> speculative: preview (pure or live-read) - speculative --> not_applicable: no planId is ever issued - resolved --> inspected: inspect baseline (live-read) - inspected --> planned: ExecutablePlan created and bound - planned --> policy_refused: destructive policy / environment refusal - planned --> policy_allowed: policy decision recorded in the plan - policy_allowed --> approved: signature required by environment - policy_allowed --> ready: signature not required - approved --> ready - ready --> expired: expiresAt passed - ready --> stale: manifest, baseline, pins, or policy changed - ready --> revoked: explicitly revoked - ready --> apply - policy_refused --> [*] - not_applicable --> [*] -``` - -`[PROPOSAL]` A speculative preview is **never** accepted by `apply`; the type has no `planId` and no -code path coerces it. Consent is not an interactive prompt: in CI and production the policy must be -`allow-with-approval` **and** the plan must carry a signature. An interactive "yes" is a development -affordance only. - -#### Apply, checkpoints, and recovery +Fragment order must not change the canonical contract digest; that is a conformance case. Plugin +spaces never appear in this root — they are separate contracts with separate artifacts, applied on +their own lineage. + +### Artifacts and their authority + +Six separately named values, with disjoint responsibilities. Nothing else is authoritative for these +questions. + +| Value or artifact | Authoritative for | Identity and failure behaviour | +| ----------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Authored intent | Source value only; it is compiled and never consumed by runtime, control, apply, or verify | +| `ContractArtifact` | Provider contract content | `ContractSnapshotId`; `db.artifact.stale` refuses to plan or bind | +| `DatabaseManifest` | Resolved desired composition | `ManifestDigest` over the canonical manifest including pins; a consumer with a different digest refuses and names both | +| `ExecutablePlan` | What will be executed | `PlanId`; `db.plan.stale`, `db.plan.expired`, `db.plan.revoked` | +| `ProviderMarker` / `ProviderLedger` | **Applied state** | Provider-owned, recorded as opaque versioned attributes; divergence from the manifest is drift, classified by ownership | +| `OperationReceipt` | Evidence of attempts and observations | `ReceiptId` per run with ordered checkpoints; never desired state, and a resume reads it _plus_ live state | + +Manifests and plans carry secret _references_ only, so a plan is safe to commit and archive. +Artifact roots are staged and atomically committed, never patched in place, so an interrupted job +leaves a fully old or fully new root. Receipt outcomes are `succeeded`, `refused`, `skipped`, +`failed`, `partial-success`, `cleanup-required`, `outcome-unknown`, and `cancelled`; the last three +are separate from `failed` precisely because "the ledger was repaired" must never read as "the +database was repaired" ([Flyway repair][flyway-repair]). + +Composition is pure and total. Beyond the refusals listed in the guide it validates provider pins, +contribution provenance and contract format, mirror integrity, and output/migration root isolation, +refuses dependency cycles and extension facet skew, and is covered by a determinism gate asserting +that `ManifestDigest` is a pure function of the definition, its snapshots, and its pins. Every +invariant has a diagnostic and a negative test. + +### Operations, plans, and recovery + +Operations are classified before they run, and the class determines what an operation may resolve. + +| Class | Examples | May resolve | Lock | +| ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | +| `pure` | `compose`, `emit`, `inventory`, offline `preview`, `sign` | Artifact readers, the atomic publisher, the signature policy. **Never** a connection, Aspire, Docker, secrets, or the network. | No | +| `live-read` | `inspect`, live `preview`, `plan`, `verify` | An explicit target connection | No | +| `mutating` | `apply`, `seed`, adoption baseline, space retirement | An explicit connection, provider lock/fencing, and a bound plan | Yes | +| `resident` | `studio`, and anything whose connection lives inside a host | An explicit target and an orchestration binding | Advisory | + +`sign` is deliberately `pure`: signing binds a policy decision to an artifact, so it neither takes a +connection nor acquires a migration lock. A plan is created only from an inspected baseline and +binds everything that could invalidate it — manifest digest, closure, baseline fingerprint, provider +pins, policy decision, environment, secret references, ordered steps, the destructive-operation list +with its data-loss risk, and a mandatory expiry. In CI and production the policy must be +`allow-with-approval` **and** the plan must carry a signature. ```mermaid stateDiagram-v2 @@ -1997,370 +819,303 @@ stateDiagram-v2 acquiring_lock --> locked locked --> revalidating: re-check manifest, baseline, pins, policy, expiry revalidating --> refused: db.plan.stale / db.plan.expired / db.plan.revoked - revalidating --> started - started --> applying - applying --> applying: atomic receipt checkpoint per irreversible step or provider transaction group + revalidating --> applying + applying --> applying: atomic receipt checkpoint per irreversible step or transaction group applying --> outcome_unknown: transport lost after dispatch applying --> failed applying --> cancelled: AbortSignal applying --> applied applied --> verifying - verifying --> verified - verified --> succeeded - failed --> cleanup_required: non-transactional step left objects behind + verifying --> succeeded + failed --> cleanup_required: a non-transactional step left objects behind outcome_unknown --> inspect_before_resume cleanup_required --> inspect_before_resume cancelled --> inspect_before_resume - inspect_before_resume --> revalidating: resume, only for steps whose outcome is known and unfinished + inspect_before_resume --> revalidating: resume only steps whose outcome is known and unfinished succeeded --> [*] refused --> [*] ``` -`[PROPOSAL]` The rules that give this diagram teeth: - -- **Loss of transport after dispatch produces `outcome-unknown`, never `failed`.** `[PRIMARY]` This - is Pulumi's documented `pending operation` lesson: the engine cannot know whether the provider - completed the work, and recovery requires inspecting the provider before acting - ([interrupted updates][pulumi-interrupted]). -- **Resume always inspects live state and the provider ledger first**, revalidates the plan - bindings, and then continues only operations whose outcome is known and unfinished. It never - blindly replays non-idempotent DDL or a data transform. -- **Checkpoint granularity is per irreversible operation or provider transaction group**, never only - at end-of-target. -- **A ledger repair is not a database repair.** `cleanup-required` is a distinct outcome for exactly - the case Flyway documents, where a failed non-transactional migration leaves user objects that no - ledger operation removes `[PRIMARY]`. -- **Lock scope is `(target, physical database)`**, with an owner identity, a nonce, fencing evidence - where the provider supports it, a TTL, a heartbeat, documented stale-lock inspection, and explicit - safe force-unlock preconditions. A provider that cannot supply a certified lock is **refused for - concurrent-safe apply** rather than silently racing. Native advisory versus fenced-row mechanism - is certified per provider (D-42). -- **No shared stateful runner across targets.** Each target has its own runner instance, so the - unsupported configuration is unrepresentable rather than documented. - -#### Multi-target execution is a saga +The rules that give that diagram teeth. **Loss of transport after dispatch produces +`outcome-unknown`, never `failed`** — the engine cannot know whether the provider completed the work +([interrupted updates][pulumi-interrupted]). **Resume always inspects live state and the provider +ledger first**, revalidates the plan bindings, and continues only operations whose outcome is known +and unfinished, never blindly replaying non-idempotent DDL or a data transform; because resume is a +_lookup_, the receipt store supports append plus lookup by `RunId`, `ReceiptId`, and resume token, +and an implementation may split those into source and sink roles. **Checkpoints are per irreversible +operation or provider transaction group.** **Lock scope is `(target, physical database)`**, with +owner identity, nonce, fencing evidence where the provider supports it, TTL, heartbeat, and explicit +force-unlock preconditions; a provider without a certified lock is refused for concurrent-safe +apply, and each target gets its own runner. + +**Multi-target execution is a saga, never a transaction.** Selection expands to a dependency +closure, records every omission with a reason code, orders targets deterministically, and gives each +its own runner, lock, and receipt. A mix of successful and failed, refused, or unknown targets +yields `partial-success` with a resume token; if no target succeeds, the aggregate outcome is +failed, refused, or outcome-unknown according to the per-target results. The run ends with a +whole-manifest verification; selective execution is recovery machinery, not the normal deployment +path ([resource targeting][tf-targeting]). The programmatic catalog is the source, and CLI commands, +documentation, and agent instructions are projections of it: a freshness gate fails on any diff, and +a conformance case executes every documented example. -```mermaid -stateDiagram-v2 - [*] --> selection: explicit target/space set - selection --> closure: expand dependency closure, record every omission with a reason code - closure --> ordering: deterministic topological order - ordering --> per_target: separate runner, separate lock, separate receipt per target - per_target --> all_succeeded - per_target --> partial_success: at least one target failed, refused, or is outcome-unknown - partial_success --> resume_after_inspection - all_succeeded --> whole_manifest_verify - resume_after_inspection --> whole_manifest_verify - whole_manifest_verify --> [*] -``` - -`[PROPOSAL]` **Cross-target apply is never atomic and is never described as atomic.** There is no -cross-database transaction and no automatic rollback claim. Selective target/space execution is -recovery machinery, not the normal deployment path: it requires dependency closure, records omitted -work with reason codes, and mandates a subsequent whole-manifest verification. `[PRIMARY]` This is -Terraform's own documented position on `-target` — explicitly exceptional recovery, not a routine -selector ([resource targeting][tf-targeting]). - -### Targets, providers, namespaces, ownership, and spaces - -| Case | Kernel | Prisma 8 PostgreSQL adapter, first release | -| ---------------------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------------------- | -| Two PostgreSQL databases | Named targets, fully isolated | **Required.** Distinct artifacts, runtime, ledger, locks, receipts. | -| Multiple namespaces in one target | First-class kernel identity axis | **Withheld** `[COND]` — see D-37 below. | -| Writer / read replicas | Roles on one target | Conditional runtime capability; a reader is read-only and never migrates. | -| App plus independently versioned plugin spaces | Required | **Required.** Independent artifacts, heads, dependency order, package-free apply/verify. | -| `managed` / `adopted` / `external` / `ignored` | Required | **Required.** Ownership-aware plan, verify, and drift. | -| Process / request scope | Distinct types and lifecycles | **Required.** | -| Prisma SQLite / MongoDB / MySQL / SQL Server | Provider and family axes remain open | **Explicitly unsupported.** `db.target.unsupported`; no fallback, no Prisma 7 path. | -| Cross-target relation or transaction | Not representable | Structured composition refusal. | -| Provider-specific query features | Capability-visible | Native provider surface, app-local. No portable wrapper. | - -#### The namespace capability is withheld, and why - -`[RC1]` Prisma's runtime lowering honours per-model namespaces, but the authoring type maps do not: -the source states that the authoring path lumps every model under the default storage namespace and -leaves additional namespace maps empty -(`packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691`; independently re-verified -during PLAN-EVAL cycle 2). `[POST-RC]` The audited post-RC object retains the limitation. - -`[PROPOSAL]` `NamespaceRef` therefore stays a first-class **kernel** identity axis — manifests, -ownership, object keys, and plans all carry it — while the adapter **must not advertise a -multi-namespace capability** until exact type/runtime parity passes with **no casts, no private -imports, and no flattening workaround**. If upstream never fixes it, the kernel carries an unused -axis and nothing else needs rework. This is a withheld claim, not a blocked architecture (D-37). - -#### Ownership - -| Policy | Planned | Mutated | Verified | Typical source | -| ---------- | ------- | ------- | ------------------------------------- | -------------------------------------------------------------------- | -| `managed` | Yes | Yes | Fully | An app or plugin space that owns the objects. | -| `adopted` | Yes | Yes | Against an explicit reviewed baseline | Objects brought under management by `db adopt` or retention. | -| `external` | No | No | Against declared assertions only | Hosted platforms and upstream extensions that own their own objects. | -| `ignored` | No | No | No | Deliberate exclusion with an auditable recorded reason. | - -`[PROPOSAL]` Rules: exactly one `managed` owner per `ObjectKey`; identical declaration text from two -contributors is still an ownership conflict; namespaces prevent lexical collisions but never replace -ownership checks; cross-space references require the same target plus a declared dependency edge; -and augmentation is an **owner-granted closed permission**, never an implicit merge — the absence of -a grant is a denial, and unsupported modification either asks the owner or becomes an app-owned -migration. `[PRIMARY]` The `external` policy is not an edge case: a hosted database whose tables -evolve outside the framework's knowledge is the normal shape of a managed service, and upstream has -a recorded instance of a pinned extension contract diverging from an externally-evolving database -and failing verification ([prisma#29896][pn-29896]). - -#### Plugin and contract-space lifecycle - -```mermaid -stateDiagram-v2 - [*] --> declared - declared --> installed: capabilities, dependencies, ownership, provenance validated; mirror pinned - declared --> install_refused: overlap, missing/cyclic dependency, contract-format skew, unsupported capability - installed --> upgraded: lineage path from the pinned head resolves - upgraded --> installed - installed --> upgrade_refused: ownership widening, incompatible contract format, capability regression, ambiguous branch - upgrade_refused --> installed - installed --> skew_refused: installed package digest != mirror digest (db.space.skew) - skew_refused --> installed: resynchronise the mirror - installed --> detached: runtime/package binding removed - detached --> retained: data, marker, tombstone, and ownership history preserved; managed downgraded to adopted - detached --> detach_refused: a dependent space is still installed - retained --> archived: conditional on provider capability and conformance - retained --> dropped: conditional on destructive policy, approval, dependent closure, verified lineage - retained --> [*] -``` +### The runtime layer -| Transition | Guarantee in the first release | Status | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | -| Install | Validate target, capabilities, dependencies, ownership, provenance; pin the mirror; recompile; produce a plan. | Required | -| Upgrade | Require a lineage path from the pinned head; pin the new mirror; plan each changed edge. | Required | -| Skew | Refuse mutation whenever package, mirror, manifest, and marker identities disagree; the diagnostic names every identity. | Required | -| Detach + retain | **The only guaranteed removal.** Data, marker, mirror tombstone, and ownership history are preserved; ownership is downgraded `managed → adopted` so verify keeps seeing the objects. | Required | -| Archive | Planned relocation to a quarantine namespace with a restoration path. | `[COND]` — conditional on provider capability + conformance (D-46) | -| Drop | Destructive plan with explicit policy/approval, dependent closure, and verified lineage. | `[COND]` — never a directory delete, never claimed for v1 | +A session carries its `TargetId`, scope, contract snapshot id, a `health(signal)` method, and the +provider's own `query` surface supplied by generated app-local code. Scope is a **type**, not a +configuration flag: `ProcessTargetSession` adds `transaction(run, options?)`, +while `RequestTargetSession` is `AsyncDisposable`, caches no collaborators, and has no +`transaction` member at all. That mirrors an upstream precedent — Prisma's serverless facade creates +an async-disposable runtime per request and omits the closure-cached `orm`, `runtime()`, and +`transaction()` surfaces that would be unsafe in that lifecycle — and it prevents the class of bug +where a closure caches a per-request handle. + +Guarantees the A3 gates must prove: **one lifecycle owner** — the runtime constructs the provider +runtime, with no `setClient` and no circular assembly; **close ordering** — sessions drain before +connections close, connections close in reverse bind order, leak-free across repeated start/stop and +request lifecycles; **cancellation** — every long-running call takes an `AbortSignal`, observable in +the receipt and never leaving an orphaned connection; **readers cannot migrate** — a `reader:*` role +produces a read-only session type no control operation can address; **redaction** — connection +strings, passwords, and secret references never appear in diagnostics, receipts, or logs; and **bind +refuses mismatch**. + +Ports stay at three or four cohesive methods, because AP-3 names "a port with every operation the +backend can perform" as the integration-package failure mode and today's `DatabaseAdapter` +is that anti-pattern in shipped code. **Verify is not a provider method**: it is composed from +`ProviderControl.inspect` plus a manifest comparison plus ownership classification, which is what +keeps drift semantics identical across providers. -`[PRIMARY]` Contract spaces solve ownership and history; they do not solve removal — extension -removal is not a supported RC capability. This RFC defines the whole vocabulary now and guarantees -only `retain`. +### The runtime validation subsystem -#### The pinned mirror +This is the second primary axis of the RFC, and the one where an attractive inference is easiest to +over-sell. The +[runtime-validation source audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md) +is the evidence; three facts are decisive. The contract carries a bounded runtime value algebra — +codec references, value objects, unions, mandatory nullability, `many`, `dict`, value-set +references, and explicit relation and cross-space coordinates. But **the complete operation and +result type universe is not runtime data**: the SQL field, operation, codec, and aggregate type maps +are installed under an optional phantom key, emitted into `contract.d.ts`, and erased at runtime. +And plans retain enough for **direct** projections and no more — a projection carries alias, +expression, and an _optional_ codec reference, absent for computed expressions, subqueries, and raw +aliases. Prisma's own Standard Schema usage validates codec parameters rather than model values, +across three representations (application runtime, driver wire, target JSON), which is why the +public options are `runtime` and `json`. + +Three schema classes with materially different guarantees, which is why they are not hidden behind +one method: + +| Class | Guarantee | Refusal boundary | +| --------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| Model value | `output('model', …)` validates a named model, value object, or enum. | Never implies uniqueness, foreign keys, or check constraints are satisfied. | +| Operation input | `input(op, …)` exists **only** where the provider or an extension contributes exact runtime operation metadata. | Create/update/filter/nested-write/polymorphic semantics absent from runtime data fail at construction. | +| Selected result | `output(selection, …)` validates a fully-known direct projection whose alias, codec, nullability, and representation are known. | Computed, subquery, raw, aggregate, include, and unknown leaves need a contributed result schema or fail. | + +`ValidationIR` covers registered codec leaves, nullability, `many` and `dict`, value objects, +whole-model values with an explicit presence policy, direct-column projections with complete +metadata, model fields and relations whose cross-space references resolve through an +integrity-verified aggregate, unions only where branch identity is deterministically discriminable, +and value sets and enums whose membership resolves from the value set or native-enum entity — never +inferred from a codec id, because the PostgreSQL native-enum codec is a string pass-through carrying +no members. + +Schema **construction** throws a deterministic `DB_VALIDATION_UNSUPPORTED` — with coordinates naming +target, space, snapshot, model, operation or selection, representation, and the missing metadata — +for at least: unknown codecs, or codecs with no representation-specific value schema; unknown pack +entity kinds; corrupt or missing aggregate spaces, heads, hashes, cross-space references, or value +sets; ambiguous unions and unresolvable model variants; operation grammar absent from runtime data; +computed, subquery, raw, aggregate, include, or unknown result leaves; opaque SQL index and check +expressions; database-state constraints such as uniqueness and foreign keys, which are not local +value validation; and non-deterministic or asynchronous predicates where the requested mode promises +synchronous validation. + +No unsupported case becomes `unknown`, a pass-through, or a warning. This is deliberately **stricter +than the provider's own decoders**, which accept missing codecs and pass through unknown shapes: a +decoder's job is decoding, a validator's job is refusing. Invalid _values_ never throw — they return +Standard Schema issues carrying a stable code, contract coordinates, field path, expected class, and +observed value class. + +A codec is supported only when its contributor supplies a deterministic value schema for **every** +advertised public representation: -```text -.netscript/database/spaces/plugin--netscript--plugin-auth/ - space.json # descriptor snapshot: id, owner, version, requires, dependencies, owns, ownership - contract.json # the space's canonical contract artifact at the pinned version - contract.d.ts # the space's declaration artifact - lineage/ # the space's own migration lineage nodes - PROVENANCE # package identity, resolved version, integrity hash, mirror digest +```ts +defineValidationCodec({ + codecId: 'pgvector.vector@1', + representations: { runtime: vectorRuntimeSchema, json: vectorJsonSchema }, +}); ``` -`[PROPOSAL]` Production apply and verify read the mirror, never the installed package graph, so a -deployment does not need plugin packages resolvable. The mirror digest is comparable against the -installed package digest, which makes version skew detectable rather than latent. Half-installation -— a schema contribution present without its runtime/codec half, or the reverse — is a composition -error, because both halves are named by one contribution record. - -### CLI, agents, and CI - -`[PROPOSAL]` The CLI is a rendering layer over the operation catalog. It owns argument parsing, -human-readable output, and exit-code projection, and it owns no database logic. Machine output is -the contract; human text never is, and no gate may assert on a message string. `[NS-SRC]` The -current merge-readiness migration fixture asserts on a literal message and refuses to run outside -Linux — both are removed by this design, and Windows coverage becomes a required conformance row. - -Exit-code projection is fixed: `succeeded` → 0; `refused` and `failed` → non-zero; `partial-success` -→ non-zero **with** a resume token in the machine result. An exit code is never the result. - -How this shortens and stabilises CI: - -| Mechanism | Effect | -| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------- | -| `pure` compilation and emission with no connection, Aspire, Docker, or network | The most common CI database step stops needing an orchestrator at all. | -| Content-addressed `ManifestDigest` as a cache key | A job that already emitted for a digest asserts the recorded digest instead of re-emitting. | -| Atomic staged-then-committed artifact roots | An interrupted job leaves a fully old or fully new root; no half-patched tree to diagnose. | -| Real-service stages bounded to named gates | Expensive PostgreSQL work runs where it is required, not on every step. | -| Structured receipts reused across jobs | Evidence is machine-readable and survives log loss. | -| Removal of hand-patching and repair workflows | An entire class of order-dependent, non-idempotent CI steps disappears. | - -`[PROPOSAL]` **No unmeasured CI reduction is promised.** The implementation program defines the -measurements and their release thresholds instead: wall-clock and orchestrator-start count for the -pure emission path (target: zero orchestrator starts, enforced as a hard gate rather than a -threshold); cache-hit rate for unchanged manifest digests; flake rate of the database gates over a -rolling window; and the number of gates asserting on message strings (target: zero, enforced). A -percentage improvement claim would be a guess, and this RFC does not make one. - -### The consolidated refusal boundary - -`[PROPOSAL]` These refusals are the architecture. Each is mechanically checkable, and each has a -conformance row in [Appendix D](#appendix-d-conformance-matrix). - -1. **No query DSL, repository, ORM, or portable client facade.** The kernel packages contain zero - query types; the provider's query surface reaches the application as a generic argument. -2. **No compatibility layer.** No Prisma 7 facade, legacy generated module, dual client, `setClient` - lifecycle, alias barrel, copied schema bridge, dual migration history, or runtime shim. -3. **No false portability.** Capabilities are visible and statically checked; unsupported targets - and operations fail explicitly rather than degrading. -4. **No runtime capability negotiation.** Capabilities are open namespaced **static declared data**. -5. **No global mutable provider registry and no service locator.** Provider registries are - composition-root values; `bind` is reachable only from composition roots and generated code. -6. **No hosted control plane.** No RBAC, approval service, registry/promotion, fleet scheduler, - continuous-drift agent, KMS, notification service, or permanent audit server. -7. **No validation overclaim.** The bounded algebra above, failing closed at construction. -8. **No upstream re-export.** Only the PostgreSQL adapter imports Prisma runtime/control modules, - through one facade module and an allowlist. -9. **No text-patched generated source.** Artifacts are produced from an IR and replaced atomically, - or they are not produced. -10. **No implicit target selection.** No primary-ish fallback, no first-available fallback, no - silent single-target execution of a multi-target command. -11. **No arbitrary TypeScript during production apply.** CI and production consume canonical - verified artifacts (D-40). -12. **No cross-target atomicity, cross-database relation, or cross-database transaction.** +Encode/decode functions are not validation: conversion success is compatible with arbitrary +coercion, as the ArkType JSON extension documents — encoding does not validate, so an invalid write +can reach the database and fail only on `RETURNING` decode. A derived validator's cache key covers +the canonical full-contract snapshot digest, contract schema version, `SpaceId`, target/family, +operation or normalized selection shape, representation, interpreter ABI version, and contributor +versions; a storage hash alone is insufficient, because domain, roots, and extension semantics can +change without storage changing. Plugin spaces cache under their own `SpaceId`. + +Input validation is **mandatory** at external mutation boundaries wherever a supported schema +exists; output validation is **mandatory** for declared API/RPC responses, SSR/hydration payloads, +and external-service messages, and **opt-in** for internal query loops, because a design that +validates every row on every read gets disabled wholesale. An input failure is a client error with +field paths; an output failure is a server/contract error **and** a drift signal. NetScript +re-exports no validation library, and no ahead-of-time projection is claimed: one may ship later +only if it is content-addressed, atomically replaced, never required by any code path, and proven to +pass the identical semantic corpus as the runtime interpreter. + +### Ownership, spaces, and the withheld namespace capability + +| Policy | Planned | Mutated | Verified | Typical source | +| ---------- | ------- | ------- | -------------------------------- | ---------------------------------------------------------------- | +| `managed` | Yes | Yes | Fully | An app or plugin space that owns the objects. | +| `adopted` | Yes | Yes | Against a reviewed baseline | Objects brought under management by `db adopt` or by retention. | +| `external` | No | No | Against declared assertions only | Hosted platforms and upstream extensions that own their objects. | +| `ignored` | No | No | No | Deliberate exclusion with an auditable recorded reason. | + +Exactly one `managed` owner per `ObjectKey`; identical declaration text from two contributors is +still an ownership conflict; cross-space references require the same target plus a declared +dependency edge; and augmentation is an **owner-granted closed permission**, so the absence of a +grant is a denial and an unsupported modification either asks the owner or becomes an app-owned +migration. The `external` policy is not an edge case — a hosted database whose tables evolve outside +the framework's knowledge is the normal shape of a managed service, and upstream has a recorded +instance of a pinned extension contract diverging from an externally evolving database and failing +verification ([prisma#29896][pn-29896]). + +The space lifecycle is `declared → installed → upgraded`, with refusals for overlap, missing or +cyclic dependencies, contract-format skew, capability regression, ownership widening, and mirror +skew; then `detached → retained`, with `archived` and `dropped` specified but unclaimed. +Detach-and-retain is the **only guaranteed removal**: data, marker, tombstone, and ownership history +are preserved, and ownership is downgraded `managed → adopted`. Detaching a space a still-installed +space depends on is refused, naming the dependent. + +Prisma's runtime lowering honours per-model namespaces, but its authoring type maps do not: the +authoring path lumps every model under the default storage namespace and leaves additional namespace +maps empty (`packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691`), and the audited +post-RC object retains the limitation. `NamespaceRef` therefore stays a **kernel** identity axis — +manifests, ownership, object keys, and plans all carry it — while the adapter declares only the +target's default physical namespace as a capability, and declaring a second namespace or binding a +space to a non-default one is refused with `db.target.namespace-unsupported`. The capability must +not be advertised until exact type/runtime parity passes with **no casts, no private imports, and no +flattening workaround**. The consequence, stated so it cannot be misread: logical `SpaceId` and +ownership coordinates prevent silent merging, but they do **not** make two identical physical table +names coexist in one namespace, so spaces sharing a target must use distinct physical object names +until the capability is released. If upstream never fixes the type maps, the kernel carries an +unused axis and nothing else needs rework. + +### The refusal boundary + +These refusals are the architecture: each is mechanically checkable and each has a conformance row +in the [approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md). Beyond +the non-goals in the summary and the refusals in the guide: **no compatibility layer** — no Prisma 7 +facade, legacy generated module, dual client, `setClient` lifecycle, alias barrel, copied schema +bridge, dual migration history, or runtime shim, and no code path that selects between the two +stacks; **no upstream re-export**, since only the adapter imports Prisma runtime or control modules; +**no text-patched generated source and no arbitrary TypeScript during production apply**, because +artifacts are emitted from an IR and replaced atomically while CI consumes verified artifacts; and +**no implicit target selection, cross-target atomicity, cross-database relation, or cross-database +transaction**. ## Drawbacks -`[INFERENCE]` The honest costs of this proposal, stated without softening. - **It is a large program, and it lands as a break.** Twelve waves, six new packages, changes to four existing ones, a doctrine amendment, a first-party plugin conversion, and a cutover. No individual -wave is exotic, but the sequence is long, and until W10 the repository carries both the old and the -new foundation (on separate branches or release lines). Anyone who wants a small change here will -find that the smallest coherent unit is still substantial, because the operation contract — not a -missing feature — is what is being replaced. - -**It bets on an Early-Access upstream.** Prisma 8 RC1 is explicitly not recommended for production, -its release notes warn that RC respins may break APIs and the contract format, and the integration -seam demonstrably moved within six days of the tag `[PRIMARY]` `[POST-RC]`. The mitigation — one -adapter package, one facade module, an import allowlist, independent versioning, and a kill switch -that costs a provider rather than the architecture — is real but not free: it adds a package -boundary and a translation layer that a direct dependency would not need. +wave is exotic, but the sequence is long, and until the cutover the repository carries both +foundations on separate branches. Anyone wanting a small change here will find the smallest coherent +unit is still substantial, because the operation contract — not a missing feature — is what is being +replaced. + +**It bets on an Early-Access upstream.** RC1 is explicitly not recommended for production, its notes +warn that respins may break APIs and the contract format, and the seam demonstrably moved within six +days of the tag. The mitigation — one adapter package, one facade module, an import allowlist, +independent versioning, and a kill switch that costs a provider rather than the architecture — is +real but not free: it adds a boundary a direct dependency would not need. **It adds indirection where a direct call used to be.** A definition compiles to a manifest, which -binds a plan, which yields a receipt. For a solo developer running one PostgreSQL database, this is -more moving parts than `prisma migrate dev`. The pay-off arrives with the second target, the first -plugin space, the first partial failure, and the first production apply — not on day one. - -**Six new published packages is a real maintenance surface.** Each carries JSR obligations: export -maps, include lists, module docs, runnable examples, isolated declarations, doc-lint, dry-run, -publish-list inspection, and packed-consumer install. Splitting definition from runtime from control -is correct by archetype and gate profile, but it is four packages where a less disciplined design -would ship one. - -**The typed binding is generated, and generation is a step.** `isolatedDeclarations` and the -oRPC-only slow-types carve-out mean the inferred contract type cannot be published from a framework -package `[NS-SRC]`, so it terminates in a generated application-local module. That is a build step, -and a stale one is refused rather than tolerated — correct, but it does mean a developer can be told -"re-emit" at an inconvenient moment. The alternative was a permanent framework publish debt. - -**Validation is deliberately narrower than users will initially want.** "Derive all my validators -from the schema" is the intuitive expectation, and this design refuses it for filters, nested -writes, polymorphic narrowing, and computed/raw/aggregate results unless exact metadata is -contributed. Some users will experience `DB_VALIDATION_UNSUPPORTED` as a missing feature. It is a -correct refusal, and the RFC would rather explain it than silently return a schema that accepts -wrong data. +binds a plan, which yields a receipt. For a solo developer with one PostgreSQL database this is more +moving parts than `prisma migrate dev`; the pay-off arrives with the second target, the first plugin +space, the first partial failure, and the first production apply. Six published packages is likewise +a real maintenance surface, each carrying JSR obligations — correct by archetype and gate profile, +but four packages where a less disciplined design would ship one. + +**The typed binding is generated, and validation is narrower than users will initially want.** +`isolatedDeclarations` plus the oRPC-only carve-out mean the inferred contract type cannot be +published from a framework package, so it terminates in a generated app-local module and a stale +binding is refused rather than tolerated — correct, but a developer can be told "re-emit" at an +inconvenient moment. Likewise "derive all my validators from the schema" is the intuitive +expectation, and this design refuses it for filters, nested writes, polymorphic narrowing, and +computed/raw/aggregate results unless exact metadata is contributed, so some users will experience +`DB_VALIDATION_UNSUPPORTED` as a missing feature. It is a correct refusal, and this RFC would rather +explain it than silently return a schema that accepts wrong data. **Some capabilities regress relative to today.** Prisma SQLite, MongoDB, MySQL, and SQL Server are not carried forward; multi-namespace end-to-end typing is withheld; destructive plugin removal is -not guaranteed. These are deliberate (D-34, D-37, D-46) and each names the gate that would release -it, but a user who has a MySQL target today has no migration path inside this design other than -staying on the old release line until a certified provider exists. - -**One soundness seam is accepted rather than eliminated.** `runtime.bind` cannot prove that the -provider's runtime value matches the erased `TQuery`; three gates mitigate it (generation, digest -verification, a mismatch conformance case) but the seam is real and is named in -[the type propagation section](#the-one-deliberate-soundness-seam) rather than hidden. +not guaranteed. Each names the gate that would release it, but a user with a MySQL target today has +no path inside this design other than the old release line. And one soundness seam at `runtime.bind` +is accepted rather than eliminated, mitigated by three gates but real. **The conformance matrix is expensive.** Real PostgreSQL, Windows and Linux, failure injection, crash and unknown-outcome recovery, packed consumer installs, and a two-consumer Standard Schema -corpus are all required before the adapter is advertised. That cost is the point — it is what turns +corpus are all required before the adapter is advertised. That cost is the point — it turns "upstream says it is supported" into "NetScript proved it" — but it is a standing CI bill. ## Rationale and alternatives ### Why this shape -`[INFERENCE]` The design follows from four observations that the evidence forces: - -1. **The five current systems fail because nothing joins them.** A join point is therefore - mandatory. It must be a _value_ rather than a live object, because everything the design needs - from it — inspection, diffing, hashing, review, transport to CI, agent consumption, stale - detection — are properties of a serialisable value, and a live graph reachable from feature code - is a service locator with a domain name (D-03). -2. **Provider identity replaced target identity**, so identity must be declared and - provider-neutral, and every artifact must key off it (D-14, D-15, D-16). -3. **Prisma's contract/space/lineage semantics are genuinely good and its operational layer has - gaps** — no mature reset/resolve/diff/squash workflow, no general shadow-database workflow, no - complete advisory-lock story, no row-count-aware data-loss analysis, and no extension removal - `[PRIMARY]`. Waiting for upstream to close those gates adoption on someone else's roadmap; owning - them means NetScript keeps them when a second provider arrives (D-29). -4. **The publish constraint decides where types live.** `isolatedDeclarations` plus the oRPC-only - carve-out is not a style rule; it determines that the inferred binding is generated app-side - (D-08). +Four observations force the design. **The five current systems fail because nothing joins them**, so +a join point is mandatory — and it must be a _value_ rather than a live object, because inspection, +diffing, hashing, review, transport to CI, agent consumption, and stale detection are all properties +of a serialisable value, while a live graph reachable from feature code is a service locator with a +domain name. **Provider identity replaced target identity**, so identity must be declared, +provider-neutral, and the key of every artifact. **Prisma's contract/space/lineage semantics are +genuinely good while its operational layer has gaps** — no mature reset/resolve/diff/squash +workflow, no general shadow-database workflow, no complete advisory lock story, no row-count-aware +data-loss analysis, no extension removal — so waiting would gate adoption on someone else's roadmap, +while owning them means NetScript keeps them when a second provider arrives. And **the publish +constraint decides where types live**: `isolatedDeclarations` plus the oRPC-only carve-out +determines that the inferred binding is generated app-side. ### Alternatives considered and rejected -| Alternative | Why rejected | -| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **Keep Prisma 7 and add Prisma 8 as an opt-in pilot** (issue #313's shape) | It preserves every seam in [Motivation](#the-problem-is-not-a-prisma-version). The current architecture is what a compatibility-first constraint produced; repeating the constraint reproduces the outcome. Owner directive is explicit. | -| **A one-to-one migration of the current design onto Prisma 8** | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are all independent of the Prisma major version. | -| **A proprietary NetScript schema DSL that lowers to the provider contract** | A third schema language that must track every native type, index kind, constraint, and default; permanently lagging; error messages become a translation of a translation. This is the clearest instance of the second-ORM failure. | -| **Recreate the deleted fluent `target/table/column` builder** | It was real at `fd88abf4` and was deliberately removed upstream `[PRIMARY]`. Recreating it for familiarity would mean maintaining a dead API against a live one. | -| **A live `DatabaseGraph` as the public artifact** | A runtime graph accretes traversal APIs and becomes a lookup surface. The manifest gives every property the graph was wanted for, and a graph survives only as private compiler IR (D-03). | -| **A global mutable provider registry** | Publishing a mutable registry is how a service locator is born. Registries are composition-root data (D-13). | -| **Re-export Prisma from a NetScript package** | Doctrine AP-14, plus the publish constraint, plus 138 upstream export keys at the pin `[RC1]` — a re-export converts Early-Access internals into NetScript public API. | -| **A portable query client across providers** | A lowest-common-denominator surface weakens every provider and hides real semantics. Provider-specific queries stay native and app-local (D-05). | -| **Generated mirror validators (a schema file per model/input/output)** | Combinatorially wrong for selection-aware output validation, and it recreates the import-rewriting/circular-reference/getter/decimal repair pipeline that already failed here `[NS-SRC]`. | -| **Claim full operation/result validation from contract data** | The pinned source shows the operation and result type maps are phantom and erased at runtime `[RC1]`. The claim would be false. | -| **Copy plugin schema fragments (status quo)** | No version, ownership, capability guard, dependency order, provenance, or safe removal — with two recorded production failures. | -| **CLI as the business logic (status quo)** | An exit-code result type makes structured reporting impossible; the CLI must be a projection (D-27). | -| **Build a hosted control plane (registry, RBAC, approvals, drift agents)** | Those are persistent products with operators, not local primitives. Atlas Cloud, Pulumi Cloud, and Bytebase demonstrate the value **and** the required services `[PRIMARY]` (D-31, D-47). | -| **Pre-build a direct-SQL contingency provider to prove the SPI** | It would recreate low-level database machinery to prove a hypothesis. A second **real** provider certifies the SPI when demand and maturity exist (D-44, W11). | -| **Extend the `--allow-slow-types` carve-out to database packages** | It converts an application-local inference problem into permanent framework-wide publish debt, and doctrine records any other package setting it as a finding `[NS-SRC]`. | - -### Market lessons, as architecture rather than a feature list - -`[PRIMARY]` Seventeen comparators were examined. What matters is not their feature lists but the -architectural pressure each one applies. The full comparison is in [Prior art](#prior-art); the -lessons that changed this design are: - -- **One resolved manifest, not many config files.** Named connections in Adonis, Rails, and Django - are legible; Atlas proves multiple schema sources can compose. Neither gives a deterministic, - content-addressed resolved value, and Atlas's composite ordering is load order rather than - declared semantic edges. -- **Contributor-owned migration spaces.** Django's per-app graphs with declared cross-app - dependencies and Prisma's contract spaces are the two strong ownership models. Flyway locations - and Liquibase changelogs merge into one shared history, which is why they cannot express - contributor isolation regardless of their tooling quality. -- **Native authoring with framework policy around it.** ZenStack v3 is the closest comparator for - schema/runtime composition and runtime-derived, selection-shaped validators — and its plugin - surface is preview, its validators are Zod-specific, and schema-time and runtime installation can - diverge. NetScript binds both halves in one contribution record and keeps Standard Schema as the - boundary. -- **Apply-bound plans.** Atlas's develop → review → deliver → apply model is the right process - shape; Terraform and Pulumi add the harder lesson that a preview is not an executable plan and - that applying a valid plan is not an atomic transaction. -- **Managed versus external ownership.** Rails' `database_tasks: false`, Drizzle's filters, Atlas's - external sources, and the upstream Supabase drift incident all point the same way: a framework - that treats every visible object as its own reports permanent false drift. -- **Capability-specific behaviour instead of false portability.** MikroORM and Django document - provider differences rather than hiding them; Kysely exposes dialect behaviour honestly. -- **A programmatic core with CLI and agent projections.** Adonis, MikroORM, Kysely, and Atlas all - expose programmatic runners. The CLI should be the thin layer, not the seat of the logic. -- **Separate source, manifest, plan, ledger, and receipt.** Terraform's four-way separation of - configuration, saved plan, mutable state, and backend is the clearest prior art — and its mutable - state is precisely what NetScript must **not** build. - -`[PROPOSAL]` What a **local** meta-framework must not rebuild, stated as scope law: hosted RBAC; -organisation, workspace, and fleet management; remote schema registries and environment promotion; -policy-as-a-service; approval and issue-tracking engines; and continuous drift control planes. Each -of those is a persistent service with operators and an availability budget. NetScript exposes stable -artifacts and integration events so such a system can be added as an adapter, and integrates with -Bytebase or Atlas optionally rather than reimplementing them (D-31, D-47). - -### The impact of not doing this - -`[INFERENCE]` Covered in [Motivation](#what-it-costs-to-not-do-this): two same-provider databases -stay unrepresentable, plugin schema stays a regex copy, CI keeps paying for an orchestrator on pure -generation, success keeps being an exit code, generated source keeps being repaired textually, and -the auth roadmap's deterministic plugin-aware migration requirement has nowhere to land. +| Alternative | Why rejected | +| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Keep Prisma 7 and add Prisma 8 as an opt-in pilot (issue #313) | It preserves every seam in Motivation. The current architecture is what a compatibility-first constraint produced; repeating the constraint reproduces the outcome. | +| A one-to-one migration of the current design onto Prisma 8 | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are all independent of the Prisma major version. | +| A proprietary NetScript schema DSL lowering to the contract | A third schema language tracking every native type, index kind, constraint, and default; permanently lagging; errors become a translation of a translation. | +| A live `DatabaseGraph` as the public artifact | A runtime graph accretes traversal APIs and becomes a lookup surface. The manifest gives every property the graph was wanted for. | +| Re-export Prisma from a NetScript package | Doctrine AP-14, the publish constraint, and 138 upstream export keys at the pin — a re-export converts Early-Access internals into NetScript public API. | +| Generated mirror validators (a schema file per model/input/output) | Combinatorially wrong for selection-aware output validation, and it recreates the repair pipeline that already failed here. | +| Claim full operation/result validation from contract data | The pinned source shows the operation and result type maps are phantom and erased at runtime. The claim would be false. | +| Copy plugin schema fragments (status quo) | No version, ownership, capability guard, dependency order, provenance, or safe removal — with two recorded production failures. | +| Build a hosted control plane (registry, RBAC, approvals, drift) | Those are persistent products with operators, not local primitives. Atlas Cloud, Pulumi Cloud, and Bytebase demonstrate the value **and** the required services. | +| Extend the `--allow-slow-types` carve-out to database packages | It converts an application-local inference problem into permanent framework-wide publish debt. | + +### Market lessons + +Seventeen comparators were examined for the framework-level problem rather than for ORM popularity +([market analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md)). +Five lessons changed this design: + +- **One resolved manifest beats many config files.** Named connections in Adonis, Rails, and Django + are legible, and Atlas proves multiple schema sources can compose — but none yields a + deterministic content-addressed resolved value, and Atlas's composite ordering is load order + rather than declared semantic edges. +- **Contributor-owned migration spaces are the only ownership model that scales.** Django's per-app + graphs and Prisma's contract spaces are the strong examples; Flyway locations and Liquibase + changelogs merge into one shared history and cannot express contributor isolation. +- **A preview is not an executable plan, and applying a valid plan is not a transaction.** Atlas's + develop → review → deliver → apply model is the right process shape; Terraform and Pulumi supply + the harder recovery lesson this RFC encodes as `outcome-unknown` and inspect-before-resume. +- **Managed and external ownership are different.** Rails' `database_tasks: false`, Drizzle's + filters, Atlas's external sources, and the upstream Supabase drift incident all point one way: a + framework that treats every visible object as its own reports permanent false drift. +- **Runtime-derived, selection-shaped validation is the right ergonomic, but the boundary must be + standard.** ZenStack v3 is the closest comparator ([its Zod factory][zenstack-zod]), and its + validators are Zod-specific, its plugin surface is preview, and schema-time and runtime + installation can diverge. NetScript binds both halves in one contribution record and keeps + Standard Schema as the boundary. + +Also stated as scope law: a _local_ meta-framework must not rebuild hosted RBAC, workspace and fleet +management, remote schema registries and environment promotion, policy-as-a-service, approval +engines, or continuous drift control planes. NetScript exposes stable artifacts and integration +events so such a system can be added as an adapter. ## Breaking changes and migration @@ -2368,773 +1123,174 @@ the auth roadmap's deterministic plugin-aware migration requirement has nowhere ### The no-compatibility law -`[PROPOSAL]` No backwards compatibility is allowed, and the prohibition is specific so that it -cannot be eroded one convenience at a time. None of the following survives: a Prisma 7 client or -facade; a legacy generated module or alias barrel; a dual client or `setClient` lifecycle; a -deprecated re-export; a dual migration history; a copied schema bridge; a runtime shim; or any code -path that selects between the old and new stacks. - +None of the following survives: a Prisma 7 client or facade; a legacy generated module or alias +barrel; a dual client or `setClient` lifecycle; a deprecated re-export; a dual migration history; a +copied schema bridge; a runtime shim; or any code path that selects between the old and new stacks. Old and new stacks may coexist **in the repository**, on separate branches or release lines, while -features are developed. A single application composition may never load both. That is a branch -strategy, not a public API, and it does not authorise a dual runtime. - -### What breaks - -| Surface | Break | -| -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -| `@netscript/database` (current adapters, `setClient`, scripts) | Replaced wholesale by the new package graph. Removed at W10. | -| `@netscript/prisma-adapter-mysql` | Retired. A hand-written low-level driver adapter is exactly the maintenance surface the redesign removes. | -| Generated engine workspaces `database//` | Deleted, along with the **42** generated `db:*` task keys per workspace, the repair scripts, and the generated Zod pipeline `[NS-SRC]`. | -| Generated client deep imports | Removed. Applications consume the generated `AppBinding`, never a filesystem path into generated output. | -| `@netscript/plugin` legacy database/migration contribution abstracts and their contribution-axis members | Removed at W7 with breaking-surface accounting; the seam is replaced by `defineDatabaseSpace` `[NS-SRC]`. | -| Plugin `database/**/*.prisma` fragments | Replaced by plugin-owned spaces with pinned artifacts. Copying stops. | -| The fourteen `db` CLI verbs | Replaced by operation-catalog projections; see the disposition table below. | -| Implicit target defaulting and silent single-target execution | **Deliberately removed.** There is no fallback chain anywhere. | -| Prisma SQLite / MySQL / SQL Server targets | Not carried forward (D-34). Structured `db.target.unsupported`, no fallback. | +features are developed; a single application composition may never load both. That is a branch +strategy, not a public API. + +| Surface | Break | +| ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database` (current adapters, `setClient`) and `@netscript/prisma-adapter-mysql` | Replaced wholesale by the new package graph; the hand-written driver adapter is retired. | +| Generated engine workspaces `database//` | Deleted, along with their `db:*` task graph, repair scripts, and the Zod pipeline. | +| Generated client deep imports | Removed. Applications consume the generated binding, never a path into generated output. | +| `@netscript/plugin` legacy database abstracts and plugin `*.prisma` fragments | Replaced by `definePluginSpace` and plugin-owned spaces with pinned artifacts. Copying stops. | +| The current `db` CLI verbs | Replaced by catalog projections; `generate` becomes pure `emit`, `migrate` splits into `plan` + `apply`, `list`/`status` become `inventory`/`verify`. | +| Implicit target defaulting and silent single-target execution | **Deliberately removed.** There is no fallback chain anywhere. | +| Prisma SQLite / MySQL / SQL Server targets | Not carried forward. Structured `db.target.unsupported`, no fallback. | ### The adoption protocol -`[PROPOSAL]` `netscript db adopt` is a temporary migration codemod and tool. It is **not** a -compatibility layer, it is not a permanent command, and it is deleted after the migration window. - -| Step | Operation | Mutates the database? | Failure behaviour | -| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------- | ----------------------------------------------------------------------------------------------- | -| 1 | Read legacy configuration and generated layout (`appsettings.json` targets, engine mapping, workspace layout) | No | Refuse on ambiguous or duplicate config keys | -| 2 | Generate explicit target identities — **`TargetId` comes from config keys, never from provider or engine names** | No | Refuse when two config keys resolved to the same engine directory; the author must name them | -| 3 | Introspect every reachable target | No | Report unreachable targets; adoption proceeds for reachable ones only | -| 4 | Propose object ownership: one space per attributable owner (`app`, one per installed plugin) plus `external`/`adopted` classifications | No | Objects that cannot be attributed are reported, never guessed | -| 5 | **Hard-stop on unattributed or conflicting objects** | No | The author must resolve every unattributed object before continuing | -| 6 | Compile the manifest and atomically emit canonical artifacts and bindings | No | Standard composition diagnostics | -| 7 | Establish one baseline/root lineage node per space, matching the **observed** live state | No | Pure artifact work | -| 8 | Write provider marker metadata **only** — zero table or data DDL/DML | **Yes, markers only** | Idempotent and re-runnable; produces a receipt | -| 9 | Verify live state against the manifest and baseline; require zero drift | No | Any diff here is a genuine finding: an unattributed object or an incorrect ownership assignment | -| 10 | Delete legacy engine workspaces, the 42 per-workspace generated `db:*` task keys, copied plugin fragments, repair scripts, old adapters, and old dependencies — **only after verified adoption** | No | Reversible by reverting the commit | - -`[PROPOSAL]` The load-bearing property is step 8: **no table is created, altered, or dropped during -adoption.** That is what makes the migration safe on production data, and it is what makes step 10 -the only irreversible-looking step — while in fact touching only the repository. - -### Data-safety gates - -Every one of these is required before a release-class cutover: - -| Gate | Requirement | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Rehearsal | A seeded, production-shaped rehearsal proves adoption performs zero schema/data mutation, with the receipt as evidence. | -| Backup | A verified restorable backup exists before the first `mutating` operation in each environment. | -| Ownership preflight | A committed CI artifact listing every target with reachability and provider version, every `ObjectKey` with owner and policy, every unattributable object, every required capability against what each target declares, and every plugin fragment that cannot be attributed to an installed package. Unattributed objects are a hard stop. | -| Destructive consent | Destructive operations require a policy decision; in CI and production, an approved and signed plan. An interactive "yes" is never sufficient outside development. | -| Partial outcome | Multi-target adoption records per-target and per-space outcomes; `partial-success` is first class and carries a resume token. | -| Crash | A crash-fault injection run proves checkpoints, `outcome-unknown`, and inspect-before-resume behave as specified. | -| Marker | Marker writes are idempotent and independently removable before the first new `apply`. | -| Secret | No secret value appears in any plan, receipt, diagnostic, or log; a redaction conformance case proves it. | -| Lock | Lock acquisition, contention, TTL expiry, holder death, and safe force-unlock preconditions are exercised. | -| Release window | The migration window, the legacy release-line end date, and the rollback runbook are agreed before W10 begins. | +`netscript db adopt` is a temporary migration codemod and tool. It is not a compatibility layer, not +a permanent command, and it is deleted after the migration window. It operates on an **explicitly +selected target set** and returns a status for **every** selected target — there is no "whatever was +reachable" mode. + +| Step | Operation | Mutates the database? | Failure behaviour | +| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Read legacy configuration and layout, and derive explicit `TargetId`s from config keys, never engine names | No | Refuse on ambiguous or duplicate keys, and when two keys resolved to one engine directory | +| 2 | Introspect every **selected** target | No | An unreachable target is reported as `not-attempted` with a reason code; the run continues for the rest and cannot be marked complete | +| 3 | Propose ownership — one space per attributable owner, plus `external`/`adopted` — and hard-stop on unattributed or conflicting objects | No | Objects that cannot be attributed are reported, never guessed | +| 4 | Compile the manifest, atomically emit artifacts and bindings, and establish one baseline lineage node per space matching the **observed** state | No | Standard composition diagnostics | +| 5 | Write provider marker metadata **only** — zero table or data DDL/DML | **Yes, markers only** | Idempotent and re-runnable; produces a receipt | +| 6 | Verify live state against the manifest and baseline; require zero drift on every selected target | No | Any diff is a genuine finding: an unattributed object or an incorrect ownership assignment | +| 7 | Delete legacy engine workspaces, task graphs, copied fragments, repair scripts, and old adapters | No | Reversible by reverting the commit | + +Step 5 is the load-bearing property: **no table is created, altered, or dropped during adoption**, +which is what makes the migration safe on production data. Full cutover — step 7 and the removal of +the legacy release line — is blocked until every _intended_ target has been reached, attributed, +baselined, and verified; a partially adopted target set is a resumable state, never a finished one. + +Required before a release-class cutover: a seeded production-shaped **rehearsal** proving zero +schema/data mutation, with the receipt as evidence; a verified restorable **backup** before the +first mutating operation in each environment; a committed **ownership preflight** artifact listing +every target with reachability and provider version, every `ObjectKey` with owner and policy, every +unattributable object, and every capability requirement against what each target declares; +**destructive consent** as an approved signed plan; per-target **partial outcomes** with resume +tokens; a **crash** fault-injection run exercising checkpoints, `outcome-unknown`, and +inspect-before-resume; **idempotent marker** writes; a **secret** redaction conformance case; +**lock** contention, TTL expiry, holder death, and force-unlock preconditions; and an agreed +migration window, legacy release-line end date, and rollback runbook. ### Rollback boundaries -| Point | Rollback | Cost | -| ------------------------------------------------------ | ---------------------------------------------------------------------- | --------------------------------------------------------------------------- | -| Before step 8 | Delete generated artifacts | None; nothing was written to any database | -| After step 8, before the cutover commit | Remove the adopted spaces' marker rows where provider semantics permit | Trivial; markers are metadata | -| After the cutover commit, before the first new `apply` | Revert the commit | Repository-only; the database is untouched | -| After the first new `apply` | **Forward only** — through lineage, the provider ledger, and receipts | Ordinary migration recovery; the receipt identifies exactly which steps ran | - -`[PROPOSAL]` There is deliberately no "run both stacks" rollback. It would require the compatibility -layer this design refuses, and it would double the failure surface during precisely the window when -the system is least understood. - -### Verb disposition - -`[NS-SRC]` The fourteen current verbs map as follows. Parity is claimed only where the new operation -is a superset; everything else is stated as a deliberate removal or a behaviour change. - -| Current verb | Disposition | -| ------------ | --------------------------------------------------------------------------------------------------------------------------- | -| `add` | Replaced by editing the definition file. Scaffolding becomes a codemod, not a config rewrite plus helper regeneration. | -| `list` | `inventory` — superset: targets, spaces, ownership, capabilities, heads, and drift status as structured output. | -| `remove` | Replaced by the space retirement protocol. **Behaviour change:** removal produces a plan; it no longer deletes a directory. | -| `init` | `apply` against an empty baseline. | -| `generate` | `emit` — **now `pure`**, and structurally unable to reach an orchestrator. This closes `DB-GENERATE-ASPIRE-COUPLING`. | -| `migrate` | `plan` + `apply`, separated. **Behaviour change:** planning and applying are distinct operations with distinct policies. | -| `seed` | `seed`, a `mutating` operation with a receipt. | -| `status` | `verify` + `inventory`, structured. | -| `studio` | Retained as `resident`, but **must take an explicit target**; the silent first-target selection is removed. | -| `introspect` | `introspect`, feeding `adopt`. | -| `reset` | Retained, `mutating`, destructive-policy gated; refused in production regardless of consent. | -| `deploy` | `apply` with a signed plan and a production environment. | -| `validate` | `compose` — a `pure` operation returning complete diagnostics rather than a first error. | -| `resolve` | Replaced by explicit lineage operations against named nodes. | - -Two capabilities are removed on purpose and are stated as removals rather than gaps: **implicit -target defaulting**, and **silent single-target execution of a multi-target command**. +| Point | Rollback | Cost | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | +| Before the marker write | Delete generated artifacts | None; nothing was written to any database | +| After markers, before the cutover commit | Remove the adopted spaces' marker rows **where the provider's certified marker semantics prove removal is safe and idempotent**; otherwise the markers stay and the spaces remain `adopted` | Trivial; markers are metadata and carry no user data | +| After the cutover commit, before the first new `apply` | Revert the commit | Repository-only; the database is untouched | +| After the first new `apply` | **Forward only** — through lineage, the provider ledger, and receipts | Ordinary migration recovery; the receipt names which steps ran | + +There is deliberately no "run both stacks" rollback. It would require the compatibility layer this +design refuses, and it would double the failure surface during precisely the window when the system +is least understood. ## Prior art -`[PRIMARY]` Seventeen comparators, examined for the framework-level problem rather than for ORM -popularity. Each row states the strongest transferable idea and the limitation that stops it being a -template. - -| Product | Strongest relevant idea | Limitation for NetScript | -| --------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -| [Wasp][wasp] | Framework-owned commands and generated auth schema produce a coherent happy path | One framework-managed schema/client; schema combination is a special case, not an ownership protocol | -| [RedwoodJS][redwood] | Structural and data migrations are recognised as different concerns, with a data-migration ledger | Two sequences the developer must coordinate; replay ordering is a known hazard | -| [Payload][payload] | A thin internal database contract with official adapters in separate packages | The adapter is shaped around CMS collections; third-party schema gets no independent migration ownership | -| [Better Auth][better-auth] | Typed plugin schema declarations plus an adapter factory that centralises mechanics | With Prisma or Drizzle the user still generates ORM schema and merges/migrates it manually | -| [AdonisJS Lucid][lucid] | Named typed connections, framework-owned lifecycle, a programmatic runner, locks, dry runs | Ownership is configuration, not versioned contributor spaces; cross-connection apply is not atomic | -| [Drizzle][drizzle] | Broad dialects, inspectable SQL, schema filters that exclude externally-managed objects | Multiple configs are the composition mechanism; exported-declaration aggregation is a convention | -| [MikroORM][mikroorm] | Clean core/driver/extension split; programmable migration runner; documented provider caveats | One instance does not span independent connections; schema fan-out has stateful caveats | -| [Kysely][kysely] | Small open dialect/driver/plugin interfaces; honest typed raw SQL; migration-lock hooks | Type generation, schema source, and migration authoring are intentionally external and can drift | -| [Flyway][flyway] | Mature history states, checksum validation, database locks, structured repair, programmatic runner | Locations merge into one history; **repair does not clean objects left by a failed non-transactional migration** | -| [Liquibase][liquibase] | Changeset ledger and lock, preview, rollback, a broad extension surface | Path/order composition and one shared ledger; `update-sql` explicitly does not prove correctness | -| [Terraform][tf-state] | Explicit separation of configuration, saved plan, mutable state, and backend; honest partial-apply recovery | State is a mutable binding database, not a manifest or a receipt; saved plans are opaque and can carry secrets; targeting is exceptional | -| [Pulumi][pulumi-state] | Frequent checkpoints and first-class recovery for interrupted, outcome-unknown operations | Plan completeness is weakened by arbitrary program execution; robust checkpoint backends are a hosted concern | -| [Atlas][atlas-projects] | Composite schema sources, semantic lint, plan/review/deliver/apply, destructive-change policy | Composition is load order; registry, promotion, fleet history, and continuous drift are Cloud services | -| [Bytebase][bytebase-plan] | Plan → issue → rollout with stages, per-database tasks, SQL review, explicit skip reasons | A persistent control plane; **automatic schema drift detection was removed in 3.14.0** ([changelog][bytebase-3140]) | -| [ZenStack v3][zenstack-multifile] | Explicit schema imports, schema/CLI/runtime plugins, [runtime-derived selection-shaped validators][zenstack-zod] | One aggregate history; plugins are preview; validators are Zod-specific; schema-time and runtime installation can diverge | -| [Django][django-multidb] | Per-app migration graphs with declared cross-app dependencies; routing as a policy surface | Multiple databases are operated one at a time; router mistakes can silently skip migrations | -| [Rails][rails-multidb] | Named databases, per-database migration roots, role/shard switching, `database_tasks: false` | Ownership is configuration and folder convention, not a typed contribution protocol | - -`[INFERENCE]` No product is a template to copy. The distinctive combination this RFC proposes — one -deterministic resolved manifest, contributor-owned spaces with independent lineage, native upstream -authoring with framework policy around it, apply-bound plans with receipts and -inspect-before-resume, ownership-aware drift, capability-specific behaviour, a programmatic core -with CLI/agent projections, and a runtime Standard Schema boundary — does not exist as a single -local product today. ZenStack v3 is the closest on schema/runtime composition and validator -ergonomics; Atlas and Bytebase are closest on delivery, and both put the interesting parts in a -hosted service. - -### NetScript's own prior art - -`[NS-SRC]` The oRPC integration is the internal precedent for composing an upstream type system: -real upstream builder, NetScript policy around it, precise types flowing from upstream values, -Standard Schema consumed structurally, one const-generic root fanning into several surfaces, and -compile-failure soundness tests. [The transfer analysis](#the-orpc-precedent-transferred-precisely) -states exactly which parts transfer and which must not. The contribution-axis pattern with versioned -contributions and skew detection is the precedent for pinned mirrors and `db.space.skew`. +The +[market analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md) +compares seventeen products in depth; the lessons this design actually adopted are listed above. The +sources that most directly shaped specific decisions are +[Django's per-app migration graphs with declared dependencies][django-multidb] and Prisma's +[contract spaces ADR][adr-212] for contributor ownership; +[Terraform's targeting guidance][tf-targeting] and +[Pulumi's interrupted-update recovery][pulumi-interrupted] for saga semantics, partial success, and +inspect-before-resume; [Flyway's `repair`][flyway-repair] for the distinction between repairing a +ledger and repairing a database; [ZenStack's runtime Zod factory][zenstack-zod] for selection-shaped +validator ergonomics; and the upstream [Supabase drift incident][pn-29896] for ownership policy. No +product is a template: the combination proposed here — one deterministic resolved manifest, +contributor-owned spaces with independent lineage, native upstream authoring with framework policy +around it, apply-bound plans with receipts, ownership-aware drift, capability-specific behaviour, a +programmatic core with CLI/agent projections, and a runtime Standard Schema boundary — does not +exist as a single local product today. + +NetScript's own prior art is the oRPC integration: the real upstream builder, NetScript policy +around it, precise types flowing from upstream values, Standard Schema consumed structurally, one +const-generic root fanning into several surfaces, and compile-failure soundness tests. The +[transfer analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md) +states exactly which parts transfer and which must not. ## Unresolved questions -`[PROPOSAL]` These are recorded honestly and by category. **No must-resolve-now architecture -question remains**; the plan gate verified that independently. Nothing below can force a -package-boundary rewrite. - -### Locked — not open - -For the avoidance of doubt: the vocabulary, identity model, package graph and archetypes, artifact -taxonomy, refusal boundary, ownership model, plan/apply/recovery semantics, validation bounds, and -clean-break law are **locked** by decisions D-01–D-40 (Appendix A). Reopening one requires the -architecture kill criteria in [Kill and switch criteria](#kill-and-switch-criteria), not a -preference. - -### Implementation-time decisions, by owning wave - -| ID | Question | Wave | Why deferral is safe | -| ---- | ----------------------------------------------------------------------------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------- | -| U-1 | Canonical manifest/digest encoding and the public format-version evolution policy | W1 | `formatVersion` exists and consumers refuse unknown versions; the encoding is internal to that contract. | -| U-2 | Exact Prisma import allowlist, module specifiers, and the supported compatibility window (D-41) | W3 | Adapter-local by construction; pinning a specifier now would design against a surface that moved post-RC. | -| U-3 | Whether the multi-namespace capability can be claimed at all (D-37) | W3 | Withholds a claim, not a boundary. If upstream never fixes it, the kernel carries an unused axis. | -| U-4 | Extension facet mapping onto the provider's authoring/control/runtime/validation locations | W3 | The bundle identity contract is fixed; only the mapping is version-specific. | -| U-5 | Concrete request/process scope shapes and transaction capability types | W4 | The scope split and its guarantees are locked; the concrete option shapes are adapter-facing. | -| U-6 | Plan signature format and production key custody (D-35) | W5 / W10 | The `SignaturePolicy` port and the signed-plan requirement are locked now; only the mechanism is open. | -| U-7 | Provider lock mechanism: native advisory versus fenced row (D-42) | W5, per provider | Public lock semantics — owner, nonce, fencing evidence, TTL, force-unlock preconditions — are locked. | -| U-8 | Receipt storage location and retention policy, and the crash-fault harness | W5 | The receipt contract and outcomes are locked; where they are stored is operational. | -| U-9 | The initial augmentation grant vocabulary and the executable contribution-phase allowlist | W7 | Grants are already closed-by-default; adding a grant kind is additive. | -| U-10 | Whether the testkit needs a runnable binary, or folds into `./testing` subpaths | Before W1 | Explicitly bounded and pre-publication. It cannot rework another unit. | -| U-11 | Migration window, legacy release-line end date, rollback runbook, and remote release evidence | W10 | Release operations, not architecture. | - -### Conditional on upstream - -| ID | Question | Status | -| --- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | -| C-1 | Does Prisma's namespace type map stop flattening non-default namespaces? | `[COND]` Blocks the multi-namespace **capability claim** only. No cast workaround is permitted. | -| C-2 | Do prepared-statement, transaction, raw-SQL, and numeric/aggregate semantics settle by GA? | `[COND]` `[POST-RC]` Aggregate number semantics already changed after RC1. No public NetScript guarantee until proven per pin. | -| C-3 | Does upstream ship an extension/space removal primitive? | `[COND]` If not, `retain` is the product behaviour and archive/drop stay unclaimed (D-46). | -| C-4 | Does the contract format stabilise across releases? | `[COND]` NetScript records its own digest meanwhile; more than one format break without a migration path is a kill trigger. | -| C-5 | Is the Deno platform matrix clean without vendoring or patching? | `[COND]` A named W3 gate. Failure kills the adapter, not the kernel. | -| C-6 | Is the runtime-derived validation direction sustained upstream? | `[EXCHANGE]` Exploratory only. NetScript's bounded interpreter does not depend on an upstream commitment. | - -### Safe to defer - -Second provider; Prisma SQLite, MongoDB, MySQL, and SQL Server; runtime capability negotiation -(rejected until a concrete case exists); AOT validation; archive/drop removal beyond retain; public -raw/prepared/aggregate conveniences; hosted approval, registry, promotion, fleet, drift, and secret -services. Cross-database relations and transactions are **explicitly unsupported**, not deferred -parity debt (D-43–D-47). - -### Discussion questions for reviewers - -1. Is `retain` as the only guaranteed removal acceptable for the first release, given that - archive/drop are specified but unclaimed? -2. Is the generated-`AppBinding` seam the right trade against the alternative of a - framework-published contract-typed value, which the publish constraint forbids? -3. Should the optional policy factory be specified at all, or should Candidate A be the entire - authoring API from the start? -4. Is `@netscript/database-testkit` a package or a subpath — decided before W1 and never after - publication? +The vocabulary, identity model, package graph, artifact taxonomy, refusal boundary, ownership model, +plan/apply/recovery semantics, validation bounds, and clean-break law are **locked**. Nothing below +can force a package-boundary rewrite; each item is a mechanism, version, or release decision behind +stable public semantics, and the full ledger with owning waves is in the +[approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md). + +Implementation-time, by owning wave: the canonical manifest/digest encoding and format-version +evolution policy (W1 — a `formatVersion` exists and consumers refuse unknown versions); the exact +Prisma import allowlist, module specifiers, and supported compatibility window (W3 — adapter-local +by construction, and pinning a specifier now would design against a surface that moved post-RC); +whether the multi-namespace capability can be claimed at all (W3); the mapping of extension facets +onto the provider's authoring/control/runtime/validation locations (W3); the concrete scope shapes +and whether an interactive transaction can expose the ordinary query type (W4); plan signature +format and production key custody (W5/W10 — the port and the signed-plan requirement are locked, +only the mechanism is open); the provider lock mechanism (W5, per provider); receipt storage +location and retention (W5); the initial augmentation grant vocabulary (W7); whether the testkit +needs a runnable binary or folds into `./testing` subpaths (decided before W1); and the migration +window, legacy release-line end date, and rollback runbook (W10). + +Conditional on upstream, each blocking only a _claim_: whether Prisma's namespace type map stops +flattening non-default namespaces (no cast workaround is permitted); whether prepared-statement, +transaction, raw-SQL, and numeric/aggregate semantics settle by GA (aggregate semantics already +changed after RC1, so no public guarantee is made until proven per pin); whether upstream ships an +extension/space removal primitive (if not, `retain` is the product behaviour); whether the contract +format stabilises (more than one format break without a migration path is a kill trigger); whether +the Deno platform matrix is clean without vendoring or patching (failure kills the adapter, not the +kernel); and whether the runtime-derived validation direction is sustained upstream (the bounded +interpreter does not depend on it). + +Explicitly deferred rather than open: a second provider; Prisma SQLite, MongoDB, MySQL, and SQL +Server; runtime capability negotiation; AOT validation; archive/drop removal beyond retain; public +raw/prepared/aggregate conveniences; and hosted approval, registry, promotion, fleet, drift, and +secret services. Cross-database relations and transactions are **unsupported**, not deferred parity +debt. + +Two questions are genuinely for reviewers. Is detach-and-retain as the only guaranteed removal +acceptable for the first release, given that archive and drop are specified but unclaimed? And is +the generated app-local binding the right trade against the alternative of a framework-published +contract-typed value, which the publish constraint forbids? ## Future possibilities -`[PROPOSAL]` Natural extensions this architecture enables and this RFC deliberately excludes: - -- **A second certified provider (W11).** The narrow provider SPI is proven by a real second adapter - when demand and maturity exist — never by a speculative fallback built to prove a port. -- **The multi-namespace capability**, released by the parity gate rather than by a workaround. -- **AOT validation**, released only by mechanical corpus equivalence with the runtime interpreter. -- **Archive and drop retirement**, released by provider conformance and a destructive-plan policy. -- **Delivery-backend adapters** that export plans, receipts, and diagnostics to Atlas, Bytebase, or - a hosted approval system — as adapters over stable artifacts, never as a local reimplementation. -- **Richer data-transform authoring** on top of invariant-guarded transitions, with descriptor - wiring generated from the manifest rather than left as planner placeholders. -- **Deeper agent capability**: an allowlisted operation surface with policy metadata, derived from - the operation catalog, so an agent gets structured operations rather than unrestricted query - access. -- **Additional first-party spaces** beyond auth, workers, sagas, triggers, and streams, once the - contribution seam is certified. -- **Read-replica-aware routing helpers**, if a concrete need appears — as an application-composition - affordance, never as a hidden runtime router that could silently send a write to a reader. - -## Appendix A: decision trace D-01–D-47 - -`[PROPOSAL]` Every locked decision and its definitive section in this RFC. Nothing is silently -dropped or weakened; where a decision is conditional or deferred, the status column says so and the -gate is named in Appendix F or in [Unresolved questions](#unresolved-questions). - -### Clean break, data continuity, artifact separation, no query abstraction (D-01–D-05) - -| ID | Decision | Status | Definitive section | -| ---- | ---------------------------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------ | -| D-01 | Clean break; no backward-compatibility API or runtime surface. | Locked | Breaking changes and migration → The no-compatibility law; Refusal boundary §2 | -| D-02 | Data continuity and mechanical migration are mandatory. | Locked | Breaking changes and migration → The adoption protocol; Data-safety gates | -| D-03 | The durable join point is `DatabaseManifest`; a graph is private compiler IR only. | Locked | Locked vocabulary; Artifacts → `DatabaseManifest` | -| D-04 | Definition, manifest, executable plan, provider ledger, and receipt stay separate. | Locked | The one story; Artifacts → The artifact contract, at a glance | -| D-05 | NetScript defines no query DSL, repository, or portable client facade. | Locked | Refusal boundary §1; Runtime layer | - -### Native authoring, Candidate A, inference, app-local binding (D-06–D-08, D-36) - -| ID | Decision | Status | Definitive section | -| ---- | --------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------- | -| D-06 | Current model-first native Prisma authoring is primary; the obsolete fluent chain is not recreated. | Locked; import spelling adapter-pinned | Guide § Step 1; Rationale → Alternatives rejected | -| D-07 | Candidate A (native contract + thin definition) is the baseline; the optional factory dies on private imports, copied overloads, or widening. | Locked | The definition layer; The optional policy factory, and its kill criterion | -| D-08 | The app-specific inferred binding is generated app-local, never a kernel export. | Locked | End-to-end type propagation; Package graph (`-runtime`) | -| D-36 | Model-first callback, Candidate A, two-phase collection, const-preserving root, no re-export. | Locked; exact RC/GA path in W3 | The definition layer; Two-phase composition | - -### Packages, provider boundary, targets, replicas, capabilities (D-09–D-16) - -| ID | Decision | Status | Definitive section | -| ---- | ----------------------------------------------------------------------------------- | ------ | --------------------------------------------------------- | -| D-09 | The package/archetype graph is exact; runtime is A3. | Locked | The package graph and archetypes | -| D-10 | The kernel is provider-neutral; the first certified adapter is Prisma 8 PostgreSQL. | Locked | Package graph (`-prisma-postgres`); Targets and providers | -| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | Locked | Targets and providers; Refusal boundary §3 | -| D-12 | Capabilities are static declared tags, never runtime negotiation. | Locked | Identity model; Refusal boundary §4 | -| D-13 | The provider registry is composition-root data, never global mutable state. | Locked | Consumed ports (closing note) | -| D-14 | A stable target id owns connection, output, runtime, migrations, locks, receipts. | Locked | Identity model | -| D-15 | Target selection is explicit and dependency-closed, and records every omission. | Locked | Multi-target execution is a saga | -| D-16 | Replicas are roles of a target, never migration targets. | Locked | Identity model; Runtime layer guarantees | - -### Spaces, ownership, extensions, mirrors, lifecycle (D-17–D-20, D-38–D-40) - -| ID | Decision | Status | Definitive section | -| ---- | ------------------------------------------------------------------------------------------- | ------ | ----------------------------------------------------- | -| D-17 | Provider-native contract spaces plus NetScript policy replace copied fragments. | Locked | Plugin and contract-space lifecycle; Guide § Step 6 | -| D-18 | One `managed` owner per `ObjectKey`; augmentation requires an owner grant. | Locked | Ownership | -| D-19 | Pinned mirrors make apply/verify independent of installed plugin code. | Locked | The pinned mirror | -| D-20 | Detach-and-retain is the guaranteed removal; archive/drop are conditional. | Locked | Plugin and contract-space lifecycle | -| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin tables default to a space. | Locked | Two contribution modes; the fragment publication rule | -| D-39 | One extension bundle supplies identity-matched authoring/control/runtime/validation facets. | Locked | Guide § Step 7; Two-phase composition; V-9 | -| D-40 | CI and production consume canonical verified artifacts, never arbitrary schema TypeScript. | Locked | Two-phase composition; Refusal boundary §11 | - -### Bounded Standard Schema interpretation (D-21–D-25) - -| ID | Decision | Status | Definitive section | -| ---- | ------------------------------------------------------------------------------------ | ------ | ---------------------------------------------------- | -| D-21 | Standard Schema is public; bounded runtime interpretation is the default. | Locked | The runtime validation subsystem → The public API | -| D-22 | Public representations are `runtime` and `json`; driver wire is adapter-internal. | Locked | The public API | -| D-23 | Full Prisma operation validation is not contract-derived; contributors are required. | Locked | Three schema classes; What is explicitly not claimed | -| D-24 | Unknown validation metadata fails at schema construction. | Locked | Mandatory fail-closed cases | -| D-25 | Optional AOT validation is corpus-equivalent only and never required. | Locked | Optional ahead-of-time projection | - -### Operations, catalog, plans, control ownership, receipts, artifacts, agents (D-26–D-33) - -| ID | Decision | Status | Definitive section | -| ---- | ------------------------------------------------------------------------------------------------------ | ------ | ------------------------------------------------ | -| D-26 | Pure operations cannot resolve connections, Aspire, Docker, secrets, or the network. | Locked | Operation classes | -| D-27 | The programmatic operation catalog is primary; CLI, docs, and agents are projections. | Locked | The operation catalog; CLI, agents, and CI | -| D-28 | A preview is not an executable plan; `apply` accepts only bound, revalidated plans. | Locked | Preview, plan, policy, approval | -| D-29 | NetScript owns policy, locks, recovery, receipts, and the saga; the provider owns diff/lineage/marker. | Locked | Consumed ports; Apply, checkpoints, and recovery | -| D-30 | Cross-target apply is never atomic; partial and unknown outcomes are first class. | Locked | Multi-target execution is a saga | -| D-31 | The local kernel does not rebuild hosted registry/RBAC/fleet/drift products. | Locked | Refusal boundary §6; Market lessons | -| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | Locked | The artifact contract; Refusal boundary §9 | -| D-33 | Agent instructions and catalogs are generated, and every example executes. | Locked | The operation catalog; CLI, agents, and CI | - -### Legacy provider parity and signed production plans (D-34–D-35) - -| ID | Decision | Status | Definitive section | -| ---- | ----------------------------------------------------------------------------------- | ------------------------- | ---------------------------------------------- | -| D-34 | Existing MySQL/SQL Server/SQLite support is not carried through compatibility code. | Locked | Breaking changes → What breaks; Targets matrix | -| D-35 | Production plans require signatures; mechanism and key custody are chosen later. | Pre-implementation W5/W10 | `ExecutablePlan`; Unresolved U-6 | - -### Withheld capability (D-37) - -| ID | Decision | Status | Definitive section | -| ---- | ---------------------------------------------------------------------------------------------------------- | -------------------------- | --------------------------------------------- | -| D-37 | The multi-namespace adapter capability is withheld while type maps flatten namespaces; no cast workaround. | Conditional upstream block | The namespace capability is withheld, and why | - -### Implementation-time pin, import, and lock choices (D-41–D-42) - -| ID | Decision | Status | Definitive section | -| ---- | --------------------------------------------------------------------------- | -------------------------------- | --------------------------------------- | -| D-41 | The exact Prisma control/runtime import allowlist and compatibility window. | Pre-implementation W3 | Package graph (`-prisma-postgres`); U-2 | -| D-42 | Native advisory versus fenced-row lock is certified per provider. | Pre-implementation, per provider | Apply, checkpoints, and recovery; U-7 | - -### Explicitly deferred optional capabilities (D-43–D-47) - -| ID | Decision | Status | Definitive section | -| ---- | -------------------------------------------------------------------------- | -------- | ------------------------------------------------------- | -| D-43 | Whether AOT validation ships at all. | Deferred | Optional ahead-of-time projection; Future possibilities | -| D-44 | A real second provider. | Deferred | Alternatives rejected; Appendix C wave W11 | -| D-45 | Public raw/prepared/aggregate conveniences stay deferred or adapter-local. | Deferred | Unresolved → Safe to defer; C-2 | -| D-46 | Archive/drop plugin retirement in v1. | Deferred | Plugin and contract-space lifecycle | -| D-47 | Remote approval, registry, and continuous-drift integrations. | Deferred | Refusal boundary §6; Future possibilities | - -## Appendix B: claim and source trace - -`[PROPOSAL]` Every load-bearing fact this RFC relies on, with its class, its pin, and its -verification status. This table is the RFC's own claim ledger; a reviewer should be able to falsify -any row from the cited source alone. - -| # | Claim | Class | Pin / source | Verification | -| -- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | Executing `generateDatabaseDenoJson` for PostgreSQL, SQLite, MySQL, and SQL Server yields **42 `db:*` task keys per generated engine workspace** | `[NS-SRC]` | `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` at `383170bbc` | **Executed** by the PLAN-EVAL evaluator for all four providers. Supersedes an independent report's figure of 30. | -| 2 | The current-state audit's phrase "more than twenty database tasks" was **accurate** | `[NS-SRC]` | Same generator | Confirmed: 42 > 20. An independent report's "correction" to exactly 30 was itself wrong and is dispositioned. | -| 3 | `@prisma/orm-postgres` publishes **138** top-level export subpath keys | `[RC1]` | `packages/9-public/@prisma/orm-postgres/package.json` at `a76a6c5` | Recounted independently during PLAN-EVAL cycle 2. Supersedes an independent report's "~275". | -| 4 | `resolveTarget` defaults only with exactly one enabled target and never consults `PrimaryDatabase` | `[NS-SRC]` | `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66-91` | Re-verified during PLAN-EVAL cycle 2. | -| 5 | The generated workspace directory is `join('database', provider.dirName)` | `[NS-SRC]` | `workspace-resolver.ts:51` | Re-verified. | -| 6 | Plugin schema contribution is file copy plus regex declaration scanning | `[NS-SRC]` | `prisma-declaration-scanner.ts:13`; `prisma-schema-writer.ts:19,100-122` | Re-verified during PLAN-EVAL cycle 2. | -| 7 | Generated templates pin `npm:prisma@^7.4.2` while the root catalog uses caret ranges `^7.8.0` | `[NS-SRC]` | `generate-db-deno-json.ts:36,56,59,61,67`; root `deno.json:231-236` | Re-verified during PLAN-EVAL cycle 2. | -| 8 | The operation runner's result type is `Promise`; `studio` uses the first target; `--db all` is fail-fast | `[NS-SRC]` | `operation-runner.ts:85,90-105,116-117` | Verified by the independent architecture review; consistent with the current-state audit. | -| 9 | `isolatedDeclarations: true` is repo-wide and the slow-types carve-out is oRPC-only | `[NS-SRC]` | root `deno.json:174`; `docs/architecture/doctrine/02-public-surface.md:217-240` | Re-verified during PLAN-EVAL cycle 2. | -| 10 | Doctrine codifies plain `*.prisma` plugin fragments and does not register the proposed packages | `[NS-SRC]` | `06-archetypes.md:209-211`; `10-codebase-verdict-and-handoff.md` | Re-verified during PLAN-EVAL cycle 2; the W0 amendment obligation follows. | -| 11 | `DB-GENERATE-ASPIRE-COUPLING` is open; `packages/database — AP-17` is open with a stale rename half | `[NS-SRC]` | `.llm/harness/debt/arch-debt.md` | Re-verified during PLAN-EVAL cycle 2 (`packages/database/ports/` exists). | -| 12 | Prisma 8 RC1 is Early Access and not recommended for production; RC respins may break or rename APIs | `[PRIMARY]` | [RC1 release][rc1-release]; [RC1 README][rc1-readme] | Primary source. | -| 13 | PostgreSQL is the sole database intended for the 8.0 GA target set; MongoDB EA, SQLite proof-of-concept, MySQL later, SQL Server absent | `[PRIMARY]` | [scorecard][rc1-scorecard]; [supported versions][rc1-versions] | Primary source. | -| 14 | Authoring is model-first `defineContract(scaffold, callback)` with literal-preserving overloads | `[RC1]` | `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121`; `contract-builder.ts:437-462` | Re-verified during PLAN-EVAL cycle 2. | -| 15 | The fluent `target/table/column` builder existed at `fd88abf4`, was replaced by PR #261 / `27ccefc3`, and removed by `e1e5ab2c` | `[PRIMARY]` | [PR #261][pn-261]; [`27ccefc3`][pn-27ccefc3]; [`e1e5ab2c`][pn-e1e5ab2c] | Primary source. | -| 16 | Authoring type maps flatten non-default namespaces while runtime lowering honours them | `[RC1]` | `packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691` | Re-verified during PLAN-EVAL cycle 2. Retained `[POST-RC]` at `71e2e0d9…`. | -| 17 | Operation/result type maps are phantom and emitted to `contract.d.ts`, not retained as runtime data | `[RC1]` | `packages/2-sql/1-core/contract/src/types.ts:90-139,207-215`; `generate-contract-dts.ts:179-221` | Pinned-source audit. | -| 18 | SQL projections carry no codec for computed, subquery, and raw aliases | `[RC1]` | `packages/2-sql/4-lanes/relational-core/src/ast/types.ts:1480-1505` | Pinned-source audit. | -| 19 | Codecs have three representations: application runtime, driver wire, target JSON | `[RC1]` | `framework-components/src/shared/codec.ts:16-30,44-51` | Pinned-source audit. Public NetScript representations are therefore `runtime` and `json`. | -| 20 | Prisma's Standard Schema slot validates codec **parameters**, not model values | `[RC1]` | `shared/codec-descriptor.ts:27-54` | Pinned-source audit. | -| 21 | Contract hashing covers storage, execution, and profile separately; domain/roots/extensions are excluded | `[RC1]` | `contract/src/hashing.ts:74-106`; `canonicalization.ts:250-277` | Pinned-source audit — the reason for the full-contract validator cache key. | -| 22 | The migration aggregate keeps spaces separate and defers cross-space domain checks | `[RC1]` | `migration/src/aggregate/types.ts:32-79,81-123`; `validate-domain.ts:140-147` | Pinned-source audit. | -| 23 | A custom codec requires conversions and a JSON round trip but no value predicate; encoding does not validate | `[RC1]` | `mongo-codec/src/codecs.ts:23-42,44-82`; `arktype-json/README.md:7-17,40,74-87` | Pinned-source audit — the reason codec contributions must carry value schemas. | -| 24 | Contract spaces define one `(contract, migration graph, head ref)` tuple per contributor | `[PRIMARY]` | [ADR 212][adr-212] | Primary source. | -| 25 | Data transforms are invariant-guarded transitions | `[PRIMARY]` | [ADR 176][adr-176] | Primary source. | -| 26 | The integration seam moved materially within six days of the RC tag | `[POST-RC]` | [`3dc98cb`][pn-3dc98cb], [`d0c8333`][pn-d0c8333], [`15308c6`][pn-15308c6], [`92b6ee3`][pn-92b6ee3], [`c4a5875`][pn-c4a5875], [`5d4a4db`][pn-5d4a4db], [`a900bc1`][pn-a900bc1], [`71e2e0d`][pn-71e2e0d] | All eight verified as descendants of the RC tag by an independent review. | -| 27 | Generated contract JSON Schema is labelled lossy/advisory with ArkType authoritative | `[POST-RC]` | `data-contract-json-schema.ts:10-15,31-38,68-110` at `71e2e0d9…` | Pinned-source audit. Corroborates direction; changes no RC1 capability. | -| 28 | An externally-evolving hosted database can break `db verify` against a pinned extension contract | `[PRIMARY]` | [prisma#29896][pn-29896] | Primary source — the motivation for `external`/`adopted` ownership. | -| 29 | A published type can be accepted and then ignored at runtime | `[PRIMARY]` | [prisma#29932][pn-29932] | Primary source — the reason conformance rows must cross type → plan → SQL → result. | -| 30 | An introspection schema selector could be silently ignored | `[PRIMARY]` | [prisma#29923][pn-29923] / [PR #29944][pn-29944] | Primary source — the reason a silently-ignored namespace selector is a conformance failure. | -| 31 | An exact CLI-engine peer is needed to prevent duplicate engine copies | `[PRIMARY]` | [PR #30009][pn-30009] | Primary source — the reason for the one-resolved-component-set gate. | -| 32 | Upstream "proven" for PostgreSQL includes PGlite-backed integration tests | `[PRIMARY]` | [scorecard][rc1-scorecard] | Reported by an independent review against the RC scorecard; **re-verify at W3**. It is why "one real PostgreSQL service, not only PGlite" is a NetScript gate. | -| 33 | Flyway's `repair` realigns the ledger and does not clean objects left by a failed non-transactional migration | `[PRIMARY]` | [Flyway repair][flyway-repair] | Primary source — the reason `cleanup-required` is a distinct outcome. | -| 34 | Pulumi cannot know whether an interrupted create completed, and recovery inspects the provider first | `[PRIMARY]` | [interrupted updates][pulumi-interrupted] | Primary source — the reason for `outcome-unknown` and inspect-before-resume. | -| 35 | Terraform targeting is documented as exceptional recovery, not a routine selector | `[PRIMARY]` | [resource targeting][tf-targeting] | Primary source. | -| 36 | Bytebase removed automatic schema drift detection in 3.14.0 | `[PRIMARY]` | [Bytebase 3.14.0 changelog][bytebase-3140] | Primary source — no current Bytebase drift capability is claimed here. | -| 37 | ZenStack v3 derives selection-shaped validators from its runtime schema, Zod-specific | `[PRIMARY]` | [ZenStack Zod factory][zenstack-zod] | Primary source — prior art for ergonomics, not for choosing Zod as the boundary. | - -### Claims deliberately **not** used as evidence - -| Claim | Why it is excluded | -| -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| Counts of legacy `@internal/*` roots or `PN-*` error codes in the upstream agent skill | Two independent measurements disagreed materially and the totals vary with the counting pattern. The qualitative conclusion (a hand-maintained agent surface decays) is used; no count is. | -| "Approximately 275 `@prisma/orm-postgres` export keys" | Superseded by the recounted 138 (row 3). | -| "Exactly 30 generated `db:*` tasks" | Superseded by the executed 42 per workspace (row 1). | -| Exact upstream scorecard verdict tallies | The methodology is cited (row 32); the tallies are not load-bearing and are re-measured at W3 rather than argued. | -| A live `DatabaseGraph` as the public join point | Rejected in favour of a durable plain `DatabaseManifest` (D-03). | -| Broad "derive all validation from the contract" claims | Narrowed by the pinned-source audit (rows 17–23). | -| Provider re-export proposals | Rejected; only the adapter imports Prisma, and applications import the public authoring builder directly. | -| "Contract spaces solve plugin removal" | Overclaim. Spaces solve ownership and history; removal beyond `retain` stays conditional (D-20, D-46). | - -## Appendix C: implementation and release plan (W0–W11) - -`[PROPOSAL]` Each wave lands independently, has a gate that can fail, and depends only on earlier -waves. No production code, doctrine mutation, package publication, provider certification, plugin -conversion, legacy deletion, or release operation is authorised by this RFC; acceptance authorises -the program. - -| Wave | Scope | Depends on | Exit evidence | -| ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| W0 | RFC acceptance; doctrine amendments to `06-archetypes.md` and `10-codebase-verdict-and-handoff.md`; register every new unit in the gated denominator; replace the plain-fragment rule | — | Accepted RFC; `arch:check` discovers the new roots; the archetype-count consequence resolved or carried as an explicit debt entry | -| W1 | `@netscript/database-contract` (A1): identities, artifact schemas, capability/ownership vocabularies, diagnostics, operation/receipt types, space descriptor, ports | W0 | A1 gates; zero dependencies; `deno doc --lint` clean; `deno publish --dry-run` **without** `--allow-slow-types`; packed consumer install | -| W2 | `@netscript/database` (A4): definitions, two-phase composition, the pure compiler, invariants V-1…V-9, diagnostics | W1 | A4 gates; determinism/property tests; every invariant has a negative test with the right code; an AP-25 scan proving no IO is reachable | -| W3 | **Experimental** `@netscript/database-prisma-postgres` (A2) spike: native builder integration, artifacts, control adapter, runtime factory, spaces, extension bundles, `ValidationIR` decoder, Deno matrix, namespace parity check | W1, W2 | Real PostgreSQL (**not** PGlite only); packed Deno consumer; import allowlist; exactly one resolved Prisma component set; a recorded kill/switch review; **no public stability claim** | -| W4 | `@netscript/database-runtime` (A3) and the Aspire `ConnectionSource` adapter | W1–W3 | **All F-1…F-19 plus required runtime gates**; lifecycle, leak, cancellation, and scope tests; redaction case; bind-mismatch refusal | -| W5 | `@netscript/database-control` (A2): catalog, preview/plan/apply/verify, locks, receipts, recovery, cross-target saga | W1–W4 | A2 gates; failure-injection matrix; atomic emission; an offline test proving a `pure` operation cannot reach an orchestrator | -| W6 | `@netscript/database-testkit` (A6): provider **and** space conformance suites with machine reports | W1–W5 | A6 + F-CLI gates; deliberately broken provider and space fixtures must fail; real-service machine report | -| W7 | `@netscript/plugin` contribution seam; remove the legacy contribution abstracts; first plugin-core fixture | W1–W6 | Breaking-surface accounting for a published package; plugin thinness/seam gates; a contribution that carries no provider dependency | -| W8 | CLI, agent surface, and adoption codemod as projections | W2, W5–W7 | Generated example and catalog freshness; every generated example compiles and runs; a populated adoption preflight; zero text-log assertions | -| W9 | First-party spaces: auth, workers, sagas, triggers, streams | W7–W8 | Each space certified by the space conformance kit; package-free apply/verify; runtime parity in a generated project | -| W10 | Clean cutover and legacy deletion | W1–W9 | Full release-gate class; Windows and Linux; production-shaped adoption rehearsal on seeded data; remote published E2E against exact JSR versions; no compatibility remnant | -| W11 | A second real provider — only on demonstrated demand and maturity | W10 | The same provider conformance suite passes; **no kernel or public manifest rewrite** | - -`[PROPOSAL]` W3 is deliberately a spike **before** public runtime/control stabilisation, so that a -failed Prisma adapter does not invalidate W1–W2. No old package is deleted before W10, and that -temporary repository coexistence never authorises a dual runtime composition. - -## Appendix D: conformance matrix - -`[PROPOSAL]` Every behavioural feature must cross **type → composition/plan → provider artifact or -SQL → result → lifecycle/evidence**. A type-only pass or an exit-code-only pass is never evidence. -Negative paths are first-class rows. - -### D.1 Archetype and package gates - -| Row | Requirement | -| --- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| A-1 | Each new unit passes the F-1…F-19 subset its archetype requires, per the archetype gate matrix. | -| A-2 | `@netscript/database-runtime` (A3) passes **all** F-1…F-19 and the **required** runtime gates. | -| A-3 | First-party plugins (A5) pass thinness, base-seam, golden-emitter, doctor, contract-soundness, and `scaffold.runtime` parity. | -| A-4 | The testkit (A6) passes the F-CLI family. | -| A-5 | Scoped check, lint, and format wrappers; `quality:scan`; `arch:check`; public surface and subpath audit; naming/folder/layering/inheritance/upstream-re-export/permission/test-shape gates. | - -### D.2 Composition, typing, and artifacts - -| Row | Case | Passes when | -| ---- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | -| T-1 | A space requires a capability its bound target lacks | Composition fails with `db.compose.capability.missing`, naming capability, space, target | -| T-2 | A space is bound to an undeclared target | **Type error** at the authoring site, not a runtime diagnostic | -| T-3 | Two spaces manage one `ObjectKey` | `db.compose.ownership.conflict`, naming both spaces | -| T-4 | A cyclic dependency between spaces | `db.compose.dependency.cycle`, with the cycle path | -| T-5 | A cross-target relation is declared | Refused at composition, never emitted | -| T-6 | Native contract inference survives to the app binding | Model, query, and result types are preserved end to end | -| T-7 | App fragment composition under reordering | Literal model/field/relation names preserved; the canonical digest is unchanged | -| T-8 | A deliberately widened fragment registry fixture | **Fails** its type-soundness gate | -| T-9 | No private import, cast, copied overload, or declaration widening in the adapter | An allowlist and a source scan prove it; a violation fails the build | -| T-10 | Namespace type/runtime parity | Either exact parity with no casts, or the capability remains unclaimed — never a workaround | -| T-11 | A 500-model representative application | Type-check and editor latency inside the agreed budget | -| T-12 | A published package exports a fragment naming provider helper types | **Fails** the publish gate | -| T-13 | Extension bundle facet identity | Identical id/version across all four facets; a missing or mismatched facet fails composition | - -### D.3 Deterministic and atomic emission - -| Row | Case | Passes when | -| --- | -------------------------------------------------------------- | ---------------------------------------------------------------- | -| E-1 | Emit twice from clean inputs | Byte-identical artifacts and an identical `ManifestDigest` | -| E-2 | Emit two targets concurrently into distinct roots | Both succeed with no interleaving | -| E-3 | Emit interrupted mid-write | The artifact root is fully old or fully new — never half-written | -| E-4 | Schema edited without re-emitting | `db.artifact.stale` at bind time, naming the exact command | -| E-5 | Every artifact root records its manifest digest | Present and matching | -| E-6 | CI re-run with an unchanged digest | Emission skipped; the recorded digest asserted instead | -| E-7 | Migration apply with application/plugin TypeScript unavailable | Succeeds from canonical artifacts alone | - -### D.4 Runtime, platform, and validation - -| Row | Case | Passes when | -| --- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| R-1 | Full runtime suite against a **real** PostgreSQL service | Connect, query, relations, raw, codecs, transactions, prepared statements, streaming, cancellation, close — never satisfied by PGlite alone | -| R-2 | Connection injection and an external pool | Correct behaviour under concurrency | -| R-3 | Error mapping and redaction | No connection string, password, or secret in any diagnostic, receipt, or log | -| R-4 | Repeated start/stop and request lifecycles | Leak-free; close ordering respected | -| R-5 | Request-scoped session used after disposal | Prevented by type where possible; a runtime error otherwise | -| R-6 | A transaction handle escaping its callback | Rejected; a transaction handle does not expose transaction-opening members | -| D-1 | Deno import graph of runtime paths | No undeclared Node globals; no CLI or toolchain module reachable | -| D-2 | Packed-artifact install into a blank fixture | Every used export and peer resolves exactly once; exactly one Prisma component set | -| D-3 | Upstream deep-import allowlist | Any newly-introduced off-allowlist import fails the build | -| V-1 | `runtime`/`json` corpus | Strings, numbers, booleans, `Date`, bigint, numeric string, bytes, JSON, domain enum, value set, native enum, null, list, dict, value object, union, and one custom codec — each representation tested separately with round trips and malformed cases | -| V-2 | Every mandatory unsupported case | Fails at **schema construction** with stable coordinates; never `unknown`, never pass-through | -| V-3 | Invalid values | Return path-rich Standard Schema issues; never throw | -| V-4 | Direct selection/result shapes | Strict; computed, raw, aggregate, include, and unknown leaves never pass through | -| V-5 | App plus two extension spaces | Aggregate resolution correct; duplicate model names across spaces never collide | -| V-6 | Two independent Standard Schema consumers | The same schema values consumed by two integrations with no generated mirror files | -| V-7 | Cache invalidation | Domain-only, extension-only, execution-default, codec-version, representation, selection, and space changes each invalidate correctly | -| V-8 | Custom codec without representation schemas | Unsupported, fails closed | -| V-9 | AOT projection, **if it exists** | Passes the identical semantic corpus and invalidation suite; otherwise it does not ship | - -### D.5 Control, migration, ownership, and recovery - -| Row | Case | Passes when | -| ---- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -| M-1 | Offline emit with no Aspire, .NET, Docker, or network | Succeeds | -| M-2 | Greenfield apply | Succeeds with a complete receipt | -| M-3 | Adoption of a populated database | Marker rows only; **zero DDL/DML**; `verify` clean | -| M-4 | Externally-introduced drift | `db.verify.drift` classifies managed, adopted, external, and ignored correctly | -| M-5 | Destructive change under a deny policy | Refused with the destructive operation list | -| M-6 | Destructive change in production with an unsigned plan | Refused regardless of interactive consent | -| M-7 | Apply after the manifest, baseline, pins, or policy changed | `db.plan.stale` | -| M-8 | Apply after plan expiry | `db.plan.expired` | -| M-9 | Apply fails mid-run | The receipt names the exact failed step; resume revalidates the baseline before continuing | -| M-10 | Transport lost after dispatch | `outcome-unknown`; resume inspects marker and live state before acting | -| M-11 | Two concurrent applies on one target | The second receives `db.apply.lock.held` with owner and TTL; no interleaved DDL | -| M-12 | The lock holder dies | TTL/fencing releases it; no permanent wedge; force-unlock preconditions enforced | -| M-13 | A data transform with an unsatisfied invariant | Fails, reports remaining work, and does not advance the head | -| M-14 | A non-default namespace selector | Honoured; a silently ignored selector is a **failure** | -| M-15 | Two same-provider targets | Fully isolated output, lineage, markers, locks, receipts, and runtime bindings | -| M-16 | Cross-target failure | Complete per-target and per-space outcomes; `partial-success`; resume continues only unfinished work | -| M-17 | Selective target/space execution | Dependency closure expanded, omissions recorded with reasons, whole-manifest verification afterwards | -| M-18 | Migration on Windows **and** Linux | Both run; no gate asserts on a human message string | -| P-1 | Two plugin spaces with declared ordering | Applied in the manifest's recorded topological order | -| P-2 | Plugin object-name collision across spaces | Namespaced and non-conflicting; no lexical prefix convention required | -| P-3 | Cross-space reference along a declared edge | Allowed; refused without the edge | -| P-4 | Plugin upgrade with a lineage step | Only that space's head advances | -| P-5 | Installed package digest ≠ mirror digest | `db.space.skew`, naming both digests and the sync action | -| P-6 | Apply/verify with **no plugin package installed** | Succeeds from the pinned mirror alone | -| P-7 | Uninstall with retention | Objects retained; ownership downgraded to `adopted`; verify still sees them | -| P-8 | Uninstall with a dependent space installed | Refused, naming the dependent | -| P-9 | Archive or drop | **Excluded** until individually certified; never claimed by default | -| P-10 | A plugin requiring a capability its target lacks | Install refused at composition | -| P-11 | Augmentation outside a granted axis | Refused, naming the grant that would be required | -| P-12 | An upstream extension owning its own space | Recorded as `external`; never reported as drift | - -### D.6 Journeys, generated surfaces, and release - -| Row | Case | Passes when | -| --- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | -| J-1 | Scaffold → add a second same-provider target → add two plugin spaces → plan → apply → deploy | No manual step and no hand-edited generated file | -| J-2 | Adopt a populated legacy project | Preflight clean; zero DDL; verify clean | -| J-3 | Generated project type-checks and starts | Unattended | -| G-1 | Generated CLI, help, docs, and agent catalogs | Exactly match the machine operation and diagnostic schemas | -| G-2 | Every generated example | Compiles and runs in CI | -| G-3 | Every diagnostic code | Reachable by a negative test and carries a structured `nextAction` | -| G-4 | No gate asserts on human-readable message text | Enforced | -| C-1 | Full `scaffold.runtime` E2E at cutover | Green | -| C-2 | No legacy remnant | No legacy adapter, generated task, copied fragment, repair script, deep generated import, or compatibility alias remains | -| C-3 | Release-class adoption rehearsal on seeded, production-shaped data | Zero schema/data mutation, with the receipt as evidence | - -## Appendix E: publishability and JSR gates - -`[PROPOSAL]` The prospective audit verdict for the planned surface is -**`PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`**. The six new packages **do not exist**, so -`deno publish --dry-run`, `deno doc --lint`, publish-file inspection, packed install, canary, and -remote-consumer results are currently **N/A** — never recorded as PASS. - -At implementation, each unit requires: - -- one manifest with a scoped name, synchronised version, license, and a concise description; -- an **explicit export map** and an `include` whitelist, with test and fixture exclusions; -- `@module` documentation, a runnable example per entrypoint, and full symbol JSDoc against a 100% - documentation-score target for stable surfaces; -- explicit public declarations satisfying root `isolatedDeclarations`, and **no `--allow-slow-types` - waiver** — no database package inherits the oRPC-only carve-out; -- relative imports within a package (preventing JSR self-referential subpath resolution against an - older published version) and declared specifiers across packages; -- ESM and Deno purity: no CommonJS, no HTTP imports, no top-level filesystem assumptions; -- publishable generated assets as checked-in deterministic TypeScript constants with - regenerate-and-diff freshness gates — runtime file reads and text/JSON import attributes stay - forbidden until an authenticated registry canary proves the limitation resolved; -- `deno doc --lint` with zero diagnostics, `deno publish --dry-run` without slow types, an inspected - publish file list, public import tests, a clean packed consumer install, `quality:scan`, and - `arch:check`. - -W3 additionally requires the exact Prisma import allowlist, exactly one resolved component set, Deno -import purity, and real PostgreSQL conformance before the provider package is advertised at all. W10 -additionally requires release preflight, GitHub OIDC/SLSA provenance, an authenticated canary, -registry settings reconciliation, and the production E2E path against **exact published JSR -versions**. A local dry run or packed install cannot substitute for that remote-graph verdict. - -**Kill or split a surface** if Prisma types leak into a public declaration; if app inference -requires a published slow type; if any unit needs `--allow-slow-types`; if the provider requires -private or deep imports or an upstream re-export; if internal bare self-imports appear; if generated -assets need runtime filesystem access; if a package combines two archetypes; or if a clean remote -consumer resolves duplicate or off-allowlist Prisma components. - -## Appendix F: risk register, kill criteria, and switch criteria - -### Risk register - -| Risk | Mitigation and kill response | -| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | -| Designing to RC marketing or a stale builder screenshot | Pin the source; use the current model-first API; keep exact module paths adapter-local; prove them in the W3 spike. | -| Upstream changes during the RFC or the implementation program | RC/post-RC separation; an exact provider pin and import allowlist; independent provider release cadence; a compatibility-window gate. | -| Replacing glue with a second ORM or a control plane | No query or model DSL; no runtime negotiation; no hosted services; small ports; an explicit refusal boundary. | -| Published slow types or Prisma leakage | App-local inference; no re-export or private imports; isolated declarations; no slow-types waiver; the JSR gates in Appendix E. | -| Native fragment composition widens inference | Two-phase explicit const-preserving generated root; compile-failure soundness fixtures; an editor/type-check budget. | -| A false multi-namespace claim | Withhold the capability until type/runtime parity passes with no casts (D-37). | -| Contract-derived validation overclaims full operations | A bounded algebra, explicit contributors, the runtime/JSON split, and failure at schema construction. | -| A custom codec accepts invalid values | Mandatory representation-specific value schemas; encode/decode is not validation. | -| Stale or half-published artifacts | Full canonical digest; atomic staged publication; facet identity; runtime and apply mismatch refusal. | -| Plugin removal destroys data | `retain` by default; archive/drop only through a conditional destructive plan; no directory-delete semantics anywhere. | -| Provider spaces mistaken for portability | PostgreSQL-only certification; explicit unsupported targets; a native capability surface. | -| An apply exit code masks partial work | Typed per-target and per-space outcomes; immutable checkpoints; `outcome-unknown`; inspect-before-resume. | -| Cross-target atomicity or rollback implied | Saga language only; no global transaction; complete partial-success receipts. | -| Mutable receipts become shadow state | The provider ledger remains the authority; receipts are append-only evidence. | -| A no-compatibility cutover causes data loss | Ownership preflight; marker-only adoption; a zero-DDL rehearsal; forward recovery; a parallel release line only. | -| The JSR plan is mistaken for readiness | Explicit `N/A` now; per-package dry-run, docs, packed, canary, and remote E2E receipts required later. | -| The RFC's breadth becomes unimplementable | Exact packages; W0–W11 dependencies; per-wave exits; kill and switch criteria. | -| Agent and documentation drift | Generate from the operation catalog and manifest; execute every example in CI. | -| CI stays long or flaky | Pure offline paths; digest caching; bounded real-service stages; atomic structured receipts; defined measurements instead of promised percentages. | -| The upstream seam moves during the RFC's own authoring window | Already observed `[POST-RC]`. Contained structurally by the one-package, one-facade, allowlisted, independently-versioned adapter. | -| An implementation-time decision silently widens support | Every withheld capability names its gate; a claim without a passing conformance row is a conformance failure. | - -### Kill and switch criteria - -#### Kill only the Prisma adapter - -`[PROPOSAL]` Keep the provider-neutral kernel and do not publish or switch to Prisma 8 if, at the -adoption pin, any of these hold: - -- Deno runtime or import purity requires vendoring or textually patching upstream. -- Packed provider artifacts cannot publish or install without slow-type or duplicate-component - failures. -- Native TypeScript authoring cannot preserve app-local inference through a stable public builder - seam without casts, private imports, or copied overloads. -- Contract emission cannot be deterministic and atomically installed. -- Programmatic control cannot produce enough structured information to bind plans, verify outcomes, - and avoid terminal-text parsing. -- PostgreSQL marker and ledger advancement cannot be proven safe with migration effects. -- Contract spaces cannot prove disjoint ownership and package-free apply for an app plus plugins. -- Required runtime lifecycle, transaction, error, or cancellation behaviour fails against real - PostgreSQL. -- Upstream changes the contract format without a viable migration path more than once before - NetScript's first stable adapter release. - -Switching to a different provider adapter happens only after it passes the same conformance suite. -**Prisma 7 compatibility is never reopened.** - -#### Narrow or kill a subsystem - -- If full-operation Standard Schema derivation would require reproducing Prisma's phantom type - system, keep only model-value and known-result validation plus explicit contributors. This - narrowing is already the plan, not a failure. -- If runtime interpretation misses cold-start budgets, test AOT equivalence; if equivalence fails, - retain runtime interpretation and require explicit schemas at the affected boundary rather than - shipping a divergent mirror. -- If provider-generic capability types start growing into query abstractions or negotiation, delete - them and keep literal static tags. -- If contribution archive or drop cannot be verified, ship detach-and-retain only. -- If the public provider SPI starts changing to accommodate hypothetical providers before a second - adapter exists, revert to the smallest Prisma-exercised seam and defer generalisation. -- If the optional policy factory needs a cast, a private import, or a copied overload, delete it and - keep Candidate A. - -#### Reopen the architecture - -`[PROPOSAL]` Reopen this RFC — not merely an adapter — only if implementation proves that a -deterministic manifest cannot express one target/space composition without depending on live state; -that app-local type binding necessarily becomes a published framework slow type; that target -identity cannot remain provider-independent; or that ownership and history cannot remain separate -from query and runtime types. - -## Appendix G: run provenance, slice trace, and review surface - -### Provenance - -| Field | Value | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| Run | `docs-database-architecture-rfc--prisma-8-rfc` | -| Branch | `docs/database-architecture-rfc` | -| NetScript baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | -| Prisma RC pin | `v8.0.0-rc.1` @ `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` | -| Prisma post-RC pin | `71e2e0d9ee1f306b5a11435cd1973023cb33866a` | -| Research index | [`research.md`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md) | -| Plan and decisions | [`plan.md`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md) | -| Plan gate | [`plan-eval.md`](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md) — cycle 2 `PASS` at commit `383170bbc` | -| Historical evidence | [issue #313](https://github.com/rickylabs/netscript/issues/313), carried as problem evidence only | - -### Eight-slice trace - -| Slice | Scope | State in this document | -| ----- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | -| 0 | Harness bootstrap and draft review surface | Summarised in this appendix; not rewritten here | -| 1 | Research corpus, current-main rebaseline, prospective JSR audit, plan lock | Summarised; the corpus is cited as a claim index, with primary sources carried into Appendix B | -| 2 | Independent PLAN-EVAL accepts the locked plan | Cycle 1 `FAIL_PLAN` on one factual-integrity defect (the generated-task count); cycle 2 `PASS`. **Final Plan-Gate cycle; no further PLAN-EVAL.** | -| 3 | Vocabulary, package graph, public APIs, TypeScript/E2E types, validation, operations, spaces, targets, state machines, refusal boundaries | [Reference-level explanation](#reference-level-explanation) and its subsections | -| 4 | Adoption, clean cutover, data safety, waves, conformance, CI/JSR/release gates, market implications, risks, kill/switch criteria | Breaking changes and migration; Prior art; Appendices C–F | -| 5 | Focused and adversarial post-draft reviews | The disposition surface below | -| 6 | Implementation-grade completeness review and author/editor dispositions | Recorded in the same disposition surface. **Not another PLAN-EVAL, and it does not restart planning.** | -| 7 | One final substantive refinement, then mechanical checks only | Reserved; the reviewer is named below | - -### Post-draft review and disposition surface - -`[PROPOSAL]` The post-draft sequence is fixed and ordered. There is no generic additional -focused-review party and there are no further plan-evaluation cycles. - -| Order | Reviewer | Scope | State at draft time | -| ----- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -| 1 | Root (personal review) | Source, doctrine, and API review of the complete draft | Pending | -| 2 | Qwen 3.8 Max | Focused review across TypeScript inference, Standard Schema, control and recovery, migration safety, package/JSR surfaces, and market claims | Pending | -| 3 | Grok 4.6 high | Whole-RFC adversarial review | Pending | -| 4 | Author/editor | Explicit disposition of every finding, then revision | Pending | -| 5 | Fable 5 high | The absolute final substantive review and refinement. **Nothing substantive follows it** — only mechanical checks and publication. | Pending | - -Findings are recorded here as they arrive, one row each, and no finding is closed without an -explicit disposition: - -| Finding | Reviewer | Severity | Claim | Disposition | Section changed | -| ------------------------------------------------------- | -------- | -------- | ----- | ----------- | --------------- | -| _None recorded yet — this draft has not been reviewed._ | — | — | — | — | — | - -Disposition vocabulary: **accepted** (the RFC changed, and the section is named), **narrowed** (a -capability was withheld or a claim weakened), **declined with reason** (the RFC did not change, and -the reason is recorded), or **deferred to a wave** (the question is real but is an -implementation-time decision, and it is added to [Unresolved questions](#unresolved-questions) with -its owning wave). A declined finding still records the reviewer's claim verbatim. +Natural extensions this architecture enables and this RFC deliberately excludes: + +- **A second certified provider**, proving the narrow provider SPI with a real adapter when demand + and maturity exist — never with a speculative fallback built to prove a port. +- **The multi-namespace capability**, **archive/drop retirement**, and **AOT validation**, each + released by its gate (upstream type parity, provider conformance, corpus equivalence) rather than + by a workaround. +- **A policy-applied authoring factory** that pre-applies naming and control defaults and forwards + the provider's exact composed helpers — revisitable once the thin surface has shipped, and only if + it needs no cast, private import, or copied overload. +- **Delivery-backend adapters** exporting plans, receipts, and diagnostics to Atlas, Bytebase, or a + hosted approval system — as adapters over stable artifacts, never a local reimplementation. +- **Deeper agent capability**: an allowlisted operation surface with policy metadata derived from + the catalog, so an agent gets structured operations rather than unrestricted query access. +- **Additional first-party spaces** beyond auth, workers, sagas, triggers, and streams, and + **read-replica-aware routing helpers** if a concrete need appears — as composition affordances, + never a hidden router that could silently send a write to a reader. -[ns-98]: https://github.com/rickylabs/netscript/pull/98 -[ns-145]: https://github.com/rickylabs/netscript/pull/145 -[ns-173]: https://github.com/rickylabs/netscript/issues/173 [ns-1014]: https://github.com/rickylabs/netscript/issues/1014 [ns-1059]: https://github.com/rickylabs/netscript/pull/1059 -[ns-1088]: https://github.com/rickylabs/netscript/pull/1088 -[ns-1196]: https://github.com/rickylabs/netscript/issues/1196 -[ns-1202]: https://github.com/rickylabs/netscript/issues/1202 -[ns-1254]: https://github.com/rickylabs/netscript/issues/1254 -[ns-1290]: https://github.com/rickylabs/netscript/issues/1290 -[ns-1295]: https://github.com/rickylabs/netscript/issues/1295 -[ns-1301]: https://github.com/rickylabs/netscript/pull/1301 -[ns-1310]: https://github.com/rickylabs/netscript/issues/1310 -[ns-1311]: https://github.com/rickylabs/netscript/pull/1311 -[ns-1327]: https://github.com/rickylabs/netscript/issues/1327 -[ns-1393]: https://github.com/rickylabs/netscript/pull/1393 [rc1-release]: https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1 [rc1-readme]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/README.md [rc1-scorecard]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/scorecard.md -[rc1-versions]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/Supported%20Versions.md -[adr-176]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20176%20-%20Data%20migrations%20as%20invariant-guarded%20transitions.md [adr-212]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20212%20-%20Contract%20spaces.md -[pn-261]: https://github.com/prisma/prisma-next/pull/261 -[pn-27ccefc3]: https://github.com/prisma/prisma-next/commit/27ccefc3 -[pn-e1e5ab2c]: https://github.com/prisma/prisma-next/commit/e1e5ab2c [pn-3dc98cb]: https://github.com/prisma/prisma/commit/3dc98cb -[pn-d0c8333]: https://github.com/prisma/prisma/commit/d0c8333 -[pn-15308c6]: https://github.com/prisma/prisma/commit/15308c6 -[pn-92b6ee3]: https://github.com/prisma/prisma/commit/92b6ee3 -[pn-c4a5875]: https://github.com/prisma/prisma/commit/c4a5875 -[pn-5d4a4db]: https://github.com/prisma/prisma/commit/5d4a4db -[pn-a900bc1]: https://github.com/prisma/prisma/commit/a900bc1 -[pn-71e2e0d]: https://github.com/prisma/prisma/commit/71e2e0d9ee1f306b5a11435cd1973023cb33866a [pn-29896]: https://github.com/prisma/prisma/issues/29896 -[pn-29923]: https://github.com/prisma/prisma/issues/29923 -[pn-29932]: https://github.com/prisma/prisma/issues/29932 -[pn-29944]: https://github.com/prisma/prisma/pull/29944 -[pn-30009]: https://github.com/prisma/prisma/pull/30009 - - - -[wasp]: https://wasp.sh/docs/data-model/databases -[redwood]: https://docs.redwoodjs.com/docs/data-migrations -[payload]: https://payloadcms.com/docs/database/overview -[better-auth]: https://better-auth.com/docs/beta/guides/create-a-db-adapter -[lucid]: https://lucid.adonisjs.com/docs/migrations -[drizzle]: https://orm.drizzle.team/docs/migrations -[mikroorm]: https://mikro-orm.io/docs/architecture -[kysely]: https://www.kysely.dev/ -[flyway]: https://documentation.red-gate.com/flyway/reference/commands + + + [flyway-repair]: https://documentation.red-gate.com/flyway/reference/commands/repair -[liquibase]: https://docs.liquibase.com/community/user-guide-5-0-2/what-is-the-databasechangelog-table -[tf-state]: https://developer.hashicorp.com/terraform/language/state [tf-targeting]: https://developer.hashicorp.com/terraform/tutorials/state/resource-targeting -[pulumi-state]: https://www.pulumi.com/docs/iac/concepts/state-and-backends/ [pulumi-interrupted]: https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/ -[atlas-projects]: https://atlasgo.io/atlas-schema/projects -[bytebase-plan]: https://docs.bytebase.com/change-database/plan -[bytebase-3140]: https://docs.bytebase.com/changelog/bytebase-3-14-0 -[zenstack-multifile]: https://zenstack.dev/docs/modeling/multi-file [zenstack-zod]: https://zenstack.dev/docs/utilities/zod [django-multidb]: https://docs.djangoproject.com/en/5.2/topics/db/multi-db/ -[rails-multidb]: https://guides.rubyonrails.org/active_record_multiple_databases.html From be83301c6b73da3d82a0f94141fe6c30a74de0b0 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 21:30:39 +0200 Subject: [PATCH 11/19] docs(rfc): record focused Qwen review --- .../briefs/grok-rfc-adversarial-review.md | 219 ++++++++++++++++++ .../briefs/qwen-rfc-focused-review.md | 92 ++++++++ .../context-pack.md | 50 ++-- .../reviews/qwen-rfc-focused-review.md | 83 +++++++ .../reviews/root-rfc-review.md | 35 ++- .../supervisor.md | 31 ++- .../worklog.md | 71 ++++-- 7 files changed, 543 insertions(+), 38 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/grok-rfc-adversarial-review.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-rfc-focused-review.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/grok-rfc-adversarial-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/grok-rfc-adversarial-review.md new file mode 100644 index 0000000000..2ad72b6c53 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/grok-rfc-adversarial-review.md @@ -0,0 +1,219 @@ +# use harness — Grok 4.6 whole-RFC adversarial review + +You are an independent, bounded adversarial reviewer of NetScript's database architecture RFC. You +are not its author, editor, implementer, or final acceptance gate. + +## SKILL + +Use the NetScript harness discipline for this review. Preserve generator/reviewer separation, +requested-versus-observed route identity, read-only scope, evidence-backed findings, and a bounded +output. Do not invoke another skill, workflow, model, agent, or reviewer. + +## Route and checkpoint + +- Requested route: OpenCode via OpenRouter, model `openrouter/x-ai/grok-4.6`, variant `high`. +- Review the compact RFC checkpoint `5dfc4e8eb` + (`docs(rfc): consolidate database architecture + draft`). This is a post-draft adversarial review, + not final acceptance. +- Verify the evaluated RFC bytes against `5dfc4e8eb`. If the worktree RFC differs, review the exact + checkpoint with read-only Git inspection and report the mismatch; do not review an uncommitted + replacement silently. +- If the requested route cannot be observed or the observed model/variant differs, return + `ROUTE_BLOCKED` with the requested and observed identity. Do not simulate Grok or continue on an + alternate model. + +## Hard boundaries + +- Do not edit, create, delete, or format any repository file. +- Do not commit, push, open or update a PR, post comments, or mutate external state. +- Do not spawn subagents, child sessions, teams, workflows, background agents, or alternate models. +- Do not ask another agent to verify claims. Work as one Grok parent session. +- Read-only shell and focused source inspection are allowed. Do not run mutation, generation, + migration, database, network-deployment, or broad test commands. +- Do not turn this into a new research report or redesign the whole framework. Test whether the RFC + is coherent, safe, implementable, and economical on its own terms. +- Return the complete review in the final response. The supervisor will persist and disposition it. +- Maximum output: **2,500 words**, including tables and receipt. + +## Required complete reading + +Read these files completely, not summaries or selected line ranges: + +1. `rfcs/0000-database-architecture.md` +2. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +3. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +4. If present at launch time, + `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md`; if + the expected path is absent, read any single `reviews/qwen*rfc*review*.md` artifact that exists + and record its exact path. If no Qwen focused-review result exists, record `not present` and + continue independently. + +The plan is the locked decision and implementation-gate context. The root and optional Qwen reviews +are attack maps, not authority: independently verify their relevant claims and do not echo findings +without confirming that the checkpoint still contains the problem. + +For a disputed, load-bearing statement only, you may inspect the already available research corpus +or pinned Prisma RC source. Distinguish Prisma 8 RC1 fact, post-RC observation, current NetScript +fact, and RFC proposal. Do not browse broadly or restate source audits. + +## Review objective + +Attempt to falsify the RFC as one architecture. Look for contradictions between examples, +interfaces, invariants, provider claims, artifact roles, operation states, ownership rules, and +implementation waves. A finding is actionable only when it identifies a concrete RFC correction, +deletion, clarification, or implementation gate. Do not manufacture findings to appear adversarial. + +Review all seven axes below. + +### 1. Abstraction integrity + +- Is there exactly one coherent path from native schema authoring through definition, contract + artifact, manifest, generated binding, runtime, validation, operation plan, ledger, and receipt? +- Do definition, artifact, manifest, plan, provider ledger/marker, and immutable receipt retain + distinct authority and identity? +- Does any example make a downstream stage consume an upstream authoring value that the reference + architecture says it must not consume? +- Are pure compilation, live inspection, mutation, verification, and recovery structurally separated + rather than distinguished only by convention? + +### 2. Provider-neutral kernel versus Prisma leakage + +- Does the kernel express only provider-neutral identities, capabilities, ports, operation states, + and artifacts while the first certified adapter remains Prisma 8/PostgreSQL? +- Does native Prisma `defineContract(scaffold, callback)` remain the schema authority without a + NetScript schema/query DSL, copied overloads, private imports, re-exported builder, or + type-erasing wrapper? +- Are provider-specific query, transaction, codec, migration, and contract types confined to the + adapter/generated app-local boundary? +- Does “provider-neutral” describe an extensible kernel rather than falsely claiming portable query + semantics or feature parity across providers? + +### 3. Artifact authority, control, and recovery safety + +- Can every mutating operation identify its closed target set, exact manifest/contract inputs, + inspected baseline, executable plan, signature/expiry/staleness state, lock/fencing ownership, + provider ledger transition, and immutable receipt? +- Are partial success, no-success, unknown outcome, resume, idempotency, lookup, and verification + representable without guessing? +- Can recovery work after the original process and plugin package are absent? +- Does adoption preserve data and avoid silent target omission, accidental DDL/DML, unproved marker + removal, or rollback promises that a provider cannot guarantee? + +### 4. Plugin, multi-space, and multi-database extensibility + +- Is one owner responsible for every persistent object and migration history? +- Are plugin-owned spaces independently versioned and deployable from pinned artifacts, while + application-local fragments remain const-preserving native values composed in two phases? +- Are augmentation permissions explicit and collision/ownership checked? +- Do extension authoring, control, runtime, and validation facets share one verified identity and + version? +- Are `TargetId`, `SpaceId`, physical namespace, provider, resource, contract hash, and migration + head distinct? Are cross-space and cross-database references treated differently? +- Does the first adapter refuse uncertified multi-namespace behavior and physical collisions rather + than masking them? + +### 5. Public API, developer experience, and type safety + +- Can an implementer reconcile all imports, symbol roles, generics, generated files, lifecycle + calls, and error behavior into one implementable API? +- Does exact native contract inference survive into the app-local binding without casts, widening, + private imports, or phantom NetScript mirrors? +- Are transaction types honest, target-key checking placed at the composition point, and extension + helper availability target/pack-sensitive? +- Is Standard Schema validation selection-aware, `runtime | json`, bounded by explicit metadata, and + fail-closed at construction without pretending full Prisma operation parity? +- Does the normal path eliminate manual copying, generation repair, repeated extension wiring, and + Aspire-dependent pure work? + +### 6. Implementation feasibility and release gates + +- Do package boundaries and dependency directions permit the shown API without circular or forbidden + dependencies? +- Are W0–W11 ordered so each wave has the inputs and proof needed by the next? +- Are Prisma RC volatility, contract decoding, multi-namespace type gaps, custom codec predicates, + operation metadata, type-check performance, and prospective JSR constraints gated rather than + wished away? +- Are kill/switch criteria strong enough to narrow or stop an unsound implementation? +- Can the proposed conformance suite prove the public claims without relying on the implementation's + own types or permissive decoders? + +### 7. Editorial economy + +- Does each section make or constrain a decision, API, invariant, refusal, migration guarantee, or + unresolved gate? +- Identify duplicated proof, repeated refusals, process detail, speculative future work, oversized + declarations, and market/upstream prose that can become links. +- Prefer correction by replacement or deletion. Any proposed addition must name an equal or larger + deletion. +- The RFC is 11,205 words at the checkpoint. Propose a **net reduction**, targeting at most 10,000 + words without deleting public APIs, safety invariants, explicit refusals, or clean-break/data-safe + adoption guarantees. + +## Severity and disposition law + +Use stable finding IDs `GR-01`, `GR-02`, and so on, ordered by severity. + +- **blocker**: permits data loss/corruption, breaks an authority or ownership invariant, makes the + public API/type promise unimplementable, introduces hidden Prisma coupling into the neutral + kernel, contradicts the clean break, or makes apply/recovery unsafe. +- **refinement**: improves precision, coherence, implementability, DX, or economy without changing + the accepted architecture. + +Do not upgrade editorial preference to a blocker. Do not recommend backward compatibility, Prisma 7 +fallback, dual runtime, a second schema/query DSL, a global registry/service locator, hosted control +plane, casts/private imports, permissive validation, false provider parity, destructive uninstall, +or silent target subsets. + +## Required output contract + +Return one concise Markdown document in this order: + +### Route receipt + +Include requested and observed provider/model/variant, OpenCode session identifier if exposed, +evaluated commit and RFC byte identity, every required file actually read, optional Qwen artifact +status/path, any extra source path inspected, and explicit confirmation that no subagent was used. + +### Verdict + +Use exactly one: + +- `PASS` — no actionable blocker or refinement remains; +- `PASS_WITH_REFINEMENTS` — no blocker; bounded corrections/deletions remain; +- `REVISE_BLOCKERS` — one or more blockers must be dispositioned before final refinement; +- `ROUTE_BLOCKED` — requested route identity could not be proved. + +Give a two-sentence rationale and counts by class. + +### Findings + +Provide one table with: + +| ID | Class | Axis | RFC lines | Violated invariant/decision | Consequence | Smallest correction | Offset deletion | +| -- | ----- | ---- | --------- | --------------------------- | ----------- | ------------------- | --------------- | + +Use only `blocker` or `refinement` in `Class`. Every addition must identify an equal-or-larger +offset deletion. If there are no findings, say so; do not invent one. + +### Axis verdicts + +For all seven axes, give `PASS` or `FAIL`, the strongest negative evidence tested, and the result. +Do not fill this section with praise. + +### Net deletion ledger + +Name concrete RFC sections/line ranges, estimated removable words, and why removal preserves the +decision. Sum additions and deletions and report the expected **net word change**. The proposal must +be net negative; target at least 1,205 words of net reduction when this can be done without +weakening the architecture or safety contract. Also list content that must not be cut. + +### Sound claims not to reopen + +List only claims you actively checked and found sound. This prevents later editors from reopening +settled architecture without new evidence. + +### Final gate statement + +End with one line stating whether the RFC may proceed to author/editor disposition. Do not claim +final acceptance; the owner-directed Fable 5 high refinement remains the last substantive gate. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-rfc-focused-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-rfc-focused-review.md new file mode 100644 index 0000000000..aa54fd3596 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-rfc-focused-review.md @@ -0,0 +1,92 @@ +# Qwen 3.8 Max — focused review of the consolidated database RFC + +You are the owner-directed focused reviewer, not the author. Work in +`/home/codex/repos/netscript-db-rfc` on branch `docs/database-architecture-rfc` at commit +`5dfc4e8eb`. + +Use one parent session only. Do not spawn children, subagents, teams, workflows, background agents, +or alternate models. Do not edit any file, commit, push, or comment on GitHub. Read-only shell and +source inspection are allowed. Return the complete review in your final response; the root will +persist it. + +## Required reading + +Read completely: + +1. `rfcs/0000-database-architecture.md` +2. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +3. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +4. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md` +5. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md` +6. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +7. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` +8. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md` + +Use the pinned Prisma checkout at `.llm/tmp/prisma-v8-rc1` only for a disputed load-bearing claim. +Distinguish RC1 evidence from post-RC evidence. Do not turn the review into another research report. + +## Owner's editorial law + +The owner will not read an 18,000-word book. The RFC is now 11,205 words after a 60% reduction. Its +final target is at most 10,000 words when cuts preserve the public API, safety invariants, and +explicit refusals. Prefer links to the research corpus over duplicated proof. Every suggested +addition must name an equal or larger deletion; otherwise recommend no addition. + +The center of gravity must remain: + +- end-goal API surface and developer journey; +- exact end-to-end TypeScript inference from native Prisma contract to app-local binding; +- contract-first canonical artifacts and the `DatabaseManifest` join point; +- bounded, fail-closed Standard Schema input/output validation; +- full plugin-space ownership, application-local fragments, controlled augmentation, and one + extension bundle fanning into authoring/control/runtime/validation; +- deterministic operations, plan/apply/receipt/recovery, and data-safe clean-break adoption. + +## Six review axes + +Review only these six axes. Falsify the examples and invariants rather than merely summarizing them. + +1. **TypeScript inference and API coherence** — native model-first Prisma surface, const/literal + preservation, target-key checking, generated `AppBinding`, transaction type honesty, import + subpaths, absence of type widening/private imports/re-export/query DSL, and whether every example + is one implementable API rather than pseudocode with incompatible symbol roles. +2. **Standard Schema and trust boundaries** — `input`/`output` semantics, `runtime | json`, exact + metadata requirements, codec/space/selection identity, fail-closed construction, path-rich value + issues, mandatory external boundaries, no claim of full Prisma operation parity, and no generated + validator repair pipeline in disguise. +3. **Control, recovery, and artifact authority** — pure/live/mutating separation, manifest as + durable downstream join point, provider ledger versus receipt, plan signing/expiry/staleness, + lock and fencing claims, unknown outcome, lookup/resume, multi-target aggregate outcomes, + explicit target closure, and CLI/docs/agent projection from one catalog. +4. **Migration and plugin safety** — one owner per object, space independence, plugin package-free + apply/verify, augmentation permissions, default-namespace collision refusal, detach-retain, + marker-only adoption, no silent target subset, rollback wording, no dual runtime or compatibility + path, and no accidental data mutation claim. +5. **Package and prospective JSR surface** — exact A1/A4/A3/A2/A2/A6 graph, dependency directions, + provider isolation, public subpaths, application-local generated typing, `isolatedDeclarations`, + no slow-type waiver, no unearned actual-publish-readiness claim, and whether any API example + forces a forbidden dependency or runtime authoring import. +6. **Market/upstream claims and reader economy** — only load-bearing claims, direct official links, + RC1 versus post-RC wording, no comparator straw man, no marketing overclaim, and concrete cuts to + reach at most 10,000 words without removing decisions. + +## Required output + +Return a concise Markdown review, maximum 2,500 words, with: + +- route receipt: requested model `qwen/qwen3.8-max`, requested effort `max`, evaluated commit, files + actually read, and whether any Prisma source path was inspected; +- verdict: `PASS`, `PASS_WITH_CHANGES`, or `REVISE`; +- findings table ordered by severity, each with stable id `QF-01...`, severity + `critical|high|medium|low`, exact RFC line(s), violated decision/invariant, why it matters, and + the smallest correction; +- a six-axis pass/fail table including negative evidence, not praise; +- a deletion ledger identifying at least 1,200 removable words by section/line range, while naming + any content that must not be cut; +- a final list of claims checked and found sound, so later editors do not reopen them without new + evidence. + +Do not propose backward compatibility, a second query/model DSL, a Prisma 7 fallback, a global +registry, a hosted control plane, false multi-provider parity, casts/private imports, or permissive +validation. A finding is actionable only if it can change the RFC or an explicit implementation +gate. Do not manufacture findings to appear adversarial. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index a20a922951..076adabf3c 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -15,9 +15,11 @@ A clean-break database architecture RFC run is active. Issue #313 is historical evidence; its compatibility-first solution is superseded. Native Fable 5 medium PLAN-EVAL cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` passed commit `383170bbc`. Native Claude Code Opus 5 high -authored an evidence-complete 28,194-word raw draft, pushed as `05e5fbac2`. Root substantive review -returned `REVISE_CONSOLIDATE`: the reader-facing RFC must be reduced to 8,000–10,000 words (12,000 -hard ceiling) and apply findings R1–R10 before external post-draft review. Current-main commit +authored an evidence-complete 28,194-word raw draft, pushed as `05e5fbac2`. Opus 5 high +consolidation session `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` resolved root findings R1–R10 and +reduced it to 11,205 words. Root read the entire compact RFC, added three narrow correctness fixes, +and pushed it as `5dfc4e8eb`. Qwen 3.8 Max reviewed that frozen commit without edits and returned +`PASS_WITH_CHANGES`; QF-01–QF-05 remain open. It is not finally accepted. Current-main commit `01e096049` remains nonblocking CI/gate-tooling drift. ## Completed @@ -31,21 +33,31 @@ hard ceiling) and apply findings R1–R10 before external post-draft review. Cur workspace, and obtained cycle 2 `PASS`. - Authored and pushed the evidence-complete raw RFC draft. - Completed root personal source/doctrine/API review and wrote the Opus consolidation contract. +- Completed the Opus 5 high consolidation from 28,194 to 11,205 words and resolved R1–R10. +- Clarified that runtime consumes the manifest rather than `DatabaseDefinition`, kept artifact/value + authority explicit, and restricted `partial-success` to mixed target outcomes. +- Root read the complete compact RFC and accepted commit `5dfc4e8eb` for focused review after + targeted fmt, `docs:links`, and diff checks passed. +- Completed the 2,181-word Qwen focused review through requested/observed `qwen/qwen3.8-max`, effort + `max`, session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`. It made no edits and returned + `PASS_WITH_CHANGES` with QF-01 high, QF-02 medium, and QF-03–QF-05 low. +- Qwen passed architecture/type model, Standard Schema boundary, control/recovery, migration/plugin + safety, and market/upstream claims. Its narrow failures affect TypeScript/API examples and one + package/dependency example only. ## In Progress -- Slice 3 canonical RFC consolidation and technical correction by a fresh Opus 5 high authoring - session. +- Grok 4.6 high whole-RFC adversarial review. The RFC remains frozen at 11,205 words and the run + remains in `rfc-authoring`; Qwen findings have not yet been dispositioned. ## Next Steps -1. Consolidate the raw RFC to 8,000–10,000 words and resolve root findings R1–R10. -2. Root reviews and signs off the consolidated reader-facing draft. -3. Run Qwen 3.8 Max as the focused post-draft review. -4. Run Grok 4.6 high as the whole-RFC adversarial review. -5. Apply author/editor dispositions for every actionable finding. -6. Run one final Fable 5 high substantive refinement. -7. Run mechanical checks only, then commit/push and update the PR trail. +1. Run Grok 4.6 high as the whole-RFC adversarial review. +2. Use Opus for author/editor dispositions and consolidation of Qwen/Grok findings. Qwen's + approximately 1,240-word deletion ledger projects approximately 9,965 words but its named + must-not-cut contracts remain mandatory. +3. Run one final Fable 5 high substantive refinement. +4. Run mechanical checks only, then commit/push and update the PR trail. ## Key Decisions @@ -64,17 +76,19 @@ hard ceiling) and apply findings R1–R10 before external post-draft review. Cur ## Gates -| Gate family | Current status | Evidence | -| ----------- | -------------- | ----------------------------------- | -| Static | pending | Bootstrap inspection follows. | -| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | -| Runtime | N/A | Docs-only RFC run. | -| Consumer | revise | Root review requires consolidation. | +| Gate family | Current status | Evidence | +| ----------- | -------------- | ------------------------------------ | +| Static | PASS | Compact RFC fmt, `docs:links`, diff. | +| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | +| Runtime | N/A | Docs-only RFC run. | +| Consumer | changes open | Qwen `PASS_WITH_CHANGES`; Grok next. | ## Open Questions - No must-resolve-now architecture decision remains; pre-implementation decisions stay assigned to their W1/W3/W4/W5/W7/W10 gates. +- QF-01–QF-05 are review findings, not reopened architecture decisions; they await author/editor + disposition after Grok. ## Drift and Debt diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md new file mode 100644 index 0000000000..1edc793cf4 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md @@ -0,0 +1,83 @@ +# Qwen 3.8 Max — focused review: database architecture RFC + +## Route receipt + +| Field | Value | +| --- | --- | +| Requested model | `qwen/qwen3.8-max` | +| Requested effort | `max` | +| Evaluated commit | `5dfc4e8eb` (`docs/database-architecture-rfc`); RFC file verified byte-identical to commit | +| Files read completely | `rfcs/0000-database-architecture.md` (11,205 words); run `plan.md`; `reviews/root-rfc-review.md`; `research/typescript-schema-orpc-audit.md`; `research/runtime-validation-source-audit.md`; `research/prisma-8-deep-dive.md`; `research/market-analysis.md`; `research/planned-jsr-audit.md` | +| Prisma source inspected | **Yes** — pinned checkout `.llm/tmp/prisma-v8-rc1`, verified at tag `v8.0.0-rc.1` (commit `a76a6c5`). Paths read: `packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:630-704`; `packages/3-extensions/postgres/src/contract/define-contract.ts:40-125`; `packages/2-sql/1-core/contract/src/types.ts:85-140, 200-220`; `packages/9-public/@prisma/orm-postgres/package.json` (export count). All inspections are **RC1 evidence**; no post-RC object was needed — the RFC's post-RC statements are correctly labeled as churn enumeration and were checked against the deep-dive's labeled post-RC table only. | +| NetScript source inspected | `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:40-109`; doctrine `06-archetypes.md:209`, `02-public-surface.md:217-231`, `09-anti-patterns-and-fitness-functions.md:165` | + +## Verdict: `PASS_WITH_CHANGES` + +No decision, invariant, or refusal in D-01–D-47 is violated; the five findings are example-level and wording-level. One high finding (a flagship example that is not executable as written) must be fixed before the final refinement pass. + +## Findings + +| ID | Sev | RFC line(s) | Violated decision/invariant | Why it matters | Smallest correction | +| --- | --- | --- | --- | --- | --- | +| QF-01 | high | 309–310; consumed at 324, 334, 371–373 | Example-status block (169–171: `@netscript/*` examples "executable exactly as written"); one implementable API | `primary.binding.ts` shows `export declare const primaryBinding: AppBinding<…>` and `export declare const PRIMARY_MANIFEST_DIGEST` — ambient declarations emit **no runtime value**. But `primaryBinding` is imported as a value and called: `runtime.bind(primaryBinding)` (334) and `primaryBinding.ref({space:'app'}).model('User')` (371–373), and the digest is load-bearing for startup refusal (713–714). As written the module exports nothing and the imports throw at link time — the generated-binding example, the RFC's center of gravity, is pseudocode with incompatible symbol roles. | Rewrite the generated file as an emitted value module (e.g. the emitter constructs `primaryBinding` and the digest constant), or split into a `.d.ts` plus a runtime module the composition root imports. ≤3 example lines; no API change. | +| QF-02 | medium | 492–507 vs 661–665 | Dependency law: "only the adapter imports Prisma runtime or control modules"; application/plugin modules may import only the public **authoring** builder | The Step 7 extension bundle carries `control` and `runtime` facets. If the bundle is authored in app/plugin code as the example implies, that code must import Prisma `/control` and `/runtime` modules — forbidden by the RFC's own law. The RFC never says where `defineDatabaseExtension` bundles are defined, so the example can force a forbidden dependency (an implementation-gate question for the W3 import allowlist). | One sentence: extension bundles are defined by the adapter/extension-pack publisher inside the controlled build (facets opaque to consumers), or explicitly widen the law to allow controlled-build extension modules the public facet subpaths under the W3 allowlist. | +| QF-03 | low | 331, 335, 520–531 | Example-status "executable exactly as written" | The composition-root and control-journey examples (both presented as complete files with `@netscript/*` imports) leave `connections`, `runId` (×4), and `policy` unbound; `AccountStore`/`PrismaAccountStore` are prose-explained but not marked elided. Undercuts the executability claim the RFC makes of itself. | Declare the values (`const runId = …`, `const connections = fromEnv(…)`, `const policy = …`) or mark elisions with a comment. ~4 lines. | +| QF-04 | low | 181 | Claim attribution discipline | `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121` is a path in the **Prisma** checkout but appears in the guide without attribution; every other citation in the section is a NetScript repo path. A reader will look for it in this repo. | Prefix "Prisma RC1" or link the deep dive. One phrase. | +| QF-05 | low | 899–901 | Audit-faithful wording (runtime-validation-source-audit §3/§4) | "Prisma's own Standard Schema usage validates codec parameters rather than model values, across three representations" conflates two distinct audit facts: `paramsSchema` validates JSON-sourced codec *parameters*; the three representations are *conversion* channels, not all validation channels. The derived conclusion (`runtime \| json` public, wire internal) is unaffected but the sentence overstates its premise. | Split: Prisma validates codec parameters, not model values; its codecs define three conversion representations, of which the driver-wire one stays adapter-internal. | + +## Six-axis verdict + +| Axis | Verdict | Negative evidence | +| --- | --- | --- | +| 1. TypeScript inference & API coherence | **FAIL** | QF-01/QF-03. The type model itself is sound: `defineDatabase`'s `const` generics with `DatabaseSpaceDefinition, unknown>` make `target: 'primry'` error at the right call site (verified against R2's requirement); one 3-parameter generic `(TId, TQuery, TTx)` is used consistently for `AppBinding`/`ProcessTargetSession`; `RequestTargetSession` has no `TTx` and no `transaction`; transaction surface is honestly deferred to W4 (358–363); no widening, private imports, re-export, or query DSL found in any signature. | +| 2. Standard Schema & trust boundaries | **PASS** | `input`/`output` semantics, `runtime \| json`, whole-model `'model'` form, construction-time `DB_VALIDATION_UNSUPPORTED` with coordinates, path-rich issues for invalid values, mandatory external boundaries, cache-key composition, codec value-schema requirement — all match the pinned-source audit. No full-parity claim (58–60, 408–414); no generated-validator repair pipeline (1084 row). Defect: QF-05 wording only. | +| 3. Control, recovery, artifact authority | **PASS** | Pure `createDatabaseControl` has no connection resolver (518–520; structural, not promised); `sign` is pure and lock-free; six-value authority table is disjoint; `outcome-unknown` on transport loss; resume = lookup (append + lookup by `RunId`/`ReceiptId`/resume token, source/sink split allowed); aggregate outcome when no target succeeds is failed/refused/outcome-unknown, never `partial-success` (854–856); every requested target appears with status; plan expiry/staleness/revocation codes present. No silent-subset or atomic-cross-target path found. | +| 4. Migration & plugin safety | **PASS** | One `managed` owner per `ObjectKey`; identical text is still a conflict; physical name collisions refused while the namespace capability is withheld (472–478, 592) — R1 resolved consistently across guide, refusal table, and reference; pinned mirror gives package-free apply/verify with `db.space.skew`; augmentation is grant-closed with explicit denies; detach-and-retain is the only guaranteed removal; adoption is marker-only over an explicitly selected target set with per-target statuses and blocked cutover; rollback row 2 promises marker removal only where provider semantics prove it. No accidental data-mutation claim found. | +| 5. Package & prospective JSR surface | **FAIL** (narrow) | Sole defect is QF-02 (last clause of this axis: whether any example forces a forbidden dependency). Everything else verifies: exact A1/A4/A3/A2/A2/A6 graph matches the plan; `-runtime`/`-control` never import each other or a provider; adapter subpaths are exactly root + `/binding`; inferred typing terminates app-local; `isolatedDeclarations` reasoning for the fragment-publish ban is correct; no slow-types waiver (669–671, 1088); no actual-publish-readiness claim anywhere in the RFC. | +| 6. Market/upstream claims & reader economy | **PASS** | All load-bearing upstream claims carry direct official links; RC1/post-RC separation is maintained (143–156); the 138-export-surface claim and the EA/scorecard claims are RC1-pinned and verified; comparator treatment credits each product before stating the limitation (no straw man); the NetScript row in the market matrix is labeled design-target, and the RFC never claims more. Defect: ~1,200 words of redundancy remain (ledger below). | + +## Deletion ledger (≥1,200 words; no decision, invariant, refusal, or API contract removed) + +| # | Location (lines) | Cut | Words | +| --- | --- | --- | ---: | +| 1 | 1006–1013 | Refusal boundary: delete the no-compat enumeration (restated verbatim at 1126–1131) and the no-re-export clause (restated at 661–665); keep only the no-text-patched-source/no-arbitrary-TS and no-implicit-target clauses | 80 | +| 2 | 1222–1233 | Unresolved questions: compress the implementation-time enumeration to the three largest open decisions (W3 allowlist/namespace; W5/W10 signatures; W10 window) — the full sweep is already linked in the plan (1219–1220) | 115 | +| 3 | 1190–1206 | Prior art: the five adopted lessons are already stated with links at 1092–1113; compress to link + one "no product is a template" sentence; keep the oRPC-precedent sentences (1208–1212) | 95 | +| 4 | 578–584 | "What you stop doing" prose: the eight-item enumeration restates Motivation and earlier guide steps; keep the refusal table and one intro sentence | 65 | +| 5 | 85–102 | Motivation defects: keep the `db add postgres --name analytics` counter-example and the non-atomic conclusion; move `resolveTarget` mechanics (`:66-91`, `PrimaryDatabase`) and the seven-step repair enumeration behind the linked current-state audit | 90 | +| 6 | 127–139 | "That attacks NetScript's pain points at the root" — compress the six-item mirror of Motivation to one clause | 35 | +| 7 | 913–919 | `ValidationIR` coverage paragraph: one sentence naming the supported algebra (the fail-closed inventory at 920–928 already carries the negative half) | 35 | +| 8 | 1115–1118 | Scope-law paragraph: already stated as D-31, summary non-goal (55–57), and alternatives row (1087); reduce to one sentence | 35 | +| 9 | 838–849 | Diagram-teeth prose: drop what the mermaid diagram already encodes (outcome-unknown edge, inspect-before-resume); keep never-replay, checkpoint granularity, lock scope, certified-lock refusal | 45 | +| 10 | 789–794 | Composition-validates prose: keep the determinism gate and "every invariant has a diagnostic"; drop the validation list duplicating guide refusals | 35 | +| 11 | 1053–1056 | Conformance-cost drawback: merge one sentence into the Early-Access drawback | 30 | +| 12 | 1029–1035 | Indirection drawback: drop the closing comparator ("four packages where a less disciplined design would ship one") | 30 | +| 13 | 1024–1028 | Early-Access drawback: mitigation list overlaps 157–163 and the risk register; compress | 30 | +| 14 | 866–870 | Serverless-precedent sentence: compress to a subordinate clause | 30 | +| 15 | 614–620 | Five-values paragraph: the authority table (771–782) re-introduces the same values with roles; shrink to a forward pointer | 30 | +| 16 | 222–225 | "Three things NetScript will not do": restated in summary non-goals, alternatives rows, and refusal boundary; one sentence pointing to alternatives | 45 | +| 17 | 1062–1073 | Why-this-shape: observation 3's operational-gap list is duplicated proof (lives in the deep dive); observation 4 restates 722–723 and 1037–1039 | 65 | +| 18 | 675–677 | Definition-layer wrap intro: overlaps Step 2 prose (276–280) and the contract-identity rule (703–704) | 30 | +| 19 | 741–749 | Two-phase paragraph: trim the phase-1 enumeration, keep the two-phase rationale and the no-registry/no-reduce law | 25 | +| 20 | 852–859 | Saga paragraph: the catalog-projection sentence restates Step 8's opening (510–512); keep freshness-gate/executed-examples clauses | 30 | +| 21 | 55–60 | Summary non-goals second sentence: compress the withheld-capability enumeration (each is detailed in Drawbacks/Unresolved/refusal table) | 25 | +| 22 | 282–290 | Target-key prose: drop the trailing "no fallback chain anywhere" sentence (restated at 1140–1141) | 20 | +| 23 | 1092–1113 | Market lessons: tighten each bullet ~8 words against the linked analysis | 40 | +| 24 | 432–436 | Step 5 isolation enumeration: compress to a pointer at the identity table | 15 | +| 25 | 1264–1267 | Future: policy-factory bullet — removed from v1 narrative per root review; its kill condition restates 1266–1267's own guard | 25 | +| 26 | 1216–1220 | Unresolved opening: trim the locked-topics enumeration | 15 | +| 27 | 1017–1022 | Drawbacks opening: trim ~20 words of restated scope | 20 | +| | | **Total** | **≈1,240** | + +**Must not be cut:** all code blocks except the QF-01 rewrite; the refusal tables (586–599) and refusal boundary pointer; the authority and identity tables; the four inference rules and the soundness-seam paragraph; the namespace paragraph (989–1000); the fail-closed inventory and mandatory-boundary rules; the mermaid diagram (the one retained lifecycle diagram); the adoption step table, pre-cutover list, and rollback table; the alternatives table; the incident table; the operational-journey JSON/error examples; and all direct official links. With these cuts the RFC lands at ≈9,965 words. + +## Claims checked and found sound (do not reopen without new evidence) + +1. `@prisma/orm-postgres` publishes **138** top-level export subpath keys at the RC1 pin (RFC 149–151) — counted from `package.json` at tag `v8.0.0-rc.1`. +2. Authoring type maps lump all models under the default storage namespace and leave non-default namespace table maps empty (`contract-types.ts:644-691`, RFC 990) — verified verbatim; the withheld namespace capability (D-37) rests on accurate evidence. +3. The `defineContract(scaffold, callback)` overload exists with `const` generics preserving returned literal types; the callback receives `ComposedAuthoringHelpers` (RFC 179–182) — verified. +4. SQL field/operation/codec/aggregate type maps are installed under an optional phantom key (`__@internal/sql-contract/typeMaps@__`) — the "not runtime data" premise of bounded validation (RFC 893–896) — verified. +5. `workspace-resolver.ts:51` computes `join('database', provider.dirName)`; `resolveTarget` defaults only when exactly one target is enabled, never consults `NetScript.PrimaryDatabase`, and throws `Unknown database target: (default)` (RFC 86–91); engine selection is a four-engine `switch` (`:97-109`) — all verified against source. +6. Doctrine codifies plain `*.prisma` plugin fragments (A5, `06-archetypes.md:209`) and the oRPC-only slow-types carve-out (`02-public-surface.md:217-231`); AP-24 exists (`09-…:165`) — RFC 92–94, 667–671 are sound. +7. RC1 vs post-RC wording discipline (RFC 143–156) holds; post-RC churn items are correctly attributed as post-tag changes with linked evidence in the deep dive. +8. Root-review corrections R1–R10 are all present and consistent in the committed text (namespace contradiction, target-key location, structural offline control, pure `sign`, one binding generic, validation vocabulary, contribution modes, transaction honesty, receipt lookup, adoption closure). diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md index ee40f5bee9..f8580dde92 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md @@ -1,4 +1,4 @@ -# Root review: raw database architecture RFC +# Root review: database architecture RFC ## Review receipt @@ -21,6 +21,39 @@ Target **8,000–10,000 words**. Hard ceiling **12,000 words**. The final docume an implementer who reads it once and to an owner who wants to decide whether the proposed database story is the right one. +## Consolidated draft receipt + +| Field | Value | +| ---------------- | ------------------------------------------------------------------- | +| Reviewer | Root Codex supervisor | +| Date | 2026-08-13 | +| Evaluated commit | `5dfc4e8eb` | +| Authoring lane | Native Claude Code `claude-opus-5`, high, session `de518f07-68e0-…` | +| Evaluated file | `rfcs/0000-database-architecture.md` | +| Size | 11,205 words; 1,296 lines | +| Verdict | `PASS_TO_FOCUSED_REVIEW` | + +Root read the complete consolidated RFC, not only the diff. The rewrite removes 60% of the raw +draft, deletes the appendices and inline evidence taxonomy, retains one lifecycle diagram, links the +research corpus, and moves the center of gravity to the native contract, NetScript definition, +app-local binding, Standard Schema, plugin-space/extension, runtime, and plan/apply DX. Findings +R1–R10 below are resolved in the committed text. + +Root made three narrow correctness corrections before accepting the checkpoint: + +- downstream runtime now consumes the compiled manifest and generated binding, not the authored + `DatabaseDefinition`; this preserves the manifest join point and package-free plugin deployment; +- the authority section now distinguishes the five control-flow values from each space's + provider-owned `ContractArtifact`, instead of silently changing the locked taxonomy; and +- `partial-success` now requires mixed successful and unsuccessful target outcomes; a run in which + no target succeeds cannot be called partial success. + +The draft is ready for the owner-locked Qwen 3.8 Max focused review. It is below the mandatory +12,000-word ceiling but remains 1,205 words above the preferred band. Subsequent reviewers must +identify deletions or consolidations alongside findings; they must not grow the RFC into another +research report. The final target is at most 10,000 words when that can be achieved without removing +an API contract, a safety invariant, or an explicit refusal. + ## What the RFC must make obvious After reading the RFC, a contributor should be able to answer these questions without opening the diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index 42aa0d5871..a8c4683a26 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -55,6 +55,29 @@ reports and briefs remain immutable evidence. Cycle 2 passed at `383170bbc`; the cycle is requested. Cycle 2 also classified current-main `01e096049` as nonblocking CI/gate-tooling drift and independently confirmed 42 generated `db:*` keys per engine workspace. +## RFC authoring and consolidation + +| Stage | Route / model / effort | Session | Result | +| ------------------- | ------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------ | +| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | +| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | +| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | +| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | + +Before commit `5dfc4e8eb`, root added three narrow corrections: runtime consumes the compiled +`DatabaseManifest`, not `DatabaseDefinition`; the authority table distinguishes each artifact and +value's role; and `partial-success` requires mixed successful and unsuccessful target outcomes. +Targeted formatting, `docs:links`, and diff checks passed. The phase remains `rfc-authoring`. The +preferred final target remains at most 10,000 words where further cuts preserve decision and API +clarity. + +The Qwen focused review passed architecture/type model, Standard Schema boundary, control/recovery, +migration/plugin safety, and market/upstream claims. Its narrow failures affect TypeScript/API +examples and one package/dependency example. QF-01 is high, QF-02 medium, and QF-03–QF-05 low. Its +approximately 1,240-word deletion ledger projects approximately 9,965 words while naming +must-not-cut contracts. The RFC remains frozen at 11,205 words until Grok review and Opus +author/editor disposition; this is not final acceptance. + ## Recorded lane/eval overrides - The root session is Codex rather than the default Opus 5 orchestrator. This is the active @@ -72,7 +95,9 @@ drift and independently confirmed 42 generated `db:*` keys per engine workspace. refinement gate. That owner directive overrides the ordinary `docs_polish` Fable-medium effort for this run. No substantive model gate may follow it. - Qwen 3.8 Max is selected for the owner-clarified focused post-draft review, after the root's - personal complete-draft review and before Grok's whole-RFC adversarial pass. + personal complete-draft review and before Grok's whole-RFC adversarial pass. The completed route + requested and observed `qwen/qwen3.8-max` at `max`, session + `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`, against commit `5dfc4e8eb`. - The owner subsequently requires Grok 4.6 high. On 2026-08-13 the live OpenRouter models API returned `x-ai/grok-4.6` with `reasoning_effort` support. The repository's static model catalog still names Grok 4.5, so this is an explicit owner-directed route override rather than a claim @@ -96,5 +121,5 @@ drift and independently confirmed 42 generated `db:*` keys per engine workspace. establish the exact upstream state and derive candidate end-to-end NetScript type flows before plan lock; the Opus synthesis brief now requires this subsystem explicitly. - The owner locked the post-draft sequence: root personal review → Qwen 3.8 Max focused review → - Grok 4.6 high whole-RFC adversarial review → author/editor dispositions → one final Fable 5 high - substantive refinement → mechanical checks only. + Grok 4.6 high whole-RFC adversarial review → Opus author/editor dispositions and consolidation → + one final Fable 5 high substantive refinement → mechanical checks only. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 5ab55e0f48..844edad4ce 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -16,7 +16,8 @@ The Design checkpoint is **locked and evaluator-approved**. Cycle 1 returned `FA because the copied generated-workspace task count was factually wrong; evaluator execution found 42 `db:*` keys per workspace for all four providers. After correction, native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. -Canonical RFC authorship is unblocked but not yet complete; no further PLAN-EVAL cycle is planned. +Canonical RFC authorship is unblocked. The consolidated draft is accepted for focused review but is +not finally accepted; no further PLAN-EVAL cycle is planned. ### Public Surface and Package Graph @@ -154,6 +155,41 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in | 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | | 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | | 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | +| 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | + +### RFC Consolidation and Root Acceptance + +Native Claude Code Opus 5 high session `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` completed the +single-author consolidation. The canonical RFC fell from 28,194 to 11,205 words while resolving +R1–R10 and preserving the locked architecture; root committed and pushed it as `5dfc4e8eb`. + +Root personally read the entire compact RFC and added three narrow corrections before commit: +runtime consumes the manifest rather than `DatabaseDefinition`; artifact/value authority remains +explicit; and `partial-success` requires mixed successful and unsuccessful target outcomes. Targeted +fmt, `docs:links`, and diff checks passed. The checkpoint is accepted for Qwen review, not finally +accepted. + +### Qwen Focused Post-Draft Review + +OpenRouter requested and observed `qwen/qwen3.8-max` at effort `max`, model session +`3d1277dd-be6a-44af-9e98-4560d8aaf1b7`, against RFC commit `5dfc4e8eb`. The exact review output was +2,181 words, made no edits, and returned `PASS_WITH_CHANGES`. Architecture/type model, Standard +Schema boundary, control/recovery, migration/plugin safety, and market/upstream claims passed. The +narrow failures were TypeScript/API examples and one package/dependency example. + +Open findings, pending author/editor disposition: + +- **QF-01 high:** generated-binding example uses ambient declarations as runtime values. +- **QF-02 medium:** extension-bundle authoring can violate the adapter-only runtime/control import + law. +- **QF-03 low:** unbound values and elisions undermine the executable-as-written claim. +- **QF-04 low:** Prisma source-path attribution needs correction or qualification. +- **QF-05 low:** codec parameter validation is conflated with three conversion representations. + +Qwen also supplied an approximately 1,240-word deletion ledger projecting an approximately +9,965-word RFC while naming must-not-cut contracts. It is editorial input, not authorization to +remove load-bearing semantics. The canonical RFC remains frozen at 11,205 words; no disposition, +edit, or final acceptance occurred. ### PLAN-EVAL Cycle 1 @@ -205,15 +241,17 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | Gate | Command or check | Result | Notes | | -------------- | ----------------------------------------------- | ------ | ----------------------------------------------------- | | Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | +| Compact RFC | Targeted fmt; `docs:links`; `git diff --check` | PASS | Commit `5dfc4e8eb`; 11,205 words and R1–R10 resolved. | ### Fitness Gates -| Gate | Result | Evidence | Notes | -| ---------------------------- | --------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------ | -| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | -| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | -| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | -| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | +| Gate | Result | Evidence | Notes | +| ---------------------------- | ----------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | +| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | +| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | +| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | +| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | +| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings remain open; review made no edits. | ### Runtime Gates @@ -223,10 +261,10 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ### Consumer Gates -| Consumer | Result | Evidence | Notes | -| ---------------------- | ------ | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | -| RFC reader/implementer | REVISE | `reviews/root-rfc-review.md`; raw draft commit `05e5fbac2` | Evidence is complete; the reader-facing RFC must now be consolidated and technically corrected. | +| Consumer | Result | Evidence | Notes | +| ---------------------- | ---------------------- | ---------------------------------------------------------------------------- | -------------------------------------------- | +| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | +| RFC reader/implementer | QWEN_PASS_WITH_CHANGES | Compact RFC `5dfc4e8eb`; Qwen session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | QF-01–QF-05 await disposition; Grok is next. | ## Handoff Notes @@ -234,8 +272,9 @@ CI/gate-tooling drift that changes structured check invocation rather than datab preserved; cycle 2 passed and no further PLAN-EVAL cycle is requested. - Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until packages exist and must produce implementation/release receipts later. -- Resume the Opus 5 high authoring family with `briefs/claude-opus-rfc-consolidate.md` and reduce - the canonical RFC to 8,000–10,000 words (12,000 hard ceiling), applying root findings R1–R10. -- After root accepts the consolidated draft, continue the owner-locked order: Qwen 3.8 Max focused - review, Grok 4.6 high whole-RFC adversarial review, author/editor dispositions, one final Fable 5 - high substantive refinement, and mechanical checks only. +- The consolidated RFC remains frozen at `5dfc4e8eb` and 11,205 words. Qwen returned + `PASS_WITH_CHANGES`; QF-01–QF-05 and its deletion ledger await disposition. Any cut toward the + projected approximately 9,965 words must preserve its named must-not-cut contracts. +- Continue the owner-locked order: Grok 4.6 high whole-RFC adversarial review, Opus author/editor + dispositions and consolidation, one final Fable 5 high substantive refinement, and mechanical + checks only. The current checkpoint is not final acceptance. From 84ff5f788e3ed1d2d9600d55a7587adefc15c8fe Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 21:46:05 +0200 Subject: [PATCH 12/19] docs(rfc): record Grok adversarial review --- .../context-pack.md | 37 ++++---- .../reviews/grok-rfc-adversarial-review.md | 90 +++++++++++++++++++ .../supervisor.md | 24 +++-- .../worklog.md | 59 ++++++++---- 4 files changed, 174 insertions(+), 36 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index 076adabf3c..30f48a7a30 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -19,8 +19,9 @@ authored an evidence-complete 28,194-word raw draft, pushed as `05e5fbac2`. Opus consolidation session `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` resolved root findings R1–R10 and reduced it to 11,205 words. Root read the entire compact RFC, added three narrow correctness fixes, and pushed it as `5dfc4e8eb`. Qwen 3.8 Max reviewed that frozen commit without edits and returned -`PASS_WITH_CHANGES`; QF-01–QF-05 remain open. It is not finally accepted. Current-main commit -`01e096049` remains nonblocking CI/gate-tooling drift. +`PASS_WITH_CHANGES`. Grok 4.6 high then reviewed the same byte-identical RFC without edits and +returned `PASS_WITH_REFINEMENTS` with zero blockers. QF-01–QF-05 and GR-01–GR-08 remain open. It is +not finally accepted. Current-main commit `01e096049` remains nonblocking CI/gate-tooling drift. ## Completed @@ -44,18 +45,24 @@ and pushed it as `5dfc4e8eb`. Qwen 3.8 Max reviewed that frozen commit without e - Qwen passed architecture/type model, Standard Schema boundary, control/recovery, migration/plugin safety, and market/upstream claims. Its narrow failures affect TypeScript/API examples and one package/dependency example only. +- Completed the Grok whole-RFC review through requested/observed `x-ai/grok-4.6`, variant `high`, + session `ses_003644aeaffeSm3UCAW9xUqRIK`. It evaluated byte-identical blob `f46040d8...` from RFC + commit `5dfc4e8eb` at HEAD `be83301c6`, used no subagents, made no edits, and returned + `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. +- Grok passed axes 2, 3, 4, and 6. Abstraction, public API/DX/types, and economy failed narrowly; + the architecture stands. ## In Progress -- Grok 4.6 high whole-RFC adversarial review. The RFC remains frozen at 11,205 words and the run - remains in `rfc-authoring`; Qwen findings have not yet been dispositioned. +- Opus 5 high author/editor dispositions and consolidation. The RFC remains frozen at 11,205 words + and the run remains in `rfc-authoring`; no QF/GR finding has been dispositioned yet. ## Next Steps -1. Run Grok 4.6 high as the whole-RFC adversarial review. -2. Use Opus for author/editor dispositions and consolidation of Qwen/Grok findings. Qwen's - approximately 1,240-word deletion ledger projects approximately 9,965 words but its named - must-not-cut contracts remain mandatory. +1. Use Opus 5 high for author/editor disposition of every QF/GR finding and consolidation to at most + 10,000 words. Preserve Qwen's must-not-cut contracts; Grok projects a net approximately + 1,040–1,200-word cut plus another safe approximately 80 words if needed. +2. Root checks the consolidated result. 3. Run one final Fable 5 high substantive refinement. 4. Run mechanical checks only, then commit/push and update the PR trail. @@ -76,19 +83,19 @@ and pushed it as `5dfc4e8eb`. Qwen 3.8 Max reviewed that frozen commit without e ## Gates -| Gate family | Current status | Evidence | -| ----------- | -------------- | ------------------------------------ | -| Static | PASS | Compact RFC fmt, `docs:links`, diff. | -| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | -| Runtime | N/A | Docs-only RFC run. | -| Consumer | changes open | Qwen `PASS_WITH_CHANGES`; Grok next. | +| Gate family | Current status | Evidence | +| ----------- | -------------- | --------------------------------------------------- | +| Static | PASS | Compact RFC fmt, `docs:links`, diff. | +| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | +| Runtime | N/A | Docs-only RFC run. | +| Consumer | changes open | Qwen/Grok reviews complete; Opus dispositions next. | ## Open Questions - No must-resolve-now architecture decision remains; pre-implementation decisions stay assigned to their W1/W3/W4/W5/W7/W10 gates. - QF-01–QF-05 are review findings, not reopened architecture decisions; they await author/editor - disposition after Grok. + disposition together with GR-01–GR-08. ## Drift and Debt diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md new file mode 100644 index 0000000000..e461eedeed --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md @@ -0,0 +1,90 @@ +### Route receipt + +| Field | Value | +| --- | --- | +| Requested | OpenCode via OpenRouter, `openrouter/x-ai/grok-4.6`, variant `high` | +| Observed | OpenCode (`OPENCODE=1`, PID `2056871`); model `openrouter/x-ai/grok-4.6` from runtime identity. Variant `high` is **not** independently echoed into the session identity string; observed model does not differ. | +| Session | OpenCode PID `2056871`; receipt `.llm/tmp/grok-rfc-adversarial-review-receipt.jsonl` (`msg_ffc9bb764001ebDsKVA7KpWQuK` …) | +| Evaluated commit | `5dfc4e8eb3988818fc81c6f5dc2856d551443249` (`docs(rfc): consolidate database architecture draft`) | +| RFC identity | blob `f46040d8b89f94809c61371da478aeeffb68c9db`; sha256 `20c1a6b719a2b523be61a4dff4a33cc9006273a34009a3d0467d77afa98b5e22`; **11,205 words**. Worktree bytes **identical** to `5dfc4e8eb`. HEAD is `be83301c6` on a clean `docs/database-architecture-rfc` tree; RFC file itself is unchanged. | +| Required files read completely | `rfcs/0000-database-architecture.md`; `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md`; `reviews/root-rfc-review.md`; `reviews/qwen-rfc-focused-review.md` | +| Qwen artifact | **present** at `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md` | +| Extra inspection | `research/prisma-8-deep-dive.md:430-469`; `research/architecture-plan-synthesis.md:265-317`; `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:45-113`; pinned Prisma RC1 `define-contract.ts:40-122`, `contract-types.ts:644-691`; doctrine `02-public-surface.md:217-236` | +| Subagents | **None.** One Grok parent session. | + +### Verdict + +**`PASS_WITH_REFINEMENTS`** + +The checkpoint is one architecture: native Prisma authoring, thin NetScript definition, distinct artifacts, Prisma-8/PostgreSQL-only adapter, fail-closed validation, and a data-safe clean break. No blocker remains; eight refinements must be dispositioned so the flagship examples and a few authority sentences cannot be implemented as a merged-contract or Prisma-import leak. + +Counts: **0 blocker**, **8 refinement**. + +### Findings + +| ID | Class | Axis | RFC lines | Violated invariant/decision | Consequence | Smallest correction | Offset deletion | +| -- | ----- | ---- | --------- | --------------------------- | ----------- | ------------------- | --------------- | +| GR-01 | refinement | 5 | 169–171, 299–311, 334, 371–373, 713–714 | `@netscript/*` examples executable as written; binding is a generated **value** | `export declare const primaryBinding` / `PRIMARY_MANIFEST_DIGEST` emit nothing; `runtime.bind` and `.ref()` are unlinkable. Confirms Qwen QF-01 on this checkpoint. | Emit a real value module (or `.d.ts` + runtime sibling) that constructs the binding and digest. | Delete the two `declare` lines and the “GENERATED” header’s implied ambient style (~25 w). | +| GR-02 | refinement | 2 | 492–507 vs 661–665 | Only the adapter imports Prisma **runtime/control**; apps/plugins import the public **authoring** builder | Step 7’s bundle, if authored in app/plugin code, must import `/control` and `/runtime`. Kernel `defineDatabaseExtension` cannot name those Prisma types under isolatedDeclarations. Confirms QF-02. | One sentence: bundles are defined by the adapter/extension-pack publisher; facets are opaque handles. Show the import from `@netscript/database-prisma-postgres`. | Drop “Today a single logical extension…” (488–491) (~45 w). | +| GR-03 | refinement | 1 | 299–307, 765–767; identity 626–631 | Plugin spaces are separate contracts/artifacts; Prisma aggregate **does not merge** contracts (RC1 `aggregate/types.ts`, deep-dive 456–458) | Flagship binding is `QueryOf` from `./primary/contract.d.ts` with **one** `cs:` hash. A reader will merge app+auth into one target contract, breaking space identity. | Binding is per-target; query/validator types are **per-space**. Path `primary/app/contract.d.ts`; header lists each space snapshot; `ref({space})` is the query key, not a merged `AppContract`. | Delete “One generic model is used everywhere…” (313–318) after folding the three parameters into the corrected example (~70 w). | +| GR-04 | refinement | 1 | 603–620, 776, 800–802 vs 692–699 | Definition is “never consumed by … control”; catalog lists `compose` as a control `pure` op | Implementers will put `compileDatabase` in `-control` or pass definitions into apply/verify. | Authority cell: only `compose`/`compileDatabase` (A4, catalog-projected) consumes a definition; runtime/apply/verify consume the manifest. | Shrink the five-values prose (614–620) to a pointer at the authority table (~40 w). | +| GR-05 | refinement | 3 | 479–484, 965–968, 981–986 | Detach-and-retain must not invite later DDL; `adopted` is also the post-adopt manage-forward policy | Same row says adopted is Planned/Mutated **Yes**. After uninstall, a literal reading allows planning retained plugin tables. | Tombstoned retain: verify-only, not planned/mutated, until a new space re-adopts. Keep adopted-from-`db adopt` as manage-forward. | One clause; delete the second “ownership is downgraded…” repeat (484 vs 985) (~25 w). | +| GR-06 | refinement | 3 | 544–556, 852–856 | Per-space statuses exist; run-level `partial-success` is **target**-mixed only | Mixed spaces on one locked target have no rollup. | A target is `succeeded` iff every requested space succeeded; mixed spaces → that target failed/cleanup-required/outcome-unknown; only mixed **targets** yield run `partial-success`. | Drop mermaid-duplicated “diagram teeth” sentences (839–841) (~40 w). | +| GR-07 | refinement | 5 | 247–256 vs 328; 331, 520–531 | One implementable API; examples executable | `prismaPostgres({ minVersion: 15 })` vs `providers: [prismaPostgres]`; `connections` / `runId` / `policy` unbound (QF-03). | One sentence: factory vs configured descriptor. Bind or mark elisions. | No net add: replace the dual call sites’ surrounding prose. | +| GR-08 | refinement | 7 | see ledger | 11,205 > 10,000; repeated refusals/proof | Editors will re-expand during disposition. | Apply the deletion ledger; do not add sections. | **≈1,320 words** below. QF-04 (line 181: prefix “Prisma RC1”) and QF-05 (899–901: split paramsSchema vs conversion channels) fold here (~15 w replace, not add). | + +### Axis verdicts + +| Axis | Verdict | Strongest negative evidence | Result | +| --- | --- | --- | --- | +| 1 Abstraction integrity | **FAIL** | GR-03 one `AppContract`/`cs:` vs unmerged spaces; GR-04 compose vs “control never consumes definition.” Pipeline, six-value authority, preview≠plan, and definition↛runtime otherwise hold. | Correct the binding shape and authority sentence. Architecture stands. | +| 2 Kernel vs Prisma leakage | **PASS** | GR-02 is example placement, not a kernel import. No query DSL, no re-export, adapter subpaths = root+`/binding`, `QueryOf` stays adapter-local, “provider-neutral” ≠ portable queries. | State bundle ownership. | +| 3 Artifact / recovery safety | **PASS** | GR-05/GR-06 are rollup/policy precision. Closed target set, plan bindings, lock `(target, physical DB)`, `outcome-unknown`, inspect-before-resume, receipt lookup, marker-only adopt, no false rollback — hold. | Two sentences. | +| 4 Plugin / multi-space / multi-DB | **PASS** | One `ObjectKey` owner; pinned mirrors; grant-closed augmentation; physical collisions refused; non-default namespace refused; cross-target relation ≠ same-target cross-space. R1 still fixed. | GR-03 is the query-type consequence, not an ownership hole. | +| 5 Public API / DX / types | **FAIL** | GR-01/GR-02/GR-07. `defineDatabase` target-key check, `const` inference, distinct `TTx`, request session without `transaction`, fail-closed `input`/`output`, `runtime\|json` — sound. | Fix examples; do not change the type model. | +| 6 Feasibility / gates | **PASS** | W0–W11 are ordered; `-runtime`/`-control` do not import each other or a provider; RC pin/allowlist/namespace/JSR/slow-types are gated; kill list in the plan is strong enough. Type-check budget lives in the plan, not the RFC — acceptable after consolidation. | No RFC rewrite. | +| 7 Editorial economy | **FAIL** | Still 1,205 words over the preferred cap; refusals, kill lists, and market lessons are restated. | Net-delete; do not add chapters. | + +### Net deletion ledger + +| Cut | Lines | Est. words | Why safe | +| --- | ---: | ---: | --- | +| Motivation repair/`resolveTarget` mechanics; keep analytics collision + non-atomic conclusion | 85–102 | 90 | Linked current-state audit | +| Prisma-8 “attacks pain points” hexad | 127–139 | 35 | Mirrors Motivation | +| “Three things NetScript will not do” | 222–226 | 45 | Alternatives table | +| “What you stop doing” octad; keep refusal table | 578–584 | 65 | Restates guide | +| Five-values prose (GR-04 pointer) | 614–620 | 40 | Authority table 771–782 | +| Composition-validates laundry list | 789–794 | 35 | Guide refusals | +| Diagram-teeth / catalog-projection repeats (GR-06) | 838–841, 857–859 | 55 | Mermaid + Step 8 | +| ValidationIR positive paragraph | 913–919 | 35 | Fail-closed list remains | +| Refusal-boundary no-compat/no-re-export | 1006–1013 | 80 | 661–665 and 1126–1131 | +| Drawbacks EA/indirection/conformance overlap | 1017–1035, 1053–1056 | 80 | Summary + plan risk register | +| Why-this-shape obs. 3–4 lists | 1062–1073 | 65 | Deep-dive + 722–723 | +| Scope-law paragraph | 1115–1118 | 35 | D-31, summary, alternatives | +| Prior-art lesson restatement | 1190–1206 | 95 | 1092–1113; keep oRPC 1208–1212 | +| Unresolved implementation sweep + locked-topics opener | 1216–1233 | 130 | Plan already linked | +| Future policy-factory bullet | 1264–1267 | 25 | Root removed it from v1 | +| Market-lesson tighten + Step 5 isolation list + target-key trailing fallback sentence | 282–290, 432–436, 1092–1113 | 75 | Identity table + linked analysis | +| GR-01/02/03 local swaps | 313–318, 488–491 | 95 | Replaced by shorter corrections | +| **Gross delete** | | **≈1,180** | | +| **Gross add** (GR-01 value emit, GR-02 sentence, GR-03 space-keyed header, GR-04/05/06 clauses, GR-07 factory sentence, QF-04/05 wording) | | **≈140** | | +| **Net** | | **≈ −1,040 to −1,200** | Lands ~10,000–10,160. A second pass on Motivation 114–123 incident-table prose (−80) crosses 10,000 without touching APIs. | + +**Do not cut:** all code blocks except GR-01/GR-03 rewrite; refusal table 586–599; authority + identity tables; four inference rules + bind soundness seam; namespace withhold 989–1000; fail-closed inventory + mandatory-boundary rules; mermaid apply diagram; adoption steps, pre-cutover list, rollback table; alternatives table; incident table; JSON/`db.plan.stale` examples; official Prisma/comparator links; D-01–D-47 and W0–W11 (stay in the plan). + +### Sound claims not to reopen + +Checked on this checkpoint / pinned RC1 / current NetScript source: + +1. `workspace-resolver.ts:51` collapses workspaces to `database/`; `resolveTarget` defaults only when one target is enabled and throws `Unknown database target: (default)`; engine map is a four-way `switch` (`:97–113`). +2. RC1 `defineContract(scaffold, callback)` exists with `const` generics and `ComposedAuthoringHelpers` (`define-contract.ts:82–104`). +3. Authoring storage maps put every table under the default namespace and leave non-default maps as `Record` (`contract-types.ts:644–691`). D-37 is evidenced. +4. Prisma aggregate exposes per-space contracts and does **not** merge them (deep-dive 456–458). Do not “fix” GR-03 by inventing a merged `AppContract`. +5. Codec `paramsSchema` validates parameters; three representations are **conversion** channels (deep-dive 430–439). Public `runtime \| json` remains correct. +6. oRPC-only `--allow-slow-types` carve-out is doctrine (`02-public-surface.md:217–231`). Do not extend it to database packages. +7. Root R1–R10 are present and consistent (namespace, target-key site, structurally offline control, pure `sign`, one `(TId,TQuery,TTx)` model, `input`/`output`, space vs fragment, honest `TTx`, receipt lookup, explicit adopt set + proved marker removal). +8. Qwen QF-01–QF-05 still exist in `5dfc4e8eb`; not silently fixed. + +### Final gate statement + +RFC may proceed to author/editor disposition of GR-01–GR-08; this is not final acceptance — Fable 5 high remains the last substantive gate. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index a8c4683a26..d9c49ee7d2 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -57,12 +57,13 @@ drift and independently confirmed 42 generated `db:*` keys per engine workspace. ## RFC authoring and consolidation -| Stage | Route / model / effort | Session | Result | -| ------------------- | ------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------ | -| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | -| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | -| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | -| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | +| Stage | Route / model / effort | Session | Result | +| --------------------- | -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------ | +| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | +| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | +| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | +| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | +| Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | Before commit `5dfc4e8eb`, root added three narrow corrections: runtime consumes the compiled `DatabaseManifest`, not `DatabaseDefinition`; the authority table distinguishes each artifact and @@ -78,6 +79,13 @@ approximately 1,240-word deletion ledger projects approximately 9,965 words whil must-not-cut contracts. The RFC remains frozen at 11,205 words until Grok review and Opus author/editor disposition; this is not final acceptance. +The Grok review ran against current HEAD `be83301c6` while proving the RFC blob byte-identical to +commit `5dfc4e8eb`. Axes 2, 3, 4, and 6 passed. Abstraction, public API/DX/types, and economy failed +narrowly through GR-01–GR-08; the architecture stands. The deletion ledger estimates approximately +1,180 words deleted and 140 added, net approximately 1,040–1,200 removed, landing around +10,000–10,160 with another safe approximately 80-word cut. The RFC remains frozen at 11,205 words +pending Opus dispositions; this is not final acceptance. + ## Recorded lane/eval overrides - The root session is Codex rather than the default Opus 5 orchestrator. This is the active @@ -105,6 +113,10 @@ author/editor disposition; this is not final acceptance. `openrouter/x-ai/grok-4.6` and variant `high`, record requested/observed identity and raw receipt, and run it after the focused Qwen review. No substantive gate may follow the final Fable 5 high refinement. +- The completed Grok route requested and observed `x-ai/grok-4.6`, variant `high`, session + `ses_003644aeaffeSm3UCAW9xUqRIK`, with no subagents and no edits. It evaluated RFC commit + `5dfc4e8eb` / blob `f46040d8...` at HEAD `be83301c6` and returned `PASS_WITH_REFINEMENTS` with + zero blockers. - Qwen integration-risk launch evidence: OpenRouter evaluator guard requested `qwen/qwen3.8-max` at `max`; session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` initialized with observed model `qwen/qwen3.8-max` and provider `Alibaba`. This is a complementary falsification pass, not diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 844edad4ce..6bdb696be8 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -156,6 +156,7 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in | 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | | 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | | 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | +| 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | ### RFC Consolidation and Root Acceptance @@ -191,6 +192,33 @@ Qwen also supplied an approximately 1,240-word deletion ledger projecting an app remove load-bearing semantics. The canonical RFC remains frozen at 11,205 words; no disposition, edit, or final acceptance occurred. +### Grok Whole-RFC Adversarial Review + +OpenCode/OpenRouter requested and observed `x-ai/grok-4.6`, variant `high`, session +`ses_003644aeaffeSm3UCAW9xUqRIK`. It evaluated RFC commit `5dfc4e8eb`; the RFC blob was +byte-identical to `f46040d8...` at current HEAD `be83301c6`. The lane used no subagents, made no +edits, and returned `PASS_WITH_REFINEMENTS` with zero blockers. Axes 2, 3, 4, and 6 passed; axis 1 +abstraction, axis 5 public API/DX/types, and axis 7 economy failed narrowly while the architecture +stood. + +Open refinements for Opus author/editor disposition: + +- **GR-01:** use real generated binding values, overlapping QF-01. +- **GR-02:** put opaque control/runtime extension facets under extension-pack/adapter ownership, + overlapping QF-02. +- **GR-03:** bind queries, validators, and hashes per target/per space; never merge a Prisma + `AppContract`. +- **GR-04:** make pure compose/compile authority consistent with control wording. +- **GR-05:** distinguish adopted manage-forward objects from detach-retained verify-only tombstones. +- **GR-06:** specify space → target → run outcome rollup explicitly. +- **GR-07:** show a configured provider factory and remove executable-example elisions. +- **GR-08:** perform net consolidation and resolve QF-04/QF-05. + +Grok's deletion ledger estimates approximately 1,180 words removed and 140 added, net approximately +1,040–1,200 words removed, landing around 10,000–10,160 words; it identifies another safe +approximately 80-word cut to cross 10,000. The RFC remains frozen at 11,205 words until Opus applies +all QF/GR dispositions. This gate is not final acceptance. + ### PLAN-EVAL Cycle 1 Fresh Fable 5 medium cycle 1 returned `FAIL_PLAN` on one medium factual-integrity defect only: an @@ -245,13 +273,14 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ### Fitness Gates -| Gate | Result | Evidence | Notes | -| ---------------------------- | ----------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | -| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | -| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | -| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | -| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | -| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings remain open; review made no edits. | +| Gate | Result | Evidence | Notes | +| ---------------------------- | --------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | +| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | +| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | +| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | +| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | +| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings remain open; review made no edits. | +| Grok whole-RFC review | PASS_WITH_REFINEMENTS | Session `ses_003644aeaffeSm3UCAW9xUqRIK`; blob `f46040d8...` | Zero blockers; GR-01–GR-08 await disposition. | ### Runtime Gates @@ -261,10 +290,10 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ### Consumer Gates -| Consumer | Result | Evidence | Notes | -| ---------------------- | ---------------------- | ---------------------------------------------------------------------------- | -------------------------------------------- | -| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | -| RFC reader/implementer | QWEN_PASS_WITH_CHANGES | Compact RFC `5dfc4e8eb`; Qwen session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | QF-01–QF-05 await disposition; Grok is next. | +| Consumer | Result | Evidence | Notes | +| ---------------------- | ----------------------------- | ------------------------------------------------------------- | --------------------------------------------------- | +| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | +| RFC reader/implementer | REVIEWS_COMPLETE_CHANGES_OPEN | Frozen RFC `5dfc4e8eb`; Qwen/Grok receipts | QF-01–QF-05 and GR-01–GR-08 await Opus disposition. | ## Handoff Notes @@ -273,8 +302,8 @@ CI/gate-tooling drift that changes structured check invocation rather than datab - Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until packages exist and must produce implementation/release receipts later. - The consolidated RFC remains frozen at `5dfc4e8eb` and 11,205 words. Qwen returned - `PASS_WITH_CHANGES`; QF-01–QF-05 and its deletion ledger await disposition. Any cut toward the - projected approximately 9,965 words must preserve its named must-not-cut contracts. -- Continue the owner-locked order: Grok 4.6 high whole-RFC adversarial review, Opus author/editor - dispositions and consolidation, one final Fable 5 high substantive refinement, and mechanical + `PASS_WITH_CHANGES`; Grok returned `PASS_WITH_REFINEMENTS` and zero blockers. All QF/GR findings + and both deletion ledgers await disposition. +- Continue the owner-locked order: Opus 5 high author/editor dispositions plus consolidation to at + most 10,000 words, root checks, one final Fable 5 high substantive refinement, and mechanical checks only. The current checkpoint is not final acceptance. From d340df30ada3e5f930db982123f2c37e455a47fb Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 21:56:11 +0200 Subject: [PATCH 13/19] docs(rfc): make layered database DX a first principle --- ...claude-opus-rfc-disposition-consolidate.md | 403 ++++++++++++++++++ .../context-pack.md | 41 +- .../plan.md | 222 +++++----- .../research.md | 35 +- .../research/layered-dx-api-audit.md | 214 ++++++++++ .../supervisor.md | 22 +- .../worklog.md | 93 ++-- 7 files changed, 863 insertions(+), 167 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-disposition-consolidate.md create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-disposition-consolidate.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-disposition-consolidate.md new file mode 100644 index 0000000000..285480b5f6 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-disposition-consolidate.md @@ -0,0 +1,403 @@ +# use harness — Opus 5 RFC disposition and final consolidation + +You are the bounded author/editor for NetScript's database architecture RFC. Run as **native Claude +Code Opus 5, effort high**. This is the post-review disposition pass, not a new architecture pass +and not the absolute final substantive gate. + +## SKILL + +Use the NetScript harness discipline for this edit. Preserve the approved plan, reviewer separation, +route identity, edit scope, evidence boundaries, and final handoff contract. Do not invoke another +skill, model, agent, team, workflow, background worker, or review surface. + +## Frozen input and edit scope + +Work in `/home/codex/repos/netscript-db-rfc`. + +The sole editable file is: + +```text +rfcs/0000-database-architecture.md +``` + +The RFC input is frozen to commit `5dfc4e8eb3988818fc81c6f5dc2856d551443249`, RFC blob +`f46040d8b89f94809c61371da478aeeffb68c9db`, 11,205 words. HEAD may be newer because review and brief +artifacts were committed afterward; that does not authorize using a different RFC draft. + +Before editing, prove with read-only Git/hash inspection that the worktree RFC bytes equal the RFC +at `5dfc4e8eb`. If they differ, stop and return `BLOCKED_RFC_BASE_MISMATCH`; do not overwrite or +merge an unknown draft. + +Do not edit bookkeeping, reviews, briefs, research, plan, context pack, supervisor, worklog, drift, +doctrine, production code, generated files, or lock files. Do not commit, push, amend, open/update a +PR, or post comments. Do not use subagents or alternate models. + +## Required complete reading + +Read these files completely before editing: + +1. `AGENTS.md` +2. `.agents/skills/netscript-harness/SKILL.md` +3. `.llm/harness/workflow/lane-policy.md` +4. `rfcs/0000-database-architecture.md` +5. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +6. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +7. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md` +8. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md` + +If a focused Hono/DAL progressive-adoption precedent audit has appeared under this run's `research/` +directory by launch time, read it completely before editing and use its verified NetScript public- +surface lessons. If none exists, record that absence and continue; do not create the audit or launch +new research. + +The reviews already performed the source audit. Do not browse, launch new research, or expand the +research corpus. Consult an existing linked research file only to resolve an exact wording dispute. + +## Locked architecture and editorial law + +Decisions D-01–D-47 in the approved plan are locked except for the narrow, explicit owner override +`OWNER-DX-01` below. That override may refine or supersede D-07, D-08, D-36, and directly related +RFC prose only where the focused precedent evidence and a demonstrated type/runtime boundary support +it. All other decisions remain locked exactly in substance. Apart from this required correction, +this pass may repair examples, resolve contradictions, tighten authority/identity semantics, and +delete duplication; it may not add architecture. + +Do not introduce: + +- compatibility, Prisma 7 fallback, dual runtime, legacy facade, schema bridge, or migration-history + bridge; +- a NetScript model/field/relation/query DSL, repository layer, portable query facade, provider + switch, global registry/service locator, or hosted control plane; `OWNER-DX-01` requires a thin + NetScript orchestration recipe/DSL, not a parallel database language; +- new packages, new chapters, new public extension axes, private Prisma imports, copied overloads, + casts, slow-type waivers, or permissive validation; +- a merged Prisma contract across spaces, false multi-provider parity, non-default namespace claim, + cross-database relation/transaction, automatic rollback, or destructive plugin removal claim; +- review process, route/session metadata, exhaustive gates, or new research exposition in the public + RFC. + +The final RFC must be **at most 10,000 words**. Every addition must be offset by a larger deletion +in the same pass. Preserve the repository RFC headings; do not add a chapter or appendix. Prefer +local replacement and deletion over explanatory expansion. + +Keep the center of gravity on: + +1. the end-goal developer API and journey; +2. exact TypeScript inference from Prisma's current native model-first + `defineContract(scaffold, callback)` contract into sound app-local bindings, preferring source- + native inference over generated type code where it survives the proved package/declaration + boundary; +3. canonical provider artifacts and `DatabaseManifest` as the durable downstream join point; +4. bounded, fail-closed Standard Schema input/output validation; +5. plugin-owned spaces, app-local fragments, controlled augmentation, and single-registration + extension bundles; +6. explicit multi-target plan/apply/receipt/recovery semantics; +7. a clean break with marker-only, data-safe adoption. + +## `OWNER-DX-01` — three-level adoption and zero-manual-typegen correction + +This is an owner-authorized architectural correction, not editorial polish. The current RFC over- +indexes on “do not mirror Prisma's DSL” and does not expose NetScript's established progressive- +disclosure model. Correct the meaning everywhere: NetScript must not reproduce Prisma models, +fields, relations, native types, or query operations, but it **must** own a concise orchestration +surface for the framework seams around those native contracts. + +Do not add a chapter. Replace and compress the current verbose Step 1–3 prose/examples with one +concrete progressive-disclosure subsection. Show the **same small application and the same native +Prisma contract** side by side at all three levels, rather than presenting three unrelated designs: + +1. **Golden-path recipe/DSL.** A few-line normal-app surface covers a single target and shows the + minimal delta for multiple targets. It coordinates targets, connections, native contracts, + spaces/extensions, deterministic artifacts and bindings, runtime/control wiring, and Aspire and + agent projections. It delegates schema and query semantics to Prisma unchanged. +2. **Public factory builders.** The recipe lowers to the public NetScript factories/primitives that + application and plugin authors use for custom logic. Customization must not opt out of manifest + compilation, bindings, extension/plugin identity, validation, control, receipts, or safety + policy. Derive exact names and signatures from the focused Hono/DAL audit when present, the oRPC + precedent, the already-approved package graph, and existing database factory examples; do not + invent arbitrary syntax merely to fill the three boxes. +3. **Native foundation.** Advanced authors compose Prisma's public native + `defineContract(scaffold, callback)` value directly with NetScript kernel primitives/ports. This + remains unrestricted native Prisma authoring, not a NetScript schema facade, and reaches the same + compiler, manifest, artifact, validation, runtime, and control pipeline as the other two levels. + +Include a compact API-ownership map naming, for each shown surface, its owning package, source of +truth, value it produces/lowers to, and boundary it must not cross. At minimum distinguish Prisma- +owned contract authoring/query types, NetScript-owned recipe and factories, adapter/extension-owned +provider facets, app-local binding identity, and manifest-derived CLI/Aspire/agent projections. Do +not change the locked package graph just to make the table neat. + +Specify the normal development loop. A source contract or definition change must deterministically +and atomically refresh required compile artifacts and stale checks through the normal +dev/build/watch path. There may be an explicit CI emit/verify command, but a normal developer must +never discover a surprise manual “re-emit” or manual type-generation ritual. Automatic compilation +does **not** imply automatic migration planning or database mutation; plan/apply authority remains +explicit. + +### Binding decision hierarchy + +Challenge the current generated-binding premise instead of preserving it by inertia: + +1. First try to prove that app-local source-native `typeof contract`/definition inference can feed a + stable binding factory through type-only imports while runtime consumes only the durable manifest + and pinned provider artifacts. The proof must cover `isolatedDeclarations`, declaration emit, + package boundaries, plugin-owned spaces, per-target/per-space literal identity, and absence of + Prisma type leakage from public NetScript declarations. If sound, prefer it and remove generated + **type-code** as a required architecture step. +2. If source-native inference fails any boundary, show the minimal compile/type proof explaining + why. A generated module is then permitted only as an automatic implementation artifact: real + runtime values where runtime values are needed, deterministic and atomic output, + digest/provider/per-space identity, watch/build integration, and zero manual type-gen workflow. + It must never be the durable control authority; runtime still verifies against the manifest. + +Whichever branch wins, make the binding representation and stale-refusal semantics concrete in code, +and state why the rejected branch is unsound or needlessly generated. Do not force the frozen +draft's implementation merely because QF-01/GR-01 reviewed its example. + +## Mandatory dispositions + +Disposition every finding `QF-01` through `QF-05` and `GR-01` through `GR-08`. Several findings +overlap; one correction may close multiple IDs, but the final response must name every ID +separately. + +All corrections below are required. Do not silently decline or replace them with new architecture. + +### 1. Bindings are sound values, not ambient runtime fiction — QF-01 / GR-01 + +Remove `export declare const` from any module consumed for runtime binding. Apply the `OWNER-DX-01` +decision hierarchy first. If source-native type inference wins, show a real binding factory value +with type-only app-contract imports while runtime consumes and verifies the manifest. If generation +is proved necessary, both binding and manifest digest must be emitted runtime values, and the +generated value must carry the target identity, manifest digest, provider pin, and per-space +snapshot identity used by bind-time stale checks. + +Use the adapter-owned `/binding` seam for the provider-specific value factory. Do not expose that +factory as a provider-neutral query API, and do not hand-wave a `.d.ts` value into existence. Keep +the soundness rule: type identity, runtime construction, manifest, and provider artifacts resolve to +the same target/space identities, and bind refuses digest mismatch before the first query. + +### 2. Bindings are per target and per space; contracts remain disjoint — GR-03 + +Remove the single merged `AppContract` / single `cs:` implication. Prisma contract spaces remain +separate contracts and artifacts; the binding must not merge their Prisma values or query types. + +Show a target-level binding containing a literal, space-keyed type/value map, whether its types are +source-native or its module is automatically generated under the proved fallback. Each space entry +has its own contract declaration type and `ContractSnapshotId`; the target binding also carries the +`ManifestDigest` and provider pin. Query and validator lookup select an explicit `SpaceId`. + +The example may use a compact space-keyed type such as `PrimaryQueries['app']`, but it must preserve +each native contract's exact type and must not widen the map to a generic record. Update the session +query example coherently so it cannot imply that plugin and app contracts were combined into one +Prisma contract. Preserve separate per-target output roots, bindings, artifacts, lineages, locks, +and receipts. + +### 3. Multi-facet extension bundles are provider-owned opaque values — QF-02 / GR-02 + +The application must not construct a bundle by importing Prisma authoring, control, and runtime +facets. State and show that the Prisma adapter or the extension-pack publisher defines the complete +identity/version-checked bundle inside the controlled provider boundary. Consumers import one opaque +configured extension value; the provider fans it into authoring, control, runtime, and validation. + +The provider-neutral kernel sees only identity, version, provider/capability requirements, and +opaque facet handles. Preserve the dependency law: applications may import Prisma's public authoring +builder for native schema authoring, while only the adapter/extension publisher imports Prisma +runtime and control modules. + +### 4. Definition compilation and control execution have distinct owners — GR-04 + +Clarify that `compileDatabase`/composition is the pure A4 responsibility of `@netscript/database`. +The operation catalog may project a `compose` command, but `@netscript/database-control` does not +own the compiler and live control does not consume a `DatabaseDefinition`. + +The authored definition is consumed only by the pure compiler. Runtime, emit-after-compilation, +inspect, plan, apply, verify, and recovery consume the resolved manifest and pinned artifacts as +appropriate. Correct the authority table and operation-class prose without collapsing definition, +manifest, plan, ledger, or receipt. + +### 5. `adopted` management is not a detach tombstone — GR-05 + +Keep `adopted` as the manage-forward ownership policy established by reviewed `db adopt`: it may be +planned and mutated against its baseline. A detached-and-retained plugin space instead loses its +runtime binding and active migration owner while preserving data, provider marker, lineage, +ownership history, and a **verify-only tombstone**. It is not planned or mutated until a new +explicit space re-adopts it. + +Do not add a fifth ownership policy merely to encode lifecycle. Express the tombstone as retained +space lifecycle state/evidence, distinct from the active `adopted` policy. Preserve retain as the +only guaranteed removal behavior. + +### 6. Define space → target → run outcome rollup — GR-06 + +Add one compact deterministic rollup rule near the multi-target saga: + +- every selected space records a terminal outcome; +- a target is `succeeded` only when every selected space for that target succeeds; +- `outcome-unknown` and `cleanup-required` dominate target rollup, followed by failed/refused/ + cancelled according to the catalog's closed precedence; +- mixed space outcomes never make that target “partially successful”; +- run-level `partial-success` exists only when at least one target succeeds and at least one + selected target has a non-success terminal outcome; +- when no target succeeds, the run uses the deterministic non-success outcome, never + `partial-success`. + +Do not add a second state diagram or a large status catalog. + +### 7. Use one configured provider value and bind/mark every elision — QF-03 / GR-07 + +Use one unambiguous role for `prismaPostgres`: either name the factory and the configured immutable +provider descriptor separately, or show a single configured value reused by target definition, +runtime, and control. Do not alternate between `prismaPostgres({ minVersion: 15 })` and +`providers: [prismaPostgres]` as if they were the same value. + +Bind `connections`, `runId`, and `policy` through function parameters or explicit declarations, or +mark a snippet as an intentional excerpt. Do the same for application-owned `AccountStore` / +`PrismaAccountStore`. A snippet presented as a complete file cannot contain undeclared values. Keep +the API examples compact; do not add a framework helper merely to fill an example variable. + +### 8. Correct the two Prisma evidence sentences — QF-04 / QF-05 / GR-08 + +- Attribute `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121` explicitly to + the **Prisma RC1 checkout** or link the existing deep dive, so it is not mistaken for a NetScript + path. +- State separately that Prisma's Standard Schema `paramsSchema` validates codec **parameters**, not + model values, and that Prisma codecs define three **conversion representations**: application + runtime, driver wire, and target JSON. Only `runtime | json` are NetScript's public validation + representations; driver wire remains adapter-internal. Conversion success is not validation. + +Do not change the bounded-validation decision or reopen the audited fail-closed list. + +## Deletion ledger: apply, validate, and finish below 10,000 words — GR-08 + +Start at 11,205 words. The corrections above add some words, so delete **more than 1,205 plus every +added word**. Measure; do not rely on estimates. The primary funding source for `OWNER-DX-01` is +replacement of the current verbose Step 1–3 walkthrough with its smaller side-by-side three-level +surface—not a new chapter appended elsewhere. Then use the Qwen and Grok ledgers as one prioritized +ledger: + +| Priority | Candidate content | Preserve | +| -------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Motivation's `resolveTarget` mechanics and repair-pipeline enumeration | The two-target collision, non-atomic conclusion, and linked current-state audit | +| 2 | The six-item “Prisma 8 attacks the pain points” restatement | Contract/control/space opportunity and deep-dive link | +| 3 | “Three things NetScript will not do” paragraph | One short sentence preserving no obsolete fluent **schema/query** API or re-export, without forbidding the required orchestration recipe | +| 4 | “What you stop doing” eight-item repetition | Refusal table and one transition sentence | +| 5 | Five/six-value explanatory prose duplicated by the authority table | The authority table and all distinct artifact roles | +| 6 | Composition-validation laundry list | Determinism, diagnostics, and negative-test requirement | +| 7 | Prose that repeats edges already visible in the one Mermaid diagram | Never-replay, checkpoint granularity, lock scope, certified-lock refusal | +| 8 | Positive `ValidationIR` inventory duplicated by the schema-class table/fail-closed list | Bounded algebra, construction-time refusal, value issues, representations, cache identity | +| 9 | Refusal-boundary compatibility/re-export repetition | One canonical clean-break law, no arbitrary TS/text repair, no implicit/cross-target claims | +| 10 | Early-Access, indirection, and conformance-cost drawback repetition | Real costs and the adapter-boundary mitigation | +| 11 | “Why this shape” operational-gap lists already in the deep dive | Manifest join point, target identity, app-local type constraint | +| 12 | Market-lessons and Prior-art repetition | Direct official links, the adopted lessons once, and the oRPC transfer paragraph | +| 13 | Scope-law paragraph repeated by D-31/non-goals/alternatives | One local-kernel refusal | +| 14 | Unresolved-question implementation sweep already owned by the plan | Only the few genuinely reader-relevant W3/W5/W10/upstream gates | +| 15 | Future policy-factory bullet | Remove it; Candidate A is the v1 decision | +| 16 | Repeated target-default, target-isolation, two-phase, serverless-precedent, summary-withhold, and package-count prose | Each unique invariant once | + +Continue tightening only within those duplicate zones until `wc -w` reports **≤10,000**. If a line +range changed after earlier edits, follow the content, not stale line numbers. Do not delete unique +safety or public-contract content to make the number. + +### Must not cut + +Preserve, while updating only where a mandatory correction above requires it: + +- the native Prisma model-first authoring example and + current-builder/no-parallel-schema-or-query-DSL decision; +- the compact three-level adoption surface, same-app side-by-side examples, API-ownership map, + automated dev loop, one coherent factory/runtime/query example, validation example, + plugin-space/extension example, and plan/apply example; +- the refusal table and one canonical clean-break/no-compatibility law; +- authority and identity tables, inference rules, binding soundness seam, and package boundaries; +- the first-adapter namespace-withhold paragraph and physical-collision refusal; +- Standard Schema classes, bounded/fail-closed inventory, mandatory trust boundaries, codec/value + schema and cache/version identity; +- one-owner/object rule, space independence, augmentation grant, package-free pinned artifacts, and + corrected detach-and-retain semantics; +- the sole Mermaid lifecycle diagram, closed-target/no-silent-omission law, corrected rollup, + unknown-outcome/inspect-before-resume, locking, receipt lookup, and saga semantics; +- adoption steps, pre-cutover safety list, rollback-boundary table, marker-only zero-DDL/DML + guarantee, and explicit selected-target closure; +- alternatives table, incident table, structured JSON/stale-plan examples, and direct official + upstream/comparator links; +- unsupported-provider and no-false-portability statements. + +Do not copy D-01–D-47 or W0–W11 into the RFC; keep their direct plan link. + +## Claims already checked: no silent reopenings + +Do not alter these claims without new contradictory evidence, which this pass is not authorized to +seek: + +- RC1 exposes the current model-first `defineContract(scaffold, callback)` const-generic overload + and composed helpers. Whether NetScript needs generated type code around it is deliberately + reopened only by `OWNER-DX-01` and must be settled by the required type/package-boundary proof. +- RC1 Prisma spaces remain separate contracts; its aggregate does not merge them. +- RC1 namespace authoring type maps flatten into the default namespace; the capability remains + withheld with no cast/private-import workaround. +- `@prisma/orm-postgres` has 138 audited top-level export keys at the RC1 pin. +- Prisma operation/type maps needed for full runtime validation are phantom/erased. +- Public validation modes remain `runtime | json`; driver wire remains internal. +- Current NetScript target/workspace collapse, plugin-fragment doctrine, AP-24, and the oRPC-only + slow-types carve-out are source-verified. +- Root R1–R10 remain resolved. +- No database package receives a slow-types waiver, and no public NetScript declaration leaks Prisma + types. + +## Required checks + +After editing only the RFC, run: + +```bash +deno fmt rfcs/0000-database-architecture.md +deno fmt --check rfcs/0000-database-architecture.md +deno task docs:links +git diff --check -- rfcs/0000-database-architecture.md +wc -w rfcs/0000-database-architecture.md +``` + +Inspect the scoped diff against `5dfc4e8eb` and verify: + +- only `rfcs/0000-database-architecture.md` changed during this session; +- the word count is at most 10,000; +- every addition has a larger deletion; +- `OWNER-DX-01` is visibly satisfied with all three levels, the same-app comparison, an explicit API + ownership map, a no-surprise-manual-emit development loop, and a binding proof/decision; +- every QF/GR correction is visible; +- no decision outside the named D-07/D-08/D-36 owner-override envelope, must-not-cut contract, + direct link, or safety/refusal guarantee disappeared; +- no new chapter, compatibility path, architecture beyond `OWNER-DX-01`, unsupported claim, or + unresolved must-decide-now item was introduced. + +Do not commit or push after checks. + +## Final response contract + +Return a concise Markdown handoff containing: + +1. **Route receipt:** native Claude Code, requested/observed `claude-opus-5`, high effort, session + ID, frozen input commit/blob, and confirmation that no subagent/workflow/alternate model ran. +2. **Counts:** before and after words and lines, gross additions/deletions from the scoped Git diff, + and net word reduction. +3. **Stable disposition table:** one row for `OWNER-DX-01` and one row for each `QF-01`–`QF-05` and + `GR-01`–`GR-08`, with status `applied`, `merged-with `, or `declined`; exact RFC + section/line; and a one-sentence rationale. For `OWNER-DX-01`, name the selected binding branch, + the evidence supporting it, and any precise D-07/D-08/D-36 refinement. The required corrections + above should be applied or explicitly reported blocked, never silently omitted. +4. **Deletion ledger actually applied:** sections/content removed, approximate word savings, and the + resulting final count. +5. **Locked-content confirmation:** every decision except the explicitly dispositioned `OWNER-DX-01` + refinements to D-07/D-08/D-36 preserved, root R1–R10 preserved, must-not-cut content present, and + checked-sound claims not otherwise reopened. +6. **Files changed:** must list only `rfcs/0000-database-architecture.md`. +7. **Checks:** exact command and exit status for format, `docs:links`, diff check, and word-count + gate. +8. **Residual risks:** only genuine implementation/upstream gates already present in the RFC/plan; + do not create new architecture questions. + +End with `READY_FOR_FABLE_FINAL_REFINEMENT` only if every required correction is dispositioned, all +checks pass, the RFC is ≤10,000 words, and no out-of-scope file changed. Otherwise end with +`BLOCKED: `. + +Do not claim final RFC acceptance. The owner-directed Fable 5 high in-place refinement remains the +absolute last substantive gate; after that, only mechanical verification may follow. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index 30f48a7a30..b741a1cbea 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -21,7 +21,11 @@ reduced it to 11,205 words. Root read the entire compact RFC, added three narrow and pushed it as `5dfc4e8eb`. Qwen 3.8 Max reviewed that frozen commit without edits and returned `PASS_WITH_CHANGES`. Grok 4.6 high then reviewed the same byte-identical RFC without edits and returned `PASS_WITH_REFINEMENTS` with zero blockers. QF-01–QF-05 and GR-01–GR-08 remain open. It is -not finally accepted. Current-main commit `01e096049` remains nonblocking CI/gate-tooling drift. +not finally accepted. After PLAN-EVAL and these reviews, the owner issued `OWNER-DX-01`: D-07/D-08/ +D-36 now require L1 preset/recipe → L2 public factories → L3 native Prisma plus NetScript +primitives, with source-native app inference preferred over generated type bindings. This is an +owner override, not a new PLAN-EVAL cycle. Current-main commit `01e096049` remains nonblocking +CI/gate-tooling drift. ## Completed @@ -51,17 +55,24 @@ not finally accepted. Current-main commit `01e096049` remains nonblocking CI/gat `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. - Grok passed axes 2, 3, 4, and 6. Abstraction, public API/DX/types, and economy failed narrowly; the architecture stands. +- Completed `research/layered-dx-api-audit.md`: shipped service/Hono uses preset → factory → native + primitives; SDK and Fresh preserve inferred lower-layer values; pinned Prisma separates runtime + `contractJson` from its phantom compile-time contract generic. The audit recommends erased + `typeof definition` for app-owned contracts and automatic atomic launcher-integrated declarations + only for W3-proven publish/artifact-only boundaries. ## In Progress -- Opus 5 high author/editor dispositions and consolidation. The RFC remains frozen at 11,205 words - and the run remains in `rfc-authoring`; no QF/GR finding has been dispositioned yet. +- Opus 5 high author/editor dispositions and consolidation, including `OWNER-DX-01` exact API + selection and type-boundary proof. The RFC remains frozen at 11,205 words and the run remains in + `rfc-authoring`; no QF/GR finding has been dispositioned yet. ## Next Steps -1. Use Opus 5 high for author/editor disposition of every QF/GR finding and consolidation to at most - 10,000 words. Preserve Qwen's must-not-cut contracts; Grok projects a net approximately - 1,040–1,200-word cut plus another safe approximately 80 words if needed. +1. Use Opus 5 high for author/editor disposition of every QF/GR finding, integrate `OWNER-DX-01`, + choose the exact layered API, and state how W3 proves direct inference versus fallback while + consolidating to at most 10,000 words. Preserve Qwen's must-not-cut contracts; Grok projects a + net approximately 1,040–1,200-word cut plus another safe approximately 80 words if needed. 2. Root checks the consolidated result. 3. Run one final Fable 5 high substantive refinement. 4. Run mechanical checks only, then commit/push and update the PR trail. @@ -73,6 +84,8 @@ not finally accepted. Current-main commit `01e096049` remains nonblocking CI/gat | No backward compatibility | Owner directive | Migration safety is required; runtime compatibility shims are not. | | NetScript owns its DB concepts | Initial plan | Prisma remains an adapter/engine target, not the framework-facing vocabulary. | | Exact future package graph | Plan lock | A1 contract → A4 definition → A3 runtime → A2 control → A2 Prisma PostgreSQL adapter → A6 testkit. | +| Layered database adoption | Owner override | L1 preset/recipe uses L2 factories; L3 is native Prisma plus NetScript primitives/ports. | +| App type flow | Owner override | Erased `typeof definition` first; automatic atomic declaration only at a W3-proven boundary. | | Fable 5 high is last | Owner directive | Final gate includes refinement, not only critique. | ## Files Changed @@ -83,19 +96,21 @@ not finally accepted. Current-main commit `01e096049` remains nonblocking CI/gat ## Gates -| Gate family | Current status | Evidence | -| ----------- | -------------- | --------------------------------------------------- | -| Static | PASS | Compact RFC fmt, `docs:links`, diff. | -| Fitness | plan PASS | Cycle 2 `plan-eval.md`; D-01–D-47. | -| Runtime | N/A | Docs-only RFC run. | -| Consumer | changes open | Qwen/Grok reviews complete; Opus dispositions next. | +| Gate family | Current status | Evidence | +| ----------- | -------------- | ----------------------------------------------------- | +| Static | PASS | Compact RFC fmt, `docs:links`, diff. | +| Fitness | owner override | Cycle 2 PASS; D-01–D-47 plus post-eval `OWNER-DX-01`. | +| Runtime | N/A | Docs-only RFC run. | +| Consumer | changes open | Qwen/Grok reviews complete; Opus dispositions next. | ## Open Questions - No must-resolve-now architecture decision remains; pre-implementation decisions stay assigned to - their W1/W3/W4/W5/W7/W10 gates. + their W1/W3/W4/W5/W7/W10 gates. W3 now includes direct-erasure and automatic-fallback proof. - QF-01–QF-05 are review findings, not reopened architecture decisions; they await author/editor disposition together with GR-01–GR-08. +- Exact L1/L2 API spelling is an Opus author/editor task under the owner override; it may not add a + mirrored Prisma schema/query DSL or change the six-package graph. ## Drift and Debt diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md index 12d46e09e1..9a221707cc 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -19,7 +19,9 @@ provider is Prisma 8 PostgreSQL, while NetScript owns a provider-neutral composi runtime-lifecycle, validation, and operations system. The experience must eliminate copied schemas, manually synchronized types, hand-wired clients/adapters, textual generated-source repair, implicit target selection, Aspire-coupled pure work, terminal-log contracts, and hand-maintained agent -instructions. +instructions. Adoption must follow NetScript's established progression: an L1 preset/recipe for the +golden path, the L2 public factories it uses, and L3 native Prisma plus NetScript primitives/ports; +source-native app inference is preferred over generated TypeScript bindings. ## Plan-Eval Disposition @@ -34,6 +36,12 @@ additional PLAN-EVAL cycle is requested. `origin/main` has since advanced by one CI/gate-tooling commit (`01e096049`); the evaluator found no architecture, database, doctrine, or RFC premise invalidated, and the existing fresh-pin drift watch remains sufficient. +After that pass, the owner issued `OWNER-DX-01`: the accepted architecture must expose NetScript's +existing layered adoption pattern and must not assume generated app type bindings are inevitable. +This is an explicit owner override to D-07/D-08/D-36, not a new PLAN-EVAL cycle; no further +PLAN-EVAL will run. The Opus author/editor pass owns exact API selection and the source-native +versus fallback type-boundary proof while keeping the RFC at or below 10,000 words. + ## Scope - Current-state, failure-history, doctrine/debt, Prisma RC/current-source, market, and agent-surface @@ -41,7 +49,8 @@ RFC premise invalidated, and the existing fresh-pin drift watch remains sufficie - Exact durable vocabulary, artifact taxonomy, package/archetype/dependency graph, public versus adapter-local ownership, and refusal boundaries. - Current model-first native Prisma TypeScript authoring, const-preserving app/plugin composition, - contract spaces, extension bundles, app-local inferred bindings, and an E2E type flow. + contract spaces, extension bundles, layered adoption, source-native app-local inference with a + bounded automatic declaration fallback, and an E2E type flow. - Bounded contract-derived Standard Schema validation for runtime and JSON representations, selection-aware results, codec contributions, fail-closed semantics, caching, and optional AOT equivalence. @@ -59,10 +68,11 @@ RFC premise invalidated, and the existing fresh-pin drift watch remains sufficie - Production package, CLI, plugin, or provider implementation in this RFC PR. - Any backward-compatible facade, Prisma 7 client, legacy generated module, alias barrel, dual migration history, `setClient`, copied fragment, or runtime shim. -- A NetScript query DSL, generic repository, ORM, model language, or lowest-common-denominator - portability API. -- Recreating Prisma's obsolete target/table/column fluent builder or re-exporting Prisma as though - NetScript owns it. +- A mirrored Prisma model/field/relation/query DSL, generic repository, ORM, or + lowest-common-denominator portability API. NetScript presets/factories may orchestrate identity, + policy, lifecycle, artifacts, extensions, and validation around the native contract. +- Recreating Prisma's obsolete target/table/column fluent builder, copying private types/overloads, + or re-exporting Prisma as though NetScript owns it. - Runtime capability negotiation; capabilities are declared static data. - Cross-database foreign keys, transparent joins, atomic transactions, or automatic rollback. - Hosted control-plane products: RBAC, approval workflow, registries/promotion, fleet schedulers, @@ -92,7 +102,7 @@ packages land. This RFC records the target; it does not mutate doctrine before a | A7 | Wrap Prisma and Standard Schema; do not rebuild an ORM or validator ecosystem. | | A8 | Definition, runtime, control, provider, and tooling responsibilities live in separate role-named packages/folders. | | A9 | Each future package has exactly one archetype; runtime is explicitly A3. | -| A10 | Generated application composition roots bind providers/targets; no global registry/service locator. | +| A10 | Application composition roots bind providers/targets; no global registry/service locator. | | A11 | Extension axes are named as target, role, namespace, space, provider, capability, connection source, runtime scope, and validation representation. | | A12 | Plan/apply/recovery, contribution lifecycle, and multi-target execution are explicit state machines. | | A13 | Runtime/control crash boundaries, cancellation, unknown outcomes, and supervision are explicit. | @@ -113,7 +123,7 @@ assertions, implicit fallback selection, and arbitrary schema TypeScript during | `SpaceContribution` | Declarative owner/version/dependency/capability/provenance/retention record for one contract space. | | `ContractArtifact` | Canonical provider contract data/declaration, lineage, and provenance pinned per space. | | `DatabaseManifest` | Deterministic, versioned, content-addressed resolved snapshot; the durable join point. A graph is private compiler IR only. | -| `AppBinding` | Generated application-local inferred bridge from native contract declarations to sessions, validators, and consumers. | +| `AppBinding` | Application-local inferred bridge to sessions/validators: source-native by default; an atomic declaration is a bounded fallback. | | `TargetRef` / `TargetSession` | Explicit target reference and process/request lifecycle shell; concrete provider query type is app-local. | | `SpeculativePreview` | Advisory output that cannot be approved or applied. | | `ExecutablePlan` | Expiring plan bound to manifest, target/space closure, live baseline, provider pins, policy, environment, and secret references. | @@ -132,7 +142,7 @@ or dependency edges. | Unit | Archetype | Owns | Must not own | | ------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | | `@netscript/database-contract` | A1 | Plain identities, manifests/plans/receipts/diagnostics, capabilities, ownership, shared small SPIs. | IO, query types, provider imports. | -| `@netscript/database` | A4 | `defineDatabase`, target/space/policy definitions, pure compiler/resolver, frozen definitions. | Connections, provider/Aspire imports, execution. | +| `@netscript/database` | A4 | L1 database preset/recipe, L2 `defineDatabase`/target/space/policy factories, pure compiler/resolver, frozen definitions. | Connections, provider/Aspire imports, execution. | | `@netscript/database-runtime` | A3 | Process/request lifecycle, binding, connection ownership, health/readiness, cancellation, validation coordination. | Migration orchestration, CLI, provider query vocabulary. | | `@netscript/database-control` | A2 | Programmatic classify/compose/emit/preview/plan/apply/verify/inspect, provider ports, locks, receipts, recovery, cross-target saga. | Provider SQL/AST/types, terminal text, CLI rendering. | | `@netscript/database-prisma-postgres` | A2 | Sole framework runtime/control Prisma boundary, capability descriptor, artifact/control/runtime/validation adapters, import allowlist. | Prisma re-export, private-type public surface, hand-written low-level driver. | @@ -167,11 +177,15 @@ their plain canonical artifacts. - Candidate A is the baseline: native current model-first Prisma `defineContract`, then thin `defineDatabase({ contract, ... })` or `defineDatabaseSpace({ contract, ... })` preserving `typeof contract` unchanged. -- An optional policy factory exists only if it forwards exact native helpers without private - imports, copied overloads, or inference widening; otherwise it is killed. +- The adoption surface is L1 preset/recipe → L2 public factories → L3 native Prisma plus NetScript + primitives/ports. L1 literally composes L2 and returns the same definition; neither layer mirrors + Prisma schema/query vocabulary. Exact API spelling is settled by the Opus author/editor pass. +- Any optional policy factory dies if it forwards/copies native helpers, needs private imports or + copied overloads, or widens inference. - `ownership: app` fragments return const-preserved native builder values and are composed by an - explicit generated root. `ownership: space` contributions own a full contract artifact and - migration head; this is the default for plugin-owned tables. + explicit source root; generation is reserved for a proved artifact boundary. `ownership: space` + contributions own a full contract artifact and migration head; this is the default for + plugin-owned tables. - One identity/version-checked `DatabaseExtension` bundle fans authoring, control, runtime, and validation facets through two-phase collection. - `TargetRef`/session handles expose lifecycle and a narrow query generic. Application-owned stores @@ -214,59 +228,60 @@ Prisma control/runtime/contract/codec/AST shapes stay adapter-local. ## Locked Decision Ledger -| ID | Decision | Status | -| ---- | -------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | -| D-01 | Clean break; no backward-compatibility API/runtime surface. | Locked | -| D-02 | Data continuity and mechanical migration are mandatory. | Locked | -| D-03 | Durable join point is `DatabaseManifest`; live graph is private compiler IR. | Locked | -| D-04 | Definition, manifest, executable plan, provider ledger, and receipt remain separate values. | Locked | -| D-05 | NetScript defines no query DSL, repository, or portable client facade. | Locked | -| D-06 | Current native model-first Prisma TypeScript authoring is primary; obsolete fluent chaining is not recreated. | Locked; import spelling adapter-pinned | -| D-07 | Candidate A native contract plus thin definition is baseline; optional factory dies on private imports/overload copying/type widening. | Locked | -| D-08 | App-specific inferred binding is generated app-local, never a kernel package export. | Locked | -| D-09 | Package/archetype graph above is exact; runtime is A3. | Locked | -| D-10 | Kernel is provider-neutral; first certified adapter is Prisma 8 PostgreSQL only. | Locked | -| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | Locked | -| D-12 | Capabilities are static tags/requirements, never runtime negotiation. | Locked | -| D-13 | Provider registry is composition-root data, never global/public mutable state. | Locked | -| D-14 | Stable target ID owns connection, output, runtime, migrations, locks, and receipts. | Locked | -| D-15 | Target selection is explicit, dependency-closed, and records every omission/reason. | Locked | -| D-16 | Replicas are roles of a target, never migration targets. | Locked | -| D-17 | Provider-native contract spaces plus NetScript policy replace copied fragments. | Locked | -| D-18 | One managed owner per `ObjectKey`; augmentation requires owner grant. | Locked | -| D-19 | Pinned mirrors make apply/verify independent of installed plugin code. | Locked | -| D-20 | Detach-and-retain is guaranteed removal; archive/drop are conditional. | Locked | -| D-21 | Standard Schema is public; bounded runtime interpretation is default. | Locked | -| D-22 | Public validation representations are `runtime` and `json`; driver wire is internal. | Locked | -| D-23 | Complete Prisma operation validation is not contract-derived; exact operation contributors are required. | Locked | -| D-24 | Unknown validation metadata fails while constructing the schema. | Locked | -| D-25 | Optional AOT validation is corpus-equivalent only and never required. | Locked | -| D-26 | Pure operations cannot resolve connections, Aspire, Docker, or network. | Locked | -| D-27 | Programmatic operation catalog is primary; CLI/docs/agents are generated projections. | Locked | -| D-28 | Preview is not executable plan; apply accepts only bound/revalidated plans. | Locked | -| D-29 | NetScript owns policy/lock/recovery/receipts/cross-target saga; provider owns diff/lineage/marker mechanics. | Locked | -| D-30 | Cross-target apply is never atomic; partial and unknown outcomes are first-class. | Locked | -| D-31 | Local kernel does not rebuild hosted registry/RBAC/fleet/drift products. | Locked | -| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | Locked | -| D-33 | Agent instructions/catalogs are generated and every example executes. | Locked | -| D-34 | Existing MySQL/MSSQL/SQLite support is not carried through compatibility code. | Locked | -| D-35 | Production plans require signatures; mechanism/key custody is selected before production cutover. | Pre-implementation W5/W10 | -| D-36 | Model-first callback, Candidate A, two-phase collection, const-preserving root, and no-re-export rule define builder strategy. | Locked; exact RC/GA path W3 | -| D-37 | Multi-namespace adapter capability is withheld while Prisma type maps flatten runtime namespaces; no cast workaround. | Conditional upstream block | -| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin tables default to full space ownership. | Locked | -| D-39 | One extension bundle supplies identity-matched authoring/control/runtime/validation facets. | Locked | -| D-40 | CI/production migration and runtime consume canonical verified artifacts, not arbitrary schema TypeScript. | Locked | -| D-41 | Exact Prisma control/runtime import allowlist and compatibility window are selected in W3. | Pre-implementation W3 | -| D-42 | Native advisory versus fenced-row lock is certified per provider. | Pre-implementation provider detail | -| D-43 | Whether AOT validation ships is safe to defer. | Deferred | -| D-44 | A real second provider is safe to defer. | Deferred | -| D-45 | Public raw/prepared/aggregate conveniences are safe to defer/keep adapter-local. | Deferred | -| D-46 | Archive/drop plugin retirement in v1 is safe to defer. | Deferred | -| D-47 | Remote approval/registry/continuous-drift integrations are safe to defer. | Deferred | +| ID | Decision | Status | +| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | +| D-01 | Clean break; no backward-compatibility API/runtime surface. | Locked | +| D-02 | Data continuity and mechanical migration are mandatory. | Locked | +| D-03 | Durable join point is `DatabaseManifest`; live graph is private compiler IR. | Locked | +| D-04 | Definition, manifest, executable plan, provider ledger, and receipt remain separate values. | Locked | +| D-05 | NetScript defines no query DSL, repository, or portable client facade. | Locked | +| D-06 | Current native model-first Prisma TypeScript authoring is primary; obsolete fluent chaining is not recreated. | Locked; import spelling adapter-pinned | +| D-07 | Candidate A uses L1 preset/recipe → L2 public factories → L3 native Prisma + NetScript primitives; no mirrored Prisma schema/query DSL. | Owner override; locked | +| D-08 | App-owned contracts prefer erased `typeof definition` inference while runtime consumes artifacts; atomic launcher-integrated declarations are a W3-proven publish/artifact-only fallback. | Owner override; locked | +| D-09 | Package/archetype graph above is exact; runtime is A3. | Locked | +| D-10 | Kernel is provider-neutral; first certified adapter is Prisma 8 PostgreSQL only. | Locked | +| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | Locked | +| D-12 | Capabilities are static tags/requirements, never runtime negotiation. | Locked | +| D-13 | Provider registry is composition-root data, never global/public mutable state. | Locked | +| D-14 | Stable target ID owns connection, output, runtime, migrations, locks, and receipts. | Locked | +| D-15 | Target selection is explicit, dependency-closed, and records every omission/reason. | Locked | +| D-16 | Replicas are roles of a target, never migration targets. | Locked | +| D-17 | Provider-native contract spaces plus NetScript policy replace copied fragments. | Locked | +| D-18 | One managed owner per `ObjectKey`; augmentation requires owner grant. | Locked | +| D-19 | Pinned mirrors make apply/verify independent of installed plugin code. | Locked | +| D-20 | Detach-and-retain is guaranteed removal; archive/drop are conditional. | Locked | +| D-21 | Standard Schema is public; bounded runtime interpretation is default. | Locked | +| D-22 | Public validation representations are `runtime` and `json`; driver wire is internal. | Locked | +| D-23 | Complete Prisma operation validation is not contract-derived; exact operation contributors are required. | Locked | +| D-24 | Unknown validation metadata fails while constructing the schema. | Locked | +| D-25 | Optional AOT validation is corpus-equivalent only and never required. | Locked | +| D-26 | Pure operations cannot resolve connections, Aspire, Docker, or network. | Locked | +| D-27 | Programmatic operation catalog is primary; CLI/docs/agents are generated projections. | Locked | +| D-28 | Preview is not executable plan; apply accepts only bound/revalidated plans. | Locked | +| D-29 | NetScript owns policy/lock/recovery/receipts/cross-target saga; provider owns diff/lineage/marker mechanics. | Locked | +| D-30 | Cross-target apply is never atomic; partial and unknown outcomes are first-class. | Locked | +| D-31 | Local kernel does not rebuild hosted registry/RBAC/fleet/drift products. | Locked | +| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | Locked | +| D-33 | Agent instructions/catalogs are generated and every example executes. | Locked | +| D-34 | Existing MySQL/MSSQL/SQLite support is not carried through compatibility code. | Locked | +| D-35 | Production plans require signatures; mechanism/key custody is selected before production cutover. | Pre-implementation W5/W10 | +| D-36 | Prisma's model-first builder remains authority; progressive NetScript layers orchestrate seams without re-export, copied overloads, private types, or widening. | Owner override; exact RC/GA path W3 | +| D-37 | Multi-namespace adapter capability is withheld while Prisma type maps flatten runtime namespaces; no cast workaround. | Conditional upstream block | +| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin tables default to full space ownership. | Locked | +| D-39 | One extension bundle supplies identity-matched authoring/control/runtime/validation facets. | Locked | +| D-40 | CI/production migration and runtime consume canonical verified artifacts, not arbitrary schema TypeScript. | Locked | +| D-41 | Exact Prisma control/runtime import allowlist and compatibility window are selected in W3. | Pre-implementation W3 | +| D-42 | Native advisory versus fenced-row lock is certified per provider. | Pre-implementation provider detail | +| D-43 | Whether AOT validation ships is safe to defer. | Deferred | +| D-44 | A real second provider is safe to defer. | Deferred | +| D-45 | Public raw/prepared/aggregate conveniences are safe to defer/keep adapter-local. | Deferred | +| D-46 | Archive/drop plugin retirement in v1 is safe to defer. | Deferred | +| D-47 | Remote approval/registry/continuous-drift integrations are safe to defer. | Deferred | No must-resolve-now decision remains. Pre-implementation items have stable public semantics and cannot force a package-boundary rewrite. D-37 withholds a capability claim rather than blocking the -provider-neutral architecture. +provider-neutral architecture. `OWNER-DX-01` explicitly overrides D-07/D-08/D-36 after PLAN-EVAL; it +does not start another evaluator cycle or alter the other decisions or six-package graph. ## Control and Contribution State Machines @@ -329,20 +344,20 @@ marker cleanup where supported. After apply, recovery is forward via lineage and ## Implementation Waves -| Wave | Scope | Dependency | Exit evidence | -| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------------------------ | -| W0 | Accepted RFC, doctrine/verdict amendments planned, package/gate registration. | — | RFC gates and architecture acceptance. | -| W1 | A1 contract kernel. | W0 | Zero-provider-dependency publish/doc/consumer gates. | -| W2 | A4 definition/compiler and manifest invariants. | W1 | Pure deterministic property/negative tests; no IO. | -| W3 | Experimental Prisma PostgreSQL spike: native builder, artifacts, control/runtime, spaces, extensions, validation decoder, Deno, namespace check. | W1–W2 | Real PostgreSQL, packed Deno, import allowlist, kill/switch review. | -| W4 | A3 runtime and Aspire connection adapter. | W1–W3 | Lifecycle/leak/cancellation/scope/validation gates. | -| W5 | A2 control, plans, locks, receipts, recovery, cross-target saga. | W1–W4 | Failure injection, atomic emit, pure path without Aspire. | -| W6 | A6 provider/space conformance testkit. | W1–W5 | Intentionally broken fixtures fail; real-service machine report. | -| W7 | `@netscript/plugin` contribution seam and first plugin-core fixture. | W1–W6 | Breaking surface and thinness/seam/package-free gates. | -| W8 | CLI/agent/adoption projection. | W2, W5–W7 | Generated examples/catalog freshness, populated adoption preflight. | -| W9 | First-party auth/workers/sagas/triggers spaces. | W7–W8 | Each space certified; package-free apply/verify and runtime parity. | -| W10 | Clean cutover and legacy deletion. | W1–W9 | Full release class, Windows/Linux, production-shaped adoption, remote published E2E. | -| W11 | Second real provider only when demanded/mature. | W10 | Same provider conformance; no kernel/manifest public rewrite. | +| Wave | Scope | Dependency | Exit evidence | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | --------------------------------------------------------------------------------------------------------- | +| W0 | Accepted RFC, doctrine/verdict amendments planned, package/gate registration. | — | RFC gates and architecture acceptance. | +| W1 | A1 contract kernel. | W0 | Zero-provider-dependency publish/doc/consumer gates. | +| W2 | A4 definition/compiler and manifest invariants. | W1 | Pure deterministic property/negative tests; no IO. | +| W3 | Experimental Prisma PostgreSQL spike: native builder, layered API, source-native inference/fallback boundary, artifacts, spaces/extensions, validation, Deno/namespaces. | W1–W2 | Direct-erasure and fallback fixtures, real PostgreSQL, packed Deno, import allowlist, kill/switch review. | +| W4 | A3 runtime, manifest-only consumption, typed adapter binding, and Aspire connection adapter. | W1–W3 | Lifecycle/leak/cancellation/scope/validation and no-authoring-runtime-import gates. | +| W5 | A2 control, plans, locks, receipts, recovery, cross-target saga. | W1–W4 | Failure injection, atomic emit, pure path without Aspire. | +| W6 | A6 provider/space conformance testkit. | W1–W5 | Intentionally broken fixtures fail; real-service machine report. | +| W7 | `@netscript/plugin` contribution seam and first plugin-core fixture. | W1–W6 | Breaking surface and thinness/seam/package-free gates. | +| W8 | CLI/agent/adoption projection plus launcher-integrated atomic emit/watch/bind. | W2, W5–W7 | Golden-path examples, catalog freshness, stale auto-remediation, populated adoption preflight. | +| W9 | First-party auth/workers/sagas/triggers spaces. | W7–W8 | Each space certified; package-free apply/verify and runtime parity. | +| W10 | Clean cutover and legacy deletion. | W1–W9 | Full release class, Windows/Linux, production-shaped adoption, remote published E2E. | +| W11 | Second real provider only when demanded/mature. | W10 | Same provider/layer conformance; no kernel, manifest, or L1/L2 public rewrite. | ## RFC Commit Slices @@ -395,7 +410,8 @@ may follow. namespace/space isolation, locks, crash/unknown/resume, ownership/removal, and negative diagnostic matrices. - App fragment literal-type preservation, extension-bundle facet identity, namespace type/runtime - parity, 500-model editor/type-check budget, and no private/cast workaround. + parity, source-native `typeof definition` erasure, artifact-only/JSR fallback declarations, + 500-model editor/type-check budget, and no private/cast/copied-overload workaround. - Standard Schema runtime/JSON corpus, two independent consumers, selection-aware outputs, fail-closed unsupported cases, contract-space aggregation, and optional AOT equivalence. - Generated project journeys, agent/help catalog freshness, executable examples, and full @@ -432,27 +448,27 @@ packed install cannot substitute for the remote-graph verdict. ## Risk Register -| Risk | Mitigation / kill response | -| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | -| Designing to RC marketing or stale builder screenshots | Pin source; current model-first API; keep exact paths adapter-local; W3 spike. | -| Upstream changes during RFC/implementation | RC/current split, exact provider pin/allowlist, independent provider release, compatibility-window gate. | -| Replacing glue with a second ORM/control plane | No query/model DSL, no runtime negotiation, no hosted services, small SPIs and refusal boundary. | -| Published slow types or Prisma leakage | App-local inference; no re-export/private imports; isolated declarations; no slow-types waiver; prospective JSR gates. | -| Native fragment composition widens inference | Two-phase explicit const-preserving generated root; compile-failure soundness fixtures and editor budget. | -| False multi-schema claim | Withhold capability until Prisma type/runtime parity passes without casts. | -| Contract-derived validation overclaims full operations | Bounded algebra, explicit contributors, runtime/JSON split, fail at schema construction. | -| Custom codec accepts invalid values | Mandatory representation-specific value schemas; encode/decode is not validation. | -| Stale or half-published artifacts | Full canonical digest, atomic publish, facet identity, runtime/apply mismatch refusal. | -| Plugin removal destroys data | Retain default; archive/drop conditional destructive plan; no directory-delete semantics. | -| Provider spaces mistaken for complete portability | PostgreSQL-only certification; explicit unsupported targets; native capability surface. | -| Apply success/exit code masks partial work | Typed per-target/space outcomes, immutable checkpoints, `outcome-unknown`, inspect-before-resume. | -| Cross-target atomicity/rollback implied | Saga language only; no global transaction; complete partial-success receipt. | -| Mutable receipts become shadow state | Provider ledger remains authority; receipts are append-only evidence. | -| No-compat cutover causes data loss | Ownership preflight, marker-only adoption, zero-DDL rehearsal, forward recovery, parallel release line only. | -| JSR plan mistaken for actual readiness | Explicit N/A now; per-package dry-run/docs/packed/canary/remote E2E receipts required later. | -| RFC breadth becomes unimplementable | Exact packages, W0–W11 dependencies, per-wave exits, kill/switch criteria. | -| Agent/docs drift | Generate from operation catalog/manifest and execute every example. | -| CI remains long/flaky | Pure/offline paths, digest caching, real-service gates only at bounded stages, atomic structured receipts. | +| Risk | Mitigation / kill response | +| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Designing to RC marketing or stale builder screenshots | Pin source; current model-first API; keep exact paths adapter-local; W3 spike. | +| Upstream changes during RFC/implementation | RC/current split, exact provider pin/allowlist, independent provider release, compatibility-window gate. | +| Replacing glue with a second ORM/control plane | No query/model DSL, no runtime negotiation, no hosted services, small SPIs and refusal boundary. | +| Published slow types or Prisma leakage | Source-native app inference; atomic fallback only across publish/artifact boundaries; no re-export/private imports or slow-types waiver. | +| Native fragment composition widens inference | Two-phase explicit const-preserving root; generate only at proved boundaries; compile-failure fixtures and editor budget. | +| False multi-schema claim | Withhold capability until Prisma type/runtime parity passes without casts. | +| Contract-derived validation overclaims full operations | Bounded algebra, explicit contributors, runtime/JSON split, fail at schema construction. | +| Custom codec accepts invalid values | Mandatory representation-specific value schemas; encode/decode is not validation. | +| Stale or half-published artifacts | Full canonical digest, atomic publish, facet identity, runtime/apply mismatch refusal. | +| Plugin removal destroys data | Retain default; archive/drop conditional destructive plan; no directory-delete semantics. | +| Provider spaces mistaken for complete portability | PostgreSQL-only certification; explicit unsupported targets; native capability surface. | +| Apply success/exit code masks partial work | Typed per-target/space outcomes, immutable checkpoints, `outcome-unknown`, inspect-before-resume. | +| Cross-target atomicity/rollback implied | Saga language only; no global transaction; complete partial-success receipt. | +| Mutable receipts become shadow state | Provider ledger remains authority; receipts are append-only evidence. | +| No-compat cutover causes data loss | Ownership preflight, marker-only adoption, zero-DDL rehearsal, forward recovery, parallel release line only. | +| JSR plan mistaken for actual readiness | Explicit N/A now; per-package dry-run/docs/packed/canary/remote E2E receipts required later. | +| RFC breadth becomes unimplementable | Exact packages, W0–W11 dependencies, per-wave exits, kill/switch criteria. | +| Agent/docs drift | Generate from operation catalog/manifest and execute every example. | +| CI remains long/flaky | Pure/offline paths, digest caching, real-service gates only at bounded stages, atomic structured receipts. | ## Kill and Switch Criteria @@ -478,8 +494,9 @@ None. ### Must resolve before implementation wave - W1: canonical manifest/digest encoding and public format-version evolution. -- W3: exact Prisma pin/import allowlist/public builder subpath, runtime/Deno matrix, extension facet - mappings, namespace capability result, and experimental publication status. +- W3: exact Prisma pin/import allowlist/public builder subpath, L1/L2 API spelling, direct-erasure + versus automatic declaration boundary, runtime/Deno matrix, extension facet mappings, namespace + capability result, and experimental publication status. - W4: concrete request/process scope and transaction capability shapes. - W5/W10: signature format/key custody, provider lock implementation, receipt storage/retention, and crash-fault harness. @@ -508,7 +525,8 @@ their gates have run. - Current NetScript baseline, issue/PR history, doctrine, debt, RFC process, and harness protocols. - Prisma RC1/pinned current source, official release/ADRs/scorecard/issues/PRs, plus a fresh pin check during RFC drafting and W3. -- Standard Schema and current NetScript oRPC/Fresh/plugin composition precedents. +- Standard Schema and current NetScript service/Hono, SDK, Fresh, oRPC, and plugin composition + precedents, including the preset → factory → native-primitives progression. - Drift watch: Prisma RC/API/contract changes; namespace typing; moving control/runtime paths; NetScript DB changes merged to main; model route identity; any compatibility or hosted-control- plane creep; any package surface requiring slow types. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md index d989b808b7..ca1793bd83 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md @@ -48,12 +48,17 @@ the harness-required current research entrypoint; it does not duplicate the repo 8. Prisma runtime lowering supports namespaces, but RC1 and the inspected post-RC source flatten namespaces in type maps. Sound multi-namespace E2E typing is an upstream-blocked capability, not a current product claim. -9. NetScript's `isolatedDeclarations` and doctrine slow-type boundary require application-specific - inferred Prisma bindings to remain generated app-local values rather than published framework - exports. +9. NetScript's service/Hono surface already implements preset → public factory → native framework + plus NetScript primitives; SDK and Fresh preserve the same inferred lower-layer values through + progressively lower adoption surfaces. 10. Market evidence separates source definition, resolved manifest, executable plan, provider ledger, and immutable receipt. It supports partial/unknown outcome recovery and rejects a local reinvention of hosted RBAC, fleet, registry, and continuous-drift products. +11. Pinned Prisma separates compile-time `TContract` from runtime `contractJson` (including a + phantom contract type on the emitted path). App-owned contracts can therefore prefer an erased + source-native `typeof definition` binding while runtime consumes only manifest/artifact values. + Root `isolatedDeclarations` still requires an automatic atomic declaration fallback when exact + types cross a publish or artifact-only boundary. ## Corrections and conflict resolutions @@ -80,6 +85,15 @@ the harness-required current research entrypoint; it does not duplicate the repo - Opus's provider re-export sketch is rejected. Applications and controlled plugin authoring may import Prisma's public builder directly; NetScript wraps the resulting native value and never pretends to own or vendor the builder. +- `OWNER-DX-01` supersedes the earlier universal-generated-binding assumption after PLAN-EVAL. The + current model-first Prisma builder remains schema authority, while NetScript adopts its + established L1 preset/recipe → L2 public factories → L3 native Prisma plus primitives/ports + progression. This permits orchestration layers but still forbids a mirrored Prisma + model/field/relation/query DSL, re-export, copied overloads, private types, or inference widening. +- The prospective JSR audit's generated-app-binding statement was planning evidence, not an executed + impossibility proof. Source-native app inference is now the default; a same-compile, + launcher-integrated declaration is the bounded fallback for publish/artifact-only boundaries and + must be proved in W3. - Plugin removal is not solved by contract spaces alone. Detach-and-retain is the initial guaranteed lifecycle; archive/drop remain conditional. - The kernel is provider-neutral while the first adapter is Prisma 8 PostgreSQL-only. Unsupported @@ -96,6 +110,7 @@ the harness-required current research entrypoint; it does not duplicate the repo | [runtime-validation-maintainer-exchange.md](./research/runtime-validation-maintainer-exchange.md) | Owner-supplied exploratory primary evidence for runtime-derived validation direction. | | [runtime-validation-source-audit.md](./research/runtime-validation-source-audit.md) | Pinned-source proof of bounded validation algebra, missing operation metadata, codec representations, cache identity, and fail-closed cases. | | [typescript-schema-orpc-audit.md](./research/typescript-schema-orpc-audit.md) | Historical/current Prisma builder evolution, native fragment/space composition, oRPC transfer, extension bundles, namespace blocker, and artifact boundary. | +| [layered-dx-api-audit.md](./research/layered-dx-api-audit.md) | `OWNER-DX-01` repository-grounded service/Hono, SDK, Fresh, pinned-Prisma type-flow audit and proposed three-layer adoption API. | | [qwen-prisma-risk-review.md](./research/qwen-prisma-risk-review.md) | Independent adversarial minimum-kernel, provider-contingency, risk, conformance, and kill review; factual conflicts corrected above. | | [claude-opus-architecture-review.md](./research/claude-opus-architecture-review.md) | Independent package/archetype, identity, runtime, control, contribution, cutover, waves, and conformance architecture review. | | [planned-jsr-audit.md](./research/planned-jsr-audit.md) | Prospective JSR verdict `PASS-AS-PLANNED`; explicitly not actual publish readiness because packages do not exist. | @@ -103,10 +118,10 @@ the harness-required current research entrypoint; it does not duplicate the repo ## Research verdict -Research supports proceeding to PLAN-EVAL with no must-resolve-now architecture decision. The exact -Prisma RC/GA import spelling, provider lock mechanism, signature/key custody, and other -implementation details are classified by wave and cannot force a package-boundary rewrite. The -Prisma namespace type/runtime mismatch is a capability block: it withholds a claim rather than -blocking the provider-neutral architecture. - -No canonical RFC may be authored until the separate evaluator returns `PASS`. +PLAN-EVAL cycle 2 passed with no must-resolve-now architecture decision. `OWNER-DX-01` is a later, +explicit owner override, not a new evaluator cycle. The exact Prisma RC/GA import spelling, provider +lock mechanism, signature/key custody, and other implementation details remain classified by wave; +the Opus author/editor pass will choose the exact layered API and state the W3 type-boundary proof +while consolidating the RFC to at most 10,000 words. The namespace mismatch continues to withhold a +capability claim rather than blocking the provider-neutral architecture. No further PLAN-EVAL will +run. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md new file mode 100644 index 0000000000..edaf7dd6ed --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md @@ -0,0 +1,214 @@ +# Layered database DX API audit + +> Scope: owner finding `OWNER-DX-01`; current repository and pinned Prisma RC1 source.\ +> Verdict: **the RFC has the right kernel, but presents its middle layer as the golden path and +> unnecessarily makes a generated TypeScript binding universal.** Adopt the repository's existing +> preset → factory → native-primitives pattern and make direct app-local inference the default. + +Labels below distinguish **[FACT]** repository/upstream evidence, **[INFERENCE]** conclusions from +that evidence, and **[PROPOSAL]** new API. + +## 1. The shipped NetScript pattern + +**[FACT] Service/Hono.** `packages/service/src/presets/define-service.ts:216-275` (`defineService`) +is the golden-path preset and literally calls +`packages/service/src/builder/service-builder.ts:195-200` (`createService`), then applies the +standard chain. `ServiceBuilder` exposes one-method-deeper customization (`withCors`, +`withDatabase`, `withRPC`, `use`, `route`, `build`, `serve`) at lines 61-175. Its implementation +constructs a real Hono app and composes Hono plus NetScript primitives in +`service-builder-impl.ts:12-45,60-88`; direct adopters can instead use such public primitives as +`createRPCPlugins`/`createRPCHandler` in `primitives/handlers.ts:38-114`. The repository calls these +implementation layers 3/2/1; this audit calls them user-facing L1/L2/L3 (highest to lowest). + +**[FACT] SDK/frontend data access.** There is no public symbol named “DAL”. The actual seam is +contract-derived clients and query resources. `packages/sdk/src/presets/define-services.ts:97-127` +(`defineServices`) fans one exact contract map into the same values returned by +`createServiceClient`, `createQueryFactory`, and `createServiceQueryUtils`. The first delegates to +native `createORPCClient` (`src/client/service-client.ts:41-65`); the second derives cache/query +operations without replacing the contract (`src/query/query-factory.ts:41-188`). +`packages/sdk/mod.ts:9-32` explicitly promises that dropping down a layer does not replace wiring. + +**[FACT] Fresh.** `defineFreshApp` returns the real Fresh `App` and accepts an existing app plus +factory/configuration escape hatches +(`packages/fresh/src/runtime/server/define-fresh-app.ts:24-117`). `definePage` builds its public +type-state facade from `createBuilder(createDefaultConfig())` +(`src/application/builders/define-page/builder/mod.tsx:465-471`); `withResource(s)` carries resource +types forward (`builder/state.ts:45-64`) while `retagConfig` changes compile-time state without +inventing runtime concepts (`builder/factory.ts:8-49`). + +**[FACT] Doctrine.** A3 requires the 80% case in one chain and advanced cases one method deeper; A6 +permits helpers only for policy, a test seam, or stable non-trivial work; A10 prefers a plain +composition factory; A11 requires named extension axes. Public `define`/`create` semantics and the +ban on upstream re-exporting remain binding (`docs/architecture/doctrine/01-thesis-and-axioms.md`, +`02-public-surface.md`, `07-composition-and-extension.md`). + +### Reusable laws + +1. The preset uses the public factory; it is not a parallel implementation. +2. Every layer preserves the same inferred source value and returns the same lower-layer objects. +3. NetScript adds cross-cutting policy once; the native library remains visible at the escape hatch. +4. One registration fans out to every consumer; type-state is not promoted into runtime machinery. +5. Defaults are inspectable, immutable, and replaceable; diagnostics name the failed policy. + +## 2. What the current RFC lacks + +**[FACT]** The RFC jumps from native `defineContract` to a 40-line target/space composition and then +to a generated binding (`Step 2`, lines 227-290; `Step 3`, lines 292-363). This is a sound L2/L3 +explanation, not an A3 adoption API. Plugin space registration is separate from the application +contract example. The cost section explicitly accepts surprise “re-emit” (`lines 1037-1045`). + +**[INFERENCE]** Users must currently understand target identity, spaces, policy, artifacts, provider +registration, runtime, and binding generation before the first query. The architecture is flexible, +but the presentation does not resemble NetScript's Hono, SDK, or Fresh adoption surfaces. + +## 3. Proposed three-layer analogue + +All examples describe the same one-target app. L1 and L2 produce the same `DatabaseDefinition`; L3 +uses the same manifest, provider, ports, and native query object. None defines models, fields, +relations, filters, or queries for Prisma. + +### L1 — golden-path recipe + +```ts +import { definePostgresDatabase, fromAspire } from '@netscript/database'; +import { authDatabase } from '@netscript/plugin-auth-core/database'; +import { appContract } from './app.contract.ts'; // native Prisma defineContract(...) + +export default definePostgresDatabase({ + contract: appContract, + connection: fromAspire('postgres'), + extensions: [authDatabase()], +}); +``` + +**[PROPOSAL]** This preset chooses inspectable defaults: target `primary`, app space `app`, managed +ownership, retain-on-removal, and the certified PostgreSQL provider. It calls only the L2 functions +below. An optional chained form is justified only if real successive type-state appears; do not add +a cosmetic builder. + +### L2 — factories used by L1 + +```ts +const primary = defineDatabaseTarget({ + id: 'primary', + provider: prismaPostgres({ minVersion: 15 }), + connection: fromAspire('postgres'), + policy: { destructive: 'deny', defaultOwnership: 'managed' }, +}); + +export default defineDatabase({ + targets: { primary }, + spaces: { + app: defineDatabaseSpace({ + id: 'app', + owner: 'app', + target: 'primary', + contract: appContract, + }), + }, + extensions: [authDatabase()], +}); +``` + +**[PROPOSAL]** `extensions` is the sole registration. Each bundle may contribute authoring, +manifest/control, runtime, and validation facets; the compiler expands it in the already-planned two +phases, rejects duplicate identities, and preserves deterministic order. L1 forwards the exact same +bundle and therefore cannot omit a facet. + +### L3 — native authoring plus NetScript ports + +```ts +// app.contract.ts: direct @prisma/orm-postgres/contract-builder defineContract(...) + +// runtime.ts +import type definition from './database.ts'; // erased +import { manifest } from './.netscript/database/manifest.ts'; // emitted value + +const binding = createPrismaPostgresBinding< + ContractOf +>({ target: 'primary', space: 'app', manifestDigest: manifest.digest }); + +await using runtime = await createDatabaseRuntime({ + manifest, + providers: [prismaPostgres()], + connections, +}); +export const primary = runtime.bind(binding); // primary.query is native Prisma +``` + +**[PROPOSAL]** `ContractOf` only extracts an opaque generic; adapter-owned +`createPrismaPostgresBinding` maps it to Prisma query/transaction types. The provider-neutral kernel +never names Prisma. Advanced consumers may construct ports and call compile/plan/apply separately, +but runtime still receives only the manifest, provider values, connections, and a digest-bearing +binding—not `DatabaseDefinition`. + +## 4. Remove manual type generation + +**[FACT]** Pinned Prisma already proves both halves. Its no-emit demo calls +`postgres({ contract })` +(`.llm/tmp/prisma-v8-rc1/examples/prisma-8-demo/src/prisma-no-emit/context.ts:1-15`). More +importantly, the emitted overload accepts `contractJson` plus a compile-time `TContract`; +`_contract?: TContract` is phantom +(`packages/3-extensions/postgres/src/runtime/postgres.ts:96-129,150-166`). Runtime always +serializes/deserializes to a contract value. `PostgresClient` exposes typed `sql`, `orm`, +enums, and transactions (`lines 45-78`). Therefore a type-only `typeof definition` can type a stable +adapter factory while runtime consumes the canonical artifact. + +**[FACT]** Root `deno.json:174` enables `isolatedDeclarations`. A local minimal Deno check confirms +that an exported `const contract = defineContract(...)`-shaped inferred call requires an explicit +annotation under that option. Prisma's demo does not claim this constraint. The planned JSR audit +correctly forbids slow types for framework packages, but its claim that every app binding must be +generated was prospective, not executed evidence. + +**[PROPOSAL] Decision.** App-owned authoring modules are build inputs, not JSR exports. Give that +narrow app-local project `isolatedDeclarations: false`; retain strict checking and keep every +published `@netscript/*` package at `true`. Then the default emits **no TypeScript binding**: exact +inference flows `typeof definition → ContractOf → adapter binding`, and the import erases. +Emit/watch only content-addressed manifest, contract JSON, lineage, and provenance values. + +Artifact-only plugin spaces remain behind plugin-owned ports. If a consumer intentionally exports an +inferred database definition from a publishable package or requests direct queries over an +artifact-only space, exact types cannot be reconstructed from JSON by TypeScript. In that bounded +case, generate the provider declaration automatically and atomically during the same compile—not a +hand-run NetScript binding, not a framework slow type. W3 must prove both paths against the pinned +public declarations; fall back universally only if the direct fixture fails without private imports +or copied overloads. + +## 5. Automation and projections + +**[PROPOSAL]** `netscript dev/start/test/build` runs an initial content-hash compile before loading +the runtime; `dev` then watches the authoring graph, writes a temporary artifact set, verifies it, +and atomically swaps the directory before restarting affected consumers. Generated task dependencies +make direct project commands do the same. CI runs compile-and-diff; production startup never mutates +schema or auto-applies migrations. A digest mismatch remains a hard safety refusal, but its message +says which file changed and the normal launcher already repairs artifacts—“run re-emit” is only an +escape-hatch command, never the expected workflow. + +Aspire projects target/resources and injects connections from the manifest; CLI projects the same +operation catalog; agents read manifest/plan/receipt schemas. None evaluates the TypeScript +contract. This makes the serializable artifact both the interoperability boundary and the low-token +agent surface; L1 is the low-token authoring path, L2 is explicit customization, and L3 is a stable +escape hatch rather than an undocumented deep import. + +## 6. Ownership, RFC edits, and gates + +**[PROPOSAL] Package impact.** Keep the six-package graph. Add the L1 preset and `ContractOf` to +`@netscript/database`; put only `createPrismaPostgresBinding` and provider type mapping in +`@netscript/database-prisma-postgres/binding`; keep lifecycle in `-runtime`. No new package, global +registry, Prisma re-export, or runtime dependency is required. + +To keep the RFC at or below 10k words, replace rather than append: + +- compress `Step 2` into L1 plus the L2 expansion; replace `Step 3`'s generated module with the + type-only binding example above; +- revise “two tracks”/soundness (`lines 702-723`), costs (`1037-1045`), rationale (`1071-1073`), + migration wave 4, introduction diagram, and conclusion wherever generation is stated as universal; +- fold the single-extension rule into the composition example and delete repetitive prose that + separately re-explains target/space fields already specified in the formal contracts. + +Acceptance requires fixtures for direct inference, type-only erasure, root/published +`isolatedDeclarations`, artifact-only fallback, stale atomic watch, plugin single registration, +packed JSR consumers, manifest mismatch refusal, and native query/transaction inference. Kill the +direct path if it needs Prisma private imports, copied overloads, a provider type in a neutral +package, or runtime evaluation of authoring code; then generation must remain automatic, atomic, +launcher-integrated, and invisible. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index d9c49ee7d2..31a99d50c6 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -32,7 +32,7 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | `/root/market_gap_audit` | OpenAI · GPT-5.6 Sol · high | Missing delivery/control/validation comparators and market QA | Complete | | `/root/validation_source_audit` | OpenAI · GPT-5.6 Sol · high | RC contract/result-plan proof for runtime Standard Schema | Complete | | `/root/typescript_schema_audit` | OpenAI · GPT-5.6 Sol · high | Native TypeScript builder evolution and NetScript oRPC transfer | Complete | -| `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Reconcile all evidence into a decision-grade Plan-Gate proposal | Complete | +| `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Plan-Gate synthesis plus repository-grounded `OWNER-DX-01` audit | Complete | | `/root/planned_jsr_audit` | OpenAI · GPT-5.6 Sol · high | Prospective publishability/slow-type review of the planned graph | Complete | These lanes are independent research/synthesis inputs. None is the formal PLAN-EVAL or the @@ -55,6 +55,12 @@ reports and briefs remain immutable evidence. Cycle 2 passed at `383170bbc`; the cycle is requested. Cycle 2 also classified current-main `01e096049` as nonblocking CI/gate-tooling drift and independently confirmed 42 generated `db:*` keys per engine workspace. +After cycle 2, `OWNER-DX-01` explicitly overrode D-07/D-08/D-36. It requires the shipped NetScript +L1 preset/recipe → L2 public factories → L3 native-framework/primitives progression and prefers an +erased source-native `typeof definition` binding over universal generated TypeScript. This is owner +authority applied after evaluation, not a third PLAN-EVAL cycle; the six-package graph and all other +decisions remain locked, and no further PLAN-EVAL will run. + ## RFC authoring and consolidation | Stage | Route / model / effort | Session | Result | @@ -86,6 +92,14 @@ narrowly through GR-01–GR-08; the architecture stands. The deletion ledger est 10,000–10,160 with another safe approximately 80-word cut. The RFC remains frozen at 11,205 words pending Opus dispositions; this is not final acceptance. +The subsequent `OWNER-DX-01` audit is recorded in `research/layered-dx-api-audit.md`. It inspected +the defining service/Hono preset, builder, and native primitives; SDK/Fresh analogues; and pinned +Prisma's runtime `contractJson` plus phantom compile-time contract split. Opus remains the +author/editor responsible for selecting the exact layered API and expressing the W3 proof/fallback +boundary while reducing the RFC to at most 10,000 words. The default is source-native app inference +with runtime manifest/artifact consumption; automatic atomic launcher-integrated declarations are +reserved for proved publish/artifact-only boundaries. + ## Recorded lane/eval overrides - The root session is Codex rather than the default Opus 5 orchestrator. This is the active @@ -135,3 +149,9 @@ pending Opus dispositions; this is not final acceptance. - The owner locked the post-draft sequence: root personal review → Qwen 3.8 Max focused review → Grok 4.6 high whole-RFC adversarial review → Opus author/editor dispositions and consolidation → one final Fable 5 high substantive refinement → mechanical checks only. +- After PLAN-EVAL cycle 2 and the frozen Qwen/Grok review inputs, the owner issued `OWNER-DX-01`. + The override changes D-07/D-08/D-36 only: progressive NetScript adoption layers are required, only + a mirrored Prisma model/field/relation/query DSL is forbidden, and erased source-native app + inference replaces universal generated bindings. It triggers no further PLAN-EVAL. Opus decides + exact API spelling and proves the fallback boundary during the already-planned ≤10k disposition + pass. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 6bdb696be8..4c5771f9d9 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -17,15 +17,17 @@ because the copied generated-workspace task count was factually wrong; evaluator `db:*` keys per workspace for all four providers. After correction, native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. Canonical RFC authorship is unblocked. The consolidated draft is accepted for focused review but is -not finally accepted; no further PLAN-EVAL cycle is planned. +not finally accepted; no further PLAN-EVAL cycle is planned. After cycle 2, the owner issued +`OWNER-DX-01`, overriding D-07/D-08/D-36 to require layered adoption and source-native app inference +by default. This is not a new PLAN-EVAL cycle and leaves the exact six-package graph intact. ### Public Surface and Package Graph - Planned RFC record: `rfcs/0000-database-architecture.md`; its authorship is now unblocked. - `@netscript/database-contract` (A1): plain identities, manifest/plan/receipt/diagnostic schemas, capabilities, ownership, and shared small SPIs; zero provider dependencies. -- `@netscript/database` (A4): thin `defineDatabase`/target/space/policy definitions and pure - deterministic manifest compiler. +- `@netscript/database` (A4): L1 preset/recipe, the L2 `defineDatabase`/target/space/policy + factories it uses, and the pure deterministic manifest compiler. - `@netscript/database-runtime` (A3): process/request lifecycle, connection ownership, health/readiness, cancellation, and validation coordination. - `@netscript/database-control` (A2): programmatic operation catalog, emit/preview/plan/apply/ @@ -37,11 +39,13 @@ not finally accepted; no further PLAN-EVAL cycle is planned. - Existing `@netscript/plugin` (A4), first-party plugins (A5), Aspire (A2), and CLI (A6) receive thin database contribution, connection-source, and operation-projection changes. -Candidate A is the authoring baseline: applications and controlled plugin build inputs call current -model-first Prisma `defineContract`, then pass the exact native value into thin -`defineDatabase`/`defineDatabaseSpace` functions that preserve inference. NetScript neither -recreates the deleted screenshot fluent DSL nor vendors/re-exports Prisma. App-specific inferred -bindings and const-preserving fragment composition are generated application-locally. +Candidate A remains the authoring baseline: current model-first Prisma `defineContract` is schema +authority. NetScript exposes its established L1 preset/recipe → L2 public factories → L3 native +Prisma plus NetScript primitives/ports progression. It bans a mirrored Prisma +model/field/relation/query DSL, vendoring/re-export, copied overloads, private types, and +widening—not progressive orchestration. App-owned contracts prefer erased `typeof definition` +inference while runtime consumes manifest/artifact values; automatic atomic launcher-integrated +declarations are a W3-proven fallback only for publish/artifact-only boundaries. ### Domain Vocabulary @@ -51,7 +55,8 @@ bindings and const-preserving fragment composition are generated application-loc - `ContractArtifact`: canonical provider data/declaration/lineage/provenance, pinned per space. - `DatabaseManifest`: deterministic versioned resolved value and durable join point; a graph is private compiler IR only. -- `AppBinding`: generated app-local inferred target/session/validation bridge. +- `AppBinding`: app-local inferred target/session/validation bridge, source-native by default and + declaration-backed only at a proved boundary. - `TargetRef`/`TargetSession`: explicit identity and lifecycle shell with app-local query generic. - `SpeculativePreview` versus baseline-bound `ExecutablePlan`. - Provider-owned `ProviderMarker`/`ProviderLedger` versus immutable NetScript `OperationReceipt`. @@ -130,14 +135,17 @@ reconciliation, and `e2e-cli-prod` against exact JSR versions. ### Contributor Path and Implementation Waves Contributors author native provider contracts, then declare app-owned fragments or plugin-owned full -spaces. A two-phase generated root collects extension bundles/dependencies first, then invokes -native fragments with exact helpers. Plugin tables default to their own space, artifacts, lineage, -and head; production apply/verify consumes the pinned mirror without plugin code. - -W0 RFC/doctrine plan → W1 contract → W2 definition/compiler → W3 experimental Prisma PostgreSQL -spike → W4 runtime → W5 control → W6 testkit → W7 plugin seam → W8 CLI/agent/adoption → W9 -first-party spaces → W10 clean cutover → W11 second provider only when real/mature. Every wave has -the archetype, source, JSR, consumer, conformance, and release exits recorded in `plan.md`. +spaces. A two-phase root collects extension bundles/dependencies first, then invokes native +fragments with exact helpers. One extension registration fans all facets. Plugin tables default to +their own space, artifacts, lineage, and head; production apply/verify consumes the pinned mirror +without plugin code. Generated type declarations are not universal and, where W3 proves them +necessary, are created automatically in the same atomic launcher-integrated compile. + +W0 RFC/doctrine plan → W1 contract → W2 definition/compiler → W3 experimental Prisma PostgreSQL and +type-boundary spike → W4 manifest-only runtime → W5 control → W6 testkit → W7 plugin seam → W8 +layered CLI/agent/emit-watch adoption → W9 first-party spaces → W10 clean cutover → W11 second +provider only when real/mature. Every wave has the archetype, source, JSR, consumer, conformance, +and release exits recorded in `plan.md`. ## Progress Log @@ -157,6 +165,7 @@ the archetype, source, JSR, consumer, conformance, and release exits recorded in | 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | | 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | | 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | +| 2026-08-13 | 6 | owner-dx | `OWNER-DX-01` audited shipped service/Hono preset→factory→native primitives, SDK/Fresh analogues, and Prisma's runtime `contractJson` plus phantom compile-time contract split. Owner overrode D-07/D-08/D-36 after PLAN-EVAL: source-native app inference is default; automatic declarations are a bounded W3 fallback. No new PLAN-EVAL. | ### RFC Consolidation and Root Acceptance @@ -240,19 +249,19 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ## Decisions -| Decision | Reason | Source | -| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | -| #313 is superseded design evidence | Its additive/compatibility premise conflicts with the owner-directed clean break. | Owner directive + current rebaseline | -| Compiled manifest, not live graph | A plain deterministic value is the durable join point and avoids service location. | Synthesis D-03/D-04 | -| Exact A1/A4/A3/A2/A2/A6 package split | One archetype per responsibility; runtime lifecycle requires A3 gates. | Doctrine + synthesis §4 | -| Native model-first Prisma authoring | Preserve the real current builder/inference; never recreate the deleted fluent screenshot API or another DSL. | TypeScript/oRPC audit + D-06/D-07 | -| App-local inferred binding | Satisfies isolated declarations without expanding the oRPC-only slow-type exception. | Doctrine/JSR audit + D-08 | -| Contract spaces and extension bundles | Plugin ownership/history and one authoring/control/runtime/validation registration replace copied fragments/manual facets. | Prisma source + D-17–D-20/D-38–D-40 | -| Bounded Standard Schema interpreter | Contract runtime data is useful but omits full operation/result types; runtime/JSON schemas fail closed. | Validation source audit + D-21–D-25 | -| Provider-neutral kernel, PostgreSQL-only first adapter | Matches Prisma maturity without compatibility fallback or false portability. | Prisma scorecard/source + D-10/D-11/D-34 | -| NetScript operational semantics, provider migration mechanics | NetScript owns policy/locks/recovery/receipts/saga while provider owns diff/lineage/marker. | Market/source reconciliation + D-27–D-30 | -| PLAN-EVAL before RFC | Architecture has no open must-resolve item but still requires independent acceptance. | Harness Plan-Gate + D-01–D-47 | -| Fable 5 high remains last substantive gate | Explicit owner exception; no substantive model review follows it. | Owner directive | +| Decision | Reason | Source | +| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| #313 is superseded design evidence | Its additive/compatibility premise conflicts with the owner-directed clean break. | Owner directive + current rebaseline | +| Compiled manifest, not live graph | A plain deterministic value is the durable join point and avoids service location. | Synthesis D-03/D-04 | +| Exact A1/A4/A3/A2/A2/A6 package split | One archetype per responsibility; runtime lifecycle requires A3 gates. | Doctrine + synthesis §4 | +| Native model-first Prisma authoring and layered adoption | Prisma owns schema vocabulary; L1 preset uses L2 factories and L3 exposes native Prisma plus NetScript primitives/ports. | OWNER-DX-01 + D-06/D-07/D-36 | +| App-local inferred binding | Prefer erased `typeof definition`; use atomic launcher-integrated declarations only at W3-proven publish/artifact boundaries. | OWNER-DX-01 + D-08 | +| Contract spaces and extension bundles | Plugin ownership/history and one authoring/control/runtime/validation registration replace copied fragments/manual facets. | Prisma source + D-17–D-20/D-38–D-40 | +| Bounded Standard Schema interpreter | Contract runtime data is useful but omits full operation/result types; runtime/JSON schemas fail closed. | Validation source audit + D-21–D-25 | +| Provider-neutral kernel, PostgreSQL-only first adapter | Matches Prisma maturity without compatibility fallback or false portability. | Prisma scorecard/source + D-10/D-11/D-34 | +| NetScript operational semantics, provider migration mechanics | NetScript owns policy/locks/recovery/receipts/saga while provider owns diff/lineage/marker. | Market/source reconciliation + D-27–D-30 | +| PLAN-EVAL before RFC | Architecture has no open must-resolve item but still requires independent acceptance. | Harness Plan-Gate + D-01–D-47 | +| Fable 5 high remains last substantive gate | Explicit owner exception; no substantive model review follows it. | Owner directive | ## Drift @@ -273,14 +282,14 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ### Fitness Gates -| Gate | Result | Evidence | Notes | -| ---------------------------- | --------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | -| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | -| Open-decision sweep | PASS_PLANNED | D-01–D-47 | No must-resolve-now item; pre-wave/deferred items cannot rewrite package boundaries. | -| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | -| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | -| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings remain open; review made no edits. | -| Grok whole-RFC review | PASS_WITH_REFINEMENTS | Session `ses_003644aeaffeSm3UCAW9xUqRIK`; blob `f46040d8...` | Zero blockers; GR-01–GR-08 await disposition. | +| Gate | Result | Evidence | Notes | +| ---------------------------- | --------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | +| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | +| Open-decision sweep | PASS_OWNER_OVERRIDE | D-01–D-47 plus `OWNER-DX-01` | No must-resolve-now item; D-07/D-08/D-36 updated without changing package boundaries. | +| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | +| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | +| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings remain open; review made no edits. | +| Grok whole-RFC review | PASS_WITH_REFINEMENTS | Session `ses_003644aeaffeSm3UCAW9xUqRIK`; blob `f46040d8...` | Zero blockers; GR-01–GR-08 await disposition. | ### Runtime Gates @@ -298,12 +307,14 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ## Handoff Notes - Planning is complete and evaluator-approved at commit `383170bbc`. Cycle 1's failure remains - preserved; cycle 2 passed and no further PLAN-EVAL cycle is requested. + preserved; cycle 2 passed and no further PLAN-EVAL cycle is requested. `OWNER-DX-01` is an + explicit later owner override, not an evaluator rerun. - Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until packages exist and must produce implementation/release receipts later. - The consolidated RFC remains frozen at `5dfc4e8eb` and 11,205 words. Qwen returned `PASS_WITH_CHANGES`; Grok returned `PASS_WITH_REFINEMENTS` and zero blockers. All QF/GR findings and both deletion ledgers await disposition. - Continue the owner-locked order: Opus 5 high author/editor dispositions plus consolidation to at - most 10,000 words, root checks, one final Fable 5 high substantive refinement, and mechanical - checks only. The current checkpoint is not final acceptance. + most 10,000 words, including exact layered API selection and proof of the source-native/fallback + boundary; root checks, one final Fable 5 high substantive refinement, and mechanical checks only. + The current checkpoint is not final acceptance. From ad8effff913356f109f6f93f708bba1cafa27260 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 22:48:00 +0200 Subject: [PATCH 14/19] docs(rfc): apply database architecture review dispositions --- .../claude-opus-rfc-root-corrections.md | 232 +++ rfcs/0000-database-architecture.md | 1530 +++++++++-------- 2 files changed, 1087 insertions(+), 675 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-root-corrections.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-root-corrections.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-root-corrections.md new file mode 100644 index 0000000000..98bf1e6b98 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-root-corrections.md @@ -0,0 +1,232 @@ +# Claude Opus 5 high — root semantic corrections + +You are the **single native Claude Code Opus 5 high lead author/editor** for a bounded correction of +NetScript's database architecture RFC. Continue in `/home/codex/repos/netscript-db-rfc`. + +Edit only: + +```text +rfcs/0000-database-architecture.md +``` + +Do not edit run bookkeeping, plans, research, reviews, briefs, doctrine, source code, generated +files, or locks. Do not use subagents, another model, browsing, or a new research workflow. Do not +commit or push. + +## This brief supersedes the old size gate + +This brief supersedes every instruction in `briefs/claude-opus-rfc-disposition-consolidate.md`, +reviews, worklogs, or messages that sets a word-count target, `<=10k` target, required net deletion, +deletion budget, or size-conditioned completion token. **There is no word-count acceptance gate.** +Do not delete unique evidence, API contracts, safety rules, examples, or explanation to reach a +number. + +The only editorial criteria are semantic completeness, correctness, clarity, useful detail, and +non-duplication. Remove or combine prose only when it says the same thing without adding precision. +Do not add a book: repair the existing sections locally and keep the current heading structure. + +The current worktree RFC is the correction base, not frozen commit `5dfc4e8eb`. At brief creation it +has Git blob `f0b87f19c117d6167ee2a7b2b623aa8aa6e149c7`; verify it before editing and stop rather +than overwrite a different concurrent draft. + +## Required reading and invariants + +Read completely before editing: `AGENTS.md`, the current RFC, `plan.md`, `research.md`, +`research/layered-dx-api-audit.md`, `research/typescript-schema-orpc-audit.md`, +`research/runtime-validation-source-audit.md`, and the existing Qwen/Grok/root reviews. Use the +pinned RC1 checkout under `.llm/tmp/prisma-v8-rc1` only to confirm exact API spelling already named +below; do not widen research. + +Preserve D-01–D-47 except the already-authorized `OWNER-DX-01` refinements to D-07, D-08, and D-36. +Preserve the exact six-package graph, native Prisma schema/query authority, provider-neutral kernel, +PostgreSQL-only first adapter, bounded fail-closed Standard Schema, separate contract spaces, +manifest/plan/ledger/receipt identities, explicit effects and recovery, clean break, and data-safe +adoption. Add no compatibility layer, schema/query mirror DSL, repository facade, provider switch, +global registry, private Prisma import, copied overload, cast workaround, or unsupported claim. + +## Required corrections + +### 1. Make L1 provider ownership and value flow real + +The current L1 imports `definePostgresDatabase` from neutral `@netscript/database`, silently chooses +a PostgreSQL provider, exports no configured provider value, and later claims the composition root +can import/reach that same value. This contradicts all of: the adapter-only provider boundary, the +neutral package's no-provider dependency, the rule that runtime does not consume +`DatabaseDefinition`, and the executable-example promise. + +Correct the same-app progression so: + +- the application creates **one** configured immutable provider value from + `@netscript/database-prisma-postgres` and exports/reuses it in L1/L2, runtime, and control; +- the L1 recipe owned by `@netscript/database` is provider-neutral and accepts that value; it + literally calls L2 and returns the same `DatabaseDefinition`; +- no hidden default, provider lookup, `database.providers` runtime read, or second provider instance + exists; +- the L1 name does not promise a provider-specific implementation from a neutral package. Choose a + concise provider-neutral name/signature consistent with `define` semantics; do not add a package; +- L3 receives the manifest, configured provider, connections, and binding—not the definition. + +Resolve `fromAspire` ownership at the same time. The actual Aspire `ConnectionSource` adapter and +resource projection belong to `@netscript/aspire`. Either import an Aspire-owned pure reference +constructor from that package, or state and type a neutral data-only reference constructor that has +no Aspire implementation/dependency. Do not let `@netscript/database` smuggle in Aspire IO. + +### 2. Register an extension once, early enough for authoring + +The current example first builds `appContract` with Prisma's raw pgvector pack, then separately +registers a NetScript `pgvector(...)` bundle after the contract exists. That is two registration +sites; the later value cannot retroactively provide the authoring facet. + +Show one configured extension value created before native contract construction and a real two-phase +flow: phase 1 collects and identity/version-checks the provider-owned opaque bundle; phase 2 invokes +the native Prisma model-first builder with its public authoring facet and then fans the same bundle +into control, runtime, and validation. The app never assembles/imports Prisma control or runtime +facets. NetScript may orchestrate `defineContract`; it may not mirror its model/field/ +relation/query vocabulary. Keep direct native Prisma authoring as an honest L3 escape hatch and say +precisely whether that escape hatch must pass the same configured bundle's public authoring +projection. + +### 3. Correct examples to the pinned RC1 API + +- Replace `field.timestamp().defaultNow()` with the pinned RC1 temporal helper actually demonstrated + by upstream, such as `field.temporal.createdAt()`. +- Replace Prisma-7-shaped lowercase `orm.post.findMany` / `orm.user.create` calls. Current RC1 ORM + is Pascal-case and fluent: examples use shapes such as + `db.Post.where(...).select(...).take(...).all()` and `db.User.create(...)`. Keep explicit space + selection, but let `space('app').orm` expose that native RC1 surface unchanged. +- Cite the pinned example/source beside claims whose spelling is RC1-specific; do not present a + proposed NetScript wrapper as an observed Prisma API. + +### 4. Make mixed source-native and artifact-only binding sound + +Keep erased `typeof definition` inference for app-authored contracts. A plugin-owned pinned space is +artifact-only at the consumer and TypeScript cannot infer its exact query type from JSON. Therefore +the target binding must explicitly combine: + +- source-native, type-only app contract evidence; and +- an automatically and atomically emitted provider declaration for each artifact-only queried space. + +Show the generated **declaration** imported into the hand-written/real adapter binding value, or +omit an artifact-only space from the typed query map. Do not claim `PrimaryQueries` contains `auth` +without showing its declaration evidence. Each space remains a separate contract type and +`ContractSnapshotId`; no merged Prisma contract or generic-record widening is allowed. The runtime +value is constructed by the adapter `/binding` factory from the manifest/provider identities and is +not an ambient `declare const`. + +Bound the fallback exactly. Automatic declaration emission is for publish/artifact-only boundaries +proved in W3. Do not incidentally say failure of the direct app fixture makes generation universal. +If direct app inference requires a private import, copied overload, cast, provider type in a neutral +package, or runtime authoring evaluation, record it as a W3 kill/rethink criterion. Runtime still +consumes manifest and pinned artifact values; a declaration is type evidence, never control +authority. + +### 5. Make L3 and all example status honest + +L3 must be a complete, coherent example of native Prisma `defineContract` plus NetScript +primitives/ports reaching the same compiler, manifest, adapter binding, runtime, and control—not an +L2 definition relabelled “native foundation.” It may be a compact excerpt, but label it as such. + +Across every snippet, either bind imports/values (`postgres`, `connections`, `runId`, `policy`, +`AccountStore`, plugin contribution factories, generated declarations) or label the code as a +focused excerpt and name the omitted prior value. Do not claim examples are executable exactly as +written while using ellipses, undeclared symbols, a callable constant, or a value exported only by +another layer. Keep examples useful; do not inflate them with irrelevant scaffolding. + +Use “generated declaration” or “generated provider type artifact” for the bounded fallback. Use +“binding” for the real adapter-created runtime value that carries/verifies target, manifest digest, +provider pin, and per-space snapshot ids. The manifest remains the durable runtime/control +authority. + +### 6. Demonstrate a valid validation happy path + +The contract alone does not contain full create/update operation grammar. Before showing +`users.input('create', ...)`, identify the exact registered operation contributor that makes +`create` supported, where it is registered through the single extension/provider flow, and how its +identity/version participates in manifest/cache identity. Do not invent contract-only parity. +Unsupported operations still fail at schema construction; invalid values still return Standard +Schema issues. + +Correct the leakage invariant: **provider-neutral NetScript packages** must never expose Prisma +types. The Prisma adapter's explicitly provider-specific `/binding` declaration necessarily maps +opaque contract evidence to Prisma query/transaction types; do not claim that no published NetScript +declaration anywhere can name Prisma. + +### 7. Repair package dependency and compile/effect wording + +Keep six packages, but state the actual dependency edges rather than an ambiguous chain. +`@netscript/database` depends on `-contract` and owns definitions plus deterministic resolution. +Runtime and control consume manifest/contract SPIs and must not depend on `@netscript/database` for +definition types they never consume. They do not import each other. The adapter implements the +published runtime/control SPIs; the app supplies it as a value. `@netscript/plugin` publishes plain +contributions without provider/runtime/control dependencies. Testkit is never a runtime dependency. + +Reserve mathematically **pure/deterministic** for in-memory resolution of a definition plus supplied +snapshots. Loading source artifacts and atomically publishing emitted artifacts are offline effects; +they may be classified `pure` in the operation catalog only if the RFC explicitly defines that class +as “no live database/network/connection,” not side-effect-free. `compileDatabase` must not be called +both pure/total and an implicit IO loader. Preserve the structural rule that live control never +receives a definition. + +### 8. Complete rollup and plugin artifact semantics + +Make space → target → run rollup a total deterministic function over every terminal status, +including `skipped` and the all-success case. Preserve: target success requires all selected spaces; +unknown/cleanup dominate; mixed space outcomes do not make a target partially successful; run-level +`partial-success` requires at least one successful target and another non-success target; when none +succeeds, use the closed non-success precedence. Do not add another diagram. + +Replace the plugin example's contract-JSON-only `pinnedArtifact(...)` with one coherent pinned-space +aggregate containing descriptor snapshot, canonical contract data **and declaration**, migration +lineage/graph, head, hashes, and provenance. Make the exported symbol's call/value shape consistent +with L1/L2 use. Production package-free apply consumes this aggregate; query typing uses its +automatically emitted consumer declaration without merging spaces. + +### 9. Tell the truth about marker mutation and rollback + +Marker-only adoption performs provider-metadata DML. Replace “zero table or data DDL/DML” with the +precise guarantee: no application-schema DDL and no application/user-data DML; only idempotent, +receipt-backed provider marker/ledger metadata writes occur. Use the same wording in summary, +adoption table, and safety claims. + +If marker removal is not certified safe during pre-apply rollback, do not leave the space actively +`adopted`. Preserve the marker and transition it to the retained, verify-only lifecycle/tombstone +state: no runtime binding, plan, or apply until explicit re-adoption. Keep post-first-apply recovery +forward-only. + +### 10. Add exact pinned source links + +Keep RC1 facts separate from post-RC facts. Add direct pinned GitHub source links—not only local +checkout paths—for the load-bearing current builder, temporal helper/example, phantom runtime +contract overload, fluent Pascal-case ORM example, separate-space aggregate, namespace type-map, and +bounded-validation claims. Reuse existing deep-dive links where they resolve exactly; do not link a +moving branch or marketing page for a source-level claim. + +## Completion standard and checks + +Read the full result once after editing. Confirm that the guide and reference sections add different +value; remove only genuine repetition. Confirm the same configured provider and extension values +flow through all three adoption layers, runtime, and control. Confirm there is no hidden provider, +second registration, merged contract, arbitrary production TypeScript evaluation, manual emit/type +generation ritual, or compatibility path. + +Run: + +```bash +deno fmt rfcs/0000-database-architecture.md +deno fmt --check rfcs/0000-database-architecture.md +deno task docs:links +git diff --check -- rfcs/0000-database-architecture.md +git status --short +``` + +Also inspect the scoped diff and search for the superseded invalid shapes: `defaultNow`, lowercase +Prisma-7 `findMany`, an implicit `definePostgresDatabase` provider, contract-JSON-only plugin +artifact, universal-generation fallback, “zero ... DDL/DML” wording that ignores marker DML, and +provider-neutral Prisma leakage. Do not run or report a word-count gate. + +Return a concise handoff with: native route/session receipt; one disposition row per numbered +correction above; exact RFC sections/lines; confirmation that only the RFC changed; check commands +and exit status; and genuine residual W3/W4/W5/W10/upstream risks. End +`READY_FOR_ROOT_SEMANTIC_REVIEW` only if every correction is applied and checks pass. Otherwise end +`BLOCKED: `. Do not claim final acceptance: root semantic review and the one final +Fable 5 high refinement remain. diff --git a/rfcs/0000-database-architecture.md b/rfcs/0000-database-architecture.md index f46040d8b8..e5ca8a5133 100644 --- a/rfcs/0000-database-architecture.md +++ b/rfcs/0000-database-architecture.md @@ -16,23 +16,27 @@ NetScript replaces its inherited database foundation with one provider-neutral c operations kernel, and certifies exactly one adapter first: Prisma 8 on PostgreSQL. Applications and plugins author schema in **native Prisma TypeScript** — the current model-first -`defineContract(scaffold, callback)` form — and pass that exact native value into a thin NetScript -definition that adds identity, ownership, capability requirements, policy, and lifecycle. NetScript -adds no schema vocabulary of its own: no query DSL, no model language, no re-exported builder. A -pure compiler resolves those definitions into canonical contract artifacts and one deterministic, -content-addressed `DatabaseManifest`. The manifest is the durable join point for everything -downstream: a generated application-local binding whose types are inferred from the native contract, -typed process/request sessions, bounded `StandardSchemaV1` validators at trust boundaries, -programmatic emit/inspect/plan/apply/verify operations, provider markers and ledgers, immutable -operation receipts, and generated CLI, documentation, and agent surfaces. +`defineContract(scaffold, callback)` form — and pass that exact native value into NetScript's own +adoption surface, which adds identity, ownership, capability requirements, policy, and lifecycle. +That surface has the three levels NetScript already uses for Hono, the SDK, and Fresh: an **L1 +recipe** for the golden path, the **L2 factories** it calls, and **L3 native Prisma plus kernel +primitives**. None of them describes a model, field, relation, or query: NetScript adds no schema or +query vocabulary and re-exports no builder. A compiler with no live dependencies resolves those +definitions into canonical contract artifacts and one deterministic, content-addressed +`DatabaseManifest`. That manifest is the durable join point for everything downstream: an app-local +binding typed from the authored contracts by erased inference, with an automatically emitted +declaration supplying the same evidence for any space the consumer did not author; typed +process/request sessions; bounded `StandardSchemaV1` validators; programmatic +emit/inspect/plan/apply/verify operations; provider markers and ledgers; immutable receipts; and +generated CLI, Aspire, and agent projections. The end-to-end flow is one pipeline of separately named values, and no stage may impersonate another: ```text native contracts + NetScript definitions - → pure composition → ContractArtifacts → DatabaseManifest - → generated app-local binding → sessions + bounded validators + → deterministic composition → ContractArtifacts → DatabaseManifest + → app-local binding → sessions + bounded validators → inspected baseline → ExecutablePlan → provider apply/ledger → immutable OperationReceipts → verify / resume ``` @@ -40,30 +44,26 @@ native contracts + NetScript definitions This is a clean break. There is no compatibility API, no Prisma 7 fallback, no dual runtime, no legacy adapter facade, and no application that composes both stacks. Data continuity is nevertheless absolute: `netscript db adopt` introspects live databases, proposes ownership, writes provider -marker metadata only, and performs **zero** table or data DDL/DML before verification. +marker metadata only, and performs **no application-schema DDL and no application-data DML** — the +only writes are idempotent, receipt-backed provider marker and ledger rows. Two acceptance conditions bind implementation, and the design is narrowed rather than softened if either fails: > **Exact native contract inference survives into the app-local query binding** — no private -> imports, no copied overloads, no casts, no declaration widening. +> imports, no copied overloads, no casts, no widening, and no manual type-generation step in a +> developer's normal loop. > > **Runtime validation is intentionally bounded and fails closed** — a schema is produced only where -> the contract plus registered operation, selection, codec, and extension metadata can prove it; -> everything else raises `DB_VALIDATION_UNSUPPORTED` at schema construction. +> the contract plus registered operation, selection, codec, and extension metadata can prove it. Explicit non-goals: no query DSL or repository layer, no portable client facade, no runtime -capability negotiation, no global provider registry, no hosted control plane, and no capability -claimed before a conformance gate proves it. Where a capability cannot be made sound today — -multi-namespace end-to-end typing, full Prisma operation validation from contract data, destructive -plugin removal, non-PostgreSQL providers — this RFC withholds the claim and names the gate that -would release it. - -The approved architecture, the locked decision ledger (D-01–D-47), the implementation waves -(W0–W11), and the conformance and publishability matrices live in the +capability negotiation, no global provider registry, and no hosted control plane. Where a capability +cannot be made sound today — multi-namespace typing, full operation validation from contract data, +destructive plugin removal, non-PostgreSQL providers — this RFC withholds the claim and names the +gate that would release it. The locked decision ledger, waves, and conformance matrices live in the [approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md); the evidence -behind every upstream claim lives in the linked research artifacts. This document is the decision -and the developer experience. +behind every upstream claim lives in the linked research artifacts. ## Motivation @@ -75,8 +75,8 @@ engine registry and operation runner, a generated per-engine Prisma workspace an runtime adapter wrapping a user-constructed Prisma client, and an install-time plugin fragment copier. The happy path works only when all five agree about config keys, engine directory names, environment variables, generated files, Prisma CLI behaviour, adapter packages, and a live Aspire -resource graph — an agreement the framework makes a developer and CI responsibility. There is no -canonical value joining the five views, so every fix lands in one of them and the failure moves +resource graph — an agreement the framework makes a developer and CI responsibility. No canonical +value joins the five views, so every fix lands in one of them and the failure moves ([current-state audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md)). Three defects are structural rather than incidental. @@ -86,116 +86,117 @@ Three defects are structural rather than incidental. (`packages/cli/src/kernel/adapters/database/workspace-resolver.ts:51`), so two PostgreSQL databases share one schema tree, one migration history, one generated client, and one task set: `db add postgres --name analytics` writes another configuration entry but still resolves -`database/postgres/`. `resolveTarget` defaults only when exactly one target is enabled and never -consults `NetScript.PrimaryDatabase` (`:66-91`), so a bare command with two enabled targets throws -`Unknown database target: (default)`, contradicting the documentation. Engine selection is a -`switch` over `'postgres' | 'mysql' | 'sqlite' | 'mssql'` — the literal counter-example doctrine -records as AP-24 +`database/postgres/`. Engine selection is a `switch` over +`'postgres' | 'mysql' | 'sqlite' | 'mssql'` — the literal counter-example doctrine records as AP-24 ([anti-patterns](../docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md)) — and every downstream artifact inherits that collapse. -**Generation is a repair pipeline, not an emission.** The nominal `db:generate` path performs -placeholder removal, client generation, a second generation through a Zod wrapper, four kinds of -source rewriting, a generated CRUD alias barrel, client renaming and facade patching, and a further -repair pass. The result is non-atomic generated source that NetScript mutates from upstream textual -output, and a developer can edit the schema, skip the pipeline, and keep compiling against stale -types. Pure code generation also boots Aspire — the open `DB-GENERATE-ASPIRE-COUPLING` debt entry. +**Generation is a repair pipeline, not an emission.** The nominal `db:generate` path removes +placeholders, generates a client, generates again through a Zod wrapper, rewrites the result four +ways, builds an alias barrel, patches a facade, and repairs once more — non-atomic generated source +that NetScript mutates from upstream textual output, while a developer can edit the schema, skip the +pipeline, and keep compiling against stale types. Pure code generation also boots Aspire, the open +`DB-GENERATE-ASPIRE-COUPLING` debt entry. **Plugin schema contribution has no ownership semantics.** Plugins ship plain `database/**/*.prisma` -files; on install the CLI copies each fragment into the consumer's schema tree, scans top-level -blocks with a regex/balanced-brace parser, removes byte-identical declarations, and rejects -same-name declarations with different bodies. That cannot express a contribution contract, schema -version, capability requirement, dependency order, declaration or migration ownership, uninstall -data policy, or provenance, and its failure modes are on record: dependency-mode installs reported -success while omitting every plugin table ([#1014][ns-1014]), and model-name clashes broke -authentication installs until namespacing plus a collision guard landed ([PR #1059][ns-1059]). -Removal deletes a directory; it plans no migration at all. +files that the CLI copies into the consumer's schema tree, scanning top-level blocks with a regex +parser and rejecting same-name declarations with different bodies. That cannot express a +contribution contract, schema version, capability requirement, dependency order, declaration or +migration ownership, uninstall data policy, or provenance, and its failure modes are on record: +dependency-mode installs reported success while omitting every plugin table ([#1014][ns-1014]), and +model-name clashes broke authentication installs until namespacing plus a collision guard landed +([PR #1059][ns-1059]). Removal deletes a directory; it plans no migration. The operational history says the same thing from a different angle. Each row below cost real recovery time, and each is a missing architectural concept rather than a missing feature: -| Incident | Lesson the architecture must encode | -| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| A read-only command killed the resident AppHost | Operations need one lifecycle owner and an operation class | -| A second AppHost mounted live `PGDATA` and corrupted it | Operations must bind an authoritative resolved value, not rebuild it | -| Headless migrate returned success with no artifact | An exit code is not a result; operations need typed postconditions | -| A generated Zod alias hid symbols; its repair broke boot | Generated symbol paths cannot be the framework contract, and validation needs a standards-facing boundary | +| Incident | Lesson the architecture must encode | +| -------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| A read-only command killed the resident AppHost | Operations need one lifecycle owner and an operation class | +| A second AppHost mounted live `PGDATA` and corrupted it | Operations bind an authoritative resolved value, never rebuild it | +| Headless migrate returned success with no artifact | An exit code is not a result; operations need typed postconditions | +| A generated Zod alias hid symbols; its repair broke boot | Generated symbol paths cannot be the contract; validation needs a standards-facing boundary | Substituting Prisma 8 for Prisma 7 under this structure would preserve every one of those seams. ### Why Prisma 8 changes the calculus Prisma 8 is not Prisma 7 with a new generator. Its source is arranged as a canonical contract plus -separate control and execution planes: PSL or a TypeScript contract builder lowers into a canonical -`contract.json` and a `contract.d.ts`, a small versioned runtime consumes the contract, a -programmatic control client exposes emit/inspect/plan/apply, migrations are content-addressed graph -edges with per-space markers and a ledger, and **contract spaces** make one contributor's +separate control and execution planes: PSL or a TypeScript builder lowers into a canonical +`contract.json` and `contract.d.ts`, a small versioned runtime consumes the contract, a programmatic +control client exposes emit/inspect/plan/apply, migrations are content-addressed graph edges with +per-space markers and a ledger, and **contract spaces** make one contributor's `(contract, migration graph, head ref)` a first-class disjoint tuple ([ADR 212][adr-212]). That -attacks NetScript's pain points at the root: generated executable client source disappears, -source-rewriting and validator repair passes disappear, schema ownership is modelled instead of -inferred from copied files, migrations are planned and verified programmatically, structured results -replace log scraping, and family/target/adapter/driver/extension become distinct axes instead of one -`engine` string +replaces generated client source, source rewriting, copied-file ownership, log scraping, and the +single `engine` string with modelled equivalents ([deep dive](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md)). It is also not a safe surface to expose directly, and this RFC treats that as a design input: -- Prisma 8 RC1 is Early Access and explicitly not recommended for production ([README][rc1-readme]); - its release notes warn that RC respins may break, remove, or rename APIs and the contract format - ([release][rc1-release]). PostgreSQL is the sole database intended for the 8.0 GA target set; +- RC1 is Early Access and explicitly not recommended for production ([README][rc1-readme]); its + notes warn that respins may break, remove, or rename APIs and the contract format + ([release][rc1-release]). PostgreSQL is the sole database intended for the 8.0 GA target set — MongoDB is Early Access, SQLite a proof of concept, MySQL later, SQL Server absent ([scorecard][rc1-scorecard]). -- `@prisma/orm-postgres` — the one package an application installs — publishes 138 top-level export - subpath keys at the pin, spanning adapters, control internals, contract internals, migration - tooling, query ASTs, runtime, target planning, and utilities. A framework that re-exported that - surface would convert upstream Early-Access internals into NetScript public API. -- The integration seam moved materially within six days of the RC tag: the `prisma-next` CLI stopped - being published in favour of a unified CLI ([`3dc98cb`][pn-3dc98cb]), migration and database - commands were routed through the control API, contract JSON Schema became generated, the - PostgreSQL floor dropped from 17 to 15, and aggregate number semantics changed. +- `@prisma/orm-postgres`, the one package an application installs, publishes 138 top-level export + subpath keys at the pin, spanning adapters, control and contract internals, migration tooling, + query ASTs, runtime, and utilities; re-exporting that surface would convert Early-Access internals + into NetScript public API. +- The seam moved within six days of the RC tag: the `prisma-next` CLI stopped being published in + favour of a unified CLI ([`3dc98cb`][pn-3dc98cb]), migration commands moved behind the control + API, contract JSON Schema became generated, the PostgreSQL floor dropped from 17 to 15, and + aggregate number semantics changed. The correct response to a good architecture on a moving surface is to adopt its _semantics_ through one small allowlisted adapter, and keep NetScript's own vocabulary, artifacts, and operations stable -across the churn. What that unlocks: a developer declares targets and spaces once, authors schema in -native Prisma TypeScript, and receives query types, lifecycle-owned sessions, boundary validators, -migrations with plans and receipts, plugin schema ownership with independent history, structured CI -evidence, and a generated agent surface — without a copied schema, a hand-synchronised type, a -hand-written adapter, a textual repair, or an implicit target choice. +across the churn. ## Guide-level explanation This section describes the system as if it had shipped. -> **Example status.** Examples importing `@netscript/*` are intended to be executable exactly as -> written once the packages in [§ The package graph](#the-package-graph) exist. Examples importing -> `@prisma/*` show the current RC1 authoring shape; the exact module specifier is an adapter-pinned, -> implementation-time decision (wave W3). Prisma's own public CLI package name changed six days -> after the RC tag, so freezing an upstream specifier into a NetScript contract would be a design -> error. +> **Example status.** A snippet with a file-path comment and imports is a complete module for the +> packages in [§ The package graph](#the-package-graph); a snippet marked _excerpt_ names the values +> it assumes from an earlier one. `@netscript/*` shapes are proposed API. `@prisma/*` shapes are +> observed in the pinned RC1 checkout and linked to it; the exact module specifier is an +> adapter-pinned, implementation-time decision (W3), because Prisma's public CLI package name +> changed six days after the RC tag. ### Step 1 — author the contract natively Schema authoring is Prisma's job and NetScript does not put a vocabulary in front of it. The current authoring API is model-first: `defineContract(scaffold, callback)`, where the callback receives a composed helper surface and returns native `types`, `models`, and `enums` -(`packages/3-extensions/postgres/src/contract/define-contract.ts:46-121`; the callback overload -preserves its returned literal types). +([`define-contract.ts`][rc1-define-contract]; the callback overload preserves its returned literal +types). + +One thing precedes the contract: the extension bundle. A logical extension such as pgvector has +authoring, control, runtime, and validation facets, and the authoring facet has to exist _before_ +the builder runs, so the application configures the bundle once and passes its **public authoring +projection** into `defineContract`: + +```ts +// database/extensions.ts — one configured, identity- and version-checked bundle +import { pgvector } from '@netscript/database-prisma-postgres'; + +export const vector = pgvector({ dimensions: 1536 }); +``` ```ts // database/app.contract.ts — provider-native authoring; specifier pinned in W3 -import pgvector from '@prisma/orm-extension-pgvector/pack'; import { defineContract, rel } from '@prisma/orm-postgres/contract-builder'; +import { vector } from './extensions.ts'; export const appContract = defineContract( - { extensions: { pgvector } }, + { extensions: { pgvector: vector.authoring } }, // the bundle's authoring facet, not a second import ({ field, model, type }) => { const types = { Embedding: type.pgvector.Vector(1536) } as const; const User = model('User', { fields: { id: field.id.uuidv4String(), - email: field.text().unique(), - createdAt: field.timestamp().defaultNow(), + email: field.text(), + createdAt: field.temporal.createdAt(), }, }); @@ -204,6 +205,7 @@ export const appContract = defineContract( id: field.id.uuidv4String(), userId: field.uuidString(), title: field.text(), + createdAt: field.temporal.createdAt(), embedding: field.namedType(types.Embedding).optional(), }, }); @@ -219,32 +221,75 @@ export const appContract = defineContract( ); ``` -Three things NetScript will **not** do to that code. It will not recreate the older fluent -`target(...).table(...).column(...)` chain — that API was real but was replaced by the model-first -redesign and then removed upstream. It will not introduce a NetScript model DSL that lowers into the -same contract. And it will not vendor or re-export Prisma's builder as though NetScript owned it. +Every helper above is the pinned RC1 spelling, including `field.temporal.createdAt()` and the +`type.pgvector.Vector(1536)` named type ([pinned contract example][rc1-contract-example]). NetScript +neither recreates the fluent `target(...).table(...).column(...)` chain that upstream removed, nor +mirrors this vocabulary in a schema or query DSL of its own, nor re-exports Prisma's builder — it +owns only the orchestration around the contract, and that surface has three levels. -### Step 2 — declare targets and spaces +### Step 2 — three levels of adoption, one application -NetScript's own authoring surface adds identity, ownership, capability requirements, policy, and -lifecycle around that native value — and nothing else. +The same app and the same `appContract` appear at every level. L1 calls L2; L2 produces the value +L3's primitives consume. Nothing below defines a model, field, relation, or query. + +**L1 — the golden path.** One call with inspectable, replaceable defaults: target id `primary`, app +space `app`, managed ownership, and retain-on-removal. The provider is **not** one of the defaults — +the application constructs exactly one configured provider value and hands it in, so a +provider-neutral package never chooses, imports, or looks up a provider. ```ts // database/database.ts +import { fromAspire } from '@netscript/aspire'; +import { defineSingleTargetDatabase } from '@netscript/database'; +import { prismaPostgres } from '@netscript/database-prisma-postgres'; +import { authSpace } from '@netscript/plugin-auth-core/database'; +import { appContract } from './app.contract.ts'; +import { vector } from './extensions.ts'; + +/** The one configured provider value. Targets, runtime, and control all receive this object. */ +export const postgres = prismaPostgres({ minVersion: 15 }); + +export default defineSingleTargetDatabase({ + provider: postgres, + contract: appContract, + connection: fromAspire('netscript-db'), + spaces: [authSpace()], // plugin-owned schema, independently versioned + extensions: [vector], // the same bundle the contract was authored with +}); +``` + +`defineSingleTargetDatabase` is provider-neutral: it names the shape it supports (one target, one +app space) rather than promising a PostgreSQL implementation from a package that has no provider +dependency, and it literally calls the L2 factories below and returns the same `DatabaseDefinition`. +`fromAspire` is an Aspire-owned **pure reference constructor** exported by `@netscript/aspire`; it +builds plain connection-reference data and performs no IO, and the matching `ConnectionSource` +adapter that resolves it lives in the same package. `@netscript/database` exports only the neutral +`fromEnv` equivalent and never imports Aspire. + +**L2 — the factories L1 calls.** Drop one level for a second target, an explicit policy, a role, or +several app-owned spaces. The recipe is not a parallel implementation: it calls exactly these, and +returns the same `DatabaseDefinition`. + +```ts +// database/database.ts — the same app, one level down +import { fromAspire } from '@netscript/aspire'; import { defineDatabase, defineDatabaseSpace, defineDatabaseTarget, - fromAspire, fromEnv, } from '@netscript/database'; import { prismaPostgres } from '@netscript/database-prisma-postgres'; import { authSpace } from '@netscript/plugin-auth-core/database'; import { appContract } from './app.contract.ts'; +import { vector } from './extensions.ts'; +import { warehouseContract } from './warehouse.contract.ts'; + +export const postgres = prismaPostgres({ minVersion: 15 }); // configured once, reused everywhere const primary = defineDatabaseTarget({ id: 'primary', - provider: prismaPostgres({ minVersion: 15 }), + provider: postgres, connection: fromAspire('netscript-db'), roles: { writer: {}, 'reader:reporting': { readOnly: true } }, policy: { destructive: 'deny', defaultOwnership: 'managed' }, @@ -252,7 +297,7 @@ const primary = defineDatabaseTarget({ const analytics = defineDatabaseTarget({ id: 'analytics', // same provider, different database, zero shared state - provider: prismaPostgres({ minVersion: 15 }), + provider: postgres, connection: fromEnv('ANALYTICS_DATABASE_URL'), policy: { destructive: 'plan-only', defaultOwnership: 'adopted' }, }); @@ -269,126 +314,225 @@ export default defineDatabase({ policy: { removal: 'retain' }, }), auth: authSpace({ target: 'primary' }), + warehouse: defineDatabaseSpace({ + id: 'warehouse', + owner: 'app', + version: '1.0.0', + target: 'analytics', + contract: warehouseContract, + }), }, + extensions: [vector], // the same configured bundle, still registered exactly once }); ``` -The important property is what `defineDatabaseSpace` does to `appContract`: nothing. It stores the -value and preserves `typeof appContract` unchanged. NetScript never reinterprets models, never -copies Prisma overloads, and never widens the contract into a generic record. Everything NetScript -adds — `id`, `owner`, `version`, `target`, `dependencies`, capability requirements, ownership, -retention — is plain data that survives a provider replacement. +Adding `analytics` is the entire multi-target delta. The two targets share nothing — separate output +roots, artifacts, lineages, markers, bindings, locks, and receipts — a relation between their models +is refused with `db.compose.cross-target-relation`, and no multi-target operation is ever described +as atomic. -The second property is where the target key is checked. `defineDatabaseSpace` is evaluated on its -own and cannot know the keys of a `targets` object that does not exist yet, so it does **not** -promise a type error at its own call site. The check happens where both halves are visible: the -`spaces` parameter of `defineDatabase` requires every space's target to be a key of `targets`, so -`target: 'primry'` is a type error at the `defineDatabase` call. If the type check is bypassed — -JavaScript callers, generated input, `as` casts — composition refuses with -`db.compose.target.unknown` rather than falling back. Today's installer resolves a target through a -fallback chain that can end at a **disabled** target; under this design there is no fallback chain -anywhere in the system. +`defineDatabaseSpace` stores `appContract` and preserves `typeof appContract` unchanged; everything +NetScript adds is plain data that survives a provider replacement. The target key is checked where +both halves are visible: `defineDatabase` requires every space's target to be a key of `targets`, so +`target: 'primry'` is a type error at that call, and a bypassed check is refused with +`db.compose.target.unknown` — there is no fallback chain anywhere. -### Step 3 — the generated binding and typed sessions - -Composition emits canonical artifacts and one manifest, and the emitter writes a small -application-local binding module. That module is where inferred provider types live — never inside a -published NetScript package. +**L3 — the native foundation.** The same native contract and the same definition value, but the +application drives the pipeline itself instead of letting the launcher do it: compiler → manifest → +adapter binding → runtime → control, with no NetScript magic in between. ```ts -// .netscript/database/primary.binding.ts — GENERATED. Do not edit. -// manifest nsdb1:9f3c… · contract cs:7ab2… · provider @prisma/orm-postgres@ -import type { QueryOf, TransactionQueryOf } from '@netscript/database-prisma-postgres/binding'; -import type { AppBinding, ProcessTargetSession } from '@netscript/database-runtime'; -import type { AppContract } from './primary/contract.d.ts'; - -export type PrimaryQuery = QueryOf; -export type PrimaryTxQuery = TransactionQueryOf; -export type PrimarySession = ProcessTargetSession<'primary', PrimaryQuery, PrimaryTxQuery>; - -export declare const primaryBinding: AppBinding<'primary', PrimaryQuery, PrimaryTxQuery>; -export declare const PRIMARY_MANIFEST_DIGEST: 'nsdb1:9f3c…'; -``` +// tools/pipeline.ts — excerpt. `database` and `postgres` come from database/database.ts above, +// `primaryBinding` from database/binding.ts below, `connections` from Step 3's composition root, +// and `io` is the artifact source/publisher pair the launcher normally supplies. +import { compileDatabase } from '@netscript/database'; +import { createDatabaseControl } from '@netscript/database-control'; +import { createDatabaseRuntime } from '@netscript/database-runtime'; -One generic model is used everywhere: a binding carries -`(target id, query type, transaction query -type)`, and every session type is parameterised by -exactly those three. `QueryOf` and `TransactionQueryOf` are provider-specific helpers exported by -the adapter for generated code only; no provider-neutral package ever names them. +const compiled = await compileDatabase(database, io); // offline effects only; no connection in scope +if (!compiled.ok) throw new DatabaseCompositionError(compiled.diagnostics); -```ts -// composition-root.ts — hand-written, and the only place a target is bound by name -import { createDatabaseRuntime } from '@netscript/database-runtime'; -import { prismaPostgres } from '@netscript/database-prisma-postgres'; -import { manifest } from './.netscript/database/manifest.ts'; -import { primaryBinding, type PrimarySession } from './.netscript/database/primary.binding.ts'; +const { manifest } = compiled; // durable, content-addressed; the only value passed on from here await using runtime = await createDatabaseRuntime({ manifest, - providers: [prismaPostgres], - targets: ['primary'], + providers: [postgres], + bindings: [primaryBinding], scope: 'process', connections, }); -const primary: PrimarySession = runtime.bind(primaryBinding); -const accounts: AccountStore = new PrismaAccountStore(primary); +const control = createDatabaseControl({ manifest, providers: [postgres] }); ``` -Feature code receives `AccountStore` — an application-owned port — not the runtime. `runtime.bind` -is reachable only from declared composition-root and generated files, enforced as an `arch:check` -rule, because a database handle reachable from anywhere is a service locator with a domain name. -NetScript does not generate repositories and does not define what `AccountStore` looks like; that is -application architecture. - -Inside the session, the query surface is Prisma's own: +Nothing downstream of `compileDatabase` receives the `DatabaseDefinition`: runtime and control take +the manifest, the configured provider, connections, and bindings. The binding itself is the one +place where app-local type evidence and emitted artifacts meet: ```ts -const recent = await primary.query.orm.post.findMany({ - where: { userId: input.userId }, - select: { id: true, title: true }, +// database/binding.ts — hand-written once +import type { ContractOf } from '@netscript/database'; +import type { ProcessSessionOf } from '@netscript/database-runtime'; +import { + createPrismaPostgresBinding, + type QueriesOf, +} from '@netscript/database-prisma-postgres/binding'; +// Source-native evidence: type-only, erased at run time. +import type database from './database.ts'; +// Generated declaration: the auth space is artifact-only here, so its exact type cannot be +// reconstructed from JSON. The launcher emits this declaration atomically during the same compile. +import type { AuthContract } from '../.netscript/database/primary/auth.contract.d.ts'; +import { manifest } from '../.netscript/database/manifest.ts'; // emitted value + +export const primaryBinding = createPrismaPostgresBinding<{ + app: ContractOf; + auth: AuthContract; +}>({ + target: 'primary', + manifest, // carries the ManifestDigest, provider pin, and per-space ContractSnapshotIds }); -await primary.transaction(async (tx) => { - await tx.orm.user.create({ data: { email: input.email } }); - await tx.orm.post.create({ data: { userId: input.userId, title: 'Hello' } }); +export type PrimaryQueries = QueriesOf; // { app: …; auth: … } +export type PrimarySession = ProcessSessionOf; +``` + +The type argument is a **literal, space-keyed map** and each entry carries its own evidence: `app` +from erased source inference, `auth` from a generated declaration. Prisma contract spaces are +separate contracts with separate artifacts and heads ([space aggregate][rc1-space-aggregate]), so +the binding never merges them into one contract or one query type, and each entry keeps its own +`ContractSnapshotId`. An application that does not query a pinned space simply omits it from the +map: the space is still planned, applied, and verified — it just has no typed query surface. +Claiming `auth` in `PrimaryQueries` without importing its declaration would be the unsound version +of this, and the emitter refuses to produce a binding whose map names a space it has no evidence +for. `primaryBinding` is a real value constructed by the adapter factory from the manifest's +identities — never an ambient `declare const`. + +#### Who owns what + +| Surface | Owner | Source of truth | Produces / lowers to | Must not cross | +| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| `defineContract`, ORM and SQL query surfaces | `@prisma/orm-postgres`, imported directly by app and plugin authoring modules | Prisma | native contract value, `contract.json`, `contract.d.ts` | never mirrored, wrapped, or re-exported by NetScript | +| L1 `defineSingleTargetDatabase` and the L2 `defineDatabase*` factories | `@netscript/database` | this RFC | L1 calls L2 → one `DatabaseDefinition` → `resolveDatabase`/`compileDatabase` | no schema or query vocabulary, no provider import, no live IO | +| `prismaPostgres(...)` and `pgvector(...)` bundles | `@netscript/database-prisma-postgres` (or an extension publisher inside that boundary) | the adapter | one opaque configured value carrying identity, version, capabilities, and four facets | control/runtime facets never leave the provider boundary; the app touches only `.authoring` | +| `fromAspire` and its `ConnectionSource` adapter | `@netscript/aspire` | Aspire | plain connection-reference data, resolved at runtime | reference construction performs no IO; the kernel never imports Aspire | +| `createPrismaPostgresBinding`, `QueriesOf` | `@netscript/database-prisma-postgres/binding` | app-local `typeof` evidence + emitted declarations + manifest | per-space query/transaction types and a digest-verifying runtime value | provider-specific by design; never a provider-neutral query API | +| Sessions, validators, ports | `@netscript/database-runtime`, `@netscript/database-control` | manifest, binding, pinned artifacts | typed sessions, Standard Schema values, plans, receipts | provider-neutral packages never name a Prisma type | +| CLI, Aspire resources, agent surfaces | `@netscript/cli`, `@netscript/aspire` | `DatabaseManifest` + operation catalog | commands, resources, agent schemas | never evaluates authoring TypeScript | + +#### The normal loop has no manual type generation + +`netscript dev`, `start`, `test`, and `build` compile the authoring graph to a content-addressed +artifact set before the runtime loads; generated task dependencies give a plain `deno task` the same +behaviour. `dev` watches the graph, writes a temporary artifact set, verifies it, and atomically +swaps the directory before restarting affected consumers — which is also how the generated +declaration for an artifact-only space stays current without anyone running a type-generation +command. CI runs an explicit `netscript db emit --verify` compile-and-diff so a stale commit fails +there rather than in production. A digest mismatch is still a hard refusal that names the file that +changed, but the normal launcher has already repaired it, so `db emit` is an escape hatch, never a +ritual. Compilation is not migration: it reads authoring sources and publishes artifacts, and it +never opens a connection, plans, or applies. Plan and apply authority stays explicit. + +### Step 3 — sessions and queries + +```ts +// composition-root.ts — hand-written; the only place a target is bound by name +import { aspireConnections } from '@netscript/aspire'; +import { + createDatabaseRuntime, + envConnections, + resolveConnections, +} from '@netscript/database-runtime'; +import { manifest } from './.netscript/database/manifest.ts'; +import { postgres } from './database/database.ts'; +import { primaryBinding, type PrimarySession } from './database/binding.ts'; + +const connections = await resolveConnections(manifest, [aspireConnections, envConnections]); + +await using runtime = await createDatabaseRuntime({ + manifest, + providers: [postgres], + bindings: [primaryBinding], + scope: 'process', + connections, }); + +const primary: PrimarySession = runtime.bind(primaryBinding); // digests verified before any query +const accounts: AccountStore = new PrismaAccountStore(primary); // application-owned port ``` -There is no NetScript query language wrapping those calls, and there never will be. The transaction -callback receives the binding's `PrimaryTxQuery`, which is inferred from the same contract but is a -**distinct** type: whether an interactive transaction can expose exactly the ordinary query surface -is an upstream behaviour W4 must prove, so the design does not assert it in advance. Interactive -transactions exist only on process-scoped sessions; a request-scoped session is `AsyncDisposable`, -caches no collaborators, and its type has no `transaction` member at all. +```ts +// accounts.store.ts — application-owned adapter; `space` selects one contract space, +// and the surface inside it is Prisma's own (shapes follow the pinned RC1 ORM examples). +export class PrismaAccountStore implements AccountStore { + constructor(private readonly primary: PrimarySession) {} + + recentPosts(userId: string, limit: number) { + return this.primary.space('app').orm.Post + .where({ userId }) + .orderBy((post) => post.createdAt.desc()) + .take(limit) + .all(); + } + + register(id: string, email: string) { + return this.primary.transaction( + 'app', + (tx) => tx.orm.User.select('id', 'email').create({ id, email }), + ); + } +} +``` + +Those are the RC1 collection shapes verbatim — Pascal-case models, fluent +`where(...).orderBy(...).take(...).all()` reads and `select(...).create(...)` writes +([reads][rc1-orm-read], [writes][rc1-orm-write]). `space('app')` hands back the provider's own +facade, so `.orm` is the ORM collection client and `.sql` is the same SQL DSL escape hatch the +provider already ships; NetScript wraps neither and adds no query language of its own. `postgres` is +the identical configured provider value the target declared, imported from the application's own +database module, so no composition root builds a second one. Connections are resolved from the +manifest's connection references through `ConnectionSource` adapters, which is the only place Aspire +enters the picture. + +Feature code receives `AccountStore` — an application-owned port — not the runtime. `runtime.bind` +is reachable only from declared composition-root files, enforced by `arch:check`, because a database +handle reachable from anywhere is a service locator with a domain name; NetScript generates no +repositories. + +Space selection is explicit because spaces are separate contracts, and the transaction callback +receives that space's own inferred transaction type, **distinct** from its query type: whether an +interactive transaction exposes exactly the ordinary surface is upstream behaviour W4 must prove. +Interactive transactions exist only on process-scoped sessions; a request-scoped session is +`AsyncDisposable`, caches no collaborators, and has no `transaction` member at all. ### Step 4 — validation at trust boundaries -The same contract that types the query surface produces Standard Schema validators, with no -generated validator file anywhere in the repository: +Validators come from the registered values, not from the contract alone, and there is no generated +validator file anywhere in the repository. The contract proves model **values**; the create, update, +and filter grammar the collection surface accepts is compile-time-only at run time (see +[§ the runtime validation subsystem](#the-runtime-validation-subsystem)), so an **operation pack** +has to contribute it. The configured provider value carries exactly one — `prismaPostgres` registers +`ormCollection@1`, covering the RC1 collection grammar — through the same single registration flow +as every other facet: no second import, no separate validator wiring. That pack's `(id, version)` is +recorded in the manifest beside the provider pin and enters every derived validator's cache key, so +`input('create', …)` below is supported _because_ `ormCollection@1` is registered for this space. A +space whose provider or extensions contribute no pack for an operation fails at schema construction +instead of guessing. ```ts -import { primaryBinding } from './.netscript/database/primary.binding.ts'; +import { primaryBinding } from './database/binding.ts'; const users = primaryBinding.ref({ space: 'app' }).model('User'); const createUser = users.input('create', { representation: 'json' }); -const publicUser = users.output( - { select: { id: true, email: true } }, - { representation: 'json' }, -); +const publicUser = users.output({ select: { id: true, email: true } }, { representation: 'json' }); const wholeUser = users.output('model', { representation: 'json' }); ``` -Two methods and two representations, and the two methods mean materially different things. `input` -produces an **operation input** schema and exists only where the provider or an extension has -contributed exact metadata for that operation. `output` produces a **selected result** schema for -the shape actually requested, or the whole-model shape under the explicit `'model'` form. The only -public representations are `runtime` and `json`; the database-driver wire representation is a third -channel upstream and stays adapter-internal, because calling JSON "wire" would be ambiguous. - -Those values implement `StandardSchemaV1`, so they drop into independent consumers unchanged — and -each boundary uses the schema that actually describes it: +Two methods, two representations. `input` produces an **operation input** schema — the pack-backed +half — while `output` produces a **selected result** schema for the shape actually requested, or the +whole-model shape under the explicit `'model'` form. The only public representations are `runtime` +and `json`. Both implement `StandardSchemaV1`, so they drop into independent consumers unchanged, +and each boundary uses the schema that actually describes it: ```ts // an oRPC route contract: create-input in, selected output out @@ -405,46 +549,21 @@ if (parsed.issues) return renderFieldErrors(parsed.issues); Validating an inbound payload with a query-result schema is a category error, and the API's shape makes it visible rather than merely discouraged. -Two honest limits are enforced rather than documented. First, `users.input('create', …)` succeeds -**only** when exact operation metadata exists; otherwise it throws `DB_VALIDATION_UNSUPPORTED` while -the schema is being constructed, naming the missing metadata. The same applies to an `output` -selection whose leaves are computed, raw, aggregated, or otherwise unprovable. Second, invalid user -data never throws: it returns Standard Schema issues with a field path, a stable code, and the -contract coordinates. Construction failures and validation failures are different events with -different audiences. +Both limits are enforced rather than documented. An unsupported operation — or an `output` selection +whose leaves are computed, raw, or aggregated — throws `DB_VALIDATION_UNSUPPORTED` while the schema +is being constructed, naming the missing metadata. Invalid user data never throws: it returns +Standard Schema issues with a field path, a stable code, and the contract coordinates. -### Step 5 — a second PostgreSQL database - -```ts -spaces: { - app: /* … bound to 'primary' … */, - warehouse: defineDatabaseSpace({ - id: 'warehouse', - owner: 'app', - version: '1.0.0', - target: 'analytics', - contract: warehouseContract, - policy: { removal: 'retain' }, - }), -} -``` - -`primary` and `analytics` are both PostgreSQL and share nothing: separate output roots, contract -artifacts, migration lineages, provider markers, runtime bindings, locks, and receipts. A relation -from a `primary` model to an `analytics` model is refused at composition with -`db.compose.cross-target-relation`, and no multi-target operation is ever described as atomic. Those -are not adapter limitations; they are honest statements about two separate databases. - -### Step 6 — install a plugin that owns its schema +### Step 5 — install a plugin that owns its schema A plugin whose tables outlive an install — auth, workers, sagas — contributes a **full space**: its -own native contract, its own canonical artifact, its own migration lineage and head, versioned -independently of the application. +own native contract, canonical artifact, migration lineage, and head, versioned independently of the +application. ```ts -// plugins/auth/core: the plugin owns a space, not a fragment +// plugins/auth/core/src/database.ts — the plugin owns a space, not a fragment +import { CAP, pinnedSpace } from '@netscript/database-contract'; import { definePluginSpace } from '@netscript/plugin'; -import { CAP, pinnedArtifact } from '@netscript/database-contract'; export const authSpace = definePluginSpace({ id: 'plugin:@netscript/plugin-auth', @@ -458,64 +577,80 @@ export const authSpace = definePluginSpace({ denies: ['drop-column', 'change-type', 'add-required-column'], }, policy: { removal: 'retain' }, - artifact: pinnedArtifact('./artifacts/contract.json'), + // One pinned space aggregate, not a lone contract.json: descriptor snapshot, canonical contract + // data *and* declaration, migration packages and graph, head ref, hashes, and provenance. + space: pinnedSpace('./artifacts/auth.space'), }); ``` -The consumer writes one line — `auth: authSpace({ target: 'primary' })` — and installation copies -nothing into the application's schema. It writes a **pinned mirror** under the application's -generated root containing the descriptor snapshot, the space's canonical contract artifact, its -lineage, and its provenance. Production apply and verify read the mirror, so a deployment does not -need the plugin's package graph resolvable at all, and a mirror digest that disagrees with the -installed package digest is `db.space.skew` rather than a latent divergence. - -Ownership is checked over `(target, namespace, object kind, name)`, not over declaration text. Two -spaces that both want a table named `user` are an ownership conflict naming both spaces — and while -the first adapter supports only one physical namespace per target (see -[§ The withheld namespace capability](#the-withheld-namespace-capability)), physical name collisions -between spaces are refused at composition. A published space therefore names its objects so they -cannot collide; namespaces will relax that requirement when the capability is released, and will -never replace the ownership check. - -Uninstalling is a planned operation, not a directory delete. The guaranteed behaviour is -**detach-and-retain**: the runtime binding goes away, the data and the marker stay, a tombstone -records the history, and ownership is downgraded from `managed` to `adopted` so `verify` keeps -noticing drift instead of going blind. Archiving and dropping are specified in this RFC but ship -only if provider conformance proves them. - -### Step 7 — one extension, registered once - -Today a single logical extension such as pgvector must be registered independently in schema -authoring (`/pack`), in control/config (`/control`), and at runtime construction (`/runtime`). -Half-registering it is silent until something fails. +`definePluginSpace` returns a **callable descriptor**: `authSpace()` takes the single target an L1 +application has, `authSpace({ target: 'primary' })` names one explicitly at L2, and both produce the +same `SpaceContribution`. Installation copies nothing into the application's schema; it writes that +pinned aggregate under the application's generated root, mirroring the shape Prisma's own migration +tooling already loads per space ([space aggregate][rc1-space-aggregate]). Production apply and +verify read the aggregate, so a deployment never needs the plugin's package graph resolvable, and an +aggregate that disagrees with the installed package is `db.space.skew`. Typed queries against the +space use the consumer declaration emitted from that same aggregate — the `AuthContract` import in +the binding above — and the spaces are never merged. + +Ownership is checked over `(target, namespace, object kind, name)`, not over declaration text, so +two spaces wanting a table named `user` are a conflict naming both. Because the first adapter +supports one physical namespace per target, physical name collisions are refused at composition and +a published space names its objects so they cannot collide. + +Uninstalling is a planned operation, not a directory delete: **detach-and-retain** removes the +runtime binding while data, provider marker, lineage, and ownership history stay behind a +verify-only tombstone. + +### Step 6 — one extension, registered once + +Upstream, one logical extension is several modules: `@prisma/orm-extension-pgvector/pack` for +authoring and `@prisma/orm-extension-pgvector/runtime` for the runtime facet, plus control wiring. +Registering some of them and forgetting the rest is silent until something fails. Those runtime and +control modules are exactly what an application must not import, so the **adapter or the extension's +publisher** assembles the bundle inside the provider boundary: ```ts -export const pgvectorExtension = defineDatabaseExtension({ - id: 'pgvector', - version: '0.4.0', - provider: 'prisma-postgres', - authoring: pgvectorPack, - control: pgvectorControl, - runtime: pgvectorRuntime, - validation: pgvectorValidation, -}); +// @netscript/database-prisma-postgres — assembled inside the provider boundary, not by the app +export declare function pgvector(options: PgVectorOptions): DatabaseExtension<'pgvector'>; +// → { id, version, requires: [CAP.pgvector], authoring, control, runtime, validation } +// `authoring` is the only facet an application can reach. ``` -One bundle, one identity, four facets. The generated composition root fans that single declaration -into every phase, and a missing, mismatched, or half-installed facet is a composition error naming -the facet and both versions. - -### Step 8 — the operational journey +The application creates that value **once, before the contract** (Step 1), and passes the same +object to the definition (Step 2). Composition then runs two phases. Phase 1 collects every declared +bundle, checks identity and version against what each space's contract was authored with, refuses a +duplicate identity or a facet mismatch with `db.compose.extension.facet-mismatch`, and orders +contributions. Phase 2 invokes the native model-first builder with `bundle.authoring`, +canonicalizes, publishes artifacts, and then fans the _same_ bundle into control, runtime, and +validation. A later value cannot supply the authoring facet retroactively, which is why the order is +fixed. + +The provider-neutral kernel sees only identity, version, provider and capability requirements, and +opaque facet handles. The L3 escape hatch stays open with one condition: an author may call +`defineContract` against Prisma's public `/pack` import directly, but if the space declares that +extension in its NetScript definition, the contract must be built from the registered bundle's +`.authoring` projection — composition compares the extension identity and version recorded in the +emitted contract against the registered bundle and refuses on mismatch. A raw pack import is +equivalent only when no bundle is registered for it, and then that extension has no control, +runtime, or validation facet at all. + +### Step 7 — the operational journey Every operation is a typed programmatic call first; the CLI, the docs, and the agent surface are projections of the same catalog. The API boundary — not a promise in prose — is what proves that pure work cannot reach a database: ```ts +// excerpt: `manifest`, `postgres`, and `connections` are the values bound in Step 3 import { createDatabaseControl } from '@netscript/database-control'; +import { newRunId } from '@netscript/database-contract'; + +const runId = newRunId(); +const policy = { destructive: 'allow-with-approval' } as const; // Pure control: artifacts and policy only. It has no connection resolver to reach. -const control = createDatabaseControl({ manifest, providers: [prismaPostgres] }); +const control = createDatabaseControl({ manifest, providers: [postgres] }); const emitted = await control.emit({ targets: ['primary'], runId }); const advisory = await control.preview({ targets: ['primary'], runId }); @@ -547,7 +682,7 @@ $ netscript db plan --target primary --json "status": "succeeded", "spaces": [ { "space": "app", "status": "planned", "steps": 3, "destructive": 0 }, - { "space": "plugin:@netscript/plugin-auth", "status": "planned", "steps": 1, "destructive": 0 } + { "space": "plugin:@netscript/plugin-auth", "status": "planned", "steps": 1 } ], "plan": { "planId": "plan:4c19…", "expiresAt": "2026-08-13T18:42:00Z" } } @@ -557,12 +692,11 @@ $ netscript db plan --target primary --json } ``` -Four properties are guaranteed by the shape of that output. Every requested target appears with a -status — there is no silent skip and no implicit "all". `nextAction` is structured data, so the CLI, -CI annotations, and an agent render the same remediation without any of them parsing prose. Human -text is never a contract; gates assert on codes. And the exit code is a projection of `outcome` -(`succeeded` → 0, `refused`/`failed` → non-zero, `partial-success` → non-zero with a resume token), -never the result itself. +Four properties follow from that shape. Every requested target appears with a status — no silent +skip, no implicit "all". `nextAction` is structured data, so CLI, CI annotations, and agents render +the same remediation without parsing prose. Human text is never a contract; gates assert on codes. +And the exit code is a projection of `outcome` (`succeeded` → 0, `refused`/`failed` → non-zero, +`partial-success` → non-zero with a resume token), never the result itself. When something goes wrong, the vocabulary is equally explicit: @@ -575,28 +709,25 @@ error db.plan.stale: plan plan:4c19… was bound to manifest nsdb1:9f3c…, curr ### What you stop doing, and what you are refused -The following stop existing as developer-visible work: copying a plugin's `.prisma` file into your -schema; running a generate pipeline whose later steps repair the output of its earlier steps; -keeping a generated Zod mirror in sync; importing a client by its generated filesystem path; -discovering that a command silently used the first target; starting Aspire in order to compile; -reading logs to learn whether a migration produced an artifact; and hand-maintaining an agent -instruction file describing commands that have since changed. Equally important is what the system -declines to do, loudly and early: - -| You try to… | You get | -| --------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -| Bind a space to a target that does not exist | A **type error** at the `defineDatabase` call; `db.compose.target.unknown` if bypassed | -| Declare a relation between models in two different targets | `db.compose.cross-target-relation` at composition | -| Let two spaces manage the same object, or claim the same table name | `db.compose.ownership.conflict` / `db.compose.object-name.conflict`, naming both | -| Use a capability the bound target does not declare | `db.compose.capability.missing`, naming capability, space, and target | -| Request a non-default physical namespace on the first adapter | `db.target.namespace-unsupported` — the capability is withheld, not faked | -| Apply a speculative preview | Refusal: a preview has no `planId` and `apply` accepts only bound plans | -| Apply a plan after the manifest, baseline, pins, or policy changed | `db.plan.stale`; after its expiry, `db.plan.expired` | -| Migrate a read replica | Refusal: replicas are roles, and no control operation can address a role | -| Run a destructive step in production with an interactive "yes" | Refusal: production requires an approved, signed plan | -| Build a validator with no contributed operation or selection metadata | `DB_VALIDATION_UNSUPPORTED` while constructing the schema | -| Target Prisma SQLite, MongoDB, MySQL, or SQL Server | `db.target.unsupported` — structured, with no fallback and no Prisma 7 path | -| Drop a plugin's tables on uninstall | Refusal: `retain` is the guaranteed mode; `archive`/`drop` await conformance | +Copied plugin fragments, self-repairing generate pipelines, hand-synchronised Zod mirrors, deep +imports into generated output, silent target defaulting, Aspire-to-compile, log-scraped migration +results, and hand-maintained agent instructions all stop being developer-visible work. What the +system declines to do is equally explicit: + +| You try to… | You get | +| --------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| Bind a space to a target that does not exist | A **type error** at `defineDatabase`; `db.compose.target.unknown` if bypassed | +| Declare a relation between models in two targets | `db.compose.cross-target-relation` | +| Let two spaces manage one object or claim one table name | `db.compose.ownership.conflict` / `db.compose.object-name.conflict`, naming both | +| Use a capability the bound target does not declare | `db.compose.capability.missing`, naming capability, space, target | +| Request a non-default physical namespace | `db.target.namespace-unsupported` — withheld, not faked | +| Apply a speculative preview | Refusal: a preview has no `planId`; `apply` takes bound plans only | +| Apply a plan after manifest, baseline, pins, or policy changed | `db.plan.stale`; after expiry, `db.plan.expired` | +| Migrate a read replica | Refusal: replicas are roles, and no operation addresses a role | +| Run a destructive production step on an interactive "yes" | Refusal: production requires an approved, signed plan | +| Build a validator with no contributed operation or selection metadata | `DB_VALIDATION_UNSUPPORTED` at schema construction | +| Target Prisma SQLite, MongoDB, MySQL, or SQL Server | `db.target.unsupported` — no fallback, no Prisma 7 path | +| Drop a plugin's tables on uninstall | Refusal: `retain` is guaranteed; `archive`/`drop` await conformance | ## Reference-level explanation @@ -604,31 +735,30 @@ declines to do, loudly and early: Similar-looking values are intentionally distinct; conflating any two is a review finding. -| Term | Meaning and invariant | -| -------------------- | ------------------------------------------------------------------------------------------------------------------- | -| `DatabaseDefinition` | Authored targets, spaces, connections, capabilities, and policy. Pure; performs no IO. Not a manifest. | -| `NativeContract` | A Prisma `defineContract` result. NetScript never translates its entity or query vocabulary. | -| `AppBinding` | App-local generated bridge from the native contract to sessions and validators. Never a published framework export. | -| `SpeculativePreview` | Advisory preview. **Cannot be approved or applied**, and has no `PlanId`. | +| Term | Meaning and invariant | +| -------------------- | ----------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Authored targets, spaces, connections, capabilities, policy. Pure; no IO. Not a manifest. | +| `NativeContract` | A Prisma `defineContract` result; NetScript never translates its vocabulary. | +| `AppBinding` | App-local bridge from authored contracts to sessions and validators. Never published. | +| `SpeculativePreview` | Advisory only. **Cannot be approved or applied**; has no `PlanId`. | A `SpaceContribution` carries a space's owner, version, target, dependencies, ownership, capabilities, artifact refs, and retention; `ValidationIR` is the internal, never-exported -value/selection algebra behind the validators. The control flow keeps five values separate: -`DatabaseDefinition`, `DatabaseManifest`, `ExecutablePlan`, `ProviderMarker`/`ProviderLedger`, and -`OperationReceipt`. A provider-owned `ContractArtifact` is pinned per space and remains distinct -from all five. +value/selection algebra behind the validators. `DatabaseDefinition`, `DatabaseManifest`, +`ExecutablePlan`, `ProviderMarker`/`ProviderLedger`, and `OperationReceipt` stay separate, and a +provider-owned `ContractArtifact` is pinned per space and distinct from all five. Identity is declared, never derived: provider names, engine names, filesystem paths, config aliases, and traversal order are never identities and never dependency edges. -| Identity | Notes | -| --------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `TargetId` | Author-chosen (`'primary'`). Owns connection, output root, runtime binding, lineage, locks, receipts. | -| `RoleRef` | `(TargetId, 'writer' \| 'reader:')`. A replica is a role, never a target, and no control operation addresses one. | -| `NamespaceRef` | `(TargetId, namespace)`. A kernel axis; the first adapter declares only the default namespace. | -| `SpaceId` | `'app'`, `'plugin:@netscript/plugin-auth'`. One schema owner; a published identity, never an install path. | -| `ObjectKey` | `(TargetId, namespace, objectKind, name)`. The unit of ownership; exactly one `managed` owner. | -| `RunId` / `ReceiptId` | Sortable unique ids supplied at the edge, so receipts are addressable and resumable. | +| Identity | Notes | +| --------------------- | ------------------------------------------------------------------------------------------- | +| `TargetId` | Author-chosen. Owns connection, output root, binding, lineage, locks, receipts. | +| `RoleRef` | `(TargetId, 'writer' \| 'reader:')`. A replica is a role; no operation addresses one. | +| `NamespaceRef` | `(TargetId, namespace)`. Kernel axis; the first adapter declares only the default. | +| `SpaceId` | `'app'`, `'plugin:@netscript/plugin-auth'`. One schema owner; never an install path. | +| `ObjectKey` | `(TargetId, namespace, objectKind, name)`. Unit of ownership; one `managed` owner. | +| `RunId` / `ReceiptId` | Sortable ids supplied at the edge, so receipts are addressable and resumable. | `ContractSnapshotId`, `ManifestDigest`, and `PlanId` are content hashes, described with the artifacts they address. @@ -638,31 +768,42 @@ artifacts they address. Six new units and four changed ones. Each has exactly one doctrine archetype; where two genuinely apply, the remedy is two packages, not one package with two shapes. -| Unit | Archetype | Why this boundary exists | -| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------ | -| `@netscript/database-contract` | A1 | Identities, artifacts, diagnostics, vocabularies, SPIs. Zero dependencies and permissions, so everything can depend on it. | -| `@netscript/database` | A4 | `defineX` builders plus the **pure** compiler. Separation from control keeps composition total and IO-free. | -| `@netscript/database-runtime` | A3 | Scope, connection ownership, close ordering, health, cancellation, sessions. A3 makes the runtime gate column mandatory. | -| `@netscript/database-control` | A2 | Operation catalog, plan/apply/verify, policy, locks, receipts, recovery, saga — integration work with failure-injection gates. | -| `@netscript/database-prisma-postgres` | A2 | The **only** framework Prisma import boundary. Independently versioned, so an upstream break is a provider patch. | -| `@netscript/database-testkit` | A6 | Runnable provider **and space** conformance certification with machine-readable reports. | - -Four existing units change. `@netscript/plugin` (A4) gains `definePluginSpace`, typed only by -`-contract`, and loses the hollow legacy database abstracts, keeping a driver out of every plugin's -dependency graph; first-party `plugins/*` (A5) become thin descriptors plus pinned artifacts from -their `-core` package; `@netscript/aspire` (A2) narrows to one `ConnectionSource` adapter and a -resource projection, **never required by a pure operation**; and `@netscript/cli` (A6) projects the -operation catalog and hosts the adoption codemod, with no database logic and no engine switch. - -Dependency law, each clause mechanically checkable. `-contract` imports nothing from this family and -no provider. `-runtime` and `-control` depend on `-contract` and on `-database` for definition types -they must not redeclare, and never import each other or a provider. **No framework package depends -on a provider**: providers are composition-root values, so there is no global registry and no lookup -by string. Nothing depends on the testkit at runtime. And **no framework package re-exports Prisma** -— only the adapter imports Prisma runtime or control modules, while application and plugin authoring -modules import Prisma's public authoring builder directly during the controlled build phase, which -is provider-native authoring, not a re-export. Public subpaths are part of that contract: the -adapter owns exactly two, its root and `/binding`. +| Unit | Archetype | Why this boundary exists | +| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database-contract` | A1 | Identities, artifacts, diagnostics, SPIs. Zero dependencies, so everything can depend on it. | +| `@netscript/database` | A4 | L1 recipe, L2 factories, `ContractOf`, and deterministic resolution; separation from control keeps composition free of live IO. | +| `@netscript/database-runtime` | A3 | Scope, binding, connection ownership, close ordering, cancellation — the mandatory A3 gate column. | +| `@netscript/database-control` | A2 | Catalog, plan/apply/verify, policy, locks, receipts, recovery, saga — with failure-injection gates. | +| `@netscript/database-prisma-postgres` | A2 | The **only** framework Prisma import boundary, extensions included; independently versioned. | +| `@netscript/database-testkit` | A6 | Runnable provider **and space** conformance certification with machine-readable reports. | + +Four existing units change: `@netscript/plugin` (A4) gains `definePluginSpace` typed only by +`-contract` and loses the legacy database abstracts; first-party `plugins/*` (A5) become thin +descriptors plus pinned artifacts; `@netscript/aspire` (A2) narrows to one `ConnectionSource` +adapter and a manifest-derived resource projection, **never required by a pure operation**; and +`@netscript/cli` (A6) projects the operation catalog with no database logic and no engine switch. + +The dependency edges are exact, and each clause is mechanically checkable: + +- `@netscript/database-contract` imports nothing from this family and no provider. Everything else + depends on it. +- `@netscript/database` depends on `-contract` only. It owns the L1 recipe, the L2 factories, and + deterministic resolution. +- `@netscript/database-runtime` and `@netscript/database-control` depend on `-contract` only. They + consume manifests, pinned artifacts, and the shared SPIs — never a `DatabaseDefinition`, so they + have no reason to depend on `@netscript/database` — and they never import each other. +- `@netscript/database-prisma-postgres` implements the published runtime and control SPIs and is + supplied to both as a value by the application composition root. +- `@netscript/plugin` publishes plain contributions typed by `-contract`, with no provider, runtime, + or control dependency. +- `@netscript/database-testkit` may depend on every public surface; nothing depends on it at + runtime. + +**No framework package depends on a provider** — providers are composition-root values, so there is +no global registry and no lookup by string — and **no framework package re-exports Prisma**: only +the adapter and extension publishers import Prisma runtime or control modules, while application and +plugin authoring modules import Prisma's public authoring builder during the controlled build phase. +The adapter owns exactly two public subpaths, its root and `/binding`. Doctrine currently codifies the model this RFC removes — Archetype 5 makes plugin database contributions plain `*.prisma` files ([archetypes](../docs/architecture/doctrine/06-archetypes.md)) @@ -686,70 +827,119 @@ export declare function defineDatabase< Record, unknown>> >, >( - input: { targets: TTargets; spaces: TSpaces; policy?: DatabasePolicy }, + input: { targets: TTargets; spaces: TSpaces; extensions?: readonly DatabaseExtension[] }, ): DatabaseDefinition; -/** Pure resolution. Total: it returns diagnostics; it does not throw for authoring mistakes. */ +/** + * Mathematically pure and total: in-memory resolution of a definition plus already-loaded contract + * snapshots. No IO of any kind; it returns diagnostics instead of throwing on authoring mistakes. + */ +export declare function resolveDatabase( + definition: AnyDatabaseDefinition, + snapshots: readonly ContractSnapshot[], +): + | { readonly ok: true; readonly manifest: DatabaseManifest } + | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] }; + +/** + * Offline effects only: reads contract artifacts through the supplied source, calls + * `resolveDatabase`, and atomically publishes the emitted artifact set. Never resolves a + * connection, Aspire resource, secret, or network endpoint. + */ export declare function compileDatabase( definition: AnyDatabaseDefinition, - sources: ContractArtifactSource, + io: ContractArtifactSource & ArtifactPublisher, ): Promise< | { readonly ok: true; readonly manifest: DatabaseManifest } | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] } >; ``` +The split matters because "pure" is used for two different things elsewhere in this document. +`resolveDatabase` is pure in the mathematical sense. `compileDatabase` performs offline effects — +loading sources, publishing artifacts — and is classified `pure` **only** in the operation catalog's +sense defined below: no live database, network, or connection. Live control never receives a +definition at all. + Four inference rules, each with a conformance fixture: literal preservation through `const` type parameters; **contract identity**, so `typeof definition.spaces.app.contract` is exactly -`typeof appContract`; **no structural widening**, so no signature accepts a contract as -`Record` and a deliberately widened fixture must _fail_ its soundness gate; and -**no upstream leakage**, so no published NetScript declaration names a Prisma type. - -Two tracks run in parallel and must never be merged. The **inference track** is `typeof contract`: -provider generics, valid only inside the application's own compilation, terminating in generated -app-local files. The **identity track** is `ContractSnapshotId` and `ManifestDigest`: plain data -used by plans, markers, receipts, validators, and agents, crossing every boundary freely. Conflating -them is how a system ends up unable to answer "is this database consistent with this build?" without -type-checking, so every generated binding records the manifest digest and provider pin and startup -refuses a mismatch with `db.artifact.stale`. +`typeof appContract`; **no structural widening**, so a deliberately widened fixture must _fail_ its +soundness gate; and **no leakage into neutral packages**, so no **provider-neutral** NetScript +declaration names a Prisma type. `ContractOf` extracts one space's contract +evidence as an opaque generic; mapping it to concrete Prisma query and transaction types is the job +of the adapter's explicitly provider-specific `/binding` declaration, which is allowed to name +Prisma types because that is precisely what it is for. + +Two tracks run in parallel and must never be merged. The **inference track** is `typeof definition`: +provider generics valid only inside the application's own compilation, erased at run time. The +**identity track** is `ContractSnapshotId` and `ManifestDigest`: plain data used by plans, markers, +receipts, validators, and agents, crossing every boundary freely. Conflating them is how a system +ends up unable to answer "is this database consistent with this build?" without type-checking, so +every binding carries the digests and refuses a mismatch at bind time with `db.artifact.stale`. + +#### Where each space's type evidence comes from + +Two upstream facts decide the app-authored case. Prisma's emitted runtime option type carries a +compile-time `TContract` in a phantom `_contract?: TContract` field beside the runtime +`contractJson` ([`postgres.ts`][rc1-postgres-runtime]), and the no-emit path passes the authored +value directly as `postgres({ contract })` ([no-emit context][rc1-no-emit]) — so a +query surface can be typed from `typeof` while the runtime value comes from the canonical artifact. +And root `deno.json` enables `isolatedDeclarations`, under which an exported inferred +`defineContract(...)` constant needs an explicit annotation; app-owned authoring modules are **build +inputs, not JSR exports**, so that narrow app-local project sets `isolatedDeclarations: false` while +every published `@netscript/*` package keeps it `true`. For app-authored spaces nothing is emitted, +no neutral declaration names a Prisma type, and no slow-types waiver is requested: evidence flows +`typeof definition → ContractOf → adapter binding`. + +A consumer cannot do that for a space it did not author. A pinned plugin space arrives as artifacts, +and TypeScript cannot reconstruct an exact contract type from JSON. For those spaces — and for an +application that deliberately exports an inferred definition from a publishable package — the +provider **declaration** is generated **automatically and atomically in the same compile** that +publishes the artifacts, and imported as type-only evidence into the hand-written binding. It is +never hand-run, never a framework slow type, and never control authority: runtime and control still +consume the manifest and pinned artifact values, and a declaration only tells the type checker what +the artifact already says. + +The fallback is bounded to exactly those two boundaries, both proved in W3. If direct app inference +turns out to require a private import, a copied overload, a cast, a provider type in a neutral +package, or runtime evaluation of authoring code, that is recorded as a **W3 kill/rethink +criterion** — the layered surface is reconsidered rather than silently promoted to universal +generation. **The one deliberate soundness seam.** `runtime.bind` returns a session whose query types come from -generated code, and the kernel cannot prove the runtime value the provider constructs matches them, -because those type parameters are erased. Three gates make the seam safe: the binding is _generated_ -from the same manifest and provider declaration artifact that produced the session (hand-writing one -is an `arch:check` failure); it carries the digests the provider verifies at bind time; and a -conformance case asserts that a mismatched binding fails at bind rather than at first query. The -alternative — publishing a contract-typed value from a framework package — `isolatedDeclarations` -and the no-slow-types rule forbid outright. +app-local inference, and the kernel cannot prove that the runtime value the provider constructs +matches them, because those type parameters are erased. Three gates make the seam safe: the binding +is constructed by the adapter factory from the same manifest that produced the artifacts; it carries +the manifest digest, provider pin, and per-space snapshot ids that the provider verifies at bind +time; and a conformance case asserts that a mismatched binding fails at bind rather than at first +query. ### Contribution modes The mode decides migration ownership, and it is explicit. -| Mode | Owns migrations | Used for | -| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------- | -| Space (`definePluginSpace`, `defineDatabaseSpace`) — a complete native contract, canonical artifact, migration lineage, and head, published as pinned data | The contributor | **All persistent plugin-owned tables**, and application schema | -| App-local fragment (`defineContractFragment`) — a function receiving the exact composed native helpers and returning const-preserved `types`/`models`/`enums` | The application | Application schema an app chooses to split across modules | +| Mode | Owns migrations | Used for | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------- | +| Space (`definePluginSpace`, `defineDatabaseSpace`) — a complete native contract, canonical artifact, lineage, and head, published as pinned data | The contributor | **All persistent plugin-owned tables**, and application schema | +| App-local fragment (`defineContractFragment`) — a function taking the exact composed native helpers and returning const-preserved `types`/`models`/`enums` | The application | Application schema split across modules | A fragment's `build` parameter necessarily names the provider's composed helper type, so under `isolatedDeclarations` a **published** package cannot export one without putting a Prisma type in a published declaration. Fragments are therefore application-local and a published fragment is a gate -failure — which is why persistent plugin tables default to full spaces, whose published surface is -plain data plus pinned artifacts. If W3 proves a mechanism that preserves exact inference across a -published boundary, a published fragment mode may be added then. +failure — which is why persistent plugin tables default to full spaces published as plain data plus +pinned artifacts. Composition is two-phase because extension packs determine the composed helper object's shape -_before_ Prisma invokes the callback, so "register an extension while a fragment is executing" -cannot be sound. Phase 1 collects contribution manifests, extension bundles, dependency edges, and +_before_ Prisma invokes the callback. Phase 1 collects contributions, bundles, dependency edges, and capability requirements, resolving extension identity and version, detecting facet mismatch, ordering fragments, and refusing cycles; phase 2 builds one scaffold into the exact composed helper surface, invokes fragments in dependency order, canonicalizes, and atomically publishes the -artifacts. Both phases are pure, and the generated root is explicit calls and spreads in dependency -order — never a runtime registry, never `Array.reduce`, never a value typed -`Record`: +artifacts. Both phases are pure, the root is explicit calls and spreads in deterministic order — +never a registry, never `Array.reduce`, never `Record` — and fragment order must +not change the canonical digest. Plugin spaces never appear in that root. ```ts -// .netscript/database/primary.contract-root.ts — GENERATED. Do not edit. +// database/contract-root.ts — app-owned fragments composed in one explicit, const-preserving root export const primaryContract = defineContract(scaffold, (h) => { const billing = billingFragment.build(h, {}); const app = appFragment.build(h, { billing }); @@ -762,46 +952,43 @@ export const primaryContract = defineContract(scaffold, (h) => { }); ``` -Fragment order must not change the canonical contract digest; that is a conformance case. Plugin -spaces never appear in this root — they are separate contracts with separate artifacts, applied on -their own lineage. - ### Artifacts and their authority Six separately named values, with disjoint responsibilities. Nothing else is authoritative for these questions. -| Value or artifact | Authoritative for | Identity and failure behaviour | -| ----------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `DatabaseDefinition` | Authored intent | Source value only; it is compiled and never consumed by runtime, control, apply, or verify | -| `ContractArtifact` | Provider contract content | `ContractSnapshotId`; `db.artifact.stale` refuses to plan or bind | -| `DatabaseManifest` | Resolved desired composition | `ManifestDigest` over the canonical manifest including pins; a consumer with a different digest refuses and names both | -| `ExecutablePlan` | What will be executed | `PlanId`; `db.plan.stale`, `db.plan.expired`, `db.plan.revoked` | -| `ProviderMarker` / `ProviderLedger` | **Applied state** | Provider-owned, recorded as opaque versioned attributes; divergence from the manifest is drift, classified by ownership | -| `OperationReceipt` | Evidence of attempts and observations | `ReceiptId` per run with ordered checkpoints; never desired state, and a resume reads it _plus_ live state | +| Value or artifact | Authoritative for | Identity and failure behaviour | +| ----------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Authored intent | Consumed only by `compileDatabase` in `@netscript/database`; no runtime, control, apply, or verify path takes one | +| `ContractArtifact` | Provider contract content | `ContractSnapshotId`; `db.artifact.stale` refuses to plan or bind | +| `DatabaseManifest` | Resolved desired composition | `ManifestDigest` over the canonical manifest including pins; a different digest refuses and names both | +| `ExecutablePlan` | What will be executed | `PlanId`; `db.plan.stale`, `db.plan.expired`, `db.plan.revoked` | +| `ProviderMarker` / `ProviderLedger` | **Applied state** | Provider-owned opaque versioned attributes; divergence is drift, classified by ownership | +| `OperationReceipt` | Evidence of attempts and observations | `ReceiptId` per run, ordered checkpoints; never desired state, and resume reads it _plus_ live state | Manifests and plans carry secret _references_ only, so a plan is safe to commit and archive. -Artifact roots are staged and atomically committed, never patched in place, so an interrupted job -leaves a fully old or fully new root. Receipt outcomes are `succeeded`, `refused`, `skipped`, -`failed`, `partial-success`, `cleanup-required`, `outcome-unknown`, and `cancelled`; the last three -are separate from `failed` precisely because "the ledger was repaired" must never read as "the -database was repaired" ([Flyway repair][flyway-repair]). - -Composition is pure and total. Beyond the refusals listed in the guide it validates provider pins, -contribution provenance and contract format, mirror integrity, and output/migration root isolation, -refuses dependency cycles and extension facet skew, and is covered by a determinism gate asserting -that `ManifestDigest` is a pure function of the definition, its snapshots, and its pins. Every -invariant has a diagnostic and a negative test. +Artifact roots are staged and atomically committed, never patched in place. Receipt outcomes are +`succeeded`, `refused`, `skipped`, `failed`, `partial-success`, `cleanup-required`, +`outcome-unknown`, and `cancelled`; the last three are separate from `failed` because "the ledger +was repaired" must never read as "the database was repaired" ([Flyway repair][flyway-repair]). + +Composition is pure and total: every invariant it checks has a diagnostic and a negative test, and a +determinism gate asserts that `ManifestDigest` is a pure function of the definition, its snapshots, +and its pins. ### Operations, plans, and recovery Operations are classified before they run, and the class determines what an operation may resolve. +In this catalog `pure` means **no live database, network, connection, or orchestrator** — not +side-effect-free: `emit` reads authoring artifacts and publishes an artifact set atomically. +`compose` is the catalog's projection of the A4 compiler, and the control package does not own the +compiler; live control never receives a `DatabaseDefinition`. | Class | Examples | May resolve | Lock | | ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | | `pure` | `compose`, `emit`, `inventory`, offline `preview`, `sign` | Artifact readers, the atomic publisher, the signature policy. **Never** a connection, Aspire, Docker, secrets, or the network. | No | | `live-read` | `inspect`, live `preview`, `plan`, `verify` | An explicit target connection | No | -| `mutating` | `apply`, `seed`, adoption baseline, space retirement | An explicit connection, provider lock/fencing, and a bound plan | Yes | +| `mutating` | `apply`, `seed`, adoption baseline, space retirement | An explicit connection, provider lock/fencing, a bound plan | Yes | | `resident` | `studio`, and anything whose connection lives inside a host | An explicit target and an orchestration binding | Advisory | `sign` is deliberately `pure`: signing binds a policy decision to an artifact, so it neither takes a @@ -836,96 +1023,115 @@ stateDiagram-v2 refused --> [*] ``` -The rules that give that diagram teeth. **Loss of transport after dispatch produces -`outcome-unknown`, never `failed`** — the engine cannot know whether the provider completed the work -([interrupted updates][pulumi-interrupted]). **Resume always inspects live state and the provider -ledger first**, revalidates the plan bindings, and continues only operations whose outcome is known -and unfinished, never blindly replaying non-idempotent DDL or a data transform; because resume is a -_lookup_, the receipt store supports append plus lookup by `RunId`, `ReceiptId`, and resume token, -and an implementation may split those into source and sink roles. **Checkpoints are per irreversible +The rules that give that diagram teeth. **Resume never blindly replays** non-idempotent DDL or a +data transform: it inspects live state and the provider ledger first, revalidates the plan bindings, +and continues only operations whose outcome is known and unfinished. Because resume is a _lookup_, +the receipt store supports append plus lookup by `RunId`, `ReceiptId`, and resume token, and an +implementation may split those into source and sink roles. **Checkpoints are per irreversible operation or provider transaction group.** **Lock scope is `(target, physical database)`**, with owner identity, nonce, fencing evidence where the provider supports it, TTL, heartbeat, and explicit force-unlock preconditions; a provider without a certified lock is refused for concurrent-safe -apply, and each target gets its own runner. +apply. **Multi-target execution is a saga, never a transaction.** Selection expands to a dependency closure, records every omission with a reason code, orders targets deterministically, and gives each -its own runner, lock, and receipt. A mix of successful and failed, refused, or unknown targets -yields `partial-success` with a resume token; if no target succeeds, the aggregate outcome is -failed, refused, or outcome-unknown according to the per-target results. The run ends with a -whole-manifest verification; selective execution is recovery machinery, not the normal deployment -path ([resource targeting][tf-targeting]). The programmatic catalog is the source, and CLI commands, -documentation, and agent instructions are projections of it: a freshness gate fails on any diff, and -a conformance case executes every documented example. +its own runner, lock, and receipt. + +Rollup is a total deterministic function over terminal statuses. Every selected space ends in +exactly one of `succeeded`, `skipped` (deliberately excluded, with a recorded reason), or a +non-success status — `outcome-unknown`, `cleanup-required`, `failed`, `refused`, `cancelled` — in +that closed dominance order. A target is `succeeded` when every selected space is `succeeded` or +`skipped` and at least one succeeded; `skipped` when every selected space is `skipped`; otherwise it +takes the dominant non-success status among its spaces. Mixed space outcomes therefore never make a +target "partially successful". The run applies the same function one level up: `succeeded` when +every selected target is `succeeded` or `skipped` with at least one success, `skipped` when all are, +`partial-success` when at least one target succeeded **and** another has a non-success status, and +otherwise the dominant non-success status — so a run in which no target succeeded is never reported +as partial success. + +Selective execution is recovery machinery, not the normal deployment path +([resource targeting][tf-targeting]). The catalog is the source: CLI, Aspire, docs, and agent +surfaces are projections, a freshness gate fails on any diff, and a conformance case executes every +documented example. ### The runtime layer -A session carries its `TargetId`, scope, contract snapshot id, a `health(signal)` method, and the -provider's own `query` surface supplied by generated app-local code. Scope is a **type**, not a -configuration flag: `ProcessTargetSession` adds `transaction(run, options?)`, -while `RequestTargetSession` is `AsyncDisposable`, caches no collaborators, and has no -`transaction` member at all. That mirrors an upstream precedent — Prisma's serverless facade creates -an async-disposable runtime per request and omits the closure-cached `orm`, `runtime()`, and -`transaction()` surfaces that would be unsafe in that lifecycle — and it prevents the class of bug -where a closure caches a per-request handle. - -Guarantees the A3 gates must prove: **one lifecycle owner** — the runtime constructs the provider -runtime, with no `setClient` and no circular assembly; **close ordering** — sessions drain before -connections close, connections close in reverse bind order, leak-free across repeated start/stop and -request lifecycles; **cancellation** — every long-running call takes an `AbortSignal`, observable in -the receipt and never leaving an orphaned connection; **readers cannot migrate** — a `reader:*` role -produces a read-only session type no control operation can address; **redaction** — connection -strings, passwords, and secret references never appear in diagnostics, receipts, or logs; and **bind -refuses mismatch**. +A session carries its `TargetId`, scope, per-space contract snapshot ids, a `health(signal)` method, +and `space(id)`. That call returns the provider's own facade for one space — for the Prisma adapter, +`.orm` is the collection client and `.sql` the SQL DSL escape hatch, both exactly as upstream ships +them — typed from that space's own evidence. Scope is a **type**, not a configuration flag: +`ProcessTargetSession` adds `transaction(space, run, options?)`, while +`RequestTargetSession` is `AsyncDisposable`, caches no collaborators, and has no +`transaction` member at all — the same asymmetry Prisma's serverless facade encodes by omitting its +closure-cached surfaces. + +Guarantees the A3 gates must prove: **one lifecycle owner** — no `setClient`, no circular assembly; +**close ordering** — sessions drain before connections close, in reverse bind order, leak-free +across repeated start/stop and request lifecycles; **cancellation** — every long-running call takes +an `AbortSignal`, observable in the receipt and never orphaning a connection; **readers cannot +migrate**; **redaction** — connection strings, passwords, and secret references never reach +diagnostics, receipts, or logs; and **bind refuses mismatch**. Ports stay at three or four cohesive methods, because AP-3 names "a port with every operation the backend can perform" as the integration-package failure mode and today's `DatabaseAdapter` -is that anti-pattern in shipped code. **Verify is not a provider method**: it is composed from -`ProviderControl.inspect` plus a manifest comparison plus ownership classification, which is what -keeps drift semantics identical across providers. +is that anti-pattern in shipped code. The consumed set is `ContractArtifactSource`, +`ArtifactPublisher` (stage/commit/abort, never patch in place), `ProviderRuntimeFactory`, +`ProviderControl` (emit/inspect/plan/apply), `ConnectionSource` (the Aspire, environment, and +secret-reference adapters), `MigrationLock`, and the append-plus-lookup receipt store, plus `Clock`, +`IdSource`, and `SignaturePolicy` where deterministic testing or production approval requires them. +**Verify is not a provider method**: it is composed from `ProviderControl.inspect` plus a manifest +comparison plus ownership classification, which is what keeps drift semantics identical across +providers. ### The runtime validation subsystem -This is the second primary axis of the RFC, and the one where an attractive inference is easiest to -over-sell. The +This is the axis where an attractive inference is easiest to over-sell. The [runtime-validation source audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md) is the evidence; three facts are decisive. The contract carries a bounded runtime value algebra — codec references, value objects, unions, mandatory nullability, `many`, `dict`, value-set references, and explicit relation and cross-space coordinates. But **the complete operation and result type universe is not runtime data**: the SQL field, operation, codec, and aggregate type maps -are installed under an optional phantom key, emitted into `contract.d.ts`, and erased at runtime. -And plans retain enough for **direct** projections and no more — a projection carries alias, -expression, and an _optional_ codec reference, absent for computed expressions, subqueries, and raw -aliases. Prisma's own Standard Schema usage validates codec parameters rather than model values, -across three representations (application runtime, driver wire, target JSON), which is why the -public options are `runtime` and `json`. +sit under an optional phantom key ([`TypeMapsPhantomKey`][rc1-type-maps]), are emitted into +`contract.d.ts`, and are erased at runtime. And plans retain enough for **direct** projections and +no more — a projection carries alias, expression, and an _optional_ codec reference, absent for +computed expressions, subqueries, and raw aliases. + +Two related upstream facts are often merged and must not be. Prisma's own Standard Schema usage +validates codec **parameters**, not model values. Separately, a codec declares three **conversion** +representations — application runtime, driver wire, and target JSON — of which only `runtime` and +`json` are NetScript's public validation representations; the driver-wire channel stays +adapter-internal, and conversion success is never validation. Three schema classes with materially different guarantees, which is why they are not hidden behind one method: -| Class | Guarantee | Refusal boundary | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | -| Model value | `output('model', …)` validates a named model, value object, or enum. | Never implies uniqueness, foreign keys, or check constraints are satisfied. | -| Operation input | `input(op, …)` exists **only** where the provider or an extension contributes exact runtime operation metadata. | Create/update/filter/nested-write/polymorphic semantics absent from runtime data fail at construction. | -| Selected result | `output(selection, …)` validates a fully-known direct projection whose alias, codec, nullability, and representation are known. | Computed, subquery, raw, aggregate, include, and unknown leaves need a contributed result schema or fail. | +| Class | Guarantee | Refusal boundary | +| --------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| Model value | `output('model', …)` validates a named model, value object, or enum. | Never implies uniqueness, foreign keys, or check constraints hold. | +| Operation input | `input(op, …)` exists **only** where a registered operation pack contributes exact runtime metadata. | Create/update/filter/nested-write/polymorphic grammar absent from runtime data fails at construction. | +| Selected result | `output(selection, …)` validates a direct projection with known alias, codec, nullability, representation. | Computed, subquery, raw, aggregate, include, and unknown leaves need a contributed schema or fail. | + +Operation metadata reaches the interpreter as an **operation pack** contributed by the configured +provider or an extension bundle through the single registration flow — `prismaPostgres` contributes +`ormCollection@1` for the RC1 collection grammar — and each pack's identity and version is recorded +in the manifest and in every derived validator's cache key. Nothing is inferred from the contract +that the contract does not contain. -`ValidationIR` covers registered codec leaves, nullability, `many` and `dict`, value objects, -whole-model values with an explicit presence policy, direct-column projections with complete -metadata, model fields and relations whose cross-space references resolve through an -integrity-verified aggregate, unions only where branch identity is deterministically discriminable, -and value sets and enums whose membership resolves from the value set or native-enum entity — never -inferred from a codec id, because the PostgreSQL native-enum codec is a string pass-through carrying -no members. +`ValidationIR` supports exactly the algebra the pinned source proves: registered codec leaves, +nullability, lists and dictionaries, value objects, whole-model values with an explicit presence +policy, direct-column projections, integrity-checked cross-space relations, deterministically +discriminable unions, and value sets and enums whose membership resolves from the value set or +native-enum entity rather than from a codec id. Schema **construction** throws a deterministic `DB_VALIDATION_UNSUPPORTED` — with coordinates naming target, space, snapshot, model, operation or selection, representation, and the missing metadata — -for at least: unknown codecs, or codecs with no representation-specific value schema; unknown pack +for at least: unknown codecs or codecs without a representation-specific value schema; unknown pack entity kinds; corrupt or missing aggregate spaces, heads, hashes, cross-space references, or value sets; ambiguous unions and unresolvable model variants; operation grammar absent from runtime data; computed, subquery, raw, aggregate, include, or unknown result leaves; opaque SQL index and check expressions; database-state constraints such as uniqueness and foreign keys, which are not local -value validation; and non-deterministic or asynchronous predicates where the requested mode promises -synchronous validation. +value validation; and asynchronous predicates where the requested mode promises synchronous +validation. No unsupported case becomes `unknown`, a pass-through, or a warning. This is deliberately **stricter than the provider's own decoders**, which accept missing codecs and pass through unknown shapes: a @@ -944,12 +1150,12 @@ defineValidationCodec({ ``` Encode/decode functions are not validation: conversion success is compatible with arbitrary -coercion, as the ArkType JSON extension documents — encoding does not validate, so an invalid write -can reach the database and fail only on `RETURNING` decode. A derived validator's cache key covers -the canonical full-contract snapshot digest, contract schema version, `SpaceId`, target/family, -operation or normalized selection shape, representation, interpreter ABI version, and contributor -versions; a storage hash alone is insufficient, because domain, roots, and extension semantics can -change without storage changing. Plugin spaces cache under their own `SpaceId`. +coercion, as the ArkType JSON extension documents. A derived validator's cache key covers the +canonical snapshot digest, contract schema version, `SpaceId`, target/family, operation or +normalized selection shape, representation, interpreter ABI version, and the identity and version of +every contributing operation pack and codec; a storage hash alone is insufficient, because domain, +roots, and extension semantics can change without storage changing. Plugin spaces cache under their +own `SpaceId`. Input validation is **mandatory** at external mutation boundaries wherever a supported schema exists; output validation is **mandatory** for declared API/RPC responses, SSR/hydration payloads, @@ -957,135 +1163,118 @@ and external-service messages, and **opt-in** for internal query loops, because validates every row on every read gets disabled wholesale. An input failure is a client error with field paths; an output failure is a server/contract error **and** a drift signal. NetScript re-exports no validation library, and no ahead-of-time projection is claimed: one may ship later -only if it is content-addressed, atomically replaced, never required by any code path, and proven to -pass the identical semantic corpus as the runtime interpreter. +only if it is content-addressed, atomically replaced, never required by any code path, and corpus- +equivalent to the runtime interpreter. ### Ownership, spaces, and the withheld namespace capability -| Policy | Planned | Mutated | Verified | Typical source | -| ---------- | ------- | ------- | -------------------------------- | ---------------------------------------------------------------- | -| `managed` | Yes | Yes | Fully | An app or plugin space that owns the objects. | -| `adopted` | Yes | Yes | Against a reviewed baseline | Objects brought under management by `db adopt` or by retention. | -| `external` | No | No | Against declared assertions only | Hosted platforms and upstream extensions that own their objects. | -| `ignored` | No | No | No | Deliberate exclusion with an auditable recorded reason. | +| Policy | Planned | Mutated | Verified | Typical source | +| ---------- | ------- | ------- | --------------------------- | ----------------------------------------------------------------- | +| `managed` | Yes | Yes | Fully | A space that owns the objects | +| `adopted` | Yes | Yes | Against a reviewed baseline | Objects brought under management by `db adopt` | +| `external` | No | No | Against declared assertions | Hosted platforms and upstream extensions owning their own objects | +| `ignored` | No | No | No | Deliberate exclusion with a recorded reason | Exactly one `managed` owner per `ObjectKey`; identical declaration text from two contributors is -still an ownership conflict; cross-space references require the same target plus a declared -dependency edge; and augmentation is an **owner-granted closed permission**, so the absence of a -grant is a denial and an unsupported modification either asks the owner or becomes an app-owned -migration. The `external` policy is not an edge case — a hosted database whose tables evolve outside -the framework's knowledge is the normal shape of a managed service, and upstream has a recorded -instance of a pinned extension contract diverging from an externally evolving database and failing +still a conflict; cross-space references require the same target plus a declared dependency edge; +and augmentation is an **owner-granted closed permission**, so the absence of a grant is a denial +and an unsupported modification either asks the owner or becomes an app-owned migration. The +`external` policy is not an edge case — a hosted database whose tables evolve outside the +framework's knowledge is the normal shape of a managed service, and upstream has a recorded instance +of a pinned extension contract diverging from an externally evolving database and failing verification ([prisma#29896][pn-29896]). The space lifecycle is `declared → installed → upgraded`, with refusals for overlap, missing or cyclic dependencies, contract-format skew, capability regression, ownership widening, and mirror skew; then `detached → retained`, with `archived` and `dropped` specified but unclaimed. -Detach-and-retain is the **only guaranteed removal**: data, marker, tombstone, and ownership history -are preserved, and ownership is downgraded `managed → adopted`. Detaching a space a still-installed -space depends on is refused, naming the dependent. +Detach-and-retain is the **only guaranteed removal**, and retained is a lifecycle state rather than +an ownership policy: the space keeps its data, marker, lineage, and ownership history as a +**verify-only tombstone** that drift reporting still sees but no plan or apply may touch until a new +explicit space re-adopts it. Detaching a space a still-installed space depends on is refused. Prisma's runtime lowering honours per-model namespaces, but its authoring type maps do not: the authoring path lumps every model under the default storage namespace and leaves additional namespace -maps empty (`packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691`), and the audited -post-RC object retains the limitation. `NamespaceRef` therefore stays a **kernel** identity axis — -manifests, ownership, object keys, and plans all carry it — while the adapter declares only the -target's default physical namespace as a capability, and declaring a second namespace or binding a -space to a non-default one is refused with `db.target.namespace-unsupported`. The capability must -not be advertised until exact type/runtime parity passes with **no casts, no private imports, and no -flattening workaround**. The consequence, stated so it cannot be misread: logical `SpaceId` and -ownership coordinates prevent silent merging, but they do **not** make two identical physical table -names coexist in one namespace, so spaces sharing a target must use distinct physical object names -until the capability is released. If upstream never fixes the type maps, the kernel carries an +maps empty ([`contract-types.ts`][rc1-namespace-map]), and the audited post-RC object retains the +limitation. `NamespaceRef` therefore stays a **kernel** identity axis — manifests, ownership, object +keys, and plans all carry it — while the adapter declares only the default physical namespace as a +capability, and a second namespace or a non-default binding is refused with +`db.target.namespace-unsupported`. The capability must not be advertised until exact type/runtime +parity passes with **no casts, no private imports, and no flattening workaround**. Logical `SpaceId` +and ownership coordinates prevent silent merging, but they do **not** let two identical physical +table names coexist in one namespace. If upstream never fixes the type maps, the kernel carries an unused axis and nothing else needs rework. ### The refusal boundary These refusals are the architecture: each is mechanically checkable and each has a conformance row in the [approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md). Beyond -the non-goals in the summary and the refusals in the guide: **no compatibility layer** — no Prisma 7 -facade, legacy generated module, dual client, `setClient` lifecycle, alias barrel, copied schema -bridge, dual migration history, or runtime shim, and no code path that selects between the two -stacks; **no upstream re-export**, since only the adapter imports Prisma runtime or control modules; -**no text-patched generated source and no arbitrary TypeScript during production apply**, because -artifacts are emitted from an IR and replaced atomically while CI consumes verified artifacts; and -**no implicit target selection, cross-target atomicity, cross-database relation, or cross-database -transaction**. +the summary's non-goals and the guide's refusals: **no compatibility layer** and no code path that +selects between the two stacks; **no text-patched generated source and no arbitrary TypeScript +during production apply**, because artifacts are emitted from an IR and replaced atomically while CI +consumes verified artifacts; and **no implicit target selection, cross-target atomicity, +cross-database relation, or cross-database transaction**. ## Drawbacks -**It is a large program, and it lands as a break.** Twelve waves, six new packages, changes to four -existing ones, a doctrine amendment, a first-party plugin conversion, and a cutover. No individual -wave is exotic, but the sequence is long, and until the cutover the repository carries both -foundations on separate branches. Anyone wanting a small change here will find the smallest coherent -unit is still substantial, because the operation contract — not a missing feature — is what is being -replaced. - -**It bets on an Early-Access upstream.** RC1 is explicitly not recommended for production, its notes -warn that respins may break APIs and the contract format, and the seam demonstrably moved within six -days of the tag. The mitigation — one adapter package, one facade module, an import allowlist, -independent versioning, and a kill switch that costs a provider rather than the architecture — is -real but not free: it adds a boundary a direct dependency would not need. - -**It adds indirection where a direct call used to be.** A definition compiles to a manifest, which -binds a plan, which yields a receipt. For a solo developer with one PostgreSQL database this is more -moving parts than `prisma migrate dev`; the pay-off arrives with the second target, the first plugin -space, the first partial failure, and the first production apply. Six published packages is likewise -a real maintenance surface, each carrying JSR obligations — correct by archetype and gate profile, -but four packages where a less disciplined design would ship one. - -**The typed binding is generated, and validation is narrower than users will initially want.** -`isolatedDeclarations` plus the oRPC-only carve-out mean the inferred contract type cannot be -published from a framework package, so it terminates in a generated app-local module and a stale -binding is refused rather than tolerated — correct, but a developer can be told "re-emit" at an -inconvenient moment. Likewise "derive all my validators from the schema" is the intuitive -expectation, and this design refuses it for filters, nested writes, polymorphic narrowing, and -computed/raw/aggregate results unless exact metadata is contributed, so some users will experience -`DB_VALIDATION_UNSUPPORTED` as a missing feature. It is a correct refusal, and this RFC would rather -explain it than silently return a schema that accepts wrong data. - -**Some capabilities regress relative to today.** Prisma SQLite, MongoDB, MySQL, and SQL Server are -not carried forward; multi-namespace end-to-end typing is withheld; destructive plugin removal is -not guaranteed. Each names the gate that would release it, but a user with a MySQL target today has -no path inside this design other than the old release line. And one soundness seam at `runtime.bind` -is accepted rather than eliminated, mitigated by three gates but real. - -**The conformance matrix is expensive.** Real PostgreSQL, Windows and Linux, failure injection, -crash and unknown-outcome recovery, packed consumer installs, and a two-consumer Standard Schema -corpus are all required before the adapter is advertised. That cost is the point — it turns -"upstream says it is supported" into "NetScript proved it" — but it is a standing CI bill. +**It is a large program, it lands as a break, and it adds indirection.** Twelve waves, six new +packages, changes to four existing ones, a doctrine amendment, a first-party plugin conversion, and +a cutover; until then the repository carries both foundations on separate branches. A definition +compiles to a manifest, which binds a plan, which yields a receipt — for a solo developer with one +PostgreSQL database that is more moving parts than `prisma migrate dev`, and the pay-off arrives +with the second target, the first plugin space, the first partial failure, and the first production +apply. Six published packages are likewise a real maintenance surface, each carrying JSR +obligations. + +**It bets on an Early-Access upstream, and pays for the insulation.** RC1 is not recommended for +production, its notes warn that respins may break APIs and the contract format, and the seam moved +within six days of the tag. One adapter package, one facade module, an import allowlist, independent +versioning, and a kill switch that costs a provider rather than the architecture keep that contained +— but they add a boundary a direct dependency would not need, and the conformance matrix behind them +(real PostgreSQL, Windows and Linux, failure injection, crash and unknown-outcome recovery, packed +consumer installs, a two-consumer Standard Schema corpus) is a standing CI bill. That cost is the +point: it turns "upstream says it is supported" into "NetScript proved it". + +**Validation is narrower than users will want, and some capabilities regress.** "Derive all my +validators from the schema" is the intuitive expectation, and this design refuses it for filters, +nested writes, polymorphic narrowing, and computed/raw/aggregate results unless exact metadata is +contributed — a correct refusal this RFC would rather explain than silently return a schema that +accepts wrong data. Prisma SQLite, MongoDB, MySQL, and SQL Server are not carried forward, +multi-namespace typing is withheld, and destructive plugin removal is not guaranteed; each names the +gate that would release it, but a user with a MySQL target today has no path inside this design +other than the old release line. One soundness seam at `runtime.bind` is likewise accepted rather +than eliminated, mitigated by three gates but real. And the type story is not uniform: app-authored +spaces need no emitted types at all, while a queried pinned space depends on a declaration the +launcher emits — automatic and atomic, but still a build artifact a reader has to know exists. ## Rationale and alternatives ### Why this shape -Four observations force the design. **The five current systems fail because nothing joins them**, so -a join point is mandatory — and it must be a _value_ rather than a live object, because inspection, -diffing, hashing, review, transport to CI, agent consumption, and stale detection are all properties -of a serialisable value, while a live graph reachable from feature code is a service locator with a -domain name. **Provider identity replaced target identity**, so identity must be declared, -provider-neutral, and the key of every artifact. **Prisma's contract/space/lineage semantics are -genuinely good while its operational layer has gaps** — no mature reset/resolve/diff/squash -workflow, no general shadow-database workflow, no complete advisory lock story, no row-count-aware -data-loss analysis, no extension removal — so waiting would gate adoption on someone else's roadmap, -while owning them means NetScript keeps them when a second provider arrives. And **the publish -constraint decides where types live**: `isolatedDeclarations` plus the oRPC-only carve-out -determines that the inferred binding is generated app-side. +Four observations force the design. **Nothing joins the five current systems**, so a join point is +mandatory — and it must be a _value_, because inspection, diffing, hashing, review, transport to CI, +agent consumption, and stale detection are properties of a serialisable value, while a live graph +reachable from feature code is a service locator with a domain name. **Provider identity replaced +target identity**, so identity must be declared, provider-neutral, and the key of every artifact. +**Prisma's contract, space, and lineage semantics are good while its operational layer has gaps**, +so NetScript owns policy, locking, recovery, receipts, and the saga. And **NetScript already has an +adoption pattern** — preset, factories, native primitives — so the database surface is a third +instance of it rather than a new idiom. ### Alternatives considered and rejected -| Alternative | Why rejected | -| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Keep Prisma 7 and add Prisma 8 as an opt-in pilot (issue #313) | It preserves every seam in Motivation. The current architecture is what a compatibility-first constraint produced; repeating the constraint reproduces the outcome. | -| A one-to-one migration of the current design onto Prisma 8 | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are all independent of the Prisma major version. | -| A proprietary NetScript schema DSL lowering to the contract | A third schema language tracking every native type, index kind, constraint, and default; permanently lagging; errors become a translation of a translation. | -| A live `DatabaseGraph` as the public artifact | A runtime graph accretes traversal APIs and becomes a lookup surface. The manifest gives every property the graph was wanted for. | -| Re-export Prisma from a NetScript package | Doctrine AP-14, the publish constraint, and 138 upstream export keys at the pin — a re-export converts Early-Access internals into NetScript public API. | -| Generated mirror validators (a schema file per model/input/output) | Combinatorially wrong for selection-aware output validation, and it recreates the repair pipeline that already failed here. | -| Claim full operation/result validation from contract data | The pinned source shows the operation and result type maps are phantom and erased at runtime. The claim would be false. | -| Copy plugin schema fragments (status quo) | No version, ownership, capability guard, dependency order, provenance, or safe removal — with two recorded production failures. | -| Build a hosted control plane (registry, RBAC, approvals, drift) | Those are persistent products with operators, not local primitives. Atlas Cloud, Pulumi Cloud, and Bytebase demonstrate the value **and** the required services. | -| Extend the `--allow-slow-types` carve-out to database packages | It converts an application-local inference problem into permanent framework-wide publish debt. | +| Alternative | Why rejected | +| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Keep Prisma 7 and add Prisma 8 as an opt-in pilot (issue #313) | It preserves every seam in Motivation; the current architecture is what a compatibility-first constraint produced. | +| A one-to-one migration of the current design onto Prisma 8 | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are version-independent. | +| A proprietary NetScript schema DSL lowering to the contract | A third schema language tracking every native type, index kind, constraint, and default; permanently lagging. | +| A live `DatabaseGraph` as the public artifact | A runtime graph accretes traversal APIs and becomes a lookup surface; the manifest gives every property it was wanted for. | +| Re-export Prisma from a NetScript package | AP-14, the publish constraint, and 138 upstream export keys — it converts Early-Access internals into NetScript public API. | +| A generated app-local binding as the universal default | Prisma's phantom contract type parameter and an app-local `isolatedDeclarations` scope make direct inference sound for app-authored spaces, so universal generation would add a ritual with no type benefit. Generation is kept exactly where evidence is missing: pinned spaces the consumer did not author, and publishable exports. | +| Generated mirror validators (one schema file per model/input/output) | Combinatorially wrong for selection-aware output, and it recreates the repair pipeline that already failed here. | +| Claim full operation/result validation from contract data | The operation and result type maps are phantom and erased at runtime; the claim would be false. | +| Copy plugin schema fragments (status quo) | No version, ownership, capability guard, dependency order, provenance, or safe removal — two recorded production failures. | +| Build a hosted control plane (registry, RBAC, approvals, drift) | Persistent products with operators, not local primitives; a local kernel exposes stable artifacts and integration events instead. | +| Extend the `--allow-slow-types` carve-out to database packages | It converts an application-local inference problem into permanent framework-wide publish debt. | ### Market lessons @@ -1094,28 +1283,21 @@ Seventeen comparators were examined for the framework-level problem rather than Five lessons changed this design: - **One resolved manifest beats many config files.** Named connections in Adonis, Rails, and Django - are legible, and Atlas proves multiple schema sources can compose — but none yields a - deterministic content-addressed resolved value, and Atlas's composite ordering is load order - rather than declared semantic edges. -- **Contributor-owned migration spaces are the only ownership model that scales.** Django's per-app - graphs and Prisma's contract spaces are the strong examples; Flyway locations and Liquibase - changelogs merge into one shared history and cannot express contributor isolation. + are legible and Atlas proves multiple schema sources can compose, but none yields a deterministic + content-addressed resolved value. +- **Contributor-owned migration spaces are the only ownership model that scales**, and **managed and + external ownership are different**. Django's per-app graphs and Prisma's contract spaces are the + strong examples, while Flyway locations and Liquibase changelogs merge into one shared history; + Rails' `database_tasks: false`, Drizzle's filters, Atlas's external sources, and the upstream + Supabase drift incident all show that treating every visible object as your own reports permanent + false drift. - **A preview is not an executable plan, and applying a valid plan is not a transaction.** Atlas's develop → review → deliver → apply model is the right process shape; Terraform and Pulumi supply - the harder recovery lesson this RFC encodes as `outcome-unknown` and inspect-before-resume. -- **Managed and external ownership are different.** Rails' `database_tasks: false`, Drizzle's - filters, Atlas's external sources, and the upstream Supabase drift incident all point one way: a - framework that treats every visible object as its own reports permanent false drift. + the recovery lesson encoded here as `outcome-unknown` and inspect-before-resume. - **Runtime-derived, selection-shaped validation is the right ergonomic, but the boundary must be standard.** ZenStack v3 is the closest comparator ([its Zod factory][zenstack-zod]), and its - validators are Zod-specific, its plugin surface is preview, and schema-time and runtime - installation can diverge. NetScript binds both halves in one contribution record and keeps - Standard Schema as the boundary. - -Also stated as scope law: a _local_ meta-framework must not rebuild hosted RBAC, workspace and fleet -management, remote schema registries and environment promotion, policy-as-a-service, approval -engines, or continuous drift control planes. NetScript exposes stable artifacts and integration -events so such a system can be added as an adapter. + validators are Zod-specific while schema-time and runtime installation can diverge; NetScript + binds both halves in one contribution record and keeps Standard Schema as the boundary. ## Breaking changes and migration @@ -1126,19 +1308,18 @@ events so such a system can be added as an adapter. None of the following survives: a Prisma 7 client or facade; a legacy generated module or alias barrel; a dual client or `setClient` lifecycle; a deprecated re-export; a dual migration history; a copied schema bridge; a runtime shim; or any code path that selects between the old and new stacks. -Old and new stacks may coexist **in the repository**, on separate branches or release lines, while -features are developed; a single application composition may never load both. That is a branch -strategy, not a public API. - -| Surface | Break | -| ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| `@netscript/database` (current adapters, `setClient`) and `@netscript/prisma-adapter-mysql` | Replaced wholesale by the new package graph; the hand-written driver adapter is retired. | -| Generated engine workspaces `database//` | Deleted, along with their `db:*` task graph, repair scripts, and the Zod pipeline. | -| Generated client deep imports | Removed. Applications consume the generated binding, never a path into generated output. | -| `@netscript/plugin` legacy database abstracts and plugin `*.prisma` fragments | Replaced by `definePluginSpace` and plugin-owned spaces with pinned artifacts. Copying stops. | -| The current `db` CLI verbs | Replaced by catalog projections; `generate` becomes pure `emit`, `migrate` splits into `plan` + `apply`, `list`/`status` become `inventory`/`verify`. | -| Implicit target defaulting and silent single-target execution | **Deliberately removed.** There is no fallback chain anywhere. | -| Prisma SQLite / MySQL / SQL Server targets | Not carried forward. Structured `db.target.unsupported`, no fallback. | +Old and new may coexist **in the repository** on separate branches or release lines while features +are developed; a single application composition may never load both. + +| Surface | Break | +| ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database` (current adapters, `setClient`) and `@netscript/prisma-adapter-mysql` | Replaced wholesale; the hand-written driver adapter is retired. | +| Generated engine workspaces `database//` | Deleted with their `db:*` task graph, repair scripts, and Zod pipeline. | +| Generated client deep imports | Removed; applications consume the app-local binding. | +| `@netscript/plugin` legacy database abstracts and plugin `*.prisma` fragments | Replaced by `definePluginSpace` and pinned-artifact spaces. Copying stops. | +| The current `db` CLI verbs | Catalog projections: `generate` → pure `emit`, `migrate` → `plan` + `apply`, `list`/`status` → `inventory`/`verify`. | +| Implicit target defaulting and silent single-target execution | **Deliberately removed.** There is no fallback chain anywhere. | +| Prisma SQLite / MySQL / SQL Server targets | Not carried forward; structured `db.target.unsupported`. | ### The adoption protocol @@ -1147,131 +1328,118 @@ a permanent command, and it is deleted after the migration window. It operates o selected target set** and returns a status for **every** selected target — there is no "whatever was reachable" mode. -| Step | Operation | Mutates the database? | Failure behaviour | -| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| 1 | Read legacy configuration and layout, and derive explicit `TargetId`s from config keys, never engine names | No | Refuse on ambiguous or duplicate keys, and when two keys resolved to one engine directory | -| 2 | Introspect every **selected** target | No | An unreachable target is reported as `not-attempted` with a reason code; the run continues for the rest and cannot be marked complete | -| 3 | Propose ownership — one space per attributable owner, plus `external`/`adopted` — and hard-stop on unattributed or conflicting objects | No | Objects that cannot be attributed are reported, never guessed | -| 4 | Compile the manifest, atomically emit artifacts and bindings, and establish one baseline lineage node per space matching the **observed** state | No | Standard composition diagnostics | -| 5 | Write provider marker metadata **only** — zero table or data DDL/DML | **Yes, markers only** | Idempotent and re-runnable; produces a receipt | -| 6 | Verify live state against the manifest and baseline; require zero drift on every selected target | No | Any diff is a genuine finding: an unattributed object or an incorrect ownership assignment | -| 7 | Delete legacy engine workspaces, task graphs, copied fragments, repair scripts, and old adapters | No | Reversible by reverting the commit | - -Step 5 is the load-bearing property: **no table is created, altered, or dropped during adoption**, -which is what makes the migration safe on production data. Full cutover — step 7 and the removal of -the legacy release line — is blocked until every _intended_ target has been reached, attributed, -baselined, and verified; a partially adopted target set is a resumable state, never a finished one. +| Step | Operation | Mutates the database? | Failure behaviour | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| 1 | Read legacy configuration and derive explicit `TargetId`s from config keys, never engine names | No | Refuse on ambiguous or duplicate keys, or when two keys resolved to one engine directory | +| 2 | Introspect every **selected** target | No | An unreachable target is `not-attempted` with a reason code; the run continues but cannot be marked complete | +| 3 | Propose ownership — one space per attributable owner, plus `external`/`adopted` — and hard-stop on unattributed or conflicting objects | No | Unattributable objects are reported, never guessed | +| 4 | Compile the manifest, atomically emit artifacts, and establish one baseline lineage node per space matching the **observed** state | No | Standard composition diagnostics | +| 5 | Write provider marker/ledger metadata **only** — no application-schema DDL, no application-data DML | **Yes: provider metadata rows** | Idempotent and re-runnable; every write is receipt-backed | +| 6 | Verify live state against the manifest and baseline; require zero drift on every selected target | No | Any diff is a genuine finding: an unattributed object or a wrong ownership assignment | +| 7 | Delete legacy engine workspaces, task graphs, copied fragments, repair scripts, and old adapters | No | Reversible by reverting the commit | + +Step 5 is the load-bearing property, stated precisely: adoption performs **no application-schema DDL +and no application-data DML**. It does write provider marker and ledger metadata — that is metadata +DML, it is idempotent, and every write is backed by a receipt — and it creates, alters, or drops +nothing that belongs to the application. That is what makes the migration safe on production data. +Full cutover — step 7 and removal of the legacy release line — is blocked until every _intended_ +target has been reached, attributed, baselined, and verified; a partially adopted target set is +resumable, never finished. Required before a release-class cutover: a seeded production-shaped **rehearsal** proving zero -schema/data mutation, with the receipt as evidence; a verified restorable **backup** before the -first mutating operation in each environment; a committed **ownership preflight** artifact listing -every target with reachability and provider version, every `ObjectKey` with owner and policy, every -unattributable object, and every capability requirement against what each target declares; -**destructive consent** as an approved signed plan; per-target **partial outcomes** with resume -tokens; a **crash** fault-injection run exercising checkpoints, `outcome-unknown`, and -inspect-before-resume; **idempotent marker** writes; a **secret** redaction conformance case; -**lock** contention, TTL expiry, holder death, and force-unlock preconditions; and an agreed -migration window, legacy release-line end date, and rollback runbook. +schema/data mutation with the receipt as evidence; a verified restorable **backup** before the first +mutating operation in each environment; a committed **ownership preflight** listing every target +with reachability and provider version, every `ObjectKey` with owner and policy, every +unattributable object, and every capability requirement; **destructive consent** as an approved +signed plan; per-target **partial outcomes** with resume tokens; a **crash** fault-injection run +exercising checkpoints, `outcome-unknown`, and inspect-before-resume; **idempotent marker** writes; +a **secret** redaction case; **lock** contention, TTL expiry, holder death, and force-unlock +preconditions; and an agreed migration window, legacy release-line end date, and rollback runbook. ### Rollback boundaries -| Point | Rollback | Cost | -| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -| Before the marker write | Delete generated artifacts | None; nothing was written to any database | -| After markers, before the cutover commit | Remove the adopted spaces' marker rows **where the provider's certified marker semantics prove removal is safe and idempotent**; otherwise the markers stay and the spaces remain `adopted` | Trivial; markers are metadata and carry no user data | -| After the cutover commit, before the first new `apply` | Revert the commit | Repository-only; the database is untouched | -| After the first new `apply` | **Forward only** — through lineage, the provider ledger, and receipts | Ordinary migration recovery; the receipt names which steps ran | +| Point | Rollback | Cost | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | +| Before the marker write | Delete generated artifacts | None; nothing was written to any database | +| After markers, before the cutover commit | Remove the adopted spaces' marker rows **where certified provider marker semantics prove removal is safe and idempotent**; otherwise preserve the marker and move the space to the retained verify-only tombstone state — no binding, plan, or apply until explicit re-adoption | Trivial; markers carry no user data | +| After the cutover commit, before the first new `apply` | Revert the commit | Repository-only; the database is untouched | +| After the first new `apply` | **Forward only** — lineage, provider ledger, receipts | Ordinary migration recovery; the receipt names which steps ran | -There is deliberately no "run both stacks" rollback. It would require the compatibility layer this -design refuses, and it would double the failure surface during precisely the window when the system -is least understood. +There is deliberately no "run both stacks" rollback: it would require the compatibility layer this +design refuses and would double the failure surface exactly when the system is least understood. ## Prior art -The +No product is a template. The [market analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md) -compares seventeen products in depth; the lessons this design actually adopted are listed above. The -sources that most directly shaped specific decisions are -[Django's per-app migration graphs with declared dependencies][django-multidb] and Prisma's -[contract spaces ADR][adr-212] for contributor ownership; -[Terraform's targeting guidance][tf-targeting] and -[Pulumi's interrupted-update recovery][pulumi-interrupted] for saga semantics, partial success, and -inspect-before-resume; [Flyway's `repair`][flyway-repair] for the distinction between repairing a -ledger and repairing a database; [ZenStack's runtime Zod factory][zenstack-zod] for selection-shaped -validator ergonomics; and the upstream [Supabase drift incident][pn-29896] for ownership policy. No -product is a template: the combination proposed here — one deterministic resolved manifest, -contributor-owned spaces with independent lineage, native upstream authoring with framework policy -around it, apply-bound plans with receipts, ownership-aware drift, capability-specific behaviour, a -programmatic core with CLI/agent projections, and a runtime Standard Schema boundary — does not -exist as a single local product today. - -NetScript's own prior art is the oRPC integration: the real upstream builder, NetScript policy -around it, precise types flowing from upstream values, Standard Schema consumed structurally, one -const-generic root fanning into several surfaces, and compile-failure soundness tests. The -[transfer analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md) -states exactly which parts transfer and which must not. +records the full comparison; the sources that shaped specific decisions are +[Django's per-app migration graphs][django-multidb] and Prisma's [contract spaces ADR][adr-212] for +contributor ownership, [Terraform's targeting guidance][tf-targeting] and +[Pulumi's interrupted-update recovery][pulumi-interrupted] for saga semantics, +[Flyway's `repair`][flyway-repair] for the ledger-versus-database distinction, +[ZenStack's runtime Zod factory][zenstack-zod] for selection-shaped validators, and the upstream +[Supabase drift incident][pn-29896] for ownership policy. + +NetScript's own prior art is closer. The oRPC integration proves the type discipline — the real +upstream builder, NetScript policy around it, precise types flowing from upstream values, Standard +Schema consumed structurally, and compile-failure soundness tests +([transfer analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md)) +— while `defineService`, `defineServices`, and `defineFreshApp` prove the adoption shape: a preset +that literally calls the public factories, which compose the native library +([layered DX audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md)). ## Unresolved questions The vocabulary, identity model, package graph, artifact taxonomy, refusal boundary, ownership model, -plan/apply/recovery semantics, validation bounds, and clean-break law are **locked**. Nothing below -can force a package-boundary rewrite; each item is a mechanism, version, or release decision behind -stable public semantics, and the full ledger with owning waves is in the -[approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md). - -Implementation-time, by owning wave: the canonical manifest/digest encoding and format-version -evolution policy (W1 — a `formatVersion` exists and consumers refuse unknown versions); the exact -Prisma import allowlist, module specifiers, and supported compatibility window (W3 — adapter-local -by construction, and pinning a specifier now would design against a surface that moved post-RC); -whether the multi-namespace capability can be claimed at all (W3); the mapping of extension facets -onto the provider's authoring/control/runtime/validation locations (W3); the concrete scope shapes -and whether an interactive transaction can expose the ordinary query type (W4); plan signature -format and production key custody (W5/W10 — the port and the signed-plan requirement are locked, -only the mechanism is open); the provider lock mechanism (W5, per provider); receipt storage -location and retention (W5); the initial augmentation grant vocabulary (W7); whether the testkit -needs a runnable binary or folds into `./testing` subpaths (decided before W1); and the migration -window, legacy release-line end date, and rollback runbook (W10). +plan/apply/recovery semantics, validation bounds, layered adoption surface, and clean-break law are +**locked**. Nothing below can force a package-boundary rewrite, and the full ledger with owning +waves is in the [approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md). + +Implementation-time, by owning wave: the exact Prisma import allowlist, module specifiers, L1/L2 API +spelling, the source-native-versus-generated boundary, and whether the multi-namespace capability +can be claimed at all (W3 — adapter-local by construction, and pinning a specifier now would design +against a surface that moved post-RC); the concrete scope shapes and whether an interactive +transaction can expose the ordinary query type (W4); plan signature format and key custody, the +provider lock mechanism, and receipt storage and retention (W5/W10 — the ports and the signed-plan +requirement are locked, only the mechanisms are open); and the migration window, legacy release-line +end date, and rollback runbook (W10). Conditional on upstream, each blocking only a _claim_: whether Prisma's namespace type map stops -flattening non-default namespaces (no cast workaround is permitted); whether prepared-statement, -transaction, raw-SQL, and numeric/aggregate semantics settle by GA (aggregate semantics already -changed after RC1, so no public guarantee is made until proven per pin); whether upstream ships an -extension/space removal primitive (if not, `retain` is the product behaviour); whether the contract -format stabilises (more than one format break without a migration path is a kill trigger); whether -the Deno platform matrix is clean without vendoring or patching (failure kills the adapter, not the -kernel); and whether the runtime-derived validation direction is sustained upstream (the bounded -interpreter does not depend on it). +flattening non-default namespaces; whether prepared-statement, transaction, raw-SQL, and +numeric/aggregate semantics settle by GA (aggregate semantics already changed after RC1, so no +public guarantee is made until proven per pin); whether upstream ships an extension or space removal +primitive (if not, `retain` is the product behaviour); whether the contract format stabilises (more +than one break without a migration path is a kill trigger); and whether the Deno platform matrix is +clean without vendoring or patching (failure kills the adapter, not the kernel). Explicitly deferred rather than open: a second provider; Prisma SQLite, MongoDB, MySQL, and SQL -Server; runtime capability negotiation; AOT validation; archive/drop removal beyond retain; public +Server; runtime capability negotiation; AOT validation; archive/drop removal; public raw/prepared/aggregate conveniences; and hosted approval, registry, promotion, fleet, drift, and -secret services. Cross-database relations and transactions are **unsupported**, not deferred parity -debt. +secret services. Cross-database relations and transactions are **unsupported**, not parity debt. Two questions are genuinely for reviewers. Is detach-and-retain as the only guaranteed removal acceptable for the first release, given that archive and drop are specified but unclaimed? And is -the generated app-local binding the right trade against the alternative of a framework-published -contract-typed value, which the publish constraint forbids? +the split type story the right trade — an app-local `isolatedDeclarations: false` authoring scope +(build inputs, never JSR exports) for spaces the application authors, plus an automatically emitted +declaration for spaces it only consumes — against the simpler-to-explain alternative of generating +every space's types? ## Future possibilities Natural extensions this architecture enables and this RFC deliberately excludes: - **A second certified provider**, proving the narrow provider SPI with a real adapter when demand - and maturity exist — never with a speculative fallback built to prove a port. + and maturity exist — never a speculative fallback built to prove a port. - **The multi-namespace capability**, **archive/drop retirement**, and **AOT validation**, each - released by its gate (upstream type parity, provider conformance, corpus equivalence) rather than - by a workaround. -- **A policy-applied authoring factory** that pre-applies naming and control defaults and forwards - the provider's exact composed helpers — revisitable once the thin surface has shipped, and only if - it needs no cast, private import, or copied overload. + released by its gate — upstream type parity, provider conformance, corpus equivalence — rather + than by a workaround. - **Delivery-backend adapters** exporting plans, receipts, and diagnostics to Atlas, Bytebase, or a - hosted approval system — as adapters over stable artifacts, never a local reimplementation. -- **Deeper agent capability**: an allowlisted operation surface with policy metadata derived from - the catalog, so an agent gets structured operations rather than unrestricted query access. + hosted approval system, and **deeper agent capability** through an allowlisted operation surface + with catalog-derived policy metadata — adapters over stable artifacts, never local + reimplementations. - **Additional first-party spaces** beyond auth, workers, sagas, triggers, and streams, and - **read-replica-aware routing helpers** if a concrete need appears — as composition affordances, - never a hidden router that could silently send a write to a reader. + **read-replica-aware routing helpers** if a concrete need appears — composition affordances, never + a hidden router that could send a write to a reader. @@ -1287,6 +1455,18 @@ Natural extensions this architecture enables and this RFC deliberately excludes: [pn-3dc98cb]: https://github.com/prisma/prisma/commit/3dc98cb [pn-29896]: https://github.com/prisma/prisma/issues/29896 + + +[rc1-define-contract]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/contract/define-contract.ts#L46-L121 +[rc1-contract-example]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/prisma/contract.ts +[rc1-postgres-runtime]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/runtime/postgres.ts#L96-L110 +[rc1-no-emit]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/prisma-no-emit/context.ts#L11 +[rc1-orm-read]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/get-user-posts.ts +[rc1-orm-write]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/create-user.ts +[rc1-space-aggregate]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/1-framework/3-tooling/migration/src/aggregate/types.ts#L71-L124 +[rc1-namespace-map]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/2-sql/2-authoring/contract-ts/src/contract-types.ts#L644-L691 +[rc1-type-maps]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/2-sql/1-core/contract/src/types.ts#L207 + [flyway-repair]: https://documentation.red-gate.com/flyway/reference/commands/repair From d28d8e779125a268dd10057526078d1abb4b885e Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 23:04:33 +0200 Subject: [PATCH 15/19] docs(rfc): close database semantic review findings --- rfcs/0000-database-architecture.md | 497 ++++++++++++++++------------- 1 file changed, 275 insertions(+), 222 deletions(-) diff --git a/rfcs/0000-database-architecture.md b/rfcs/0000-database-architecture.md index e5ca8a5133..3d652d46a1 100644 --- a/rfcs/0000-database-architecture.md +++ b/rfcs/0000-database-architecture.md @@ -23,12 +23,11 @@ recipe** for the golden path, the **L2 factories** it calls, and **L3 native Pri primitives**. None of them describes a model, field, relation, or query: NetScript adds no schema or query vocabulary and re-exports no builder. A compiler with no live dependencies resolves those definitions into canonical contract artifacts and one deterministic, content-addressed -`DatabaseManifest`. That manifest is the durable join point for everything downstream: an app-local -binding typed from the authored contracts by erased inference, with an automatically emitted -declaration supplying the same evidence for any space the consumer did not author; typed -process/request sessions; bounded `StandardSchemaV1` validators; programmatic -emit/inspect/plan/apply/verify operations; provider markers and ledgers; immutable receipts; and -generated CLI, Aspire, and agent projections. +`DatabaseManifest`. That manifest is the durable join point for everything downstream: an emitted +app-local binding descriptor coupling erased inference for authored contracts with an automatically +emitted declaration for any space the consumer did not author; typed process/request sessions; +bounded `StandardSchemaV1` validators; programmatic emit/inspect/plan/apply/verify operations; +provider markers and ledgers; immutable receipts; and generated CLI, Aspire, and agent projections. The end-to-end flow is one pipeline of separately named values, and no stage may impersonate another: @@ -155,12 +154,12 @@ across the churn. This section describes the system as if it had shipped. -> **Example status.** A snippet with a file-path comment and imports is a complete module for the -> packages in [§ The package graph](#the-package-graph); a snippet marked _excerpt_ names the values -> it assumes from an earlier one. `@netscript/*` shapes are proposed API. `@prisma/*` shapes are -> observed in the pinned RC1 checkout and linked to it; the exact module specifier is an -> adapter-pinned, implementation-time decision (W3), because Prisma's public CLI package name -> changed six days after the RC tag. +> **Example status.** A snippet explicitly marked _complete module_ is complete for the packages in +> [§ The package graph](#the-package-graph); every other snippet is an excerpt whose surrounding +> application values are named where they matter. `@netscript/*` shapes are proposed API. +> `@prisma/*` shapes are observed in the pinned RC1 checkout and linked to it; the exact module +> specifier is an adapter-pinned, implementation-time decision (W3), because Prisma's public CLI +> package name changed six days after the RC tag. ### Step 1 — author the contract natively @@ -170,25 +169,30 @@ composed helper surface and returns native `types`, `models`, and `enums` ([`define-contract.ts`][rc1-define-contract]; the callback overload preserves its returned literal types). -One thing precedes the contract: the extension bundle. A logical extension such as pgvector has -authoring, control, runtime, and validation facets, and the authoring facet has to exist _before_ -the builder runs, so the application configures the bundle once and passes its **public authoring -projection** into `defineContract`: +One thing precedes the contract: the configured provider value. A logical extension such as pgvector +has authoring, control, runtime, and validation facets, and the authoring facet has to exist +_before_ the builder runs. The application therefore creates the extension once, registers it once +on the provider, and uses that provider's **public authoring scaffold** with `defineContract`: ```ts -// database/extensions.ts — one configured, identity- and version-checked bundle -import { pgvector } from '@netscript/database-prisma-postgres'; +// database/provider.ts — complete module; the sole live provider/extension composition root +import { pgvector, prismaPostgres } from '@netscript/database-prisma-postgres'; -export const vector = pgvector({ dimensions: 1536 }); +const vector = pgvector({ dimensions: 1536 }); + +export const postgres = prismaPostgres({ + minVersion: 15, + extensions: [vector], +}); ``` ```ts // database/app.contract.ts — provider-native authoring; specifier pinned in W3 import { defineContract, rel } from '@prisma/orm-postgres/contract-builder'; -import { vector } from './extensions.ts'; +import { postgres } from './provider.ts'; export const appContract = defineContract( - { extensions: { pgvector: vector.authoring } }, // the bundle's authoring facet, not a second import + postgres.authoring.scaffold, ({ field, model, type }) => { const types = { Embedding: type.pgvector.Vector(1536) } as const; @@ -232,6 +236,12 @@ owns only the orchestration around the contract, and that surface has three leve The same app and the same `appContract` appear at every level. L1 calls L2; L2 produces the value L3's primitives consume. Nothing below defines a model, field, relation, or query. +`postgres.authoring.scaffold` contains Prisma's native PostgreSQL scaffold composed with the +registered extension authoring facets. It does not expose control or runtime implementations. The +same `postgres` module can therefore be imported by build tooling and by the application runtime +without making the runtime import the contract module; the dependency points from the contract to +the provider, never back from the provider to authoring code. + **L1 — the golden path.** One call with inspectable, replaceable defaults: target id `primary`, app space `app`, managed ownership, and retain-on-removal. The provider is **not** one of the defaults — the application constructs exactly one configured provider value and hands it in, so a @@ -241,20 +251,15 @@ provider-neutral package never chooses, imports, or looks up a provider. // database/database.ts import { fromAspire } from '@netscript/aspire'; import { defineSingleTargetDatabase } from '@netscript/database'; -import { prismaPostgres } from '@netscript/database-prisma-postgres'; import { authSpace } from '@netscript/plugin-auth-core/database'; import { appContract } from './app.contract.ts'; -import { vector } from './extensions.ts'; - -/** The one configured provider value. Targets, runtime, and control all receive this object. */ -export const postgres = prismaPostgres({ minVersion: 15 }); +import { postgres } from './provider.ts'; export default defineSingleTargetDatabase({ provider: postgres, contract: appContract, connection: fromAspire('netscript-db'), spaces: [authSpace()], // plugin-owned schema, independently versioned - extensions: [vector], // the same bundle the contract was authored with }); ``` @@ -279,14 +284,11 @@ import { defineDatabaseTarget, fromEnv, } from '@netscript/database'; -import { prismaPostgres } from '@netscript/database-prisma-postgres'; import { authSpace } from '@netscript/plugin-auth-core/database'; import { appContract } from './app.contract.ts'; -import { vector } from './extensions.ts'; +import { postgres } from './provider.ts'; import { warehouseContract } from './warehouse.contract.ts'; -export const postgres = prismaPostgres({ minVersion: 15 }); // configured once, reused everywhere - const primary = defineDatabaseTarget({ id: 'primary', provider: postgres, @@ -313,7 +315,7 @@ export default defineDatabase({ contract: appContract, // `typeof appContract` is preserved exactly policy: { removal: 'retain' }, }), - auth: authSpace({ target: 'primary' }), + [authSpace.id]: authSpace({ target: 'primary' }), warehouse: defineDatabaseSpace({ id: 'warehouse', owner: 'app', @@ -322,7 +324,6 @@ export default defineDatabase({ contract: warehouseContract, }), }, - extensions: [vector], // the same configured bundle, still registered exactly once }); ``` @@ -332,92 +333,92 @@ is refused with `db.compose.cross-target-relation`, and no multi-target operatio as atomic. `defineDatabaseSpace` stores `appContract` and preserves `typeof appContract` unchanged; everything -NetScript adds is plain data that survives a provider replacement. The target key is checked where -both halves are visible: `defineDatabase` requires every space's target to be a key of `targets`, so -`target: 'primry'` is a type error at that call, and a bypassed check is refused with -`db.compose.target.unknown` — there is no fallback chain anywhere. - -**L3 — the native foundation.** The same native contract and the same definition value, but the -application drives the pipeline itself instead of letting the launcher do it: compiler → manifest → -adapter binding → runtime → control, with no NetScript magic in between. +NetScript adds is plain data that survives a provider replacement. Both coordinates are checked +where their halves are visible: `defineDatabase` requires every space's target to be a key of +`targets` and every map key to equal that contribution's canonical `SpaceId`. Thus +`target: 'primry'` or `{ auth: authSpace(...) }` is a type error at that call; a bypassed check is +refused with `db.compose.target.unknown` or `db.compose.space-id.mismatch` — there is no fallback or +alias chain anywhere. + +**L3 — the native foundation.** The same native contract and definition, but the application owns +the two module-graph phases that the launcher normally sequences. Emission must finish before the +application imports emitted bindings; pretending both happen through static imports in one module +would make first boot impossible and could pair a new manifest with a stale binding. ```ts -// tools/pipeline.ts — excerpt. `database` and `postgres` come from database/database.ts above, -// `primaryBinding` from database/binding.ts below, `connections` from Step 3's composition root, -// and `io` is the artifact source/publisher pair the launcher normally supplies. +// tools/emit-database.ts — excerpt; a build process runs this before application type-check/load. +// `io` is the explicit artifact source + atomic publisher the launcher normally supplies. import { compileDatabase } from '@netscript/database'; -import { createDatabaseControl } from '@netscript/database-control'; -import { createDatabaseRuntime } from '@netscript/database-runtime'; +import database from '../database/database.ts'; -const compiled = await compileDatabase(database, io); // offline effects only; no connection in scope +const compiled = await compileDatabase(database, io); // offline effects; no connection in scope if (!compiled.ok) throw new DatabaseCompositionError(compiled.diagnostics); - -const { manifest } = compiled; // durable, content-addressed; the only value passed on from here - -await using runtime = await createDatabaseRuntime({ - manifest, - providers: [postgres], - bindings: [primaryBinding], - scope: 'process', - connections, -}); - -const control = createDatabaseControl({ manifest, providers: [postgres] }); ``` -Nothing downstream of `compileDatabase` receives the `DatabaseDefinition`: runtime and control take -the manifest, the configured provider, connections, and bindings. The binding itself is the one -place where app-local type evidence and emitted artifacts meet: +The successful atomic publish contains the manifest and one target binding descriptor. The following +is simplified **emitted output**, not code a developer maintains: ```ts -// database/binding.ts — hand-written once -import type { ContractOf } from '@netscript/database'; -import type { ProcessSessionOf } from '@netscript/database-runtime'; +// .netscript/database/primary.binding.ts — emitted atomically with manifest.ts +import type database from '../../database/database.ts'; import { + artifactSpaceEvidence, createPrismaPostgresBinding, + definePrismaPostgresBindingDescriptor, type QueriesOf, + sourceSpaceEvidence, } from '@netscript/database-prisma-postgres/binding'; -// Source-native evidence: type-only, erased at run time. -import type database from './database.ts'; -// Generated declaration: the auth space is artifact-only here, so its exact type cannot be -// reconstructed from JSON. The launcher emits this declaration atomically during the same compile. -import type { AuthContract } from '../.netscript/database/primary/auth.contract.d.ts'; -import { manifest } from '../.netscript/database/manifest.ts'; // emitted value - -export const primaryBinding = createPrismaPostgresBinding<{ - app: ContractOf; - auth: AuthContract; -}>({ +import type { ProcessSessionOf } from '@netscript/database-runtime'; +import type { AuthContract } from './primary/plugin-auth.contract.d.ts'; +import { manifest } from './manifest.ts'; + +const descriptor = definePrismaPostgresBindingDescriptor({ target: 'primary', - manifest, // carries the ManifestDigest, provider pin, and per-space ContractSnapshotIds + manifestDigest: 'nsdb1:9f3c…', + spaces: { + app: sourceSpaceEvidence({ snapshot: 'nsdbc1:2c71…' }), + 'plugin:@netscript/plugin-auth': artifactSpaceEvidence({ + snapshot: 'nsdbc1:71ba…', + }), + }, }); -export type PrimaryQueries = QueriesOf; // { app: …; auth: … } +export const primaryBinding = createPrismaPostgresBinding({ descriptor, manifest }); +export type PrimaryQueries = QueriesOf; export type PrimarySession = ProcessSessionOf; ``` -The type argument is a **literal, space-keyed map** and each entry carries its own evidence: `app` -from erased source inference, `auth` from a generated declaration. Prisma contract spaces are -separate contracts with separate artifacts and heads ([space aggregate][rc1-space-aggregate]), so -the binding never merges them into one contract or one query type, and each entry keeps its own -`ContractSnapshotId`. An application that does not query a pinned space simply omits it from the -map: the space is still planned, applied, and verified — it just has no typed query surface. -Claiming `auth` in `PrimaryQueries` without importing its declaration would be the unsound version -of this, and the emitter refuses to produce a binding whose map names a space it has no evidence -for. `primaryBinding` is a real value constructed by the adapter factory from the manifest's -identities — never an ambient `declare const`. +The compiler, not application code, writes that literal map. Each key is the canonical `SpaceId` +used by definitions, manifests, receipts, `.space(...)`, and diagnostics; local aliases do not +exist. Each value couples type-only evidence to a value-level `ContractSnapshotId`, while the +descriptor itself carries its target and `ManifestDigest`. The adapter rejects a missing, duplicate, +extra, wrong-target, or wrong-snapshot entry before returning a binding, and bind time rechecks the +descriptor against the manifest. Editing or hand-writing the generated module is detected by +`db emit --verify`. + +`app` still gets its exact contract type from erased `typeof database`; no app model type is +generated. The plugin space needs the automatically emitted `AuthContract` declaration because its +publisher supplied data artifacts rather than the consumer's TypeScript source. Prisma spaces stay +separate contracts with separate heads ([space aggregate][rc1-space-aggregate]); this descriptor +associates them but never merges their models or query types. An application that does not query a +pinned space asks the emitter to omit its binding evidence: the space is still planned, applied, and +verified, but has no typed query surface. + +Only after that build phase does the application module graph import `primary.binding.ts` and create +runtime or control values. Nothing downstream receives `DatabaseDefinition`: runtime and control +take the manifest, the same configured provider value, connections, and emitted bindings. #### Who owns what -| Surface | Owner | Source of truth | Produces / lowers to | Must not cross | -| ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | -| `defineContract`, ORM and SQL query surfaces | `@prisma/orm-postgres`, imported directly by app and plugin authoring modules | Prisma | native contract value, `contract.json`, `contract.d.ts` | never mirrored, wrapped, or re-exported by NetScript | -| L1 `defineSingleTargetDatabase` and the L2 `defineDatabase*` factories | `@netscript/database` | this RFC | L1 calls L2 → one `DatabaseDefinition` → `resolveDatabase`/`compileDatabase` | no schema or query vocabulary, no provider import, no live IO | -| `prismaPostgres(...)` and `pgvector(...)` bundles | `@netscript/database-prisma-postgres` (or an extension publisher inside that boundary) | the adapter | one opaque configured value carrying identity, version, capabilities, and four facets | control/runtime facets never leave the provider boundary; the app touches only `.authoring` | -| `fromAspire` and its `ConnectionSource` adapter | `@netscript/aspire` | Aspire | plain connection-reference data, resolved at runtime | reference construction performs no IO; the kernel never imports Aspire | -| `createPrismaPostgresBinding`, `QueriesOf` | `@netscript/database-prisma-postgres/binding` | app-local `typeof` evidence + emitted declarations + manifest | per-space query/transaction types and a digest-verifying runtime value | provider-specific by design; never a provider-neutral query API | -| Sessions, validators, ports | `@netscript/database-runtime`, `@netscript/database-control` | manifest, binding, pinned artifacts | typed sessions, Standard Schema values, plans, receipts | provider-neutral packages never name a Prisma type | -| CLI, Aspire resources, agent surfaces | `@netscript/cli`, `@netscript/aspire` | `DatabaseManifest` + operation catalog | commands, resources, agent schemas | never evaluates authoring TypeScript | +| Surface | Owner | Source of truth | Produces / lowers to | Must not cross | +| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `defineContract`, ORM and SQL query surfaces | `@prisma/orm-postgres`, imported directly by app and plugin authoring modules | Prisma | native contract value, `contract.json`, `contract.d.ts` | never mirrored, wrapped, or re-exported by NetScript | +| L1 `defineSingleTargetDatabase` and the L2 `defineDatabase*` factories | `@netscript/database` | this RFC | L1 calls L2 → one `DatabaseDefinition` → `resolveDatabase`/`compileDatabase` | no schema or query vocabulary, no provider import, no live IO | +| `prismaPostgres(...)` and `pgvector(...)` bundles | `@netscript/database-prisma-postgres` plus compatible extension publishers | provider composition | one configured provider carrying registered extension identities and live facets | manifest stores only pins; runtime code never reconstructs executable facets from data | +| `fromAspire` and its `ConnectionSource` adapter | `@netscript/aspire` | Aspire | plain connection-reference data, resolved at runtime | reference construction performs no IO; the kernel never imports Aspire | +| emitted target descriptor; `createPrismaPostgresBinding`, `QueriesOf` | compiler; `@netscript/database-prisma-postgres/binding` | app-local `typeof` evidence + emitted declarations + manifest | canonical per-space query/transaction types and a digest-verifying runtime value | no hand-written evidence map, provider-neutral query API, or local space alias | +| Sessions, validators, ports | `@netscript/database-runtime`, `@netscript/database-control` | manifest, binding, pinned artifacts | typed sessions, Standard Schema values, plans, receipts | provider-neutral packages never name a Prisma type | +| CLI, Aspire resources, agent surfaces | `@netscript/cli`, `@netscript/aspire` | `DatabaseManifest` + operation catalog | commands, resources, agent schemas | never evaluates authoring TypeScript | #### The normal loop has no manual type generation @@ -435,7 +436,7 @@ never opens a connection, plans, or applies. Plan and apply authority stays expl ### Step 3 — sessions and queries ```ts -// composition-root.ts — hand-written; the only place a target is bound by name +// composition-root.ts — complete module; the only place a target is bound by name import { aspireConnections } from '@netscript/aspire'; import { createDatabaseRuntime, @@ -443,8 +444,10 @@ import { resolveConnections, } from '@netscript/database-runtime'; import { manifest } from './.netscript/database/manifest.ts'; -import { postgres } from './database/database.ts'; -import { primaryBinding, type PrimarySession } from './database/binding.ts'; +import { primaryBinding, type PrimarySession } from './.netscript/database/primary.binding.ts'; +import { PrismaAccountStore } from './database/accounts.store.ts'; +import { postgres } from './database/provider.ts'; +import type { AccountStore } from './ports/account.store.ts'; const connections = await resolveConnections(manifest, [aspireConnections, envConnections]); @@ -461,12 +464,18 @@ const accounts: AccountStore = new PrismaAccountStore(primary); // application-o ``` ```ts -// accounts.store.ts — application-owned adapter; `space` selects one contract space, -// and the surface inside it is Prisma's own (shapes follow the pinned RC1 ORM examples). +// database/accounts.store.ts — complete application-owned adapter. `space` selects one contract +// space; the surface inside it is Prisma's own (shapes follow the pinned RC1 ORM examples). +import type { FieldValueOf } from '@netscript/database-prisma-postgres/binding'; +import { primaryBinding, type PrimarySession } from '../.netscript/database/primary.binding.ts'; +import type { AccountStore } from '../ports/account.store.ts'; + +type UserId = FieldValueOf; + export class PrismaAccountStore implements AccountStore { constructor(private readonly primary: PrimarySession) {} - recentPosts(userId: string, limit: number) { + recentPosts(userId: UserId, limit: number) { return this.primary.space('app').orm.Post .where({ userId }) .orderBy((post) => post.createdAt.desc()) @@ -474,7 +483,7 @@ export class PrismaAccountStore implements AccountStore { .all(); } - register(id: string, email: string) { + register(id: UserId, email: string) { return this.primary.transaction( 'app', (tx) => tx.orm.User.select('id', 'email').create({ id, email }), @@ -483,15 +492,17 @@ export class PrismaAccountStore implements AccountStore { } ``` -Those are the RC1 collection shapes verbatim — Pascal-case models, fluent -`where(...).orderBy(...).take(...).all()` reads and `select(...).create(...)` writes -([reads][rc1-orm-read], [writes][rc1-orm-write]). `space('app')` hands back the provider's own -facade, so `.orm` is the ORM collection client and `.sql` is the same SQL DSL escape hatch the -provider already ships; NetScript wraps neither and adds no query language of its own. `postgres` is -the identical configured provider value the target declared, imported from the application's own -database module, so no composition root builds a second one. Connections are resolved from the -manifest's connection references through `ConnectionSource` adapters, which is the only place Aspire -enters the picture. +Those are the RC1 collection shapes — Pascal-case models, fluent `where(...)` filtering, +`orderBy(...).take(...).all()` reads and `select(...).create(...)` writes ([filter][rc1-orm-filter], +[reads][rc1-orm-read], [writes][rc1-orm-write]). The ID type is derived from the binding because +RC1's UUID string codec is a branded `Char<36>`, not an ordinary `string`; external text reaches +this port only after a boundary schema validates and decodes it to `UserId`. `space('app')` hands +back the provider's own facade, so `.orm` is the ORM collection client and `.sql` is the same SQL +DSL escape hatch the provider already ships; NetScript wraps neither and adds no query language of +its own. `postgres` is the identical configured provider value the target declared, imported from +the application's own database module, so no composition root builds a second one. Connections are +resolved from the manifest's connection references through `ConnectionSource` adapters, which is the +only place Aspire enters the picture. Feature code receives `AccountStore` — an application-owned port — not the runtime. `runtime.bind` is reachable only from declared composition-root files, enforced by `arch:check`, because a database @@ -519,7 +530,7 @@ space whose provider or extensions contribute no pack for an operation fails at instead of guessing. ```ts -import { primaryBinding } from './database/binding.ts'; +import { primaryBinding } from './.netscript/database/primary.binding.ts'; const users = primaryBinding.ref({ space: 'app' }).model('User'); @@ -529,19 +540,23 @@ const wholeUser = users.output('model', { representation: 'json' }); ``` Two methods, two representations. `input` produces an **operation input** schema — the pack-backed -half — while `output` produces a **selected result** schema for the shape actually requested, or the -whole-model shape under the explicit `'model'` form. The only public representations are `runtime` -and `json`. Both implement `StandardSchemaV1`, so they drop into independent consumers unchanged, -and each boundary uses the schema that actually describes it: +half — while `output` produces a selected-result schema or the whole-model shape under the explicit +`'model'` form. The literal `select` above is a validation projection, not a second query API and +not automatically the identity of a later query: the route handler's inferred result is checked +against the schema output type. The overload also accepts a provider-produced plan or selection +value when the adapter can prove every projected leaf; W3 must prove that public coupling for the +pinned ORM, and otherwise the explicit projection is the honest fallback. The only public +representations are `runtime` and `json`. Both implement `StandardSchemaV1`, so they drop into +independent consumers unchanged, and each boundary uses the schema that actually describes it: ```ts -// an oRPC route contract: create-input in, selected output out +// excerpt: `baseContract` is the application oRPC builder. const createAccount = baseContract .route({ method: 'POST', path: '/accounts' }) .input(createUser) .output(publicUser); -// a Fresh action consuming the same input schema for the same payload shape +// excerpt: `formPayload` is already a JSON-shaped object, not a raw FormData value. const parsed = await createUser['~standard'].validate(formPayload); if (parsed.issues) return renderFieldErrors(parsed.issues); ``` @@ -564,9 +579,12 @@ application. // plugins/auth/core/src/database.ts — the plugin owns a space, not a fragment import { CAP, pinnedSpace } from '@netscript/database-contract'; import { definePluginSpace } from '@netscript/plugin'; +import { authSpaceAggregate } from './artifacts/auth.space.ts'; + +export const AUTH_SPACE_ID = 'plugin:@netscript/plugin-auth' as const; export const authSpace = definePluginSpace({ - id: 'plugin:@netscript/plugin-auth', + id: AUTH_SPACE_ID, owner: '@netscript/plugin-auth', version: '0.0.7', contractFormat: '>=1 <2', @@ -577,21 +595,29 @@ export const authSpace = definePluginSpace({ denies: ['drop-column', 'change-type', 'add-required-column'], }, policy: { removal: 'retain' }, - // One pinned space aggregate, not a lone contract.json: descriptor snapshot, canonical contract - // data *and* declaration, migration packages and graph, head ref, hashes, and provenance. - space: pinnedSpace('./artifacts/auth.space'), + // A generated module statically materializes the whole aggregate in Deno's module graph. + space: pinnedSpace(authSpaceAggregate), }); ``` -`definePluginSpace` returns a **callable descriptor**: `authSpace()` takes the single target an L1 -application has, `authSpace({ target: 'primary' })` names one explicitly at L2, and both produce the -same `SpaceContribution`. Installation copies nothing into the application's schema; it writes that -pinned aggregate under the application's generated root, mirroring the shape Prisma's own migration -tooling already loads per space ([space aggregate][rc1-space-aggregate]). Production apply and -verify read the aggregate, so a deployment never needs the plugin's package graph resolvable, and an -aggregate that disagrees with the installed package is `db.space.skew`. Typed queries against the -space use the consumer declaration emitted from that same aggregate — the `AuthContract` import in -the binding above — and the spaces are never merged. +`definePluginSpace` returns a **callable descriptor** carrying its literal `.id`: `authSpace()` +takes the single target an L1 application has, `authSpace({ target: 'primary' })` names one +explicitly at L2, and both produce the same `SpaceContribution`. L2 keys the contribution with +`[authSpace.id]`; there is no shorter local alias whose meaning disappears at run time. +`auth.space.ts` is a checked-in deterministic generated module that statically contains or imports +every descriptor, canonical contract value and declaration, migration package/graph, head, hash, and +provenance record. It is in the publisher's explicit JSR asset/export allowlist, so Deno +materializes the complete graph before executing the consumer; `compileDatabase` receives an +already-loaded value and performs no fetch. The release gate proves a cold remote consumer can +materialize the package once and then run emit/verify with network access disabled. + +Installation copies nothing into the application's schema; it publishes that pinned aggregate under +the application's generated root, mirroring the shape Prisma's own migration tooling already loads +per space ([space aggregate][rc1-space-aggregate]). Production apply and verify read the local +mirror, so a deployment never needs the plugin package graph resolvable, and an aggregate that +disagrees with the installed package is `db.space.skew`. Typed queries against the space use the +consumer declaration emitted from that same aggregate — the `AuthContract` import in the binding +above — and the spaces are never merged. Ownership is checked over `(target, namespace, object kind, name)`, not over declaration text, so two spaces wanting a table named `user` are a conflict naming both. Because the first adapter @@ -602,38 +628,39 @@ Uninstalling is a planned operation, not a directory delete: **detach-and-retain runtime binding while data, provider marker, lineage, and ownership history stay behind a verify-only tombstone. -### Step 6 — one extension, registered once +### Step 6 — one extension value, registered once Upstream, one logical extension is several modules: `@prisma/orm-extension-pgvector/pack` for authoring and `@prisma/orm-extension-pgvector/runtime` for the runtime facet, plus control wiring. Registering some of them and forgetting the rest is silent until something fails. Those runtime and -control modules are exactly what an application must not import, so the **adapter or the extension's -publisher** assembles the bundle inside the provider boundary: +control modules are exactly what an application must not import, so the **adapter or a compatible +extension publisher** assembles one bundle for the provider boundary: ```ts // @netscript/database-prisma-postgres — assembled inside the provider boundary, not by the app -export declare function pgvector(options: PgVectorOptions): DatabaseExtension<'pgvector'>; +export declare function pgvector(options: PgVectorOptions): PostgresExtension<'pgvector'>; // → { id, version, requires: [CAP.pgvector], authoring, control, runtime, validation } -// `authoring` is the only facet an application can reach. ``` -The application creates that value **once, before the contract** (Step 1), and passes the same -object to the definition (Step 2). Composition then runs two phases. Phase 1 collects every declared -bundle, checks identity and version against what each space's contract was authored with, refuses a -duplicate identity or a facet mismatch with `db.compose.extension.facet-mismatch`, and orders -contributions. Phase 2 invokes the native model-first builder with `bundle.authoring`, -canonicalizes, publishes artifacts, and then fans the _same_ bundle into control, runtime, and -validation. A later value cannot supply the authoring facet retroactively, which is why the order is -fixed. - -The provider-neutral kernel sees only identity, version, provider and capability requirements, and -opaque facet handles. The L3 escape hatch stays open with one condition: an author may call -`defineContract` against Prisma's public `/pack` import directly, but if the space declares that -extension in its NetScript definition, the contract must be built from the registered bundle's -`.authoring` projection — composition compares the extension identity and version recorded in the -emitted contract against the registered bundle and refuses on mismatch. A raw pack import is -equivalent only when no bundle is registered for it, and then that extension has no control, -runtime, or validation facet at all. +The application creates the extension **once**, before the contract, and passes it once to +`prismaPostgres({ extensions: [...] })` (Step 1). That provider composes +`postgres.authoring.scaffold` for the app's one native `defineContract` call and retains the same +bundle's executable control, runtime, and validation facets. The completed contract records the +extension identity and version. Later, `compileDatabase` does **not** invoke the builder again: it +compares those recorded pins with the extensions registered on the target's provider, refuses a +duplicate, missing identity, version skew, or facet mismatch with +`db.compose.extension.facet-mismatch`, and writes only serializable pins and capabilities to the +manifest. At run time the application supplies the same configured `postgres` value; runtime and +control obtain executable facets from it, never from manifest data and never from a global registry. + +This is a two-stage flow, not retroactive authoring: **authoring** evaluates the app-owned native +builder with the already-composed scaffold; **offline compilation** verifies, canonicalizes, and +publishes. A third-party publisher participates by returning a compatible `PostgresExtension` value +to the application's explicit provider configuration. The L3 escape hatch remains native: an author +may assemble Prisma's public pack directly, but a NetScript target using that contract is accepted +only when its configured provider carries the same extension identity/version and all facets +required by the claimed capabilities. Otherwise native authoring still works outside the NetScript +seam, while NetScript runtime/control/validation correctly refuse it. ### Step 7 — the operational journey @@ -652,7 +679,6 @@ const policy = { destructive: 'allow-with-approval' } as const; // Pure control: artifacts and policy only. It has no connection resolver to reach. const control = createDatabaseControl({ manifest, providers: [postgres] }); -const emitted = await control.emit({ targets: ['primary'], runId }); const advisory = await control.preview({ targets: ['primary'], runId }); // Live control: constructed from the pure catalog by supplying explicit live dependencies. @@ -666,9 +692,12 @@ const applied = await live.apply({ plan: signed, runId }); const verified = await live.verify({ targets: ['primary'], runId }); ``` -`emit` is offline because there is no connection in scope, not because an injected resolver happens -to go unused. This is the structural closure of the `DB-GENERATE-ASPIRE-COUPLING` debt entry: Aspire -is a property of a target's connection source, and a pure operation never receives one. +There is deliberately no `control.emit`. `emit` is the operation-catalog/CLI projection of +`compileDatabase(definition, sourceAndPublisher)` from L3; the explicit `ArtifactPublisher` is its +effect port, and the control package never receives a definition. It is offline because there is no +connection in scope, not because an injected resolver happens to go unused. This is the structural +closure of the `DB-GENERATE-ASPIRE-COUPLING` debt entry: Aspire is a property of a target's +connection source, and a pure operation never receives one. ```console $ netscript db plan --target primary --json @@ -799,11 +828,16 @@ The dependency edges are exact, and each clause is mechanically checkable: - `@netscript/database-testkit` may depend on every public surface; nothing depends on it at runtime. -**No framework package depends on a provider** — providers are composition-root values, so there is -no global registry and no lookup by string — and **no framework package re-exports Prisma**: only -the adapter and extension publishers import Prisma runtime or control modules, while application and -plugin authoring modules import Prisma's public authoring builder during the controlled build phase. -The adapter owns exactly two public subpaths, its root and `/binding`. +**No provider-neutral framework package depends on a provider** — providers are composition-root +values, so there is no global registry and no lookup by string — and **no framework package +re-exports Prisma**: only the adapter and extension publishers import Prisma runtime or control +modules, while application and plugin authoring modules import Prisma's public authoring builder +during the controlled build phase. The adapter owns exactly two public subpaths, its root and +`/binding`; provider-specific `defineContractFragment` lives at the adapter root rather than leaking +a Prisma helper type into `@netscript/database`. W1/W3 cannot publish any of these surfaces until +documentation/type lint, `isolatedDeclarations`, JSR dry-run, packed and cold remote consumers, +explicit aggregate-module asset inclusion, network-disabled emit/verify after dependency +materialization, provenance, and release E2E all pass. Doctrine currently codifies the model this RFC removes — Archetype 5 makes plugin database contributions plain `*.prisma` files ([archetypes](../docs/architecture/doctrine/06-archetypes.md)) @@ -820,14 +854,25 @@ type `TContract`. The target key is checked one level up, where both halves are ```ts // @netscript/database -/** Composes targets and spaces into a frozen definition; the target keys are checked here. */ +/** Composes targets and canonically keyed spaces into a frozen definition. */ export declare function defineDatabase< const TTargets extends Readonly>>, const TSpaces extends Readonly< Record, unknown>> >, >( - input: { targets: TTargets; spaces: TSpaces; extensions?: readonly DatabaseExtension[] }, + input: { + targets: TTargets; + spaces: + & TSpaces + & { + readonly [K in keyof TSpaces]: DatabaseSpaceDefinition< + Extract, + Extract, + unknown + >; + }; + }, ): DatabaseDefinition; /** @@ -887,18 +932,21 @@ query surface can be typed from `typeof` while the runtime value comes from the And root `deno.json` enables `isolatedDeclarations`, under which an exported inferred `defineContract(...)` constant needs an explicit annotation; app-owned authoring modules are **build inputs, not JSR exports**, so that narrow app-local project sets `isolatedDeclarations: false` while -every published `@netscript/*` package keeps it `true`. For app-authored spaces nothing is emitted, -no neutral declaration names a Prisma type, and no slow-types waiver is requested: evidence flows -`typeof definition → ContractOf → adapter binding`. +every published `@netscript/*` package keeps it `true`. For app-authored spaces no contract +declaration or generated model/query type is emitted, no neutral declaration names a Prisma type, +and no slow-types waiver is requested: evidence flows +`typeof definition → ContractOf → emitted adapter binding descriptor`. A consumer cannot do that for a space it did not author. A pinned plugin space arrives as artifacts, and TypeScript cannot reconstruct an exact contract type from JSON. For those spaces — and for an application that deliberately exports an inferred definition from a publishable package — the provider **declaration** is generated **automatically and atomically in the same compile** that -publishes the artifacts, and imported as type-only evidence into the hand-written binding. It is -never hand-run, never a framework slow type, and never control authority: runtime and control still -consume the manifest and pinned artifact values, and a declaration only tells the type checker what -the artifact already says. +publishes the artifacts. The compiler also emits the target binding descriptor shown above: it +references app-authored spaces through `typeof definition`, artifact-only spaces through their +generated declarations, and couples both to value-level snapshot identities. This is generated +wiring, not generated app model types. It is never hand-run, never a framework slow type, and never +control authority: runtime and control still consume the manifest, descriptor, and pinned artifact +values, and a declaration only tells the type checker what the artifact already says. The fallback is bounded to exactly those two boundaries, both proved in W3. If direct app inference turns out to require a private import, a copied overload, a cast, a provider type in a neutral @@ -906,13 +954,12 @@ package, or runtime evaluation of authoring code, that is recorded as a **W3 kil criterion** — the layered surface is reconsidered rather than silently promoted to universal generation. -**The one deliberate soundness seam.** `runtime.bind` returns a session whose query types come from -app-local inference, and the kernel cannot prove that the runtime value the provider constructs -matches them, because those type parameters are erased. Three gates make the seam safe: the binding -is constructed by the adapter factory from the same manifest that produced the artifacts; it carries -the manifest digest, provider pin, and per-space snapshot ids that the provider verifies at bind -time; and a conformance case asserts that a mismatched binding fails at bind rather than at first -query. +**The one deliberate soundness seam.** `runtime.bind` returns a session whose source-authored query +types are erased at run time. Application code cannot supply an arbitrary type map: the compiler +emits the descriptor from the same resolution that emits the manifest, with canonical `SpaceId`s, +provider pin, manifest digest, and per-space snapshot ids. The adapter verifies those values before +constructing the binding, and conformance swaps every target, space, declaration, and snapshot in +turn to prove a mismatch fails at construction or bind rather than at first query. ### Contribution modes @@ -929,18 +976,19 @@ published declaration. Fragments are therefore application-local and a published failure — which is why persistent plugin tables default to full spaces published as plain data plus pinned artifacts. -Composition is two-phase because extension packs determine the composed helper object's shape -_before_ Prisma invokes the callback. Phase 1 collects contributions, bundles, dependency edges, and -capability requirements, resolving extension identity and version, detecting facet mismatch, -ordering fragments, and refusing cycles; phase 2 builds one scaffold into the exact composed helper -surface, invokes fragments in dependency order, canonicalizes, and atomically publishes the -artifacts. Both phases are pure, the root is explicit calls and spreads in deterministic order — -never a registry, never `Array.reduce`, never `Record` — and fragment order must -not change the canonical digest. Plugin spaces never appear in that root. +Extension composition and contract compilation are ordered but do not invoke the builder twice. The +app first configures the provider extensions, then its explicit contract root invokes Prisma's +native builder once and invokes app-local fragments in dependency order against that composed helper +surface. The later offline compiler verifies extension pins, dependency edges, capability +requirements, ownership, and cycles; canonicalizes the completed contract; and atomically publishes +artifacts. Only the in-memory resolution step is mathematically pure — publishing is an explicit +offline effect. The authoring root uses explicit calls and const-preserving spreads in deterministic +order, never a registry, `Array.reduce`, or `Record`, and fragment order must not +change the canonical digest. Plugin spaces never appear in that root. ```ts -// database/contract-root.ts — app-owned fragments composed in one explicit, const-preserving root -export const primaryContract = defineContract(scaffold, (h) => { +// database/contract-root.ts — excerpt; app-owned fragments in one const-preserving native root +export const primaryContract = defineContract(postgres.authoring.scaffold, (h) => { const billing = billingFragment.build(h, {}); const app = appFragment.build(h, { billing }); @@ -980,9 +1028,10 @@ and its pins. Operations are classified before they run, and the class determines what an operation may resolve. In this catalog `pure` means **no live database, network, connection, or orchestrator** — not -side-effect-free: `emit` reads authoring artifacts and publishes an artifact set atomically. -`compose` is the catalog's projection of the A4 compiler, and the control package does not own the -compiler; live control never receives a `DatabaseDefinition`. +side-effect-free: `emit` is the CLI/catalog projection of `compileDatabase`, reads authoring +artifacts, and publishes through its explicit atomic publisher. `compose` projects +`resolveDatabase`; neither operation is a method on `DatabaseControl`. The control package does not +own the compiler, and live control never receives a `DatabaseDefinition`. | Class | Examples | May resolve | Lock | | ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | @@ -1075,13 +1124,13 @@ diagnostics, receipts, or logs; and **bind refuses mismatch**. Ports stay at three or four cohesive methods, because AP-3 names "a port with every operation the backend can perform" as the integration-package failure mode and today's `DatabaseAdapter` is that anti-pattern in shipped code. The consumed set is `ContractArtifactSource`, -`ArtifactPublisher` (stage/commit/abort, never patch in place), `ProviderRuntimeFactory`, -`ProviderControl` (emit/inspect/plan/apply), `ConnectionSource` (the Aspire, environment, and -secret-reference adapters), `MigrationLock`, and the append-plus-lookup receipt store, plus `Clock`, -`IdSource`, and `SignaturePolicy` where deterministic testing or production approval requires them. -**Verify is not a provider method**: it is composed from `ProviderControl.inspect` plus a manifest -comparison plus ownership classification, which is what keeps drift semantics identical across -providers. +`ArtifactPublisher` (stage/commit/abort, never patch in place), `ProviderContractCompiler` +(validate/canonicalize), `ProviderRuntimeFactory`, `ProviderControl` (inspect/plan/apply), +`ConnectionSource` (the Aspire, environment, and secret-reference adapters), `MigrationLock`, and +the append-plus-lookup receipt store, plus `Clock`, `IdSource`, and `SignaturePolicy` where +deterministic testing or production approval requires them. **Verify is not a provider method**: it +is composed from `ProviderControl.inspect` plus a manifest comparison plus ownership classification, +which is what keeps drift semantics identical across providers. ### The runtime validation subsystem @@ -1188,9 +1237,12 @@ The space lifecycle is `declared → installed → upgraded`, with refusals for cyclic dependencies, contract-format skew, capability regression, ownership widening, and mirror skew; then `detached → retained`, with `archived` and `dropped` specified but unclaimed. Detach-and-retain is the **only guaranteed removal**, and retained is a lifecycle state rather than -an ownership policy: the space keeps its data, marker, lineage, and ownership history as a -**verify-only tombstone** that drift reporting still sees but no plan or apply may touch until a new -explicit space re-adopts it. Detaching a space a still-installed space depends on is refused. +an ownership policy. Under the provider lock/fence, one receipt-backed ledger transition records the +previous head/snapshot, reason, `retained` state, and transition `ReceiptId`; the runtime binding is +removed and the provider marker is preserved. The space keeps its data, lineage, and ownership +history as a **verify-only tombstone** that inventory and drift reporting still see but no plan or +apply may touch until a new explicit space re-adopts it. Detaching a space a still-installed space +depends on is refused. Prisma's runtime lowering honours per-model namespaces, but its authoring type maps do not: the authoring path lumps every model under the default storage namespace and leaves additional namespace @@ -1262,19 +1314,19 @@ instance of it rather than a new idiom. ### Alternatives considered and rejected -| Alternative | Why rejected | -| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Keep Prisma 7 and add Prisma 8 as an opt-in pilot (issue #313) | It preserves every seam in Motivation; the current architecture is what a compatibility-first constraint produced. | -| A one-to-one migration of the current design onto Prisma 8 | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are version-independent. | -| A proprietary NetScript schema DSL lowering to the contract | A third schema language tracking every native type, index kind, constraint, and default; permanently lagging. | -| A live `DatabaseGraph` as the public artifact | A runtime graph accretes traversal APIs and becomes a lookup surface; the manifest gives every property it was wanted for. | -| Re-export Prisma from a NetScript package | AP-14, the publish constraint, and 138 upstream export keys — it converts Early-Access internals into NetScript public API. | -| A generated app-local binding as the universal default | Prisma's phantom contract type parameter and an app-local `isolatedDeclarations` scope make direct inference sound for app-authored spaces, so universal generation would add a ritual with no type benefit. Generation is kept exactly where evidence is missing: pinned spaces the consumer did not author, and publishable exports. | -| Generated mirror validators (one schema file per model/input/output) | Combinatorially wrong for selection-aware output, and it recreates the repair pipeline that already failed here. | -| Claim full operation/result validation from contract data | The operation and result type maps are phantom and erased at runtime; the claim would be false. | -| Copy plugin schema fragments (status quo) | No version, ownership, capability guard, dependency order, provenance, or safe removal — two recorded production failures. | -| Build a hosted control plane (registry, RBAC, approvals, drift) | Persistent products with operators, not local primitives; a local kernel exposes stable artifacts and integration events instead. | -| Extend the `--allow-slow-types` carve-out to database packages | It converts an application-local inference problem into permanent framework-wide publish debt. | +| Alternative | Why rejected | +| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Keep Prisma 7 and add Prisma 8 as an opt-in pilot (issue #313) | It preserves every seam in Motivation; the current architecture is what a compatibility-first constraint produced. | +| A one-to-one migration of the current design onto Prisma 8 | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are version-independent. | +| A proprietary NetScript schema DSL lowering to the contract | A third schema language tracking every native type, index kind, constraint, and default; permanently lagging. | +| A live `DatabaseGraph` as the public artifact | A runtime graph accretes traversal APIs and becomes a lookup surface; the manifest gives every property it was wanted for. | +| Re-export Prisma from a NetScript package | AP-14, the publish constraint, and 138 upstream export keys — it converts Early-Access internals into NetScript public API. | +| Generated model/query declarations as the universal type source | Prisma's phantom contract type parameter and an app-local `isolatedDeclarations` scope preserve direct inference for app-authored spaces. The target descriptor is emitted wiring, but generated contract declarations remain bounded to pinned spaces the consumer did not author and publishable exports. | +| Generated mirror validators (one schema file per model/input/output) | Combinatorially wrong for selection-aware output, and it recreates the repair pipeline that already failed here. | +| Claim full operation/result validation from contract data | The operation and result type maps are phantom and erased at runtime; the claim would be false. | +| Copy plugin schema fragments (status quo) | No version, ownership, capability guard, dependency order, provenance, or safe removal — two recorded production failures. | +| Build a hosted control plane (registry, RBAC, approvals, drift) | Persistent products with operators, not local primitives; a local kernel exposes stable artifacts and integration events instead. | +| Extend the `--allow-slow-types` carve-out to database packages | It converts an application-local inference problem into permanent framework-wide publish debt. | ### Market lessons @@ -1358,12 +1410,12 @@ preconditions; and an agreed migration window, legacy release-line end date, and ### Rollback boundaries -| Point | Rollback | Cost | -| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -| Before the marker write | Delete generated artifacts | None; nothing was written to any database | -| After markers, before the cutover commit | Remove the adopted spaces' marker rows **where certified provider marker semantics prove removal is safe and idempotent**; otherwise preserve the marker and move the space to the retained verify-only tombstone state — no binding, plan, or apply until explicit re-adoption | Trivial; markers carry no user data | -| After the cutover commit, before the first new `apply` | Revert the commit | Repository-only; the database is untouched | -| After the first new `apply` | **Forward only** — lineage, provider ledger, receipts | Ordinary migration recovery; the receipt names which steps ran | +| Point | Rollback | Cost | +| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| Before the marker write | Delete generated artifacts | None; nothing was written to any database | +| After markers, before the cutover commit | Under the provider lock/fence, append a receipt-backed lifecycle transition carrying previous head/snapshot, reason, and `retained`; preserve the marker as a verify-only tombstone. Remove metadata only where certified provider semantics prove the inverse transition safe and idempotent | Application schema/data are untouched; provider metadata remains auditable | +| After the cutover commit, before the first new `apply` | Revert the repository commit; retain and verify any adoption metadata already written | Repository rollback only for application code/schema; provider metadata may remain retained | +| After the first new `apply` | **Forward only** — lineage, provider ledger, receipts | Ordinary migration recovery; the receipt names which steps ran | There is deliberately no "run both stacks" rollback: it would require the compatibility layer this design refuses and would double the failure surface exactly when the system is least understood. @@ -1461,6 +1513,7 @@ Natural extensions this architecture enables and this RFC deliberately excludes: [rc1-contract-example]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/prisma/contract.ts [rc1-postgres-runtime]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/runtime/postgres.ts#L96-L110 [rc1-no-emit]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/prisma-no-emit/context.ts#L11 +[rc1-orm-filter]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/get-posts-by-tag-filter.ts [rc1-orm-read]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/get-user-posts.ts [rc1-orm-write]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/create-user.ts [rc1-space-aggregate]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/1-framework/3-tooling/migration/src/aggregate/types.ts#L71-L124 From 2510ab7d55f7ab0c998093f15eb4cd5dfde2886d Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Thu, 13 Aug 2026 23:09:43 +0200 Subject: [PATCH 16/19] docs(rfc): record database RFC closure gate --- .../context-pack.md | 76 ++++++------ .../plan.md | 25 ++-- .../reviews/root-semantic-closure.md | 50 ++++++++ .../supervisor.md | 103 ++++++++--------- .../worklog.md | 109 +++++++++--------- 5 files changed, 207 insertions(+), 156 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-semantic-closure.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index b741a1cbea..04a8618b60 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -6,33 +6,28 @@ | -------------- | ------------------------------------------------------- | | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | -| Current phase | `rfc-authoring` | +| Current phase | `final-verification` | | Archetype | Docs-only RFC describing future A1/A4/A3/A2/A2/A6 graph | | Scope overlays | `SCOPE-docs.md` | ## Current State -A clean-break database architecture RFC run is active. Issue #313 is historical evidence; its -compatibility-first solution is superseded. Native Fable 5 medium PLAN-EVAL cycle 2 session -`f3286656-7d0f-4da2-a22d-32897a5e6482` passed commit `383170bbc`. Native Claude Code Opus 5 high -authored an evidence-complete 28,194-word raw draft, pushed as `05e5fbac2`. Opus 5 high -consolidation session `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` resolved root findings R1–R10 and -reduced it to 11,205 words. Root read the entire compact RFC, added three narrow correctness fixes, -and pushed it as `5dfc4e8eb`. Qwen 3.8 Max reviewed that frozen commit without edits and returned -`PASS_WITH_CHANGES`. Grok 4.6 high then reviewed the same byte-identical RFC without edits and -returned `PASS_WITH_REFINEMENTS` with zero blockers. QF-01–QF-05 and GR-01–GR-08 remain open. It is -not finally accepted. After PLAN-EVAL and these reviews, the owner issued `OWNER-DX-01`: D-07/D-08/ -D-36 now require L1 preset/recipe → L2 public factories → L3 native Prisma plus NetScript -primitives, with source-native app inference preferred over generated type bindings. This is an -owner override, not a new PLAN-EVAL cycle. Current-main commit `01e096049` remains nonblocking -CI/gate-tooling drift. +A clean-break database architecture RFC is at final verification. Issue #313 remains historical +evidence; its compatibility-first solution is superseded. PLAN-EVAL cycle 2 passed, Opus authored +and consolidated the draft, Qwen and Grok reviewed it, and the author/editor disposition checkpoint +was pushed at `ad8effff9`. The owner then removed the length target and stopped every further +Claude/Fable route. Root resolved the remaining value-flow, binding-evidence, module-order, +operation-authority, JSR-asset, branded-type, validation, and rollback findings. Existing non-Claude +TypeScript/API, prospective JSR, and architecture lanes each returned `PASS`; the resulting RFC is +pushed at `d28d8e779`. Only mechanical verification, run-state bookkeeping, and PR handoff remain. ## Completed - Loaded current repository, RFC process, harness, PR, doctrine-navigation, and docs-profile rules. - Created an isolated worktree/branch from `origin/main` @ `cd7205293`. - Read GitHub issue #313 and its comments through the connected GitHub surface. -- Selected mandatory PLAN-EVAL and the owner-directed Fable 5 high final refinement override. +- Selected and completed mandatory PLAN-EVAL; the later planned Fable refinement was superseded by + the owner's Claude freeze before it ran. - Completed the research corpus, D-01–D-47 lock, prospective JSR audit, and architecture synthesis. - Preserved cycle 1 `FAIL_PLAN`, corrected the task finding to 42 keys per generated engine workspace, and obtained cycle 2 `PASS`. @@ -60,22 +55,25 @@ CI/gate-tooling drift. `contractJson` from its phantom compile-time contract generic. The audit recommends erased `typeof definition` for app-owned contracts and automatic atomic launcher-integrated declarations only for W3-proven publish/artifact-only boundaries. +- Completed author/editor dispositions and pushed `ad8effff9`. +- Root replaced the impossible extension and binding flows with one configured provider value and a + compiler-emitted, canonical-space/snapshot-bound target descriptor; split emission from runtime + module loading; unified `emit` authority; corrected branded IDs, examples, validation selection, + plugin aggregate transport, and durable retained rollback semantics. +- TypeScript/API, prospective JSR, and architecture closure lanes all returned `PASS`; root ran + targeted formatting, internal-link, whitespace, and fence checks and pushed `d28d8e779`. The + consolidated receipt is `reviews/root-semantic-closure.md`. ## In Progress -- Opus 5 high author/editor dispositions and consolidation, including `OWNER-DX-01` exact API - selection and type-boundary proof. The RFC remains frozen at 11,205 words and the run remains in - `rfc-authoring`; no QF/GR finding has been dispositioned yet. +- Final mechanical verification, authoritative run-state update, and PR handoff. No substantive + model route remains active. ## Next Steps -1. Use Opus 5 high for author/editor disposition of every QF/GR finding, integrate `OWNER-DX-01`, - choose the exact layered API, and state how W3 proves direct inference versus fallback while - consolidating to at most 10,000 words. Preserve Qwen's must-not-cut contracts; Grok projects a - net approximately 1,040–1,200-word cut plus another safe approximately 80 words if needed. -2. Root checks the consolidated result. -3. Run one final Fable 5 high substantive refinement. -4. Run mechanical checks only, then commit/push and update the PR trail. +1. Run the final mechanical format/link/diff and repository-status checks. +2. Commit and push the run-state/handoff gate. +3. Update draft PR #1640 with the semantic and verification checkpoints; request owner review. ## Key Decisions @@ -86,37 +84,39 @@ CI/gate-tooling drift. | Exact future package graph | Plan lock | A1 contract → A4 definition → A3 runtime → A2 control → A2 Prisma PostgreSQL adapter → A6 testkit. | | Layered database adoption | Owner override | L1 preset/recipe uses L2 factories; L3 is native Prisma plus NetScript primitives/ports. | | App type flow | Owner override | Erased `typeof definition` first; automatic atomic declaration only at a W3-proven boundary. | -| Fable 5 high is last | Owner directive | Final gate includes refinement, not only critique. | +| No further Claude/Fable usage | Owner directive | Supersedes the planned final Fable gate; existing evidence remains historical. | +| Content, not a word target | Owner directive | Consolidation serves clarity; length is not an acceptance metric. | ## Files Changed | Path | Status | Notes | | --------------------------------------------------------- | ------ | --------------------------------------- | | `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` | new | Harness provenance and resumable state. | +| `rfcs/0000-database-architecture.md` | new | Canonical RFC; semantic closure pushed. | ## Gates -| Gate family | Current status | Evidence | -| ----------- | -------------- | ----------------------------------------------------- | -| Static | PASS | Compact RFC fmt, `docs:links`, diff. | -| Fitness | owner override | Cycle 2 PASS; D-01–D-47 plus post-eval `OWNER-DX-01`. | -| Runtime | N/A | Docs-only RFC run. | -| Consumer | changes open | Qwen/Grok reviews complete; Opus dispositions next. | +| Gate family | Current status | Evidence | +| ----------- | -------------- | ----------------------------------------------------------------------- | +| Static | PASS | RFC format, `docs:links`, diff, balanced fences at semantic checkpoint. | +| Fitness | PASS | D-01–D-47, OWNER-DX-01, and three final closure audits. | +| Runtime | N/A | Docs-only RFC; future matrices are explicit implementation gates. | +| Consumer | PASS | TypeScript/API, JSR, and architecture closure all passed `d28d8e779`. | ## Open Questions - No must-resolve-now architecture decision remains; pre-implementation decisions stay assigned to their W1/W3/W4/W5/W7/W10 gates. W3 now includes direct-erasure and automatic-fallback proof. -- QF-01–QF-05 are review findings, not reopened architecture decisions; they await author/editor - disposition together with GR-01–GR-08. -- Exact L1/L2 API spelling is an Opus author/editor task under the owner override; it may not add a - mirrored Prisma schema/query DSL or change the six-package graph. +- No review blocker/high remains. RFC implementation-time questions stay assigned to their + W1/W3/W4/W5/W7/W10 gates and do not reopen the architecture. ## Drift and Debt -- Drift: #313 compatibility-first architecture is superseded; final-gate effort is owner-overridden. +- Drift: #313 compatibility-first architecture is superseded; the planned final Fable gate and + length target are superseded by the latest owner directives. - Debt: pending targeted ledger scan. ## Commits +- Semantic review closure: `d28d8e779` (pushed). - See the draft PR's commit list + per-slice PR comments (V3 retired `commits.md`). diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md index 9a221707cc..e9d40d98b3 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -7,8 +7,8 @@ | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | | Baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | -| Phase | `rfc-authoring` | -| Target | `rfcs/0000-database-architecture.md` plus harness provenance; authorship is unblocked but not yet complete | +| Phase | `final-verification` | +| Target | `rfcs/0000-database-architecture.md` plus harness provenance; semantic closure is pushed at `d28d8e779` | | Current changeset | Documentation/RFC under `SCOPE-docs.md` | | Future architecture | A1 contract, A2 control/provider integrations, A3 runtime, A4 definition/plugin DSL, A5 thin plugins, A6 testkit/CLI | @@ -39,8 +39,10 @@ RFC premise invalidated, and the existing fresh-pin drift watch remains sufficie After that pass, the owner issued `OWNER-DX-01`: the accepted architecture must expose NetScript's existing layered adoption pattern and must not assume generated app type bindings are inevitable. This is an explicit owner override to D-07/D-08/D-36, not a new PLAN-EVAL cycle; no further -PLAN-EVAL will run. The Opus author/editor pass owns exact API selection and the source-native -versus fallback type-boundary proof while keeping the RFC at or below 10,000 words. +PLAN-EVAL will run. The completed author/editor pass selected the layered API and source-native +versus fallback type boundary. The owner subsequently removed every word-count acceptance target and +stopped all further Claude/Fable usage. Root applied the remaining semantic corrections, and three +non-Claude closure lanes passed the resulting RFC at `d28d8e779`. ## Scope @@ -370,11 +372,12 @@ marker cleanup where supported. After apply, recovery is forward via lineage and | 4 | RFC completes adoption/cutover, implementation waves, exhaustive conformance/release matrix, market implications, risks, and kill/switch criteria. | Requirement/decision trace, migration safety, claim/source audit, docs gates. | Same RFC plus run context/worklog. | | 5 | Root personal review, Qwen 3.8 Max focused review, and Grok 4.6 high whole-RFC adversarial review complete. | Review receipts, source audit, and no undispositioned critical/high finding. | RFC plus review/run artifacts. | | 6 | Author/editor dispositions resolve every actionable post-draft finding and preserve D-01–D-47. | Finding ledger closed or reasoned decline; contradiction and decision trace rerun. | RFC plus review/run artifacts. | -| 7 | Owner-directed Fable 5 high performs the absolute final substantive refinement; publish the final review state. | Fable refinement, docs static checks only afterward, commit/push/PR trail. | RFC and final run/handoff artifacts. | +| 7 | Root closes the final semantic findings, obtains non-Claude TypeScript/JSR/architecture closure, and publishes the final review state. | Three closure verdicts `PASS`; docs static checks, commit/push/PR trail. | RFC and final run/handoff artifacts. | -There are eight ordered slices, below the Plan-Gate limit. The canonical RFC does not exist before -Slice 2 passes. Fable 5 high is the last substantive model gate; only mechanical static verification -may follow. +There are eight ordered slices, below the Plan-Gate limit. The canonical RFC did not exist before +Slice 2 passed. The owner superseded the planned Fable gate after Slice 6 and froze every Claude +route; Slice 7 therefore ends with root-authored corrections and independent non-Claude closure. +Only mechanical static verification and run-state bookkeeping follow. ## Gate Set @@ -443,8 +446,10 @@ packed install cannot substitute for the remote-graph verdict. 3. Qwen 3.8 Max focused post-draft review. 4. Grok 4.6 high whole-RFC adversarial review. 5. Author/editor dispositions for every actionable finding. -6. One Fable 5 high final in-place refinement as the absolute last substantive gate. -7. Mechanical format/link/diff checks, commit/push, and PR handoff only. +6. Owner supersession: remove the length target and stop every further Claude/Fable route. +7. Root semantic closure, then independent TypeScript/API, prospective JSR, and architecture passes + through the existing non-Claude lanes. +8. Mechanical format/link/diff checks, commit/push, and PR handoff only. ## Risk Register diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-semantic-closure.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-semantic-closure.md new file mode 100644 index 0000000000..41e3ec38e2 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-semantic-closure.md @@ -0,0 +1,50 @@ +# Root Semantic Closure — Database Architecture RFC + +## Checkpoint + +- RFC: `rfcs/0000-database-architecture.md` +- Reviewed and pushed commit: `d28d8e779` +- Branch: `docs/database-architecture-rfc` +- Owner supersessions in force: RFC length is not an acceptance gate; no Claude/Fable route may be + launched or resumed. +- Result: **PASS_TO_FINAL_MECHANICAL** + +## Closed findings + +| Finding | Final disposition | +| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Executable extension facets had no live downstream path | One extension value is registered once on the configured provider. Native authoring consumes `postgres.authoring.scaffold`; compile verifies serializable pins; runtime/control receive the same provider value carrying live facets. | +| Native builder was described as running again during compile | Authoring invokes Prisma's native builder once. Offline compile verifies, canonicalizes, and publishes the completed contract; it never retroactively invokes authoring. | +| Hand-written generic binding could lie about space types/snapshots | The compiler emits a target descriptor with canonical `SpaceId` keys, `ManifestDigest`, per-space `ContractSnapshotId`, source-native evidence for app spaces, and declaration evidence only for artifact-owned spaces. | +| L3 imported generated binding before it emitted artifacts | L3 is split into a prior build/emission module graph and a later application/runtime graph. First boot and stale static-import ordering are explicit refusals. | +| `emit` had two owners and hidden IO | Catalog/CLI `emit` is the sole projection of `compileDatabase` with an explicit atomic publisher. `DatabaseControl` has no `emit` method. | +| Query examples passed ordinary strings to branded UUID fields | Application ports derive field values through provider-specific `FieldValueOf`; external strings cross only after validation/decoding. | +| Validation projection implied automatic query coupling | The RFC calls the literal selection a validation projection, requires handler output-type alignment, and gates provider plan/selection coupling on W3 proof. | +| Plugin `SpaceId` used an erased local alias | Definition maps, emitted descriptors, manifests, receipts, diagnostics, and `.space(...)` all use the same canonical plugin ID; map key and contribution ID are constrained to match. | +| Remote plugin aggregate could require network during offline compile | The plugin statically imports a generated aggregate module containing/importing the complete artifact graph. Release gates require cold remote materialization followed by network-disabled emit/verify. | +| Retained rollback was not a durable transition | Provider lock/fence plus a receipt-backed ledger transition preserves marker, previous head/snapshot, reason, and retained verify-only state; repository rollback does not claim provider metadata vanished. | + +## Independent closure + +The existing non-Claude lanes performed read-only checks of the corrected RFC. They made no edits, +commits, pushes, model launches, or word-count checks. + +| Lane | Scope | Verdict | +| ----------------------------------- | --------------------------------------------------------------------------------------------- | -------- | +| `/root/typescript_schema_audit` | TypeScript/API, native RC1 shapes, binding evidence, examples, validation | **PASS** | +| `/root/planned_jsr_audit` | Package graph, static aggregate transport, offline emit, JSR/release gates, retained rollback | **PASS** | +| `/root/architecture_plan_synthesis` | D-01–D-47, OWNER-DX-01, canonical identities, extension ordering, L3 loading, emit authority | **PASS** | + +## Mechanical evidence at semantic gate + +- `deno fmt --check rfcs/0000-database-architecture.md`: PASS +- `deno task docs:links`: PASS (`103` documents; no broken links, anchors, or enforced orphans) +- `git diff --check`: PASS +- Markdown fences: `40`, balanced +- Semantic residue scan: no obsolete hand-written binding, duplicate `control.emit`, + definition-level extension registration, stale binding path, second builder invocation, or numeric + length gate in the RFC + +No blocker or high-severity finding remains. Implementation claims remain conditional on the W1–W10 +conformance and release gates named in the RFC; this is an RFC acceptance verdict, not a claim that +the future packages already pass those gates. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index 31a99d50c6..ae30662baa 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -13,17 +13,17 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | Baseline | `origin/main` @ `cd720529333328bcba5e1a308ce7632f4350efdf` (2026-08-13) | | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | -## Routes in force - -| Task lane | Provider / model / effort | Role in this run | -| ------------------------------------- | --------------------------------------- | ---------------------------------------------------------------------------- | -| `planning_decisions` | OpenAI · Codex · GPT-5 family · high | Root research coordinator and RFC generator in the active user session | -| owner-directed architecture deep dive | Anthropic · Claude Code · Opus 5 · high | Fresh independent architecture/API review with optional native workflows | -| `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | -| `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | -| focused post-draft RFC review | OpenRouter · Qwen 3.8 Max · max | Focused review after the root's complete-draft personal review | -| owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | -| owner-directed final refinement | Anthropic · Fable 5 · high | Absolute final review-and-refinement gate after every other substantive gate | +## Routes used and final disposition + +| Task lane | Provider / model / effort | Role in this run | +| ------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------- | +| `planning_decisions` | OpenAI · Codex · GPT-5 family · high | Root research coordinator and RFC generator in the active user session | +| owner-directed architecture deep dive | Anthropic · Claude Code · Opus 5 · high | Fresh independent architecture/API review with optional native workflows | +| `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | +| `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | +| focused post-draft RFC review | OpenRouter · Qwen 3.8 Max · max | Focused review after the root's complete-draft personal review | +| owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | +| owner-directed final refinement | Anthropic · Fable 5 · high | **Cancelled before launch** by the latest owner Claude freeze | ## Delegated research and synthesis lanes @@ -35,8 +35,8 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Plan-Gate synthesis plus repository-grounded `OWNER-DX-01` audit | Complete | | `/root/planned_jsr_audit` | OpenAI · GPT-5.6 Sol · high | Prospective publishability/slow-type review of the planned graph | Complete | -These lanes are independent research/synthesis inputs. None is the formal PLAN-EVAL or the -owner-directed final Fable refinement. +These lanes are independent research/synthesis inputs. The three existing non-Claude lanes also +performed the final read-only closure checks; no new lane and no Claude/Fable route was launched. ## Formal plan evaluation @@ -50,10 +50,10 @@ research/synthesis lanes. Its only required fix was the copied claim of 30 gener evaluator execution of `generateDatabaseDenoJson` established 42 keys per generated engine workspace for PostgreSQL, SQLite, MySQL, and MSSQL. `research.md`, the architecture synthesis, and `plan.md` now carry the executed result and disposition Qwen F3 as an incorrect correction; independent model -reports and briefs remain immutable evidence. Cycle 2 passed at `383170bbc`; the phase is now -`rfc-authoring`, canonical RFC authorship is unblocked but incomplete, and no further PLAN-EVAL -cycle is requested. Cycle 2 also classified current-main `01e096049` as nonblocking CI/gate-tooling -drift and independently confirmed 42 generated `db:*` keys per engine workspace. +reports and briefs remain immutable evidence. Cycle 2 passed at `383170bbc` and unblocked RFC +authorship; no further PLAN-EVAL cycle is requested. The current phase is `final-verification` after +semantic closure at `d28d8e779`. Cycle 2 also classified current-main `01e096049` as nonblocking +CI/gate-tooling drift and independently confirmed 42 generated `db:*` keys per engine workspace. After cycle 2, `OWNER-DX-01` explicitly overrode D-07/D-08/D-36. It requires the shipped NetScript L1 preset/recipe → L2 public factories → L3 native-framework/primitives progression and prefers an @@ -63,42 +63,35 @@ decisions remain locked, and no further PLAN-EVAL will run. ## RFC authoring and consolidation -| Stage | Route / model / effort | Session | Result | -| --------------------- | -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------ | -| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | -| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | -| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | -| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | -| Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | +| Stage | Route / model / effort | Session | Result | +| ------------------------ | -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------ | +| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | +| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | +| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | +| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | +| Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | +| Author/editor checkpoint | Native Claude Code · Opus 5 · high | completed session recorded in worklog | Root corrections applied and pushed as `ad8effff9`; no later Claude use. | +| Root semantic closure | Codex supervisor + existing non-Claude lanes | current root session | TypeScript/API, JSR, and architecture verdicts `PASS`; pushed as `d28d8e779`. | Before commit `5dfc4e8eb`, root added three narrow corrections: runtime consumes the compiled `DatabaseManifest`, not `DatabaseDefinition`; the authority table distinguishes each artifact and -value's role; and `partial-success` requires mixed successful and unsuccessful target outcomes. -Targeted formatting, `docs:links`, and diff checks passed. The phase remains `rfc-authoring`. The -preferred final target remains at most 10,000 words where further cuts preserve decision and API -clarity. +value's role; and `partial-success` requires mixed successful and unsuccessful target outcomes. The +later author/editor and root closure passes resolved all blocker/high findings without changing the +package graph. The phase is `final-verification`; length is not an acceptance gate. The Qwen focused review passed architecture/type model, Standard Schema boundary, control/recovery, -migration/plugin safety, and market/upstream claims. Its narrow failures affect TypeScript/API -examples and one package/dependency example. QF-01 is high, QF-02 medium, and QF-03–QF-05 low. Its -approximately 1,240-word deletion ledger projects approximately 9,965 words while naming -must-not-cut contracts. The RFC remains frozen at 11,205 words until Grok review and Opus -author/editor disposition; this is not final acceptance. +migration/plugin safety, and market/upstream claims. Its QF-01–QF-05 findings are dispositioned in +the author/editor/root passes; its deletion ledger remains historical editorial input. The Grok review ran against current HEAD `be83301c6` while proving the RFC blob byte-identical to -commit `5dfc4e8eb`. Axes 2, 3, 4, and 6 passed. Abstraction, public API/DX/types, and economy failed -narrowly through GR-01–GR-08; the architecture stands. The deletion ledger estimates approximately -1,180 words deleted and 140 added, net approximately 1,040–1,200 removed, landing around -10,000–10,160 with another safe approximately 80-word cut. The RFC remains frozen at 11,205 words -pending Opus dispositions; this is not final acceptance. +commit `5dfc4e8eb`. Axes 2, 3, 4, and 6 passed. GR-01–GR-08 are dispositioned; its deletion ledger +is historical editorial input, not a gate. The subsequent `OWNER-DX-01` audit is recorded in `research/layered-dx-api-audit.md`. It inspected the defining service/Hono preset, builder, and native primitives; SDK/Fresh analogues; and pinned -Prisma's runtime `contractJson` plus phantom compile-time contract split. Opus remains the -author/editor responsible for selecting the exact layered API and expressing the W3 proof/fallback -boundary while reducing the RFC to at most 10,000 words. The default is source-native app inference -with runtime manifest/artifact consumption; automatic atomic launcher-integrated declarations are -reserved for proved publish/artifact-only boundaries. +Prisma's runtime `contractJson` plus phantom compile-time contract split. The final RFC selects that +layered API, source-native app inference, and bounded artifact-only declarations; its emitted target +descriptor couples both evidence tracks to canonical runtime snapshot identities. ## Recorded lane/eval overrides @@ -113,9 +106,9 @@ reserved for proved publish/artifact-only boundaries. `3f8a9a69-5589-4b91-9a32-91f7770fe7c2`, PID `1944525`, worktree matched, native UI reported “Opus 5 with high effort · Claude Max.” The session immediately exposed four internal agents; their roles/identities must be recorded in its report. -- The owner explicitly requires Fable 5 **high**, not merely an adversarial review, as the final - refinement gate. That owner directive overrides the ordinary `docs_polish` Fable-medium effort for - this run. No substantive model gate may follow it. +- Historical directive: the owner initially selected Fable 5 **high** as the final refinement gate. + The latest owner directive supersedes it and freezes all further Claude/Fable usage; the session + was not launched. - Qwen 3.8 Max is selected for the owner-clarified focused post-draft review, after the root's personal complete-draft review and before Grok's whole-RFC adversarial pass. The completed route requested and observed `qwen/qwen3.8-max` at `max`, session @@ -125,8 +118,8 @@ reserved for proved publish/artifact-only boundaries. still names Grok 4.5, so this is an explicit owner-directed route override rather than a claim that the catalog is current. Use the existing bounded OpenCode/OpenRouter runner with model `openrouter/x-ai/grok-4.6` and variant `high`, record requested/observed identity and raw receipt, - and run it after the focused Qwen review. No substantive gate may follow the final Fable 5 high - refinement. + and run it after the focused Qwen review. That Grok route completed; the later planned Fable route + was cancelled by owner supersession. - The completed Grok route requested and observed `x-ai/grok-4.6`, variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, with no subagents and no edits. It evaluated RFC commit `5dfc4e8eb` / blob `f46040d8...` at HEAD `be83301c6` and returned `PASS_WITH_REFINEMENTS` with @@ -146,12 +139,14 @@ reserved for proved publish/artifact-only boundaries. architecture axis beside contract-derived validation. A separate read-only source audit must establish the exact upstream state and derive candidate end-to-end NetScript type flows before plan lock; the Opus synthesis brief now requires this subsystem explicitly. -- The owner locked the post-draft sequence: root personal review → Qwen 3.8 Max focused review → - Grok 4.6 high whole-RFC adversarial review → Opus author/editor dispositions and consolidation → - one final Fable 5 high substantive refinement → mechanical checks only. +- Historical sequence: root personal review → Qwen 3.8 Max focused review → Grok 4.6 high whole-RFC + adversarial review → Opus author/editor dispositions. The owner then superseded the planned Fable + step; root plus the three existing non-Claude lanes closed semantics before mechanical checks. - After PLAN-EVAL cycle 2 and the frozen Qwen/Grok review inputs, the owner issued `OWNER-DX-01`. The override changes D-07/D-08/D-36 only: progressive NetScript adoption layers are required, only a mirrored Prisma model/field/relation/query DSL is forbidden, and erased source-native app - inference replaces universal generated bindings. It triggers no further PLAN-EVAL. Opus decides - exact API spelling and proves the fallback boundary during the already-planned ≤10k disposition - pass. + inference replaces universal generated declarations. It triggered no further PLAN-EVAL. The + completed author/editor/root passes selected the API and proved the fallback boundary. +- Latest owner supersession: RFC length is not an acceptance gate, and all further Claude usage is + stopped. Completed Claude outputs remain provenance only. No Claude or Fable session may be + launched or resumed; final closure uses root judgment and the already-running non-Claude lanes. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 4c5771f9d9..a6b38d6b4a 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -6,7 +6,7 @@ | -------------- | ------------------------------------------------------------- | | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | -| Phase | `rfc-authoring` | +| Phase | `final-verification` | | Archetype | Docs-only RFC describing future A1/A2/A3/A4/A5/A6 surfaces | | Scope overlays | `SCOPE-docs.md`; future packages use their archetype matrices | @@ -16,10 +16,12 @@ The Design checkpoint is **locked and evaluator-approved**. Cycle 1 returned `FA because the copied generated-workspace task count was factually wrong; evaluator execution found 42 `db:*` keys per workspace for all four providers. After correction, native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. -Canonical RFC authorship is unblocked. The consolidated draft is accepted for focused review but is -not finally accepted; no further PLAN-EVAL cycle is planned. After cycle 2, the owner issued -`OWNER-DX-01`, overriding D-07/D-08/D-36 to require layered adoption and source-native app inference -by default. This is not a new PLAN-EVAL cycle and leaves the exact six-package graph intact. +Canonical RFC authorship is complete and no further PLAN-EVAL cycle is planned. After cycle 2, the +owner issued `OWNER-DX-01`, overriding D-07/D-08/D-36 to require layered adoption and source-native +app inference by default. The author/editor checkpoint landed at `ad8effff9`; root then closed the +remaining semantic findings, and three non-Claude lanes passed the result at `d28d8e779`. The owner +removed the length target and stopped all further Claude/Fable usage. Only mechanical verification +and handoff remain; the exact six-package graph is unchanged. ### Public Surface and Package Graph @@ -27,11 +29,11 @@ by default. This is not a new PLAN-EVAL cycle and leaves the exact six-package g - `@netscript/database-contract` (A1): plain identities, manifest/plan/receipt/diagnostic schemas, capabilities, ownership, and shared small SPIs; zero provider dependencies. - `@netscript/database` (A4): L1 preset/recipe, the L2 `defineDatabase`/target/space/policy - factories it uses, and the pure deterministic manifest compiler. + factories it uses, deterministic resolution, and compile/emit through an explicit publisher. - `@netscript/database-runtime` (A3): process/request lifecycle, connection ownership, health/readiness, cancellation, and validation coordination. -- `@netscript/database-control` (A2): programmatic operation catalog, emit/preview/plan/apply/ - verify/inspect, provider ports, locks, receipts, recovery, and cross-target saga. +- `@netscript/database-control` (A2): preview/inspect/plan/apply/verify, policy, provider ports, + locks, receipts, recovery, and cross-target saga; it does not own compile/emit. - `@netscript/database-prisma-postgres` (A2): experimental/certified provider and sole framework Prisma runtime/control boundary; no Prisma re-export. - `@netscript/database-testkit` (A6): runnable provider/space conformance only if a binary is @@ -106,7 +108,7 @@ outcome is inspected before resume; cross-target atomicity is never claimed. | 4 | Cutover/waves/conformance/risks/market completion. | Migration safety, claim trace, docs gates. | RFC plus run context/worklog. | | 5 | Root, Qwen focused, and Grok whole-RFC reviews complete. | Review receipts; no undispositioned critical/high. | RFC plus review/run artifacts. | | 6 | Author/editor dispositions complete. | Finding ledger closed; decision/contradiction trace. | RFC plus review/run artifacts. | -| 7 | Absolute final Fable 5 high refinement and publish handoff. | Fable substantive gate, then mechanical checks only. | RFC/final run/handoff artifacts. | +| 7 | Root semantic closure, three non-Claude passes, and publish handoff. | Closure verdicts, then mechanical checks only. | RFC/final run/handoff artifacts. | ### Prospective JSR Verdict @@ -166,6 +168,9 @@ and release exits recorded in `plan.md`. | 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | | 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | | 2026-08-13 | 6 | owner-dx | `OWNER-DX-01` audited shipped service/Hono preset→factory→native primitives, SDK/Fresh analogues, and Prisma's runtime `contractJson` plus phantom compile-time contract split. Owner overrode D-07/D-08/D-36 after PLAN-EVAL: source-native app inference is default; automatic declarations are a bounded W3 fallback. No new PLAN-EVAL. | +| 2026-08-13 | 6 | disposition | The author/editor pass resolved QF/GR and OWNER-DX-01 findings; root's correction pass was committed and pushed as `ad8effff9`. | +| 2026-08-13 | 7 | owner-gate | Owner removed word-count acceptance criteria and froze all further Claude/Fable usage. Existing completed sessions remain provenance only; no planned final Fable session ran. | +| 2026-08-13 | 7 | closure | Root corrected executable extension transport, canonical space/snapshot binding evidence, emit/load ordering, compile/emit authority, branded IDs, validation projection honesty, package aggregate transport, and retained rollback. TypeScript/API, prospective JSR, and architecture lanes all returned `PASS`; `d28d8e779` was pushed. | ### RFC Consolidation and Root Acceptance @@ -187,19 +192,16 @@ OpenRouter requested and observed `qwen/qwen3.8-max` at effort `max`, model sess Schema boundary, control/recovery, migration/plugin safety, and market/upstream claims passed. The narrow failures were TypeScript/API examples and one package/dependency example. -Open findings, pending author/editor disposition: +Dispositioned findings: -- **QF-01 high:** generated-binding example uses ambient declarations as runtime values. -- **QF-02 medium:** extension-bundle authoring can violate the adapter-only runtime/control import - law. -- **QF-03 low:** unbound values and elisions undermine the executable-as-written claim. -- **QF-04 low:** Prisma source-path attribution needs correction or qualification. -- **QF-05 low:** codec parameter validation is conflated with three conversion representations. +- **QF-01:** closed by the compiler-emitted target descriptor carrying real manifest/snapshot + values. +- **QF-02:** closed by registering one extension value on the configured provider before authoring. +- **QF-03:** closed by explicit complete-module/excerpt status and bound example imports. +- **QF-04/QF-05:** closed by pinned API attribution and the runtime/JSON validation boundary. -Qwen also supplied an approximately 1,240-word deletion ledger projecting an approximately -9,965-word RFC while naming must-not-cut contracts. It is editorial input, not authorization to -remove load-bearing semantics. The canonical RFC remains frozen at 11,205 words; no disposition, -edit, or final acceptance occurred. +Qwen also supplied a deletion ledger. It remains historical editorial input, not authorization to +remove load-bearing semantics; the owner later removed length as an acceptance criterion. ### Grok Whole-RFC Adversarial Review @@ -210,23 +212,18 @@ edits, and returned `PASS_WITH_REFINEMENTS` with zero blockers. Axes 2, 3, 4, an abstraction, axis 5 public API/DX/types, and axis 7 economy failed narrowly while the architecture stood. -Open refinements for Opus author/editor disposition: +Dispositioned refinements: -- **GR-01:** use real generated binding values, overlapping QF-01. -- **GR-02:** put opaque control/runtime extension facets under extension-pack/adapter ownership, - overlapping QF-02. -- **GR-03:** bind queries, validators, and hashes per target/per space; never merge a Prisma - `AppContract`. -- **GR-04:** make pure compose/compile authority consistent with control wording. -- **GR-05:** distinguish adopted manage-forward objects from detach-retained verify-only tombstones. -- **GR-06:** specify space → target → run outcome rollup explicitly. -- **GR-07:** show a configured provider factory and remove executable-example elisions. -- **GR-08:** perform net consolidation and resolve QF-04/QF-05. +- **GR-01–GR-03:** closed by the emitted canonical-space/snapshot descriptor and configured provider + value; Prisma contract spaces remain disjoint. +- **GR-04:** closed by making catalog/CLI `emit` the sole projection of `compileDatabase` with an + explicit publisher; `DatabaseControl` has no competing method. +- **GR-05–GR-06:** closed by durable receipt-backed retained transitions and total outcome rollup. +- **GR-07–GR-08:** closed by the provider module, honest excerpt markers, source corrections, and + consolidation that preserved content over a numeric length target. -Grok's deletion ledger estimates approximately 1,180 words removed and 140 added, net approximately -1,040–1,200 words removed, landing around 10,000–10,160 words; it identifies another safe -approximately 80-word cut to cross 10,000. The RFC remains frozen at 11,205 words until Opus applies -all QF/GR dispositions. This gate is not final acceptance. +Grok's deletion ledger remains historical editorial input. QF/GR dispositions are complete; the +owner's later direction makes content and clarity, not a numeric length, the acceptance criterion. ### PLAN-EVAL Cycle 1 @@ -261,24 +258,27 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | Provider-neutral kernel, PostgreSQL-only first adapter | Matches Prisma maturity without compatibility fallback or false portability. | Prisma scorecard/source + D-10/D-11/D-34 | | NetScript operational semantics, provider migration mechanics | NetScript owns policy/locks/recovery/receipts/saga while provider owns diff/lineage/marker. | Market/source reconciliation + D-27–D-30 | | PLAN-EVAL before RFC | Architecture has no open must-resolve item but still requires independent acceptance. | Harness Plan-Gate + D-01–D-47 | -| Fable 5 high remains last substantive gate | Explicit owner exception; no substantive model review follows it. | Owner directive | +| No further Claude/Fable route | Latest owner directive supersedes the planned final Fable gate; completed evidence remains historical. | Owner directive | +| No numeric RFC length gate | Content and clarity govern acceptance; consolidation is not a word-count exercise. | Owner directive | ## Drift | Drift | Severity | Logged in drift.md | | ------------------------------------------------------------ | ------------- | ------------------ | | #313 compatibility-first plan is no longer authoritative | architectural | yes | -| Fable 5 high is the owner-directed final refinement gate | significant | yes | +| Planned final Fable refinement was cancelled by owner | significant | run-state override | +| Word-count target was removed by owner | significant | run-state override | | `origin/main` advanced by CI/gate-tooling commit `01e096049` | nonblocking | plan-eval evidence | ## Gate Results ### Static Gates -| Gate | Command or check | Result | Notes | -| -------------- | ----------------------------------------------- | ------ | ----------------------------------------------------- | -| Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | -| Compact RFC | Targeted fmt; `docs:links`; `git diff --check` | PASS | Commit `5dfc4e8eb`; 11,205 words and R1–R10 resolved. | +| Gate | Command or check | Result | Notes | +| -------------- | ------------------------------------------------------ | ------ | ------------------------------------------------------- | +| Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | +| Compact RFC | Targeted fmt; `docs:links`; `git diff --check` | PASS | Commit `5dfc4e8eb`; 11,205 words and R1–R10 resolved. | +| Semantic RFC | Targeted fmt; `docs:links`; `git diff --check`; fences | PASS | Commit `d28d8e779`; final blocker/high findings closed. | ### Fitness Gates @@ -288,8 +288,11 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | Open-decision sweep | PASS_OWNER_OVERRIDE | D-01–D-47 plus `OWNER-DX-01` | No must-resolve-now item; D-07/D-08/D-36 updated without changing package boundaries. | | Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | | PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | -| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings remain open; review made no edits. | -| Grok whole-RFC review | PASS_WITH_REFINEMENTS | Session `ses_003644aeaffeSm3UCAW9xUqRIK`; blob `f46040d8...` | Zero blockers; GR-01–GR-08 await disposition. | +| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings were later dispositioned; review made no edits. | +| Grok whole-RFC review | PASS_WITH_REFINEMENTS | Session `ses_003644aeaffeSm3UCAW9xUqRIK`; blob `f46040d8...` | Zero blockers; GR-01–GR-08 were later dispositioned. | +| TypeScript/API closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Extension, binding, loading, branded ID, validation and examples closed. | +| Prospective JSR closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Static aggregate module plus cold-remote/network-disabled gate closed the last high. | +| Architecture closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | D-01–D-47, OWNER-DX-01, package graph and four prior findings closed. | ### Runtime Gates @@ -299,10 +302,10 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ### Consumer Gates -| Consumer | Result | Evidence | Notes | -| ---------------------- | ----------------------------- | ------------------------------------------------------------- | --------------------------------------------------- | -| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | -| RFC reader/implementer | REVIEWS_COMPLETE_CHANGES_OPEN | Frozen RFC `5dfc4e8eb`; Qwen/Grok receipts | QF-01–QF-05 and GR-01–GR-08 await Opus disposition. | +| Consumer | Result | Evidence | Notes | +| ---------------------- | ------ | ------------------------------------------------------------- | -------------------------------------------------------------------- | +| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | +| RFC reader/implementer | PASS | RFC `d28d8e779`; Qwen/Grok plus three closure verdicts | No blocker/high finding remains; implementation gates stay explicit. | ## Handoff Notes @@ -311,10 +314,8 @@ CI/gate-tooling drift that changes structured check invocation rather than datab explicit later owner override, not an evaluator rerun. - Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until packages exist and must produce implementation/release receipts later. -- The consolidated RFC remains frozen at `5dfc4e8eb` and 11,205 words. Qwen returned - `PASS_WITH_CHANGES`; Grok returned `PASS_WITH_REFINEMENTS` and zero blockers. All QF/GR findings - and both deletion ledgers await disposition. -- Continue the owner-locked order: Opus 5 high author/editor dispositions plus consolidation to at - most 10,000 words, including exact layered API selection and proof of the source-native/fallback - boundary; root checks, one final Fable 5 high substantive refinement, and mechanical checks only. - The current checkpoint is not final acceptance. +- Qwen returned `PASS_WITH_CHANGES`; Grok returned `PASS_WITH_REFINEMENTS`. Author/editor and root + dispositions are complete, and three final non-Claude closure audits passed `d28d8e779`. +- The owner removed the word-count gate and stopped all Claude/Fable usage. Do not launch or resume + any such route. Only mechanical run-state verification, commit/push, PR update, and owner review + remain. From a7a6887c228f2a908f8a5998129678c1f307e034 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Fri, 14 Aug 2026 21:09:49 +0200 Subject: [PATCH 17/19] chore(rfc): schedule final Fable gate --- .../briefs/fable-final-evaluator.md | 102 ++++++++++++++++++ .../context-pack.md | 30 +++--- .../drift.md | 13 +++ .../supervisor.md | 15 +-- .../workflows/launch-final-fable.sh | 91 ++++++++++++++++ .../worklog.md | 23 ++-- 6 files changed, 244 insertions(+), 30 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-final-evaluator.md create mode 100755 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/workflows/launch-final-fable.sh diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-final-evaluator.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-final-evaluator.md new file mode 100644 index 0000000000..691c2f7909 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-final-evaluator.md @@ -0,0 +1,102 @@ +use harness + +# Final Fable 5 high RFC evaluator and refinement gate + +Run one fresh native Claude Code session as the absolute-final substantive gate for the NetScript +database architecture RFC. The owner explicitly reinstated this single Fable 5 high launch on +2026-08-14; that instruction supersedes the earlier Claude/Fable freeze only for this gate. + +## SKILL + +- Read `AGENTS.md`, `.agents/skills/netscript-harness/SKILL.md`, + `.llm/harness/evaluator/protocol.md`, `.llm/harness/evaluator/verdict-definitions.md`, and + `.llm/harness/archetypes/SCOPE-docs.md`. +- This is an owner-authorized final **evaluation plus refinement** exception to the protocol's + read-only evaluator rule. It does not authorize package/plugin implementation or a broader + redesign. +- Do not spawn subagents, start workflows, resume an earlier Claude session, or use a fallback + model. If native Fable cannot run, record the failure and stop. + +## Target and authority + +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Branch: `docs/database-architecture-rfc` +- Draft PR: +- Canonical RFC: `rfcs/0000-database-architecture.md` +- Run: `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` +- The launcher fast-forwards to the exact remote branch before this session. Record that starting + commit in `evaluate.md`; evaluate the checked-out content, not a remembered draft. + +Read the complete RFC. Then read the compact governing evidence rather than reproducing the full +research corpus: + +1. `plan.md`, `plan-eval.md`, `worklog.md`, `context-pack.md`, and `drift.md`; +2. `reviews/root-semantic-closure.md`, `reviews/qwen-rfc-focused-review.md`, and + `reviews/grok-rfc-adversarial-review.md`; +3. `research/layered-dx-api-audit.md`, `research/typescript-schema-orpc-audit.md`, and + `research/runtime-validation-source-audit.md`; +4. pinned or official sources linked by the RFC when a claim needs verification. + +Do not restart the market study, duplicate source extracts into the RFC, or optimize for a word +count. Content, clarity, and implementability are the criteria. + +## Evaluation focus + +Judge whether an implementer can build the intended system without inventing missing architecture, +with special weight on the owner's end goal: + +1. A fantastic, low-ceremony developer experience built as one progressive surface: concise L1 + preset/DSL, public L2 factories, and unfenced L3 native Prisma plus NetScript primitives. +2. Prisma Next's current native TypeScript contract builder remains the schema authority. NetScript + adds adoption seams and policy; it does not mirror or fork Prisma's schema/query vocabulary. +3. Contract-first end-to-end type safety: source-native app inference by default, precise branded + values, and generated declarations only at proven publish/artifact boundaries. +4. One plugin contribution value registered once and fanning out authoring, runtime, control, + validation, CLI/docs/agent, ownership, and migration facets without a live service locator. +5. Runtime and JSON Standard Schema validation derived from the contract where metadata is + sufficient, with explicit operation/codec contributions and deterministic fail-closed refusal + elsewhere. +6. Coherent manifest -> plan -> receipt authority, locks, recovery, retained rollback, multi-space + identity, and honest PostgreSQL-first scope without pretending full multi-engine parity. +7. A clean break: no backward-compatibility requirement or compatibility shim. Migration guidance, + tests, and an optional parallel branch provide adoption safety instead. +8. API examples that are internally complete at their stated level and match pinned Prisma 8 RC + surfaces, package boundaries, emitted artifacts, and runtime value flow. + +Attack abstraction cost and manual steps particularly hard. A simple application must not pay +enterprise ceremony before it benefits from it, while advanced users and plugins must retain full +power. Verify that automated watch/compile/emit/staleness behavior makes the happy path feel native +rather than like a sequence of manual generators and adapters. + +## Refinement authority + +- If the RFC is already sound, do not rewrite it for style or manufacture findings. +- Correct factual contradictions, incomplete value/type flows, misleading API examples, or missing + DX commitments directly in the RFC when the repair stays within D-01–D-47 and `OWNER-DX-01`. +- Prefer clearer API contracts and links to evidence over duplicated explanation. Consolidate only + when it improves comprehension; there is no minimum, maximum, or target word count. +- Do not reopen the package graph, compatibility posture, native-Prisma authority, or fail-closed + validation boundary without a demonstrated blocker. A material architectural rescope receives + `FAIL_RESCOPE`; do not improvise it in this final pass. +- Do not edit `packages/**`, `plugins/**`, generated evidence, or the verbatim Qwen/Grok review + artifacts. + +## Required outputs and close gate + +1. Create `evaluate.md` from `.llm/harness/templates/evaluate.md`. Keep it decision-grade and cite + concrete file sections, commands, commits, or primary-source links for every substantive result. +2. If you refine the RFC, record each material disposition in `evaluate.md`; then reread the + affected end-to-end flows so a local correction does not create a cross-section contradiction. +3. Update `worklog.md`, `context-pack.md`, `supervisor.md`, and `drift.md` with the actual fresh + route, starting commit, verdict, refinements, and the fact that this one gate superseded the + earlier cancellation. Preserve the cancellation as historical provenance. +4. Run the docs-only mechanical gates: targeted `deno fmt --check` for the mutable Markdown files, + `deno task docs:links`, `git diff --check`, balanced-fence verification, and a clean status + check. Do not run package/runtime E2E for this RFC-only gate. +5. Use exactly one formal verdict: `PASS`, `FAIL_FIX`, `FAIL_RESCOPE`, or `FAIL_DEBT`. A `PASS` may + include evaluator-owned narrow refinements only when all resulting claims and gates are green. +6. Commit the complete final-evaluator gate with a message naming what it proves, push + `docs/database-architecture-rfc`, and comment on draft PR #1640 with the commit, verdict, + refinements, and command evidence. Keep the PR draft; do not merge or mark it ready. +7. Finish with a clean worktree whose local HEAD equals the remote branch. If any required step + fails, leave an honest failure receipt and do not claim the gate passed. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index 04a8618b60..b9a166b0f1 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -14,12 +14,11 @@ A clean-break database architecture RFC is at final verification. Issue #313 remains historical evidence; its compatibility-first solution is superseded. PLAN-EVAL cycle 2 passed, Opus authored -and consolidated the draft, Qwen and Grok reviewed it, and the author/editor disposition checkpoint -was pushed at `ad8effff9`. The owner then removed the length target and stopped every further -Claude/Fable route. Root resolved the remaining value-flow, binding-evidence, module-order, -operation-authority, JSR-asset, branded-type, validation, and rollback findings. Existing non-Claude -TypeScript/API, prospective JSR, and architecture lanes each returned `PASS`; the resulting RFC is -pushed at `d28d8e779`. Only mechanical verification, run-state bookkeeping, and PR handoff remain. +and consolidated the draft, Qwen and Grok reviewed it, and root closed the remaining semantic +findings at `d28d8e779`. The owner removed the length target and temporarily stopped further +Claude/Fable use, then explicitly reinstated exactly one final Fable 5 high evaluation/refinement +gate. It is scheduled for 2026-08-15 00:00 Europe/Zurich as the one-shot systemd user unit +`netscript-db-rfc-final-fable-20260815`; no other Claude route is reopened. ## Completed @@ -66,14 +65,15 @@ pushed at `d28d8e779`. Only mechanical verification, run-state bookkeeping, and ## In Progress -- Final mechanical verification, authoritative run-state update, and PR handoff. No substantive - model route remains active. +- One fresh native Fable 5 high final evaluator/refiner is scheduled from the clean pushed branch. + Its fail-closed launcher, brief, and output contract are persisted in this run. ## Next Steps -1. Run the final mechanical format/link/diff and repository-status checks. -2. Commit and push the run-state/handoff gate. -3. Update draft PR #1640 with the semantic and verification checkpoints; request owner review. +1. At 2026-08-15 00:00 Europe/Zurich, launch the single final Fable 5 high gate. +2. Record its exact starting commit, session, verdict, refinements, and mechanical evidence. +3. Commit and push the evaluator gate, comment on draft PR #1640, and leave the PR draft for owner + review. ## Key Decisions @@ -84,7 +84,7 @@ pushed at `d28d8e779`. Only mechanical verification, run-state bookkeeping, and | Exact future package graph | Plan lock | A1 contract → A4 definition → A3 runtime → A2 control → A2 Prisma PostgreSQL adapter → A6 testkit. | | Layered database adoption | Owner override | L1 preset/recipe uses L2 factories; L3 is native Prisma plus NetScript primitives/ports. | | App type flow | Owner override | Erased `typeof definition` first; automatic atomic declaration only at a W3-proven boundary. | -| No further Claude/Fable usage | Owner directive | Supersedes the planned final Fable gate; existing evidence remains historical. | +| Single final Fable gate | Owner directive | Reinstates one fresh Fable 5 high evaluator/refiner; all other Claude usage remains frozen. | | Content, not a word target | Owner directive | Consolidation serves clarity; length is not an acceptance metric. | ## Files Changed @@ -102,6 +102,7 @@ pushed at `d28d8e779`. Only mechanical verification, run-state bookkeeping, and | Fitness | PASS | D-01–D-47, OWNER-DX-01, and three final closure audits. | | Runtime | N/A | Docs-only RFC; future matrices are explicit implementation gates. | | Consumer | PASS | TypeScript/API, JSR, and architecture closure all passed `d28d8e779`. | +| Evaluator | PENDING | Final Fable 5 high gate is scheduled for 2026-08-15 00:00 CEST. | ## Open Questions @@ -112,8 +113,9 @@ pushed at `d28d8e779`. Only mechanical verification, run-state bookkeeping, and ## Drift and Debt -- Drift: #313 compatibility-first architecture is superseded; the planned final Fable gate and - length target are superseded by the latest owner directives. +- Drift: #313 compatibility-first architecture is superseded; the numeric length target remains + removed; the earlier final-Fable cancellation is historical and is superseded only for this one + scheduled gate. - Debt: pending targeted ledger scan. ## Commits diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md index ae6802d21a..f4af8cb927 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -180,3 +180,16 @@ documentation. 8,000–10,000-word target and 12,000-word hard ceiling, apply root findings R1–R10, then continue Qwen → Grok → dispositions → final Fable review order. - **Evidence:** `briefs/claude-opus-rfc-consolidate.md`; no architecture decision is reopened. + +## 2026-08-14 — Owner reinstated one final Fable refinement gate + +- **What:** The owner superseded the prior no-Claude/Fable directive for exactly one fresh final + Fable 5 high evaluation/refinement gate at the next midnight. +- **Expected:** The previous run-state override cancelled the originally planned Fable gate. +- **Actual:** A one-shot native Fable 5 high launch is scheduled for 2026-08-15 00:00 Europe/Zurich + through systemd user unit `netscript-db-rfc-final-fable-20260815`. +- **Severity:** significant owner override. +- **Action:** run only the persisted final-evaluator brief; prohibit subagents, workflows, resumes, + and fallback models; require a clean committed/pushed close gate. All other Claude use stays + frozen. +- **Evidence:** `briefs/fable-final-evaluator.md` and `workflows/launch-final-fable.sh`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index ae30662baa..b85255f124 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -23,7 +23,7 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | | focused post-draft RFC review | OpenRouter · Qwen 3.8 Max · max | Focused review after the root's complete-draft personal review | | owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | -| owner-directed final refinement | Anthropic · Fable 5 · high | **Cancelled before launch** by the latest owner Claude freeze | +| owner-directed final refinement | Anthropic · Fable 5 · high | One fresh gate scheduled for 2026-08-15 00:00 Europe/Zurich | ## Delegated research and synthesis lanes @@ -36,7 +36,8 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | `/root/planned_jsr_audit` | OpenAI · GPT-5.6 Sol · high | Prospective publishability/slow-type review of the planned graph | Complete | These lanes are independent research/synthesis inputs. The three existing non-Claude lanes also -performed the final read-only closure checks; no new lane and no Claude/Fable route was launched. +performed the final read-only closure checks. The owner later reinstated one fresh Fable 5 high +evaluator/refiner; no other Claude/Fable lane is reopened. ## Formal plan evaluation @@ -70,8 +71,9 @@ decisions remain locked, and no further PLAN-EVAL will run. | Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | | Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | | Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | -| Author/editor checkpoint | Native Claude Code · Opus 5 · high | completed session recorded in worklog | Root corrections applied and pushed as `ad8effff9`; no later Claude use. | +| Author/editor checkpoint | Native Claude Code · Opus 5 · high | completed session recorded in worklog | Root corrections applied and pushed as `ad8effff9`; no later Opus use. | | Root semantic closure | Codex supervisor + existing non-Claude lanes | current root session | TypeScript/API, JSR, and architecture verdicts `PASS`; pushed as `d28d8e779`. | +| Final evaluator/refiner | Native Claude Code · Fable 5 · high | scheduled fresh session | One-shot 2026-08-15 00:00 Europe/Zurich; verdict and commit pending. | Before commit `5dfc4e8eb`, root added three narrow corrections: runtime consumes the compiled `DatabaseManifest`, not `DatabaseDefinition`; the authority table distinguishes each artifact and @@ -106,9 +108,10 @@ descriptor couples both evidence tracks to canonical runtime snapshot identities `3f8a9a69-5589-4b91-9a32-91f7770fe7c2`, PID `1944525`, worktree matched, native UI reported “Opus 5 with high effort · Claude Max.” The session immediately exposed four internal agents; their roles/identities must be recorded in its report. -- Historical directive: the owner initially selected Fable 5 **high** as the final refinement gate. - The latest owner directive supersedes it and freezes all further Claude/Fable usage; the session - was not launched. +- Historical directive: the owner initially selected Fable 5 **high** as the final refinement gate, + then froze all further Claude/Fable usage before it launched. On 2026-08-14 the owner explicitly + superseded that cancellation for exactly one fresh final Fable 5 high gate at the next midnight. + All other Claude usage remains frozen. - Qwen 3.8 Max is selected for the owner-clarified focused post-draft review, after the root's personal complete-draft review and before Grok's whole-RFC adversarial pass. The completed route requested and observed `qwen/qwen3.8-max` at `max`, session diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/workflows/launch-final-fable.sh b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/workflows/launch-final-fable.sh new file mode 100755 index 0000000000..e4b1c5f882 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/workflows/launch-final-fable.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +umask 077 + +readonly repo='/home/codex/repos/netscript-db-rfc' +readonly branch='docs/database-architecture-rfc' +readonly run_dir="$repo/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc" +readonly prompt="$run_dir/briefs/fable-final-evaluator.md" +readonly output_dir="$repo/.llm/tmp/final-fable-evaluator" +readonly deno_bin='/home/codex/.deno/bin/deno' + +export HOME='/home/codex' +export PATH='/home/codex/.local/bin:/home/codex/.deno/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' + +mkdir -p "$output_dir" +readonly launched_at="$(date --iso-8601=seconds)" +readonly log_path="$output_dir/$launched_at.stream-json.log" +readonly status_path="$output_dir/latest-status.json" + +exec > >(tee -a "$log_path") 2>&1 + +write_status() { + local exit_code="$?" + local head='unavailable' + local remote_head='unavailable' + head="$(git -C "$repo" rev-parse HEAD 2>/dev/null || printf unavailable)" + remote_head="$(git -C "$repo" ls-remote origin "refs/heads/$branch" 2>/dev/null | awk '{print $1}' || printf unavailable)" + local completed_at + completed_at="$(date --iso-8601=seconds)" + local temporary_status="$status_path.tmp" + printf '{"launchedAt":"%s","completedAt":"%s","exitCode":%s,"head":"%s","remoteHead":"%s","log":"%s"}\n' \ + "$launched_at" "$completed_at" "$exit_code" "$head" "$remote_head" "$log_path" > "$temporary_status" + mv "$temporary_status" "$status_path" + printf 'final-fable launcher exit=%s head=%s remote=%s log=%s\n' \ + "$exit_code" "$head" "$remote_head" "$log_path" +} +trap write_status EXIT + +cd "$repo" + +if [[ "$(git branch --show-current)" != "$branch" ]]; then + printf 'refusing launch: expected branch %s, found %s\n' "$branch" "$(git branch --show-current)" >&2 + exit 20 +fi + +if [[ -n "$(git status --porcelain --untracked-files=all)" ]]; then + printf 'refusing launch: worktree is not clean\n' >&2 + git status --short >&2 + exit 21 +fi + +git fetch --quiet origin "refs/heads/$branch" +local_head="$(git rev-parse HEAD)" +remote_head="$(git rev-parse FETCH_HEAD)" + +if [[ "$local_head" != "$remote_head" ]]; then + if git merge-base --is-ancestor "$local_head" "$remote_head"; then + git merge --ff-only "$remote_head" + else + printf 'refusing launch: local and remote branch are diverged or local is unpushed\n' >&2 + exit 22 + fi +fi + +printf 'launching final evaluator at %s from commit %s\n' "$launched_at" "$(git rev-parse HEAD)" + +"$deno_bin" run -A .llm/tools/agentic/claude/claude-print.ts \ + --model claude-fable-5 \ + --effort high \ + --prompt "$prompt" + +if [[ -n "$(git status --porcelain --untracked-files=all)" ]]; then + printf 'evaluator returned with an uncommitted worktree\n' >&2 + git status --short >&2 + exit 30 +fi + +readonly final_head="$(git rev-parse HEAD)" +readonly pushed_head="$(git ls-remote origin "refs/heads/$branch" | awk '{print $1}')" +if [[ "$final_head" != "$pushed_head" ]]; then + printf 'evaluator did not push final HEAD: local=%s remote=%s\n' "$final_head" "$pushed_head" >&2 + exit 31 +fi + +if [[ ! -s "$run_dir/evaluate.md" ]]; then + printf 'evaluator did not create a non-empty evaluate.md\n' >&2 + exit 32 +fi + +printf 'final Fable gate completed and pushed at %s\n' "$final_head" diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index a6b38d6b4a..49e5591834 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -171,6 +171,7 @@ and release exits recorded in `plan.md`. | 2026-08-13 | 6 | disposition | The author/editor pass resolved QF/GR and OWNER-DX-01 findings; root's correction pass was committed and pushed as `ad8effff9`. | | 2026-08-13 | 7 | owner-gate | Owner removed word-count acceptance criteria and froze all further Claude/Fable usage. Existing completed sessions remain provenance only; no planned final Fable session ran. | | 2026-08-13 | 7 | closure | Root corrected executable extension transport, canonical space/snapshot binding evidence, emit/load ordering, compile/emit authority, branded IDs, validation projection honesty, package aggregate transport, and retained rollback. TypeScript/API, prospective JSR, and architecture lanes all returned `PASS`; `d28d8e779` was pushed. | +| 2026-08-14 | 8 | owner-gate | Owner reinstated exactly one fresh native Fable 5 high final evaluator/refinement gate at 2026-08-15 00:00 Europe/Zurich. Unit `netscript-db-rfc-final-fable-20260815` uses the persisted fail-closed launcher and brief; no fallback, subagent, workflow, or other Claude route is authorized. | ### RFC Consolidation and Root Acceptance @@ -258,17 +259,17 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | Provider-neutral kernel, PostgreSQL-only first adapter | Matches Prisma maturity without compatibility fallback or false portability. | Prisma scorecard/source + D-10/D-11/D-34 | | NetScript operational semantics, provider migration mechanics | NetScript owns policy/locks/recovery/receipts/saga while provider owns diff/lineage/marker. | Market/source reconciliation + D-27–D-30 | | PLAN-EVAL before RFC | Architecture has no open must-resolve item but still requires independent acceptance. | Harness Plan-Gate + D-01–D-47 | -| No further Claude/Fable route | Latest owner directive supersedes the planned final Fable gate; completed evidence remains historical. | Owner directive | +| One final Fable 5 high route | Latest owner directive supersedes the prior cancellation for this gate only; all other Claude usage remains frozen. | Owner directive | | No numeric RFC length gate | Content and clarity govern acceptance; consolidation is not a word-count exercise. | Owner directive | ## Drift -| Drift | Severity | Logged in drift.md | -| ------------------------------------------------------------ | ------------- | ------------------ | -| #313 compatibility-first plan is no longer authoritative | architectural | yes | -| Planned final Fable refinement was cancelled by owner | significant | run-state override | -| Word-count target was removed by owner | significant | run-state override | -| `origin/main` advanced by CI/gate-tooling commit `01e096049` | nonblocking | plan-eval evidence | +| Drift | Severity | Logged in drift.md | +| ------------------------------------------------------------ | ------------- | -------------------------------- | +| #313 compatibility-first plan is no longer authoritative | architectural | yes | +| Final Fable cancellation was later superseded for one gate | significant | owner-directed one-shot schedule | +| Word-count target was removed by owner | significant | run-state override | +| `origin/main` advanced by CI/gate-tooling commit `01e096049` | nonblocking | plan-eval evidence | ## Gate Results @@ -279,6 +280,7 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | | Compact RFC | Targeted fmt; `docs:links`; `git diff --check` | PASS | Commit `5dfc4e8eb`; 11,205 words and R1–R10 resolved. | | Semantic RFC | Targeted fmt; `docs:links`; `git diff --check`; fences | PASS | Commit `d28d8e779`; final blocker/high findings closed. | +| Final schedule | Targeted fmt; `docs:links`; `bash -n`; diff; calendar | PASS | One-shot launcher resolves to 2026-08-15 00:00 CEST. | ### Fitness Gates @@ -293,6 +295,7 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | TypeScript/API closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Extension, binding, loading, branded ID, validation and examples closed. | | Prospective JSR closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Static aggregate module plus cold-remote/network-disabled gate closed the last high. | | Architecture closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | D-01–D-47, OWNER-DX-01, package graph and four prior findings closed. | +| Final Fable evaluator | PENDING_SCHEDULED | Unit `netscript-db-rfc-final-fable-20260815` | Fresh native Fable 5 high at 2026-08-15 00:00 Europe/Zurich. | ### Runtime Gates @@ -316,6 +319,6 @@ CI/gate-tooling drift that changes structured check invocation rather than datab packages exist and must produce implementation/release receipts later. - Qwen returned `PASS_WITH_CHANGES`; Grok returned `PASS_WITH_REFINEMENTS`. Author/editor and root dispositions are complete, and three final non-Claude closure audits passed `d28d8e779`. -- The owner removed the word-count gate and stopped all Claude/Fable usage. Do not launch or resume - any such route. Only mechanical run-state verification, commit/push, PR update, and owner review - remain. +- The owner removed the word-count gate. The earlier Claude/Fable freeze remains in force except for + the explicitly scheduled single fresh Fable 5 high evaluator/refiner. After it commits and pushes + its gate, only PR handoff and owner review remain. From cc90ead7047a6f071c239c305619ac1ed77f2dae Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 15 Aug 2026 00:09:10 +0200 Subject: [PATCH 18/19] docs(rfc): pass final Fable 5 high evaluator gate Proves the owner-reinstated absolute-final substantive gate: a fresh native Fable 5 high session evaluated the complete RFC at starting commit a7a6887c2 against the eight owner criteria, independently re-verified the pinned RC1 claims (138 exports, phantom type maps, namespace flattening, demo helper spellings), and returned PASS in evaluate.md. One evaluator-owned refinement: Step 1 pgvector() no longer implies an extension-level dimensions option that pgvector and the pinned demo do not have; dimensions remain per-column only. Docs gates green post-edit: targeted fmt, docs:links (103 docs, 0 broken), git diff --check, 40 balanced fences. Run artifacts record the route, the verdict, and the supersession provenance; PR #1640 stays draft. Co-Authored-By: Claude Fable 5 --- .../context-pack.md | 34 ++-- .../drift.md | 21 +++ .../evaluate.md | 176 ++++++++++++++++++ .../supervisor.md | 4 +- .../worklog.md | 63 ++++--- rfcs/0000-database-architecture.md | 4 +- 6 files changed, 253 insertions(+), 49 deletions(-) create mode 100644 .llm/runs/docs-database-architecture-rfc--prisma-8-rfc/evaluate.md diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index b9a166b0f1..8cb69d48fa 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -6,19 +6,21 @@ | -------------- | ------------------------------------------------------- | | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | -| Current phase | `final-verification` | +| Current phase | `closed — final gate passed` | | Archetype | Docs-only RFC describing future A1/A4/A3/A2/A2/A6 graph | | Scope overlays | `SCOPE-docs.md` | ## Current State -A clean-break database architecture RFC is at final verification. Issue #313 remains historical -evidence; its compatibility-first solution is superseded. PLAN-EVAL cycle 2 passed, Opus authored -and consolidated the draft, Qwen and Grok reviewed it, and root closed the remaining semantic -findings at `d28d8e779`. The owner removed the length target and temporarily stopped further -Claude/Fable use, then explicitly reinstated exactly one final Fable 5 high evaluation/refinement -gate. It is scheduled for 2026-08-15 00:00 Europe/Zurich as the one-shot systemd user unit -`netscript-db-rfc-final-fable-20260815`; no other Claude route is reopened. +The clean-break database architecture RFC has passed its absolute-final substantive gate. Issue #313 +remains historical evidence; its compatibility-first solution is superseded. PLAN-EVAL cycle 2 +passed, Opus authored and consolidated the draft, Qwen and Grok reviewed it, root closed the +remaining semantic findings at `d28d8e779`, and the owner-reinstated one-shot fresh native Fable 5 +high evaluator/refiner ran on 2026-08-15 from starting commit `a7a6887c2`. It returned **`PASS`** in +`evaluate.md` after re-verifying the pinned RC1 claims and applying one narrow example refinement +(Step 1 `pgvector()` — upstream-false extension-level `dimensions` removed). The earlier +cancellation is preserved as provenance; it was superseded for exactly this gate and all other +Claude use stays frozen. Draft PR #1640 awaits owner review and stays draft. ## Completed @@ -63,17 +65,18 @@ gate. It is scheduled for 2026-08-15 00:00 Europe/Zurich as the one-shot systemd targeted formatting, internal-link, whitespace, and fence checks and pushed `d28d8e779`. The consolidated receipt is `reviews/root-semantic-closure.md`. +- The final Fable 5 high gate ran 2026-08-15: starting commit `a7a6887c2`, verdict **`PASS`**, one + narrow refinement, docs gates green post-edit; recorded in `evaluate.md` and committed/pushed with + a PR #1640 comment. + ## In Progress -- One fresh native Fable 5 high final evaluator/refiner is scheduled from the clean pushed branch. - Its fail-closed launcher, brief, and output contract are persisted in this run. +- Nothing. The run is closed pending owner review of draft PR #1640. ## Next Steps -1. At 2026-08-15 00:00 Europe/Zurich, launch the single final Fable 5 high gate. -2. Record its exact starting commit, session, verdict, refinements, and mechanical evidence. -3. Commit and push the evaluator gate, comment on draft PR #1640, and leave the PR draft for owner - review. +1. Owner reviews draft PR #1640 and decides on RFC acceptance (W0). The PR stays draft; no merge or + ready transition is authorized from this run. ## Key Decisions @@ -102,7 +105,7 @@ gate. It is scheduled for 2026-08-15 00:00 Europe/Zurich as the one-shot systemd | Fitness | PASS | D-01–D-47, OWNER-DX-01, and three final closure audits. | | Runtime | N/A | Docs-only RFC; future matrices are explicit implementation gates. | | Consumer | PASS | TypeScript/API, JSR, and architecture closure all passed `d28d8e779`. | -| Evaluator | PENDING | Final Fable 5 high gate is scheduled for 2026-08-15 00:00 CEST. | +| Evaluator | PASS | `evaluate.md` — final Fable 5 high gate, 2026-08-15, one refinement. | ## Open Questions @@ -121,4 +124,5 @@ gate. It is scheduled for 2026-08-15 00:00 Europe/Zurich as the one-shot systemd ## Commits - Semantic review closure: `d28d8e779` (pushed). +- Final Fable gate + refinement: committed and pushed 2026-08-15 from starting commit `a7a6887c2`. - See the draft PR's commit list + per-slice PR comments (V3 retired `commits.md`). diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md index f4af8cb927..9dfb7d532b 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -193,3 +193,24 @@ documentation. and fallback models; require a clean committed/pushed close gate. All other Claude use stays frozen. - **Evidence:** `briefs/fable-final-evaluator.md` and `workflows/launch-final-fable.sh`. + +## 2026-08-15 — Final Fable gate executed; verdict PASS with one refinement + +- **What:** The owner-reinstated one-shot fresh native Fable 5 high evaluator/refiner ran as the + absolute-final substantive gate, superseding the earlier Claude/Fable cancellation for exactly + this gate. The cancellation remains historical provenance; all other Claude use stays frozen. +- **Source:** Owner directive 2026-08-14; unit `netscript-db-rfc-final-fable-20260815`; + `briefs/fable-final-evaluator.md`. +- **Expected:** Evaluate the checked-out RFC at the exact remote tip; refine only within D-01–D-47 + and `OWNER-DX-01`; no subagents, workflows, resumes, or fallback models. +- **Actual:** Starting commit `a7a6887c2` (verified equal to the fetched remote tip). The full RFC, + run artifacts, three reviews, and three audits were read; the load-bearing pinned RC1 claims were + independently re-verified (138 export keys, phantom type maps at `types.ts:207`, namespace + flattening, demo helper spellings). One example-level defect was found and repaired: Step 1's + `pgvector({ dimensions: 1536 })` invented an extension-level dimension option that pgvector and + the pinned demo do not have; the call is now `pgvector()` and the Step 6 declaration takes + `options?`. No decision was reopened. Verdict: **`PASS`** in `evaluate.md`; targeted fmt, + `docs:links` (103 docs, 0 broken), `git diff --check`, and fence balance all green post-edit. +- **Severity:** none — gate completed as authorized. +- **Action:** close the run; draft PR #1640 stays draft for owner review. +- **Evidence:** `evaluate.md`; this gate's commit on `docs/database-architecture-rfc`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/evaluate.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/evaluate.md new file mode 100644 index 0000000000..dcdef85296 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/evaluate.md @@ -0,0 +1,176 @@ +# Evaluation: NetScript Database Architecture RFC — final Fable 5 high gate + +Final owner-authorized evaluation **plus refinement** gate. This session is the one-shot fresh +native Fable 5 high launch reinstated by the owner on 2026-08-14 (unit +`netscript-db-rfc-final-fable-20260815`); it supersedes the earlier Claude/Fable freeze for exactly +this gate. The evaluator read the complete RFC at the starting commit, the governing run artifacts, +the three review receipts, and the three research audits, and independently re-verified the +load-bearing pinned-source claims against the local RC1 checkout. + +## Metadata + +| Field | Value | +| --------------- | ---------------------------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Target | `rfcs/0000-database-architecture.md` (canonical RFC), draft PR #1640 | +| Archetype | N/A — docs-only RFC describing the future A1/A4/A3/A2/A2/A6 graph | +| Scope overlays | `SCOPE-docs.md` | +| Evaluator | Native Claude Code · `claude-fable-5` · high · fresh session · 2026-08-15 | +| Starting commit | `a7a6887c228f2a908f8a5998129678c1f307e034` = remote tip (verified via fetch) | +| Route authority | Owner directive 2026-08-14; recorded in `drift.md` and `supervisor.md` | + +Constraints honored: no subagents, no workflows, no session resume, no fallback model. The evaluated +content is the checked-out worktree at the starting commit, not a remembered draft. + +## Process Verification + +| Check | Result | Evidence | +| -------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------- | +| Plan-Gate passed before implementation | PASS | `plan-eval.md` cycle 2 `PASS` (Fable 5 medium, session `f3286656…`, commit `383170bbc`); cycle 1 `FAIL_PLAN` preserved | +| Design section exists in worklog | PASS | `worklog.md` § Design — locked, evaluator-approved, `OWNER-DX-01` recorded as an explicit post-eval owner override | +| Commit slices match design plan | PASS | Slices 0–7 in `plan.md`/`worklog.md` match the branch history through `d28d8e779`/`a7a6887c2`; this gate is the terminal one | +| Each slice has a passing gate | PASS | `worklog.md` § Gate Results: bootstrap, compact-RFC, semantic-RFC, and final-schedule static gates all PASS with commands | +| Review chain honored | PASS | Root review → Qwen `PASS_WITH_CHANGES` → Grok `PASS_WITH_REFINEMENTS` (0 blockers) → dispositions → root semantic closure | +| Owner supersession provenance | PASS | `drift.md` 2026-08-14 entry preserves the cancellation and records this one reinstated gate | + +## Substantive Evaluation Against the Eight Focus Criteria + +1. **Layered DX as one progressive surface — PASS.** Step 2 shows L1 `defineSingleTargetDatabase` + literally calling the L2 `defineDatabase*` factories and returning the same `DatabaseDefinition`; + L3 is native Prisma plus kernel primitives with the emission/runtime module graphs honestly + split. "The normal loop has no manual type generation" commits `dev/start/test/build` to + content-hash compile, watch, verify, and atomic swap, with `db emit --verify` in CI and `db emit` + demoted to an escape hatch. A one-database app pays: one 3-line provider module, one native + contract, one L1 call — no enterprise ceremony before benefit. +2. **Prisma authority, no mirrored vocabulary — PASS.** Step 1 authors through the pinned RC1 + `defineContract(scaffold, callback)`; every helper spelling in the example was re-verified this + session against `examples/prisma-8-demo/prisma/contract.ts` in the pinned checkout + (`field.id.uuidv4String()`, `field.temporal.createdAt()`, `type.pgvector.Vector(1536)`, + `field.namedType(…).optional()`, `rel.hasMany/belongsTo` coordinates — all exact). No NetScript + schema/query DSL, no re-export, no copied overloads anywhere in the surface. +3. **Contract-first end-to-end type safety — PASS.** Erased `typeof definition` inference is the + default for app-authored spaces (backed by the phantom `_contract?: TContract` and no-emit + evidence, re-verified: `TypeMapsPhantomKey` at `2-sql/1-core/contract/src/types.ts:207`); + generated declarations are bounded to pinned artifact-only spaces and publishable exports, both + W3-proved; `FieldValueOf` keeps branded values (`Char<36>` UUID) honest at the boundary. The four + inference rules each name a conformance fixture; the one soundness seam at `runtime.bind` is + named, mitigated, and gated. +4. **One plugin contribution value fanning out — PASS.** `definePluginSpace` (Step 5) is one + callable descriptor carrying id/owner/version/capabilities/grants/policy plus a statically + imported aggregate; one `PostgresExtension` bundle registered once on the configured provider + (Step 6) fans authoring/control/runtime/validation, with `db.compose.extension.facet-mismatch` + refusing skew. Providers are composition-root values; no service locator or global registry. +5. **Validation derived where provable, fail-closed elsewhere — PASS.** Three schema classes with + distinct guarantees; operation grammar comes only from contributed packs (`ormCollection@1`) + whose identity/version enter manifest and cache key; `DB_VALIDATION_UNSUPPORTED` at construction + with coordinates; invalid values return Standard Schema issues, never throw; representations are + exactly `runtime`/`json` with driver wire internal — matching the runtime-validation source audit + §3/§4/§7 precisely (the earlier QF-05 conflation is fixed in the current text). +6. **Manifest → plan → receipt authority chain — PASS.** The six-value authority table is disjoint; + `DatabaseDefinition` is consumed only by `compileDatabase`; there is no `control.emit`; the apply + state machine, lock scope `(target, physical database)` with fencing, inspect-before-resume, and + the total two-level rollup function (mixed spaces never make a target "partially successful"; a + run with no succeeded target is never `partial-success`) are all explicit. Retained detach is a + receipt-backed, verify-only tombstone under the provider lock. PostgreSQL-first scope is honest: + SQLite/MongoDB/MySQL/MSSQL refuse with `db.target.unsupported`, and the namespace capability is + withheld on re-verified upstream evidence (`contract-types.ts:644+` flattening comment confirmed + in the pinned checkout). +7. **Clean break with adoption safety — PASS.** The no-compatibility law enumerates every banned + survival; `db adopt` is a seven-step marker-metadata-only protocol (zero application-schema DDL, + zero application-data DML) with per-target statuses, rehearsal/backup/preflight requirements, and + forward-only recovery after first apply; parallel branches without co-composition. +8. **Examples internally complete and RC1-faithful — PASS after one narrow repair.** The emitted + binding is now a real value module; `manifest`/`postgres`/`connections`/`runId`/`policy` are + bound or explicitly named across Steps 3 and 7; the configured-provider value is used + consistently at every call site. One residual defect found and fixed this session (below). The + 138-export claim was independently re-counted this session: `python3` over the pinned + `packages/9-public/@prisma/orm-postgres/package.json` returns exactly 138 export keys at + `a76a6c5` (`v8.0.0-rc.1`). + +### Prior-review disposition spot-audit + +QF-01/GR-01 (declare-only binding), QF-02/GR-02 (bundle authorship vs import law), GR-03 (per-space +evidence, no merged contract), GR-04 (emit authority), GR-05 (retained tombstone), GR-06 (rollup +totality), GR-07 (factory vs configured value), QF-04 (Prisma path attribution), and QF-05 +(paramsSchema vs conversion channels) were each re-checked in the current text and are genuinely +closed, consistent with `reviews/root-semantic-closure.md`. + +## Refinements Applied by This Gate + +| # | Location | Defect | Repair | +| - | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | +| 1 | Step 1 `database/provider.ts` | `pgvector({ dimensions: 1536 })` invented extension-level dimension configuration. pgvector has no such parameter — dimension is a per-column type modifier — and the pinned demo registers the pack with no configuration (`extensions: { pgvector }`). The duplicated `1536` invited implementing a conflicting config axis against `type.pgvector.Vector(1536)`. | `const vector = pgvector();` — dimensions now appear only in the per-column type call, as upstream. | +| 2 | Step 6 declaration | `pgvector(options: PgVectorOptions)` required an argument the corrected Step 1 call no longer passes. | `options?: PgVectorOptions` — declaration and flagship call site agree. | + +Affected end-to-end flow (Step 1 provider creation → Step 2 targets → Step 6 registration → +validation codec `pgvector.vector@1`) was reread after the edit; no cross-section contradiction was +introduced, and no prose anywhere referenced extension-level dimensions. No other correction was +warranted: no factual contradiction, incomplete value/type flow, or missing DX commitment survived +the full read. The package graph, compatibility posture, native-Prisma authority, and fail-closed +validation boundary were not reopened; D-01–D-47 and `OWNER-DX-01` are untouched. + +## Static Gates (docs-only mechanical set, run this session) + +| Gate | Command or check | Result | Evidence | +| --------------- | ----------------------------------------------------- | ------ | -------------------------------------------------------------- | +| Format | `deno fmt --check rfcs/0000-database-architecture.md` | PASS | "Checked 1 file", post-refinement | +| Link/path check | `deno task docs:links` | PASS | 103 docs, 0 broken links, 0 broken anchors, 0 enforced orphans | +| Diff hygiene | `git diff --check` | PASS | No whitespace errors | +| Fence balance | count of `` ``` `` lines | PASS | 40 fences, balanced | +| Run artifacts | `deno fmt --check` over mutated run Markdown | PASS | Recorded at commit time | +| Clean close | `git status` clean; local HEAD equals pushed remote | PASS | Recorded at commit time | + +Package/runtime E2E, publish dry-run, doc-lint, and F-1…F-19 fitness functions are **N/A** for this +docs-only RFC gate; they are named as future implementation gates in the RFC and `plan.md`, and the +RFC claims none of them have run. + +## Runtime Gates + +| Gate | Validation | Result | Evidence | +| ---------------- | ------------------- | ------ | --------------------------------------------------------------- | +| Runtime behavior | Docs-only Plan-Gate | N/A | Future A3/provider/control matrices remain explicit in the plan | + +## Consumer Gates + +| Consumer | Validation | Result | Evidence | +| ---------------------- | --------------------------------------------------- | ------ | ----------------------------------------------------------------- | +| RFC reader/implementer | Can build the system without inventing architecture | PASS | Eight-criteria evaluation above; every API/state machine is named | +| Pinned-source claims | Independent re-verification | PASS | 138 exports, phantom type maps, namespace flattening, demo shapes | + +## Anti-Pattern Check + +Docs-only scope: the RFC prescribes rejection of the applicable patterns rather than shipping code. +AP-3 (god ports — capped at 3–4 methods), AP-14 (re-export — banned with the 138-export evidence), +AP-24 (engine switch — the motivating counter-example), and AP-25 (side effects outside edges — +pure/offline split) are addressed in the text; all 25 are `N/A` as code checks for this changeset. + +## Arch-Debt Delta + +| Metric | Count | Evidence | +| --------------------- | ----- | ------------------------------------------------------------------------------- | +| New entries | 0 | Docs-only; no doctrine violation introduced | +| Resolved entries | 0 | `DB-GENERATE-ASPIRE-COUPLING` closure is _designed_ (structural), not yet coded | +| Deepened violations | 0 | — | +| Unrecorded violations | 0 | — | + +## Findings + +| Severity | Finding | Evidence | Required action | +| -------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------ | +| low | Step 1 pgvector example implied extension-level dimension configuration | Pinned demo `extensions: { pgvector }`; per-column `Vector(1536)` | Fixed this session (see above) | + +No high or medium finding. No `FAIL_RESCOPE` trigger: the package graph, clean-break posture, +native-Prisma authority, and fail-closed boundary are sound as written. + +## Lessons for Promotion + +| Lesson | Pattern | Applies to | Confidence | +| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------- | ---------- | +| Flagship examples must not invent upstream config surfaces | Every option shown on a wrapper of a pinned upstream must exist upstream or be specified | docs runs | medium | + +## Verdict + +| Field | Value | +| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Verdict | **PASS** | +| Rationale | The RFC is implementation-grade against all eight owner criteria: an implementer can build the layered surface, type flow, plugin fan-out, bounded validation, and control chain without inventing architecture. The single defect found was example-level, repaired within refinement authority, and all resulting docs gates are green. | diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index b85255f124..6d3da6c3de 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -23,7 +23,7 @@ Written at run start per `workflow/lane-policy.md` § Supervisor identity. | `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | | focused post-draft RFC review | OpenRouter · Qwen 3.8 Max · max | Focused review after the root's complete-draft personal review | | owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | -| owner-directed final refinement | Anthropic · Fable 5 · high | One fresh gate scheduled for 2026-08-15 00:00 Europe/Zurich | +| owner-directed final refinement | Anthropic · Fable 5 · high | Ran 2026-08-15 as one fresh session; verdict `PASS` with one refinement | ## Delegated research and synthesis lanes @@ -73,7 +73,7 @@ decisions remain locked, and no further PLAN-EVAL will run. | Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | | Author/editor checkpoint | Native Claude Code · Opus 5 · high | completed session recorded in worklog | Root corrections applied and pushed as `ad8effff9`; no later Opus use. | | Root semantic closure | Codex supervisor + existing non-Claude lanes | current root session | TypeScript/API, JSR, and architecture verdicts `PASS`; pushed as `d28d8e779`. | -| Final evaluator/refiner | Native Claude Code · Fable 5 · high | scheduled fresh session | One-shot 2026-08-15 00:00 Europe/Zurich; verdict and commit pending. | +| Final evaluator/refiner | Native Claude Code · Fable 5 · high | fresh one-shot session, 2026-08-15 | Starting commit `a7a6887c2`; verdict **`PASS`**; one example refinement; gate committed/pushed. | Before commit `5dfc4e8eb`, root added three narrow corrections: runtime consumes the compiled `DatabaseManifest`, not `DatabaseDefinition`; the authority table distinguishes each artifact and diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 49e5591834..29a3a3b6a4 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -151,27 +151,28 @@ and release exits recorded in `plan.md`. ## Progress Log -| Time | Slice | Step | Notes | -| ---------- | ----- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | -| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | -| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | -| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | -| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | -| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | -| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | -| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | -| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | -| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | -| 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | -| 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | -| 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | -| 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | -| 2026-08-13 | 6 | owner-dx | `OWNER-DX-01` audited shipped service/Hono preset→factory→native primitives, SDK/Fresh analogues, and Prisma's runtime `contractJson` plus phantom compile-time contract split. Owner overrode D-07/D-08/D-36 after PLAN-EVAL: source-native app inference is default; automatic declarations are a bounded W3 fallback. No new PLAN-EVAL. | -| 2026-08-13 | 6 | disposition | The author/editor pass resolved QF/GR and OWNER-DX-01 findings; root's correction pass was committed and pushed as `ad8effff9`. | -| 2026-08-13 | 7 | owner-gate | Owner removed word-count acceptance criteria and froze all further Claude/Fable usage. Existing completed sessions remain provenance only; no planned final Fable session ran. | -| 2026-08-13 | 7 | closure | Root corrected executable extension transport, canonical space/snapshot binding evidence, emit/load ordering, compile/emit authority, branded IDs, validation projection honesty, package aggregate transport, and retained rollback. TypeScript/API, prospective JSR, and architecture lanes all returned `PASS`; `d28d8e779` was pushed. | -| 2026-08-14 | 8 | owner-gate | Owner reinstated exactly one fresh native Fable 5 high final evaluator/refinement gate at 2026-08-15 00:00 Europe/Zurich. Unit `netscript-db-rfc-final-fable-20260815` uses the persisted fail-closed launcher and brief; no fallback, subagent, workflow, or other Claude route is authorized. | +| Time | Slice | Step | Notes | +| ---------- | ----- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | +| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | +| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | +| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | +| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | +| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | +| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | +| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | +| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | +| 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | +| 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | +| 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | +| 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | +| 2026-08-13 | 6 | owner-dx | `OWNER-DX-01` audited shipped service/Hono preset→factory→native primitives, SDK/Fresh analogues, and Prisma's runtime `contractJson` plus phantom compile-time contract split. Owner overrode D-07/D-08/D-36 after PLAN-EVAL: source-native app inference is default; automatic declarations are a bounded W3 fallback. No new PLAN-EVAL. | +| 2026-08-13 | 6 | disposition | The author/editor pass resolved QF/GR and OWNER-DX-01 findings; root's correction pass was committed and pushed as `ad8effff9`. | +| 2026-08-13 | 7 | owner-gate | Owner removed word-count acceptance criteria and froze all further Claude/Fable usage. Existing completed sessions remain provenance only; no planned final Fable session ran. | +| 2026-08-13 | 7 | closure | Root corrected executable extension transport, canonical space/snapshot binding evidence, emit/load ordering, compile/emit authority, branded IDs, validation projection honesty, package aggregate transport, and retained rollback. TypeScript/API, prospective JSR, and architecture lanes all returned `PASS`; `d28d8e779` was pushed. | +| 2026-08-14 | 8 | owner-gate | Owner reinstated exactly one fresh native Fable 5 high final evaluator/refinement gate at 2026-08-15 00:00 Europe/Zurich. Unit `netscript-db-rfc-final-fable-20260815` uses the persisted fail-closed launcher and brief; no fallback, subagent, workflow, or other Claude route is authorized. | +| 2026-08-15 | 8 | final-gate | Fresh native Fable 5 high evaluator ran from starting commit `a7a6887c2` (= remote tip), read the complete RFC, run artifacts, three reviews, and three audits, re-verified the pinned RC1 claims (138 exports, phantom type maps, namespace flattening, demo helper spellings), applied one narrow example repair (`pgvector()` — extension-level `dimensions` removed as upstream-false), and returned **`PASS`** in `evaluate.md`. Docs gates green post-edit. | ### RFC Consolidation and Root Acceptance @@ -275,12 +276,13 @@ CI/gate-tooling drift that changes structured check invocation rather than datab ### Static Gates -| Gate | Command or check | Result | Notes | -| -------------- | ------------------------------------------------------ | ------ | ------------------------------------------------------- | -| Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | -| Compact RFC | Targeted fmt; `docs:links`; `git diff --check` | PASS | Commit `5dfc4e8eb`; 11,205 words and R1–R10 resolved. | -| Semantic RFC | Targeted fmt; `docs:links`; `git diff --check`; fences | PASS | Commit `d28d8e779`; final blocker/high findings closed. | -| Final schedule | Targeted fmt; `docs:links`; `bash -n`; diff; calendar | PASS | One-shot launcher resolves to 2026-08-15 00:00 CEST. | +| Gate | Command or check | Result | Notes | +| -------------- | ------------------------------------------------------ | ------ | ----------------------------------------------------------------------- | +| Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | +| Compact RFC | Targeted fmt; `docs:links`; `git diff --check` | PASS | Commit `5dfc4e8eb`; 11,205 words and R1–R10 resolved. | +| Semantic RFC | Targeted fmt; `docs:links`; `git diff --check`; fences | PASS | Commit `d28d8e779`; final blocker/high findings closed. | +| Final schedule | Targeted fmt; `docs:links`; `bash -n`; diff; calendar | PASS | One-shot launcher resolves to 2026-08-15 00:00 CEST. | +| Final gate | Targeted fmt; `docs:links`; `git diff --check`; fences | PASS | Post-refinement: 1 file checked, 103 docs 0 broken, 40 balanced fences. | ### Fitness Gates @@ -295,7 +297,7 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | TypeScript/API closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Extension, binding, loading, branded ID, validation and examples closed. | | Prospective JSR closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Static aggregate module plus cold-remote/network-disabled gate closed the last high. | | Architecture closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | D-01–D-47, OWNER-DX-01, package graph and four prior findings closed. | -| Final Fable evaluator | PENDING_SCHEDULED | Unit `netscript-db-rfc-final-fable-20260815` | Fresh native Fable 5 high at 2026-08-15 00:00 Europe/Zurich. | +| Final Fable evaluator | PASS | `evaluate.md`; starting commit `a7a6887c2` | Fresh native Fable 5 high, 2026-08-15; one narrow example refinement, gates green. | ### Runtime Gates @@ -320,5 +322,6 @@ CI/gate-tooling drift that changes structured check invocation rather than datab - Qwen returned `PASS_WITH_CHANGES`; Grok returned `PASS_WITH_REFINEMENTS`. Author/editor and root dispositions are complete, and three final non-Claude closure audits passed `d28d8e779`. - The owner removed the word-count gate. The earlier Claude/Fable freeze remains in force except for - the explicitly scheduled single fresh Fable 5 high evaluator/refiner. After it commits and pushes - its gate, only PR handoff and owner review remain. + the explicitly scheduled single fresh Fable 5 high evaluator/refiner, which ran on 2026-08-15 from + starting commit `a7a6887c2` and returned **`PASS`** with one narrow example refinement + (`evaluate.md`). Only owner review of draft PR #1640 remains; the PR stays draft. diff --git a/rfcs/0000-database-architecture.md b/rfcs/0000-database-architecture.md index 3d652d46a1..caeb492630 100644 --- a/rfcs/0000-database-architecture.md +++ b/rfcs/0000-database-architecture.md @@ -178,7 +178,7 @@ on the provider, and uses that provider's **public authoring scaffold** with `de // database/provider.ts — complete module; the sole live provider/extension composition root import { pgvector, prismaPostgres } from '@netscript/database-prisma-postgres'; -const vector = pgvector({ dimensions: 1536 }); +const vector = pgvector(); export const postgres = prismaPostgres({ minVersion: 15, @@ -638,7 +638,7 @@ extension publisher** assembles one bundle for the provider boundary: ```ts // @netscript/database-prisma-postgres — assembled inside the provider boundary, not by the app -export declare function pgvector(options: PgVectorOptions): PostgresExtension<'pgvector'>; +export declare function pgvector(options?: PgVectorOptions): PostgresExtension<'pgvector'>; // → { id, version, requires: [CAP.pgvector], authoring, control, runtime, validation } ``` From 2e97c86e4e16984bb226e509e77c8f43f6facf04 Mon Sep 17 00:00:00 2001 From: Rickylabs Date: Sat, 15 Aug 2026 01:09:05 +0200 Subject: [PATCH 19/19] docs(rfc): close final evaluator run --- .../context-pack.md | 47 ++++++++-------- .../drift.md | 7 ++- .../supervisor.md | 43 ++++++++------ .../worklog.md | 56 ++++++++++--------- 4 files changed, 85 insertions(+), 68 deletions(-) diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md index 8cb69d48fa..8caf984853 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -17,18 +17,20 @@ remains historical evidence; its compatibility-first solution is superseded. PLA passed, Opus authored and consolidated the draft, Qwen and Grok reviewed it, root closed the remaining semantic findings at `d28d8e779`, and the owner-reinstated one-shot fresh native Fable 5 high evaluator/refiner ran on 2026-08-15 from starting commit `a7a6887c2`. It returned **`PASS`** in -`evaluate.md` after re-verifying the pinned RC1 claims and applying one narrow example refinement -(Step 1 `pgvector()` — upstream-false extension-level `dimensions` removed). The earlier -cancellation is preserved as provenance; it was superseded for exactly this gate and all other -Claude use stays frozen. Draft PR #1640 awaits owner review and stays draft. +`evaluate.md` as fresh session `3517a6d2-b0b5-47ec-a207-b3533657a90c` after re-verifying the pinned +RC1 claims and applying one narrow example refinement (Step 1 `pgvector()` — upstream-false +extension-level `dimensions` removed). Gate `cc90ead70` is pushed. The earlier cancellation is +preserved as provenance; it was superseded for exactly this gate and all other Claude use stays +frozen. Draft PR #1640 awaits owner review and stays draft. ## Completed - Loaded current repository, RFC process, harness, PR, doctrine-navigation, and docs-profile rules. - Created an isolated worktree/branch from `origin/main` @ `cd7205293`. - Read GitHub issue #313 and its comments through the connected GitHub surface. -- Selected and completed mandatory PLAN-EVAL; the later planned Fable refinement was superseded by - the owner's Claude freeze before it ran. +- Selected and completed mandatory PLAN-EVAL. The owner's later Claude freeze temporarily cancelled + final refinement, then a subsequent directive reinstated exactly one fresh Fable gate; it ran and + passed. - Completed the research corpus, D-01–D-47 lock, prospective JSR audit, and architecture synthesis. - Preserved cycle 1 `FAIL_PLAN`, corrected the task finding to 42 keys per generated engine workspace, and obtained cycle 2 `PASS`. @@ -65,9 +67,9 @@ Claude use stays frozen. Draft PR #1640 awaits owner review and stays draft. targeted formatting, internal-link, whitespace, and fence checks and pushed `d28d8e779`. The consolidated receipt is `reviews/root-semantic-closure.md`. -- The final Fable 5 high gate ran 2026-08-15: starting commit `a7a6887c2`, verdict **`PASS`**, one - narrow refinement, docs gates green post-edit; recorded in `evaluate.md` and committed/pushed with - a PR #1640 comment. +- The final Fable 5 high gate ran 2026-08-15 as session `3517a6d2-b0b5-47ec-a207-b3533657a90c`: + starting commit `a7a6887c2`, verdict **`PASS`**, one narrow refinement, docs gates green + post-edit; recorded in `evaluate.md`, pushed as `cc90ead70`, and posted to PR #1640. ## In Progress @@ -92,20 +94,20 @@ Claude use stays frozen. Draft PR #1640 awaits owner review and stays draft. ## Files Changed -| Path | Status | Notes | -| --------------------------------------------------------- | ------ | --------------------------------------- | -| `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` | new | Harness provenance and resumable state. | -| `rfcs/0000-database-architecture.md` | new | Canonical RFC; semantic closure pushed. | +| Path | Status | Notes | +| --------------------------------------------------------- | ------ | --------------------------------------------- | +| `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` | new | Harness provenance and terminal receipts. | +| `rfcs/0000-database-architecture.md` | new | Canonical RFC; final Fable refinement pushed. | ## Gates -| Gate family | Current status | Evidence | -| ----------- | -------------- | ----------------------------------------------------------------------- | -| Static | PASS | RFC format, `docs:links`, diff, balanced fences at semantic checkpoint. | -| Fitness | PASS | D-01–D-47, OWNER-DX-01, and three final closure audits. | -| Runtime | N/A | Docs-only RFC; future matrices are explicit implementation gates. | -| Consumer | PASS | TypeScript/API, JSR, and architecture closure all passed `d28d8e779`. | -| Evaluator | PASS | `evaluate.md` — final Fable 5 high gate, 2026-08-15, one refinement. | +| Gate family | Current status | Evidence | +| ----------- | -------------- | --------------------------------------------------------------------- | +| Static | PASS | Final-gate RFC format, `docs:links`, diff, and 40 balanced fences. | +| Fitness | PASS | D-01–D-47, OWNER-DX-01, and three final closure audits. | +| Runtime | N/A | Docs-only RFC; future matrices are explicit implementation gates. | +| Consumer | PASS | TypeScript/API, JSR, and architecture closure all passed `d28d8e779`. | +| Evaluator | PASS | `evaluate.md`; session `3517a6d2-b0b5-47ec-a207-b3533657a90c`. | ## Open Questions @@ -119,10 +121,11 @@ Claude use stays frozen. Draft PR #1640 awaits owner review and stays draft. - Drift: #313 compatibility-first architecture is superseded; the numeric length target remains removed; the earlier final-Fable cancellation is historical and is superseded only for this one scheduled gate. -- Debt: pending targeted ledger scan. +- Debt: final evaluator reports zero new, resolved, deepened, or unrecorded doctrine violations; + designed future debt closure is not claimed as implemented. ## Commits - Semantic review closure: `d28d8e779` (pushed). -- Final Fable gate + refinement: committed and pushed 2026-08-15 from starting commit `a7a6887c2`. +- Final Fable gate + refinement: `cc90ead70` (pushed), from starting commit `a7a6887c2`. - See the draft PR's commit list + per-slice PR comments (V3 retired `commits.md`). diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md index 9dfb7d532b..fd38e1b37c 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -200,7 +200,7 @@ documentation. absolute-final substantive gate, superseding the earlier Claude/Fable cancellation for exactly this gate. The cancellation remains historical provenance; all other Claude use stays frozen. - **Source:** Owner directive 2026-08-14; unit `netscript-db-rfc-final-fable-20260815`; - `briefs/fable-final-evaluator.md`. + `briefs/fable-final-evaluator.md`; native session `3517a6d2-b0b5-47ec-a207-b3533657a90c`. - **Expected:** Evaluate the checked-out RFC at the exact remote tip; refine only within D-01–D-47 and `OWNER-DX-01`; no subagents, workflows, resumes, or fallback models. - **Actual:** Starting commit `a7a6887c2` (verified equal to the fetched remote tip). The full RFC, @@ -210,7 +210,10 @@ documentation. `pgvector({ dimensions: 1536 })` invented an extension-level dimension option that pgvector and the pinned demo do not have; the call is now `pgvector()` and the Step 6 declaration takes `options?`. No decision was reopened. Verdict: **`PASS`** in `evaluate.md`; targeted fmt, - `docs:links` (103 docs, 0 broken), `git diff --check`, and fence balance all green post-edit. + `docs:links` (103 docs, 0 broken), `git diff --check`, and fence balance all green post-edit. The + unit exited `Result=success`/status 0 with terminal reason `completed` and no permission denials; + stream receipt SHA-256 is `9939f19d8c66981eadb2589ffdce0f2a3025f24e92ebfb5982a6f24d115cdff3`; gate + `cc90ead70` was the pushed remote and live PR head at gate close. - **Severity:** none — gate completed as authorized. - **Action:** close the run; draft PR #1640 stays draft for owner review. - **Evidence:** `evaluate.md`; this gate's commit on `docs/database-architecture-rfc`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md index 6d3da6c3de..4aad82bab7 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -64,22 +64,30 @@ decisions remain locked, and no further PLAN-EVAL will run. ## RFC authoring and consolidation -| Stage | Route / model / effort | Session | Result | -| ------------------------ | -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------ | -| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | -| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | -| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | -| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | -| Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | -| Author/editor checkpoint | Native Claude Code · Opus 5 · high | completed session recorded in worklog | Root corrections applied and pushed as `ad8effff9`; no later Opus use. | -| Root semantic closure | Codex supervisor + existing non-Claude lanes | current root session | TypeScript/API, JSR, and architecture verdicts `PASS`; pushed as `d28d8e779`. | -| Final evaluator/refiner | Native Claude Code · Fable 5 · high | fresh one-shot session, 2026-08-15 | Starting commit `a7a6887c2`; verdict **`PASS`**; one example refinement; gate committed/pushed. | +| Stage | Route / model / effort | Session | Result | +| ------------------------ | -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------- | +| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | +| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | +| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | +| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | +| Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | +| Author/editor checkpoint | Native Claude Code · Opus 5 · high | completed session recorded in worklog | Root corrections applied and pushed as `ad8effff9`; no later Opus use. | +| Root semantic closure | Codex supervisor + existing non-Claude lanes | current root session | TypeScript/API, JSR, and architecture verdicts `PASS`; pushed as `d28d8e779`. | +| Final evaluator/refiner | Native Claude Code · Fable 5 · high | `3517a6d2-b0b5-47ec-a207-b3533657a90c` | Starting commit `a7a6887c2`; verdict **`PASS`**; one example refinement; gate `cc90ead70` pushed. | Before commit `5dfc4e8eb`, root added three narrow corrections: runtime consumes the compiled `DatabaseManifest`, not `DatabaseDefinition`; the authority table distinguishes each artifact and value's role; and `partial-success` requires mixed successful and unsuccessful target outcomes. The later author/editor and root closure passes resolved all blocker/high findings without changing the -package graph. The phase is `final-verification`; length is not an acceptance gate. +package graph. The phase is `closed — final gate passed`; length is not an acceptance gate. + +Root independently verified the final route from the native stream receipt: systemd unit +`netscript-db-rfc-final-fable-20260815` exited with `Result=success` and status 0; the stream +reports model `claude-fable-5`, session `3517a6d2-b0b5-47ec-a207-b3533657a90c`, terminal reason +`completed`, and no permission denials. Receipt SHA-256 is +`9939f19d8c66981eadb2589ffdce0f2a3025f24e92ebfb5982a6f24d115cdff3`. At gate close, local, remote, +and live draft PR #1640 all resolved gate head `cc90ead7047a6f071c239c305619ac1ed77f2dae`; later +root-only terminal bookkeeping does not alter the RFC. The Qwen focused review passed architecture/type model, Standard Schema boundary, control/recovery, migration/plugin safety, and market/upstream claims. Its QF-01–QF-05 findings are dispositioned in @@ -122,7 +130,7 @@ descriptor couples both evidence tracks to canonical runtime snapshot identities that the catalog is current. Use the existing bounded OpenCode/OpenRouter runner with model `openrouter/x-ai/grok-4.6` and variant `high`, record requested/observed identity and raw receipt, and run it after the focused Qwen review. That Grok route completed; the later planned Fable route - was cancelled by owner supersession. + was temporarily cancelled, then explicitly reinstated once and completed at `cc90ead70`. - The completed Grok route requested and observed `x-ai/grok-4.6`, variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, with no subagents and no edits. It evaluated RFC commit `5dfc4e8eb` / blob `f46040d8...` at HEAD `be83301c6` and returned `PASS_WITH_REFINEMENTS` with @@ -143,13 +151,14 @@ descriptor couples both evidence tracks to canonical runtime snapshot identities establish the exact upstream state and derive candidate end-to-end NetScript type flows before plan lock; the Opus synthesis brief now requires this subsystem explicitly. - Historical sequence: root personal review → Qwen 3.8 Max focused review → Grok 4.6 high whole-RFC - adversarial review → Opus author/editor dispositions. The owner then superseded the planned Fable - step; root plus the three existing non-Claude lanes closed semantics before mechanical checks. + adversarial review → Opus author/editor dispositions. The owner temporarily cancelled the planned + Fable step; root plus the three existing non-Claude lanes closed semantics before the owner later + reinstated and completed exactly one final Fable gate. - After PLAN-EVAL cycle 2 and the frozen Qwen/Grok review inputs, the owner issued `OWNER-DX-01`. The override changes D-07/D-08/D-36 only: progressive NetScript adoption layers are required, only a mirrored Prisma model/field/relation/query DSL is forbidden, and erased source-native app inference replaces universal generated declarations. It triggered no further PLAN-EVAL. The completed author/editor/root passes selected the API and proved the fallback boundary. -- Latest owner supersession: RFC length is not an acceptance gate, and all further Claude usage is - stopped. Completed Claude outputs remain provenance only. No Claude or Fable session may be - launched or resumed; final closure uses root judgment and the already-running non-Claude lanes. +- Terminal owner supersession: RFC length is not an acceptance gate. Exactly one fresh final Fable 5 + high session was reinstated over the earlier freeze and has completed; no additional Claude or + Fable session may be launched or resumed. Only owner review of draft PR #1640 remains. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md index 29a3a3b6a4..5387dd3b88 100644 --- a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -6,7 +6,7 @@ | -------------- | ------------------------------------------------------------- | | Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | | Branch | `docs/database-architecture-rfc` | -| Phase | `final-verification` | +| Phase | `closed — final gate passed` | | Archetype | Docs-only RFC describing future A1/A2/A3/A4/A5/A6 surfaces | | Scope overlays | `SCOPE-docs.md`; future packages use their archetype matrices | @@ -20,12 +20,14 @@ Canonical RFC authorship is complete and no further PLAN-EVAL cycle is planned. owner issued `OWNER-DX-01`, overriding D-07/D-08/D-36 to require layered adoption and source-native app inference by default. The author/editor checkpoint landed at `ad8effff9`; root then closed the remaining semantic findings, and three non-Claude lanes passed the result at `d28d8e779`. The owner -removed the length target and stopped all further Claude/Fable usage. Only mechanical verification -and handoff remain; the exact six-package graph is unchanged. +removed the length target and temporarily stopped further Claude/Fable usage, then reinstated +exactly one fresh final Fable 5 high gate. Session `3517a6d2-b0b5-47ec-a207-b3533657a90c` returned +`PASS`, applied one narrow pgvector example repair, and pushed `cc90ead70`. The run is closed for +owner review; the exact six-package graph is unchanged. ### Public Surface and Package Graph -- Planned RFC record: `rfcs/0000-database-architecture.md`; its authorship is now unblocked. +- Canonical RFC record: `rfcs/0000-database-architecture.md`; its final substantive gate passed. - `@netscript/database-contract` (A1): plain identities, manifest/plan/receipt/diagnostic schemas, capabilities, ownership, and shared small SPIs; zero provider dependencies. - `@netscript/database` (A4): L1 preset/recipe, the L2 `defineDatabase`/target/space/policy @@ -151,28 +153,28 @@ and release exits recorded in `plan.md`. ## Progress Log -| Time | Slice | Step | Notes | -| ---------- | ----- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | -| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | -| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | -| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | -| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | -| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | -| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | -| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | -| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | -| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | -| 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | -| 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | -| 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | -| 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | -| 2026-08-13 | 6 | owner-dx | `OWNER-DX-01` audited shipped service/Hono preset→factory→native primitives, SDK/Fresh analogues, and Prisma's runtime `contractJson` plus phantom compile-time contract split. Owner overrode D-07/D-08/D-36 after PLAN-EVAL: source-native app inference is default; automatic declarations are a bounded W3 fallback. No new PLAN-EVAL. | -| 2026-08-13 | 6 | disposition | The author/editor pass resolved QF/GR and OWNER-DX-01 findings; root's correction pass was committed and pushed as `ad8effff9`. | -| 2026-08-13 | 7 | owner-gate | Owner removed word-count acceptance criteria and froze all further Claude/Fable usage. Existing completed sessions remain provenance only; no planned final Fable session ran. | -| 2026-08-13 | 7 | closure | Root corrected executable extension transport, canonical space/snapshot binding evidence, emit/load ordering, compile/emit authority, branded IDs, validation projection honesty, package aggregate transport, and retained rollback. TypeScript/API, prospective JSR, and architecture lanes all returned `PASS`; `d28d8e779` was pushed. | -| 2026-08-14 | 8 | owner-gate | Owner reinstated exactly one fresh native Fable 5 high final evaluator/refinement gate at 2026-08-15 00:00 Europe/Zurich. Unit `netscript-db-rfc-final-fable-20260815` uses the persisted fail-closed launcher and brief; no fallback, subagent, workflow, or other Claude route is authorized. | -| 2026-08-15 | 8 | final-gate | Fresh native Fable 5 high evaluator ran from starting commit `a7a6887c2` (= remote tip), read the complete RFC, run artifacts, three reviews, and three audits, re-verified the pinned RC1 claims (138 exports, phantom type maps, namespace flattening, demo helper spellings), applied one narrow example repair (`pgvector()` — extension-level `dimensions` removed as upstream-false), and returned **`PASS`** in `evaluate.md`. Docs gates green post-edit. | +| Time | Slice | Step | Notes | +| ---------- | ----- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | +| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | +| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | +| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | +| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | +| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | +| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | +| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | +| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | +| 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | +| 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | +| 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | +| 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | +| 2026-08-13 | 6 | owner-dx | `OWNER-DX-01` audited shipped service/Hono preset→factory→native primitives, SDK/Fresh analogues, and Prisma's runtime `contractJson` plus phantom compile-time contract split. Owner overrode D-07/D-08/D-36 after PLAN-EVAL: source-native app inference is default; automatic declarations are a bounded W3 fallback. No new PLAN-EVAL. | +| 2026-08-13 | 6 | disposition | The author/editor pass resolved QF/GR and OWNER-DX-01 findings; root's correction pass was committed and pushed as `ad8effff9`. | +| 2026-08-13 | 7 | owner-gate | Owner removed word-count acceptance criteria and froze all further Claude/Fable usage. Existing completed sessions remain provenance only; no planned final Fable session ran. | +| 2026-08-13 | 7 | closure | Root corrected executable extension transport, canonical space/snapshot binding evidence, emit/load ordering, compile/emit authority, branded IDs, validation projection honesty, package aggregate transport, and retained rollback. TypeScript/API, prospective JSR, and architecture lanes all returned `PASS`; `d28d8e779` was pushed. | +| 2026-08-14 | 8 | owner-gate | Owner reinstated exactly one fresh native Fable 5 high final evaluator/refinement gate at 2026-08-15 00:00 Europe/Zurich. Unit `netscript-db-rfc-final-fable-20260815` uses the persisted fail-closed launcher and brief; no fallback, subagent, workflow, or other Claude route is authorized. | +| 2026-08-15 | 8 | final-gate | Fresh native Fable 5 high session `3517a6d2-b0b5-47ec-a207-b3533657a90c` ran from starting commit `a7a6887c2` (= remote tip), read the complete RFC, run artifacts, three reviews, and three audits, re-verified the pinned RC1 claims (138 exports, phantom type maps, namespace flattening, demo helper spellings), applied one narrow example repair (`pgvector()` — extension-level `dimensions` removed as upstream-false), and returned **`PASS`** in `evaluate.md`. Gate `cc90ead70` is pushed; docs gates are green post-edit. | ### RFC Consolidation and Root Acceptance @@ -297,7 +299,7 @@ CI/gate-tooling drift that changes structured check invocation rather than datab | TypeScript/API closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Extension, binding, loading, branded ID, validation and examples closed. | | Prospective JSR closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Static aggregate module plus cold-remote/network-disabled gate closed the last high. | | Architecture closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | D-01–D-47, OWNER-DX-01, package graph and four prior findings closed. | -| Final Fable evaluator | PASS | `evaluate.md`; starting commit `a7a6887c2` | Fresh native Fable 5 high, 2026-08-15; one narrow example refinement, gates green. | +| Final Fable evaluator | PASS | `evaluate.md`; session `3517a6d2-b0b5-47ec-a207-b3533657a90c` | Starting commit `a7a6887c2`; gate `cc90ead70`; one narrow refinement; gates green. | ### Runtime Gates