@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
@@ -187,23 +187,23 @@ function validateStartParams(store, params) {
187
187
  /**
188
188
  * rr8/rr12: Bind the declared job owner to the caller's managed identity. The
189
189
  * Controller validates the declared owner/workspace and verifies the caller
190
- * against durable Run/Session state — a self-reported role or scope is never
190
+ * against durable Turn/Session state — a self-reported role or scope is never
191
191
  * authority on its own. The rules:
192
192
  *
193
193
  * - `user` (non-managed): rejected because it has no managed Session identity.
194
194
  * - `global`: full Task authority after current Role Session verification.
195
195
  * - `task` + mismatched taskId: rejected.
196
- * - `task` + missing `runId`: rejected (a managed caller must bind to a Run).
197
- * - `task` + Run not found / not active / `roleName !== role`: rejected — the
198
- * claimed Role must be the real Role of an active Run.
199
- * - `task`: full authority inside the matching Task after active Run and
196
+ * - `task` + missing `turnId`: rejected (a managed caller must bind to a Turn).
197
+ * - `task` + Turn not found / not active / `roleName !== role`: rejected — the
198
+ * claimed Role must be the real Role of an active Turn.
199
+ * - `task`: full authority inside the matching Task after active Turn and
200
200
  * per-Session caller-key verification; Role does not narrow it.
201
201
  */
202
202
  /**
203
203
  * rr13: `job.start`/`job.cancel` caller authorization at the Controller
204
204
  * boundary. Every identity claim the Controller can verify from durable state
205
- * (role and runId) is replayable by any client in the
206
- * same Home that reads state.json. The channel itself is therefore not
205
+ * (role and turnId) is replayable by any client in the
206
+ * same authoritative Controller. The channel itself is therefore not
207
207
  * authenticated by those claims alone. A non-replayable per-Session caller key
208
208
  * closes the gap:
209
209
  *
@@ -213,10 +213,10 @@ function validateStartParams(store, params) {
213
213
  * - `task` scope: the caller must present `callerKey` — the
214
214
  * `YUI_JOB_CALLER_KEY` injected at its native Session launch. The Controller
215
215
  * hashes it (SHA-256) and compares against the durable `jobCallerKeyHashes`
216
- * map for the caller's Role + Agent. No legacy fallback: an absent hash or a
216
+ * map for the caller's Role + Agent. An absent hash or a
217
217
  * mismatched key is UNAUTHORIZED.
218
218
  *
219
- * The existing Run binding checks run after the key check, so a forged
219
+ * The existing Turn binding checks run after the key check, so a forged
220
220
  * identity that also lacks the key is rejected at the channel boundary.
221
221
  */
222
222
  function assertCallerAuthorized(store, caller, taskId) {
@@ -257,16 +257,16 @@ function assertCallerAuthorized(store, caller, taskId) {
257
257
  if (caller.taskId !== taskId) {
258
258
  throw jobControlError("UNAUTHORIZED", "A managed Task Session may not start or cancel Jobs for a different Task.");
259
259
  }
260
- if (caller.runId === undefined) {
261
- throw jobControlError("UNAUTHORIZED", "A managed Task Session must bind its request to a Run.");
260
+ if (caller.turnId === undefined) {
261
+ throw jobControlError("UNAUTHORIZED", "A managed Task Session must bind its request to a Turn.");
262
262
  }
263
- const run = store.getAgentRun(taskId, caller.runId);
263
+ const run = store.getTurn(taskId, caller.turnId);
264
264
  if (run === null || run.status !== "active" || run.roleName !== caller.role) {
265
- throw jobControlError("UNAUTHORIZED", "A managed Task Session's Role is not bound to an active Run.");
265
+ throw jobControlError("UNAUTHORIZED", "A managed Task Session's Role is not bound to an active Turn.");
266
266
  }
267
267
  // rr13: Verify the non-replayable per-Session caller key. The key is injected
268
268
  // at native Session launch and never persisted in plaintext; only its SHA-256
269
- // hash is durable. A client that reads state.json can see the hash but cannot
269
+ // hash is durable. A client with database read access can see the hash but cannot
270
270
  // recover the key.
271
271
  if (caller.callerKey === undefined) {
272
272
  throw jobControlError("UNAUTHORIZED", "job.start/job.cancel requires a managed Session caller key.");
@@ -490,7 +490,7 @@ function parseCaller(value) {
490
490
  const record = value;
491
491
  const allowed = new Set([
492
492
  "scope", "taskId", "role", "agentId", "adapterId", "launchId", "nativeSessionId",
493
- "runId", "callerKey"
493
+ "turnId", "callerKey"
494
494
  ]);
495
495
  for (const key of Object.keys(record)) {
496
496
  if (!allowed.has(key)) {
@@ -512,7 +512,7 @@ function parseCaller(value) {
512
512
  const adapterId = optionalId("adapterId");
513
513
  const launchId = optionalId("launchId");
514
514
  const nativeSessionId = optionalId("nativeSessionId");
515
- const runId = optionalId("runId");
515
+ const turnId = optionalId("turnId");
516
516
  const callerKey = record.callerKey === undefined
517
517
  ? undefined
518
518
  : requiredId(record.callerKey, "job caller callerKey");
@@ -524,7 +524,7 @@ function parseCaller(value) {
524
524
  ...(adapterId === undefined ? {} : { adapterId }),
525
525
  ...(launchId === undefined ? {} : { launchId }),
526
526
  ...(nativeSessionId === undefined ? {} : { nativeSessionId }),
527
- ...(runId === undefined ? {} : { runId }),
527
+ ...(turnId === undefined ? {} : { turnId }),
528
528
  ...(callerKey === undefined ? {} : { callerKey })
529
529
  };
530
530
  }
@@ -32,7 +32,7 @@ export function createRuntimeResourceActivityTracker() {
32
32
  || roleKey === undefined)
33
33
  return reject();
34
34
  const identityKey = JSON.stringify([
35
- identity.runId,
35
+ identity.turnId,
36
36
  identity.agentId,
37
37
  identity.adapterId,
38
38
  identity.nativeSessionId ?? null,
@@ -262,7 +262,7 @@ function roleOwner(role) {
262
262
  ...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
263
263
  ...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
264
264
  ...(role.launchId === undefined ? {} : { launchId: role.launchId }),
265
- ...(role.runId === undefined ? {} : { runId: role.runId })
265
+ ...(role.turnId === undefined ? {} : { turnId: role.turnId })
266
266
  };
267
267
  }
268
268
  return {
@@ -275,7 +275,7 @@ function roleOwner(role) {
275
275
  ...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
276
276
  ...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
277
277
  ...(role.launchId === undefined ? {} : { launchId: role.launchId }),
278
- ...(role.runId === undefined ? {} : { runId: role.runId })
278
+ ...(role.turnId === undefined ? {} : { turnId: role.turnId })
279
279
  };
280
280
  }
281
281
  function processTree(processes, rootPid) {
@@ -437,8 +437,8 @@ function matchesResourceIdentity(identity, owner) {
437
437
  || identity.taskId.length === 0
438
438
  || typeof identity.roleName !== "string"
439
439
  || identity.roleName.length === 0
440
- || typeof identity.runId !== "string"
441
- || identity.runId.length === 0
440
+ || typeof identity.turnId !== "string"
441
+ || identity.turnId.length === 0
442
442
  || typeof identity.agentId !== "string"
443
443
  || identity.agentId.length === 0
444
444
  || typeof identity.adapterId !== "string"
@@ -449,7 +449,7 @@ function matchesResourceIdentity(identity, owner) {
449
449
  if (owner.kind !== "task-role"
450
450
  || owner.taskId !== identity.taskId
451
451
  || owner.roleName !== identity.roleName
452
- || owner.runId !== identity.runId
452
+ || owner.turnId !== identity.turnId
453
453
  || owner.agentId !== identity.agentId
454
454
  || owner.adapterId !== identity.adapterId)
455
455
  return false;
@@ -3,7 +3,7 @@ import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
3
3
  import { basename, join, resolve } from "node:path";
4
4
  import { activeLiveRoleAgentSession } from "../executor/agentExecutor.js";
5
5
  import { inspectStorageSchema } from "../storage/storageSchema.js";
6
- import { openCompatibleFileTaskStore } from "../storage/compatibleTaskStore.js";
6
+ import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
7
7
  import { NodeCommandExecutor } from "../tmux/commandExecutor.js";
8
8
  import { TmuxManager, yuiTmuxServerName } from "../tmux/tmuxManager.js";
9
9
  import { tmuxSocketDirectory, tmuxSocketEnvironment } from "../tmux/tmuxSocketEndpoint.js";
@@ -450,8 +450,7 @@ function inspectRuntimeDomain(home, processes, roles, storageStatus, now) {
450
450
  // A current, ordinary YUI_HOME is a real control domain, not a disposable
451
451
  // test domain. Keep it visible even when it is currently idle so a stale
452
452
  // artifact cannot acquire ephemeral cleanup authority by omission. An
453
- // uninitialized temporary directory with no runtime facts remains absent
454
- // to preserve the legacy empty-home inventory behavior.
453
+ // uninitialized temporary directory with no runtime facts remains absent.
455
454
  if (storageStatus !== "current"
456
455
  && processes.length === 0
457
456
  && roles.length === 0)
@@ -614,19 +613,14 @@ function inspectRuntimeDomain(home, processes, roles, storageStatus, now) {
614
613
  }
615
614
  function loadHomeState(home, warnings, options) {
616
615
  const schema = (options.inspectStorage ?? inspectStorageSchema)(home);
617
- const recordOnlyOlder = schema.status === "unsupported"
618
- && schema.incompatibleComponent === "record"
619
- && schema.direction === "older"
620
- && schema.currentLayoutVersion === schema.latestLayoutVersion
621
- && schema.currentAggregateSchemaVersion === schema.latestAggregateSchemaVersion;
622
- if (schema.status !== "current" && !recordOnlyOlder) {
616
+ if (schema.status !== "current") {
623
617
  return {
624
618
  storageStatus: schema.status,
625
619
  roles: []
626
620
  };
627
621
  }
628
622
  try {
629
- const store = (options.openCompatibleStore ?? openCompatibleFileTaskStore)(home);
623
+ const store = (options.openCurrentStore ?? openCurrentTaskStore)(home);
630
624
  const roles = [...store.listGlobalRoles()]
631
625
  .sort((left, right) => numericCompare(left.name, right.name))
632
626
  .map((role) => {
@@ -646,7 +640,7 @@ function loadHomeState(home, warnings, options) {
646
640
  const appendTaskRole = (task, role) => {
647
641
  const session = activeLiveRoleAgentSession(store.getRoleSessionSet(task.id, role.name));
648
642
  const binding = role.agentBindings[role.activeAgentId];
649
- const run = store.getActiveAgentRun(task.id, role.name);
643
+ const run = store.getActiveTurn(task.id, role.name);
650
644
  const agentId = session?.effective.agentId ?? role.activeAgentId;
651
645
  const adapterId = session?.effective.adapterId ?? binding?.adapterId;
652
646
  roles.push({
@@ -659,57 +653,42 @@ function loadHomeState(home, warnings, options) {
659
653
  ...(adapterId === undefined ? {} : { adapterId }),
660
654
  ...(session === null ? {} : { nativeSessionId: session.nativeSessionId }),
661
655
  ...(session?.launchId === undefined ? {} : { launchId: session.launchId }),
662
- ...(run === null ? {} : { runId: run.id })
656
+ ...(run === null ? {} : { turnId: run.id })
663
657
  });
664
658
  };
665
- // Layout-7 SQLite owns bounded active-Task and current-Session indexes.
666
- // Use those indexes only as selectors, then point-read the authoritative
667
- // Task/Role/Session/Run records so an index row cannot bypass ownership
668
- // fences. The legacy File store intentionally retains its complete
669
- // listTasks fallback because it has no equivalent active selector.
670
- const hotStore = store;
671
- const indexedTaskIds = hotStore.listActiveTaskIds === undefined
672
- ? undefined
673
- : [...new Set(hotStore.listActiveTaskIds())].sort(numericCompare);
674
- if (indexedTaskIds === undefined) {
675
- for (const task of store.listTasks()) {
676
- for (const role of [...store.listRoles(task.id)].sort((left, right) => (numericCompare(left.name, right.name)))) {
677
- appendTaskRole(task, role);
678
- }
679
- }
659
+ // The current SQLite store owns bounded active-Task and current-Session
660
+ // indexes. Use them only as selectors, then point-read the authoritative
661
+ // Task/Role/Session/Turn records so an index row cannot bypass ownership
662
+ // fences.
663
+ const indexedTaskIds = [...new Set(store.listActiveTaskIds())].sort(numericCompare);
664
+ const sessionCandidates = store.listRuntimeSessionCandidates({ scope: "task" });
665
+ const candidateRoles = new Map();
666
+ for (const candidate of sessionCandidates) {
667
+ if (candidate.owner.scope !== "task")
668
+ continue;
669
+ const roleNames = candidateRoles.get(candidate.owner.taskId) ?? new Set();
670
+ roleNames.add(candidate.owner.roleName);
671
+ candidateRoles.set(candidate.owner.taskId, roleNames);
680
672
  }
681
- else {
682
- const sessionCandidates = typeof store.listRuntimeSessionCandidates === "function"
683
- ? store.listRuntimeSessionCandidates({ scope: "task" })
684
- : [];
685
- const candidateRoles = new Map();
686
- for (const candidate of sessionCandidates) {
687
- if (candidate.owner.scope !== "task")
688
- continue;
689
- const roleNames = candidateRoles.get(candidate.owner.taskId) ?? new Set();
690
- roleNames.add(candidate.owner.roleName);
691
- candidateRoles.set(candidate.owner.taskId, roleNames);
692
- }
693
- const activeTaskSet = new Set(indexedTaskIds);
694
- const taskIds = [...new Set([
695
- ...indexedTaskIds,
696
- ...candidateRoles.keys()
697
- ])].sort(numericCompare);
698
- for (const taskId of taskIds) {
699
- const task = store.getTask(taskId);
700
- if (task === null)
701
- continue;
702
- const rolesForTask = activeTaskSet.has(taskId) && task.status === "active"
703
- ? store.listRoles(taskId)
704
- : [...(candidateRoles.get(taskId) ?? [])]
705
- .sort(numericCompare)
706
- .flatMap((roleName) => {
707
- const role = store.getRole(taskId, roleName);
708
- return role === null ? [] : [role];
709
- });
710
- for (const role of [...rolesForTask].sort((left, right) => (numericCompare(left.name, right.name)))) {
711
- appendTaskRole(task, role);
712
- }
673
+ const activeTaskSet = new Set(indexedTaskIds);
674
+ const taskIds = [...new Set([
675
+ ...indexedTaskIds,
676
+ ...candidateRoles.keys()
677
+ ])].sort(numericCompare);
678
+ for (const taskId of taskIds) {
679
+ const task = store.getTask(taskId);
680
+ if (task === null)
681
+ continue;
682
+ const rolesForTask = activeTaskSet.has(taskId) && task.status === "active"
683
+ ? store.listRoles(taskId)
684
+ : [...(candidateRoles.get(taskId) ?? [])]
685
+ .sort(numericCompare)
686
+ .flatMap((roleName) => {
687
+ const role = store.getRole(taskId, roleName);
688
+ return role === null ? [] : [role];
689
+ });
690
+ for (const role of [...rolesForTask].sort((left, right) => (numericCompare(left.name, right.name)))) {
691
+ appendTaskRole(task, role);
713
692
  }
714
693
  }
715
694
  return {
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * The `/proc` scanning in `resourceInventoryLinux` is blocking IO (hundreds of
6
6
  * `readFileSync` calls per pass, `spawnSync`, tmux inspection). When the worker
7
- * backend is active (`YUI_STORE_BACKEND=sqlite` + `YUI_STORE_WORKER=1`, the same
7
+ * persistence worker is active (`YUI_STORE_WORKER=1`, the same
8
8
  * flag as the persistence worker, §6), the Controller runtime and the ephemeral
9
9
  * reaper scan through this client instead: the scan runs in the inventory
10
10
  * worker (its own thread), the main event loop stays free, and the result is
@@ -17,8 +17,8 @@
17
17
  * worker -> main: ready | result | error
18
18
  *
19
19
  * Only structured-cloneable scan options cross the port (the file-backed
20
- * `inspectStorage` / `openCompatibleStore` / `now` seams stay on the direct
21
- * path, which the file backend still uses). The inventory worker never touches
20
+ * `inspectStorage` / `openCurrentStore` / `now` seams stay on the direct
21
+ * path used without the worker). The inventory worker never touches
22
22
  * the persistence worker's database connection (§3.3): it is a separate worker
23
23
  * with a separate concern.
24
24
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Runs the blocking `/proc` scanning of `resourceInventoryLinux` off the main
5
5
  * thread. The main thread asks for a scan over a `MessageChannel` port; the
6
- * worker runs the exact same `scanControllerResourceInventory` the file backend
6
+ * worker runs the exact same `scanControllerResourceInventory` as the main thread
7
7
  * calls directly and posts the inventory back. Because worker threads share the
8
8
  * process, the scanner's self-exclusion (`process.pid`, its start identity)
9
9
  * keeps excluding the Controller process exactly as on the main thread.
@@ -11,7 +11,7 @@ import { effectiveLaunchSnapshotsCompatible, effectiveLaunchSnapshotsCompatibleF
11
11
  import { AgentConfigurationCatalogService, validateAgentLaunchConfiguration } from "../executor/agentConfigurationCatalog.js";
12
12
  import { isTaskOwnedWorkspace, managedWorkspaceIdentity, sameManagedWorkspaceIdentity } from "../worktree/managedWorkspace.js";
13
13
  import { FileRoleLaunchPlanner } from "../executor/fileRoleLaunchPlanner.js";
14
- import { openCompatibleFileTaskStore } from "../storage/compatibleTaskStore.js";
14
+ import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
15
15
  import { SqliteTaskStore } from "../storage/sqliteStore.js";
16
16
  import { AsyncTaskStoreClient, resolveStoreWorkerEnabledForHome } from "../storage/storeRpc.js";
17
17
  import { FileTaskWorkspacePreparer } from "../repository/taskWorkspacePreparer.js";
@@ -45,13 +45,13 @@ import { createTaskEvent } from "../event/taskEvent.js";
45
45
  export function refreshAppliedTaskRuntimeDescriptor(store, planner, input) {
46
46
  if (input.launchId === undefined)
47
47
  return;
48
- const run = input.runId === undefined
48
+ const run = input.turnId === undefined
49
49
  ? null
50
- : store.getAgentRun(input.taskId, input.runId);
51
- if (input.runId !== undefined && run === null) {
50
+ : store.getTurn(input.taskId, input.turnId);
51
+ if (input.turnId !== undefined && run === null) {
52
52
  throw new Error("Prepared Task runtime generation is not current.");
53
53
  }
54
- // A terminal completion has already settled this exact Run and no later
54
+ // A terminal completion has already settled this exact Turn and no later
55
55
  // prompt can use its descriptor. Acknowledge the applied provider fact
56
56
  // without republishing a dead generation.
57
57
  if (run !== null && run.status !== "active")
@@ -76,22 +76,18 @@ export function refreshAppliedTaskRuntimeDescriptor(store, planner, input) {
76
76
  workspace: effective.workspace.root
77
77
  });
78
78
  }
79
- /** Production composition root for the lean FileTaskStore + tmux Controller. */
79
+ /** Production composition root for the current SQLite TaskStore + tmux Controller. */
80
80
  export async function startFileTaskControllerRuntime(home, options = {}) {
81
- // The Home decides the backend (Issue 01): a layout-7 Home runs SQLite with
82
- // the persistence worker on by default; YUI_STORE_WORKER=0/false forces the
83
- // in-process SQLite connection. The non-worker path opens the Home-decided
84
- // backend through the compatibility opener (SQLite for layout 7, file store
85
- // with normalization for older layouts).
81
+ // The current Home always uses SQLite. The persistence worker is enabled by
82
+ // default; YUI_STORE_WORKER=0/false keeps the same database in-process.
86
83
  const useWorker = resolveStoreWorkerEnabledForHome(home, options.environment ?? process.env);
87
84
  const store = options.store
88
85
  ?? (useWorker
89
- // Transitional: the scheduler/planner still use a sync store. The worker
90
- // owns the event-processing hot path; the scheduler migration is the next
91
- // step (see work-item-5 remaining call sites). Both connections point at
92
- // the same WAL db and serialize via BEGIN IMMEDIATE + busy_timeout.
86
+ // The worker owns the event-processing hot path while the scheduler uses
87
+ // the synchronous connection. Both point at the same WAL database and
88
+ // serialize via BEGIN IMMEDIATE + busy_timeout.
93
89
  ? new SqliteTaskStore(home)
94
- : openCompatibleFileTaskStore(home));
90
+ : openCurrentTaskStore(home));
95
91
  const homeId = store.getHomeIdentity().homeId;
96
92
  const durableConfig = store.getConfig();
97
93
  // When the worker backend is active, the db-touching observer folds run in
@@ -259,9 +255,8 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
259
255
  onCleanupRequired: signalRuntimeCleanup,
260
256
  runtimeIsolation
261
257
  });
262
- // One inventory scan per scheduler pass. When the worker backend is active
263
- // the blocking /proc scan runs in the inventory worker; otherwise it runs on
264
- // the main thread (file backend, unchanged).
258
+ // One inventory scan per scheduler pass. When the inventory worker is active
259
+ // the blocking /proc scan runs there; otherwise it runs on the main thread.
265
260
  const scanInventory = (panes) => inventoryClient !== undefined
266
261
  ? inventoryClient.scan({
267
262
  currentHome: home,
@@ -297,7 +292,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
297
292
  && candidate.roleName === owner.roleName));
298
293
  if (input === undefined)
299
294
  return [];
300
- const identity = owner.runId === undefined
295
+ const identity = owner.turnId === undefined
301
296
  || owner.adapterId === undefined
302
297
  || (owner.nativeSessionId === undefined && owner.launchId === undefined)
303
298
  || (owner.nativeSessionId !== undefined && owner.nativeSessionId.trim().length === 0)
@@ -306,7 +301,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
306
301
  : {
307
302
  taskId: owner.taskId,
308
303
  roleName: owner.roleName,
309
- runId: owner.runId,
304
+ turnId: owner.turnId,
310
305
  agentId: owner.agentId,
311
306
  adapterId: owner.adapterId,
312
307
  ...(owner.nativeSessionId === undefined
@@ -314,12 +309,12 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
314
309
  : { nativeSessionId: owner.nativeSessionId }),
315
310
  ...(owner.launchId === undefined ? {} : { launchId: owner.launchId })
316
311
  };
317
- const changed = !active || input.runId === undefined
312
+ const changed = !active || input.turnId === undefined
318
313
  ? false
319
314
  : resourceActivity({
320
315
  taskId: input.taskId,
321
316
  roleName: input.roleName,
322
- runId: input.runId,
317
+ turnId: input.turnId,
323
318
  agentId: input.agentId,
324
319
  adapterId: input.adapterId,
325
320
  ...(input.nativeSessionId === undefined
@@ -570,7 +565,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
570
565
  schedulerStore.beginAgentHostProviderTurn({
571
566
  taskId: value.taskId,
572
567
  roleName: value.roleName,
573
- runId: value.runId,
568
+ ...(value.turnId === undefined ? {} : { turnId: value.turnId }),
574
569
  agentId: value.agentId,
575
570
  launchId: value.launchId,
576
571
  nativeSessionId: value.nativeSessionId,
@@ -602,7 +597,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
602
597
  schedulerStore.resolveAgentHostProviderTurnSubmission({
603
598
  taskId: value.taskId,
604
599
  roleName: value.roleName,
605
- runId: value.runId,
600
+ ...(value.turnId === undefined ? {} : { turnId: value.turnId }),
606
601
  attemptId: value.attemptId,
607
602
  status,
608
603
  reason,
@@ -613,9 +608,9 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
613
608
  }
614
609
  if (method === "runtime.process-exit-observe") {
615
610
  const observation = validateRuntimeProcessExitObservation(params);
616
- const run = observation.taskId === undefined || observation.runId === undefined
611
+ const run = observation.taskId === undefined || observation.turnId === undefined
617
612
  ? null
618
- : store.getAgentRun(observation.taskId, observation.runId);
613
+ : store.getTurn(observation.taskId, observation.turnId);
619
614
  const globalRole = observation.taskId === undefined
620
615
  ? store.getGlobalRole(observation.roleName)
621
616
  : null;
@@ -625,20 +620,20 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
625
620
  ? null
626
621
  : builtinAgentDriverRegistry().findByAdapterId(adapterId);
627
622
  const turnTerminalObserved = observation.taskId !== undefined
628
- && observation.runId !== undefined
623
+ && observation.turnId !== undefined
629
624
  && store.listEvents(observation.taskId).some((event) => {
630
625
  const runtime = runtimeObservationFromTaskEvent(event);
631
626
  return runtime !== null
632
- && runtime.fence.runId === observation.runId
627
+ && runtime.fence.turnId === observation.turnId
633
628
  && ["turn.completed", "turn.failed", "turn.cancelled"].includes(runtime.kind)
634
629
  && Date.parse(runtime.receivedAt) <= Date.parse(observation.observedAt);
635
630
  });
636
631
  const turnFailureObserved = observation.taskId !== undefined
637
- && observation.runId !== undefined
632
+ && observation.turnId !== undefined
638
633
  && store.listEvents(observation.taskId).some((event) => {
639
634
  const runtime = runtimeObservationFromTaskEvent(event);
640
635
  return runtime !== null
641
- && runtime.fence.runId === observation.runId
636
+ && runtime.fence.turnId === observation.turnId
642
637
  && runtime.fence.launchId === observation.launchId
643
638
  && runtime.kind === "turn.failed"
644
639
  && Date.parse(runtime.receivedAt) <= Date.parse(observation.observedAt);
@@ -750,20 +745,20 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
750
745
  ? `Role not found: ${request.taskId}/${request.roleName}.`
751
746
  : `Global Role not found: ${request.roleName}.`);
752
747
  }
753
- const activeRun = request.scope === "task"
754
- ? store.getActiveAgentRun(request.taskId, request.roleName)
748
+ const activeTurn = request.scope === "task"
749
+ ? store.getActiveTurn(request.taskId, request.roleName)
755
750
  : null;
756
- if (request.scope === "task" && activeRun === null) {
757
- throw applicationError("INVALID_PARAMS", "Task Role runtime attachment requires an admitted active Run; it cannot create an empty Provider Conversation.");
751
+ if (request.scope === "task" && activeTurn === null) {
752
+ throw applicationError("INVALID_PARAMS", "Task Role runtime attachment requires an admitted active Turn; it cannot create an empty Provider Conversation.");
758
753
  }
759
754
  const managedWorkspace = request.scope === "task"
760
- ? activeRun?.workspace
755
+ ? activeTurn?.workspace
761
756
  ?? currentDesiredManagedWorkspace(store, request.taskId, request.roleName)
762
757
  : undefined;
763
758
  const sessions = request.scope === "task"
764
759
  ? store.getTaskRoleSessionSet(request.taskId, request.roleName)
765
760
  : store.getGlobalRoleSessionSet(request.roleName);
766
- const effective = activeRun?.effective
761
+ const effective = activeTurn?.effective
767
762
  ?? activeLiveRoleAgentSession(sessions)?.effective
768
763
  ?? resolveRuntimeDesiredEffective(store, request, role);
769
764
  const binding = role.agentBindings[effective.agentId];
@@ -776,14 +771,12 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
776
771
  }
777
772
  validateLifecycleEnvironment(request.environment, agent);
778
773
  const session = sessions?.sessions[effective.agentId];
779
- const managedTurnDispatch = activeRun !== null && (activeRun.pushedAt === undefined
780
- || activeRun.controlRequest?.state === "dispatching");
781
- // An ensure call may reattach the already-admitted Run to its existing
774
+ // An ensure call may reattach the already-admitted Turn to its existing
782
775
  // Conversation, but it may not manufacture a fresh Conversation without a
783
- // pending managed Turn. Fresh replacement remains owned by Run dispatch.
784
- const mode = activeRun === null
776
+ // pending managed Turn. Fresh replacement remains owned by Turn dispatch.
777
+ const mode = activeTurn === null
785
778
  ? roleAgentSessionResumeMode(sessions, effective.agentId, effective)
786
- : managedTurnDispatch ? activeRun.mode : "resume";
779
+ : session?.nativeSessionId === undefined ? activeTurn.mode : "resume";
787
780
  if (request.scope === "task" && mode === "resume"
788
781
  && (session?.nativeSessionId === undefined
789
782
  || session.nativeSessionId.trim().length === 0)) {
@@ -799,7 +792,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
799
792
  effective,
800
793
  workspace: effective.workspace.root,
801
794
  ...(managedWorkspace === undefined ? {} : { managedWorkspace }),
802
- ...(activeRun === null ? {} : { runId: activeRun.id }),
795
+ ...(activeTurn === null ? {} : { turnId: activeTurn.id }),
803
796
  ...(request.environment === undefined
804
797
  ? {}
805
798
  : { environment: request.environment })
@@ -852,7 +845,7 @@ function resolveRuntimeDesiredEffective(store, request, role) {
852
845
  });
853
846
  }
854
847
  function assertRuntimeLaunchRequestCurrent(store, request) {
855
- let activeRun = null;
848
+ let activeTurn = null;
856
849
  if (request.owner.scope === "task") {
857
850
  const task = store.getTask(request.owner.taskId);
858
851
  if (task === null
@@ -860,10 +853,10 @@ function assertRuntimeLaunchRequestCurrent(store, request) {
860
853
  || task.executionGate.state !== "enabled") {
861
854
  throw new Error(`Task is no longer active: ${request.owner.taskId}.`);
862
855
  }
863
- activeRun = store.getActiveAgentRun(request.owner.taskId, request.owner.roleName);
864
- if (request.runId !== undefined
865
- && activeRun?.id !== request.runId) {
866
- throw new Error(`Role Run is no longer current: ${request.runId}.`);
856
+ activeTurn = store.getActiveTurn(request.owner.taskId, request.owner.roleName);
857
+ if (request.turnId !== undefined
858
+ && activeTurn?.id !== request.turnId) {
859
+ throw new Error(`Role Turn is no longer current: ${request.turnId}.`);
867
860
  }
868
861
  }
869
862
  const role = request.owner.scope === "task"
@@ -875,8 +868,8 @@ function assertRuntimeLaunchRequestCurrent(store, request) {
875
868
  const sessions = request.owner.scope === "task"
876
869
  ? store.getTaskRoleSessionSet(request.owner.taskId, request.owner.roleName)
877
870
  : store.getGlobalRoleSessionSet(request.owner.roleName);
878
- const expectedEffective = request.owner.scope === "task" && request.runId !== undefined
879
- ? activeRun?.effective
871
+ const expectedEffective = request.owner.scope === "task" && request.turnId !== undefined
872
+ ? activeTurn?.effective
880
873
  : activeLiveRoleAgentSession(sessions)?.effective
881
874
  ?? currentDesiredEffective(store, request, role);
882
875
  if (expectedEffective === undefined
@@ -887,7 +880,7 @@ function assertRuntimeLaunchRequestCurrent(store, request) {
887
880
  throw new Error(`Role launch state changed: ${request.owner.roleName}.`);
888
881
  }
889
882
  if (request.owner.scope === "task" && request.managedWorkspace !== undefined) {
890
- const expectedWorkspace = activeRun?.workspace
883
+ const expectedWorkspace = activeTurn?.workspace
891
884
  ?? currentDesiredManagedWorkspace(store, request.owner.taskId, request.owner.roleName);
892
885
  if (expectedWorkspace === undefined
893
886
  || !sameManagedWorkspaceIdentity(expectedWorkspace, request.managedWorkspace)) {
@@ -1129,7 +1122,7 @@ function providerTurnControlParams(params) {
1129
1122
  return {
1130
1123
  taskId: requiredParam(value.taskId),
1131
1124
  roleName: requiredParam(value.roleName),
1132
- runId: requiredParam(value.runId),
1125
+ ...(value.turnId === undefined ? {} : { turnId: requiredParam(value.turnId) }),
1133
1126
  agentId: requiredParam(value.agentId),
1134
1127
  launchId: requiredParam(value.launchId),
1135
1128
  nativeSessionId: requiredParam(value.nativeSessionId),