@zq-silk/yui 0.15.6 → 0.15.8

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 (282) hide show
  1. package/ARCHITECTURE.md +192 -399
  2. package/README.md +127 -1149
  3. package/dist/agent/adapterCatalog.js +15 -2
  4. package/dist/agent/agent.js +23 -3
  5. package/dist/agent/argumentPolicy.js +7 -1
  6. package/dist/agent/connectionPlan.js +62 -0
  7. package/dist/agent/executionComponents.js +158 -0
  8. package/dist/agent/launchEnvironment.js +31 -3
  9. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  10. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  11. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  12. package/dist/brief/taskBrief.js +12 -0
  13. package/dist/cli/agentConfigurationPicker.js +13 -0
  14. package/dist/cli/commandCatalog.js +167 -70
  15. package/dist/cli/interactionCandidates.js +5 -5
  16. package/dist/cli/interactionPolicy.js +38 -8
  17. package/dist/cli/invocationRouter.js +1 -1
  18. package/dist/cli/managedDiagnostics.js +28 -0
  19. package/dist/cli/operatorWizard.js +1 -7
  20. package/dist/cli/roleOptionOrder.js +27 -0
  21. package/dist/cli/roleWizard.js +50 -14
  22. package/dist/cli/updateOrchestrator.js +1 -1
  23. package/dist/cli/updatePorts.js +3 -4
  24. package/dist/cli.js +188 -95
  25. package/dist/commands/agentCommands.js +72 -14
  26. package/dist/commands/capabilityCommands.js +57 -0
  27. package/dist/commands/configCommands.js +20 -20
  28. package/dist/commands/deliveryGuardPreflight.js +2 -2
  29. package/dist/commands/executionAuditCommands.js +24 -24
  30. package/dist/commands/globalRoleCommands.js +1 -1
  31. package/dist/commands/grantCommands.js +4 -4
  32. package/dist/commands/operatorCommands.js +1 -7
  33. package/dist/commands/projectCommands.js +4 -4
  34. package/dist/commands/resourcesCommands.js +2 -2
  35. package/dist/commands/roleConfiguration.js +25 -5
  36. package/dist/commands/roleRuntimeGuard.js +4 -5
  37. package/dist/commands/sessionCommands.js +3 -7
  38. package/dist/commands/taskActivationCommands.js +259 -0
  39. package/dist/commands/taskActor.js +28 -49
  40. package/dist/commands/taskCommands.js +1216 -730
  41. package/dist/commands/taskContextCommand.js +39 -583
  42. package/dist/commands/taskExecutionCommands.js +32 -32
  43. package/dist/commands/taskInputCommands.js +40 -104
  44. package/dist/commands/taskIntegrationCommands.js +3 -2
  45. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  46. package/dist/commands/taskNextActionCommand.js +8 -8
  47. package/dist/commands/taskOverviewCommand.js +33 -45
  48. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  49. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  50. package/dist/commands/telemetryCommands.js +36 -38
  51. package/dist/config/configCatalog.js +4 -4
  52. package/dist/config/yuiConfig.js +8 -8
  53. package/dist/context/contextSnapshot.js +10 -10
  54. package/dist/context/dispatchContext.js +11 -11
  55. package/dist/context/roleSessionContext.js +6 -3
  56. package/dist/context/{turnContextPack.js → runContextPack.js} +146 -81
  57. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  58. package/dist/context/sessionBootstrapManifest.js +21 -2
  59. package/dist/context/sourceRunContext.js +30 -0
  60. package/dist/context/taskContext.js +458 -0
  61. package/dist/context/wakeNotification.js +27 -27
  62. package/dist/controller/agentRuntimeObserver.js +21 -24
  63. package/dist/controller/capabilityBridge.js +77 -0
  64. package/dist/controller/clientRuntime.js +65 -92
  65. package/dist/controller/controller.js +127 -188
  66. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  67. package/dist/controller/jobControl.js +54 -85
  68. package/dist/controller/resourceInventory.js +8 -27
  69. package/dist/controller/resourceInventoryLinux.js +12 -13
  70. package/dist/controller/runtime.js +530 -476
  71. package/dist/controller/runtimeEventInbox.js +55 -25
  72. package/dist/controller/runtimeEventProcessor.js +22 -31
  73. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  74. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  75. package/dist/controller/runtimeObservationHook.js +14 -18
  76. package/dist/controller/sessionNotify.js +16 -24
  77. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  78. package/dist/controller/structuredProviderObservation.js +138 -99
  79. package/dist/coordination/workMailbox.js +3 -3
  80. package/dist/coordination/workMailboxQueue.js +36 -33
  81. package/dist/core/boundedRpc.js +8 -1
  82. package/dist/core/controllerClient.js +20 -1
  83. package/dist/core/controllerServer.js +4 -4
  84. package/dist/doctor/doctor.js +13 -2
  85. package/dist/domain/agentResultTransport.js +9 -9
  86. package/dist/execution/codexThreadNaming.js +2 -8
  87. package/dist/execution/executionHealth.js +51 -63
  88. package/dist/execution/reviewMainRun.js +137 -0
  89. package/dist/execution/workItemExecution.js +28 -29
  90. package/dist/execution/workItemExecutionProjection.js +99 -107
  91. package/dist/execution/workItemMainRun.js +141 -0
  92. package/dist/executor/agentAdapter.js +227 -20
  93. package/dist/executor/agentConfigurationCatalog.js +126 -4
  94. package/dist/executor/agentConfigurationProbe.js +162 -4
  95. package/dist/executor/agentExecutor.js +79 -78
  96. package/dist/executor/effectiveLaunch.js +105 -18
  97. package/dist/executor/executorRegistry.js +29 -44
  98. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  99. package/dist/executor/workspacePreflightClassification.js +16 -16
  100. package/dist/grant/capabilityGrant.js +6 -3
  101. package/dist/input/inputRequest.js +12 -10
  102. package/dist/integration/gitIntegrationService.js +4 -11
  103. package/dist/integration/integrationQueueService.js +4 -4
  104. package/dist/interaction/operatorPresentation.js +1 -1
  105. package/dist/kernel/builtinCapabilities.js +423 -0
  106. package/dist/kernel/capabilityRegistry.js +314 -0
  107. package/dist/kernel/capabilitySchema.js +91 -0
  108. package/dist/kernel/instanceHost.js +18 -1
  109. package/dist/kernel/kernelPorts.js +4 -1
  110. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  111. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  112. package/dist/message/message.js +62 -6
  113. package/dist/message/messageContinuation.js +204 -0
  114. package/dist/observability/executionAudit.js +70 -72
  115. package/dist/observability/faultClassification.js +2 -2
  116. package/dist/observability/orchestrationMetrics.js +8 -8
  117. package/dist/operator/operatorSessionHistory.js +1 -7
  118. package/dist/output/agentConfigurationPresentation.js +8 -3
  119. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  120. package/dist/output/rolePresentation.js +54 -3
  121. package/dist/plugins/pluginChild.js +104 -0
  122. package/dist/plugins/pluginIntent.js +26 -0
  123. package/dist/plugins/pluginInterpreter.js +43 -0
  124. package/dist/plugins/pluginPackage.js +101 -0
  125. package/dist/plugins/pluginProcess.js +112 -0
  126. package/dist/plugins/pluginService.js +380 -0
  127. package/dist/profile/agentProfile.js +1 -1
  128. package/dist/repository/gitWorkspace.js +26 -4
  129. package/dist/repository/project.js +19 -4
  130. package/dist/repository/taskBaseFreshness.js +13 -13
  131. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  132. package/dist/repository/taskWorkspacePreparer.js +344 -83
  133. package/dist/resources/autoResourceGc.js +3 -3
  134. package/dist/resources/liveReferences.js +3 -3
  135. package/dist/resources/projectResource.js +123 -0
  136. package/dist/resources/projectResourceService.js +421 -0
  137. package/dist/resources/resourceDiscovery.js +6 -6
  138. package/dist/resources/resourceGc.js +1 -1
  139. package/dist/resources/resourceRegistrar.js +1 -1
  140. package/dist/resources/resourceTypes.js +1 -1
  141. package/dist/review/deltaRecheck.js +3 -3
  142. package/dist/review/reviewAcceptance.js +16 -16
  143. package/dist/review/reviewDecision.js +7 -7
  144. package/dist/review/reviewRound.js +21 -20
  145. package/dist/review/reviewerAvailability.js +2 -2
  146. package/dist/role/role.js +51 -7
  147. package/dist/role/taskRoleUpdate.js +30 -0
  148. package/dist/runtime/acpProtocol.js +425 -0
  149. package/dist/runtime/acpSession.js +731 -0
  150. package/dist/runtime/acpSessionConfiguration.js +260 -0
  151. package/dist/runtime/agentDriver.js +30 -11
  152. package/dist/runtime/agentEndpoint.js +278 -0
  153. package/dist/runtime/agentEndpointIdentity.js +86 -0
  154. package/dist/runtime/agentEndpointOwnership.js +239 -0
  155. package/dist/runtime/agentError.js +2 -10
  156. package/dist/runtime/agentHost.js +565 -314
  157. package/dist/runtime/agentRunConfiguration.js +258 -0
  158. package/dist/runtime/builtinAgentDrivers.js +134 -18
  159. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  160. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  161. package/dist/runtime/claude-process-owner +0 -0
  162. package/dist/runtime/codexAppServerRuntime.js +38 -30
  163. package/dist/runtime/codexInteractiveHost.js +41 -6
  164. package/dist/runtime/continuationManager.js +2 -6
  165. package/dist/runtime/executionEnvironment.js +30 -0
  166. package/dist/runtime/firstProgressAdvisory.js +11 -11
  167. package/dist/runtime/index.js +4 -3
  168. package/dist/runtime/jsonLineChannel.js +109 -0
  169. package/dist/runtime/launchBroker.js +91 -16
  170. package/dist/runtime/launchDiagnostics.js +2 -2
  171. package/dist/runtime/lifecycleReservation.js +10 -18
  172. package/dist/runtime/managedCaller.js +61 -17
  173. package/dist/runtime/nativeSessionControl.js +102 -0
  174. package/dist/runtime/ports.js +6 -21
  175. package/dist/runtime/processExitObservation.js +8 -7
  176. package/dist/runtime/promptEnvelope.js +17 -6
  177. package/dist/runtime/providerContinuation.js +3 -9
  178. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  179. package/dist/runtime/providerControl.js +2 -7
  180. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  181. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  182. package/dist/runtime/runtimeBinding.js +0 -1
  183. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  184. package/dist/runtime/runtimeDeadlines.js +9 -0
  185. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  186. package/dist/runtime/runtimeObservation.js +29 -65
  187. package/dist/runtime/runtimeProjection.js +43 -51
  188. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  189. package/dist/runtime/sessionLaunchRequest.js +3 -7
  190. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  191. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  192. package/dist/runtime/sessionReconciliation.js +4 -8
  193. package/dist/runtime/sessionTerminationGuard.js +70 -259
  194. package/dist/runtime/sessionTokenMetrics.js +5 -16
  195. package/dist/runtime/structuredProviderHost.js +237 -117
  196. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  197. package/dist/runtime/tmuxAdapters.js +39 -86
  198. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  199. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  200. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  201. package/dist/scheduler/ports.js +80 -9
  202. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  203. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  204. package/dist/scheduler/taskExecutionProjection.js +120 -124
  205. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  206. package/dist/scheduler/taskWake.js +11 -4
  207. package/dist/scheduler/wakeReason.js +9 -1
  208. package/dist/setup/setupCommand.js +1 -0
  209. package/dist/storage/migrations/agentRunContract.js +159 -0
  210. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  211. package/dist/storage/sqliteSchema.js +431 -5
  212. package/dist/storage/sqliteStore.js +375 -220
  213. package/dist/storage/storageVersions.js +1 -1
  214. package/dist/storage/storeRpc.js +10 -5
  215. package/dist/storage/taskStore.js +13 -11
  216. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  217. package/dist/surface/surfaceContributions.js +102 -0
  218. package/dist/task/completionReadiness.js +32 -6
  219. package/dist/task/deliveryGuard.js +16 -16
  220. package/dist/task/draftPlan.js +72 -12
  221. package/dist/task/nextAction.js +144 -128
  222. package/dist/task/remoteDelivery.js +6 -6
  223. package/dist/task/task.js +184 -18
  224. package/dist/task/taskActivation.js +301 -0
  225. package/dist/task/taskActivationService.js +392 -0
  226. package/dist/task/taskRecordReference.js +5 -4
  227. package/dist/task/taskRecordRetirement.js +1 -1
  228. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  229. package/dist/telemetry/telemetryConfig.js +14 -14
  230. package/dist/telemetry/telemetryWiring.js +2 -2
  231. package/dist/web/assets/assetManifest.js +2 -0
  232. package/dist/web/assets/client/app.js +120 -20
  233. package/dist/web/assets/client/components.js +87 -54
  234. package/dist/web/assets/client/i18n.js +83 -41
  235. package/dist/web/assets/client/markdown.js +1 -1
  236. package/dist/web/assets/client/taskSurface.js +353 -0
  237. package/dist/web/assets/client/view.js +49 -44
  238. package/dist/web/assets/shell.js +1 -1
  239. package/dist/web/assets/styles/cards.js +22 -4
  240. package/dist/web/controllerWeb.js +60 -0
  241. package/dist/web/webMutation.js +28 -0
  242. package/dist/web/webServer.js +118 -8
  243. package/dist/web/webSnapshot.js +81 -74
  244. package/dist/web/webTaskSurface.js +64 -0
  245. package/dist/workItem/dependencyGate.js +1 -1
  246. package/dist/workItem/workItem.js +80 -48
  247. package/dist/workspace/workItemChangeSetManager.js +16 -9
  248. package/docs/agent-result-consumption.md +94 -0
  249. package/docs/agent-runtime-drivers.md +91 -0
  250. package/docs/architecture/README.md +38 -0
  251. package/docs/architecture/capabilities-and-resources.md +79 -0
  252. package/docs/managed-turn-and-session-runtime.md +222 -0
  253. package/docs/observability/README.md +81 -0
  254. package/docs/plugin-sdk.md +290 -0
  255. package/docs/provider-runtime.md +163 -0
  256. package/docs/release-workflow.md +303 -0
  257. package/docs/roles-and-configuration.md +113 -0
  258. package/docs/sqlite-control-plane-design.md +76 -0
  259. package/docs/task-dag-semantics.md +57 -0
  260. package/docs/task-delivery.md +103 -0
  261. package/docs/task-local-identity.md +6 -6
  262. package/docs/testing/verification-levels.md +86 -0
  263. package/i18n/README.zh-CN.md +98 -739
  264. package/package.json +5 -5
  265. package/skills/yui-leader/SKILL.md +130 -103
  266. package/skills/yui-leader/references/integration.md +39 -0
  267. package/skills/yui-leader/references/replicated-execution.md +42 -0
  268. package/skills/yui-leader/references/task-plugins.md +33 -0
  269. package/skills/yui-operator/SKILL.md +30 -59
  270. package/skills/yui-reviewer/SKILL.md +35 -36
  271. package/skills/yui-runtime/SKILL.md +88 -24
  272. package/skills/yui-runtime/references/publication.md +22 -0
  273. package/skills/yui-runtime/references/recovery.md +64 -0
  274. package/skills/yui-worker/SKILL.md +37 -39
  275. package/dist/cli/roleOptionCatalog.js +0 -68
  276. package/dist/context/sourceTurnContext.js +0 -30
  277. package/dist/execution/reviewMainTurn.js +0 -161
  278. package/dist/execution/workItemMainTurn.js +0 -164
  279. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  280. package/dist/runtime/preallocatedNativeSession.js +0 -13
  281. package/dist/runtime/runtimeStopReceipt.js +0 -42
  282. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
package/dist/cli.js CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawnSync } from "node:child_process";
3
+ import { randomUUID } from "node:crypto";
4
+ import { agentAdapterLabel as adapterLabel } from "./agent/adapterCatalog.js";
3
5
  import { readFileSync } from "node:fs";
4
6
  import { resolve } from "node:path";
5
7
  import { createInterface } from "node:readline/promises";
@@ -24,6 +26,7 @@ import { nativeAgentEnvironmentNames } from "./agent/launchEnvironment.js";
24
26
  import { runAgentCommand } from "./commands/agentCommands.js";
25
27
  import { runGlobalRoleCommand } from "./commands/globalRoleCommands.js";
26
28
  import { runConfigCommand } from "./commands/configCommands.js";
29
+ import { runCapabilityCommand } from "./commands/capabilityCommands.js";
27
30
  import { CONFIG_DOMAINS } from "./config/configCatalog.js";
28
31
  import { runConfigOverview } from "./commands/configOverview.js";
29
32
  import { parseControllerCleanupOptions, parseControllerStatusOptions, parseControllerRuntimeSnapshot, renderControllerResourceStatus, renderRuntimeIdentitySection, summarizeDurablePhysicalMismatch, runInteractiveControllerCleanup } from "./commands/controllerCommands.js";
@@ -42,7 +45,7 @@ import { assertTaskRemoteDeliveryIntegrated, createTaskRemoteDeliveryProof } fro
42
45
  import { runTaskPublicationVerifyCommand } from "./commands/taskPublicationVerifyCommand.js";
43
46
  import { createGitHubCliPublicationVerifier } from "./external/githubPublicationVerifier.js";
44
47
  import { createGitLabCliPublicationVerifier } from "./external/gitlabPublicationVerifier.js";
45
- import { taskActor } from "./commands/taskActor.js";
48
+ import { taskLocalActor, assertTaskDeliveryAuthority } from "./commands/taskActor.js";
46
49
  import { parseTaskExecutionStartRequest, parseTaskExecutionStopRequest, finalizeStoppedTaskExecution, startTaskExecutionCommand, stopTaskExecutionCommand } from "./commands/taskExecutionCommands.js";
47
50
  import { runTaskIntegrationCommand } from "./commands/taskIntegrationCommands.js";
48
51
  import { runTaskChangeSetCommand } from "./commands/taskChangeSetCommands.js";
@@ -71,7 +74,8 @@ import { runRuntimeObservationHookCommand } from "./controller/runtimeObservatio
71
74
  import { buildDoctorReport, renderDoctor, runDoctorCommand } from "./doctor/doctor.js";
72
75
  import { agentNotFound, CliError, runtimeError, usageError } from "./errors/cliError.js";
73
76
  import { FileRoleLaunchPlanner } from "./executor/fileRoleLaunchPlanner.js";
74
- import { AGENT_HOST_CONTROL_PROTOCOL, runAgentHost, sendAgentHostAuthorityControl } from "./runtime/agentHost.js";
77
+ import { AGENT_HOST_CONTROL_PROTOCOL, inspectAgentHost, runAgentHost, sendAgentHostAuthorityControl } from "./runtime/agentHost.js";
78
+ import { unknownAgentRunConfiguration } from "./runtime/agentRunConfiguration.js";
75
79
  import { TaskWorkspaceCoordinator, WorkspaceCleanupBlockedError } from "./repository/taskWorkspaceCoordinator.js";
76
80
  import { FileTaskWorkspacePreparer } from "./repository/taskWorkspacePreparer.js";
77
81
  import { inspectStorageSchema } from "./storage/storageSchema.js";
@@ -84,15 +88,15 @@ import { NodeCommandExecutor } from "./tmux/commandExecutor.js";
84
88
  import { TmuxManager } from "./tmux/tmuxManager.js";
85
89
  import { WorkItemChangeSetManager } from "./workspace/workItemChangeSetManager.js";
86
90
  import { workspaceProjectEntry } from "./worktree/managedWorkspace.js";
87
- import { parseWebCommandOptions, startYuiWebServer } from "./web/webServer.js";
91
+ import { parseWebCommandOptions } from "./web/webServer.js";
88
92
  import { AgentConfigurationCatalogService, validateAgentLaunchConfiguration } from "./executor/agentConfigurationCatalog.js";
89
93
  import { resolveAgentProfileView } from "./profile/agentProfileRuntime.js";
90
- import { TmuxWebTerminalService } from "./web/tmuxWebTerminal.js";
91
94
  import { listOperatorSessions, operatorSessionRef } from "./operator/operatorSessionHistory.js";
92
95
  import { YUI_VERSION, yuiVersionIdentity } from "./version.js";
93
96
  import { SqliteSchemaMigrationError } from "./storage/sqliteSchema.js";
94
- import { assertRuntimeCoherence, } from "./runtime/runtimeCoherence.js";
95
- import { requireManagedTaskCaller } from "./runtime/managedCaller.js";
97
+ import { assertRuntimeCoherence } from "./runtime/runtimeCoherence.js";
98
+ import { requireManagedTaskCaller, resolveManagedTaskReader } from "./runtime/managedCaller.js";
99
+ import { operatorOfflineCommand, taskDiagnosticTarget } from "./cli/managedDiagnostics.js";
96
100
  import { readSessionBootstrapManifest, refreshManagedSessionCliWrappers } from "./context/sessionBootstrapManifest.js";
97
101
  import { createTaskFinalReviewContract, extractTaskFinalReviewRequest } from "./review/taskFinalReviewContract.js";
98
102
  import { resolveRecordedTaskFinalReviewContract } from "./review/taskFinalReviewContractResolution.js";
@@ -145,7 +149,7 @@ export async function main() {
145
149
  || routedForFence?.kind === "help"
146
150
  || routedForFence?.kind === "path-error"
147
151
  || routedForFence?.kind === "incomplete";
148
- if (managedInvocation || !homeFreeInvocation) {
152
+ if (!homeFreeInvocation) {
149
153
  assertCliHomeReleaseFence({
150
154
  home,
151
155
  packageRoot: fileURLToPath(new URL("../", import.meta.url)),
@@ -169,7 +173,6 @@ export async function main() {
169
173
  process.exitCode = delegated.status ?? 5;
170
174
  return;
171
175
  }
172
- const { contract: taskFinalReviewContract, verifiedStore } = await preflightManagedTaskControlPlane();
173
176
  if (args.length === 0) {
174
177
  emit(renderCommandHelp((await import("./cli/commandCatalog.js")).ROOT_COMMAND, VERSION));
175
178
  return;
@@ -191,6 +194,7 @@ export async function main() {
191
194
  }
192
195
  if (args[0] === "version")
193
196
  throw usageError("Version usage: yui version");
197
+ const { contract: taskFinalReviewContract, verifiedStore } = await preflightManagedTaskControlPlane();
194
198
  if (args[0] === "update") {
195
199
  if (jsonOutput)
196
200
  throw usageError("Update does not support --json.");
@@ -249,6 +253,15 @@ export async function main() {
249
253
  emit(renderCommandHelp(target, VERSION), false, describeCommandTree(target));
250
254
  return;
251
255
  }
256
+ if (args[0] === "capability") {
257
+ const result = await runCapabilityCommand(args.slice(1), home, process.env);
258
+ emit(JSON.stringify(result, null, 2), false, result);
259
+ const kind = result?.kind;
260
+ if (typeof result === "object" && result !== null && !Array.isArray(result)
261
+ && typeof kind === "string" && !["value", "operation"].includes(kind))
262
+ process.exitCode = 5;
263
+ return;
264
+ }
252
265
  if (args[0] === "setup") {
253
266
  if (jsonOutput)
254
267
  throw usageError("Setup does not support --json.");
@@ -318,11 +331,10 @@ export async function main() {
318
331
  + `${result.current} already current, ${result.skipped} skipped.`, false, result);
319
332
  return;
320
333
  }
321
- if (args[1] === "agent-host" && args.length === 4) {
334
+ if (args[1] === "agent-host" && args.length === 3) {
322
335
  process.exitCode = await runAgentHost({
323
336
  home,
324
- runtimeGenerationId: args[2],
325
- ticket: args[3]
337
+ ticket: args[2]
326
338
  });
327
339
  return;
328
340
  }
@@ -333,7 +345,7 @@ export async function main() {
333
345
  if (args[1] === "runtime-hook" && args.length === 2) {
334
346
  // Provider lifecycle Hooks are observation channels, never execution
335
347
  // gates. A late/stale Hook must not make Claude reject an otherwise
336
- // valid Session or Turn; its exact fence is revalidated before any
348
+ // valid Session or AgentRun; its exact fence is revalidated before any
337
349
  // inbox fact is written, so dropping an invalid observation is safe.
338
350
  try {
339
351
  await runRuntimeObservationHookCommand(readFileSync(0, "utf8"), process.env);
@@ -539,7 +551,8 @@ export async function main() {
539
551
  emit(result.output, false, result.data);
540
552
  return;
541
553
  }
542
- await assertFileTaskControllerStorageCompatible(home);
554
+ if (!operatorOfflineCommand(args))
555
+ await assertFileTaskControllerStorageCompatible(home);
543
556
  // Reuse the store the exact runtime preflight already opened and read for
544
557
  // this same Home. Opening a second store would parse the unchanged large
545
558
  // state a second time; the per-instance fingerprint cache still invalidates
@@ -576,46 +589,37 @@ export async function main() {
576
589
  });
577
590
  const workspaceCoordinator = new TaskWorkspaceCoordinator(store, workspacePreparer, runtime);
578
591
  if (resolved[0] === "web") {
592
+ if (managedInvocation || process.env.YUI_ROLE || process.env.YUI_NATIVE_SESSION_ID) {
593
+ throw usageError("The Web user ingress must be started from a local user terminal, not a managed Session.");
594
+ }
595
+ if (resolved.length === 2 && (resolved[1] === "--status" || resolved[1] === "--stop")) {
596
+ const status = await callController(home, "web.status", {});
597
+ if (resolved[1] === "--status")
598
+ emit(status ? `Yui web control room: ${status.url}\n` : "Web is not running.\n", false, status);
599
+ else {
600
+ if (status)
601
+ await callController(home, "web.stop", { id: status.id });
602
+ emit("Web listener stopped; Controller and Agents are unchanged.\n");
603
+ }
604
+ return;
605
+ }
579
606
  if (jsonOutput)
580
- throw usageError("Web does not support --json.");
607
+ throw usageError("Web start does not support --json; use --status.");
581
608
  const options = parseWebCommandOptions(resolved.slice(1));
582
- const terminal = new TmuxWebTerminalService({
583
- yuiHome: home,
584
- tmuxBin: resolveTmuxBin(store.getConfig().tmuxBin),
585
- tmux,
586
- prepareGlobalRole: (roleName) => runtime.prepareGlobalRoleEnter(roleName),
587
- environment: process.env,
588
- onError: (error) => {
589
- const message = error instanceof Error ? error.message : String(error);
590
- process.stderr.write(`Web terminal cleanup error: ${message}\n`);
591
- }
592
- });
593
- await startYuiWebServer(store, options, {
594
- terminal,
595
- answerInput: async ({ taskId, inputId, answer }) => {
596
- const command = [
597
- "input", "answer", inputId, "--task", taskId,
598
- ...("choiceKey" in answer
599
- ? ["--choice", answer.choiceKey]
600
- : ["--text", answer.text])
601
- ];
602
- const result = runTaskCommand(command, store, {
603
- runtime,
604
- environment: {},
605
- yuiHome: home
606
- });
607
- if (result.kind !== "output") {
608
- throw new Error("Input answer returned an invalid control result.");
609
- }
610
- const data = result.data;
611
- if (data?.request === undefined) {
612
- throw new Error("Input answer did not return the updated request.");
613
- }
614
- return data.request;
615
- }
616
- });
609
+ const id = randomUUID();
610
+ await callController(home, "web.start", { ...options, id });
617
611
  const displayHost = options.host === "::1" ? "[::1]" : options.host;
618
612
  process.stdout.write(`Yui web control room: http://${displayHost}:${options.port}\n`);
613
+ await new Promise((resolve) => {
614
+ const stop = () => {
615
+ process.off("SIGINT", stop);
616
+ process.off("SIGTERM", stop);
617
+ resolve();
618
+ };
619
+ process.once("SIGINT", stop);
620
+ process.once("SIGTERM", stop);
621
+ });
622
+ await callController(home, "web.stop", { id });
619
623
  return;
620
624
  }
621
625
  if (resolved[0] === "config") {
@@ -793,7 +797,7 @@ export async function main() {
793
797
  if (task === null)
794
798
  throw usageError(`Task not found: ${taskId}.`);
795
799
  // Reject managed Task callers before inspecting or starting runtime resources.
796
- if (taskActor(process.env, taskId) === "leader") {
800
+ if (taskLocalActor(store, process.env, taskId) === "leader") {
797
801
  throw usageError("Task execution stop/start requires the global Operator or a human user.");
798
802
  }
799
803
  if (task.executionGate.state === "stopped") {
@@ -835,7 +839,7 @@ export async function main() {
835
839
  },
836
840
  candidateForTask: async (taskId) => {
837
841
  const status = store.getTask(taskId)?.status;
838
- return status === "active" || status === "retired"
842
+ return status === "active" || status === "cancelled"
839
843
  ? snapshotActualTaskReviewCandidate(taskId, store, workspacePreparer)
840
844
  : null;
841
845
  },
@@ -901,7 +905,7 @@ export async function main() {
901
905
  throw usageError("Task work capture usage: yui task work capture <task>/<work>.");
902
906
  }
903
907
  const reference = cliWorkItemReference(workItemId, process.env);
904
- taskActor(process.env, reference.taskId);
908
+ assertTaskDeliveryAuthority(store, process.env, reference.taskId);
905
909
  const changeSets = await new WorkItemChangeSetManager(store).capture(reference.taskId, reference.localId, taskFinalReviewContract === undefined
906
910
  ? {}
907
911
  : { taskFinalReviewContract });
@@ -922,7 +926,7 @@ export async function main() {
922
926
  }
923
927
  const reference = cliWorkItemReference(workItemId, process.env);
924
928
  const qualified = `${reference.taskId}/${reference.localId}`;
925
- taskActor(process.env, reference.taskId);
929
+ assertTaskDeliveryAuthority(store, process.env, reference.taskId);
926
930
  if (disposition === "--runtime-only") {
927
931
  let runtimeCleanup;
928
932
  try {
@@ -1014,7 +1018,7 @@ export async function main() {
1014
1018
  .flatMap(({ owner }) => owner.type === "work-item" ? [owner.workItemId] : []);
1015
1019
  for (const workItemId of workItemIds) {
1016
1020
  const item = store.getWorkItem(task.id, workItemId);
1017
- if (item?.status !== "completed" || disposition !== "integrated")
1021
+ if (item?.status !== "accepted" || disposition !== "integrated")
1018
1022
  continue;
1019
1023
  try {
1020
1024
  await new WorkItemChangeSetManager(store).assertIntegrated(task.id, item.id);
@@ -1061,15 +1065,15 @@ export async function main() {
1061
1065
  if (item !== null && task !== null) {
1062
1066
  // Authority and pure Lane-shape checks precede every physical or
1063
1067
  // durable workspace preparation performed for dispatch.
1064
- taskActor(process.env, task.id);
1068
+ assertTaskDeliveryAuthority(store, process.env, task.id);
1065
1069
  if (item.assignee !== undefined) {
1066
1070
  workItemDispatchLanePlan(resolved, store, item);
1067
1071
  }
1068
1072
  }
1069
1073
  // A rejected Candidate starts a new execution iteration. Release every
1070
1074
  // terminal Lane Role runtime before preparing the new Lane workspaces;
1071
- // durable Turns, Groups, Candidates, and workspace owners remain intact.
1072
- if (item?.status === "failed"
1075
+ // durable AgentRuns, Groups, Candidates, and workspace owners remain intact.
1076
+ if (item?.status === "open"
1073
1077
  && currentWorkItemExecutionGroup(item)?.lanes.every(({ disposition }) => disposition !== "open")) {
1074
1078
  await workspaceCoordinator.cleanupWorkItemRuntime(item.taskId, item.id);
1075
1079
  }
@@ -1108,7 +1112,7 @@ export async function main() {
1108
1112
  try {
1109
1113
  const reference = cliWorkItemReference(workItemId, process.env);
1110
1114
  workItemIntegrationProof = await new WorkItemChangeSetManager(store)
1111
- .assertIntegrated(reference.taskId, reference.localId) ?? undefined;
1115
+ .assertIntegrated(reference.taskId, reference.localId, optionValue(resolved, "--candidate")) ?? undefined;
1112
1116
  }
1113
1117
  catch (error) {
1114
1118
  throw usageError(error instanceof Error ? error.message : String(error));
@@ -1194,6 +1198,11 @@ export async function main() {
1194
1198
  ? await actualTaskReviewCandidateForTaskCommand(resolved, store, workspacePreparer, process.env)
1195
1199
  : archiveTaskReviewCandidate;
1196
1200
  const deltaRecheckPreflight = await deltaRecheckPreflightForTaskCommand(resolved.slice(1), store, actualTaskReviewCandidate);
1201
+ // Read-only, and only for a Session inspect. The command itself stays
1202
+ // synchronous over persisted state; this is the live reading it prints
1203
+ // beside those facts, prepared here because the Host is reached over a
1204
+ // socket.
1205
+ const liveRunConfiguration = await liveRunConfigurationForTaskCommand(resolved, store, home);
1197
1206
  // Physical preparation may precede the durable write, but Task status,
1198
1207
  // workspace identity/cwd, and ManagedWorkspace ownership are adopted by
1199
1208
  // one transaction. A failed attempt therefore leaves the Task Draft and
@@ -1203,7 +1212,8 @@ export async function main() {
1203
1212
  const taskId = resolved[2];
1204
1213
  const task = taskId === undefined ? null : store.getTask(taskId);
1205
1214
  if (task !== null && task.status === "draft") {
1206
- taskWorkspaceActivation = await workspacePreparer.activateTaskWorkspace(task.id);
1215
+ taskLocalActor(store, process.env, task.id);
1216
+ taskWorkspaceActivation = await workspacePreparer.activateTaskWorkspace(task.id, process.env);
1207
1217
  }
1208
1218
  }
1209
1219
  const result = runTaskCommand(resolved.slice(1), store, {
@@ -1232,6 +1242,9 @@ export async function main() {
1232
1242
  ...(deltaRecheckPreflight === undefined
1233
1243
  ? {}
1234
1244
  : { deltaRecheckPreflight }),
1245
+ ...(liveRunConfiguration === undefined
1246
+ ? {}
1247
+ : { liveRunConfiguration }),
1235
1248
  ...(taskRetirementProof === undefined ? {} : { taskRetirementProof }),
1236
1249
  ...(validateAgentConfiguration === undefined
1237
1250
  ? {}
@@ -1253,13 +1266,13 @@ export async function main() {
1253
1266
  let reviewData;
1254
1267
  const resumesReviewDispatch = (resolved[1] === "review" && resolved[2] === "request")
1255
1268
  || (resolved[1] === "work" && resolved[2] === "review")
1256
- || (resolved[1] === "turn" && resolved[2] === "retry");
1269
+ || (resolved[1] === "run" && resolved[2] === "retry");
1257
1270
  const reviewDispatchNeeded = requestedRound?.status === "pending"
1258
1271
  || (requestedRound?.status === "running"
1259
1272
  && resumesReviewDispatch
1260
1273
  && persistedRequestedRound?.executionGroup?.lanes.some((lane) => (lane.disposition === "open"
1261
- && (lane.currentTurnId === undefined
1262
- || store.getTurn(requestedRound.taskId, lane.currentTurnId)?.status === "failed"))) === true);
1274
+ && (lane.currentRunId === undefined
1275
+ || store.getRun(requestedRound.taskId, lane.currentRunId)?.status === "failed"))) === true);
1263
1276
  if (reviewDispatchNeeded) {
1264
1277
  try {
1265
1278
  const workspace = requestedRound.status === "running"
@@ -1309,7 +1322,7 @@ export async function main() {
1309
1322
  kind: "started",
1310
1323
  reviewerRoleName: requestedRound.reviewerRoleName,
1311
1324
  reviewRoundId: requestedRound.id,
1312
- turnId: run.id
1325
+ runId: run.id
1313
1326
  },
1314
1327
  reviewRound: store.getReviewRound(requestedRound.taskId, requestedRound.id),
1315
1328
  ...(run === null ? {} : { reviewRun: run }),
@@ -1362,7 +1375,6 @@ export async function main() {
1362
1375
  agentId: result.agentId,
1363
1376
  adapterId: result.adapterId,
1364
1377
  nativeSessionId: result.nativeSessionId,
1365
- ...(result.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: result.runtimeGenerationId }),
1366
1378
  sessionUpdatedAt: result.sessionUpdatedAt
1367
1379
  });
1368
1380
  }
@@ -1436,7 +1448,7 @@ export async function main() {
1436
1448
  }
1437
1449
  finally {
1438
1450
  const currentTask = store.getTask(result.taskId);
1439
- // Completing or retiring the Task from inside the takeover Turn owns
1451
+ // Completing or retiring the Task from inside the takeover AgentRun owns
1440
1452
  // Provider shutdown and clears the live binding. Do not turn that
1441
1453
  // successful terminal transition into a failing best-effort release.
1442
1454
  if (currentTask?.status === "active") {
@@ -1520,21 +1532,38 @@ async function preflightManagedTaskControlPlane() {
1520
1532
  && ["agent-host", "session-notify", "runtime-hook"].includes(args[1] ?? "");
1521
1533
  const home = resolveYuiHome(process.env);
1522
1534
  const manifest = assertManagedSessionManifest(home, "task");
1535
+ const diagnosticTarget = taskDiagnosticTarget(args);
1536
+ const diagnostic = diagnosticTarget !== undefined
1537
+ && diagnosticTarget === process.env.YUI_TASK_ID;
1538
+ if (diagnosticTarget !== undefined && !diagnostic) {
1539
+ throw usageError("Diagnostics must remain within this Session's Task.");
1540
+ }
1523
1541
  // One gate for every managed command: the current CLI, Home, and Controller
1524
1542
  // must agree. Internal callbacks must still be able to append their immutable
1525
1543
  // fact while the Controller is offline.
1526
- await assertRuntimeCoherence({ actualHome: home }, { checkController: !internalCallback });
1544
+ await assertRuntimeCoherence({ actualHome: home }, { checkController: !internalCallback && !diagnostic });
1527
1545
  const verifiedStore = openCurrentTaskStore(home);
1528
1546
  // One authority for "may this process act as this Task Role?". Yui's own
1529
1547
  // internal callbacks run inside the Host process Yui itself launched; an Agent
1530
1548
  // command proves it is the Role's current runtime with its per-Session caller
1531
1549
  // key. Nothing here
1532
- // gates on the current Turn: which Turn is active is durable state that the
1550
+ // gates on the current AgentRun: which AgentRun is active is durable state that the
1533
1551
  // command needing it reads, never a fact frozen into a process environment.
1534
1552
  const runtime = internalCallback
1535
1553
  ? undefined
1536
- : requireManagedTaskCaller(verifiedStore, process.env);
1554
+ : diagnostic
1555
+ ? resolveManagedTaskReader(verifiedStore, process.env)
1556
+ : requireManagedTaskCaller(verifiedStore, process.env);
1557
+ if (diagnostic && runtime?.roleName !== "leader"
1558
+ && !(args[1] === "show"
1559
+ || (args[1] === "role" && args[2] === "session" && args[3] === "inspect"
1560
+ && args[5] === runtime?.roleName))) {
1561
+ // Non-Leaders keep their Assignment-scoped read authorization.
1562
+ requireManagedTaskCaller(verifiedStore, process.env);
1563
+ }
1537
1564
  const request = taskFinalReviewInvocation.request;
1565
+ if (request !== undefined && diagnostic)
1566
+ requireManagedTaskCaller(verifiedStore, process.env);
1538
1567
  if (request === undefined) {
1539
1568
  return { contract: undefined, verifiedStore };
1540
1569
  }
@@ -1569,7 +1598,14 @@ async function preflightManagedGlobalControlPlane() {
1569
1598
  || manifest.roleKind !== expectedRoleKind) {
1570
1599
  throw new Error("Managed global invocation does not match its Session Manifest.");
1571
1600
  }
1572
- await assertRuntimeCoherence({ actualHome: home });
1601
+ if (expectedRoleKind === "operator" && ["doctor", "upgrade", "update"].includes(args[0] ?? "")) {
1602
+ // These commands inspect/adopt the storage contract themselves. Requiring
1603
+ // current storage before reaching upgrade would make recovery impossible.
1604
+ return { contract: undefined, verifiedStore: undefined };
1605
+ }
1606
+ await assertRuntimeCoherence({ actualHome: home }, {
1607
+ checkController: !(expectedRoleKind === "operator" && operatorOfflineCommand(args))
1608
+ });
1573
1609
  return { contract: undefined, verifiedStore: openCurrentTaskStore(home) };
1574
1610
  }
1575
1611
  /**
@@ -1633,7 +1669,7 @@ function cliTaskRecordReference(value, kind, environment) {
1633
1669
  try {
1634
1670
  return resolveTaskRecordReference(value, {
1635
1671
  kind,
1636
- label: kind === "turn" ? "Turn reference" : "ReviewRound reference",
1672
+ label: kind === "run" ? "AgentRun reference" : "ReviewRound reference",
1637
1673
  ...(environment.YUI_TASK_ID === undefined
1638
1674
  ? {}
1639
1675
  : { contextTaskId: environment.YUI_TASK_ID })
@@ -1650,12 +1686,12 @@ function assertWorkItemExecutionDependenciesForCommand(args, store, environment)
1650
1686
  const reference = cliWorkItemReference(args[3], environment);
1651
1687
  item = store.getWorkItem(reference.taskId, reference.localId) ?? undefined;
1652
1688
  }
1653
- else if (args[0] === "task" && args[1] === "turn" && args[2] === "retry"
1689
+ else if (args[0] === "task" && args[1] === "run" && args[2] === "retry"
1654
1690
  && args[3] !== undefined) {
1655
- const reference = cliTaskRecordReference(args[3], "turn", environment);
1656
- const turn = store.getTurn(reference.taskId, reference.localId);
1657
- item = turn?.purpose === "execution" && turn.workItemId !== undefined
1658
- ? store.getWorkItem(turn.taskId, turn.workItemId) ?? undefined
1691
+ const reference = cliTaskRecordReference(args[3], "run", environment);
1692
+ const run = store.getRun(reference.taskId, reference.localId);
1693
+ item = run?.purpose === "execution" && run.workItemId !== undefined
1694
+ ? store.getWorkItem(run.taskId, run.workItemId) ?? undefined
1659
1695
  : undefined;
1660
1696
  }
1661
1697
  if (item === undefined)
@@ -1710,7 +1746,7 @@ async function prepareExecutionLaneWorkspacesForCommand(args, store, preparer, e
1710
1746
  if (store.getRole(item.taskId, roleName) === null) {
1711
1747
  throw usageError(`Task Role not found: ${item.taskId}/${roleName}.`);
1712
1748
  }
1713
- if (store.getActiveTurn(item.taskId, roleName) !== null) {
1749
+ if (store.getActiveRun(item.taskId, roleName) !== null) {
1714
1750
  throw usageError(`${item.taskId}/${roleName} already has an active turn.`);
1715
1751
  }
1716
1752
  }
@@ -1749,7 +1785,7 @@ function workItemDispatchLanePlan(args, store, item) {
1749
1785
  const roles = args.flatMap((value, index) => (value === "--lane-role" && args[index + 1] !== undefined
1750
1786
  ? [args[index + 1]]
1751
1787
  : []));
1752
- const groupId = `execution-group-${store.peekNextTurnId(item.taskId)}`;
1788
+ const groupId = `execution-group-${store.peekNextRunId(item.taskId)}`;
1753
1789
  return {
1754
1790
  groupId,
1755
1791
  ...planReplicatedWorkItemLanes(item.assignee, roles, groupId)
@@ -1845,11 +1881,11 @@ async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, en
1845
1881
  taskId = reference.taskId;
1846
1882
  }
1847
1883
  }
1848
- else if (args[1] === "turn"
1884
+ else if (args[1] === "run"
1849
1885
  && (args[2] === "retry" || args[2] === "settle")
1850
1886
  && args[3] !== undefined) {
1851
- const reference = cliTaskRecordReference(args[3], "turn", environment);
1852
- const run = store.getTurn(reference.taskId, reference.localId);
1887
+ const reference = cliTaskRecordReference(args[3], "run", environment);
1888
+ const run = store.getRun(reference.taskId, reference.localId);
1853
1889
  const round = run?.reviewRoundId === undefined
1854
1890
  ? null
1855
1891
  : store.getReviewRound(reference.taskId, run.reviewRoundId);
@@ -1865,7 +1901,6 @@ async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, en
1865
1901
  taskId = store.getTask(args[2])?.id;
1866
1902
  }
1867
1903
  else if ((args[1] === "show"
1868
- || args[1] === "context"
1869
1904
  || args[1] === "next-action"
1870
1905
  || args[1] === "remote-delivery")
1871
1906
  && args[2] !== undefined) {
@@ -1873,10 +1908,10 @@ async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, en
1873
1908
  decisionSupportRead = true;
1874
1909
  }
1875
1910
  const status = taskId === undefined ? undefined : store.getTask(taskId)?.status;
1876
- if (taskId === undefined || (status !== "active" && status !== "retired"))
1911
+ if (taskId === undefined || (status !== "active" && status !== "cancelled"))
1877
1912
  return undefined;
1878
1913
  try {
1879
- return await snapshotActualTaskReviewCandidate(taskId, store, preparer);
1914
+ return await snapshotActualTaskReviewCandidate(taskId, store, preparer, !decisionSupportRead);
1880
1915
  }
1881
1916
  catch (error) {
1882
1917
  if (decisionSupportRead && error instanceof CliError)
@@ -1884,16 +1919,18 @@ async function actualTaskReviewCandidateForTaskCommand(args, store, preparer, en
1884
1919
  throw error;
1885
1920
  }
1886
1921
  }
1887
- async function snapshotActualTaskReviewCandidate(taskId, store, preparer) {
1922
+ async function snapshotActualTaskReviewCandidate(taskId, store, preparer, prepareWorkspace = true) {
1888
1923
  const task = store.getTask(taskId);
1889
1924
  if (task === null)
1890
1925
  throw usageError(`Task not found: ${taskId}.`);
1891
1926
  if (task.projectBindings.length === 0) {
1892
1927
  throw usageError(`Final Task Review requires a Project-backed Task: ${task.id}.`);
1893
1928
  }
1894
- // Reconcile the durable currentCommit facts from the authoritative Task
1895
- // clones before freezing a completion/review candidate.
1896
- await preparer.prepareTaskWorkspace(task.id);
1929
+ // Mutation preflights reconcile before freezing a candidate. A decision-
1930
+ // support read only observes existing heads; it must not migrate Sessions,
1931
+ // create worktrees or acquire workspace ownership as a side effect.
1932
+ if (prepareWorkspace)
1933
+ await preparer.prepareTaskWorkspace(task.id);
1897
1934
  const workspace = store.getTaskWorkspace(task.id);
1898
1935
  if (workspace === null
1899
1936
  || workspace.owner.type !== "task"
@@ -2065,13 +2102,6 @@ async function executeOperatorSessionControl(control, home, store, runtime, tmux
2065
2102
  await runtime.prepareGlobalRoleEnter(role.name);
2066
2103
  tmux.attachRole("operator", role.name, "auto");
2067
2104
  }
2068
- function adapterLabel(adapterId) {
2069
- return adapterId === "codex"
2070
- ? "Codex"
2071
- : adapterId === "claude"
2072
- ? "Claude"
2073
- : adapterId;
2074
- }
2075
2105
  function renderControllerResult(method, value) {
2076
2106
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
2077
2107
  return JSON.stringify(value);
@@ -2254,6 +2284,65 @@ async function warmLegacyRoleConfigurationMutation(commandArgs, store, catalogs)
2254
2284
  cwd: store.getConfig().defaultWorkspace ?? process.cwd()
2255
2285
  });
2256
2286
  }
2287
+ /**
2288
+ * Ask the live Agent Host what the Session is running under, for a Session
2289
+ * inspect.
2290
+ *
2291
+ * Only for `task role session inspect`. Every other command reads persisted
2292
+ * state and must keep doing so: a query that reached into a running Session
2293
+ * would make reading a Task's records depend on whether an Agent happened to be
2294
+ * up.
2295
+ *
2296
+ * The request is the Host's existing `status` control, which reads state the
2297
+ * Host already holds. It creates no Session, sends no prompt and changes nothing
2298
+ * — which is what lets a read-only inspect use it at all.
2299
+ *
2300
+ * Every failure resolves to `unknown` with the reason rather than propagating:
2301
+ * no Host is running for most Sessions ever inspected, and the persisted facts
2302
+ * the command prints are worth showing regardless of whether a live one answered.
2303
+ */
2304
+ async function liveRunConfigurationForTaskCommand(args, store, home) {
2305
+ if (args[0] !== "task" || args[1] !== "role" || args[2] !== "session"
2306
+ || args[3] !== "inspect" || args.length !== 6) {
2307
+ return undefined;
2308
+ }
2309
+ const taskId = args[4];
2310
+ const roleName = args[5];
2311
+ if (taskId === undefined || roleName === undefined)
2312
+ return undefined;
2313
+ // A Session must be recorded as active before asking. Probing a socket for a
2314
+ // Role that never ran would report a reach failure as if it were a fact about
2315
+ // that Role's Agent.
2316
+ const sessions = store.getTaskRoleSessionSet(taskId, roleName);
2317
+ const active = sessions === null
2318
+ ? undefined
2319
+ : sessions.sessions[sessions.activeAgentId];
2320
+ if (active === undefined)
2321
+ return undefined;
2322
+ if (active.status !== "active") {
2323
+ return unknownAgentRunConfiguration(`This Session is ${active.status}, so there is no live Agent to report what it `
2324
+ + "is running under.");
2325
+ }
2326
+ try {
2327
+ const snapshot = await inspectAgentHost({
2328
+ home,
2329
+ scope: "task",
2330
+ taskId,
2331
+ roleName
2332
+ });
2333
+ if (snapshot.nativeSessionId !== active.nativeSessionId
2334
+ || snapshot.adapterId !== active.adapterId
2335
+ || snapshot.state === "exited" || snapshot.state === "failed") {
2336
+ return unknownAgentRunConfiguration("The Agent Host has no live connection matching the recorded Session.");
2337
+ }
2338
+ return snapshot.runConfiguration ?? unknownAgentRunConfiguration("The Agent Host is running but has no Provider Session open, so no Agent "
2339
+ + "has reported a configuration yet.");
2340
+ }
2341
+ catch (error) {
2342
+ return unknownAgentRunConfiguration("The Agent Host for this Session could not be reached, so its live "
2343
+ + `configuration is unavailable: ${error instanceof Error ? error.message : String(error)}`);
2344
+ }
2345
+ }
2257
2346
  function hasModelOrEffortMutation(args) {
2258
2347
  const operation = (args[0] === "config" && args[1] === "role")
2259
2348
  || (args[0] === "task" && args[1] === "role");
@@ -2326,7 +2415,7 @@ function selectionCall(store, catalogs, method, params) {
2326
2415
  : store.listInputRequests(taskId);
2327
2416
  return params.all === true ? requests : requests.filter((request) => request.status === "open");
2328
2417
  }
2329
- case "task.turn.list": return callOptional(reader, "listTurns", [params.taskId]);
2418
+ case "task.turn.list": return callOptional(reader, "listRuns", [params.taskId]);
2330
2419
  case "task.decision.list": return callOptional(reader, "listDecisions", [params.taskId]);
2331
2420
  case "task.milestone.list": return presentSelectionTimes(callOptional(reader, "listMilestones", [params.taskId]), store);
2332
2421
  case "task.event.list": return presentSelectionTimes(callOptional(reader, "listEvents", [params.taskId]), store);
@@ -2424,6 +2513,10 @@ export function cliIdentity(env) {
2424
2513
  }
2425
2514
  function normalizeAliases(input) {
2426
2515
  const normalized = [...input];
2516
+ // Existing immutable Session Manifests (through 0.15.8) name this entry.
2517
+ // Remove once those Sessions are retired; both names share one handler.
2518
+ if (normalized[0] === "task" && normalized[1] === "turn")
2519
+ normalized[1] = "run";
2427
2520
  if (normalized.length === 1 && (normalized[0] === "-v" || normalized[0] === "--version")) {
2428
2521
  return ["version"];
2429
2522
  }