@zq-silk/yui 0.13.10 → 0.14.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 (230) hide show
  1. package/ARCHITECTURE.md +69 -428
  2. package/README.md +113 -300
  3. package/dist/agent/argumentPolicy.js +2 -1
  4. package/dist/agent/managedRuntimeEnvironment.js +2 -2
  5. package/dist/cli/commandCatalog.js +39 -77
  6. package/dist/cli/interactionCandidates.js +4 -4
  7. package/dist/cli/interactionPolicy.js +7 -10
  8. package/dist/cli/invocationRouter.js +1 -1
  9. package/dist/cli/updateCommand.js +6 -27
  10. package/dist/cli/updateOrchestrator.js +63 -484
  11. package/dist/cli/updatePorts.js +15 -333
  12. package/dist/cli/upgradeCommand.js +8 -65
  13. package/dist/cli.js +57 -242
  14. package/dist/commands/configCommands.js +11 -62
  15. package/dist/commands/executionAuditCommands.js +23 -23
  16. package/dist/commands/globalRoleCommands.js +2 -7
  17. package/dist/commands/jobCommands.js +1 -4
  18. package/dist/commands/projectCommands.js +5 -5
  19. package/dist/commands/releaseCommands.js +3 -10
  20. package/dist/commands/resourcesCommands.js +2 -2
  21. package/dist/commands/sessionCommands.js +2 -2
  22. package/dist/commands/taskActor.js +31 -39
  23. package/dist/commands/taskChangeSetCommands.js +5 -12
  24. package/dist/commands/taskCommands.js +464 -1249
  25. package/dist/commands/taskContextCommand.js +35 -36
  26. package/dist/commands/taskExecutionCommands.js +33 -46
  27. package/dist/commands/taskInputCommands.js +20 -42
  28. package/dist/commands/taskNextActionCommand.js +9 -9
  29. package/dist/commands/taskOverviewCommand.js +56 -95
  30. package/dist/commands/taskRoleRuntimeStatus.js +77 -107
  31. package/dist/commands/taskUpstreamCommands.js +3 -3
  32. package/dist/commands/taskWorkspaceCommands.js +7 -79
  33. package/dist/commands/telemetryCommands.js +32 -124
  34. package/dist/commands/workflowCommands.js +3 -3
  35. package/dist/completion/fileCompletionManager.js +1 -1
  36. package/dist/config/configCatalog.js +4 -6
  37. package/dist/config/yuiConfig.js +6 -43
  38. package/dist/context/dispatchContext.js +14 -30
  39. package/dist/context/roleSessionContext.js +2 -2
  40. package/dist/context/sessionBootstrapManifest.js +20 -3
  41. package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
  42. package/dist/context/turnInputContract.js +204 -0
  43. package/dist/context/wakeNotification.js +2 -2
  44. package/dist/controller/agentRuntimeObserver.js +18 -18
  45. package/dist/controller/clientRuntime.js +13 -20
  46. package/dist/controller/controller.js +89 -116
  47. package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
  48. package/dist/controller/jobControl.js +17 -17
  49. package/dist/controller/resourceInventory.js +6 -6
  50. package/dist/controller/resourceInventoryLinux.js +38 -59
  51. package/dist/controller/resourceInventoryRpc.js +3 -3
  52. package/dist/controller/resourceInventoryWorker.js +1 -1
  53. package/dist/controller/runtime.js +46 -53
  54. package/dist/controller/runtimeEventInbox.js +23 -31
  55. package/dist/controller/runtimeEventProcessor.js +15 -15
  56. package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
  57. package/dist/controller/runtimeLaunchCoordinator.js +3 -3
  58. package/dist/controller/runtimeObservationHook.js +11 -8
  59. package/dist/controller/sessionNotify.js +11 -11
  60. package/dist/controller/structuredProviderObservation.js +89 -16
  61. package/dist/coordination/workMailbox.js +309 -579
  62. package/dist/coordination/workMailboxQueue.js +5 -6
  63. package/dist/core/controllerClient.js +1 -91
  64. package/dist/core/controllerServer.js +3 -6
  65. package/dist/doctor/doctor.js +51 -314
  66. package/dist/execution/candidateConvergence.js +3 -3
  67. package/dist/execution/executionGroup.js +32 -33
  68. package/dist/execution/executionHealth.js +36 -38
  69. package/dist/execution/resourceBroker.js +12 -12
  70. package/dist/executor/agentExecutor.js +30 -265
  71. package/dist/executor/effectiveLaunch.js +9 -19
  72. package/dist/executor/executorRegistry.js +43 -17
  73. package/dist/executor/fileRoleLaunchPlanner.js +91 -57
  74. package/dist/executor/launchPlan.js +3 -3
  75. package/dist/executor/workspacePreflightClassification.js +16 -16
  76. package/dist/grant/capabilityGrant.js +20 -25
  77. package/dist/input/inputRequest.js +12 -12
  78. package/dist/integration/changeSet.js +9 -13
  79. package/dist/integration/changeSetManifest.js +1 -1
  80. package/dist/integration/gitIntegrationService.js +2 -2
  81. package/dist/integration/integrationQueueService.js +5 -21
  82. package/dist/integration/overlapDiagnostics.js +2 -2
  83. package/dist/interaction/operatorPresentation.js +1 -1
  84. package/dist/job/jobRunner.js +1 -1
  85. package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
  86. package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
  87. package/dist/message/message.js +6 -6
  88. package/dist/observability/executionAudit.js +74 -86
  89. package/dist/observability/faultClassification.js +7 -24
  90. package/dist/observability/orchestrationMetrics.js +5 -5
  91. package/dist/observability/runtimeIdentity.js +34 -101
  92. package/dist/profile/agentProfile.js +1 -1
  93. package/dist/release/cliHomeReleaseFence.js +3 -3
  94. package/dist/release/releaseWorkflowEngine.js +6 -10
  95. package/dist/release/releaseWorkflowPorts.js +2 -2
  96. package/dist/release/workflowFileLock.js +1 -1
  97. package/dist/repository/checkoutSwap.js +1 -1
  98. package/dist/repository/gitWorkspace.js +0 -13
  99. package/dist/repository/project.js +1 -1
  100. package/dist/repository/projectMaintenanceLock.js +1 -2
  101. package/dist/repository/taskBaseFreshness.js +13 -13
  102. package/dist/repository/taskWorkspaceCoordinator.js +21 -25
  103. package/dist/repository/taskWorkspaceIdentity.js +8 -21
  104. package/dist/repository/taskWorkspacePreparer.js +63 -620
  105. package/dist/resources/autoResourceGc.js +3 -3
  106. package/dist/resources/liveReferences.js +1 -1
  107. package/dist/resources/resourceGc.js +1 -1
  108. package/dist/resources/sqliteResourceRegistry.js +1 -1
  109. package/dist/review/reviewDecision.js +7 -7
  110. package/dist/review/reviewFindingLedger.js +1 -1
  111. package/dist/review/reviewOutcomeClassifier.js +35 -50
  112. package/dist/review/reviewRound.js +14 -25
  113. package/dist/review/reviewerAvailability.js +4 -4
  114. package/dist/review/taskFinalReviewContractResolution.js +41 -0
  115. package/dist/role/role.js +6 -3
  116. package/dist/runtime/agentDriver.js +4 -0
  117. package/dist/runtime/agentHost.js +151 -36
  118. package/dist/runtime/builtinAgentDrivers.js +79 -2
  119. package/dist/runtime/codexAppServerRuntime.js +122 -0
  120. package/dist/runtime/continuationManager.js +3 -5
  121. package/dist/runtime/exactControlPlane.js +17 -42
  122. package/dist/runtime/firstProgressAdvisory.js +1 -1
  123. package/dist/runtime/index.js +2 -2
  124. package/dist/runtime/launchDiagnostics.js +2 -2
  125. package/dist/runtime/lifecycleReservation.js +4 -4
  126. package/dist/runtime/processExitObservation.js +1 -1
  127. package/dist/runtime/processExitOutbox.js +0 -32
  128. package/dist/runtime/promptEnvelope.js +9 -9
  129. package/dist/runtime/providerContinuation.js +2 -2
  130. package/dist/runtime/providerContinuationReconciliationService.js +2 -2
  131. package/dist/runtime/providerRuntimeIdentity.js +76 -24
  132. package/dist/runtime/recentTurnIds.js +38 -0
  133. package/dist/runtime/runtimeContinuationProjection.js +2 -2
  134. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  135. package/dist/runtime/runtimeObservation.js +58 -21
  136. package/dist/runtime/runtimeProjection.js +19 -27
  137. package/dist/runtime/sessionLaunchRequest.js +2 -2
  138. package/dist/runtime/structuredProviderHost.js +177 -12
  139. package/dist/runtime/tmuxAdapters.js +46 -11
  140. package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
  141. package/dist/scheduler/leaderWakeupProcessor.js +147 -445
  142. package/dist/scheduler/operatorEvent.js +4 -6
  143. package/dist/scheduler/resourceQueueProjection.js +71 -0
  144. package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
  145. package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
  146. package/dist/scheduler/taskExecutionProjection.js +99 -99
  147. package/dist/scheduler/taskObservabilityProjection.js +10 -10
  148. package/dist/scheduler/taskWake.js +4 -4
  149. package/dist/scheduler/wakeReason.js +6 -10
  150. package/dist/scheduler/wakeupQueue.js +0 -9
  151. package/dist/setup/setupCommand.js +2 -2
  152. package/dist/storage/currentTaskStore.js +46 -0
  153. package/dist/storage/persistenceWorker.js +1 -1
  154. package/dist/storage/sqliteSchema.js +81 -485
  155. package/dist/storage/sqliteStore.js +206 -365
  156. package/dist/storage/storageSchema.js +1 -15
  157. package/dist/storage/storageVersions.js +8 -9
  158. package/dist/storage/storeRpc.js +10 -34
  159. package/dist/storage/taskStore.js +63 -3415
  160. package/dist/storage/upgrade/recordVersions.js +55 -149
  161. package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
  162. package/dist/task/completionReadiness.js +5 -5
  163. package/dist/task/deliveryGuard.js +10 -10
  164. package/dist/task/nextAction.js +74 -77
  165. package/dist/task/task.js +2 -4
  166. package/dist/task/taskRecordReference.js +3 -3
  167. package/dist/task/taskRecordRetirement.js +1 -1
  168. package/dist/telemetry/sqliteTelemetryStore.js +53 -53
  169. package/dist/telemetry/telemetryConfig.js +14 -14
  170. package/dist/telemetry/telemetryWiring.js +8 -14
  171. package/dist/turn/turn.js +356 -0
  172. package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
  173. package/dist/verification/gateArtifactStore.js +2 -2
  174. package/dist/web/assets/client/app.js +1 -1
  175. package/dist/web/assets/client/components.js +29 -54
  176. package/dist/web/assets/client/i18n.js +17 -37
  177. package/dist/web/assets/client/view.js +37 -37
  178. package/dist/web/assets/shell.js +1 -1
  179. package/dist/web/assets/styles/cards.js +5 -5
  180. package/dist/web/assets/styles/widgets.js +1 -2
  181. package/dist/web/webSnapshot.js +65 -60
  182. package/dist/workItem/workItem.js +11 -11
  183. package/dist/workspace/workItemChangeSetManager.js +1 -1
  184. package/docs/task-local-identity.md +5 -5
  185. package/i18n/README.zh-CN.md +42 -55
  186. package/package.json +1 -1
  187. package/skills/yui-leader/SKILL.md +85 -83
  188. package/skills/yui-operator/SKILL.md +16 -16
  189. package/skills/yui-reviewer/SKILL.md +10 -10
  190. package/skills/yui-runtime/SKILL.md +22 -24
  191. package/skills/yui-worker/SKILL.md +16 -18
  192. package/dist/context/runContextContract.js +0 -162
  193. package/dist/executor/turnCompletion.js +0 -126
  194. package/dist/review/taskFinalReviewContractEvent.js +0 -1
  195. package/dist/review/taskFinalReviewContractRebind.js +0 -367
  196. package/dist/run/agentRun.js +0 -356
  197. package/dist/run/rejectedYieldAttempt.js +0 -221
  198. package/dist/run/runControlRequest.js +0 -50
  199. package/dist/run/yieldReceipt.js +0 -65
  200. package/dist/runtime/turnCompletion.js +0 -3
  201. package/dist/scheduler/actionability.js +0 -323
  202. package/dist/scheduler/activeRoleRunDelivery.js +0 -868
  203. package/dist/scheduler/activeTaskProgress.js +0 -126
  204. package/dist/storage/compatibleTaskStore.js +0 -248
  205. package/dist/storage/migration/baseline.js +0 -78
  206. package/dist/storage/migration/classifier.js +0 -51
  207. package/dist/storage/migration/compatibleCodec.js +0 -53
  208. package/dist/storage/migration/engine.js +0 -147
  209. package/dist/storage/migration/index.js +0 -33
  210. package/dist/storage/migration/planner.js +0 -154
  211. package/dist/storage/migration/productionRegistry.js +0 -3931
  212. package/dist/storage/migration/registry.js +0 -169
  213. package/dist/storage/migration/report.js +0 -54
  214. package/dist/storage/migration/types.js +0 -31
  215. package/dist/storage/upgrade/homeClassification.js +0 -353
  216. package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
  217. package/dist/storage/upgrade/migrationReceipt.js +0 -67
  218. package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
  219. package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
  220. package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
  221. package/dist/storage/upgrade/recordVersionScan.js +0 -176
  222. package/dist/storage/upgrade/sqliteFileSet.js +0 -50
  223. package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
  224. package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
  225. package/dist/storage/upgrade/sqliteStateMigration.js +0 -926
  226. package/dist/storage/upgrade/switchProgress.js +0 -80
  227. package/dist/storage/upgrade/upgradeReceipt.js +0 -161
  228. package/dist/storage/upgradeCoordination.js +0 -187
  229. package/dist/storage/upgradeFence.js +0 -366
  230. package/dist/telemetry/telemetryCompaction.js +0 -252
@@ -1,147 +0,0 @@
1
- /**
2
- * The transactional migration engine.
3
- *
4
- * The engine is parameterized over the abstract {@link MigrationTarget} and the
5
- * `latest` supported {@link StorageVersionState}; it never touches a real Home
6
- * and holds no domain list of derived-state fields. All domain knowledge lives
7
- * behind the injected `rebuildDerivedState` / `validateCurrentState` boundary,
8
- * and every step only *declares* its effects.
9
- *
10
- * Flow (execute mode):
11
- * inspect -> plan (reject on missing step) -> detectLiveRuntime (fail-closed
12
- * if active) -> read immutable source -> apply step transforms into a fresh
13
- * output -> rebuildDerivedState(effects) -> validateCurrentState() ->
14
- * atomicSwitchWithBackup -> structured MigrationReport.
15
- *
16
- * Dry-run mode runs the same pipeline through the validation gate, then discards
17
- * the fresh output and never switches.
18
- *
19
- * Invariants: on any failure the source is never switched and stays byte-for-
20
- * byte unchanged, and — because input is immutable and output is fresh — an
21
- * interrupted run is safely retriable (delete partial output and re-run). Once
22
- * the source already equals `latest`, the run is a no-op (`already-current`).
23
- */
24
- import { planMigration } from "./planner.js";
25
- import { collectEffects, toStepSummary } from "./report.js";
26
- import { AmbiguousSwitchError } from "./types.js";
27
- /** Run the transactional migration and return a structured report. Never throws. */
28
- export function runMigration(options) {
29
- const { registry, target, latest, mode } = options;
30
- // 1) inspect — read-only.
31
- const source = target.inspectVersions();
32
- // 2) plan — a missing adjacent step or a future version fails closed here.
33
- const plan = planMigration(registry, source, latest);
34
- if (plan.kind === "blocked") {
35
- return { outcome: "blocked", mode, source, target: latest, blocker: plan.blocker };
36
- }
37
- if (plan.kind === "no-op") {
38
- return { outcome: "already-current", mode, source, target: latest };
39
- }
40
- const stepSummaries = plan.steps.map(toStepSummary);
41
- const effects = collectEffects(plan.steps);
42
- // 3) detectLiveRuntime — refuse to migrate a target a live runtime is holding.
43
- const live = target.detectLiveRuntime();
44
- if (live.active) {
45
- return {
46
- outcome: "active-runtime",
47
- mode,
48
- source,
49
- target: latest,
50
- steps: stepSummaries,
51
- ...(live.detail ? { detail: live.detail } : {})
52
- };
53
- }
54
- // 4) apply steps to a fresh output; the source is only ever read.
55
- let stage = "precondition";
56
- const applied = [];
57
- try {
58
- let snapshot = target.readSource();
59
- for (const planned of plan.steps) {
60
- stage = "precondition";
61
- planned.step.preconditions(snapshot);
62
- stage = "transform";
63
- const next = planned.step.transform(snapshot);
64
- assertFreshOutput(next, snapshot, planned);
65
- snapshot = next;
66
- applied.push(toStepSummary(planned));
67
- }
68
- stage = "write-fresh-output";
69
- target.writeFreshOutput(snapshot);
70
- // 5) injected canonical derived-state rebuild over the fresh output.
71
- stage = "rebuild";
72
- const derived = target.rebuildDerivedState(effects);
73
- // 6) injected canonical validation gate (the real post-migration loader).
74
- stage = "validate";
75
- const validation = target.validateCurrentState();
76
- if (mode === "dry-run") {
77
- // Validate only; never switch. Discard the staged output.
78
- target.discardFreshOutput();
79
- return {
80
- outcome: "dry-run",
81
- mode: "dry-run",
82
- source,
83
- target: latest,
84
- steps: stepSummaries,
85
- effects,
86
- derived,
87
- validation
88
- };
89
- }
90
- // 7) atomic switch with timestamped backup — the only write to the source.
91
- stage = "switch";
92
- const switched = target.atomicSwitchWithBackup();
93
- return {
94
- outcome: "migrated",
95
- mode: "execute",
96
- source,
97
- target: latest,
98
- steps: stepSummaries,
99
- effects,
100
- derived,
101
- validation,
102
- switch: switched
103
- };
104
- }
105
- catch (error) {
106
- // A partially-applied, ambiguous switch is NOT a clean "source unchanged"
107
- // failure: the original was moved aside and could not be restored. Surface it
108
- // as its own outcome so the orchestrator reports a truthful manual recovery
109
- // instead of a false "unchanged" (P1-4).
110
- if (error instanceof AmbiguousSwitchError) {
111
- return {
112
- outcome: "switch-ambiguous",
113
- mode,
114
- source,
115
- target: latest,
116
- steps: stepSummaries,
117
- homePath: error.homePath,
118
- backupPath: error.backupPath,
119
- stagingPath: error.stagingPath,
120
- error: error.message
121
- };
122
- }
123
- return {
124
- outcome: "failed",
125
- mode,
126
- source,
127
- target: latest,
128
- stage,
129
- stepsApplied: applied,
130
- error: error instanceof Error ? error.message : String(error)
131
- };
132
- }
133
- }
134
- /**
135
- * Defend the pure `immutable-input -> fresh-output` contract: a transform must
136
- * return a value distinct from its input (never mutate-and-return the source).
137
- */
138
- function assertFreshOutput(next, previous, planned) {
139
- if (next === previous &&
140
- typeof next === "object" &&
141
- next !== null) {
142
- throw new Error(`Migration step ${planned.axis}` +
143
- `${planned.recordKind ? `/${planned.recordKind}` : ""} ` +
144
- `${planned.fromVersion}->${planned.toVersion} returned its input object; ` +
145
- "transforms must produce a fresh output.");
146
- }
147
- }
@@ -1,33 +0,0 @@
1
- /**
2
- * Generic, pure storage-migration core.
3
- *
4
- * A future-facing, fully unit-testable migration framework over three
5
- * independent monotonic version axes (layout / aggregate / record, where the
6
- * record axis is a `recordKind -> {version, path}` map). The transactional engine
7
- * is parameterized over an abstract {@link MigrationTarget}, so it neither
8
- * touches a real Home nor hardcodes any domain derived-state list. Real wiring
9
- * (the production step graph, canonical rebuild/validate boundary, and target)
10
- * is injected elsewhere.
11
- */
12
- import { CURRENT_AGGREGATE_SCHEMA_VERSION, CURRENT_STORAGE_LAYOUT_VERSION } from "../storageVersions.js";
13
- export * from "./types.js";
14
- export { MigrationRegistry, MigrationRegistryError, createEmptyRegistry } from "./registry.js";
15
- export { planMigration } from "./planner.js";
16
- export { classifyStorage } from "./classifier.js";
17
- export { runMigration } from "./engine.js";
18
- export { collectEffects, describeReport, toStepSummary } from "./report.js";
19
- export { BASELINE_STORAGE_LAYOUT_VERSION, BASELINE_AGGREGATE_SCHEMA_VERSION, BASELINE_RECORD_VERSIONS, BASELINE_STORAGE_VERSION_STATE, baselineStorageVersionState, assertBaselineConsistency } from "./baseline.js";
20
- export { createProductionRegistry, createProductionStorageRegistry, assertRegistryCoversBaselineToCurrent } from "./productionRegistry.js";
21
- export { loadCompatibleSnapshot, writeCurrentSnapshot, StorageCompatibilityError } from "./compatibleCodec.js";
22
- /**
23
- * The current baseline scalar versions, sourced from the single authoritative
24
- * definitions in `storageSchema.ts` (never re-hardcoded here). Callers compose a
25
- * full {@link StorageVersionState} by supplying the record-family map for the
26
- * families they own — the generic core intentionally holds no record list.
27
- */
28
- export function latestScalarVersions() {
29
- return {
30
- layout: CURRENT_STORAGE_LAYOUT_VERSION,
31
- aggregate: CURRENT_AGGREGATE_SCHEMA_VERSION
32
- };
33
- }
@@ -1,154 +0,0 @@
1
- /**
2
- * The cross-axis migration path planner.
3
- *
4
- * Given the source and target (latest-supported) {@link StorageVersionState}s and
5
- * a {@link MigrationRegistry}, it produces a deterministically-ordered plan or a
6
- * precise fail-closed blocker. It performs no I/O and interprets no domain data.
7
- *
8
- * Deterministic order encodes the axis dependency: `layout -> aggregate ->
9
- * record`. Record families are nested inside the aggregate, so their steps run
10
- * after the aggregate reaches its target version; record kinds are visited in
11
- * sorted order and each family's steps ascend by version. Any single missing
12
- * adjacent step, or any axis whose source is newer than supported, fails closed.
13
- */
14
- /**
15
- * Plan the migration from `source` to `target`.
16
- *
17
- * Returns `no-op` when every axis is already current, `runnable` with a fully
18
- * ordered adjacent step chain, or `blocked` with the first fail-closed reason in
19
- * deterministic axis order (`layout`, then `aggregate`, then record kinds sorted).
20
- */
21
- export function planMigration(registry, source, target) {
22
- const ordered = [];
23
- // 1) layout, then 2) aggregate — scalars migrate before any nested record.
24
- for (const axis of ["layout", "aggregate"]) {
25
- const chain = planScalarAxis(registry, axis, source[axis], target[axis]);
26
- if (chain.kind === "blocked")
27
- return { kind: "blocked", blocker: chain.blocker };
28
- ordered.push(...chain.steps);
29
- }
30
- // 3) record families — nested inside the aggregate; visit target kinds in
31
- // sorted order so the plan is deterministic. A target-only family starts at
32
- // the explicit pre-introduction version 0 and therefore requires a registered
33
- // `introduction` step. It is not an aggregate transform or an implicit
34
- // no-op: the record family must pass the same fail-closed delivery gate as
35
- // every later version transition.
36
- const targetKinds = Object.keys(target.record).sort();
37
- for (const recordKind of targetKinds) {
38
- const sourceEntry = source.record[recordKind];
39
- const chain = planRecordFamily(registry, recordKind, sourceEntry?.version ?? 0, target.record[recordKind].version);
40
- if (chain.kind === "blocked")
41
- return { kind: "blocked", blocker: chain.blocker };
42
- ordered.push(...chain.steps);
43
- }
44
- return ordered.length === 0
45
- ? { kind: "no-op" }
46
- : {
47
- kind: "runnable",
48
- path: ordered.some(({ transition }) => transition === "offline-migration")
49
- ? "offline-migration"
50
- : "compatible",
51
- steps: ordered
52
- };
53
- }
54
- function planScalarAxis(registry, axis, from, to) {
55
- return planChain(registry, axis, undefined, from, to);
56
- }
57
- function planRecordFamily(registry, recordKind, from, to) {
58
- return planChain(registry, "record", recordKind, from, to);
59
- }
60
- /**
61
- * Resolve the adjacent step chain that advances one axis from `from` to `to`.
62
- * A source newer than supported is `future-version`; a gap with no registered
63
- * adjacent step is `missing-step`. Both carry a precise reason and action.
64
- */
65
- function planChain(registry, axis, recordKind, from, to) {
66
- const label = axisLabel(axis, recordKind);
67
- if (from > to) {
68
- return {
69
- kind: "blocked",
70
- blocker: {
71
- reason: "future-version",
72
- axis,
73
- ...(recordKind ? { recordKind } : {}),
74
- found: from,
75
- supported: to,
76
- message: `${label} version ${from} is newer than this release supports (${to}).`,
77
- action: "Upgrade to a newer Yui release that understands this version."
78
- }
79
- };
80
- }
81
- const steps = [];
82
- for (let version = from; version < to; version += 1) {
83
- const declaration = registry.lookupDeclaration(axis, recordKind, version);
84
- const registeredStep = registry.lookup(axis, recordKind, version);
85
- if (declaration === undefined && registeredStep !== undefined) {
86
- return {
87
- kind: "blocked",
88
- blocker: {
89
- reason: "missing-declaration",
90
- axis,
91
- ...(recordKind ? { recordKind } : {}),
92
- from: version,
93
- to: version + 1,
94
- message: `No compatible/offline-migration declaration is registered for ` +
95
- `${label} ${version}->${version + 1}.`,
96
- action: "Declare the adjacent change explicitly; do not infer compatibility from its version."
97
- }
98
- };
99
- }
100
- if (declaration === undefined) {
101
- return {
102
- kind: "blocked",
103
- blocker: {
104
- reason: "missing-step",
105
- axis,
106
- ...(recordKind ? { recordKind } : {}),
107
- from: version,
108
- to: version + 1,
109
- message: `No migration step is registered for ${label} ${version}->${version + 1}.`,
110
- action: "This version cannot be migrated by this release; a newer release must provide the step."
111
- }
112
- };
113
- }
114
- const step = declaration.kind === "compatible"
115
- ? {
116
- axis,
117
- ...(recordKind ? { recordKind } : {}),
118
- fromVersion: version,
119
- toVersion: version + 1,
120
- preconditions: declaration.validateSource,
121
- transform: declaration.normalize,
122
- declaredEffects: []
123
- }
124
- : registeredStep;
125
- if (step === undefined) {
126
- return {
127
- kind: "blocked",
128
- blocker: {
129
- reason: "missing-step",
130
- axis,
131
- ...(recordKind ? { recordKind } : {}),
132
- from: version,
133
- to: version + 1,
134
- message: `No migration step is registered for ${label} ${version}->${version + 1}.`,
135
- action: "This offline transition cannot run until this release provides its migration step."
136
- }
137
- };
138
- }
139
- steps.push({
140
- axis,
141
- ...(recordKind ? { recordKind } : {}),
142
- fromVersion: version,
143
- toVersion: version + 1,
144
- transition: declaration.kind,
145
- step
146
- });
147
- }
148
- return { kind: "ok", steps };
149
- }
150
- function axisLabel(axis, recordKind) {
151
- if (axis === "record")
152
- return `record family '${recordKind ?? "?"}'`;
153
- return axis === "layout" ? "storage layout" : "aggregate schema";
154
- }