Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ CLAUDE.local.md
# `scripts/sync-package-skills.ts` (run from their `prepack`). The
# canonical source of truth is `skills/` at the repository root.
packages/9-public/@prisma/*/skills/
packages/9-public/@prisma/*/skills.staging-*/
packages/9-public/@prisma/*/skills.trash-*/

# Per-machine install lockfile written by `skills add`. Local only;
# our canonical source is `skills-contrib/` (for contributors) and the
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ Just describe what you want. For example:

> *"Add a `posts` model with a relation to `users`, then write a query that loads each user's three most recent posts."*

The agent loads the `prisma-8` skill, opens its contract and queries references, then drives the change end-to-end.
The agent loads the `prisma-orm-core-concepts` skill, opens its contract and queries references, then drives the change end-to-end.

For the full catalogue and what each skill covers, see [`skills/README.md`](./skills/README.md).

## Found a bug, missing a feature, or have a question for the team?

Ask your agent. The `prisma-8` skill's feedback flow drafts a structured GitHub issue or hands you a Prisma Discord link for live Q&A. You can review and confirm before anything is submitted.
Ask your agent. The `prisma-orm-core-concepts` skill's feedback flow drafts a structured GitHub issue or hands you a Prisma Discord link for live Q&A. You can review and confirm before anything is submitted.

## For extension authors

Expand Down
4 changes: 2 additions & 2 deletions coverage.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
"package": "1-framework/0-foundation/contract",
"reason": "S1.C cross-reference encoding added CrossReference shape to Contract.roots and domain field support to canonicalization.ts. The new canonicalization branches (domain-plane key ordering, domain-unbound type params preservation) are exercised end-to-end through emit integration tests but fall ~2% below the 94% branch threshold. Direct canonicalization branch tests deferred to a follow-up slice.",
"addedDate": "2026-05-29",
"expiryDays": 90,
"expiryDays": 120,
"assignee": null,
"linear": "TML-2624",
"notes": "Recovery via dedicated canonicalization.ts branch tests covering the domain-plane ordering and typeParams preservation paths."
"notes": "Recovery via dedicated canonicalization.ts branch tests covering the domain-plane ordering and typeParams preservation paths. Renewed 2026-08-28 (expiryDays 90 -> 120): expired 2026-08-27 and turned the Test check red on every open PR; the aggregate gap is 93.75% vs 94% branches and the recovery above still applies (tracked on the entry's Linear issue)."
},
{
"package": "3-targets/3-targets/sqlite",
Expand Down
2 changes: 1 addition & 1 deletion docs/oss/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Every workspace package — publishable, private, the workspace root, and exampl

This invariant has consequences that ecosystem participants need to plan for:

- **Agent skills, the upgrade instructions, and any other tooling we ship alongside the framework version in lockstep with it.** A skill installed at the same time as `@internal/postgres@0.8.0` is a `0.8.0` skill and reasons about a `0.8.0` contract. There is no separate skill-version axis to track. This is now physical rather than conventional: the `prisma-8` skill ships inside the `@prisma/orm-postgres`, `@prisma/orm-sqlite` and `@prisma/orm-mongo` tarballs (copied in by each package's `prepack`), and `scripts/set-version.ts` stamps its `metadata.library_version` frontmatter with the version being published. Getting the skill and getting the code are one install, and a consumer can compare the stamp on its synced copy against its installed packages.
- **Agent skills, the upgrade instructions, and any other tooling we ship alongside the framework version in lockstep with it.** A skill installed at the same time as `@prisma/orm-postgres@0.8.0` is a `0.8.0` skill and reasons about a `0.8.0` contract. There is no separate skill-version axis to track. This is now physical rather than conventional: the `prisma-orm-core-concepts` and `prisma-orm-migrations` skills ship inside the `@prisma/orm-postgres`, `@prisma/orm-sqlite` and `@prisma/orm-mongo` tarballs (copied in by each package's `prepack`), and `scripts/set-version.ts` stamps each skill's `metadata.library_version` frontmatter with the version being published. Getting the skill and getting the code are one install, and a consumer can compare the stamp on its synced copy against its installed packages.
- **Extension authors that depend on internal framework packages must pin those dependencies to the framework version their consumers will use.** If your extension depends on `@internal/sql-core` (an internal framework package), publish each version of your extension targeting one specific Prisma Next minor and pin to it exactly (`"@internal/sql-core": "0.8.0"`, not `"^0.8.0"`). Internal packages do not promise inter-minor compatibility — `0.8.x` and `0.9.x` may have incompatible internals even when the user-visible surface looks similar. The extension's published version range communicates which framework minor it targets.
- **Internal packages are never published, but they still version in lockstep** so a contributor cloning the repo at any commit sees one consistent answer to "what version is this code?" The `private: true` flag means `pnpm publish` skips them.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"lint:docs": "node scripts/validate-package-readmes.mjs",
"lint:manifests": "node scripts/validate-package-manifests.mjs && node scripts/validate-typescript-peer.mjs",
"lint:workflows": "node scripts/lint-workflow-triggers.mjs",
"test:scripts": "node --test scripts/coverage-config.test.mjs scripts/coverage-report.test.mjs scripts/lint-workflow-triggers.test.mjs scripts/validate-skills.test.mjs scripts/determine-version-utils.test.ts scripts/check-upgrade-coverage.test.mjs scripts/check-release-notes.test.mjs scripts/set-version-utils.test.ts scripts/check-publish-deps.test.mjs scripts/check-conformance.test.mjs scripts/check-publish-deps-pn-pins.test.mjs scripts/check-publish-deps-declarations.test.mjs scripts/validate-package-manifests.test.mjs scripts/validate-package-readmes.test.mjs scripts/publish-packages-utils.test.mjs scripts/check-clean-tree.test.mjs scripts/lint-casts.test.mjs scripts/lint-throws.test.mjs scripts/list-error-codes.test.mjs scripts/lint-framework-vocabulary.test.mjs scripts/lint-single-import-root.test.mjs scripts/lint-legacy-name.test.mjs scripts/lint-consumer-internal-imports.test.mjs scripts/sync-agent-rules.test.mjs scripts/validate-typescript-peer.test.mjs scripts/run-logged.test.mjs scripts/migrate-migrations-layout.test.mjs skills-contrib/review-fetch-phase/scripts/render-review-state.test.mjs skills-contrib/review-triage-phase/scripts/render-review-actions.test.mjs",
"test:scripts": "node --test scripts/coverage-config.test.mjs scripts/sync-package-skills.test.mjs scripts/coverage-report.test.mjs scripts/lint-workflow-triggers.test.mjs scripts/validate-skills.test.mjs scripts/determine-version-utils.test.ts scripts/check-upgrade-coverage.test.mjs scripts/check-release-notes.test.mjs scripts/set-version-utils.test.ts scripts/check-publish-deps.test.mjs scripts/check-conformance.test.mjs scripts/check-publish-deps-pn-pins.test.mjs scripts/check-publish-deps-declarations.test.mjs scripts/validate-package-manifests.test.mjs scripts/validate-package-readmes.test.mjs scripts/publish-packages-utils.test.mjs scripts/check-clean-tree.test.mjs scripts/lint-casts.test.mjs scripts/lint-throws.test.mjs scripts/list-error-codes.test.mjs scripts/lint-framework-vocabulary.test.mjs scripts/lint-single-import-root.test.mjs scripts/lint-legacy-name.test.mjs scripts/lint-consumer-internal-imports.test.mjs scripts/sync-agent-rules.test.mjs scripts/validate-typescript-peer.test.mjs scripts/run-logged.test.mjs scripts/migrate-migrations-layout.test.mjs skills-contrib/review-fetch-phase/scripts/render-review-state.test.mjs skills-contrib/review-triage-phase/scripts/render-review-actions.test.mjs",
"bump-version": "node scripts/bump-version.ts",
"check:publish-deps": "node scripts/check-publish-deps.mjs",
"check:conformance": "node scripts/check-conformance.mjs",
Expand Down
6 changes: 3 additions & 3 deletions packages/0-shared/extension-author-tools/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# @internal/extension-author-tools

CLI tools that pair with the extension-upgrade branch of the [`prisma-8`](../../../skills/prisma-8/references/upgrade-extension.md) agent skill. Today this package ships one tool; future tools for extension authors using the upgrade-skill flow will land here.
CLI tools that pair with the extension-upgrade branch of the [`prisma-orm-core-concepts`](../../../skills/prisma-orm-core-concepts/references/upgrade-extension.md) agent skill. Today this package ships one tool; future tools for extension authors using the upgrade-skill flow will land here.

The agent-readable upgrade procedure itself (the flow in [`references/upgrade-extension.md`](../../../skills/prisma-8/references/upgrade-extension.md) and the `upgrades/<from>-to-<to>/instructions.md` set under [`upgrading/extension/`](../../../skills/prisma-8/upgrading/extension/)) ships inside the `@prisma/orm-*` tarballs. This package is the npm-published companion that supplies the CI bin the skill drives.
The agent-readable upgrade procedure itself (the flow in [`references/upgrade-extension.md`](../../../skills/prisma-orm-core-concepts/references/upgrade-extension.md) and the `upgrades/<from>-to-<to>/instructions.md` set under [`upgrading/extension/`](../../../skills/prisma-orm-core-concepts/upgrading/extension/)) ships inside the `@prisma/orm-*` tarballs. This package is the npm-published companion that supplies the CI bin the skill drives.

## Installation

Expand All @@ -18,7 +18,7 @@ npm install --save-dev @internal/extension-author-tools

CI guard for extension packages. Asserts that every `@internal/*` entry under the package's `peerDependencies` (and, optionally, `dependencies`) is pinned to an exact version, not a range.

This is the invariant the [extension-upgrade flow](../../../skills/prisma-8/references/upgrade-extension.md) relies on at upgrade time: extension authors pin every `@internal/*` peer to a single exact version per release of their extension, so the skill can mechanically advance both the framework deps and the extension's published version in lockstep.
This is the invariant the [extension-upgrade flow](../../../skills/prisma-orm-core-concepts/references/upgrade-extension.md) relies on at upgrade time: extension authors pin every `@internal/*` peer to a single exact version per release of their extension, so the skill can mechanically advance both the framework deps and the extension's published version in lockstep.

Run from the extension's repository root:

Expand Down
61 changes: 32 additions & 29 deletions packages/0-shared/publish-surface/test/package-skills.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* The `prisma-8` agent skill ships inside the tarball of every package an
* application depends on directly, so the skill a user has always describes
* The Prisma Next agent skills (`prisma-orm-core-concepts`,
* `prisma-orm-migrations`) ship inside the tarball of every package an
* application depends on directly, so the skills a user has always describe
* the version they installed.
*
* That claim is only worth as much as the artifact that proves it, and every
Expand All @@ -26,7 +27,7 @@ import { publicShells, type ShellName } from '../src/shells';

const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..', '..');
const facades: ShellName[] = ['@prisma/orm-postgres', '@prisma/orm-sqlite', '@prisma/orm-mongo'];
const SKILL_NAME = 'prisma-8';
const SKILL_NAMES = ['prisma-orm-core-concepts', 'prisma-orm-migrations'] as const;

interface Manifest {
readonly version: string;
Expand Down Expand Up @@ -93,10 +94,10 @@ function packAndUnpack(facade: ShellName): string {
return join(work, 'package');
}

describe('the skill source in the repository', () => {
it('carries the stamp the version sweep maintains', () => {
describe('the skill sources in the repository', () => {
it.each(SKILL_NAMES)('%s carries the stamp the version sweep maintains', (skillName) => {
const rootVersion = manifestAt(repoRoot).version;
const source = readFileSync(join(repoRoot, 'skills', SKILL_NAME, 'SKILL.md'), 'utf8');
const source = readFileSync(join(repoRoot, 'skills', skillName, 'SKILL.md'), 'utf8');
expect(metadataValue(source, 'library_version')).toBe(rootVersion);
});
});
Expand All @@ -112,30 +113,32 @@ describe.each(facades)('%s', (facade) => {
);
});

it('carries the whole skill tree in its tarball, stamped with what shipped it', () => {
it('carries every skill tree in its tarball, stamped with what shipped it', () => {
const packedRoot = packAndUnpack(facade);
const packedSkillDir = join(packedRoot, 'skills', SKILL_NAME);

expect(
existsSync(join(packedSkillDir, 'SKILL.md')),
`the ${facade} tarball has no skills/${SKILL_NAME}/SKILL.md`,
).toBe(true);

const packedSkill = readFileSync(join(packedSkillDir, 'SKILL.md'), 'utf8');
expect(metadataValue(packedSkill, 'library')).toBe(facade);
expect(metadataValue(packedSkill, 'library_version')).toBe(manifestAt(packedRoot).version);

// The tarball and the repository's tracked tree must serve the same
// instructions: the only difference is the package each copy names.
const sourceDir = join(repoRoot, 'skills', SKILL_NAME);
expect(filesUnder(packedSkillDir)).toEqual(filesUnder(sourceDir));
for (const file of filesUnder(sourceDir)) {
if (file === 'SKILL.md') continue;
expect(readFileSync(join(packedSkillDir, file), 'utf8')).toBe(
readFileSync(join(sourceDir, file), 'utf8'),
);
for (const skillName of SKILL_NAMES) {
const packedSkillDir = join(packedRoot, 'skills', skillName);

expect(
existsSync(join(packedSkillDir, 'SKILL.md')),
`the ${facade} tarball has no skills/${skillName}/SKILL.md`,
).toBe(true);

const packedSkill = readFileSync(join(packedSkillDir, 'SKILL.md'), 'utf8');
expect(metadataValue(packedSkill, 'library')).toBe(facade);
expect(metadataValue(packedSkill, 'library_version')).toBe(manifestAt(packedRoot).version);

// The tarball and the repository's tracked tree must serve the same
// instructions: the only difference is the package each copy names.
const sourceDir = join(repoRoot, 'skills', skillName);
expect(filesUnder(packedSkillDir)).toEqual(filesUnder(sourceDir));
for (const file of filesUnder(sourceDir)) {
if (file === 'SKILL.md') continue;
expect(readFileSync(join(packedSkillDir, file), 'utf8')).toBe(
readFileSync(join(sourceDir, file), 'utf8'),
);
}
const sourceSkill = readFileSync(join(sourceDir, 'SKILL.md'), 'utf8');
expect(packedSkill).toBe(sourceSkill.replace(/^(\s+)library:.*$/m, `$1library: '${facade}'`));
}
const sourceSkill = readFileSync(join(sourceDir, 'SKILL.md'), 'utf8');
expect(packedSkill).toBe(sourceSkill.replace(/^(\s+)library:.*$/m, `$1library: '${facade}'`));
}, 60_000);
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// The agent skills ship inside the packages they describe — the `prisma-8`
// skill travels in the `@prisma/orm-*` tarball a project installs — so init
// no longer fetches or installs them from anywhere. Skills setup belongs to
// The agent skills ship inside the packages they describe — the
// `prisma-orm-*` skills travel in the `@prisma/orm-*` tarball a project
// installs — so init no longer fetches or installs them from anywhere. Skills setup belongs to
// the family-level `prisma init` command; the only skill work left in
// `orm init` is deleting the retired directories below.

Expand All @@ -9,17 +9,19 @@
// -------------------------------------------------------------------

/**
* Skill directories that predate the consolidated `prisma-8` skill: the
* per-workflow usage cluster (including the renamed
* `prisma-8-migration-review` spelling it briefly shipped under), the
* pre-rename spellings of the consolidated skill and the extension-author
* upgrade skill, any hand-rolled `prisma-next` stub, and the two standalone
* upgrade skills that folded into the `prisma-8` router. Projects initialised
* before those changes carry these as sibling directories in each agent's
* install root; left in place they compete with the current skill for
* activation, so init removes them on every run.
* Skill directories that predate the current `prisma-orm-*` skill set: the
* consolidated `prisma-8` router it replaced, the per-workflow usage cluster
* that preceded the router (including the renamed `prisma-8-migration-review`
* spelling it briefly shipped under), the pre-rename spellings of the
* consolidated skill and the extension-author upgrade skill, any hand-rolled
* `prisma-next` stub, and the two standalone upgrade skills that folded into
* the `prisma-8` router. Projects initialised before those changes carry
* these as sibling directories in each agent's install root; left in place
* they compete with the current skills for activation, so init removes them
* on every run.
*/
export const RETIRED_SKILL_NAMES = [
'prisma-8',
'prisma-next',
'prisma-next-quickstart',
'prisma-next-contract',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ describe('legacy skill cleanup', () => {
expect(RETIRED_SKILL_NAMES).toContain('prisma-8-extension-upgrade');
});

it('retires the consolidated router the prisma-orm-* skills replaced', () => {
expect(RETIRED_SKILL_NAMES).toContain('prisma-8');
});

it('names one directory per harness root and retired skill', () => {
const dirs = legacySkillDirs();
expect(dirs).toHaveLength(AGENT_SKILL_ROOTS.length * RETIRED_SKILL_NAMES.length);
expect(dirs).toContain('.cursor/skills/prisma-next-upgrade');
expect(dirs).not.toContain('.claude/skills/prisma-8');
expect(dirs).toContain('.claude/skills/prisma-8');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ describe('init scaffold', () => {

expect(run.exitCode).toBe(0);
expect(manifest.scripts?.postinstall).toBeUndefined();
expect(gitignore).not.toContain('skills/prisma-8/');
expect(gitignore).not.toContain('skills/prisma-');
},
timeouts.coldTransformImport,
);
Expand All @@ -175,7 +175,7 @@ describe('init scaffold', () => {
const retired = join(projectDir, '.claude/skills/prisma-next-queries');
mkdirSync(retired, { recursive: true });
writeFileSync(join(retired, 'SKILL.md'), '# stale\n', 'utf-8');
const installed = join(projectDir, '.agents/skills/prisma-8');
const installed = join(projectDir, '.agents/skills/prisma-orm-core-concepts');
mkdirSync(installed, { recursive: true });
writeFileSync(join(installed, 'SKILL.md'), '# installed\n', 'utf-8');

Expand Down
6 changes: 3 additions & 3 deletions scripts/check-upgrade-coverage.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ export function parseChangesFrontmatter(src) {
return { ok: false, reason: 'changes key absent' };
}

const USER_SKILL_PKG = 'skills/prisma-8/upgrading/app';
const EXT_SKILL_PKG = 'skills/prisma-8/upgrading/extension';
const USER_SKILL_PKG = 'skills/prisma-orm-core-concepts/upgrading/app';
const EXT_SKILL_PKG = 'skills/prisma-orm-core-concepts/upgrading/extension';

/**
* Substrates covered by the gate. Each entry pairs a diff pathspec
Expand Down Expand Up @@ -284,7 +284,7 @@ const TRANSITION_PATH = new RegExp(
* Parse a path under `<skill-pkg>/upgrades/<transition>/...` and return
* the transition segment, or null if the path does not match.
*
* Example: `skills/prisma-8/upgrading/app/upgrades/0.7-to-0.8/foo.ts`
* Example: `skills/prisma-orm-core-concepts/upgrading/app/upgrades/0.7-to-0.8/foo.ts`
* → `'0.7-to-0.8'`
*/
export function parseTransitionFromPath(path) {
Expand Down
Loading
Loading