@prisma-next/cli 0.12.0-dev.9 → 0.13.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +2 -2
  2. package/dist/cli.mjs +180 -163
  3. package/dist/cli.mjs.map +1 -1
  4. package/dist/{client-KgJorIvG.mjs → client-CJzuo5wX.mjs} +222 -107
  5. package/dist/client-CJzuo5wX.mjs.map +1 -0
  6. package/dist/{command-helpers-Bbw1GbwL.mjs → command-helpers-DGMvGBeX.mjs} +318 -25
  7. package/dist/command-helpers-DGMvGBeX.mjs.map +1 -0
  8. package/dist/commands/contract-emit.d.mts.map +1 -1
  9. package/dist/commands/contract-emit.mjs +1 -1
  10. package/dist/commands/contract-infer.d.mts.map +1 -1
  11. package/dist/commands/contract-infer.mjs +1 -1
  12. package/dist/commands/db-init.d.mts.map +1 -1
  13. package/dist/commands/db-init.mjs +4 -5
  14. package/dist/commands/db-init.mjs.map +1 -1
  15. package/dist/commands/db-schema.d.mts.map +1 -1
  16. package/dist/commands/db-schema.mjs +3 -3
  17. package/dist/commands/db-schema.mjs.map +1 -1
  18. package/dist/commands/db-sign.d.mts.map +1 -1
  19. package/dist/commands/db-sign.mjs +6 -6
  20. package/dist/commands/db-sign.mjs.map +1 -1
  21. package/dist/commands/db-update.d.mts.map +1 -1
  22. package/dist/commands/db-update.mjs +10 -7
  23. package/dist/commands/db-update.mjs.map +1 -1
  24. package/dist/commands/db-verify.d.mts.map +1 -1
  25. package/dist/commands/db-verify.mjs +1 -1
  26. package/dist/commands/migrate.d.mts +37 -3
  27. package/dist/commands/migrate.d.mts.map +1 -1
  28. package/dist/commands/migrate.mjs +298 -12
  29. package/dist/commands/migrate.mjs.map +1 -1
  30. package/dist/commands/migration-check.d.mts +55 -13
  31. package/dist/commands/migration-check.d.mts.map +1 -1
  32. package/dist/commands/migration-check.mjs +3 -2
  33. package/dist/commands/migration-graph.d.mts +16 -25
  34. package/dist/commands/migration-graph.d.mts.map +1 -1
  35. package/dist/commands/migration-graph.mjs +185 -2
  36. package/dist/commands/migration-graph.mjs.map +1 -0
  37. package/dist/commands/migration-list.d.mts +26 -27
  38. package/dist/commands/migration-list.d.mts.map +1 -1
  39. package/dist/commands/migration-list.mjs +2 -190
  40. package/dist/commands/migration-log.d.mts +9 -19
  41. package/dist/commands/migration-log.d.mts.map +1 -1
  42. package/dist/commands/migration-log.mjs +1 -137
  43. package/dist/commands/migration-new.d.mts.map +1 -1
  44. package/dist/commands/migration-new.mjs +6 -5
  45. package/dist/commands/migration-new.mjs.map +1 -1
  46. package/dist/commands/migration-plan.d.mts +1 -1
  47. package/dist/commands/migration-plan.d.mts.map +1 -1
  48. package/dist/commands/migration-plan.mjs +1 -1
  49. package/dist/commands/migration-show.d.mts +17 -21
  50. package/dist/commands/migration-show.d.mts.map +1 -1
  51. package/dist/commands/migration-show.mjs +24 -36
  52. package/dist/commands/migration-show.mjs.map +1 -1
  53. package/dist/commands/migration-status.d.mts +42 -144
  54. package/dist/commands/migration-status.d.mts.map +1 -1
  55. package/dist/commands/migration-status.mjs +3 -759
  56. package/dist/commands/ref.d.mts +1 -1
  57. package/dist/commands/ref.d.mts.map +1 -1
  58. package/dist/commands/ref.mjs +4 -4
  59. package/dist/commands/ref.mjs.map +1 -1
  60. package/dist/commands/telemetry/index.d.mts +7 -0
  61. package/dist/commands/telemetry/index.d.mts.map +1 -0
  62. package/dist/commands/telemetry/index.mjs +2 -0
  63. package/dist/{config-loader-B6sJjXTv.mjs → config-loader-p9JMrekQ.mjs} +1 -1
  64. package/dist/{config-loader-B6sJjXTv.mjs.map → config-loader-p9JMrekQ.mjs.map} +1 -1
  65. package/dist/config-loader.mjs +1 -1
  66. package/dist/{contract-at-errors-BxP-TOMl.mjs → contract-at-errors-CFXsstzm.mjs} +2 -2
  67. package/dist/{contract-at-errors-BxP-TOMl.mjs.map → contract-at-errors-CFXsstzm.mjs.map} +1 -1
  68. package/dist/{contract-emit-DxcGl4Uq.mjs → contract-emit-B_qriF8B.mjs} +5 -5
  69. package/dist/{contract-emit-DxcGl4Uq.mjs.map → contract-emit-B_qriF8B.mjs.map} +1 -1
  70. package/dist/{contract-emit-D-4jrNve.mjs → contract-emit-C8HmtboH.mjs} +12 -7
  71. package/dist/contract-emit-C8HmtboH.mjs.map +1 -0
  72. package/dist/{contract-enrichment-a0V5Y_mL.mjs → contract-enrichment-gn9sWbPw.mjs} +1 -1
  73. package/dist/{contract-enrichment-a0V5Y_mL.mjs.map → contract-enrichment-gn9sWbPw.mjs.map} +1 -1
  74. package/dist/{contract-infer-D8uEbJuu.mjs → contract-infer-BYT_ra_U.mjs} +5 -5
  75. package/dist/contract-infer-BYT_ra_U.mjs.map +1 -0
  76. package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs → contract-space-aggregate-loader-ClI1KN6d.mjs} +5 -5
  77. package/dist/{contract-space-aggregate-loader-DvZwdkrr.mjs.map → contract-space-aggregate-loader-ClI1KN6d.mjs.map} +1 -1
  78. package/dist/{db-verify-v_vUKXTU.mjs → db-verify-C24FKhb7.mjs} +6 -6
  79. package/dist/{db-verify-v_vUKXTU.mjs.map → db-verify-C24FKhb7.mjs.map} +1 -1
  80. package/dist/exports/control-api.d.mts +5 -3
  81. package/dist/exports/control-api.d.mts.map +1 -1
  82. package/dist/exports/control-api.mjs +3 -3
  83. package/dist/exports/index.mjs +1 -1
  84. package/dist/exports/index.mjs.map +1 -1
  85. package/dist/exports/init-output.d.mts +1 -3
  86. package/dist/exports/init-output.d.mts.map +1 -1
  87. package/dist/exports/init-output.mjs +1 -1
  88. package/dist/{extension-pack-inputs-IDvjRCi3.mjs → extension-pack-inputs-1ySHqxKG.mjs} +1 -1
  89. package/dist/{extension-pack-inputs-IDvjRCi3.mjs.map → extension-pack-inputs-1ySHqxKG.mjs.map} +1 -1
  90. package/dist/{framework-components-fYXjz_in.mjs → framework-components-YVQHhPH7.mjs} +2 -2
  91. package/dist/{framework-components-fYXjz_in.mjs.map → framework-components-YVQHhPH7.mjs.map} +1 -1
  92. package/dist/{global-flags-DEHjV8_s.d.mts → global-flags-BpoOYtNZ.d.mts} +1 -1
  93. package/dist/{global-flags-DEHjV8_s.d.mts.map → global-flags-BpoOYtNZ.d.mts.map} +1 -1
  94. package/dist/{init-Cv9UzWL5.mjs → init-0HwB-Vh8.mjs} +5 -58
  95. package/dist/init-0HwB-Vh8.mjs.map +1 -0
  96. package/dist/{inspect-live-schema-C6ohV_oQ.mjs → inspect-live-schema-DF6IwcDl.mjs} +7 -5
  97. package/dist/inspect-live-schema-DF6IwcDl.mjs.map +1 -0
  98. package/dist/migration-check-soB5uZEQ.mjs +573 -0
  99. package/dist/migration-check-soB5uZEQ.mjs.map +1 -0
  100. package/dist/migration-cli.mjs +1 -1
  101. package/dist/migration-cli.mjs.map +1 -1
  102. package/dist/{migration-command-scaffold-CjvwO6at.mjs → migration-command-scaffold-DA-Lhx6o.mjs} +5 -5
  103. package/dist/{migration-command-scaffold-CjvwO6at.mjs.map → migration-command-scaffold-DA-Lhx6o.mjs.map} +1 -1
  104. package/dist/migration-graph-command-render-CEez7YUK.mjs +1960 -0
  105. package/dist/migration-graph-command-render-CEez7YUK.mjs.map +1 -0
  106. package/dist/migration-list-DlJJ_38Z.mjs +230 -0
  107. package/dist/migration-list-DlJJ_38Z.mjs.map +1 -0
  108. package/dist/migration-log-CG0qQAFm.mjs +222 -0
  109. package/dist/migration-log-CG0qQAFm.mjs.map +1 -0
  110. package/dist/migration-path-target-Ce6OZImp.mjs +38 -0
  111. package/dist/migration-path-target-Ce6OZImp.mjs.map +1 -0
  112. package/dist/{migration-plan-9DJ7q7_z.mjs → migration-plan-z5Ing-TD.mjs} +9 -8
  113. package/dist/migration-plan-z5Ing-TD.mjs.map +1 -0
  114. package/dist/migration-status-CgWSoI_g.mjs +446 -0
  115. package/dist/migration-status-CgWSoI_g.mjs.map +1 -0
  116. package/dist/{output-B60Gw5fu.mjs → output-mEQ74_nd.mjs} +1 -1
  117. package/dist/{output-B60Gw5fu.mjs.map → output-mEQ74_nd.mjs.map} +1 -1
  118. package/dist/{progress-adapter-C644QK8l.mjs → progress-adapter-CjAeTxY_.mjs} +1 -1
  119. package/dist/{progress-adapter-C644QK8l.mjs.map → progress-adapter-CjAeTxY_.mjs.map} +1 -1
  120. package/dist/{ref-advancement-DUZqsue6.mjs → ref-advancement-BkXlikCA.mjs} +1 -1
  121. package/dist/{ref-advancement-DUZqsue6.mjs.map → ref-advancement-BkXlikCA.mjs.map} +1 -1
  122. package/dist/schemas-CeGMYFYX.d.mts +191 -0
  123. package/dist/schemas-CeGMYFYX.d.mts.map +1 -0
  124. package/dist/schemas-KhXMzNA_.mjs +112 -0
  125. package/dist/schemas-KhXMzNA_.mjs.map +1 -0
  126. package/dist/telemetry-BIM4beEO.mjs +122 -0
  127. package/dist/telemetry-BIM4beEO.mjs.map +1 -0
  128. package/dist/{terminal-ui-5Y6mrg93.d.mts → terminal-ui-DGRNFWna.d.mts} +1 -1
  129. package/dist/terminal-ui-DGRNFWna.d.mts.map +1 -0
  130. package/dist/{types-Dt_SfqFm.d.mts → types-C_tYiJYx.d.mts} +53 -31
  131. package/dist/types-C_tYiJYx.d.mts.map +1 -0
  132. package/dist/{verify-DCA9Sldu.mjs → verify-DcOYZ1tH.mjs} +2 -2
  133. package/dist/{verify-DCA9Sldu.mjs.map → verify-DcOYZ1tH.mjs.map} +1 -1
  134. package/package.json +26 -22
  135. package/src/cli.ts +5 -0
  136. package/src/commands/contract-infer.ts +2 -2
  137. package/src/commands/db-update.ts +7 -1
  138. package/src/commands/init/index.ts +6 -35
  139. package/src/commands/init/init.ts +1 -14
  140. package/src/commands/init/inputs.ts +0 -75
  141. package/src/commands/inspect-live-schema.ts +10 -0
  142. package/src/commands/json/schemas.ts +195 -0
  143. package/src/commands/migrate.ts +527 -8
  144. package/src/commands/migration-check.ts +469 -134
  145. package/src/commands/migration-graph.ts +151 -119
  146. package/src/commands/migration-list.ts +72 -39
  147. package/src/commands/migration-log.ts +52 -102
  148. package/src/commands/migration-new.ts +2 -1
  149. package/src/commands/migration-plan.ts +2 -1
  150. package/src/commands/migration-show.ts +31 -66
  151. package/src/commands/migration-status-overlay.ts +61 -0
  152. package/src/commands/migration-status.ts +458 -1066
  153. package/src/commands/telemetry/index.ts +107 -0
  154. package/src/commands/telemetry/status.ts +67 -0
  155. package/src/control-api/client.ts +70 -9
  156. package/src/control-api/operations/contract-emit.ts +22 -2
  157. package/src/control-api/operations/db-init.ts +6 -3
  158. package/src/control-api/operations/{db-apply.ts → db-run.ts} +55 -14
  159. package/src/control-api/operations/db-update.ts +7 -4
  160. package/src/control-api/operations/db-verify.ts +15 -5
  161. package/src/control-api/operations/{migration-apply.ts → migrate.ts} +181 -80
  162. package/src/control-api/operations/{apply.ts → run-migration.ts} +33 -27
  163. package/src/control-api/types.ts +56 -29
  164. package/src/utils/cli-errors.ts +70 -2
  165. package/src/utils/formatters/errors.ts +11 -0
  166. package/src/utils/formatters/migration-graph-command-render.ts +239 -0
  167. package/src/utils/formatters/migration-graph-grid-layout.ts +1134 -0
  168. package/src/utils/formatters/migration-graph-labels.ts +408 -0
  169. package/src/utils/formatters/migration-graph-model.ts +103 -0
  170. package/src/utils/formatters/migration-graph-occlusion-render.ts +258 -0
  171. package/src/utils/formatters/migration-graph-rows.ts +128 -15
  172. package/src/utils/formatters/migration-graph-space-render.ts +188 -0
  173. package/src/utils/formatters/migration-list-data-column.ts +4 -91
  174. package/src/utils/formatters/migration-list-graph-topology.ts +72 -94
  175. package/src/utils/formatters/migration-list-render.ts +135 -71
  176. package/src/utils/formatters/migration-list-styler.ts +46 -5
  177. package/src/utils/formatters/migration-list-types.ts +5 -21
  178. package/src/utils/formatters/migration-log-table.ts +205 -0
  179. package/src/utils/formatters/migrations.ts +33 -11
  180. package/src/utils/global-flags.ts +35 -0
  181. package/src/utils/integrity-violation-to-check-failure.ts +28 -19
  182. package/src/utils/legend.ts +38 -0
  183. package/src/utils/migration-path-target.ts +60 -0
  184. package/src/utils/telemetry.ts +68 -32
  185. package/dist/client-KgJorIvG.mjs.map +0 -1
  186. package/dist/command-helpers-Bbw1GbwL.mjs.map +0 -1
  187. package/dist/commands/migration-list.mjs.map +0 -1
  188. package/dist/commands/migration-log.mjs.map +0 -1
  189. package/dist/commands/migration-status.mjs.map +0 -1
  190. package/dist/contract-emit-D-4jrNve.mjs.map +0 -1
  191. package/dist/contract-infer-D8uEbJuu.mjs.map +0 -1
  192. package/dist/graph-render-rFAqZujX.mjs +0 -1081
  193. package/dist/graph-render-rFAqZujX.mjs.map +0 -1
  194. package/dist/init-Cv9UzWL5.mjs.map +0 -1
  195. package/dist/inspect-live-schema-C6ohV_oQ.mjs.map +0 -1
  196. package/dist/migration-check-BiBJoYYW.mjs +0 -341
  197. package/dist/migration-check-BiBJoYYW.mjs.map +0 -1
  198. package/dist/migration-graph-C9WC-7eO.mjs +0 -1478
  199. package/dist/migration-graph-C9WC-7eO.mjs.map +0 -1
  200. package/dist/migration-list-styler-BRwF4-gy.mjs +0 -399
  201. package/dist/migration-list-styler-BRwF4-gy.mjs.map +0 -1
  202. package/dist/migration-plan-9DJ7q7_z.mjs.map +0 -1
  203. package/dist/migration-types-D2FW63pr.d.mts +0 -15
  204. package/dist/migration-types-D2FW63pr.d.mts.map +0 -1
  205. package/dist/migrations-Cv2jxNNK.mjs +0 -228
  206. package/dist/migrations-Cv2jxNNK.mjs.map +0 -1
  207. package/dist/terminal-ui-5Y6mrg93.d.mts.map +0 -1
  208. package/dist/types-Dt_SfqFm.d.mts.map +0 -1
  209. package/src/utils/formatters/graph-migration-mapper.ts +0 -235
  210. package/src/utils/formatters/graph-render.ts +0 -1323
  211. package/src/utils/formatters/graph-types.ts +0 -120
  212. package/src/utils/formatters/migration-graph-lane-colors.ts +0 -31
  213. package/src/utils/formatters/migration-graph-layout.ts +0 -1141
  214. package/src/utils/formatters/migration-graph-tree-render.ts +0 -768
@@ -1,6 +1,7 @@
1
1
  import type { Contract } from '@prisma-next/contract/types';
2
2
  import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
3
3
  import type {
4
+ ControlAdapterInstance,
4
5
  ControlDriverInstance,
5
6
  ControlExtensionDescriptor,
6
7
  ControlFamilyInstance,
@@ -9,7 +10,7 @@ import type {
9
10
  import { ifDefined } from '@prisma-next/utils/defined';
10
11
  import { notOk } from '@prisma-next/utils/result';
11
12
  import type { DbUpdateResult, OnControlProgress } from '../types';
12
- import { executeApply } from './db-apply';
13
+ import { executeRun } from './db-run';
13
14
 
14
15
  const DB_UPDATE_POLICY = {
15
16
  allowedOperationClasses: ['additive', 'widening', 'destructive'] as const,
@@ -26,6 +27,7 @@ const DB_UPDATE_POLICY = {
26
27
  */
27
28
  export interface ExecuteDbUpdateOptions<TFamilyId extends string, TTargetId extends string> {
28
29
  readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
30
+ readonly adapter: ControlAdapterInstance<TFamilyId, TTargetId>;
29
31
  readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
30
32
  readonly contract: Contract;
31
33
  readonly mode: 'plan' | 'apply';
@@ -56,6 +58,7 @@ export async function executeDbUpdate<TFamilyId extends string, TTargetId extend
56
58
  ): Promise<DbUpdateResult> {
57
59
  const sharedInputs = {
58
60
  driver: options.driver,
61
+ adapter: options.adapter,
59
62
  familyInstance: options.familyInstance,
60
63
  contract: options.contract,
61
64
  migrations: options.migrations,
@@ -71,7 +74,7 @@ export async function executeDbUpdate<TFamilyId extends string, TTargetId extend
71
74
  const gate = await guardDestructiveChanges<TFamilyId, TTargetId>(sharedInputs);
72
75
  if (gate !== null) return gate;
73
76
  }
74
- return (await executeApply<TFamilyId, TTargetId>({
77
+ return (await executeRun<TFamilyId, TTargetId>({
75
78
  ...sharedInputs,
76
79
  mode: options.mode,
77
80
  })) as DbUpdateResult;
@@ -85,9 +88,9 @@ export async function executeDbUpdate<TFamilyId extends string, TTargetId extend
85
88
  * run.
86
89
  */
87
90
  async function guardDestructiveChanges<TFamilyId extends string, TTargetId extends string>(
88
- sharedInputs: Omit<Parameters<typeof executeApply<TFamilyId, TTargetId>>[0], 'mode'>,
91
+ sharedInputs: Omit<Parameters<typeof executeRun<TFamilyId, TTargetId>>[0], 'mode'>,
89
92
  ): Promise<DbUpdateResult | null> {
90
- const planResult = (await executeApply<TFamilyId, TTargetId>({
93
+ const planResult = (await executeRun<TFamilyId, TTargetId>({
91
94
  ...sharedInputs,
92
95
  mode: 'plan',
93
96
  })) as DbUpdateResult;
@@ -8,11 +8,12 @@ import type {
8
8
  } from '@prisma-next/framework-components/control';
9
9
  import {
10
10
  type ContractSpaceMember,
11
+ collectAggregateNamespaces,
11
12
  requireHeadRef,
12
13
  type VerifierOutput,
13
14
  verifyMigration,
14
15
  } from '@prisma-next/migration-tools/aggregate';
15
- import { castAs } from '@prisma-next/utils/casts';
16
+ import { blindCast, castAs } from '@prisma-next/utils/casts';
16
17
  import { notOk, ok, type Result } from '@prisma-next/utils/result';
17
18
  import { CliStructuredError } from '../../utils/cli-errors';
18
19
  import {
@@ -101,7 +102,12 @@ export async function executeDbVerify<TFamilyId extends string, TTargetId extend
101
102
  const markersBySpaceId = await familyInstance.readAllMarkers({ driver });
102
103
  const schemaIntrospection = skipSchema
103
104
  ? null
104
- : await runIntrospection({ driver, familyInstance, onProgress });
105
+ : await runIntrospection({
106
+ driver,
107
+ familyInstance,
108
+ onProgress,
109
+ contract: collectAggregateNamespaces(aggregate),
110
+ });
105
111
 
106
112
  emitVerifySpan(onProgress, 'spanStart');
107
113
  const verifyResult = verifyMigration({
@@ -130,8 +136,9 @@ async function runIntrospection<TFamilyId extends string, TTargetId extends stri
130
136
  driver: ControlDriverInstance<TFamilyId, TTargetId>;
131
137
  familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
132
138
  onProgress: OnControlProgress | undefined;
139
+ contract: unknown;
133
140
  }): Promise<unknown> {
134
- const { driver, familyInstance, onProgress } = args;
141
+ const { driver, familyInstance, onProgress, contract } = args;
135
142
  onProgress?.({
136
143
  action: 'dbVerify',
137
144
  kind: 'spanStart',
@@ -139,7 +146,7 @@ async function runIntrospection<TFamilyId extends string, TTargetId extends stri
139
146
  label: 'Introspecting database schema',
140
147
  });
141
148
  try {
142
- const result = await familyInstance.introspect({ driver });
149
+ const result = await familyInstance.introspect({ driver, contract });
143
150
  onProgress?.({
144
151
  action: 'dbVerify',
145
152
  kind: 'spanEnd',
@@ -179,7 +186,10 @@ export function createPerMemberVerifier<TFamilyId extends string, TTargetId exte
179
186
  // The family's `TSchemaIR` is opaque to migration-tools; the
180
187
  // aggregate verifier passes through whatever we hand it. The
181
188
  // family expects its own IR shape on the way back.
182
- schema: projectedSchema as never,
189
+ schema: blindCast<
190
+ never,
191
+ 'family TSchemaIR is opaque to migration-tools; projectedSchema is passed straight through'
192
+ >(projectedSchema),
183
193
  strict: verifyMode === 'strict',
184
194
  frameworkComponents,
185
195
  });
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Backs the `migrate` command. Strategy: graph-walk-all-members, replay-only (no introspect/synth/planner).
3
+ */
4
+
1
5
  import type { Contract } from '@prisma-next/contract/types';
2
6
  import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
3
7
  import type {
@@ -7,6 +11,7 @@ import type {
7
11
  TargetMigrationsCapability,
8
12
  } from '@prisma-next/framework-components/control';
9
13
  import {
14
+ buildSynthMigrationEdge,
10
15
  type ContractMarkerRecordLike,
11
16
  type ContractSpaceAggregate,
12
17
  type ContractSpaceMember,
@@ -24,14 +29,14 @@ import {
24
29
  buildContractSpaceAggregate,
25
30
  } from '../../utils/contract-space-aggregate-loader';
26
31
  import type {
27
- MigrationApplyFailure,
28
- MigrationApplyPathDecision,
29
- MigrationApplyResult,
30
- MigrationApplySuccess,
32
+ MigrateFailure,
33
+ MigratePathDecision,
34
+ MigrateResult,
35
+ MigrateSuccess,
31
36
  OnControlProgress,
32
37
  PerSpaceExecutionEntry,
33
38
  } from '../types';
34
- import { applyMigration, buildPerSpaceBreakdown } from './apply';
39
+ import { buildPerSpaceBreakdown, runMigration } from './run-migration';
35
40
 
36
41
  /**
37
42
  * Inputs for the aggregate-walking `migrate` control-api
@@ -42,7 +47,7 @@ import { applyMigration, buildPerSpaceBreakdown } from './apply';
42
47
  * is the single descriptor-free seam between the CLI and the
43
48
  * aggregate runtime.
44
49
  */
45
- export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetId extends string> {
50
+ export interface ExecuteMigrateOptions<TFamilyId extends string, TTargetId extends string> {
46
51
  readonly driver: ControlDriverInstance<TFamilyId, TTargetId>;
47
52
  readonly familyInstance: ControlFamilyInstance<TFamilyId, unknown>;
48
53
  /** Already-validated app contract (the canonical "where we are heading" hash). */
@@ -95,16 +100,16 @@ export interface ExecuteMigrationApplyOptions<TFamilyId extends string, TTargetI
95
100
  * marker to `member.headRef.hash` (or `refHash` for the app
96
101
  * member when provided). Empty-graph members fail loudly — a
97
102
  * "never planned" space is a user-error condition for replay.
98
- * 4. Hand off to {@link applyMigration} (the runner-driving tail
103
+ * 4. Hand off to {@link runMigration} (the runner-driving tail
99
104
  * shared with `db init` / `db update`). Marker advancement is
100
105
  * inside the per-space transaction.
101
106
  *
102
107
  * Encodes the replay-only contract: every contract space must have an
103
108
  * authored migration graph on disk before this operation can advance it.
104
109
  */
105
- export async function executeMigrationApply<TFamilyId extends string, TTargetId extends string>(
106
- options: ExecuteMigrationApplyOptions<TFamilyId, TTargetId>,
107
- ): Promise<MigrationApplyResult> {
110
+ export async function executeMigrate<TFamilyId extends string, TTargetId extends string>(
111
+ options: ExecuteMigrateOptions<TFamilyId, TTargetId>,
112
+ ): Promise<MigrateResult> {
108
113
  const {
109
114
  driver,
110
115
  familyInstance,
@@ -151,58 +156,36 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
151
156
  // The aggregate passed the integrity gate, so every member's head ref
152
157
  // is resolved (the app's is synthesised from the live contract).
153
158
  const headRef = requireHeadRef(member);
154
- const targetHash = isAppMember && refHash !== undefined ? refHash : headRef.hash;
159
+ const memberTargetHash = isAppMember && refHash !== undefined ? refHash : headRef.hash;
160
+ const memberRefInvariants = isAppMember && refHash !== undefined ? refInvariants : undefined;
155
161
  const liveMarker = markerRows.get(member.spaceId) ?? null;
156
162
 
157
- // Empty-graph members fail loudly: replay needs an on-disk path
158
- // and an empty graph means the user has never planned this space.
159
- if (member.graph().nodes.size === 0) {
160
- // Edge case: target == EMPTY (greenfield, nothing to do) or
161
- // the live marker already matches the target. Loader integrity
162
- // allows this for extensions whose head ref is the empty
163
- // sentinel. Record a zero-op resolution so the aggregate result
164
- // still surfaces the member in `perSpace[]` as already-at-head;
165
- // the runner is not invoked for these members because they have
166
- // no authored ops and (for greenfield extensions) no marker to
167
- // advance.
168
- const liveHash = liveMarker?.storageHash;
169
- if (
170
- targetHash === liveHash ||
171
- (liveHash === undefined && targetHash === EMPTY_CONTRACT_HASH)
172
- ) {
173
- atHeadResolutions.set(
174
- member.spaceId,
175
- buildAtHeadResolution({
176
- aggregateTargetId: aggregate.targetId,
177
- member,
178
- targetHash,
179
- liveMarker,
180
- }),
181
- );
182
- continue;
183
- }
184
- return notOk(buildNeverPlannedFailure(member.spaceId, targetHash));
185
- }
186
-
187
- const targetInvariants =
188
- isAppMember && refHash !== undefined && refInvariants !== undefined
189
- ? refInvariants
190
- : headRef.invariants;
191
- const targetMember: ContractSpaceMember =
192
- targetHash === headRef.hash && targetInvariants === headRef.invariants
193
- ? member
194
- : { ...member, headRef: { hash: targetHash, invariants: targetInvariants } };
195
-
196
- const walked = graphWalkStrategy({
197
- aggregateTargetId: aggregate.targetId,
198
- member: targetMember,
199
- currentMarker: liveMarker,
200
- ...(isAppMember && refName !== undefined ? { refName } : {}),
163
+ const outcome = planMemberPath({
164
+ member,
165
+ aggregate,
166
+ targetHash: memberTargetHash,
167
+ refInvariants: memberRefInvariants,
168
+ liveMarker,
169
+ ...(isAppMember ? { refName } : {}),
201
170
  });
202
- if (walked.kind === 'unreachable') {
203
- return notOk(buildPathNotFoundFailure(member.spaceId, liveMarker, targetHash));
171
+
172
+ if (outcome.kind === 'at-head') {
173
+ // Empty-graph member whose live marker already matches the target.
174
+ // Kept out of the runner schedule so we don't write spurious markers
175
+ // for greenfield extensions, but merged back into the success envelope
176
+ // so every loaded member is represented.
177
+ atHeadResolutions.set(member.spaceId, outcome.plan);
178
+ continue;
179
+ }
180
+ if (outcome.kind === 'never-planned') {
181
+ return notOk(buildNeverPlannedFailure(outcome.spaceId, outcome.targetHash));
182
+ }
183
+ if (outcome.kind === 'unreachable') {
184
+ return notOk(
185
+ buildPathNotFoundFailure(outcome.spaceId, outcome.liveMarker, outcome.targetHash),
186
+ );
204
187
  }
205
- if (walked.kind === 'unsatisfiable') {
188
+ if (outcome.kind === 'unsatisfiable') {
206
189
  // Surface the canonical MIGRATION.NO_INVARIANT_PATH envelope
207
190
  // (the error rendering pipeline maps it to meta.code +
208
191
  // meta.required + meta.missing + meta.structuralPath that the
@@ -213,10 +196,12 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
213
196
  // string here would leave the structural lookup with a hash that
214
197
  // is never a graph node, producing an empty `structuralPath` and
215
198
  // a less actionable diagnostic.
216
- const fromHash = liveMarker?.storageHash ?? EMPTY_CONTRACT_HASH;
217
- const structural = findPathWithDecision(targetMember.graph(), fromHash, targetHash, {
218
- required: new Set<string>(),
219
- });
199
+ const structural = findPathWithDecision(
200
+ outcome.targetMember.graph(),
201
+ outcome.liveHash,
202
+ memberTargetHash,
203
+ { required: new Set<string>() },
204
+ );
220
205
  const structuralPath =
221
206
  structural.kind === 'ok'
222
207
  ? structural.decision.selectedPath.map((edge) => ({
@@ -228,14 +213,14 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
228
213
  }))
229
214
  : [];
230
215
  throw errorNoInvariantPath({
231
- ...(isAppMember && refName !== undefined ? { refName } : {}),
232
- required: targetInvariants,
233
- missing: walked.missing,
216
+ ...(outcome.refName !== undefined ? { refName: outcome.refName } : {}),
217
+ required: outcome.targetInvariants,
218
+ missing: outcome.missing,
234
219
  structuralPath,
235
220
  });
236
221
  }
237
222
 
238
- perSpacePlans.set(member.spaceId, walked.result);
223
+ perSpacePlans.set(member.spaceId, outcome.plan);
239
224
  }
240
225
 
241
226
  const canonicalOrder = [...aggregate.extensions.map((m) => m.spaceId), aggregate.app.spaceId];
@@ -276,7 +261,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
276
261
  );
277
262
  }
278
263
 
279
- const applied = await applyMigration({
264
+ const applied = await runMigration({
280
265
  aggregate,
281
266
  perSpacePlans,
282
267
  applyOrder,
@@ -285,12 +270,12 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
285
270
  migrations,
286
271
  frameworkComponents,
287
272
  policy: { allowedOperationClasses: ['additive', 'widening', 'destructive', 'data'] },
288
- action: 'migrationApply',
273
+ action: 'migrate',
289
274
  ...ifDefined('onProgress', onProgress),
290
275
  });
291
276
 
292
277
  if (!applied.ok) {
293
- const failure: MigrationApplyFailure = {
278
+ const failure: MigrateFailure = {
294
279
  code: 'RUNNER_FAILED',
295
280
  summary: applied.failure.summary,
296
281
  why: applied.failure.why,
@@ -319,7 +304,7 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
319
304
  includeMarkers: true,
320
305
  });
321
306
  const totalMigrationsApplied = applied.value.orderedResolutions.reduce(
322
- (sum, r) => sum + (r.entry.migrationEdges?.length ?? 0),
307
+ (sum, r) => sum + r.entry.migrationEdges.length,
323
308
  0,
324
309
  );
325
310
  const summary = `Applied ${totalMigrationsApplied} migration(s) (${applied.value.totalOpsExecuted} operation(s)) across ${orderedAll.length} contract space(s)`;
@@ -335,6 +320,119 @@ export async function executeMigrationApply<TFamilyId extends string, TTargetId
335
320
  );
336
321
  }
337
322
 
323
+ /**
324
+ * Outcome variants for one member's path computation.
325
+ *
326
+ * Callers switch on `kind` and map to their own error representation:
327
+ * `executeMigrate` throws / returns `notOk`; `executeMigrateShowCommand`
328
+ * returns a CLI structured error. The shared discriminant guarantees both
329
+ * paths feed `graphWalkStrategy` the same inputs.
330
+ *
331
+ * @internal Exported for `executeMigrateShowCommand` to call.
332
+ */
333
+ export type MemberPathOutcome =
334
+ | { readonly kind: 'ok'; readonly plan: PerSpacePlan }
335
+ | { readonly kind: 'at-head'; readonly plan: PerSpacePlan }
336
+ | { readonly kind: 'never-planned'; readonly spaceId: string; readonly targetHash: string }
337
+ | {
338
+ readonly kind: 'unreachable';
339
+ readonly spaceId: string;
340
+ readonly liveMarker: ContractMarkerRecordLike | null;
341
+ readonly targetHash: string;
342
+ }
343
+ | {
344
+ readonly kind: 'unsatisfiable';
345
+ readonly spaceId: string;
346
+ readonly isAppMember: boolean;
347
+ readonly missing: readonly string[];
348
+ readonly targetInvariants: readonly string[];
349
+ readonly targetMember: ContractSpaceMember;
350
+ readonly liveHash: string;
351
+ readonly refName: string | undefined;
352
+ };
353
+
354
+ /**
355
+ * Compute the graph-walk path for one contract-space member.
356
+ *
357
+ * Encapsulates the invariant-correct input assembly that both
358
+ * `executeMigrate` and `executeMigrateShowCommand` must use:
359
+ * - `currentMarker` carries the full live marker including `invariants`
360
+ * (not a stripped `{ storageHash, invariants: [] }` shell).
361
+ * - `targetInvariants` uses the caller-supplied `refInvariants` when a
362
+ * `--to` ref was resolved (not always the file head ref's invariants).
363
+ *
364
+ * Both callers map the returned `MemberPathOutcome` to their own error
365
+ * representation; the path-compute logic is shared and identical.
366
+ *
367
+ * @internal Exported for `executeMigrateShowCommand`.
368
+ */
369
+ export function planMemberPath({
370
+ member,
371
+ aggregate,
372
+ targetHash,
373
+ refInvariants,
374
+ liveMarker,
375
+ refName,
376
+ }: {
377
+ readonly member: ContractSpaceMember;
378
+ readonly aggregate: Pick<ContractSpaceAggregate, 'targetId' | 'app'>;
379
+ readonly targetHash: string;
380
+ readonly refInvariants: readonly string[] | undefined;
381
+ readonly liveMarker: ContractMarkerRecordLike | null;
382
+ readonly refName?: string;
383
+ }): MemberPathOutcome {
384
+ const isAppMember = member.spaceId === aggregate.app.spaceId;
385
+ const headRef = requireHeadRef(member);
386
+
387
+ if (member.graph().nodes.size === 0) {
388
+ const liveHash = liveMarker?.storageHash;
389
+ if (targetHash === liveHash || (liveHash === undefined && targetHash === EMPTY_CONTRACT_HASH)) {
390
+ return {
391
+ kind: 'at-head',
392
+ plan: buildAtHeadResolution({
393
+ aggregateTargetId: aggregate.targetId,
394
+ member,
395
+ targetHash,
396
+ liveMarker,
397
+ }),
398
+ };
399
+ }
400
+ return { kind: 'never-planned', spaceId: member.spaceId, targetHash };
401
+ }
402
+
403
+ const targetInvariants =
404
+ isAppMember && refInvariants !== undefined ? refInvariants : headRef.invariants;
405
+ const targetMember: ContractSpaceMember =
406
+ targetHash === headRef.hash && targetInvariants === headRef.invariants
407
+ ? member
408
+ : { ...member, headRef: { hash: targetHash, invariants: targetInvariants } };
409
+
410
+ const walked = graphWalkStrategy({
411
+ aggregateTargetId: aggregate.targetId,
412
+ member: targetMember,
413
+ currentMarker: liveMarker,
414
+ ...(isAppMember && refName !== undefined ? { refName } : {}),
415
+ });
416
+
417
+ if (walked.kind === 'unreachable') {
418
+ return { kind: 'unreachable', spaceId: member.spaceId, liveMarker, targetHash };
419
+ }
420
+ if (walked.kind === 'unsatisfiable') {
421
+ const liveHash = liveMarker?.storageHash ?? EMPTY_CONTRACT_HASH;
422
+ return {
423
+ kind: 'unsatisfiable',
424
+ spaceId: member.spaceId,
425
+ isAppMember,
426
+ missing: walked.missing,
427
+ targetInvariants,
428
+ targetMember,
429
+ liveHash,
430
+ refName,
431
+ };
432
+ }
433
+ return { kind: 'ok', plan: walked.result };
434
+ }
435
+
338
436
  /**
339
437
  * Build a zero-op {@link PerSpacePlan} for an empty-graph
340
438
  * member whose live marker already matches the target. Lets the apply
@@ -361,7 +459,13 @@ function buildAtHeadResolution(args: {
361
459
  displayOps: [],
362
460
  destinationContract: member.contract(),
363
461
  strategy: 'graph-walk',
364
- migrationEdges: [],
462
+ migrationEdges: [
463
+ buildSynthMigrationEdge({
464
+ currentMarkerStorageHash: liveMarker?.storageHash,
465
+ destinationStorageHash: targetHash,
466
+ operationCount: 0,
467
+ }),
468
+ ],
365
469
  };
366
470
  }
367
471
 
@@ -389,9 +493,9 @@ interface BuildSuccessArgs {
389
493
  readonly summary: string;
390
494
  }
391
495
 
392
- function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
496
+ function buildSuccess(args: BuildSuccessArgs): MigrateSuccess {
393
497
  // The marker hash surfaced at the top level is the **app member's**
394
- // post-apply marker (the top-level `markerHash` field).
498
+ // post-migrate marker (the top-level `markerHash` field).
395
499
  // Per-space markers live on `perSpace[].marker.storageHash`.
396
500
  const appResolution = args.orderedResolutions.find(
397
501
  (r) => r.spaceId === args.aggregate.app.spaceId,
@@ -404,7 +508,7 @@ function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
404
508
  // JSON-shape consumers (e.g. `parsed.applied.length` in integration
405
509
  // tests). The aggregate per-space breakdown lives on `perSpace[]`.
406
510
  const applied = args.orderedResolutions.flatMap((r) => {
407
- const edges = r.entry.migrationEdges ?? [];
511
+ const edges = r.entry.migrationEdges;
408
512
  return edges.map((edge) => ({
409
513
  spaceId: r.spaceId,
410
514
  dirName: edge.dirName,
@@ -416,7 +520,7 @@ function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
416
520
  });
417
521
 
418
522
  const appPlan = appResolution?.entry;
419
- const pathDecision: MigrationApplyPathDecision | undefined = appPlan?.pathDecision
523
+ const pathDecision: MigratePathDecision | undefined = appPlan?.pathDecision
420
524
  ? {
421
525
  fromHash: appPlan.pathDecision.fromHash,
422
526
  toHash: appPlan.pathDecision.toHash,
@@ -455,10 +559,7 @@ function buildSuccess(args: BuildSuccessArgs): MigrationApplySuccess {
455
559
  *
456
560
  * @internal Exported for testing only.
457
561
  */
458
- export function buildNeverPlannedFailure(
459
- spaceId: string,
460
- targetHash: string,
461
- ): MigrationApplyFailure {
562
+ export function buildNeverPlannedFailure(spaceId: string, targetHash: string): MigrateFailure {
462
563
  return {
463
564
  code: 'MIGRATION_PATH_NOT_FOUND',
464
565
  summary: `No on-disk migrations for contract space "${spaceId}"`,
@@ -481,7 +582,7 @@ export function buildPathNotFoundFailure(
481
582
  spaceId: string,
482
583
  marker: ContractMarkerRecordLike | null,
483
584
  targetHash: string,
484
- ): MigrationApplyFailure {
585
+ ): MigrateFailure {
485
586
  const fromHash = marker?.storageHash ?? '<empty>';
486
587
  // The app-case phrasing names the user-visible condition (a
487
588
  // contract has been emitted that no on-disk migration reaches) so
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Shared runner tail (`runMigration` + `buildPerSpaceBreakdown`/`collectOrdered`).
3
+ * Backs no command directly; consumed by db-run and migrate.
4
+ */
5
+
1
6
  import type { TargetBoundComponentDescriptor } from '@prisma-next/framework-components/components';
2
7
  import type {
3
8
  ControlDriverInstance,
@@ -11,32 +16,32 @@ import { notOk, ok, type Result } from '@prisma-next/utils/result';
11
16
  import type { OnControlProgress, PerSpaceExecutionEntry } from '../types';
12
17
 
13
18
  /**
14
- * Span id emitted via `onProgress` for the apply phase. Stable
19
+ * Span id emitted via `onProgress` for the run phase. Stable
15
20
  * identifier consumed by the structured-output renderer and by tests.
16
21
  */
17
- const APPLY_SPAN_ID = 'apply' as const;
22
+ const RUN_SPAN_ID = 'apply' as const;
18
23
 
19
24
  /**
20
- * Action that originated this apply call. Threaded into `OnControlProgress`
25
+ * Action that originated this run call. Threaded into `OnControlProgress`
21
26
  * events so the parent CLI command can attribute the span correctly,
22
27
  * and used to compose action-specific summary phrasing.
23
28
  */
24
- export type ApplyAction = 'dbInit' | 'dbUpdate' | 'migrationApply';
29
+ export type RunAction = 'dbInit' | 'dbUpdate' | 'migrate';
25
30
 
26
31
  /**
27
- * Failure variant emitted by {@link applyMigration} when the runner
28
- * itself rejects the apply. Mirrors the failure shape callers
32
+ * Failure variant emitted by {@link runMigration} when the runner
33
+ * itself rejects the run. Mirrors the failure shape callers
29
34
  * already wrap into their own action-specific failure envelopes
30
- * (`DbInitFailure`, `DbUpdateFailure`, `MigrationApplyFailure`) so each
35
+ * (`DbInitFailure`, `DbUpdateFailure`, `MigrateFailure`) so each
31
36
  * caller keeps owning its own discriminated failure code.
32
37
  */
33
- export interface ApplyRunnerFailure {
38
+ export interface RunnerFailure {
34
39
  readonly summary: string;
35
40
  readonly why?: string;
36
41
  readonly meta: Record<string, unknown>;
37
42
  }
38
43
 
39
- export interface ApplyMigrationInputs<TFamilyId extends string, TTargetId extends string> {
44
+ export interface RunMigrationInputs<TFamilyId extends string, TTargetId extends string> {
40
45
  readonly aggregate: ContractSpaceAggregate;
41
46
  /**
42
47
  * Per-space plans, keyed by `spaceId`. Produced by either the full
@@ -62,22 +67,22 @@ export interface ApplyMigrationInputs<TFamilyId extends string, TTargetId extend
62
67
  >;
63
68
  readonly frameworkComponents: ReadonlyArray<TargetBoundComponentDescriptor<TFamilyId, TTargetId>>;
64
69
  readonly policy: MigrationOperationPolicy;
65
- readonly action: ApplyAction;
70
+ readonly action: RunAction;
66
71
  readonly onProgress?: OnControlProgress;
67
72
  }
68
73
 
69
74
  /**
70
75
  * Resolved per-space plan in canonical schedule order. Surfaced from
71
- * {@link applyMigration} to callers so each one can build its own
76
+ * {@link runMigration} to callers so each one can build its own
72
77
  * action-specific success envelope (e.g. `DbInitSuccess` vs
73
- * `MigrationApplySuccess`) without re-deriving the ordering.
78
+ * `MigrateSuccess`) without re-deriving the ordering.
74
79
  */
75
80
  export interface OrderedResolution {
76
81
  readonly spaceId: string;
77
82
  readonly entry: PerSpacePlan;
78
83
  }
79
84
 
80
- export interface ApplyMigrationValue {
85
+ export interface RunMigrationValue {
81
86
  readonly orderedResolutions: readonly OrderedResolution[];
82
87
  readonly totalOpsPlanned: number;
83
88
  readonly totalOpsExecuted: number;
@@ -89,10 +94,10 @@ export interface ApplyMigrationValue {
89
94
  readonly perSpace: readonly PerSpaceExecutionEntry[];
90
95
  }
91
96
 
92
- export type ApplyMigrationResult = Result<ApplyMigrationValue, ApplyRunnerFailure>;
97
+ export type RunMigrationResult = Result<RunMigrationValue, RunnerFailure>;
93
98
 
94
99
  /**
95
- * Runner-driving tail shared by every apply caller — `db init`,
100
+ * Runner-driving tail shared by every run caller — `db init`,
96
101
  * `db update`, and `migrate`. Consumes already-resolved per-space
97
102
  * plans (the planner-vs-replay distinction is owned by the caller) and
98
103
  * dispatches them to the runner in canonical order.
@@ -107,9 +112,9 @@ export type ApplyMigrationResult = Result<ApplyMigrationValue, ApplyRunnerFailur
107
112
  * so callers don't have to duplicate it; the `action` field on each
108
113
  * progress event is taken from the caller's `action` argument.
109
114
  */
110
- export async function applyMigration<TFamilyId extends string, TTargetId extends string>(
111
- inputs: ApplyMigrationInputs<TFamilyId, TTargetId>,
112
- ): Promise<ApplyMigrationResult> {
115
+ export async function runMigration<TFamilyId extends string, TTargetId extends string>(
116
+ inputs: RunMigrationInputs<TFamilyId, TTargetId>,
117
+ ): Promise<RunMigrationResult> {
113
118
  const {
114
119
  aggregate,
115
120
  perSpacePlans,
@@ -130,7 +135,7 @@ export async function applyMigration<TFamilyId extends string, TTargetId extends
130
135
  onProgress?.({
131
136
  action,
132
137
  kind: 'spanStart',
133
- spanId: APPLY_SPAN_ID,
138
+ spanId: RUN_SPAN_ID,
134
139
  label: progressLabelForAction(action),
135
140
  });
136
141
 
@@ -141,6 +146,7 @@ export async function applyMigration<TFamilyId extends string, TTargetId extends
141
146
  destinationContract: r.entry.destinationContract,
142
147
  policy,
143
148
  frameworkComponents,
149
+ migrationEdges: r.entry.migrationEdges,
144
150
  // Per-space post-apply schema verification is non-strict: each
145
151
  // space's `destinationContract` describes only its own slice; a
146
152
  // strict verifier would treat every other space's tables as
@@ -151,7 +157,7 @@ export async function applyMigration<TFamilyId extends string, TTargetId extends
151
157
  const runnerResult = await runner.execute({ driver, perSpaceOptions });
152
158
 
153
159
  if (!runnerResult.ok) {
154
- onProgress?.({ action, kind: 'spanEnd', spanId: APPLY_SPAN_ID, outcome: 'error' });
160
+ onProgress?.({ action, kind: 'spanEnd', spanId: RUN_SPAN_ID, outcome: 'error' });
155
161
  return notOk({
156
162
  summary: runnerResult.failure.summary,
157
163
  ...ifDefined('why', runnerResult.failure.why),
@@ -162,7 +168,7 @@ export async function applyMigration<TFamilyId extends string, TTargetId extends
162
168
  },
163
169
  });
164
170
  }
165
- onProgress?.({ action, kind: 'spanEnd', spanId: APPLY_SPAN_ID, outcome: 'ok' });
171
+ onProgress?.({ action, kind: 'spanEnd', spanId: RUN_SPAN_ID, outcome: 'ok' });
166
172
 
167
173
  const totalOpsPlanned = runnerResult.value.perSpaceResults.reduce(
168
174
  (sum, r) => sum + r.value.operationsPlanned,
@@ -194,7 +200,7 @@ export async function applyMigration<TFamilyId extends string, TTargetId extends
194
200
  * advances as the last step of each space's transaction) and `false`
195
201
  * for plan-mode (no marker has been written yet).
196
202
  *
197
- * Exported alongside {@link applyMigration} so plan-mode callers can
203
+ * Exported alongside {@link runMigration} so plan-mode callers can
198
204
  * assemble the same per-space block without going through the runner.
199
205
  */
200
206
  export function buildPerSpaceBreakdown(
@@ -243,18 +249,18 @@ export function collectOrdered(
243
249
  }
244
250
 
245
251
  /**
246
- * Action-appropriate label for the `spanStart` event the apply
247
- * primitive emits. `applyMigration` is shared by `db init`, `db update`,
252
+ * Action-appropriate label for the `spanStart` event the run
253
+ * primitive emits. `runMigration` is shared by `db init`, `db update`,
248
254
  * and `migrate`; the span label tracks the user-visible action
249
255
  * so structured-progress output reads naturally for each surface.
250
256
  */
251
- export function progressLabelForAction(action: ApplyAction): string {
257
+ export function progressLabelForAction(action: RunAction): string {
252
258
  switch (action) {
253
259
  case 'dbInit':
254
260
  return 'Initialising database across spaces';
255
261
  case 'dbUpdate':
256
262
  return 'Updating database across spaces';
257
- case 'migrationApply':
258
- return 'Applying migration plan across spaces';
263
+ case 'migrate':
264
+ return 'Running migration plan across spaces';
259
265
  }
260
266
  }