@zq-silk/yui 0.14.1 → 0.15.0

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 (185) hide show
  1. package/ARCHITECTURE.md +91 -47
  2. package/README.md +275 -145
  3. package/dist/agent/managedRuntimeEnvironment.js +5 -8
  4. package/dist/cli/commandCatalog.js +74 -109
  5. package/dist/cli/helpRenderer.js +1 -2
  6. package/dist/cli/interactionCandidates.js +10 -0
  7. package/dist/cli/interactionPolicy.js +76 -37
  8. package/dist/cli/roleWizard.js +5 -6
  9. package/dist/cli/updateCommand.js +17 -9
  10. package/dist/cli/updateOrchestrator.js +87 -19
  11. package/dist/cli/updatePorts.js +79 -13
  12. package/dist/cli/upgradeCommand.js +105 -23
  13. package/dist/cli.js +268 -231
  14. package/dist/commands/agentCommands.js +13 -0
  15. package/dist/commands/configCommands.js +7 -19
  16. package/dist/commands/configOverview.js +3 -2
  17. package/dist/commands/controllerCommands.js +1 -1
  18. package/dist/commands/durableJobCommands.js +1 -1
  19. package/dist/commands/executionAuditCommands.js +4 -9
  20. package/dist/commands/globalRoleCommands.js +17 -0
  21. package/dist/commands/profileCommands.js +200 -30
  22. package/dist/commands/sessionCommands.js +1 -1
  23. package/dist/commands/taskActor.js +29 -127
  24. package/dist/commands/taskChangeSetCommands.js +1 -3
  25. package/dist/commands/taskCommands.js +1771 -2107
  26. package/dist/commands/taskCompletionGate.js +27 -103
  27. package/dist/commands/taskContextCommand.js +47 -80
  28. package/dist/commands/taskExecutionCommands.js +9 -27
  29. package/dist/commands/taskInputCommands.js +10 -10
  30. package/dist/commands/taskIntegrationCommands.js +69 -61
  31. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  32. package/dist/commands/taskNextActionCommand.js +8 -29
  33. package/dist/commands/taskOverviewCommand.js +25 -3
  34. package/dist/commands/taskPublicationCommands.js +151 -85
  35. package/dist/commands/taskPublicationVerifyCommand.js +181 -0
  36. package/dist/commands/taskRemoteDeliveryCommand.js +134 -0
  37. package/dist/commands/taskRoleRuntimeStatus.js +5 -6
  38. package/dist/commands/taskUpstreamCommands.js +79 -95
  39. package/dist/config/configCatalog.js +1 -1
  40. package/dist/context/contextSnapshot.js +17 -2
  41. package/dist/context/sourceTurnContext.js +30 -0
  42. package/dist/context/turnContextPack.js +107 -48
  43. package/dist/context/turnInputContract.js +11 -4
  44. package/dist/context/wakeNotification.js +84 -22
  45. package/dist/controller/agentRuntimeObserver.js +9 -12
  46. package/dist/controller/clientRuntime.js +13 -13
  47. package/dist/controller/controller.js +11 -11
  48. package/dist/controller/fileSchedulerStoreAdapter.js +262 -219
  49. package/dist/controller/jobControl.js +11 -10
  50. package/dist/controller/resourceInventory.js +6 -6
  51. package/dist/controller/resourceInventoryLinux.js +2 -2
  52. package/dist/controller/runtime.js +18 -61
  53. package/dist/controller/runtimeEventInbox.js +57 -34
  54. package/dist/controller/runtimeEventProcessor.js +36 -96
  55. package/dist/controller/runtimeHookTurnFence.js +33 -57
  56. package/dist/controller/runtimeLaunchCoordinator.js +44 -40
  57. package/dist/controller/runtimeObservationHook.js +18 -12
  58. package/dist/controller/sessionNotify.js +43 -28
  59. package/dist/controller/sessionOwnerReconciliation.js +21 -21
  60. package/dist/controller/structuredProviderObservation.js +13 -16
  61. package/dist/coordination/workMailboxQueue.js +132 -0
  62. package/dist/core/controllerServer.js +6 -5
  63. package/dist/doctor/doctor.js +37 -14
  64. package/dist/domain/agentResultTransport.js +60 -0
  65. package/dist/execution/executionHealth.js +111 -118
  66. package/dist/execution/reviewMainTurn.js +161 -0
  67. package/dist/execution/workItemExecution.js +454 -0
  68. package/dist/execution/workItemExecutionProjection.js +309 -0
  69. package/dist/execution/workItemMainTurn.js +164 -0
  70. package/dist/executor/agentExecutor.js +19 -19
  71. package/dist/executor/executorRegistry.js +7 -28
  72. package/dist/executor/fileRoleLaunchPlanner.js +16 -82
  73. package/dist/external/githubPublicationVerifier.js +114 -0
  74. package/dist/external/gitlabPublicationVerifier.js +158 -0
  75. package/dist/external/pinnedCommandRunner.js +73 -0
  76. package/dist/integration/changeSetManifest.js +0 -3
  77. package/dist/integration/deliveryObligation.js +43 -6
  78. package/dist/integration/gitIntegrationService.js +284 -101
  79. package/dist/integration/integrationAttempt.js +64 -14
  80. package/dist/integration/integrationQueueEntry.js +5 -35
  81. package/dist/integration/integrationQueueService.js +65 -194
  82. package/dist/lifecycle/canonicalLifecycleEvent.js +16 -15
  83. package/dist/lifecycle/exactTurnTerminalization.js +100 -97
  84. package/dist/message/message.js +16 -0
  85. package/dist/observability/executionAudit.js +4 -25
  86. package/dist/observability/faultClassification.js +58 -70
  87. package/dist/observability/orchestrationMetrics.js +8 -50
  88. package/dist/observability/runtimeIdentity.js +48 -50
  89. package/dist/profile/agentProfile.js +60 -15
  90. package/dist/profile/agentProfileRuntime.js +100 -0
  91. package/dist/release/releaseWorkflowPorts.js +5 -68
  92. package/dist/release/runtimeRelease.js +9 -1
  93. package/dist/repository/executionLaneGitSnapshot.js +80 -0
  94. package/dist/repository/gitWorkspace.js +9 -67
  95. package/dist/repository/taskBaseFreshness.js +3 -1
  96. package/dist/repository/taskWorkspaceCoordinator.js +32 -4
  97. package/dist/repository/taskWorkspacePreparer.js +252 -411
  98. package/dist/resources/liveReferences.js +6 -55
  99. package/dist/resources/resourceDiscovery.js +1 -30
  100. package/dist/resources/resourceRegistrar.js +0 -23
  101. package/dist/review/deltaRecheck.js +8 -65
  102. package/dist/review/reviewAcceptance.js +22 -19
  103. package/dist/review/reviewConfig.js +0 -10
  104. package/dist/review/reviewDecision.js +2 -2
  105. package/dist/review/reviewRound.js +147 -273
  106. package/dist/review/reviewerAvailability.js +13 -23
  107. package/dist/role/role.js +3 -0
  108. package/dist/runtime/agentDriverObservation.js +1 -1
  109. package/dist/runtime/agentHost.js +51 -51
  110. package/dist/runtime/builtinAgentDrivers.js +9 -2
  111. package/dist/runtime/codexAppServerRuntime.js +23 -5
  112. package/dist/runtime/exactControlPlane.js +22 -296
  113. package/dist/runtime/firstProgressAdvisory.js +1 -1
  114. package/dist/runtime/index.js +1 -1
  115. package/dist/runtime/launchBroker.js +11 -11
  116. package/dist/runtime/lifecycleReservation.js +2 -2
  117. package/dist/runtime/managedCaller.js +111 -0
  118. package/dist/runtime/ports.js +16 -3
  119. package/dist/runtime/preallocatedNativeSession.js +2 -2
  120. package/dist/runtime/processExitObservation.js +3 -2
  121. package/dist/runtime/providerContinuationReconciliationService.js +1 -1
  122. package/dist/runtime/runtimeBinding.js +1 -1
  123. package/dist/runtime/runtimeObservation.js +33 -16
  124. package/dist/runtime/runtimeSessionCandidate.js +2 -2
  125. package/dist/runtime/runtimeStopReceipt.js +11 -11
  126. package/dist/runtime/sessionLaunchRequest.js +2 -2
  127. package/dist/runtime/sessionOwnerIdentity.js +9 -9
  128. package/dist/runtime/sessionOwnerRegistry.js +13 -13
  129. package/dist/runtime/sessionReconciliation.js +4 -4
  130. package/dist/runtime/sessionTerminationGuard.js +9 -9
  131. package/dist/runtime/sessionTokenMetrics.js +5 -7
  132. package/dist/runtime/structuredProviderHost.js +5 -5
  133. package/dist/runtime/taskRuntimeIsolation.js +24 -24
  134. package/dist/runtime/tmuxAdapters.js +32 -30
  135. package/dist/scheduler/activeRoleTurnDelivery.js +37 -15
  136. package/dist/scheduler/leaderWakeupProcessor.js +78 -55
  137. package/dist/scheduler/roleTurnLiveness.js +6 -6
  138. package/dist/scheduler/roleTurnStall.js +8 -9
  139. package/dist/scheduler/taskExecutionProjection.js +19 -41
  140. package/dist/scheduler/taskObservabilityProjection.js +75 -122
  141. package/dist/storage/currentTaskStore.js +6 -4
  142. package/dist/storage/sqliteSchema.js +135 -80
  143. package/dist/storage/sqliteStore.js +69 -52
  144. package/dist/storage/storageSchema.js +92 -230
  145. package/dist/storage/storageVersions.js +12 -13
  146. package/dist/storage/taskStore.js +8 -8
  147. package/dist/storage/upgrade/upgradeOrchestrator.js +276 -85
  148. package/dist/task/completionReadiness.js +17 -98
  149. package/dist/task/deliveryGuard.js +9 -11
  150. package/dist/task/draftPlan.js +142 -0
  151. package/dist/task/nextAction.js +179 -477
  152. package/dist/task/publicationVerification.js +1 -0
  153. package/dist/task/remoteDelivery.js +233 -0
  154. package/dist/task/task.js +108 -4
  155. package/dist/task/taskRecordReference.js +0 -1
  156. package/dist/turn/turn.js +109 -16
  157. package/dist/verification/verificationGateService.js +0 -26
  158. package/dist/version.js +3 -3
  159. package/dist/web/assets/client/components.js +99 -121
  160. package/dist/web/assets/client/i18n.js +136 -58
  161. package/dist/web/assets/client/view.js +44 -0
  162. package/dist/web/assets/styles/cards.js +3 -15
  163. package/dist/web/assets/styles/widgets.js +4 -0
  164. package/dist/web/webSnapshot.js +29 -14
  165. package/dist/workItem/dependencyGate.js +34 -0
  166. package/dist/workItem/workItem.js +99 -266
  167. package/dist/workspace/workItemChangeSetManager.js +15 -59
  168. package/docs/task-local-identity.md +9 -9
  169. package/i18n/README.zh-CN.md +189 -74
  170. package/package.json +1 -1
  171. package/skills/yui-leader/SKILL.md +272 -782
  172. package/skills/yui-operator/SKILL.md +190 -365
  173. package/skills/yui-reviewer/SKILL.md +40 -33
  174. package/skills/yui-runtime/SKILL.md +22 -0
  175. package/skills/yui-worker/SKILL.md +19 -6
  176. package/dist/execution/candidateConvergence.js +0 -623
  177. package/dist/execution/executionGroup.js +0 -854
  178. package/dist/execution/resourceBroker.js +0 -426
  179. package/dist/executor/launchPlan.js +0 -16
  180. package/dist/review/reviewFinding.js +0 -240
  181. package/dist/review/reviewFindingLedger.js +0 -550
  182. package/dist/review/reviewOutcomeClassifier.js +0 -255
  183. package/dist/scheduler/resourceQueueProjection.js +0 -71
  184. package/dist/storage/upgrade/recordVersions.js +0 -82
  185. package/dist/task/repairWave.js +0 -150
@@ -1,10 +1,10 @@
1
- import { readFileSync } from "node:fs";
1
+ import { existsSync, readdirSync } from "node:fs";
2
2
  import { join } from "node:path";
3
- import { writeTextFileAtomically } from "./durableFile.js";
4
- import { CURRENT_AGGREGATE_SCHEMA_VERSION, CURRENT_STORAGE_LAYOUT_VERSION } from "./storageVersions.js";
5
- import { currentRecordVersions } from "./upgrade/recordVersions.js";
6
- export { CURRENT_STORAGE_LAYOUT_VERSION, CURRENT_AGGREGATE_SCHEMA_VERSION };
7
- export const STORAGE_SCHEMA_FILE = "schema.json";
3
+ import Database from "better-sqlite3";
4
+ import { inspectSqliteSchemaMigrations, storageMigrationPlan } from "./sqliteSchema.js";
5
+ import { CURRENT_STORAGE_VERSION, MIN_SUPPORTED_STORAGE_VERSION } from "./storageVersions.js";
6
+ export { CURRENT_STORAGE_VERSION, MIN_SUPPORTED_STORAGE_VERSION } from "./storageVersions.js";
7
+ export const CURRENT_DATABASE_FILENAME = "yui.db";
8
8
  export class StorageSchemaError extends Error {
9
9
  code;
10
10
  constructor(code, message, options) {
@@ -13,257 +13,119 @@ export class StorageSchemaError extends Error {
13
13
  this.code = code;
14
14
  }
15
15
  }
16
+ /**
17
+ * Inspect the one authoritative SQLite migration head without changing it.
18
+ *
19
+ * `schema.json` and `state.json` are recognized only to prevent setup from
20
+ * overwriting an old Home whose SQLite authority is missing. They are not
21
+ * version authorities for current Homes.
22
+ */
16
23
  export function inspectStorageSchema(rootDir) {
17
- const manifestPath = join(rootDir, STORAGE_SCHEMA_FILE);
18
- const raw = readOptionalText(manifestPath);
19
- if (raw === null) {
24
+ const databasePath = join(rootDir, CURRENT_DATABASE_FILENAME);
25
+ const hasPreBaselineEvidence = existsSync(join(rootDir, "schema.json")) || existsSync(join(rootDir, "state.json"));
26
+ if (hasPreBaselineEvidence) {
20
27
  return {
21
- status: "uninitialized",
22
- latestVersion: CURRENT_STORAGE_LAYOUT_VERSION,
23
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
24
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
25
- manifestPath
28
+ status: "unsupported",
29
+ direction: "older",
30
+ currentVersion: 0,
31
+ latestVersion: CURRENT_STORAGE_VERSION,
32
+ minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
33
+ databasePath
26
34
  };
27
35
  }
28
- let manifest;
29
- try {
30
- manifest = parseStorageManifest(raw);
31
- }
32
- catch (error) {
36
+ if (!existsSync(databasePath)) {
37
+ if (existsSync(rootDir)) {
38
+ try {
39
+ if (readdirSync(rootDir).length > 0) {
40
+ return invalid(databasePath, new Error("The authoritative yui.db is missing from a non-empty Home."));
41
+ }
42
+ }
43
+ catch (error) {
44
+ return invalid(databasePath, error);
45
+ }
46
+ }
33
47
  return {
34
- status: "invalid",
35
- latestVersion: CURRENT_STORAGE_LAYOUT_VERSION,
36
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
37
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
38
- manifestPath,
39
- detail: error instanceof Error ? error.message : String(error)
48
+ status: "uninitialized",
49
+ latestVersion: CURRENT_STORAGE_VERSION,
50
+ minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
51
+ databasePath
40
52
  };
41
53
  }
42
- if (manifest.storageVersion !== CURRENT_STORAGE_LAYOUT_VERSION) {
43
- return {
44
- status: "unsupported",
45
- incompatibleComponent: "layout",
46
- direction: manifest.storageVersion < CURRENT_STORAGE_LAYOUT_VERSION ? "older" : "newer",
47
- currentVersion: manifest.storageVersion,
48
- latestVersion: CURRENT_STORAGE_LAYOUT_VERSION,
49
- currentLayoutVersion: manifest.storageVersion,
50
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
51
- currentAggregateSchemaVersion: manifest.aggregateSchemaVersion,
52
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
53
- manifestPath
54
- };
54
+ let database;
55
+ try {
56
+ database = new Database(databasePath, { readonly: true, fileMustExist: true });
55
57
  }
56
- if (manifest.aggregateSchemaVersion !== CURRENT_AGGREGATE_SCHEMA_VERSION) {
57
- return {
58
- status: "unsupported",
59
- incompatibleComponent: "aggregate",
60
- direction: manifest.aggregateSchemaVersion < CURRENT_AGGREGATE_SCHEMA_VERSION
61
- ? "older"
62
- : "newer",
63
- currentVersion: manifest.aggregateSchemaVersion,
64
- latestVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
65
- currentLayoutVersion: manifest.storageVersion,
66
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
67
- currentAggregateSchemaVersion: manifest.aggregateSchemaVersion,
68
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
69
- manifestPath
70
- };
58
+ catch (error) {
59
+ return invalid(databasePath, error);
71
60
  }
72
- const currentRecords = currentRecordVersions();
73
- if (manifest.recordVersions === undefined) {
74
- return {
75
- status: "unsupported",
76
- incompatibleComponent: "record",
77
- direction: "older",
78
- currentVersion: 0,
79
- latestVersion: 1,
80
- currentLayoutVersion: manifest.storageVersion,
81
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
82
- currentAggregateSchemaVersion: manifest.aggregateSchemaVersion,
83
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
84
- manifestPath
61
+ try {
62
+ const migration = inspectSqliteSchemaMigrations(database);
63
+ const fields = {
64
+ currentVersion: migration.currentVersion,
65
+ latestVersion: CURRENT_STORAGE_VERSION,
66
+ minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
67
+ databasePath
85
68
  };
86
- }
87
- for (const [kind, currentEntry] of Object.entries(currentRecords)) {
88
- const persisted = manifest.recordVersions[kind];
89
- if (persisted === undefined) {
90
- return {
91
- status: "unsupported",
92
- incompatibleComponent: "record",
93
- direction: "older",
94
- currentVersion: 0,
95
- latestVersion: currentEntry.version,
96
- currentLayoutVersion: manifest.storageVersion,
97
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
98
- currentAggregateSchemaVersion: manifest.aggregateSchemaVersion,
99
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
100
- recordFamily: kind,
101
- manifestPath
102
- };
69
+ if (migration.currentVersion === CURRENT_STORAGE_VERSION) {
70
+ return { status: "current", ...fields };
71
+ }
72
+ if (migration.currentVersion > CURRENT_STORAGE_VERSION) {
73
+ return { status: "unsupported", direction: "newer", ...fields };
103
74
  }
104
- if (persisted !== currentEntry.version) {
75
+ if (migration.currentVersion < MIN_SUPPORTED_STORAGE_VERSION) {
76
+ return { status: "unsupported", direction: "older", ...fields };
77
+ }
78
+ const plan = storageMigrationPlan(migration.currentVersion);
79
+ if (plan === null) {
105
80
  return {
106
- status: "unsupported",
107
- incompatibleComponent: "record",
108
- direction: persisted < currentEntry.version ? "older" : "newer",
109
- currentVersion: persisted,
110
- latestVersion: currentEntry.version,
111
- currentLayoutVersion: manifest.storageVersion,
112
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
113
- currentAggregateSchemaVersion: manifest.aggregateSchemaVersion,
114
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
115
- recordFamily: kind,
116
- manifestPath
81
+ status: "invalid",
82
+ latestVersion: CURRENT_STORAGE_VERSION,
83
+ minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
84
+ databasePath,
85
+ detail: `Storage migration registry has no complete path from `
86
+ + `${migration.currentVersion} to ${CURRENT_STORAGE_VERSION}.`
117
87
  };
118
88
  }
89
+ return {
90
+ status: "upgradeable",
91
+ pendingVersions: plan.map(({ toVersion }) => toVersion),
92
+ ...fields
93
+ };
119
94
  }
120
- return {
121
- status: "current",
122
- currentVersion: manifest.storageVersion,
123
- latestVersion: CURRENT_STORAGE_LAYOUT_VERSION,
124
- currentLayoutVersion: manifest.storageVersion,
125
- latestLayoutVersion: CURRENT_STORAGE_LAYOUT_VERSION,
126
- currentAggregateSchemaVersion: manifest.aggregateSchemaVersion,
127
- latestAggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
128
- manifestPath
129
- };
130
- }
131
- export function ensureStorageSchema(rootDir, now = new Date()) {
132
- const state = inspectStorageSchema(rootDir);
133
- if (state.status === "uninitialized") {
134
- writeCurrentStorageManifest(rootDir, now);
135
- return;
95
+ catch (error) {
96
+ return invalid(databasePath, error);
136
97
  }
137
- requireInspectedSchema(state);
138
- }
139
- export function requireStorageSchema(rootDir) {
140
- requireInspectedSchema(inspectStorageSchema(rootDir));
141
- }
142
- /** Persist the current three-axis manifest through the existing atomic-file seam. */
143
- export function writeCurrentStorageManifest(rootDir, now = new Date()) {
144
- const recordVersions = {};
145
- for (const [kind, entry] of Object.entries(currentRecordVersions())) {
146
- recordVersions[kind] = entry.version;
98
+ finally {
99
+ database.close();
147
100
  }
148
- const manifest = {
149
- schemaVersion: 1,
150
- storageVersion: CURRENT_STORAGE_LAYOUT_VERSION,
151
- aggregateSchemaVersion: CURRENT_AGGREGATE_SCHEMA_VERSION,
152
- recordVersions,
153
- updatedAt: now.toISOString()
154
- };
155
- writeTextFileAtomically(join(rootDir, STORAGE_SCHEMA_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
156
101
  }
157
- function requireInspectedSchema(state) {
102
+ /** Require the current storage contract without normalizing historical data. */
103
+ export function requireCurrentStorageSchema(rootDir) {
104
+ const state = inspectStorageSchema(rootDir);
158
105
  switch (state.status) {
159
106
  case "current":
160
107
  return;
161
108
  case "uninitialized":
162
109
  throw new StorageSchemaError("STORAGE_UNINITIALIZED", "Yui storage is not initialized. Run `yui setup`.");
163
110
  case "invalid":
164
- throw new StorageSchemaError("STORAGE_SCHEMA_INVALID", `Invalid storage schema manifest at ${state.manifestPath}: ${state.detail}`);
111
+ throw new StorageSchemaError("STORAGE_SCHEMA_INVALID", `Invalid storage at ${state.databasePath}: ${state.detail}`);
112
+ case "upgradeable":
113
+ throw new StorageSchemaError("STORAGE_SCHEMA_UNSUPPORTED", `Storage version ${state.currentVersion} requires an explicit upgrade to `
114
+ + `${state.latestVersion}. Run \`yui upgrade\` or \`yui update\`.`);
165
115
  case "unsupported":
166
- throw unsupportedVersion(state.currentVersion, state.latestVersion, state.incompatibleComponent, state.recordFamily);
116
+ throw new StorageSchemaError("STORAGE_SCHEMA_UNSUPPORTED", state.direction === "newer"
117
+ ? `Storage version ${state.currentVersion} is newer than supported `
118
+ + `${state.latestVersion}; use a newer Yui release.`
119
+ : `Storage version ${state.currentVersion} is older than the minimum supported `
120
+ + `${state.minimumSupportedVersion}.`);
167
121
  }
168
122
  }
169
- function unsupportedVersion(current, required, component, recordFamily) {
170
- if (component === "record" && recordFamily === undefined) {
171
- return new StorageSchemaError("STORAGE_SCHEMA_UNSUPPORTED", "This Home predates the current record-version manifest. Preserve it for inspection and initialize a new Home.");
172
- }
173
- const label = component === "layout"
174
- ? "Storage layout"
175
- : component === "aggregate"
176
- ? "Aggregate schema"
177
- : `Record family '${recordFamily}'`;
178
- if (current < required) {
179
- return new StorageSchemaError("STORAGE_SCHEMA_UNSUPPORTED", `${label} ${current} is older than required ${component} version ${required}; no migration is available in this Yui release.`);
180
- }
181
- return new StorageSchemaError("STORAGE_SCHEMA_UNSUPPORTED", `${label} ${current} is newer than supported ${component} version ${required}; use a newer Yui release.`);
182
- }
183
- function parseStorageManifest(raw) {
184
- const value = parseJsonObject(raw, "Storage schema manifest");
185
- return parseStorageSchemaManifest(value);
186
- }
187
- /** Strictly parse one already-decoded manifest object through the shared contract. */
188
- export function parseStorageSchemaManifest(value) {
189
- if (!isRecord(value))
190
- throw new Error("Storage schema manifest must be an object");
191
- assertKeys(value, ["schemaVersion", "storageVersion", "aggregateSchemaVersion", "updatedAt"], ["recordVersions"], "Storage schema manifest");
192
- if (value.schemaVersion !== 1)
193
- throw new Error("schemaVersion must be 1");
194
- if (!Number.isInteger(value.storageVersion) || value.storageVersion < 1) {
195
- throw new Error("storageVersion must be a positive integer");
196
- }
197
- const aggregateSchemaVersion = value.aggregateSchemaVersion;
198
- if (!Number.isInteger(aggregateSchemaVersion) || aggregateSchemaVersion < 1) {
199
- throw new Error("aggregateSchemaVersion must be a positive integer");
200
- }
201
- if (typeof value.updatedAt !== "string" || !Number.isFinite(Date.parse(value.updatedAt))) {
202
- throw new Error("updatedAt must be an ISO timestamp");
203
- }
204
- let recordVersions;
205
- if (Object.hasOwn(value, "recordVersions")) {
206
- if (!isRecord(value.recordVersions))
207
- throw new Error("recordVersions must be an object");
208
- const known = currentRecordVersions();
209
- const kinds = Object.keys(value.recordVersions);
210
- const unknown = kinds.filter((kind) => !Object.hasOwn(known, kind));
211
- if (unknown.length > 0) {
212
- throw new Error(`recordVersions has unknown family: ${unknown[0]}`);
213
- }
214
- const parsed = {};
215
- for (const kind of kinds) {
216
- const version = value.recordVersions[kind];
217
- if (!Number.isInteger(version) || version < 1) {
218
- throw new Error(`recordVersions['${kind}'] must be a positive integer`);
219
- }
220
- parsed[kind] = version;
221
- }
222
- recordVersions = Object.freeze(parsed);
223
- }
123
+ function invalid(databasePath, error) {
224
124
  return {
225
- schemaVersion: 1,
226
- storageVersion: value.storageVersion,
227
- aggregateSchemaVersion: aggregateSchemaVersion,
228
- ...(recordVersions === undefined ? {} : { recordVersions }),
229
- updatedAt: value.updatedAt
125
+ status: "invalid",
126
+ latestVersion: CURRENT_STORAGE_VERSION,
127
+ minimumSupportedVersion: MIN_SUPPORTED_STORAGE_VERSION,
128
+ databasePath,
129
+ detail: error instanceof Error ? error.message : String(error)
230
130
  };
231
131
  }
232
- /** Read and strictly parse the durable manifest through the same contract. */
233
- export function readStorageSchemaManifest(rootDir) {
234
- return parseStorageManifest(readFileSync(join(rootDir, STORAGE_SCHEMA_FILE), "utf8"));
235
- }
236
- function parseJsonObject(raw, label) {
237
- let value;
238
- try {
239
- value = JSON.parse(raw);
240
- }
241
- catch (error) {
242
- throw new Error(`${label} is not valid JSON`, { cause: error });
243
- }
244
- if (!isRecord(value))
245
- throw new Error(`${label} must be an object`);
246
- return value;
247
- }
248
- function assertKeys(value, requiredKeys, optionalKeys, label) {
249
- const expected = new Set([...requiredKeys, ...optionalKeys]);
250
- const unknown = Object.keys(value).filter((key) => !expected.has(key));
251
- const missing = requiredKeys.filter((key) => !Object.hasOwn(value, key));
252
- if (unknown.length > 0)
253
- throw new Error(`${label} has unknown field: ${unknown[0]}`);
254
- if (missing.length > 0)
255
- throw new Error(`${label} is missing field: ${missing[0]}`);
256
- }
257
- function readOptionalText(path) {
258
- try {
259
- return readFileSync(path, "utf8");
260
- }
261
- catch (error) {
262
- if (error instanceof Error && "code" in error && error.code === "ENOENT")
263
- return null;
264
- throw error;
265
- }
266
- }
267
- function isRecord(value) {
268
- return typeof value === "object" && value !== null && !Array.isArray(value);
269
- }
@@ -1,17 +1,16 @@
1
1
  /**
2
- * Scalar storage version constants.
2
+ * The one durable compatibility axis for a Yui Home.
3
3
  *
4
- * These live in their own module so that `storageSchema.ts`, `recordVersions.ts`,
5
- * and `taskStore.ts` can all import them without creating a circular dependency.
6
- * `storageSchema.ts` re-exports them as the public storage-contract boundary.
7
- */
8
- /**
9
- * Version of the on-disk layout (`schema.json` plus the SQLite database).
4
+ * Version 1 is the clean baseline introduced by Yui 0.15.0: SQLite's migration
5
+ * ledger is authoritative and the historical layout/aggregate/record-version
6
+ * manifest is not part of the active Home. Pre-0.15.0 Homes are outside this
7
+ * compatibility line and remain untouched.
10
8
  *
11
- * Layout 8 is the current SQLite WAL control-plane layout: the authoritative
12
- * store is `yui.db`. Layout 8 is the only layout this release reads and writes;
13
- * older Homes are rejected and must not be upgraded in place.
9
+ * Runtime code reads only {@link CURRENT_STORAGE_VERSION}. The explicit
10
+ * upgrade boundary carries every forward migration from
11
+ * {@link MIN_SUPPORTED_STORAGE_VERSION} to the current version so one target
12
+ * CLI can upgrade any valid Home in that interval without installing
13
+ * intermediate Yui releases.
14
14
  */
15
- export const CURRENT_STORAGE_LAYOUT_VERSION = 8;
16
- /** Version of the logical aggregates persisted in SQLite. */
17
- export const CURRENT_AGGREGATE_SCHEMA_VERSION = 21;
15
+ export const MIN_SUPPORTED_STORAGE_VERSION = 1;
16
+ export const CURRENT_STORAGE_VERSION = 1;
@@ -13,18 +13,18 @@ export const CURRENT_CONFIG_SCHEMA_VERSION = 6;
13
13
  /** Current SQLite payload-family versions owned by this storage boundary. */
14
14
  export const CURRENT_CONFIGURED_AGENT_SCHEMA_VERSION = 2;
15
15
  export const CURRENT_PROJECT_SCHEMA_VERSION = 5;
16
- export const CURRENT_AGENT_PROFILE_SCHEMA_VERSION = 2;
16
+ export const CURRENT_AGENT_PROFILE_SCHEMA_VERSION = 3;
17
17
  export const CURRENT_GLOBAL_ROLE_SCHEMA_VERSION = 3;
18
- export const CURRENT_GLOBAL_ROLE_SESSION_SET_SCHEMA_VERSION = 4;
19
- export const CURRENT_TASK_SCHEMA_VERSION = 6;
18
+ export const CURRENT_GLOBAL_ROLE_SESSION_SET_SCHEMA_VERSION = 5;
19
+ export const CURRENT_TASK_SCHEMA_VERSION = 7;
20
20
  export const CURRENT_TASK_BRIEF_SCHEMA_VERSION = 2;
21
21
  export const CURRENT_CONTEXT_SNAPSHOT_SCHEMA_VERSION = 1;
22
22
  export const CURRENT_TASK_ROLE_SCHEMA_VERSION = 4;
23
23
  export const CURRENT_MANAGED_WORKSPACE_SCHEMA_VERSION = 2;
24
- export const CURRENT_WORK_ITEM_SCHEMA_VERSION = 13;
25
- export const CURRENT_REVIEW_ROUND_SCHEMA_VERSION = 6;
24
+ export const CURRENT_WORK_ITEM_SCHEMA_VERSION = 15;
25
+ export const CURRENT_REVIEW_ROUND_SCHEMA_VERSION = 8;
26
26
  export const CURRENT_CHANGE_SET_SCHEMA_VERSION = 4;
27
- export const CURRENT_INTEGRATION_ATTEMPT_SCHEMA_VERSION = 5;
27
+ export const CURRENT_INTEGRATION_ATTEMPT_SCHEMA_VERSION = 6;
28
28
  export const CURRENT_MESSAGE_SCHEMA_VERSION = 3;
29
29
  export const CURRENT_INPUT_REQUEST_SCHEMA_VERSION = 3;
30
30
  export const CURRENT_DECISION_SCHEMA_VERSION = 1;
@@ -65,8 +65,8 @@ export function executionLaneActiveTurnKeyParts(key) {
65
65
  /**
66
66
  * Nested-record versions consumed by the current SQLite payload validators.
67
67
  */
68
- export const CURRENT_TASK_ROLE_SESSION_SET_SCHEMA_VERSION = 11;
69
- export const CURRENT_TURN_SCHEMA_VERSION = 1;
68
+ export const CURRENT_TASK_ROLE_SESSION_SET_SCHEMA_VERSION = 12;
69
+ export const CURRENT_TURN_SCHEMA_VERSION = 5;
70
70
  export const CURRENT_INTEGRATION_QUEUE_SCHEMA_VERSION = 1;
71
71
  export class StorageRecordError extends Error {
72
72
  constructor(message) { super(message); this.name = "StorageRecordError"; }