You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TML-2500(M1): slice spec + plan amendment for disjointness reconciliation
Record Decision D-recon (fix disjointness namespace-awareness, remove namespaceOwnershipCollision) and the walking-skeleton obligation (FK deferred to M2/M3).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Will Madden <madden@prisma.io>
-**Transitive auto-loading of unlisted contract spaces.** M1.2 builds the dependency graph + cycle detection over the descriptor set the app lists in `extensionPacks`, with edges from each pack's declared `extensionPacks`, and errors on a declared-but-absent dependency. Auto-discovering and loading a pack the app did **not** list (via an extension's bundled `extensionPacks`) is deferred — it requires a `spaceId → descriptor` resolution mechanism not present today. Additive when needed.
-**Outcome:** make `main`'s `disjointness` check **namespace-aware** and **remove our duplicate `namespaceOwnershipCollision`** entirely. After this, one correct cross-space ownership check exists.
63
+
-**Fix `disjointness`** (`packages/1-framework/3-tooling/migration/src/aggregate/check-integrity.ts`~`contractViolations`, lines ~230–246): key `elementClaimedBy` on the full `(namespaceId, entityKind, entityName)` coordinate (all already yielded by `elementCoordinates`), not bare `entityName`. The `disjointness` violation's `element` becomes the qualified coordinate string (`claimedBy` shape unchanged). Update consumers' display strings (`contract-space-aggregate-loader.ts`, cli `integrity-violation-to-check-failure.ts`) and the assertion in `loader.test.ts` (~:366, `'user'` → qualified form).
64
+
-**Remove `namespaceOwnershipCollision`:** the IntegrityViolation kind (`integrity-violation.ts:67–73` + JSDoc); `findNamespaceOwnershipCollisions` + `NamespaceCollision*` types (`control-stack.ts:382–459`) + their `exports/control.ts` re-exports; the call + helper in `check-integrity.ts` (line 118 + `namespaceOwnershipCollisionViolations` 261–286 + import); the cli case `PN-MIG-CHECK-017` (`integrity-violation-to-check-failure.ts:138–145`); the `migration-check.ts:384` filter entry; and the tests (`control-stack.test.ts:730–784`, `check-integrity.test.ts:78–118`).
65
+
-**Migrate test coverage to `disjointness`:** add tests proving (a) same name in **different** namespaces across spaces → **no** collision (the `auth.users` vs `public.users` case — the false-positive we're fixing); (b) same `(namespace, kind, name)` across two spaces → collision naming both contributors; through the real load path.
66
+
-**Validation gate (expanded — closes the babysit gaps):** the touched packages' tests + `pnpm typecheck` + `pnpm lint:deps` + `pnpm lint:casts` AND **full `pnpm lint`** (`biome check --error-on-warnings`) AND **`pnpm fixtures:check`** AND the **`examples/supabase` skeleton test** — the last three were the gaps CI caught during babysit. Rebuild dependent `dist` before downstream tests.
67
+
-**dispatch-INVEST:** one logical change (make the check correct, drop the duplicate); Small-ish (mostly deletions + one keying fix + test migration).
68
+
69
+
### Dispatch M1.6 — Walking-skeleton verification + FK-deferral record
70
+
71
+
> **Resolution (2026-06-06): no code dispatch needed.** M1.5's review confirmed the skeleton requires **no M1 change** (the cross-contract FK genuinely needs M2 authoring + M3 planner/verifier), and `examples/supabase/test/skeleton.integration.test.ts`'s JSDoc already frames "later constituents extend in place." So M1.6 is satisfied by: (a) the **PR #745 description** recording that the `Profile.userId → auth.User.id` FK + cascade DoD is deferred to M2/M3, and (b) **CI** verifying the skeleton stays green against M1's reconciled checks (it couldn't be run locally — `examples/supabase` deps aren't installed in this worktree subtree). No implementer dispatch was spawned.
72
+
73
+
-**Outcome:** confirm the `examples/supabase` skeleton integration test is green against M1 (post-M1.5), and **record that the cross-contract FK + cascade-delete DoD is deferred to M2 (authoring) + M3 (planner/verifier)** — not achievable in M1 (no authoring surface). No change to the skeleton's app contract / migration artefacts.
74
+
-**Where the record lands:** the skeleton test's JSDoc (already frames "later constituents extend in place" — make the M1-vs-M2/M3 boundary explicit) and the PR #745 walking-skeleton note.
75
+
-**Validation gate:**`examples/supabase` test green; `pnpm fixtures:check` clean (the skeleton emits `migrations/supabase/*`).
76
+
-**dispatch-INVEST:** verification + docs; no production code change.
77
+
78
+
## Revised slice DoD (supersedes the above for the amended scope)
79
+
80
+
- AC6 delivered via the **namespace-aware `disjointness`** (cycle + reverse-ref + collision); `namespaceOwnershipCollision` removed; AC8/AC10 green; AC9 regression.
81
+
-`examples/supabase` skeleton green against M1; FK-step deferral to M2/M3 recorded.
82
+
- Full `pnpm lint` + `pnpm fixtures:check` + skeleton test added to the slice's standing gate (babysit lesson).
-**FK reference carrier** — `ForeignKeyReference` carries an optional `spaceId`; its presence discriminates a cross-space target from a local one (absent = local). Local FKs serialize byte-identically (NFR2). (M1.1, simplified in M1.4 — `origin` discriminator dropped per operator decision.)
10
+
-**Cross-space dependency graph + cycle rejection** — `buildExtensionLoadOrder` (framework-components), edges from each pack's declared `extensionPacks`, errors on an unlisted declared dependency, rejects cycles (FR12/FR13). The computed order is applied when assembling the control stack (review fix A-001).
11
+
-**Reverse-reference rejection** — `assertNoCrossSpaceFkReverseReferences` (SQL family) rejects an extension FK pointing against the dependency arrows (FR14).
12
+
-**Namespace-ownership collision detection** — *(superseded — see amendment below)*.
13
+
14
+
## Amendment (2026-06-06): reconcile with main's `disjointness`; update the merged walking skeleton
15
+
16
+
Merging latest `main` brought in two relevant landings (#719 Mongo marker/ledger — orthogonal; and PR#746 — the `@prisma-next/supabase` extension + the `examples/supabase`**walking skeleton**) and surfaced a redundancy + latent bug in how cross-space primitive ownership is checked.
`main` already has a `disjointness` integrity check (`PN-MIG-CHECK-014`, in `packages/1-framework/3-tooling/migration/src/aggregate/check-integrity.ts`) that detects "a storage element claimed by multiple contract spaces" using the canonical `elementCoordinates(storage)` walker — **but it keys on bare `entityName`**, discarding namespace + kind. That is namespace-blind: it would **falsely flag `auth.users` (supabase space) and `public.users` (app space)** — same name, different namespaces — as a collision. That multi-namespace same-name scenario is exactly what this project enables, so our feature turns a latent `disjointness` bug into a live one.
21
+
22
+
Our M1.3 `namespaceOwnershipCollision` (`PN-MIG-CHECK-017`) is the namespace-aware version (keys on `namespace:kind:name`), but it **duplicates the concern** with a bespoke walk in a different package — the very "hand-walk an untyped structure instead of the typed/canonical path" pattern that #719 spent a PR eliminating elsewhere.
23
+
24
+
**Resolution:** make `disjointness` namespace-aware (key on the full `(namespaceId, entityKind, entityName)` coordinate that `elementCoordinates` already yields) and **remove our `namespaceOwnershipCollision` entirely** — after the fix the two are exact duplicates, and `disjointness` is the incumbent broadly consumed by `db-init` / `db-run` / `db-verify` / `migration-check`. AC6's collision half is then delivered by the fixed `disjointness`, not a separate new check. This is preferred over removing `disjointness` (which would mean re-threading the refusal chain through many consumers).
25
+
26
+
### Walking-skeleton obligation (revised for M1's level)
27
+
28
+
`examples/supabase` (landed on `main`) composes the app space (`public.Profile`) + the `@prisma-next/supabase` extension space (`auth.*`, `storage.*`, external) via `extensionPacks`, and its integration test runs `db init` / `db verify` — which now execute our aggregate-integrity checks. The project's full walking-skeleton DoD (add `Profile.userId → auth.User.id` cross-contract FK + cascade test, planner emits qualified `REFERENCES "auth"."users"`) **requires M2 (authoring surface) + M3 (planner/verifier) and is NOT achievable in M1** (no way to author the cross-space FK yet). M1's obligation is narrower: **the skeleton stays green against M1's checks** (including the reconciled `disjointness`), and the deferral of the FK step to M2/M3 is recorded.
0 commit comments