Skip to content

TML-2727: migrate migration aggregate to elementCoordinates#629

Merged
wmadden merged 19 commits into
mainfrom
tml-2727-s1d-migration-coordinates
May 30, 2026
Merged

TML-2727: migrate migration aggregate to elementCoordinates#629
wmadden merged 19 commits into
mainfrom
tml-2727-s1d-migration-coordinates

Conversation

@wmadden
Copy link
Copy Markdown
Contributor

@wmadden wmadden commented May 29, 2026

Linked issue

Refs TML-2727 — closes TML-2580.

Parallel to S1.D-1/-2 + S1.E — disjoint files.

Summary

The migration aggregate still walked storage entities via the name-only extractStorageElementNames duck-typing helper. This PR completes PDoD6's migration consumer by routing every caller through elementCoordinates(storage) via a migration-internal storageElementNames wrapper. Output-preserving: no on-disk contract shape change, no migration-behaviour change.

Spec: projects/contract-ir-planes/slices/migration-element-coordinates/spec.md

At a glance

for (const coordinate of elementCoordinates(
  blindCast<Storage, 'Loader-boundary contract storage is Storage-shaped'>(storage),
)) {
  names.add(coordinate.entityName);
}

Call sites in loader.ts, verifier.ts, and project-schema-to-space.ts now import storageElementNames instead of the deleted helper.

Type-gap resolution

Contract.storage is typed as StorageBase (hash only); elementCoordinates expects framework Storage. Closed inside the migration package with a runtime hasNamespaceMap guard plus a single blindCast at the helper boundary — no exported public type was widened.

Grep gate

rg 'extractStorageElementNames' packages/
# → zero hits (exit 1)

Testing performed

Gate Command Result
Build cascade pnpm --filter @prisma-next/framework-components build && pnpm --filter @prisma-next/migration-tools build pass
Typecheck pnpm typecheck pass
Migration unit tests pnpm --filter @prisma-next/migration-tools test pass (528/528)
Package tests pnpm test:packages fail — environmental PG connection / timeout flakes (no @prisma-next/migration-tools failures)
Integration pnpm test:integration fail — environmental PG / timeout flakes (unrelated to this diff)
Fixtures pnpm fixtures:check pass — zero diff
Deps pnpm lint:deps pass

Skill update

n/a — internal only.

Checklist

  • All commits signed off (git commit -s).
  • Scoped to one logical concern (migration consumer swap + helper delete).
  • Tests updated (memberWithCollections now uses namespace-scoped storage, matching on-disk shape).
  • PR title uses TML-2727: prefix.
  • Skill update section filled in.

Notes for the reviewer

Refusal trigger did not fire — the StorageBase/Storage gap closed without loosening any exported type beyond the migration package.

Summary by CodeRabbit

  • Refactor

    • Simplified internal storage schema handling by updating how storage element names are derived.
    • Updated storage interface to include namespace topology structure.
  • New Features

    • Added new type exports: StorageEntitySlot, StorageNamespaceTopology, and StorageTopology for enhanced storage schema type coverage.

Review Change Stack

wmadden added 3 commits May 29, 2026 15:21
The granular S1.D ticket (TML-2625) was canceled and archived in the
2026-05-20 ticket cleanup; recreated as TML-2727 (the single live S1.D
ticket). Also: the subsumed cleanup tickets (TML-2579/2580/2582/2545/
2563) are already Canceled, so PDoD10 needs no close-out dispatch \u2014 mark
it satisfied in the coverage map.

Signed-off-by: Will Madden <madden@prisma.io>
…efer structural items

A 2026-05-29 inventory falsified S1.D as one deletions-only slice: three of
the eight subsumed surfaces carry structural prerequisites (a contract.json-
shape coordinate change, a hash-computation change, a query-builder type
rewrite). Per the narrow-and-defer decision, S1.D ships the three clean deletes
now as independent parallel slices (construction-discipline shims, canonicalizer
family hook, migration -> elementCoordinates) and defers the three structural
items to follow-ups recorded in deferred.md.

Amends PDoD5/PDoD10 to scope the deferred items out; restructures the plan
composition into parallel groups (no stack); adds the three lean slice specs.

Signed-off-by: Will Madden <madden@prisma.io>
Replace extractStorageElementNames with a migration-internal
storageElementNames helper that delegates to elementCoordinates.
Close the StorageBase/Storage gap at the helper boundary with a
runtime namespace guard and blindCast — no exported type widening.

Refs: TML-2727
Closes: TML-2580
Signed-off-by: Will Madden <madden@prisma.io>
@wmadden wmadden requested a review from a team as a code owner May 29, 2026 14:46
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR removes the extractStorageElementNames helper and replaces it with namespace-topology-aware storage element enumeration via elementCoordinates. Foundation types model the new storage structure, IR components adopt those types, callers switch to the new enumeration approach, and test fixtures align to include namespace topology in storage objects.

Changes

Storage Namespace Topology Refactoring

Layer / File(s) Summary
Foundation storage topology types
packages/1-framework/0-foundation/contract/src/types.ts, packages/1-framework/0-foundation/contract/src/exports/types.ts
Adds StorageEntitySlot, StorageNamespaceTopology, and StorageTopology types to model namespace topology. Updates StorageBase to extend StorageTopology, requiring all storage blocks to carry the namespaces structure alongside storageHash.
IR namespace and storage topology integration
packages/1-framework/1-core/framework-components/src/ir/namespace.ts, packages/1-framework/1-core/framework-components/src/ir/storage.ts, packages/1-framework/1-core/framework-components/test/element-coordinates.test.ts
Namespace interface now extends StorageNamespaceTopology instead of declaring id directly. elementCoordinates parameter type changes from framework-local Storage to foundation StorageTopology. Test assertions on Storage type are removed.
Migration aggregate callers: storage element enumeration
packages/1-framework/3-tooling/migration/src/aggregate/check-integrity.ts, packages/1-framework/3-tooling/migration/src/aggregate/project-schema-to-space.ts, packages/1-framework/3-tooling/migration/src/aggregate/verifier.ts
Replaces extractStorageElementNames imports and calls with elementCoordinates across three callers. Each now iterates entityName values from elementCoordinates(contract.storage) instead of calling the removed helper.
Foundation contract test fixtures
packages/1-framework/0-foundation/contract/test/contract-factories.test.ts, packages/1-framework/0-foundation/contract/test/contract-types.test-d.ts, packages/1-framework/0-foundation/contract/test/contract-types.test.ts, packages/1-framework/0-foundation/contract/test/canonicalization.test.ts
Updates contract factory test to use createSqlContract. Test helper minimal() and multiple canonicalization, contract-types, and type-level test cases now include storage.namespaces: {} alongside storageHash.
CLI and migration test mocks
packages/1-framework/3-tooling/cli/test/control-api/contract-enrichment.test.ts, packages/1-framework/3-tooling/migration/test/aggregate/project-schema-to-space.test.ts
CLI IR builder makeIR includes storage.namespaces: {}. Migration test helpers refactored: memberWithTables uses createSqlContract; memberWithCollections places Mongo collections under storage.namespaces[UNBOUND_NAMESPACE_ID] with namespace id and kind.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • prisma/prisma-next#552: Main PR updates migration aggregation logic to enumerate storage entities via elementCoordinates instead of the removed extractStorageElementNames, which directly depends on that PR's elementCoordinates/storage-walk substrate changes.
  • prisma/prisma-next#534: Both PRs are tightly related to the same migration-aggregate per-namespace storage work: the retrieved PR evolves extract-storage-element-names/verifier to understand storage.namespaces, while the main PR removes that helper and updates aggregate logic to enumerate claimed storage elements via elementCoordinates instead.
  • prisma/prisma-next#630: Main PR's migration tooling changes to enumerate storage entities via elementCoordinates(contract.storage) are directly connected to PR #630's removal of namespace-construction shims and enforcement of fully-built storage.namespaces, which determines the shape that elementCoordinates traverses.

Poem

🐰 A rabbit hops through namespace rows,
Storage topology now in tow—
Elements enumerated with grace,
Each one dancing in its place!
Old helpers gone, new paths aglow.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: migrating the migration aggregate module to use elementCoordinates instead of extractStorageElementNames.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2727-s1d-migration-coordinates

Comment @coderabbitai help to get the list of available commands and usage tips.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 29, 2026

Open in StackBlitz

@prisma-next/extension-author-tools

npm i https://pkg.pr.new/@prisma-next/extension-author-tools@629

@prisma-next/mongo-runtime

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

@prisma-next/family-mongo

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

@prisma-next/sql-runtime

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

@prisma-next/family-sql

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

@prisma-next/extension-arktype-json

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

@prisma-next/extension-cipherstash

npm i https://pkg.pr.new/@prisma-next/extension-cipherstash@629

@prisma-next/middleware-cache

npm i https://pkg.pr.new/@prisma-next/middleware-cache@629

@prisma-next/mongo

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

@prisma-next/extension-paradedb

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

@prisma-next/extension-pgvector

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

@prisma-next/extension-postgis

npm i https://pkg.pr.new/@prisma-next/extension-postgis@629

@prisma-next/postgres

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

@prisma-next/sql-orm-client

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

@prisma-next/sqlite

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

@prisma-next/target-mongo

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

@prisma-next/adapter-mongo

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

@prisma-next/driver-mongo

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

@prisma-next/contract

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

@prisma-next/utils

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

@prisma-next/config

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

@prisma-next/errors

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

@prisma-next/framework-components

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

@prisma-next/operations

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

@prisma-next/ts-render

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

@prisma-next/contract-authoring

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

@prisma-next/ids

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

@prisma-next/psl-parser

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

@prisma-next/psl-printer

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

@prisma-next/cli

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

@prisma-next/cli-telemetry

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

@prisma-next/emitter

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

@prisma-next/migration-tools

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

prisma-next

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

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

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

@prisma-next/mongo-codec

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

@prisma-next/mongo-contract

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

@prisma-next/mongo-value

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

@prisma-next/mongo-contract-psl

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

@prisma-next/mongo-contract-ts

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

@prisma-next/mongo-emitter

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

@prisma-next/mongo-schema-ir

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

@prisma-next/mongo-query-ast

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

@prisma-next/mongo-orm

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

@prisma-next/mongo-query-builder

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

@prisma-next/mongo-lowering

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

@prisma-next/mongo-wire

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

@prisma-next/sql-contract

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

@prisma-next/sql-errors

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

@prisma-next/sql-operations

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

@prisma-next/sql-schema-ir

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

@prisma-next/sql-contract-psl

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

@prisma-next/sql-contract-ts

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

@prisma-next/sql-contract-emitter

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

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

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

@prisma-next/sql-relational-core

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

@prisma-next/sql-builder

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

@prisma-next/target-postgres

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

@prisma-next/target-sqlite

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

@prisma-next/adapter-postgres

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

@prisma-next/adapter-sqlite

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

@prisma-next/driver-postgres

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

@prisma-next/driver-sqlite

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

commit: 8025eb8

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In
`@packages/1-framework/3-tooling/migration/src/aggregate/storage-element-names.ts`:
- Line 16: The code uses unsafe "as" casts for (contract as Contract).storage
and (storage as { readonly namespaces?: unknown }).namespaces; replace these
with proper type-narrowing: add or use a type guard (e.g., isContract or
predicate) to assert contract is a Contract before accessing storage, and
check/storage-narrow the storage shape (e.g., typeof/Array/isObject checks or an
isStorageWithNamespaces predicate) before reading namespaces so you can avoid
casting; update the references around the storage variable and the namespaces
access to use the guard-validated types instead of bare "as" casts.
- Around line 27-33: The type guard hasNamespaceMap currently only verifies that
storage.namespaces is a non-null non-array object, but elementCoordinates uses
Object.entries(ns) and will crash if any namespace value is null; update
hasNamespaceMap to also validate that every value in (storage as { readonly
namespaces?: unknown }).namespaces is itself a non-null object and not an array
(e.g., iterate Object.values(namespaces) and ensure each value passes typeof ===
'object' && value !== null && !Array.isArray(value)) so the guard guarantees
safe iteration in elementCoordinates and related code paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: f1203d71-e757-4d62-bf8b-1448f1c3dc5b

📥 Commits

Reviewing files that changed from the base of the PR and between f849c28 and ba8e451.

⛔ Files ignored due to path filters (6)
  • projects/contract-ir-planes/deferred.md is excluded by !projects/**
  • projects/contract-ir-planes/plan.md is excluded by !projects/**
  • projects/contract-ir-planes/slices/canonicalizer-family-hook/spec.md is excluded by !projects/**
  • projects/contract-ir-planes/slices/construction-discipline-shims/spec.md is excluded by !projects/**
  • projects/contract-ir-planes/slices/migration-element-coordinates/spec.md is excluded by !projects/**
  • projects/contract-ir-planes/spec.md is excluded by !projects/**
📒 Files selected for processing (6)
  • packages/1-framework/3-tooling/migration/src/aggregate/extract-storage-element-names.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/loader.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/project-schema-to-space.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/storage-element-names.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/verifier.ts
  • packages/1-framework/3-tooling/migration/test/aggregate/project-schema-to-space.test.ts
💤 Files with no reviewable changes (1)
  • packages/1-framework/3-tooling/migration/src/aggregate/extract-storage-element-names.ts

Comment thread packages/1-framework/3-tooling/migration/src/aggregate/storage-element-names.ts Outdated
Comment thread packages/1-framework/3-tooling/migration/src/aggregate/storage-element-names.ts Outdated
wmadden added 3 commits May 29, 2026 16:58
The lint:no-contract-cast guardrail flags `as Contract` as a
serializer-seam bypass. Type the helper parameter as Contract (all
callers pass member.contract) and narrow storage to Storage via an
in-narrowing type predicate, removing both the as Contract cast and
the blindCast at the walk boundary. Zero casts; behaviour unchanged.

Refs: TML-2727
Signed-off-by: Will Madden <madden@prisma.io>
elementCoordinates walks each namespace via Object.entries(ns), which
throws on a null value. The deleted name-only helper tolerated such
malformed input by skipping it. Restore that no-throw guarantee:
hasNamespaceMap now requires every namespace entry to be a non-null
object. Add a regression case to the malformed-storage projection test.

Refs: TML-2727
Signed-off-by: Will Madden <madden@prisma.io>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 29, 2026

size-limit report 📦

Path Size
postgres / no-emit 135.35 KB (0%)
postgres / emit 125.15 KB (0%)
mongo / no-emit 73.85 KB (0%)
mongo / emit 68.85 KB (0%)

Comment thread packages/1-framework/3-tooling/migration/src/aggregate/storage-element-names.ts Outdated
Comment thread packages/1-framework/3-tooling/migration/src/aggregate/storage-element-names.ts Outdated
wmadden and others added 9 commits May 30, 2026 16:22
…ype-bridge

Reviewer questioned the defensiveness in storage-element-names.ts. Record the
two actions: drop the per-entry null sweep (impossible input for a typed
Contract; elementCoordinates already skips null slots) and reframe the guard as
a foundation/core layering type-bridge rather than malformed-input defence.

Signed-off-by: Will Madden <madden@prisma.io>
Resolve add/add conflicts in contract-ir-planes slice specs by
keeping this branch's migration-element-coordinates Round 2 review
section and main's construction-discipline-shims Round 2 section.

Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
Drop the per-entry null sweep and reframe the guard as a foundation/
core layering type-bridge. Remove the impossible-input test case for
null namespace values.

Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
Operator pulled the structural fix into the slice: the duck-typing bridge is a
known layering violation (foundation lacks a typed primitive for storage
topology). Supersede the Round-2 bridge with a topology lift — StorageBase
carries a plain namespaces shape, core Storage/Namespace refine it, the
migration walk goes through contract.storage with no narrowing. Decompose into
D1 (substrate, green workspace) and D2 (delete the duck-typing).

Signed-off-by: Will Madden <madden@prisma.io>
Declare plain-data StorageTopology on StorageBase so hydrated contracts
statically carry namespaces; core Storage/Namespace refine the shape and
elementCoordinates walks StorageTopology without casts. Align test/fixture
construction sites with required namespaces; migration duck-typing unchanged.

Signed-off-by: Will Madden <madden@prisma.io>
Take main's tolerant aggregate loader and member.contract() API; keep
D1 storageElementNames bridge in check-integrity, verifier, and
project-schema-to-space until D2 removes duck-typing.

Signed-off-by: Will Madden <madden@prisma.io>
…ft breaks downstream source

The StorageBase topology lift is a public-type change; if keeping the
workspace green forces edits to examples/**/src or packages/3-extensions/**/src,
that is a consumer-facing breaking change that needs a record-upgrade-instructions
entry. Frames it as a conditional done-condition + D1 watch note, and is explicit
that framework/family-only fan-out needs no entry (no no-op changes:[] placeholders).

Signed-off-by: Will Madden <madden@prisma.io>
Delete the StorageBase→Storage bridge and call elementCoordinates on
contract.storage directly in aggregate disjointness, verifier, and
schema projection. Output-preserving for hydrated contracts.

Signed-off-by: Will Madden <madden@prisma.io>
…n-coordinates

Signed-off-by: Will Madden <madden@prisma.io>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

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

⚠️ Outside diff range comments (1)
packages/1-framework/3-tooling/migration/src/aggregate/check-integrity.ts (1)

219-223: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Dedup entityName per member when building elementClaimedBy to avoid spurious disjointness violations

contractViolations iterates elementCoordinates(contract.storage), which yields one coordinate per (namespaceId, entityKind, entityName), but elementClaimedBy is keyed only by entityName and blindly pushes member.spaceId for every coordinate. If a single member’s storage contains the same entityName in multiple namespaces / entityKinds, claimedBy.length becomes > 1 even though only one spaceId should be counted, producing a false-positive disjointness violation.

This is a behavior change from the removed extractStorageElementNames helper, which returned a deduplicated Set<string> of names.

🐛 Proposed fix: collapse names per member before recording claimers
-    for (const { entityName: elementName } of elementCoordinates(contract.storage)) {
-      const claimers = elementClaimedBy.get(elementName);
-      if (claimers) claimers.push(member.spaceId);
-      else elementClaimedBy.set(elementName, [member.spaceId]);
-    }
+    const memberElementNames = new Set<string>();
+    for (const { entityName } of elementCoordinates(contract.storage)) {
+      memberElementNames.add(entityName);
+    }
+    for (const elementName of memberElementNames) {
+      const claimers = elementClaimedBy.get(elementName);
+      if (claimers) claimers.push(member.spaceId);
+      else elementClaimedBy.set(elementName, [member.spaceId]);
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/1-framework/3-tooling/migration/src/aggregate/check-integrity.ts`
around lines 219 - 223, The code that builds elementClaimedBy inside the loop
over elementCoordinates(contract.storage) pushes member.spaceId for every
coordinate, causing duplicate claims when the same entityName appears multiple
times per member; change the logic in the block that iterates
elementCoordinates(contract.storage) (used by contractViolations) to first
deduplicate entityName values per member (e.g., collect entityName into a Set
for this member or track seen names) and only record member.spaceId once per
unique entityName when updating elementClaimedBy, preserving the map key
(entityName) and values (array of spaceIds) semantics from the removed
extractStorageElementNames helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/1-framework/3-tooling/migration/src/aggregate/check-integrity.ts`:
- Around line 219-223: The code that builds elementClaimedBy inside the loop
over elementCoordinates(contract.storage) pushes member.spaceId for every
coordinate, causing duplicate claims when the same entityName appears multiple
times per member; change the logic in the block that iterates
elementCoordinates(contract.storage) (used by contractViolations) to first
deduplicate entityName values per member (e.g., collect entityName into a Set
for this member or track seen names) and only record member.spaceId once per
unique entityName when updating elementClaimedBy, preserving the map key
(entityName) and values (array of spaceIds) semantics from the removed
extractStorageElementNames helper.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 660fe619-c0cb-46b4-bc82-7262dc309955

📥 Commits

Reviewing files that changed from the base of the PR and between 4d83d2a and 8bff96d.

⛔ Files ignored due to path filters (1)
  • projects/contract-ir-planes/slices/migration-element-coordinates/spec.md is excluded by !projects/**
📒 Files selected for processing (4)
  • packages/1-framework/3-tooling/migration/src/aggregate/check-integrity.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/project-schema-to-space.ts
  • packages/1-framework/3-tooling/migration/src/aggregate/verifier.ts
  • packages/1-framework/3-tooling/migration/test/aggregate/project-schema-to-space.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/1-framework/3-tooling/migration/test/aggregate/project-schema-to-space.test.ts

wmadden added 3 commits May 30, 2026 19:00
Removing the hasNamespaceMap guard makes elementCoordinates require
storage.namespaces. CLI test mocks built minimal storage without it;
add namespaces: {} so they model a hydrated contract honestly and
yield zero coordinates (behaviour-preserving).

Signed-off-by: Will Madden <madden@prisma.io>
…torage types

Topology is an emergent property of these shapes, not the shapes
themselves. Rename StorageNamespaceTopology -> StorageNamespace and
fold StorageTopology's namespaces member into StorageBase directly.
elementCoordinates accepts Pick<StorageBase, 'namespaces'>. Pure
type-only rename; no envelope movement.

Signed-off-by: Will Madden <madden@prisma.io>
@wmadden wmadden merged commit c37feca into main May 30, 2026
21 checks passed
@wmadden wmadden deleted the tml-2727-s1d-migration-coordinates branch May 30, 2026 17:45
wmadden-electric added a commit that referenced this pull request May 30, 2026
…istory

Replace the three synthetic normal-shape golden cases with cases drawn
from real merged PRs, so the corpus measures Drive runs against work the
team actually shipped rather than synthesised tasks:

- direct-change-example-emit-outputpath (TML-2722 / #618)
- slice-dedupe-generated-imports (TML-2714 / #614)
- project-reap-subsumed-ir-surfaces (TML-2727 / #630, #631, #629) — a
  three-slice parallel fan-out that exercises planner parallelisation and
  scope discipline.

Each real case carries the task as posed (Linear ticket, solution-scrubbed
so the run still does the design/planning), a base_sha to run against, and
a reference.md describing the known-good output by commit SHA (the output
itself is fetchable via git diff <base_sha> <merge_sha>). case.json gains
source + base_sha; the loader ignores the extra fields until the
experiment-engine slice wires base_sha into a checkout.

The two pathological cases (i12-halt, spike-first) stay synthetic: no clean
merged PR exhibits a halted or spiked run.

Update harness tests, SKILL.md examples, and the corpus README for the
renamed slugs. validate-parser fixtures are left as-is — they are
synthetic parser fixtures with tuned event counts, not corpus members.

Signed-off-by: wmadden-electric <286902546+wmadden-electric@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants