@zq-silk/yui 0.13.9 → 0.14.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 (229) hide show
  1. package/ARCHITECTURE.md +69 -428
  2. package/README.md +108 -298
  3. package/dist/agent/managedRuntimeEnvironment.js +2 -2
  4. package/dist/cli/commandCatalog.js +39 -77
  5. package/dist/cli/interactionCandidates.js +4 -4
  6. package/dist/cli/interactionPolicy.js +7 -10
  7. package/dist/cli/invocationRouter.js +1 -1
  8. package/dist/cli/updateCommand.js +6 -27
  9. package/dist/cli/updateOrchestrator.js +63 -484
  10. package/dist/cli/updatePorts.js +15 -333
  11. package/dist/cli/upgradeCommand.js +8 -65
  12. package/dist/cli.js +57 -242
  13. package/dist/commands/configCommands.js +11 -62
  14. package/dist/commands/executionAuditCommands.js +23 -23
  15. package/dist/commands/globalRoleCommands.js +2 -7
  16. package/dist/commands/jobCommands.js +1 -4
  17. package/dist/commands/projectCommands.js +5 -5
  18. package/dist/commands/releaseCommands.js +3 -10
  19. package/dist/commands/resourcesCommands.js +2 -2
  20. package/dist/commands/sessionCommands.js +2 -2
  21. package/dist/commands/taskActor.js +31 -39
  22. package/dist/commands/taskChangeSetCommands.js +5 -12
  23. package/dist/commands/taskCommands.js +464 -1249
  24. package/dist/commands/taskContextCommand.js +35 -36
  25. package/dist/commands/taskExecutionCommands.js +33 -46
  26. package/dist/commands/taskInputCommands.js +20 -42
  27. package/dist/commands/taskNextActionCommand.js +9 -9
  28. package/dist/commands/taskOverviewCommand.js +56 -95
  29. package/dist/commands/taskRoleRuntimeStatus.js +77 -107
  30. package/dist/commands/taskUpstreamCommands.js +3 -3
  31. package/dist/commands/taskWorkspaceCommands.js +7 -79
  32. package/dist/commands/telemetryCommands.js +32 -124
  33. package/dist/commands/workflowCommands.js +3 -3
  34. package/dist/completion/fileCompletionManager.js +1 -1
  35. package/dist/config/configCatalog.js +4 -6
  36. package/dist/config/yuiConfig.js +6 -43
  37. package/dist/context/dispatchContext.js +14 -30
  38. package/dist/context/roleSessionContext.js +2 -2
  39. package/dist/context/sessionBootstrapManifest.js +2 -2
  40. package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
  41. package/dist/context/turnInputContract.js +204 -0
  42. package/dist/context/wakeNotification.js +2 -2
  43. package/dist/controller/agentRuntimeObserver.js +18 -18
  44. package/dist/controller/clientRuntime.js +13 -20
  45. package/dist/controller/controller.js +89 -116
  46. package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
  47. package/dist/controller/jobControl.js +17 -17
  48. package/dist/controller/resourceInventory.js +6 -6
  49. package/dist/controller/resourceInventoryLinux.js +38 -59
  50. package/dist/controller/resourceInventoryRpc.js +3 -3
  51. package/dist/controller/resourceInventoryWorker.js +1 -1
  52. package/dist/controller/runtime.js +46 -53
  53. package/dist/controller/runtimeEventInbox.js +23 -31
  54. package/dist/controller/runtimeEventProcessor.js +15 -15
  55. package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
  56. package/dist/controller/runtimeLaunchCoordinator.js +3 -3
  57. package/dist/controller/runtimeObservationHook.js +11 -8
  58. package/dist/controller/sessionNotify.js +11 -11
  59. package/dist/controller/structuredProviderObservation.js +89 -16
  60. package/dist/coordination/workMailbox.js +309 -579
  61. package/dist/coordination/workMailboxQueue.js +5 -6
  62. package/dist/core/controllerClient.js +1 -91
  63. package/dist/core/controllerServer.js +3 -6
  64. package/dist/doctor/doctor.js +51 -314
  65. package/dist/execution/candidateConvergence.js +3 -3
  66. package/dist/execution/executionGroup.js +32 -33
  67. package/dist/execution/executionHealth.js +36 -38
  68. package/dist/execution/resourceBroker.js +12 -12
  69. package/dist/executor/agentExecutor.js +30 -265
  70. package/dist/executor/effectiveLaunch.js +9 -19
  71. package/dist/executor/executorRegistry.js +43 -17
  72. package/dist/executor/fileRoleLaunchPlanner.js +56 -56
  73. package/dist/executor/launchPlan.js +3 -3
  74. package/dist/executor/workspacePreflightClassification.js +16 -16
  75. package/dist/grant/capabilityGrant.js +20 -25
  76. package/dist/input/inputRequest.js +12 -12
  77. package/dist/integration/changeSet.js +9 -13
  78. package/dist/integration/changeSetManifest.js +1 -1
  79. package/dist/integration/gitIntegrationService.js +2 -2
  80. package/dist/integration/integrationQueueService.js +5 -21
  81. package/dist/integration/overlapDiagnostics.js +2 -2
  82. package/dist/interaction/operatorPresentation.js +1 -1
  83. package/dist/job/jobRunner.js +1 -1
  84. package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
  85. package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
  86. package/dist/message/message.js +6 -6
  87. package/dist/observability/executionAudit.js +74 -86
  88. package/dist/observability/faultClassification.js +7 -24
  89. package/dist/observability/orchestrationMetrics.js +5 -5
  90. package/dist/observability/runtimeIdentity.js +34 -101
  91. package/dist/profile/agentProfile.js +1 -1
  92. package/dist/release/cliHomeReleaseFence.js +3 -3
  93. package/dist/release/releaseWorkflowEngine.js +6 -10
  94. package/dist/release/releaseWorkflowPorts.js +2 -2
  95. package/dist/release/workflowFileLock.js +1 -1
  96. package/dist/repository/checkoutSwap.js +1 -1
  97. package/dist/repository/gitWorkspace.js +0 -13
  98. package/dist/repository/project.js +1 -1
  99. package/dist/repository/projectMaintenanceLock.js +1 -2
  100. package/dist/repository/taskBaseFreshness.js +13 -13
  101. package/dist/repository/taskWorkspaceCoordinator.js +21 -25
  102. package/dist/repository/taskWorkspaceIdentity.js +8 -21
  103. package/dist/repository/taskWorkspacePreparer.js +63 -620
  104. package/dist/resources/autoResourceGc.js +3 -3
  105. package/dist/resources/liveReferences.js +1 -1
  106. package/dist/resources/resourceGc.js +1 -1
  107. package/dist/resources/sqliteResourceRegistry.js +1 -1
  108. package/dist/review/reviewDecision.js +7 -7
  109. package/dist/review/reviewFindingLedger.js +1 -1
  110. package/dist/review/reviewOutcomeClassifier.js +35 -50
  111. package/dist/review/reviewRound.js +14 -25
  112. package/dist/review/reviewerAvailability.js +4 -4
  113. package/dist/review/taskFinalReviewContractResolution.js +41 -0
  114. package/dist/role/role.js +6 -3
  115. package/dist/runtime/agentDriver.js +4 -0
  116. package/dist/runtime/agentHost.js +151 -36
  117. package/dist/runtime/builtinAgentDrivers.js +79 -2
  118. package/dist/runtime/codexAppServerRuntime.js +122 -0
  119. package/dist/runtime/continuationManager.js +3 -5
  120. package/dist/runtime/exactControlPlane.js +17 -42
  121. package/dist/runtime/firstProgressAdvisory.js +1 -1
  122. package/dist/runtime/index.js +2 -2
  123. package/dist/runtime/launchDiagnostics.js +2 -2
  124. package/dist/runtime/lifecycleReservation.js +4 -4
  125. package/dist/runtime/processExitObservation.js +1 -1
  126. package/dist/runtime/processExitOutbox.js +0 -32
  127. package/dist/runtime/promptEnvelope.js +9 -9
  128. package/dist/runtime/providerContinuation.js +2 -2
  129. package/dist/runtime/providerContinuationReconciliationService.js +2 -2
  130. package/dist/runtime/providerRuntimeIdentity.js +76 -24
  131. package/dist/runtime/recentTurnIds.js +38 -0
  132. package/dist/runtime/runtimeContinuationProjection.js +2 -2
  133. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  134. package/dist/runtime/runtimeObservation.js +58 -21
  135. package/dist/runtime/runtimeProjection.js +19 -27
  136. package/dist/runtime/sessionLaunchRequest.js +2 -2
  137. package/dist/runtime/structuredProviderHost.js +177 -12
  138. package/dist/runtime/tmuxAdapters.js +46 -11
  139. package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
  140. package/dist/scheduler/leaderWakeupProcessor.js +147 -445
  141. package/dist/scheduler/operatorEvent.js +4 -6
  142. package/dist/scheduler/resourceQueueProjection.js +71 -0
  143. package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
  144. package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
  145. package/dist/scheduler/taskExecutionProjection.js +99 -99
  146. package/dist/scheduler/taskObservabilityProjection.js +10 -10
  147. package/dist/scheduler/taskWake.js +4 -4
  148. package/dist/scheduler/wakeReason.js +6 -10
  149. package/dist/scheduler/wakeupQueue.js +0 -9
  150. package/dist/setup/setupCommand.js +2 -2
  151. package/dist/storage/currentTaskStore.js +46 -0
  152. package/dist/storage/persistenceWorker.js +1 -1
  153. package/dist/storage/sqliteSchema.js +81 -485
  154. package/dist/storage/sqliteStore.js +206 -365
  155. package/dist/storage/storageSchema.js +1 -15
  156. package/dist/storage/storageVersions.js +8 -9
  157. package/dist/storage/storeRpc.js +10 -34
  158. package/dist/storage/taskStore.js +63 -3415
  159. package/dist/storage/upgrade/recordVersions.js +55 -149
  160. package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
  161. package/dist/task/completionReadiness.js +5 -5
  162. package/dist/task/deliveryGuard.js +10 -10
  163. package/dist/task/nextAction.js +74 -77
  164. package/dist/task/task.js +2 -4
  165. package/dist/task/taskRecordReference.js +3 -3
  166. package/dist/task/taskRecordRetirement.js +1 -1
  167. package/dist/telemetry/sqliteTelemetryStore.js +53 -53
  168. package/dist/telemetry/telemetryConfig.js +14 -14
  169. package/dist/telemetry/telemetryWiring.js +8 -14
  170. package/dist/turn/turn.js +356 -0
  171. package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
  172. package/dist/verification/gateArtifactStore.js +2 -2
  173. package/dist/web/assets/client/app.js +1 -1
  174. package/dist/web/assets/client/components.js +29 -54
  175. package/dist/web/assets/client/i18n.js +17 -37
  176. package/dist/web/assets/client/view.js +37 -37
  177. package/dist/web/assets/shell.js +1 -1
  178. package/dist/web/assets/styles/cards.js +5 -5
  179. package/dist/web/assets/styles/widgets.js +1 -2
  180. package/dist/web/webSnapshot.js +65 -60
  181. package/dist/workItem/workItem.js +11 -11
  182. package/dist/workspace/workItemChangeSetManager.js +1 -1
  183. package/docs/task-local-identity.md +5 -5
  184. package/i18n/README.zh-CN.md +41 -54
  185. package/package.json +1 -1
  186. package/skills/yui-leader/SKILL.md +85 -83
  187. package/skills/yui-operator/SKILL.md +16 -16
  188. package/skills/yui-reviewer/SKILL.md +10 -10
  189. package/skills/yui-runtime/SKILL.md +17 -18
  190. package/skills/yui-worker/SKILL.md +16 -18
  191. package/dist/context/runContextContract.js +0 -162
  192. package/dist/executor/turnCompletion.js +0 -126
  193. package/dist/review/taskFinalReviewContractEvent.js +0 -1
  194. package/dist/review/taskFinalReviewContractRebind.js +0 -367
  195. package/dist/run/agentRun.js +0 -356
  196. package/dist/run/rejectedYieldAttempt.js +0 -221
  197. package/dist/run/runControlRequest.js +0 -50
  198. package/dist/run/yieldReceipt.js +0 -65
  199. package/dist/runtime/turnCompletion.js +0 -3
  200. package/dist/scheduler/actionability.js +0 -323
  201. package/dist/scheduler/activeRoleRunDelivery.js +0 -868
  202. package/dist/scheduler/activeTaskProgress.js +0 -126
  203. package/dist/storage/compatibleTaskStore.js +0 -248
  204. package/dist/storage/migration/baseline.js +0 -78
  205. package/dist/storage/migration/classifier.js +0 -51
  206. package/dist/storage/migration/compatibleCodec.js +0 -53
  207. package/dist/storage/migration/engine.js +0 -147
  208. package/dist/storage/migration/index.js +0 -33
  209. package/dist/storage/migration/planner.js +0 -154
  210. package/dist/storage/migration/productionRegistry.js +0 -3931
  211. package/dist/storage/migration/registry.js +0 -169
  212. package/dist/storage/migration/report.js +0 -54
  213. package/dist/storage/migration/types.js +0 -31
  214. package/dist/storage/upgrade/homeClassification.js +0 -353
  215. package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
  216. package/dist/storage/upgrade/migrationReceipt.js +0 -67
  217. package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
  218. package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
  219. package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
  220. package/dist/storage/upgrade/recordVersionScan.js +0 -176
  221. package/dist/storage/upgrade/sqliteFileSet.js +0 -50
  222. package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
  223. package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
  224. package/dist/storage/upgrade/sqliteStateMigration.js +0 -918
  225. package/dist/storage/upgrade/switchProgress.js +0 -80
  226. package/dist/storage/upgrade/upgradeReceipt.js +0 -161
  227. package/dist/storage/upgradeCoordination.js +0 -187
  228. package/dist/storage/upgradeFence.js +0 -366
  229. package/dist/telemetry/telemetryCompaction.js +0 -252
@@ -1,4 +1,4 @@
1
- import { accessSync, constants, existsSync, lstatSync, readFileSync } from "node:fs";
1
+ import { accessSync, constants, existsSync, lstatSync } from "node:fs";
2
2
  import { isAbsolute, join } from "node:path";
3
3
  import Database from "better-sqlite3";
4
4
  import { configuredAgentToDefinition, resolveAgentEnvironment } from "../agent/agent.js";
@@ -10,16 +10,11 @@ import { resolveEffectiveLaunch } from "../executor/effectiveLaunch.js";
10
10
  import { compileRoleSessionContext } from "../context/roleSessionContext.js";
11
11
  import { usageError } from "../errors/cliError.js";
12
12
  import { defaultTableWidth, renderTable } from "../output/table.js";
13
- import { resolveYuiHome, STORAGE_STATE_FILE } from "../storage/taskStore.js";
14
- import { createProductionStorageRegistry, openCompatibleFileTaskStore, validateCompatibleFileTaskStore } from "../storage/compatibleTaskStore.js";
13
+ import { resolveYuiHome } from "../storage/taskStore.js";
14
+ import { CURRENT_DATABASE_FILENAME, openCurrentTaskStore } from "../storage/currentTaskStore.js";
15
15
  import { inspectStorageSchema } from "../storage/storageSchema.js";
16
- import { resolveTaskStoreBackendForHome } from "../storage/sqliteStore.js";
17
16
  import { resolveStoreWorkerEnabledForHome } from "../storage/storeRpc.js";
18
- import { classifyHome } from "../storage/upgrade/homeClassification.js";
19
17
  import { resolveTmuxBin } from "../config/yuiConfig.js";
20
- import { readMigrationReceipt } from "../storage/upgrade/migrationReceipt.js";
21
- import { latestStorageVersionState } from "../storage/upgrade/recordVersions.js";
22
- import { COMMITTED_DATABASE_FILENAME } from "../storage/upgrade/sqliteStateMigration.js";
23
18
  import { CommandExecutionError } from "../tmux/commandExecutor.js";
24
19
  import { EPHEMERAL_DOMAIN_GRACE_MS, readEphemeralDomainIdentity, readLinuxProcessStartIdentity } from "../controller/domainIdentity.js";
25
20
  /**
@@ -47,8 +42,8 @@ export function summarizeStorageHealth(checks) {
47
42
  return { healthy: blocking.length === 0, blocking };
48
43
  }
49
44
  /** Build the full machine-readable doctor report (checks + storage health). */
50
- export function buildDoctorReport(env, executor, storageOptions = {}) {
51
- const inspection = inspectDoctor(env, executor, storageOptions);
45
+ export function buildDoctorReport(env, executor) {
46
+ const inspection = inspectDoctor(env, executor);
52
47
  const home = resolveYuiHome(env);
53
48
  return {
54
49
  checks: inspection.checks,
@@ -70,8 +65,8 @@ function inspectStorageDetails(home, env) {
70
65
  const logicalLayout = schema.status === "current" || schema.status === "unsupported"
71
66
  ? schema.currentLayoutVersion
72
67
  : null;
73
- const authoritativeBackend = resolveTaskStoreBackendForHome(home, env);
74
- const dbPath = join(home, COMMITTED_DATABASE_FILENAME);
68
+ const authoritativeBackend = "sqlite";
69
+ const dbPath = join(home, CURRENT_DATABASE_FILENAME);
75
70
  const databasePath = existsSync(dbPath) ? dbPath : null;
76
71
  let journalMode = null;
77
72
  let lastCommittedRevision = null;
@@ -92,44 +87,34 @@ function inspectStorageDetails(home, env) {
92
87
  // Leave both null; the storage state check surfaces the corruption.
93
88
  }
94
89
  }
95
- else {
96
- try {
97
- const state = JSON.parse(readFileSync(join(home, STORAGE_STATE_FILE), "utf8"));
98
- lastCommittedRevision = typeof state.revision === "number" ? state.revision : null;
99
- }
100
- catch {
101
- lastCommittedRevision = null;
102
- }
103
- }
104
90
  return {
105
91
  logicalLayout,
106
92
  authoritativeBackend,
107
93
  databasePath,
108
94
  journalMode,
109
95
  workerEnabled: resolveStoreWorkerEnabledForHome(home, env),
110
- migrationReceipt: readMigrationReceipt(home),
111
96
  lastCommittedRevision
112
97
  };
113
98
  }
114
- /** Runs the read-only FileTaskStore diagnostics used by `yui doctor`. */
115
- export function runDoctorCommand(args, env, executor, storageOptions = {}) {
99
+ /** Runs the read-only current-storage diagnostics used by `yui doctor`. */
100
+ export function runDoctorCommand(args, env, executor) {
116
101
  if (args.length !== 0)
117
102
  throw usageError("Doctor usage: yui doctor");
118
- const inspection = inspectDoctor(env, executor, storageOptions);
103
+ const inspection = inspectDoctor(env, executor);
119
104
  return renderDoctor(inspection.checks, inspection.review);
120
105
  }
121
- export function getDoctorChecks(env, executor, storageOptions = {}) {
122
- return inspectDoctor(env, executor, storageOptions).checks;
106
+ export function getDoctorChecks(env, executor) {
107
+ return inspectDoctor(env, executor).checks;
123
108
  }
124
- function inspectDoctor(env, executor, storageOptions = {}) {
109
+ function inspectDoctor(env, executor) {
125
110
  const home = resolveYuiHome(env);
126
111
  const homeCheck = checkHome(home);
127
112
  const schema = readSchema(home);
128
- const compatibility = inspectCompatibility(home, homeCheck, schema, storageOptions);
129
- const schemaCheck = checkSchema(schema, compatibility);
113
+ const compatibility = inspectCompatibility(home, homeCheck, schema);
114
+ const schemaCheck = checkSchema(schema);
130
115
  const storage = inspectState(home, homeCheck, schema, compatibility);
131
116
  const domain = checkEphemeralDomain(home);
132
- const durableConfig = readDurableConfigSafely(home, compatibility.storageOptions);
117
+ const durableConfig = readDurableConfigSafely(home);
133
118
  const toolChecks = [
134
119
  checkExecutable("git", durableConfig.gitBin, ["--version"], executor),
135
120
  checkExecutable("tmux", durableConfig.tmuxBin, ["-V"], executor)
@@ -223,7 +208,7 @@ function readSchema(home) {
223
208
  return { status: "read-error", detail: errorMessage(error) };
224
209
  }
225
210
  }
226
- function checkSchema(state, compatibility) {
211
+ function checkSchema(state) {
227
212
  switch (state.status) {
228
213
  case "uninitialized":
229
214
  return { name: "storage schema", status: "missing", detail: "run yui setup" };
@@ -234,16 +219,6 @@ function checkSchema(state, compatibility) {
234
219
  detail: `current=${state.currentVersion} latest=${state.latestVersion}`
235
220
  };
236
221
  case "unsupported":
237
- if ((compatibility.storageStatus === "compatible-old"
238
- || compatibility.storageStatus === "needs-storage-repair")
239
- && compatibility.check.status === "ok") {
240
- return {
241
- name: "storage schema",
242
- status: "ok",
243
- detail: `current=${state.currentVersion} latest=${state.latestVersion} `
244
- + `direction=${state.direction}; ${compatibility.storageStatus} validated`
245
- };
246
- }
247
222
  return {
248
223
  name: "storage schema",
249
224
  status: "unsupported",
@@ -255,17 +230,8 @@ function checkSchema(state, compatibility) {
255
230
  return { name: "storage schema", status: "invalid", detail: state.detail };
256
231
  }
257
232
  }
258
- /**
259
- * The four-state storage compatibility check: USABLE / MIGRATABLE /
260
- * NEEDS_NEW_VERSION / CORRUPTED. This complements the raw "storage schema" check
261
- * with the migration framework's verdict, so a user sees whether a Home can be
262
- * used as-is, upgraded with `yui upgrade`, needs a newer release, or is damaged.
263
- * Doctor uses the same explicit production registry as `yui upgrade`; tests
264
- * may inject a synthetic registry so the same classification and validation
265
- * path proves compatible-old behavior. Missing paths fail closed, and
266
- * CORRUPTED is reserved for structural or reference failure.
267
- */
268
- function inspectCompatibility(home, homeCheck, schema, storageOptions) {
233
+ /** Diagnose admission to the exact current storage contract without repair. */
234
+ function inspectCompatibility(home, homeCheck, schema) {
269
235
  const name = "storage compatibility";
270
236
  if (homeCheck.status !== "ok") {
271
237
  return { check: { name, status: homeCheck.status, detail: homeCheck.detail } };
@@ -276,110 +242,30 @@ function inspectCompatibility(home, homeCheck, schema, storageOptions) {
276
242
  if (schema.status === "read-error") {
277
243
  return { check: { name, status: "invalid", detail: schema.detail } };
278
244
  }
279
- let classification;
280
- let resolvedStorageOptions;
281
- try {
282
- resolvedStorageOptions = {
283
- registry: storageOptions.registry ?? createProductionStorageRegistry(),
284
- latest: storageOptions.latest ?? latestStorageVersionState()
285
- };
286
- classification = classifyHome({
287
- home,
288
- registry: resolvedStorageOptions.registry,
289
- latest: resolvedStorageOptions.latest
290
- });
245
+ if (schema.status === "invalid") {
246
+ return { check: { name, status: "invalid", detail: schema.detail } };
291
247
  }
292
- catch (error) {
293
- return { check: { name, status: "invalid", detail: errorMessage(error) } };
294
- }
295
- const storageStatus = classification.classification.status;
296
- // A pseudo-layout-7 Home (needs-storage-repair) opens through the same
297
- // normalization path as compatible-old, so its records get the same eager
298
- // validation before the schema check can treat a version mismatch as
299
- // validated (Issue 01).
300
- if (storageStatus === "compatible-old" || storageStatus === "needs-storage-repair") {
301
- try {
302
- validateCompatibleFileTaskStore(home, resolvedStorageOptions);
303
- }
304
- catch (error) {
305
- return {
306
- storageStatus,
307
- storageOptions: resolvedStorageOptions,
308
- check: {
309
- name,
310
- status: "invalid",
311
- detail: `unsupported ${storageStatus} shape: ${errorMessage(error)}`
312
- }
313
- };
314
- }
248
+ if (schema.status === "unsupported") {
249
+ return {
250
+ storageStatus: "unsupported",
251
+ check: {
252
+ name,
253
+ status: "unsupported",
254
+ detail: `unsupported contract: ${schema.incompatibleComponent} is ${schema.direction} `
255
+ + `(current=${schema.currentVersion}, required=${schema.latestVersion}). `
256
+ + "Preserve this Home and initialize a new Home."
257
+ }
258
+ };
315
259
  }
316
- const versions = `layout=${classification.layoutVersion ?? "?"}/${classification.latestLayoutVersion}`
317
- + ` aggregate=${classification.aggregateVersion ?? "?"}/${classification.latestAggregateVersion}`;
318
- const incompatible = classification.incompatibleComponent === undefined
319
- ? ""
320
- : ` incompatibleComponent=${classification.incompatibleComponent}`;
321
- switch (storageStatus) {
322
- case "current":
323
- return {
324
- storageStatus,
325
- storageOptions: resolvedStorageOptions,
326
- check: { name, status: "ok", detail: `current (USABLE) ${versions}` }
327
- };
328
- case "compatible-old":
329
- return {
330
- storageStatus,
331
- storageOptions: resolvedStorageOptions,
332
- check: {
333
- name,
334
- status: "ok",
335
- detail: `compatible-old (COMPATIBLE) ${versions}; ordinary commands are supported`
336
- }
337
- };
338
- case "migration-required":
339
- return {
340
- storageStatus,
341
- storageOptions: resolvedStorageOptions,
342
- check: {
343
- name,
344
- status: "ok",
345
- detail: `migration-required (MIGRATABLE) ${versions}; run yui update when Sessions are clear`
346
- }
347
- };
348
- case "needs-storage-repair":
349
- return {
350
- storageStatus,
351
- storageOptions: resolvedStorageOptions,
352
- check: {
353
- name,
354
- // Diagnostic mode (Issue 01 rollout step 1): the Home is readable
355
- // and usable, but the manifest claims layout 7 without a yui.db.
356
- // Surface the repair need in the detail while keeping the Home
357
- // healthy so ordinary commands keep working.
358
- status: "ok",
359
- detail: `needs-storage-repair (NEEDS_STORAGE_REPAIR) ${versions}; `
360
- + "the manifest claims layout 7 but yui.db is missing. Run `yui upgrade` to rebuild it from state.json."
361
- }
362
- };
363
- case "unsupported": {
364
- const unsupported = classification.classification;
365
- return {
366
- storageStatus,
367
- storageOptions: resolvedStorageOptions,
368
- check: unsupported.verdict === "CORRUPTED"
369
- ? {
370
- name,
371
- status: "invalid",
372
- detail: `unsupported (CORRUPTED): ${unsupported.detail}`
373
- }
374
- : {
375
- name,
376
- status: "unsupported",
377
- detail: `unsupported (NEEDS_NEW_VERSION) ${versions}${incompatible}; ` +
378
- `${unsupported.blocker.reason}`
379
- }
380
- };
260
+ return {
261
+ storageStatus: "current",
262
+ check: {
263
+ name,
264
+ status: "ok",
265
+ detail: `current layout=${schema.currentLayoutVersion}/${schema.latestLayoutVersion} `
266
+ + `aggregate=${schema.currentAggregateSchemaVersion}/${schema.latestAggregateSchemaVersion}`
381
267
  }
382
- }
268
+ };
383
269
  }
384
270
  function inspectState(home, homeCheck, schema, compatibility) {
385
271
  if (homeCheck.status !== "ok") {
@@ -392,42 +278,18 @@ function inspectState(home, homeCheck, schema, compatibility) {
392
278
  return blockedStorage("invalid", schema.detail);
393
279
  if (schema.status === "read-error")
394
280
  return blockedStorage("invalid", schema.detail);
395
- // A pseudo-layout-7 Home (needs-storage-repair) has a readable state.json;
396
- // the compatibility check surfaces the repair need, but the store itself is
397
- // readable, so the state and review checks must still run (Issue 01).
398
- if (compatibility.check.status !== "ok"
399
- && compatibility.storageStatus !== "needs-storage-repair") {
281
+ if (compatibility.check.status !== "ok") {
400
282
  return blockedStorage(compatibility.check.status, storageBlockerDetail(compatibility.check));
401
283
  }
402
- if (compatibility.storageStatus !== "current"
403
- && compatibility.storageStatus !== "compatible-old"
404
- && compatibility.storageStatus !== "needs-storage-repair") {
284
+ if (compatibility.storageStatus !== "current") {
405
285
  return blockedStorage("unsupported", compatibility.check.detail);
406
286
  }
407
- if (compatibility.storageOptions === undefined) {
408
- return blockedStorage("invalid", "Storage compatibility options were not resolved.");
409
- }
410
- const statePath = join(home, STORAGE_STATE_FILE);
411
- // A repaired layout-7 Home archived state.json; yui.db is the authoritative
412
- // backend then, so the state.json gate is skipped (Issue 01).
413
- const sqliteAuthoritative = !existsSync(statePath)
414
- && existsSync(join(home, COMMITTED_DATABASE_FILENAME));
415
- if (!sqliteAuthoritative) {
416
- if (!existsSync(statePath))
417
- return blockedStorage("missing", "run yui setup");
418
- try {
419
- const metadata = lstatSync(statePath);
420
- if (!metadata.isFile() || metadata.isSymbolicLink()) {
421
- return blockedStorage("invalid", `${STORAGE_STATE_FILE} must be a regular file.`);
422
- }
423
- accessSync(statePath, constants.R_OK);
424
- }
425
- catch (error) {
426
- return blockedStorage("invalid", errorMessage(error));
427
- }
287
+ const databasePath = join(home, CURRENT_DATABASE_FILENAME);
288
+ if (!existsSync(databasePath)) {
289
+ return blockedStorage("invalid", "Current storage is incomplete: yui.db is missing.");
428
290
  }
429
291
  try {
430
- const store = openCompatibleFileTaskStore(home, compatibility.storageOptions);
292
+ const store = openCurrentTaskStore(home);
431
293
  const config = store.getConfig();
432
294
  const agents = store.listConfiguredAgents();
433
295
  const tasks = store.listTasks();
@@ -437,12 +299,12 @@ function inspectState(home, homeCheck, schema, compatibility) {
437
299
  check: {
438
300
  name: "storage state",
439
301
  status: "ok",
440
- detail: `${sqliteAuthoritative ? "yui.db readable" : "readable"} agents=${agents.length} tasks=${tasks.length} roles=${roleCount} globalRoles=${globalRoles.length} defaultAgent=${config.defaultAgent ?? "none"}`
302
+ detail: `yui.db readable agents=${agents.length} tasks=${tasks.length} roles=${roleCount} globalRoles=${globalRoles.length} defaultAgent=${config.defaultAgent ?? "none"}`
441
303
  },
442
304
  agents,
443
305
  review: {
444
306
  storageReady: true,
445
- storageDetail: sqliteAuthoritative ? "yui.db is readable" : "state.json is readable",
307
+ storageDetail: "yui.db is readable",
446
308
  ...(config.review === undefined ? {} : { policy: config.review }),
447
309
  ...(config.review === undefined
448
310
  ? {}
@@ -465,7 +327,7 @@ function inspectState(home, homeCheck, schema, compatibility) {
465
327
  function storageBlockerDetail(check) {
466
328
  const corruptionPrefix = "unsupported (CORRUPTED): ";
467
329
  return check.status === "invalid" && check.detail.startsWith(corruptionPrefix)
468
- ? `Invalid state.json: ${check.detail.slice(corruptionPrefix.length)}`
330
+ ? `Invalid storage: ${check.detail.slice(corruptionPrefix.length)}`
469
331
  : check.detail;
470
332
  }
471
333
  function blockedStorage(status, detail) {
@@ -480,11 +342,6 @@ function blockedStorage(status, detail) {
480
342
  }
481
343
  function inspectReview(source, agentChecks, environment) {
482
344
  if (!source.storageReady) {
483
- const raw = source.home === undefined
484
- ? null
485
- : inspectRawReview(source.home, source.storageDetail);
486
- if (raw !== null)
487
- return raw;
488
345
  return {
489
346
  report: {
490
347
  status: "misconfigured",
@@ -623,126 +480,6 @@ function inspectReview(source, agentChecks, environment) {
623
480
  checks
624
481
  };
625
482
  }
626
- /**
627
- * Preserve a bounded Reviewer diagnosis when another malformed record prevents
628
- * FileTaskStore from opening. This is read-only evidence, never a compatibility
629
- * path: the storage check remains invalid and the review projection cannot be
630
- * reported as ready from unvalidated bytes.
631
- */
632
- function inspectRawReview(home, storageDetail) {
633
- try {
634
- const parsed = JSON.parse(readFileSync(join(home, STORAGE_STATE_FILE), "utf8"));
635
- if (!isRecord(parsed) || !isRecord(parsed.config))
636
- return null;
637
- const rawPolicy = parsed.config.review;
638
- if (!isRecord(rawPolicy)
639
- || typeof rawPolicy.roleName !== "string"
640
- || typeof rawPolicy.trigger !== "string") {
641
- return {
642
- report: {
643
- status: "misconfigured",
644
- providerNative: "unverified",
645
- detail: `Storage state is invalid; Review policy is unavailable: ${storageDetail}`
646
- },
647
- checks: [{
648
- name: "review policy",
649
- status: "invalid",
650
- detail: `storage state invalid: ${storageDetail}`
651
- }]
652
- };
653
- }
654
- const policy = {
655
- roleName: rawPolicy.roleName,
656
- trigger: rawPolicy.trigger
657
- };
658
- const roles = isRecord(parsed.globalRoles) ? parsed.globalRoles : {};
659
- const roleValue = roles[policy.roleName];
660
- if (!isRecord(roleValue)) {
661
- return rawReviewMisconfigured(policy, storageDetail, [{
662
- name: "review policy",
663
- status: "ok",
664
- detail: `role=${policy.roleName} trigger=${policy.trigger}`
665
- }, {
666
- name: "reviewer role",
667
- status: "missing",
668
- detail: `Global Role not found: ${policy.roleName}.`
669
- }]);
670
- }
671
- const roleName = typeof roleValue.name === "string" ? roleValue.name : policy.roleName;
672
- const activeAgentId = typeof roleValue.activeAgentId === "string"
673
- ? roleValue.activeAgentId
674
- : "";
675
- const checks = [{
676
- name: "review policy",
677
- status: "ok",
678
- detail: `role=${policy.roleName} trigger=${policy.trigger}`
679
- }, {
680
- name: "reviewer role",
681
- status: "ok",
682
- detail: `name=${roleName} activeAgent=${activeAgentId || "missing"}`
683
- }];
684
- const bindings = isRecord(roleValue.agentBindings) ? roleValue.agentBindings : {};
685
- const bindingValue = activeAgentId.length === 0 ? undefined : bindings[activeAgentId];
686
- if (!isRecord(bindingValue)) {
687
- checks.push({
688
- name: "reviewer binding",
689
- status: "missing",
690
- detail: `active Agent binding is missing: ${activeAgentId || "unknown"}.`
691
- });
692
- return rawReviewMisconfigured(policy, storageDetail, checks, roleName, activeAgentId || undefined);
693
- }
694
- const bindingAgentId = typeof bindingValue.agentId === "string"
695
- ? bindingValue.agentId
696
- : activeAgentId;
697
- const adapterId = typeof bindingValue.adapterId === "string"
698
- ? bindingValue.adapterId
699
- : "unknown";
700
- checks.push({
701
- name: "reviewer binding",
702
- status: "ok",
703
- detail: `agent=${bindingAgentId} adapter=${adapterId}`
704
- });
705
- const configuredAgents = isRecord(parsed.configuredAgents)
706
- ? parsed.configuredAgents
707
- : {};
708
- const agentValue = configuredAgents[bindingAgentId];
709
- if (!isRecord(agentValue)) {
710
- checks.push({
711
- name: "reviewer agent",
712
- status: "missing",
713
- detail: `Configured Agent not found: ${bindingAgentId}.`
714
- });
715
- return rawReviewMisconfigured(policy, storageDetail, checks, roleName, bindingAgentId, adapterId);
716
- }
717
- checks.push({
718
- name: "reviewer agent",
719
- status: "invalid",
720
- detail: `Storage state is invalid; configured Agent ${bindingAgentId} cannot be validated.`
721
- });
722
- return rawReviewMisconfigured(policy, storageDetail, checks, roleName, bindingAgentId, adapterId, typeof agentValue.command === "string" ? agentValue.command : undefined);
723
- }
724
- catch {
725
- return null;
726
- }
727
- }
728
- function rawReviewMisconfigured(policy, storageDetail, checks, roleName, activeAgentId, adapterId, command) {
729
- return {
730
- report: {
731
- status: "misconfigured",
732
- policy,
733
- ...(roleName === undefined ? {} : { roleName }),
734
- ...(activeAgentId === undefined ? {} : { activeAgentId }),
735
- ...(adapterId === undefined ? {} : { adapterId }),
736
- ...(command === undefined ? {} : { command }),
737
- providerNative: "unverified",
738
- detail: `Storage state is invalid; ${checks.at(-1)?.detail ?? storageDetail}`
739
- },
740
- checks
741
- };
742
- }
743
- function isRecord(value) {
744
- return value !== null && typeof value === "object" && !Array.isArray(value);
745
- }
746
483
  function reviewMisconfigured(policy, checks, detail, role, activeAgentId, adapterId, command) {
747
484
  return {
748
485
  report: {
@@ -983,9 +720,9 @@ function errorMessage(error) {
983
720
  * Read the durable config for executable paths. Falls back to defaults when
984
721
  * the Home store cannot be opened (the doctor must still run on broken Homes).
985
722
  */
986
- function readDurableConfigSafely(home, storageOptions) {
723
+ function readDurableConfigSafely(home) {
987
724
  try {
988
- const store = openCompatibleFileTaskStore(home, storageOptions ?? {});
725
+ const store = openCurrentTaskStore(home);
989
726
  const config = store.getConfig();
990
727
  return {
991
728
  tmuxBin: resolveTmuxBin(config.tmuxBin),
@@ -12,7 +12,7 @@ export function candidateConvergenceDirective(stage) {
12
12
  const parentRefs = stage.parentResults.map(parentResultRef);
13
13
  const common = [
14
14
  "Candidate convergence contract v1 is active.",
15
- "Yield one JSON object. Keep summary/checks/findings/evidence at the top level and add convergence={schemaVersion:1,stage,artifactType,parentResultRefs,...}.",
15
+ "Return one JSON object. Keep summary/checks/findings/evidence at the top level and add convergence={schemaVersion:1,stage,artifactType,parentResultRefs,...}.",
16
16
  `convergence.stage must be ${stage.stage}; parentResultRefs must equal ${JSON.stringify(parentRefs)} in this order.`,
17
17
  "artifactType is research, architecture, or code and must stay unchanged across the round.",
18
18
  "Use only frozen parent result references; never replay sibling transcripts. Direct sources, executable checks, and frozen artifacts outrank derived analysis or vote counts."
@@ -236,7 +236,7 @@ export function candidateConvergenceEvidenceSufficient(workItem, group, selected
236
236
  || (stage.stage !== "verify" && stage.stage !== "resolve")
237
237
  || selectedLaneIds.length === 0)
238
238
  return false;
239
- const usable = group.lanes.filter(({ status }) => (status === "yielded" || status === "completed"));
239
+ const usable = group.lanes.filter(({ status }) => status === "completed");
240
240
  if (selectedLaneIds.some((laneId) => !usable.some(({ id }) => id === laneId)))
241
241
  return false;
242
242
  // Cost policy may never hide contradictory evidence that has already
@@ -320,7 +320,7 @@ function usableCandidateConvergenceEnvelopes(group) {
320
320
  const stage = group.stage;
321
321
  if (stage?.convergence === undefined)
322
322
  return [];
323
- const usable = group.lanes.filter(({ status, result }) => ((status === "yielded" || status === "completed") && result !== undefined));
323
+ const usable = group.lanes.filter(({ status, result }) => (status === "completed" && result !== undefined));
324
324
  try {
325
325
  return usable.map(({ result }) => validateCandidateConvergenceReport(result, stage.stage, stage.parentResults));
326
326
  }