@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
@@ -96,7 +96,7 @@ export function assertExecutionTargetUnchanged(group, target) {
96
96
  * Enforce the only durable Group/Lane evolution accepted by both domain
97
97
  * helpers and storage. Identity, target, prior results, and a final Leader
98
98
  * resolution never move backwards. A terminal Lane may only reopen as an
99
- * explicit retry with a fresh Run identity, or reset to pending for a
99
+ * explicit retry with a fresh Turn identity, or reset to pending for a
100
100
  * Task-final Review execution retry.
101
101
  */
102
102
  export function assertExecutionGroupTransition(existing, candidate) {
@@ -153,11 +153,11 @@ export function updateExecutionLane(group, laneId, patch, now) {
153
153
  }
154
154
  const status = patch.status ?? existing.status;
155
155
  const timestamp = now.toISOString();
156
- const terminal = status === "completed" || status === "failed" || status === "yielded";
156
+ const terminal = status === "completed" || status === "failed";
157
157
  const next = {
158
158
  ...existing,
159
159
  ...(patch.effective === undefined ? {} : { effective: validateEffectiveLaunchSnapshot(patch.effective) }),
160
- ...(patch.runId === undefined ? {} : { runId: requireIdentity(patch.runId, "Agent Run id") }),
160
+ ...(patch.turnId === undefined ? {} : { turnId: requireIdentity(patch.turnId, "Turn id") }),
161
161
  ...(patch.sessionId === undefined ? {} : { sessionId: requireIdentity(patch.sessionId, "Session id") }),
162
162
  ...(patch.reviewRoundId === undefined ? {} : { reviewRoundId: requireIdentity(patch.reviewRoundId, "ReviewRound id") }),
163
163
  ...(patch.workspace === undefined ? {} : { workspace: validateLaneWorkspace(patch.workspace) }),
@@ -173,8 +173,8 @@ export function updateExecutionLane(group, laneId, patch, now) {
173
173
  });
174
174
  }
175
175
  /**
176
- * Reopens only a failed Lane for an explicit WorkItem retry. Completed and
177
- * yielded results are immutable reusable outputs; retrying them would erase
176
+ * Reopens only a failed Lane for an explicit WorkItem retry. Completed
177
+ * results are immutable reusable outputs; retrying them would erase
178
178
  * the Group's durable evidence instead of recovering unfinished work.
179
179
  */
180
180
  export function restartExecutionLane(group, laneId, patch, now) {
@@ -187,14 +187,14 @@ export function restartExecutionLane(group, laneId, patch, now) {
187
187
  if (existing === undefined)
188
188
  throw new Error(`ExecutionLane not found: ${group.id}/${id}.`);
189
189
  if (existing.status !== "failed") {
190
- throw new Error(`Only failed ExecutionLanes can start a new AgentRun: ${group.id}/${id}.`);
190
+ throw new Error(`Only failed ExecutionLanes can start a new Turn: ${group.id}/${id}.`);
191
191
  }
192
192
  const timestamp = now.toISOString();
193
193
  const { result: _result, endedAt: _endedAt, ...base } = existing;
194
194
  const next = {
195
195
  ...base,
196
196
  ...(patch.effective === undefined ? {} : { effective: validateEffectiveLaunchSnapshot(patch.effective) }),
197
- ...(patch.runId === undefined ? {} : { runId: requireIdentity(patch.runId, "Agent Run id") }),
197
+ ...(patch.turnId === undefined ? {} : { turnId: requireIdentity(patch.turnId, "Turn id") }),
198
198
  ...(patch.sessionId === undefined ? {} : { sessionId: requireIdentity(patch.sessionId, "Session id") }),
199
199
  ...(patch.reviewRoundId === undefined ? {} : { reviewRoundId: requireIdentity(patch.reviewRoundId, "ReviewRound id") }),
200
200
  ...(patch.workspace === undefined ? {} : { workspace: validateLaneWorkspace(patch.workspace) }),
@@ -209,8 +209,8 @@ export function restartExecutionLane(group, laneId, patch, now) {
209
209
  });
210
210
  }
211
211
  /**
212
- * Reopen a failed execution Lane without starting its next Run when Resource
213
- * Broker capacity is unavailable. The failed attempt remains in AgentRun
212
+ * Reopen a failed execution Lane without starting its next Turn when Resource
213
+ * Broker capacity is unavailable. The failed attempt remains in Turn
214
214
  * history; the Lane freezes the next launch input until ordinary dispatch can
215
215
  * admit it.
216
216
  */
@@ -229,7 +229,7 @@ export function queueExecutionLaneRetry(group, laneId, patch, now) {
229
229
  throw new Error(`Only a failed ExecutionLane can queue a retry: ${group.id}/${laneId}.`);
230
230
  }
231
231
  const timestamp = now.toISOString();
232
- const { runId: _runId, sessionId: _sessionId, result: _result, endedAt: _endedAt, ...base } = existing;
232
+ const { turnId: _turnId, sessionId: _sessionId, result: _result, endedAt: _endedAt, ...base } = existing;
233
233
  const next = {
234
234
  ...base,
235
235
  effective: validateEffectiveLaunchSnapshot(patch.effective),
@@ -246,7 +246,7 @@ export function queueExecutionLaneRetry(group, laneId, patch, now) {
246
246
  }
247
247
  /**
248
248
  * Resets a terminal Reviewer Lane to pending without replacing its ExecutionGroup.
249
- * The old AgentRun remains the attempt trail; clearing the Lane's Run/session and
249
+ * The old Turn remains the attempt trail; clearing the Lane's Turn/Session and
250
250
  * result lets the same semantic ReviewRound be dispatched again.
251
251
  */
252
252
  export function resetReviewExecutionLane(group, laneId, now) {
@@ -263,7 +263,7 @@ export function resetReviewExecutionLane(group, laneId, now) {
263
263
  if (!isTerminalLane(existing.status))
264
264
  return existing;
265
265
  const timestamp = now.toISOString();
266
- const { effective: _effective, runId: _runId, sessionId: _sessionId, result: _result, endedAt: _endedAt, ...base } = existing;
266
+ const { effective: _effective, turnId: _turnId, sessionId: _sessionId, result: _result, endedAt: _endedAt, ...base } = existing;
267
267
  return validateExecutionLane({
268
268
  ...base,
269
269
  status: "pending",
@@ -289,7 +289,7 @@ export function recordExecutionLaneResult(group, laneId, result, status, now) {
289
289
  });
290
290
  }
291
291
  /**
292
- * Stop only work that has never started. Running Lanes retain their exact Run
292
+ * Stop only work that has never started. Running Lanes retain their exact Turn
293
293
  * and Session; the Resource Broker never kills a straggler merely to save
294
294
  * budget. Skipped Lanes are terminal but never usable Candidate inputs.
295
295
  */
@@ -309,7 +309,7 @@ export function skipPendingExecutionLanes(group, laneIds, summary, now) {
309
309
  const lane = group.lanes.find(({ id }) => id === laneId);
310
310
  if (lane === undefined)
311
311
  throw new Error(`ExecutionLane not found: ${group.id}/${laneId}.`);
312
- if (lane.status !== "pending" || lane.runId !== undefined) {
312
+ if (lane.status !== "pending" || lane.turnId !== undefined) {
313
313
  throw new Error(`Only an unstarted pending ExecutionLane can be skipped: ${group.id}/${laneId}.`);
314
314
  }
315
315
  }
@@ -339,7 +339,7 @@ export function resolveExecutionGroup(group, input, now) {
339
339
  const summary = requireText(input.summary, "Execution resolution summary");
340
340
  const defaultSelectedLaneIds = input.decision === "accept"
341
341
  ? group.lanes
342
- .filter((lane) => lane.status === "yielded" || lane.status === "completed")
342
+ .filter((lane) => lane.status === "completed")
343
343
  .map(({ id }) => id)
344
344
  : group.lanes.map(({ id }) => id);
345
345
  const selected = [...new Set((input.selectedLaneIds ?? defaultSelectedLaneIds)
@@ -349,12 +349,12 @@ export function resolveExecutionGroup(group, input, now) {
349
349
  }
350
350
  if (input.decision === "accept" && selected.some((id) => {
351
351
  const lane = group.lanes.find((candidate) => candidate.id === id);
352
- return lane?.status !== "yielded" && lane?.status !== "completed";
352
+ return lane?.status !== "completed";
353
353
  })) {
354
354
  throw new Error(`ExecutionGroup accept selects a Lane without usable terminal output: ${group.id}.`);
355
355
  }
356
356
  if (input.decision === "accept" && group.stage?.resources !== undefined) {
357
- const usable = group.lanes.filter(({ status }) => (status === "yielded" || status === "completed")).length;
357
+ const usable = group.lanes.filter(({ status }) => status === "completed").length;
358
358
  if (usable < group.stage.resources.quorum) {
359
359
  throw new Error(`ExecutionGroup quorum is not met: ${usable}/${group.stage.resources.quorum} usable Lanes.`);
360
360
  }
@@ -398,7 +398,7 @@ export function summarizeExecutionGroup(group) {
398
398
  laneId: lane.id,
399
399
  roleName: lane.roleName,
400
400
  ordinal: lane.ordinal,
401
- ...(lane.runId === undefined ? {} : { runId: lane.runId }),
401
+ ...(lane.turnId === undefined ? {} : { turnId: lane.turnId }),
402
402
  ...(lane.sessionId === undefined ? {} : { sessionId: lane.sessionId }),
403
403
  ...(lane.effective === undefined ? {} : { effective: lane.effective }),
404
404
  ...(lane.directive === undefined ? {} : { directive: lane.directive }),
@@ -571,7 +571,7 @@ export function validateExecutionLane(lane, group) {
571
571
  throw new Error(`ExecutionLane belongs to another Group: ${lane.id}.`);
572
572
  if (group.purpose === "review" && lane.reviewRoundId === undefined) {
573
573
  // A review lane may be pending before its ReviewRound is dispatched, but
574
- // it must acquire that identity before it can run.
574
+ // it must acquire that identity before it can turn.
575
575
  if (lane.status === "running"
576
576
  || lane.status === "completed"
577
577
  || lane.status === "failed"
@@ -584,8 +584,8 @@ export function validateExecutionLane(lane, group) {
584
584
  requireIdentity(lane.roleName, "ExecutionLane Role");
585
585
  if (lane.effective !== undefined)
586
586
  validateEffectiveLaunchSnapshot(lane.effective);
587
- if (lane.runId !== undefined)
588
- requireIdentity(lane.runId, "Agent Run id");
587
+ if (lane.turnId !== undefined)
588
+ requireIdentity(lane.turnId, "Turn id");
589
589
  if (lane.sessionId !== undefined)
590
590
  requireIdentity(lane.sessionId, "Session id");
591
591
  if (lane.reviewRoundId !== undefined)
@@ -594,14 +594,14 @@ export function validateExecutionLane(lane, group) {
594
594
  validateLaneWorkspace(lane.workspace);
595
595
  if (lane.directive !== undefined)
596
596
  requireText(lane.directive, "ExecutionLane directive");
597
- if (!["pending", "running", "yielded", "completed", "failed", "skipped"].includes(lane.status)) {
597
+ if (!["pending", "running", "completed", "failed", "skipped"].includes(lane.status)) {
598
598
  throw new Error(`ExecutionLane status is invalid: ${String(lane.status)}.`);
599
599
  }
600
600
  if (lane.status === "skipped") {
601
601
  if (group !== undefined && group.purpose !== "execution") {
602
602
  throw new Error(`Only WorkItem ExecutionLanes can be skipped: ${lane.id}.`);
603
603
  }
604
- if (lane.runId !== undefined || lane.sessionId !== undefined) {
604
+ if (lane.turnId !== undefined || lane.sessionId !== undefined) {
605
605
  throw new Error(`Skipped ExecutionLane must never have started: ${lane.id}.`);
606
606
  }
607
607
  }
@@ -627,7 +627,7 @@ function createLane(id, groupId, input, ordinal, timestamp) {
627
627
  ordinal: positiveInteger(input.ordinal ?? ordinal, "ExecutionLane ordinal"),
628
628
  roleName: requireIdentity(input.roleName, "ExecutionLane Role"),
629
629
  ...(input.effective === undefined ? {} : { effective: validateEffectiveLaunchSnapshot(input.effective) }),
630
- ...(input.runId === undefined ? {} : { runId: requireIdentity(input.runId, "Agent Run id") }),
630
+ ...(input.turnId === undefined ? {} : { turnId: requireIdentity(input.turnId, "Turn id") }),
631
631
  ...(input.sessionId === undefined ? {} : { sessionId: requireIdentity(input.sessionId, "Session id") }),
632
632
  ...(input.reviewRoundId === undefined ? {} : { reviewRoundId: requireIdentity(input.reviewRoundId, "ReviewRound id") }),
633
633
  ...(input.workspace === undefined ? {} : { workspace: validateLaneWorkspace(input.workspace) }),
@@ -745,7 +745,7 @@ function validateResolution(resolution, group) {
745
745
  && (resolution.selectedLaneIds.length === 0
746
746
  || resolution.selectedLaneIds.some((id) => {
747
747
  const lane = group.lanes.find((candidate) => candidate.id === id);
748
- return lane?.status !== "yielded" && lane?.status !== "completed";
748
+ return lane?.status !== "completed";
749
749
  }))) {
750
750
  throw new Error("Execution accept resolution must select usable Lane output.");
751
751
  }
@@ -780,7 +780,7 @@ function assertExecutionLaneTransition(existing, candidate, groupId, groupPurpos
780
780
  if (groupPurpose === "review"
781
781
  && candidate.status === "pending"
782
782
  && candidate.effective === undefined
783
- && candidate.runId === undefined
783
+ && candidate.turnId === undefined
784
784
  && candidate.sessionId === undefined
785
785
  && candidate.result === undefined
786
786
  && candidate.endedAt === undefined
@@ -791,7 +791,7 @@ function assertExecutionLaneTransition(existing, candidate, groupId, groupPurpos
791
791
  && existing.status === "failed"
792
792
  && candidate.status === "pending"
793
793
  && candidate.effective !== undefined
794
- && candidate.runId === undefined
794
+ && candidate.turnId === undefined
795
795
  && candidate.sessionId === undefined
796
796
  && candidate.result === undefined
797
797
  && candidate.endedAt === undefined
@@ -799,16 +799,16 @@ function assertExecutionLaneTransition(existing, candidate, groupId, groupPurpos
799
799
  return;
800
800
  }
801
801
  if (candidate.status !== "running"
802
- || candidate.runId === undefined
803
- || candidate.runId === existing.runId) {
804
- throw new Error(`Terminal ExecutionLane is immutable without a fresh retry Run: ${existing.id}.`);
802
+ || candidate.turnId === undefined
803
+ || candidate.turnId === existing.turnId) {
804
+ throw new Error(`Terminal ExecutionLane is immutable without a fresh retry Turn: ${existing.id}.`);
805
805
  }
806
806
  return;
807
807
  }
808
808
  if (existing.status === "running" && candidate.status === "pending") {
809
809
  throw new Error(`Running ExecutionLane cannot return to pending: ${existing.id}.`);
810
810
  }
811
- for (const key of ["effective", "runId", "sessionId", "workspace", "directive"]) {
811
+ for (const key of ["effective", "turnId", "sessionId", "workspace", "directive"]) {
812
812
  if (existing[key] !== undefined
813
813
  && !isDeepStrictEqual(existing[key], candidate[key])) {
814
814
  throw new Error(`ExecutionLane ${key} changed without retry: ${existing.id}.`);
@@ -837,8 +837,7 @@ function validatePurpose(purpose) {
837
837
  return purpose;
838
838
  }
839
839
  function isTerminalLane(status) {
840
- return status === "yielded"
841
- || status === "completed"
840
+ return status === "completed"
842
841
  || status === "failed"
843
842
  || status === "skipped";
844
843
  }
@@ -1,4 +1,4 @@
1
- import { isRoleRunStalled, latestStallProgressAt } from "../scheduler/roleRunStall.js";
1
+ import { isRoleTurnStalled, latestStallProgressAt } from "../scheduler/roleTurnStall.js";
2
2
  import { validateRuntimeProcessExitObservation } from "../runtime/processExitObservation.js";
3
3
  import { runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
4
4
  import { projectRuntimeTaskEvents } from "../runtime/runtimeProjection.js";
@@ -7,9 +7,9 @@ import { runOwnsBlockingProviderContinuation } from "../runtime/runtimeContinuat
7
7
  import { summarizeExecutionGroup } from "./executionGroup.js";
8
8
  import { executionStageSpendClosed, observedExecutionResourceUsage, projectExecutionStageResources } from "./resourceBroker.js";
9
9
  /**
10
- * Fold existing Run, runtime, Session, process-exit, and stall facts into the
10
+ * Fold existing Turn, runtime, Session, process-exit, and stall facts into the
11
11
  * four Lane health states. This is a read model only: it never advances a
12
- * Lane, terminalizes a Run, or guesses that silence means death.
12
+ * Lane, terminalizes a Turn, or guesses that silence means death.
13
13
  */
14
14
  export function projectExecutionGroupHealth(input) {
15
15
  const policy = input.policy ?? DEFAULT_RUNTIME_HEALTH_POLICY;
@@ -23,7 +23,7 @@ export function projectExecutionGroupHealth(input) {
23
23
  confirmedDeadLaneCount: countHealth(lanes, "confirmed-dead"),
24
24
  reusableLaneIds: lanes.filter(({ resultReusable }) => resultReusable)
25
25
  .map(({ laneId }) => laneId),
26
- retryableLaneIds: lanes.filter(({ recovery }) => recovery === "retry-new-agent-run")
26
+ retryableLaneIds: lanes.filter(({ recovery }) => recovery === "retry-new-turn")
27
27
  .map(({ laneId }) => laneId)
28
28
  });
29
29
  }
@@ -39,7 +39,7 @@ export function summarizeExecutionGroupHealth(input) {
39
39
  usage: observedExecutionResourceUsage({
40
40
  group: input.group,
41
41
  ...(input.stageGroups === undefined ? {} : { stageGroups: input.stageGroups }),
42
- runs: input.runs,
42
+ turns: input.turns,
43
43
  events: input.events
44
44
  }),
45
45
  now: input.now
@@ -67,45 +67,44 @@ export function actionableExecutionLaneRecoveries(groups) {
67
67
  return groups
68
68
  .filter(({ resolution }) => resolution === undefined)
69
69
  .flatMap((group) => group.laneSummaries.flatMap((lane) => {
70
- if (lane.recovery === "retry-new-agent-run"
70
+ if (lane.recovery === "retry-new-turn"
71
71
  && group.resources !== undefined
72
72
  && executionStageSpendClosed(group.resources))
73
73
  return [];
74
- if (lane.recovery !== "retry-new-agent-run")
74
+ if (lane.recovery !== "retry-new-turn")
75
75
  return [];
76
76
  return [{
77
77
  groupId: group.groupId,
78
78
  laneId: lane.laneId,
79
- ...(lane.runId === undefined ? {} : { runId: lane.runId }),
79
+ ...(lane.turnId === undefined ? {} : { turnId: lane.turnId }),
80
80
  ...(lane.runtimeHealth === undefined ? {} : { runtimeHealth: lane.runtimeHealth }),
81
81
  recovery: lane.recovery
82
82
  }];
83
83
  }));
84
84
  }
85
85
  function projectExecutionLaneHealth(lane, input, policy) {
86
- const run = lane.runId === undefined
86
+ const run = lane.turnId === undefined
87
87
  ? undefined
88
- : input.runs.find((candidate) => exactLaneRun(candidate, input.group, lane));
88
+ : input.turns.find((candidate) => exactLaneTurn(candidate, input.group, lane));
89
89
  const continuationAgentId = run?.effective.agentId ?? lane.effective?.agentId;
90
90
  if (lane.status !== "completed"
91
- && lane.status !== "yielded"
92
- && lane.runId !== undefined
91
+ && lane.turnId !== undefined
93
92
  && continuationAgentId !== undefined
94
93
  && runOwnsBlockingProviderContinuation(input.events, {
95
94
  taskId: input.group.taskId,
96
95
  roleName: lane.roleName,
97
- runId: lane.runId,
96
+ turnId: lane.turnId,
98
97
  agentId: continuationAgentId
99
98
  })) {
100
99
  return projection(lane, {
101
100
  runtimeHealth: "active",
102
101
  recovery: "none",
103
102
  resultReusable: false,
104
- reason: "the exact Run still owns an unsettled Provider continuation writer",
103
+ reason: "the exact Turn still owns an unsettled Provider continuation writer",
105
104
  evidence: ["runtime-continuation-writer-owned"]
106
105
  });
107
106
  }
108
- if (lane.status === "completed" || lane.status === "yielded") {
107
+ if (lane.status === "completed") {
109
108
  return projection(lane, {
110
109
  recovery: "reuse-result",
111
110
  resultReusable: true,
@@ -116,9 +115,9 @@ function projectExecutionLaneHealth(lane, input, policy) {
116
115
  if (lane.status === "failed") {
117
116
  return projection(lane, {
118
117
  runtimeHealth: "confirmed-dead",
119
- recovery: "retry-new-agent-run",
118
+ recovery: "retry-new-turn",
120
119
  resultReusable: false,
121
- reason: "the exact Lane attempt is durably failed; a retry must create a new AgentRun",
120
+ reason: "the exact Lane attempt is durably failed; a retry must create a new Turn",
122
121
  evidence: ["execution-lane-terminal-failure"]
123
122
  });
124
123
  }
@@ -143,17 +142,17 @@ function projectExecutionLaneHealth(lane, input, policy) {
143
142
  runtimeHealth: "suspected-stalled",
144
143
  recovery: "inspect",
145
144
  resultReusable: false,
146
- reason: "the running Lane has no exact AgentRun record",
145
+ reason: "the running Lane has no exact Turn record",
147
146
  evidence: ["execution-lineage-missing"]
148
147
  });
149
148
  }
150
149
  if (run.status === "failed") {
151
150
  return projection(lane, {
152
151
  runtimeHealth: "confirmed-dead",
153
- recovery: "retry-new-agent-run",
152
+ recovery: "retry-new-turn",
154
153
  resultReusable: false,
155
- reason: "the exact AgentRun is durably failed",
156
- evidence: ["agent-run-terminal-failure"]
154
+ reason: "the exact Turn is durably failed",
155
+ evidence: ["turn-terminal-failure"]
157
156
  });
158
157
  }
159
158
  if (run.status !== "active") {
@@ -161,14 +160,14 @@ function projectExecutionLaneHealth(lane, input, policy) {
161
160
  runtimeHealth: "suspected-stalled",
162
161
  recovery: "inspect",
163
162
  resultReusable: false,
164
- reason: "the Lane is running but its exact AgentRun is terminal without a Lane result",
163
+ reason: "the Lane is running but its exact Turn is terminal without a Lane result",
165
164
  evidence: ["execution-lineage-inconsistent"]
166
165
  });
167
166
  }
168
167
  const session = input.sessions.find((candidate) => (candidate.roleName === run.roleName
169
168
  && candidate.agentId === run.effective.agentId
170
169
  && candidate.adapterId === run.effective.adapterId));
171
- const observations = exactRunObservations(input.events, run, session);
170
+ const observations = exactTurnObservations(input.events, run, session);
172
171
  const runtime = runtimeProjection(observations, input.events, run);
173
172
  const unsettledContinuation = runtime !== null
174
173
  && Object.values(runtime.continuations).some((continuation) => (continuation.execution === "active"
@@ -178,13 +177,13 @@ function projectExecutionLaneHealth(lane, input, policy) {
178
177
  && (Object.values(runtime.operations).some(({ kind }) => kind === "subagent")
179
178
  || unsettledContinuation);
180
179
  if (observations.some((observation) => (observation.kind === "turn.failed"
181
- && observation.payload.failure?.runTerminal === true)) && !unsettledChildWork) {
180
+ && observation.payload.failure?.turnTerminal === true)) && !unsettledChildWork) {
182
181
  return projection(lane, {
183
182
  runtimeHealth: "confirmed-dead",
184
183
  recovery: "inspect",
185
184
  resultReusable: false,
186
- reason: "the Provider reported an exact run-terminal failure",
187
- evidence: ["provider-run-terminal"]
185
+ reason: "the Provider reported an exact Turn-terminal failure",
186
+ evidence: ["provider-turn-terminal"]
188
187
  });
189
188
  }
190
189
  const runtimeTerminalEvidence = runtime === null
@@ -218,20 +217,19 @@ function projectExecutionLaneHealth(lane, input, policy) {
218
217
  evidence: ["native-session-terminal", `process-exit:${exit.classification}`]
219
218
  });
220
219
  }
221
- if (isRoleRunStalled(input.events, run.id)) {
220
+ if (isRoleTurnStalled(input.events, run.id)) {
222
221
  return projection(lane, {
223
222
  runtimeHealth: "suspected-stalled",
224
223
  recovery: "inspect",
225
224
  resultReusable: false,
226
225
  reason: `the durable progress clock has not advanced since ${latestStallProgressAt(input.events, run.id) ?? run.updatedAt}; no death proof exists`,
227
- evidence: ["run-stalled"]
226
+ evidence: ["turn-stalled"]
228
227
  });
229
228
  }
230
229
  const activeOperation = runtime !== null
231
230
  && (Object.keys(runtime.operations).length > 0 || unsettledContinuation);
232
231
  const lastActivityAt = runtime?.lastRuntimeActivityAt
233
- ?? run.deliveredAt
234
- ?? run.pushedAt
232
+ ?? run.updatedAt
235
233
  ?? run.createdAt;
236
234
  const recentActivity = input.now.getTime() - Date.parse(lastActivityAt) < policy.quietAfterMs;
237
235
  if (activeOperation || recentActivity) {
@@ -243,7 +241,7 @@ function projectExecutionLaneHealth(lane, input, policy) {
243
241
  ? "the exact runtime reports unsettled continuation work"
244
242
  : activeOperation
245
243
  ? "the exact runtime reports an active operation"
246
- : "the exact Run has recent structured runtime activity",
244
+ : "the exact Turn has recent structured runtime activity",
247
245
  evidence: unsettledContinuation
248
246
  ? ["runtime-continuation-unsettled"]
249
247
  : activeOperation ? ["runtime-operation-active"] : ["runtime-activity-recent"]
@@ -253,25 +251,25 @@ function projectExecutionLaneHealth(lane, input, policy) {
253
251
  runtimeHealth: "silent",
254
252
  recovery: "none",
255
253
  resultReusable: false,
256
- reason: "the exact Run remains active without recent structured activity; silence alone is not death",
257
- evidence: ["agent-run-active"]
254
+ reason: "the exact Turn remains active without recent structured activity; silence alone is not death",
255
+ evidence: ["turn-active"]
258
256
  });
259
257
  }
260
258
  function projection(lane, value) {
261
259
  return Object.freeze({ laneId: lane.id, ...value });
262
260
  }
263
- function exactLaneRun(run, group, lane) {
264
- return run.id === lane.runId
261
+ function exactLaneTurn(run, group, lane) {
262
+ return run.id === lane.turnId
265
263
  && run.taskId === group.taskId
266
264
  && run.roleName === lane.roleName
267
265
  && run.executionGroupId === group.id
268
266
  && run.executionLaneId === lane.id;
269
267
  }
270
- function exactRunObservations(events, run, session) {
268
+ function exactTurnObservations(events, run, session) {
271
269
  return events.map(runtimeObservationFromTaskEvent)
272
270
  .filter((observation) => (observation !== null
273
271
  && observation.fence.taskId === run.taskId
274
- && observation.fence.runId === run.id
272
+ && observation.fence.turnId === run.id
275
273
  && observation.fence.roleName === run.roleName
276
274
  && observation.fence.agentId === run.effective.agentId
277
275
  && (session?.launchId === undefined || observation.fence.launchId === session.launchId)
@@ -291,7 +289,7 @@ function latestExactProcessExit(events, run, session) {
291
289
  try {
292
290
  const observation = validateRuntimeProcessExitObservation(JSON.parse(event.payload.observation ?? ""));
293
291
  if (observation.taskId !== run.taskId
294
- || observation.runId !== run.id
292
+ || observation.turnId !== run.id
295
293
  || observation.roleName !== run.roleName
296
294
  || (session?.launchId !== undefined && observation.launchId !== session.launchId)
297
295
  || (session?.nativeSessionId !== undefined
@@ -300,23 +300,23 @@ export function observedExecutionResourceUsage(input) {
300
300
  const group = validateExecutionGroup(input.group);
301
301
  const stageGroups = executionStageRetryLineage(group, input.stageGroups);
302
302
  const groupIds = new Set(stageGroups.map(({ id }) => id));
303
- const runIds = new Set([
303
+ const turnIds = new Set([
304
304
  ...stageGroups.flatMap((candidate) => candidate.lanes
305
- .flatMap(({ runId }) => runId === undefined ? [] : [runId])),
306
- ...(input.runs ?? []).filter((run) => (run.taskId === group.taskId
307
- && run.purpose === "execution"
308
- && run.executionGroupId !== undefined
309
- && groupIds.has(run.executionGroupId))).map(({ id }) => id)
305
+ .flatMap(({ turnId }) => turnId === undefined ? [] : [turnId])),
306
+ ...(input.turns ?? []).filter((turn) => (turn.taskId === group.taskId
307
+ && turn.purpose === "execution"
308
+ && turn.executionGroupId !== undefined
309
+ && groupIds.has(turn.executionGroupId))).map(({ id }) => id)
310
310
  ]);
311
311
  const observations = input.events.map(runtimeObservationFromTaskEvent)
312
312
  .filter((value) => (value !== null
313
313
  && value.fence.taskId === group.taskId
314
- && value.fence.runId !== undefined
315
- && runIds.has(value.fence.runId)));
314
+ && value.fence.turnId !== undefined
315
+ && turnIds.has(value.fence.turnId)));
316
316
  let tokens = 0;
317
317
  let tokensObservable = true;
318
- for (const runId of runIds) {
319
- const usage = observations.filter(({ fence, payload }) => (fence.runId === runId && payload.usage !== undefined)).sort((left, right) => (left.receivedAt.localeCompare(right.receivedAt)
318
+ for (const turnId of turnIds) {
319
+ const usage = observations.filter(({ fence, payload }) => (fence.turnId === turnId && payload.usage !== undefined)).sort((left, right) => (left.receivedAt.localeCompare(right.receivedAt)
320
320
  || (left.sequence ?? 0) - (right.sequence ?? 0)
321
321
  || (left.ordinal ?? 0) - (right.ordinal ?? 0)));
322
322
  if (usage.length === 0) {
@@ -345,7 +345,7 @@ export function observedExecutionResourceUsage(input) {
345
345
  tokensObservable = false;
346
346
  }
347
347
  const toolOperationIds = new Set(observations.flatMap((observation) => (observation.kind === "operation.started" && observation.payload.operation === "tool"
348
- ? [`${observation.fence.runId}\0${observation.payload.operationId ?? observation.semanticKey}`]
348
+ ? [`${observation.fence.turnId}\0${observation.payload.operationId ?? observation.semanticKey}`]
349
349
  : [])));
350
350
  const toolCallsObservable = observations.some(({ kind, payload }) => (kind === "operation.started" && payload.operation === "tool"));
351
351
  return Object.freeze({
@@ -422,5 +422,5 @@ function percentage(value, label) {
422
422
  return value;
423
423
  }
424
424
  function isUsable(status) {
425
- return status === "yielded" || status === "completed";
425
+ return status === "completed";
426
426
  }