Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .changeset/20646-cli-migrate-meta-migrations-entry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@objectstack/cli': patch
---

fix(cli): `os migrate meta` takes the migration chain from `@objectstack/spec/migrations` (#20646)

`@objectstack/spec` moved the ADR-0087 migration chain and change-manifest names (`applyMetaMigrations`, `composeSpecChanges`, `MigrationFloorError`, `MIGRATION_MAJORS`, `MIGRATION_SUPPORT_FLOOR`, …) off the package root into the new `@objectstack/spec/migrations` entry, so the command now imports them from there. It replays the same chain and prints the same guidance; nothing a user types or reads changes.
49 changes: 49 additions & 0 deletions .changeset/20646-migrations-entry-split.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
'@objectstack/spec': minor
---

feat(spec)!: the ADR-0087 migration chain leaves the package root for the new `@objectstack/spec/migrations` entry (#20646)

**BREAKING** — the migration chain and change-manifest names (ADR-0087 D3/D4), with their types, are no longer exported from the package root `@objectstack/spec`. They are exported, unchanged, from the new entry `@objectstack/spec/migrations`.

A `major`-class change — an existing import path stops resolving for these names — recorded as `minor` under the launch-window convention.

**Why.** The migration registry is mostly the guidance text `objectstack migrate meta` prints, and the root re-exported it. The registry does work when its module loads (the list of majors and each step's rationale are computed then), so no bundler could prove it unused, and all of that text rode in every bundle of the root, whatever the consumer imported. This is the source-side payback of the Studio console's first-screen ceiling raise that the maintainer ruled on the 17.5.0 upgrade. Measured on the splitting PR against its merge base `1a75e39d4a` (tsup build, gzip -9):

| | before | after |
| --- | --- | --- |
| `dist/index.js` (CommonJS root) | 3,780,033 B / 1,067,061 B gzip | 2,009,810 B / 565,386 B gzip |
| `dist/browser/index.mjs` (the ESM root a browser bundler pulls) | 3,764,293 B / 1,065,388 B gzip | 1,994,748 B / 563,787 B gzip |
| a browser bundle of the ten names the Studio console imports from the root (rolldown, minified) | 700,884 B gzip | 301,287 B gzip |

The ADR-0087 **conversion layer stays on the root**: `defineStack` and `normalizeStackInput` read it at run time, so its names (`ALL_CONVERSIONS`, `CONVERSIONS_BY_MAJOR`, `applyConversions`, `applyConversionsToFlow`, `applyConversionsToStoredItem`, `collectConversionNotices`, the `CONVERSION_*_CODE` constants and their types) import from `@objectstack/spec` exactly as before.

### FROM → TO

| removed from `@objectstack/spec` | import instead from |
| --- | --- |
| `MIGRATIONS_BY_MAJOR`, `MIGRATION_MAJORS`, `MIGRATION_SUPPORT_FLOOR` | `@objectstack/spec/migrations` |
| `RETIRED_KEYS_BY_MAJOR`, `RETIRED_DEFS_BY_MAJOR` | `@objectstack/spec/migrations` |
| `applyMetaMigrations`, `composeMigrationChain`, `MigrationFloorError` | `@objectstack/spec/migrations` |
| `composeSpecChanges`, `composeReleaseChanges` | `@objectstack/spec/migrations` |
| `SpecChangesSchema`, `SpecConvertedSchema`, `SpecMigratedSchema`, `SpecSurfaceAddSchema`, `SpecSurfaceRemoveSchema`, `SpecReleaseChangesSchema`, `SpecReleaseSurfaceSchema` | `@objectstack/spec/migrations` |
| types `MigrationStep`, `MigrationApplication`, `MigrationChainResult`, `MigrationHopResult`, `MigrationTodo`, `SemanticMigration`, `SpecChanges`, `SpecConverted`, `SpecMigrated`, `SpecSurfaceAdd`, `SpecSurfaceRemove`, `SpecReleaseChanges`, `SpecReleaseSurface`, `SurfaceDiff`, `ReleaseSurfaceDiff`, `PreviousReleaseRegistries` | `@objectstack/spec/migrations` |

**The one-line fix: change the import path.**

```ts
// before
import { applyMetaMigrations, MIGRATION_SUPPORT_FLOOR } from '@objectstack/spec';
// after
import { applyMetaMigrations, MIGRATION_SUPPORT_FLOOR } from '@objectstack/spec/migrations';
```

The compiler finds every site: `TS2305` ("Module '"@objectstack/spec"' has no exported member …"); at run time the binding is `undefined`. Nothing else changes: the chain, its steps and semantic entries, the retired-key and retired-def tables and the change-manifest schemas are the same objects, and `objectstack migrate meta` replays the same chain.

⚠️ **Out-of-repo consumers are NOT MEASURED beyond objectui.** Inside this repository the moved names had five importers — `os migrate meta` (the only runtime one) and four tests — all moved in the same PR. objectui at the pinned `.objectui-sha` imports none of the moved names from anywhere. The `cloud` repository was not measured.

The ADR-0087 D3 semantic entry `migrations-entry-split` carries the judgement: an import path is TypeScript source, not metadata, so there is no source a D2 conversion could rewrite.

Clause-②: yes (narrowing)

<!-- adr-0087: registered migrations-entry-split -->
2 changes: 1 addition & 1 deletion content/docs/deployment/troubleshooting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ import { FieldSchema } from '@objectstack/spec/data';
import { ErrorResponseSchema } from '@objectstack/spec/api';
```

Available subpaths (the `./*` entries of the package's `exports` map, in its order): `data`, `system`, `kernel`, `ai`, `automation`, `api`, `api-assembled`, `ui`, `contracts`, `integration`, `security`, `studio`, `marketplace`, `qa`, `identity`, `shared`, `meta-spelling`.
Available subpaths (the `./*` entries of the package's `exports` map, in its order): `data`, `system`, `kernel`, `ai`, `automation`, `api`, `api-assembled`, `ui`, `contracts`, `integration`, `security`, `studio`, `marketplace`, `qa`, `identity`, `shared`, `meta-spelling`, `migrations`.

---

Expand Down
6 changes: 2 additions & 4 deletions packages/cli/src/commands/migrate/meta.report-order.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,13 @@

import { stripVTControlCharacters } from 'node:util';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { ObjectStackDefinitionSchema, formatZodIssue, normalizeStackInput } from '@objectstack/spec';
import {
ObjectStackDefinitionSchema,
applyMetaMigrations,
formatZodIssue,
normalizeStackInput,
MIGRATION_MAJORS,
MIGRATION_SUPPORT_FLOOR,
type MigrationChainResult,
} from '@objectstack/spec';
} from '@objectstack/spec/migrations';
import { PROTOCOL_MAJOR } from '@objectstack/spec/kernel';
import { printMigrationReport, type MigrationReport } from './meta.js';

Expand Down
6 changes: 2 additions & 4 deletions packages/cli/src/commands/migrate/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ import { writeFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { createInterface } from 'node:readline';
import chalk from 'chalk';
import { ObjectStackDefinitionSchema, formatZodIssue, normalizeStackInput } from '@objectstack/spec';
import {
ObjectStackDefinitionSchema,
applyMetaMigrations,
composeSpecChanges,
formatZodIssue,
normalizeStackInput,
MigrationFloorError,
MIGRATION_MAJORS,
MIGRATION_SUPPORT_FLOOR,
type MigrationChainResult,
} from '@objectstack/spec';
} from '@objectstack/spec/migrations';
import { PROTOCOL_MAJOR, PROTOCOL_VERSION } from '@objectstack/spec/kernel';
import { FILE_REFERENCE_TYPES, REFERENCE_VALUE_TYPES, STRUCTURED_JSON_TYPES } from '@objectstack/spec/data';
import { FILE_REFERENCES_MIGRATION_ID, VALUE_SHAPES_MIGRATION_ID } from '@objectstack/spec/system';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/migrate-meta-default-range.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { MIGRATIONS_BY_MAJOR, MIGRATION_MAJORS, MIGRATION_SUPPORT_FLOOR } from '@objectstack/spec';
import { MIGRATIONS_BY_MAJOR, MIGRATION_MAJORS, MIGRATION_SUPPORT_FLOOR } from '@objectstack/spec/migrations';
import { PROTOCOL_MAJOR } from '@objectstack/spec/kernel';
import { childEnv } from './helpers/serve-process.js';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/migrate-meta-engine-guidance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { MIGRATIONS_BY_MAJOR, MIGRATION_SUPPORT_FLOOR } from '@objectstack/spec';
import { MIGRATIONS_BY_MAJOR, MIGRATION_SUPPORT_FLOOR } from '@objectstack/spec/migrations';
import { childEnv } from './helpers/serve-process.js';

const execFileP = promisify(execFile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { describe, expect, it } from 'vitest';
// of this package's (file, verb) pairs sat in the gate's DEBT ledger until
// #5619 sank the two predicates into a package both sides already depend on.
import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core';
import { applyMetaMigrations } from '@objectstack/spec';
import { applyMetaMigrations } from '@objectstack/spec/migrations';
import { ObjectStackProtocolImplementation } from './protocol.js';
import {
DECISION_MODE_REVIEW_CONVERSION_ID,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { describe, it, expect, beforeEach } from 'vitest';
import { ALL_CONVERSIONS, applyMetaMigrations } from '@objectstack/spec';
import { ALL_CONVERSIONS } from '@objectstack/spec';
import { applyMetaMigrations } from '@objectstack/spec/migrations';
import { AutomationEngine } from '../engine.js';
import { registerLogicNodes } from './logic-nodes.js';

Expand Down
39 changes: 39 additions & 0 deletions packages/spec/api-surface/migrations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"description": "Every exported `name (kind)` of one published entry point of @objectstack/spec — the breadth half of the ADR-0059 backward-compatibility gate. Sharded by entry point (#5837) so two PRs touching different entry points never share a file. Reads the BUILT dist/*.d.ts: regenerate with `pnpm --filter @objectstack/spec gen:api-surface` after a real build.",
"entry": "./migrations",
"exports": [
"MIGRATIONS_BY_MAJOR (const)",
"MIGRATION_MAJORS (const)",
"MIGRATION_SUPPORT_FLOOR (const)",
"MigrationApplication (interface)",
"MigrationChainResult (interface)",
"MigrationFloorError (class)",
"MigrationHopResult (interface)",
"MigrationStep (interface)",
"MigrationTodo (interface)",
"PreviousReleaseRegistries (interface)",
"RETIRED_DEFS_BY_MAJOR (const)",
"RETIRED_KEYS_BY_MAJOR (const)",
"ReleaseSurfaceDiff (interface)",
"SemanticMigration (interface)",
"SpecChanges (type)",
"SpecChangesSchema (const)",
"SpecConverted (type)",
"SpecConvertedSchema (const)",
"SpecMigrated (type)",
"SpecMigratedSchema (const)",
"SpecReleaseChanges (type)",
"SpecReleaseChangesSchema (const)",
"SpecReleaseSurface (type)",
"SpecReleaseSurfaceSchema (const)",
"SpecSurfaceAdd (type)",
"SpecSurfaceAddSchema (const)",
"SpecSurfaceRemove (type)",
"SpecSurfaceRemoveSchema (const)",
"SurfaceDiff (interface)",
"applyMetaMigrations (function)",
"composeMigrationChain (function)",
"composeReleaseChanges (function)",
"composeSpecChanges (function)"
]
}
33 changes: 0 additions & 33 deletions packages/spec/api-surface/root.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,9 @@
"MEMBERSHIP_ROLE_MEMBER (const)",
"MEMBERSHIP_ROLE_OWNER (const)",
"METADATA_ALIASES (const)",
"MIGRATIONS_BY_MAJOR (const)",
"MIGRATION_MAJORS (const)",
"MIGRATION_SUPPORT_FLOOR (const)",
"MapSupportedField (type)",
"MetadataCollectionInput (type)",
"MetadataConversion (type)",
"MigrationApplication (interface)",
"MigrationChainResult (interface)",
"MigrationFloorError (class)",
"MigrationHopResult (interface)",
"MigrationStep (interface)",
"MigrationTodo (interface)",
"NavigationItem (type)",
"NavigationItemInput (type)",
"NormalizeStackInputOptions (interface)",
Expand All @@ -133,50 +124,26 @@
"PredicateInput (type)",
"PredicateInputSchema (const)",
"PredicateSchema (const)",
"PreviousReleaseRegistries (interface)",
"RETIRED_DEFS_BY_MAJOR (const)",
"RETIRED_KEYS_BY_MAJOR (const)",
"RecordStagePackageBody (type)",
"RecordStagePackageBodyParsed (type)",
"RecordStagePackageBodySchema (const)",
"ReleaseSurfaceDiff (interface)",
"STACK_DEFINITION_KEYS (const)",
"STACK_KEY_GUIDANCE (const)",
"STACK_RUNTIME_MEMBERS (const)",
"SemanticMigration (interface)",
"Skill (type)",
"SpecChanges (type)",
"SpecChangesSchema (const)",
"SpecConverted (type)",
"SpecConvertedSchema (const)",
"SpecMigrated (type)",
"SpecMigratedSchema (const)",
"SpecReleaseChanges (type)",
"SpecReleaseChangesSchema (const)",
"SpecReleaseSurface (type)",
"SpecReleaseSurfaceSchema (const)",
"SpecSurfaceAdd (type)",
"SpecSurfaceAddSchema (const)",
"SpecSurfaceRemove (type)",
"SpecSurfaceRemoveSchema (const)",
"StackDefinitionKey (type)",
"StateNodeConfig (type)",
"StoredConversionOptions (type)",
"SurfaceDiff (interface)",
"TemplateExpressionInputSchema (const)",
"Tool (type)",
"UnknownAuthoringKeyFinding (interface)",
"ViewKeyCollision (interface)",
"applyConversions (function)",
"applyConversionsToFlow (function)",
"applyConversionsToStoredItem (function)",
"applyMetaMigrations (function)",
"cel (function)",
"classifyRequiredCapability (function)",
"collectConversionNotices (function)",
"composeMigrationChain (function)",
"composeReleaseChanges (function)",
"composeSpecChanges (function)",
"composeStacks (function)",
"createEvalUser (function)",
"cron (function)",
Expand Down
1 change: 1 addition & 0 deletions packages/spec/browser-reachable-entries.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"./integration",
"./kernel",
"./marketplace",
"./migrations",
"./qa",
"./security",
"./shared",
Expand Down
39 changes: 39 additions & 0 deletions packages/spec/export-origins/migrations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"description": "Which SOURCE DECLARATION each name exported by one public entry point of @objectstack/spec resolves to, after its alias chain is unwound: `<src path>#<declared name> (<kind>)`. Two exports share an origin string iff they are the same declaration — so equal origins across two entries are a harmless re-export, and different origins under one name are the #4411 dual-source trap. Generated from src/ (no build needed) and read by the export-surface pin tests, which compare against it instead of each building their own ts.createProgram — that was ~55s of compilation per CI lap and a non-deterministic timeout that ejected unrelated PRs from the merge queue (#4796). Sharded by entry point (#5837) so two retirement PRs never share a file. Carries NO line numbers: the pins asserted the line as `\\d+`, and recording it would rewrite this artifact on every edit that shifts a line in any .zod.ts. Regenerate with `pnpm --filter @objectstack/spec gen:export-origins` and read the diff.",
"entry": "./migrations",
"exports": {
"MIGRATIONS_BY_MAJOR": "src/migrations/registry.ts#MIGRATIONS_BY_MAJOR (const)",
"MIGRATION_MAJORS": "src/migrations/registry.ts#MIGRATION_MAJORS (const)",
"MIGRATION_SUPPORT_FLOOR": "src/migrations/registry.ts#MIGRATION_SUPPORT_FLOOR (const)",
"MigrationApplication": "src/migrations/types.ts#MigrationApplication (interface)",
"MigrationChainResult": "src/migrations/types.ts#MigrationChainResult (interface)",
"MigrationFloorError": "src/migrations/chain.ts#MigrationFloorError (class)",
"MigrationHopResult": "src/migrations/types.ts#MigrationHopResult (interface)",
"MigrationStep": "src/migrations/types.ts#MigrationStep (interface)",
"MigrationTodo": "src/migrations/types.ts#MigrationTodo (interface)",
"PreviousReleaseRegistries": "src/migrations/spec-changes.ts#PreviousReleaseRegistries (interface)",
"RETIRED_DEFS_BY_MAJOR": "src/migrations/registry.ts#RETIRED_DEFS_BY_MAJOR (const)",
"RETIRED_KEYS_BY_MAJOR": "src/migrations/registry.ts#RETIRED_KEYS_BY_MAJOR (const)",
"ReleaseSurfaceDiff": "src/migrations/spec-changes.ts#ReleaseSurfaceDiff (interface)",
"SemanticMigration": "src/migrations/types.ts#SemanticMigration (interface)",
"SpecChanges": "src/migrations/spec-changes.ts#SpecChanges (type)",
"SpecChangesSchema": "src/migrations/spec-changes.ts#SpecChangesSchema (const)",
"SpecConverted": "src/migrations/spec-changes.ts#SpecConverted (type)",
"SpecConvertedSchema": "src/migrations/spec-changes.ts#SpecConvertedSchema (const)",
"SpecMigrated": "src/migrations/spec-changes.ts#SpecMigrated (type)",
"SpecMigratedSchema": "src/migrations/spec-changes.ts#SpecMigratedSchema (const)",
"SpecReleaseChanges": "src/migrations/spec-changes.ts#SpecReleaseChanges (type)",
"SpecReleaseChangesSchema": "src/migrations/spec-changes.ts#SpecReleaseChangesSchema (const)",
"SpecReleaseSurface": "src/migrations/spec-changes.ts#SpecReleaseSurface (type)",
"SpecReleaseSurfaceSchema": "src/migrations/spec-changes.ts#SpecReleaseSurfaceSchema (const)",
"SpecSurfaceAdd": "src/migrations/spec-changes.ts#SpecSurfaceAdd (type)",
"SpecSurfaceAddSchema": "src/migrations/spec-changes.ts#SpecSurfaceAddSchema (const)",
"SpecSurfaceRemove": "src/migrations/spec-changes.ts#SpecSurfaceRemove (type)",
"SpecSurfaceRemoveSchema": "src/migrations/spec-changes.ts#SpecSurfaceRemoveSchema (const)",
"SurfaceDiff": "src/migrations/spec-changes.ts#SurfaceDiff (interface)",
"applyMetaMigrations": "src/migrations/chain.ts#applyMetaMigrations (function)",
"composeMigrationChain": "src/migrations/chain.ts#composeMigrationChain (function)",
"composeReleaseChanges": "src/migrations/spec-changes.ts#composeReleaseChanges (function)",
"composeSpecChanges": "src/migrations/spec-changes.ts#composeSpecChanges (function)"
}
}
Loading
Loading