@zq-silk/yui 0.15.7 → 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 (281) 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 +157 -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 +178 -95
  25. package/dist/commands/agentCommands.js +72 -14
  26. package/dist/commands/capabilityCommands.js +9 -6
  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 +1188 -710
  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 +17 -6
  64. package/dist/controller/clientRuntime.js +65 -92
  65. package/dist/controller/controller.js +114 -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 +529 -479
  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 +247 -12
  106. package/dist/kernel/capabilityRegistry.js +64 -18
  107. package/dist/kernel/instanceHost.js +12 -1
  108. package/dist/kernel/kernelPorts.js +2 -2
  109. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  110. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  111. package/dist/message/message.js +62 -6
  112. package/dist/message/messageContinuation.js +204 -0
  113. package/dist/observability/executionAudit.js +70 -72
  114. package/dist/observability/faultClassification.js +2 -2
  115. package/dist/observability/orchestrationMetrics.js +8 -8
  116. package/dist/operator/operatorSessionHistory.js +1 -7
  117. package/dist/output/agentConfigurationPresentation.js +8 -3
  118. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  119. package/dist/output/rolePresentation.js +54 -3
  120. package/dist/plugins/pluginChild.js +104 -0
  121. package/dist/plugins/pluginIntent.js +26 -0
  122. package/dist/plugins/pluginInterpreter.js +43 -0
  123. package/dist/plugins/pluginPackage.js +101 -0
  124. package/dist/plugins/pluginProcess.js +112 -0
  125. package/dist/plugins/pluginService.js +380 -0
  126. package/dist/profile/agentProfile.js +1 -1
  127. package/dist/repository/gitWorkspace.js +26 -4
  128. package/dist/repository/project.js +19 -4
  129. package/dist/repository/taskBaseFreshness.js +13 -13
  130. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  131. package/dist/repository/taskWorkspacePreparer.js +344 -83
  132. package/dist/resources/autoResourceGc.js +3 -3
  133. package/dist/resources/liveReferences.js +3 -3
  134. package/dist/resources/projectResource.js +123 -0
  135. package/dist/resources/projectResourceService.js +421 -0
  136. package/dist/resources/resourceDiscovery.js +6 -6
  137. package/dist/resources/resourceGc.js +1 -1
  138. package/dist/resources/resourceRegistrar.js +1 -1
  139. package/dist/resources/resourceTypes.js +1 -1
  140. package/dist/review/deltaRecheck.js +3 -3
  141. package/dist/review/reviewAcceptance.js +16 -16
  142. package/dist/review/reviewDecision.js +7 -7
  143. package/dist/review/reviewRound.js +21 -20
  144. package/dist/review/reviewerAvailability.js +2 -2
  145. package/dist/role/role.js +51 -7
  146. package/dist/role/taskRoleUpdate.js +30 -0
  147. package/dist/runtime/acpProtocol.js +425 -0
  148. package/dist/runtime/acpSession.js +731 -0
  149. package/dist/runtime/acpSessionConfiguration.js +260 -0
  150. package/dist/runtime/agentDriver.js +30 -11
  151. package/dist/runtime/agentEndpoint.js +278 -0
  152. package/dist/runtime/agentEndpointIdentity.js +86 -0
  153. package/dist/runtime/agentEndpointOwnership.js +239 -0
  154. package/dist/runtime/agentError.js +2 -10
  155. package/dist/runtime/agentHost.js +565 -314
  156. package/dist/runtime/agentRunConfiguration.js +258 -0
  157. package/dist/runtime/builtinAgentDrivers.js +134 -18
  158. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  159. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  160. package/dist/runtime/claude-process-owner +0 -0
  161. package/dist/runtime/codexAppServerRuntime.js +38 -30
  162. package/dist/runtime/codexInteractiveHost.js +41 -6
  163. package/dist/runtime/continuationManager.js +2 -6
  164. package/dist/runtime/executionEnvironment.js +30 -0
  165. package/dist/runtime/firstProgressAdvisory.js +11 -11
  166. package/dist/runtime/index.js +4 -3
  167. package/dist/runtime/jsonLineChannel.js +109 -0
  168. package/dist/runtime/launchBroker.js +91 -16
  169. package/dist/runtime/launchDiagnostics.js +2 -2
  170. package/dist/runtime/lifecycleReservation.js +10 -18
  171. package/dist/runtime/managedCaller.js +61 -17
  172. package/dist/runtime/nativeSessionControl.js +102 -0
  173. package/dist/runtime/ports.js +6 -21
  174. package/dist/runtime/processExitObservation.js +8 -7
  175. package/dist/runtime/promptEnvelope.js +17 -6
  176. package/dist/runtime/providerContinuation.js +3 -9
  177. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  178. package/dist/runtime/providerControl.js +2 -7
  179. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  180. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  181. package/dist/runtime/runtimeBinding.js +0 -1
  182. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  183. package/dist/runtime/runtimeDeadlines.js +9 -0
  184. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  185. package/dist/runtime/runtimeObservation.js +29 -65
  186. package/dist/runtime/runtimeProjection.js +43 -51
  187. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  188. package/dist/runtime/sessionLaunchRequest.js +3 -7
  189. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  190. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  191. package/dist/runtime/sessionReconciliation.js +4 -8
  192. package/dist/runtime/sessionTerminationGuard.js +70 -259
  193. package/dist/runtime/sessionTokenMetrics.js +5 -16
  194. package/dist/runtime/structuredProviderHost.js +237 -117
  195. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  196. package/dist/runtime/tmuxAdapters.js +39 -86
  197. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  198. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  199. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  200. package/dist/scheduler/ports.js +80 -9
  201. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  202. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  203. package/dist/scheduler/taskExecutionProjection.js +120 -124
  204. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  205. package/dist/scheduler/taskWake.js +11 -4
  206. package/dist/scheduler/wakeReason.js +9 -1
  207. package/dist/setup/setupCommand.js +1 -0
  208. package/dist/storage/migrations/agentRunContract.js +159 -0
  209. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  210. package/dist/storage/sqliteSchema.js +431 -5
  211. package/dist/storage/sqliteStore.js +375 -220
  212. package/dist/storage/storageVersions.js +1 -1
  213. package/dist/storage/storeRpc.js +10 -5
  214. package/dist/storage/taskStore.js +13 -11
  215. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  216. package/dist/surface/surfaceContributions.js +102 -0
  217. package/dist/task/completionReadiness.js +32 -6
  218. package/dist/task/deliveryGuard.js +16 -16
  219. package/dist/task/draftPlan.js +72 -12
  220. package/dist/task/nextAction.js +144 -128
  221. package/dist/task/remoteDelivery.js +6 -6
  222. package/dist/task/task.js +184 -18
  223. package/dist/task/taskActivation.js +301 -0
  224. package/dist/task/taskActivationService.js +392 -0
  225. package/dist/task/taskRecordReference.js +5 -4
  226. package/dist/task/taskRecordRetirement.js +1 -1
  227. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  228. package/dist/telemetry/telemetryConfig.js +14 -14
  229. package/dist/telemetry/telemetryWiring.js +2 -2
  230. package/dist/web/assets/assetManifest.js +2 -0
  231. package/dist/web/assets/client/app.js +120 -20
  232. package/dist/web/assets/client/components.js +87 -54
  233. package/dist/web/assets/client/i18n.js +83 -41
  234. package/dist/web/assets/client/markdown.js +1 -1
  235. package/dist/web/assets/client/taskSurface.js +353 -0
  236. package/dist/web/assets/client/view.js +49 -44
  237. package/dist/web/assets/shell.js +1 -1
  238. package/dist/web/assets/styles/cards.js +22 -4
  239. package/dist/web/controllerWeb.js +60 -0
  240. package/dist/web/webMutation.js +28 -0
  241. package/dist/web/webServer.js +118 -8
  242. package/dist/web/webSnapshot.js +81 -74
  243. package/dist/web/webTaskSurface.js +64 -0
  244. package/dist/workItem/dependencyGate.js +1 -1
  245. package/dist/workItem/workItem.js +80 -48
  246. package/dist/workspace/workItemChangeSetManager.js +16 -9
  247. package/docs/agent-result-consumption.md +94 -0
  248. package/docs/agent-runtime-drivers.md +91 -0
  249. package/docs/architecture/README.md +38 -0
  250. package/docs/architecture/capabilities-and-resources.md +79 -0
  251. package/docs/managed-turn-and-session-runtime.md +222 -0
  252. package/docs/observability/README.md +81 -0
  253. package/docs/plugin-sdk.md +290 -0
  254. package/docs/provider-runtime.md +163 -0
  255. package/docs/release-workflow.md +303 -0
  256. package/docs/roles-and-configuration.md +113 -0
  257. package/docs/sqlite-control-plane-design.md +76 -0
  258. package/docs/task-dag-semantics.md +57 -0
  259. package/docs/task-delivery.md +103 -0
  260. package/docs/task-local-identity.md +6 -6
  261. package/docs/testing/verification-levels.md +86 -0
  262. package/i18n/README.zh-CN.md +98 -739
  263. package/package.json +2 -2
  264. package/skills/yui-leader/SKILL.md +130 -103
  265. package/skills/yui-leader/references/integration.md +39 -0
  266. package/skills/yui-leader/references/replicated-execution.md +42 -0
  267. package/skills/yui-leader/references/task-plugins.md +33 -0
  268. package/skills/yui-operator/SKILL.md +30 -59
  269. package/skills/yui-reviewer/SKILL.md +35 -36
  270. package/skills/yui-runtime/SKILL.md +88 -24
  271. package/skills/yui-runtime/references/publication.md +22 -0
  272. package/skills/yui-runtime/references/recovery.md +64 -0
  273. package/skills/yui-worker/SKILL.md +37 -39
  274. package/dist/cli/roleOptionCatalog.js +0 -68
  275. package/dist/context/sourceTurnContext.js +0 -30
  276. package/dist/execution/reviewMainTurn.js +0 -161
  277. package/dist/execution/workItemMainTurn.js +0 -164
  278. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  279. package/dist/runtime/preallocatedNativeSession.js +0 -13
  280. package/dist/runtime/runtimeStopReceipt.js +0 -42
  281. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomBytes } from "node:crypto";
2
- import { lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmdirSync, rmSync, writeFileSync } from "node:fs";
2
+ import { lstatSync, mkdirSync, readFileSync, renameSync, rmdirSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
4
4
  import { validateManagedWorkspace } from "../worktree/managedWorkspace.js";
5
5
  import { ResourceRegistrar } from "../resources/resourceRegistrar.js";
@@ -8,7 +8,7 @@ export const YUI_TASK_RUNTIME_SERVICE_NAMESPACE = "YUI_TASK_RUNTIME_SERVICE_NAME
8
8
  const MARKER_FILE = ".yui-task-runtime-owner.json";
9
9
  /**
10
10
  * One project-neutral implementation owns descriptor construction, preflight,
11
- * exact generation activation, and exact generation cleanup. It never scans by
11
+ * exact runtime activation, and exact runtime cleanup. It never scans by
12
12
  * process name, Role, PID, age, or an ambient Home.
13
13
  */
14
14
  export class FileTaskRuntimeIsolation {
@@ -40,7 +40,7 @@ export class FileTaskRuntimeIsolation {
40
40
  pathLayout: this.#pathLayout,
41
41
  controlPlane: this.#controlPlane,
42
42
  resources: [
43
- ...inspectGenerationRoot(descriptor, fingerprint),
43
+ ...inspectRuntimeRoot(descriptor, fingerprint),
44
44
  ...(this.#inspectResources?.(descriptor) ?? [])
45
45
  ],
46
46
  allowExactActive: input.allowExactActive === true
@@ -53,13 +53,13 @@ export class FileTaskRuntimeIsolation {
53
53
  }
54
54
  activate(preparation) {
55
55
  const { descriptor, fingerprint } = validatePreparation(preparation);
56
- const root = descriptor.roots.generation;
57
- const existing = inspectGenerationRoot(descriptor, fingerprint);
56
+ const root = descriptor.roots.runtime;
57
+ const existing = inspectRuntimeRoot(descriptor, fingerprint);
58
58
  if (existing.length > 0) {
59
59
  const [resource] = existing;
60
60
  if (resource?.ownership !== "owned"
61
61
  || resource.descriptorFingerprint !== fingerprint) {
62
- throw new Error(`Task runtime generation is not exactly owned: ${root}.`);
62
+ throw new Error(`Task runtime workspace is not exactly owned: ${root}.`);
63
63
  }
64
64
  ensureOwnedDirectories(descriptor);
65
65
  this.#resourceRegistrar().registerTaskRuntimeIsolation(descriptor);
@@ -82,7 +82,7 @@ export class FileTaskRuntimeIsolation {
82
82
  this.#resourceRegistrar().registerTaskRuntimeIsolation(descriptor);
83
83
  }
84
84
  catch (error) {
85
- const current = inspectGenerationRoot(descriptor, fingerprint);
85
+ const current = inspectRuntimeRoot(descriptor, fingerprint);
86
86
  if (current[0]?.ownership === "owned")
87
87
  throw error;
88
88
  // The directory was created by this exact activation but never acquired
@@ -96,21 +96,21 @@ export class FileTaskRuntimeIsolation {
96
96
  requireCleanupReason(reason);
97
97
  const { descriptor, fingerprint } = validatePreparation(preparation);
98
98
  const resources = [
99
- ...inspectGenerationRoot(descriptor, fingerprint),
99
+ ...inspectRuntimeRoot(descriptor, fingerprint),
100
100
  ...(this.#inspectResources?.(descriptor) ?? [])
101
101
  ];
102
102
  if (resources.length === 0)
103
103
  return;
104
104
  planTaskRuntimeCleanup(descriptor, reason, resources);
105
105
  // Re-read the sole durable marker immediately before deletion. A missing,
106
- // replaced, symlinked, or mismatched generation is never cleanup authority.
107
- const current = inspectGenerationRoot(descriptor, fingerprint);
106
+ // replaced, symlinked, or mismatched runtime is never cleanup authority.
107
+ const current = inspectRuntimeRoot(descriptor, fingerprint);
108
108
  if (current.length !== 1
109
109
  || current[0]?.ownership !== "owned"
110
110
  || current[0].descriptorFingerprint !== fingerprint) {
111
111
  throw new Error("Task runtime resources changed since cleanup preflight.");
112
112
  }
113
- const root = descriptor.roots.generation;
113
+ const root = descriptor.roots.runtime;
114
114
  const claimed = `${root}.cleanup-${randomBytes(16).toString("hex")}`;
115
115
  renameSync(root, claimed);
116
116
  try {
@@ -121,7 +121,7 @@ export class FileTaskRuntimeIsolation {
121
121
  }
122
122
  rmSync(claimed, { recursive: true });
123
123
  this.#resourceRegistrar().markPathsDeleted([
124
- descriptor.roots.generation,
124
+ descriptor.roots.runtime,
125
125
  descriptor.roots.data,
126
126
  descriptor.roots.cache,
127
127
  descriptor.roots.temporary
@@ -129,7 +129,7 @@ export class FileTaskRuntimeIsolation {
129
129
  }
130
130
  catch (error) {
131
131
  // Preserve a claimed-but-unverified resource. Restore its exact path only
132
- // when no concurrent generation has appeared there; never delete it.
132
+ // when no concurrent runtime has appeared there; never delete it.
133
133
  try {
134
134
  renameSync(claimed, root);
135
135
  }
@@ -139,84 +139,14 @@ export class FileTaskRuntimeIsolation {
139
139
  throw error;
140
140
  }
141
141
  }
142
- cleanupTaskLaunch(input) {
143
- const taskId = requireIdentity(input.taskId, "Task id");
144
- const runtimeGenerationId = requireIdentity(input.runtimeGenerationId, "Runtime generation id");
145
- requireCleanupReason(input.reason);
146
- const taskRoot = taskRuntimeInventoryRoot(this.#runtimeRoot, taskId, this.#pathLayout);
147
- let entries;
148
- try {
149
- const metadata = lstatSync(taskRoot);
150
- if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
151
- throw new Error("Task runtime Task root is ambiguous.");
152
- }
153
- entries = readdirSync(taskRoot, { withFileTypes: true });
154
- }
155
- catch (error) {
156
- if (isNodeCode(error, "ENOENT"))
157
- return "absent";
158
- throw error;
159
- }
160
- const launchDigest = taskRuntimeLaunchDigest(taskId, runtimeGenerationId, this.#pathLayout);
161
- const matches = [];
162
- for (const entry of entries) {
163
- if (!entry.isDirectory() || entry.isSymbolicLink()) {
164
- throw new Error("Task runtime owner inventory is ambiguous.");
165
- }
166
- const generationRoot = join(taskRoot, entry.name, launchDigest);
167
- let metadata;
168
- try {
169
- metadata = lstatSync(generationRoot);
170
- }
171
- catch (error) {
172
- if (isNodeCode(error, "ENOENT"))
173
- continue;
174
- throw new Error("Task runtime generation inventory is ambiguous.", { cause: error });
175
- }
176
- if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
177
- throw new Error("Task runtime generation inventory is ambiguous.");
178
- }
179
- let marker;
180
- try {
181
- marker = parseMarker(readFileSync(join(generationRoot, MARKER_FILE), "utf8"));
182
- }
183
- catch (error) {
184
- throw new Error("Task runtime generation is unmarked or invalid.", {
185
- cause: error
186
- });
187
- }
188
- const descriptor = marker.descriptor;
189
- const fingerprint = taskRuntimeIsolationFingerprint(descriptor);
190
- if (marker.fingerprint !== fingerprint
191
- || descriptor.taskId !== taskId
192
- || descriptor.generation.runtimeGenerationId !== runtimeGenerationId
193
- || descriptor.roots.generation !== generationRoot) {
194
- throw new Error("Task runtime generation ownership is mismatched.");
195
- }
196
- matches.push({
197
- descriptor,
198
- fingerprint,
199
- environment: taskRuntimeIsolationEnvironment(descriptor)
200
- });
201
- }
202
- if (matches.length === 0)
203
- return "absent";
204
- if (matches.length !== 1) {
205
- throw new Error("Task runtime generation ownership is ambiguous.");
206
- }
207
- this.cleanup(matches[0], input.reason);
208
- return "cleaned";
209
- }
210
142
  }
211
143
  export function createTaskRuntimeIsolationDescriptor(input) {
212
144
  const workspace = validateManagedWorkspace(input.workspace);
213
145
  const owner = taskRuntimeWorkspaceOwner(workspace.owner);
214
146
  const taskId = requireIdentity(owner.taskId, "Task id");
215
- const runtimeGenerationId = requireIdentity(input.runtimeGenerationId, "Runtime generation id");
216
- const generationId = requireIdentity(input.generationId, "Generation id");
217
147
  const runtimeRoot = canonicalPath(input.runtimeRoot, "Task runtime root");
218
148
  const pathLayout = taskRuntimePathLayout(input.pathLayout);
219
- const generation = taskRuntimeGenerationRoot(runtimeRoot, taskId, owner, runtimeGenerationId, pathLayout);
149
+ const runtime = taskRuntimeWorkspaceRoot(runtimeRoot, taskId, owner, pathLayout);
220
150
  const declared = capabilities(input.policy?.declaredExternalCapabilities ?? [], "Declared external capability");
221
151
  const requested = capabilities(input.policy?.requestedExternalCapabilities ?? [], "Requested external capability");
222
152
  const portPreference = ports(input.policy?.portPreference ?? [], "Port preference");
@@ -227,19 +157,15 @@ export function createTaskRuntimeIsolationDescriptor(input) {
227
157
  taskId,
228
158
  workspace: Object.freeze({ owner, root: canonicalPath(workspace.root, "Workspace root") }),
229
159
  roots: Object.freeze({
230
- generation,
231
- data: join(generation, "data"),
232
- cache: join(generation, "cache"),
233
- temporary: join(generation, "tmp")
160
+ runtime,
161
+ data: join(runtime, "data"),
162
+ cache: join(runtime, "cache"),
163
+ temporary: join(runtime, "tmp")
234
164
  }),
235
- serviceNamespace: taskRuntimeServiceNamespace(taskId, owner, runtimeGenerationId, generationId),
165
+ serviceNamespace: taskRuntimeServiceNamespace(taskId, owner, runtime),
236
166
  portPreference,
237
167
  portAllocations,
238
168
  externalCapabilities: Object.freeze({ declared, requested }),
239
- generation: Object.freeze({
240
- runtimeGenerationId,
241
- generationId
242
- })
243
169
  });
244
170
  }
245
171
  export function parseTaskRuntimeIsolationDescriptor(serialized) {
@@ -258,7 +184,6 @@ export function parseTaskRuntimeIsolationDescriptor(serialized) {
258
184
  }
259
185
  const workspace = requireRecord(value.workspace, "Task runtime workspace");
260
186
  const roots = requireRecord(value.roots, "Task runtime roots");
261
- const generation = requireRecord(value.generation, "Task runtime generation");
262
187
  const external = requireRecord(value.externalCapabilities, "Task runtime external capabilities");
263
188
  const owner = taskRuntimeWorkspaceOwner(requireRecord(workspace.owner, "Task runtime workspace owner"));
264
189
  const descriptor = {
@@ -270,7 +195,7 @@ export function parseTaskRuntimeIsolationDescriptor(serialized) {
270
195
  root: canonicalPath(workspace.root, "Workspace root")
271
196
  },
272
197
  roots: {
273
- generation: canonicalPath(roots.generation, "Task runtime generation root"),
198
+ runtime: canonicalPath(roots.runtime, "Task runtime workspace root"),
274
199
  data: canonicalPath(roots.data, "Task runtime data root"),
275
200
  cache: canonicalPath(roots.cache, "Task runtime cache root"),
276
201
  temporary: canonicalPath(roots.temporary, "Task runtime temporary root")
@@ -282,10 +207,6 @@ export function parseTaskRuntimeIsolationDescriptor(serialized) {
282
207
  declared: capabilities(external.declared, "Declared external capability"),
283
208
  requested: capabilities(external.requested, "Requested external capability")
284
209
  },
285
- generation: {
286
- runtimeGenerationId: requireIdentity(generation.runtimeGenerationId, "Runtime generation id"),
287
- generationId: requireIdentity(generation.generationId, "Generation id")
288
- }
289
210
  };
290
211
  return Object.freeze(descriptor);
291
212
  }
@@ -315,22 +236,22 @@ export function assertTaskRuntimeIsolationPreflight(input) {
315
236
  }
316
237
  const runtimeRoot = canonicalPath(input.runtimeRoot, "Task runtime root");
317
238
  const pathLayout = taskRuntimePathLayout(input.pathLayout);
318
- const expectedGeneration = taskRuntimeGenerationRoot(runtimeRoot, descriptor.taskId, expectedOwner, descriptor.generation.runtimeGenerationId, pathLayout);
319
- if (descriptor.roots.generation !== expectedGeneration
320
- || descriptor.roots.data !== join(expectedGeneration, "data")
321
- || descriptor.roots.cache !== join(expectedGeneration, "cache")
322
- || descriptor.roots.temporary !== join(expectedGeneration, "tmp")) {
323
- throw new Error("Task runtime roots do not match the exact Task, owner, and runtime generation identity.");
239
+ const expectedRuntimeRoot = taskRuntimeWorkspaceRoot(runtimeRoot, descriptor.taskId, expectedOwner, pathLayout);
240
+ if (descriptor.roots.runtime !== expectedRuntimeRoot
241
+ || descriptor.roots.data !== join(expectedRuntimeRoot, "data")
242
+ || descriptor.roots.cache !== join(expectedRuntimeRoot, "cache")
243
+ || descriptor.roots.temporary !== join(expectedRuntimeRoot, "tmp")) {
244
+ throw new Error("Task runtime roots do not match the exact Task, owner, and runtime workspace identity.");
324
245
  }
325
- if (descriptor.serviceNamespace !== taskRuntimeServiceNamespace(descriptor.taskId, expectedOwner, descriptor.generation.runtimeGenerationId, descriptor.generation.generationId)) {
326
- throw new Error("Task runtime service namespace does not match its exact Task runtime generation.");
246
+ if (descriptor.serviceNamespace !== taskRuntimeServiceNamespace(descriptor.taskId, expectedOwner, descriptor.roots.runtime)) {
247
+ throw new Error("Task runtime service namespace does not match its exact Task runtime workspace.");
327
248
  }
328
- if (!isWithin(runtimeRoot, descriptor.roots.generation)) {
329
- throw new Error("Task runtime generation is outside its runtime root.");
249
+ if (!isWithin(runtimeRoot, descriptor.roots.runtime)) {
250
+ throw new Error("Task runtime workspace is outside its runtime root.");
330
251
  }
331
252
  for (const [name, root] of Object.entries(descriptor.roots)) {
332
- if (name !== "generation" && !isWithin(descriptor.roots.generation, root)) {
333
- throw new Error(`Task runtime ${name} root is outside its exact generation.`);
253
+ if (name !== "runtime" && !isWithin(descriptor.roots.runtime, root)) {
254
+ throw new Error(`Task runtime ${name} root is outside its exact runtime.`);
334
255
  }
335
256
  }
336
257
  const control = normalizeControlBoundary(input.controlPlane);
@@ -394,8 +315,8 @@ export function planTaskRuntimeCleanup(descriptor, reason, resources) {
394
315
  }
395
316
  return Object.freeze([...ids].sort());
396
317
  }
397
- function inspectGenerationRoot(descriptor, expectedFingerprint) {
398
- const root = descriptor.roots.generation;
318
+ function inspectRuntimeRoot(descriptor, expectedFingerprint) {
319
+ const root = descriptor.roots.runtime;
399
320
  let metadata;
400
321
  try {
401
322
  metadata = lstatSync(root);
@@ -453,7 +374,7 @@ function ensureOwnedDirectories(descriptor) {
453
374
  join(descriptor.roots.data, "state"),
454
375
  join(descriptor.roots.temporary, "runtime")
455
376
  ]) {
456
- ensureDirectoryChain(descriptor.roots.generation, path);
377
+ ensureDirectoryChain(descriptor.roots.runtime, path);
457
378
  }
458
379
  }
459
380
  function ensureDirectoryChain(boundary, target) {
@@ -494,8 +415,8 @@ function validatePreparation(preparation) {
494
415
  function taskRuntimeWorkspaceOwner(owner) {
495
416
  return owner;
496
417
  }
497
- function taskRuntimeGenerationRoot(runtimeRoot, taskId, owner, runtimeGenerationId, pathLayout = "hierarchical") {
498
- return join(taskRuntimeInventoryRoot(runtimeRoot, taskId, pathLayout), taskRuntimeOwnerDigest(taskId, owner, pathLayout), taskRuntimeLaunchDigest(taskId, runtimeGenerationId, pathLayout));
418
+ function taskRuntimeWorkspaceRoot(runtimeRoot, taskId, owner, pathLayout = "hierarchical") {
419
+ return join(taskRuntimeInventoryRoot(runtimeRoot, taskId, pathLayout), taskRuntimeOwnerDigest(taskId, owner, pathLayout), "runtime");
499
420
  }
500
421
  function taskRuntimeInventoryRoot(runtimeRoot, taskId, pathLayout) {
501
422
  return pathLayout === "compact" ? runtimeRoot : join(runtimeRoot, taskId);
@@ -505,9 +426,6 @@ function taskRuntimeOwnerDigest(taskId, owner, pathLayout) {
505
426
  ? digest(JSON.stringify([taskId, owner])).slice(0, 20)
506
427
  : digest(JSON.stringify(owner)).slice(0, 24);
507
428
  }
508
- function taskRuntimeLaunchDigest(taskId, runtimeGenerationId, pathLayout) {
509
- return digest(JSON.stringify([taskId, runtimeGenerationId])).slice(0, pathLayout === "compact" ? 20 : 24);
510
- }
511
429
  function taskRuntimePathLayout(value) {
512
430
  const pathLayout = value ?? "hierarchical";
513
431
  if (pathLayout !== "hierarchical" && pathLayout !== "compact") {
@@ -515,12 +433,11 @@ function taskRuntimePathLayout(value) {
515
433
  }
516
434
  return pathLayout;
517
435
  }
518
- function taskRuntimeServiceNamespace(taskId, owner, runtimeGenerationId, generationId) {
436
+ function taskRuntimeServiceNamespace(taskId, owner, runtimeRoot) {
519
437
  return `yui-task-${digest(JSON.stringify([
520
438
  taskId,
521
439
  owner,
522
- runtimeGenerationId,
523
- generationId
440
+ runtimeRoot
524
441
  ])).slice(0, 24)}`;
525
442
  }
526
443
  function normalizeControlBoundary(value) {
@@ -3,12 +3,12 @@ import { fileURLToPath } from "node:url";
3
3
  import { resolve } from "node:path";
4
4
  import { createRuntimeBinding } from "./runtimeBinding.js";
5
5
  import { normalizeRuntimeOwner } from "./runtimeOwner.js";
6
- import { RuntimeGenerationMismatchError, RuntimeHostContentionError, RuntimeHostUnavailableError, promptPushOutcome } from "./ports.js";
6
+ import { RuntimeHostContentionError, RuntimeHostUnavailableError, promptPushOutcome } from "./ports.js";
7
7
  import { providerDeliveryFailureFrom } from "./agentError.js";
8
8
  import { toRuntimeLaunchFailure } from "./launchDiagnostics.js";
9
9
  import { requireSafeIdentity } from "./validation.js";
10
10
  import { launchBrokerForHome } from "./launchBroker.js";
11
- import { AGENT_HOST_CONTROL_PROTOCOL, sendAgentHostLaunchControl, sendAgentHostTurnControl, sendAgentHostSteerControl, waitForAgentHostLaunchAck } from "./agentHost.js";
11
+ import { AGENT_HOST_CONTROL_PROTOCOL, sendAgentHostLaunchControl, sendAgentHostRunControl, sendAgentHostSteerControl, waitForAgentHostLaunchAck } from "./agentHost.js";
12
12
  const DEFAULT_INACTIVITY_TIMEOUT_MS = 300_000;
13
13
  /**
14
14
  * Runtime lifecycle adapter for the current tmux host. The returned hostRef is
@@ -143,8 +143,8 @@ export class TmuxSessionHost {
143
143
  const key = hostId;
144
144
  const previous = this.#launchTails.get(key) ?? Promise.resolve();
145
145
  let release;
146
- const turn = new Promise((resolve) => { release = resolve; });
147
- const tail = previous.then(() => turn);
146
+ const run = new Promise((resolve) => { release = resolve; });
147
+ const tail = previous.then(() => run);
148
148
  this.#launchTails.set(key, tail);
149
149
  await previous;
150
150
  try {
@@ -160,7 +160,7 @@ export class TmuxSessionHost {
160
160
  // Validate generated identity before starting an external process.
161
161
  const bindingId = requireSafeIdentity(this.#createBindingId(), "Runtime binding id");
162
162
  const writableHumanAttached = request.owner.scope === "task"
163
- && request.turnId !== undefined
163
+ && request.runId !== undefined
164
164
  && (this.tmux.hasWritableClientAsync !== undefined
165
165
  ? await this.tmux.hasWritableClientAsync(hostId, request.owner.roleName)
166
166
  : this.tmux.hasWritableClient?.(hostId, request.owner.roleName) === true);
@@ -172,9 +172,8 @@ export class TmuxSessionHost {
172
172
  agentId: request.agentId,
173
173
  adapterId: request.adapterId,
174
174
  effective: request.effective,
175
- runtimeGenerationId: request.runtimeGenerationId,
176
175
  mode: request.mode,
177
- ...(request.turnId === undefined ? {} : { turnId: request.turnId }),
176
+ ...(request.runId === undefined ? {} : { runId: request.runId }),
178
177
  ...(request.runtimeIsolation === undefined
179
178
  ? {}
180
179
  : { runtimeIsolation: request.runtimeIsolation }),
@@ -237,8 +236,7 @@ export class TmuxSessionHost {
237
236
  ?? (request.mode === "resume" ? request.nativeSessionId : undefined);
238
237
  beforeHostStart?.({
239
238
  owner: request.owner,
240
- runtimeGenerationId: request.runtimeGenerationId,
241
- ...(request.turnId === undefined ? {} : { turnId: request.turnId }),
239
+ ...(request.runId === undefined ? {} : { runId: request.runId }),
242
240
  agentId: request.agentId,
243
241
  adapterId: request.adapterId,
244
242
  effective: request.effective,
@@ -256,8 +254,8 @@ export class TmuxSessionHost {
256
254
  || (!interactiveCodex && (yuiHome === undefined
257
255
  || childLifecycle === undefined
258
256
  || planned.launch.providerControl === undefined))) {
259
- if (request.owner.scope === "task" && request.turnId !== undefined) {
260
- throw new Error("Managed Task Turn is missing its structured Agent Host contract.");
257
+ if (request.owner.scope === "task" && request.runId !== undefined) {
258
+ throw new Error("Managed Task AgentRun is missing its structured Agent Host contract.");
261
259
  }
262
260
  let hostCreated;
263
261
  try {
@@ -271,7 +269,6 @@ export class TmuxSessionHost {
271
269
  }
272
270
  let binding = createRuntimeBinding({
273
271
  id: bindingId,
274
- runtimeGenerationId: request.runtimeGenerationId,
275
272
  owner: request.owner,
276
273
  agentId: request.agentId,
277
274
  adapterId: request.adapterId,
@@ -290,7 +287,7 @@ export class TmuxSessionHost {
290
287
  }
291
288
  if (request.mode === "new"
292
289
  && request.owner.scope === "task"
293
- && request.turnId !== undefined
290
+ && request.runId !== undefined
294
291
  && this.#waitForNativeSession !== undefined) {
295
292
  binding = createRuntimeBinding({
296
293
  ...binding,
@@ -307,22 +304,27 @@ export class TmuxSessionHost {
307
304
  }
308
305
  const broker = launchBrokerForHome(yuiHome);
309
306
  const sessionManifest = planned.launch.env.YUI_SESSION_MANIFEST;
310
- if (request.owner.scope === "task" && request.turnId !== undefined
307
+ if (request.owner.scope === "task" && request.runId !== undefined
311
308
  && sessionManifest === undefined) {
312
309
  throw new Error("Managed Task Agent Host launch is missing its Session Manifest.");
313
310
  }
314
311
  const reservation = broker.reserve(Object.freeze({
315
312
  schemaVersion: 2,
316
- runtimeGenerationId: request.runtimeGenerationId,
317
313
  command: planned.launch.command,
318
314
  args: [...planned.launch.args],
319
315
  environment: { ...planned.launch.env },
320
316
  cwd: planned.role.cwd ?? planned.role.workspace,
317
+ ...(planned.launch.executionEnvironment === undefined ? {} : {
318
+ executionEnvironment: structuredClone(planned.launch.executionEnvironment)
319
+ }),
321
320
  childLifecycle,
322
321
  startMode: planned.launch.deferProviderStart === true ? "idle" : "provider",
323
322
  ...(planned.launch.providerControl === undefined
324
323
  ? {}
325
- : { providerControl: planned.launch.providerControl })
324
+ : { providerControl: planned.launch.providerControl }),
325
+ ...(planned.launch.interactiveCodexThread === undefined
326
+ ? {}
327
+ : { interactiveCodexThread: planned.launch.interactiveCodexThread })
326
328
  }));
327
329
  const hostLaunch = {
328
330
  command: process.execPath,
@@ -330,7 +332,6 @@ export class TmuxSessionHost {
330
332
  fileURLToPath(new URL("../cli.js", import.meta.url)),
331
333
  "internal",
332
334
  "agent-host",
333
- reservation.runtimeGenerationId,
334
335
  reservation.ticket
335
336
  ],
336
337
  env: {
@@ -338,7 +339,6 @@ export class TmuxSessionHost {
338
339
  YUI_SESSION_SCOPE: request.owner.scope,
339
340
  ...(request.owner.scope === "task" ? { YUI_TASK_ID: request.owner.taskId } : {}),
340
341
  YUI_ROLE: request.owner.roleName,
341
- YUI_RUNTIME_GENERATION_ID: request.runtimeGenerationId,
342
342
  ...(planned.launch.env.YUI_AGENT_ID === undefined
343
343
  ? {}
344
344
  : { YUI_AGENT_ID: planned.launch.env.YUI_AGENT_ID }),
@@ -354,7 +354,6 @@ export class TmuxSessionHost {
354
354
  }
355
355
  };
356
356
  let hostCreated = false;
357
- let providerDispatchObserved = false;
358
357
  let providerSnapshot;
359
358
  try {
360
359
  hostCreated = await ensureRoleWindow(this.tmux, hostId, planned.role, hostLaunch);
@@ -372,8 +371,7 @@ export class TmuxSessionHost {
372
371
  scope: request.owner.scope,
373
372
  ...(request.owner.scope === "task" ? { taskId: request.owner.taskId } : {}),
374
373
  roleName: request.owner.roleName,
375
- runtimeGenerationId: reservation.runtimeGenerationId,
376
- requireTurnAck: false,
374
+ requireRunAck: false,
377
375
  ...(interactiveCodex ? { assertHostRunning: assertInteractivePane } : {})
378
376
  });
379
377
  if (interactiveCodex) {
@@ -383,7 +381,6 @@ export class TmuxSessionHost {
383
381
  requireSafeIdentity(providerSnapshot.nativeSessionId, "Codex Thread identity");
384
382
  await assertInteractivePane();
385
383
  }
386
- providerDispatchObserved = true;
387
384
  }
388
385
  if (!hostCreated) {
389
386
  if (interactiveCodex) {
@@ -397,74 +394,32 @@ export class TmuxSessionHost {
397
394
  control: {
398
395
  protocol: AGENT_HOST_CONTROL_PROTOCOL,
399
396
  type: "launch",
400
- runtimeGenerationId: reservation.runtimeGenerationId,
401
397
  ticket: reservation.ticket
402
398
  }
403
399
  });
404
- if (controlResult.outcome === "active-other-generation") {
405
- broker.revoke(request.runtimeGenerationId);
400
+ if (controlResult.outcome === "busy") {
401
+ broker.revoke(reservation.ticket);
406
402
  throw new RuntimeHostContentionError("provider-child-active", `The persistent Agent Host for ${request.owner.roleName} still owns another Provider Turn.`);
407
403
  }
408
- if (controlResult.outcome === "active-same-generation") {
409
- broker.revoke(request.runtimeGenerationId);
410
- }
411
- // Identity and readiness are separate facts. Only a genuinely
412
- // different generation is a conflict that must fail closed, not
413
- // permission to stop the Host; a matching unsettled generation is this
414
- // exact activation still coming up, and stopping it would destroy a
415
- // healthy Session (and any Turn it is carrying).
416
- const observedGeneration = controlResult.snapshot.runtimeGenerationId;
417
- if (observedGeneration !== reservation.runtimeGenerationId) {
418
- broker.revoke(request.runtimeGenerationId);
419
- throw new RuntimeGenerationMismatchError(reservation.runtimeGenerationId, observedGeneration, controlResult.snapshot.state, `Agent Host acknowledgement generation mismatch for ${reservation.runtimeGenerationId}; observed=${observedGeneration ?? "none"}; `
420
- + `state=${controlResult.snapshot.state}${describeHostFailure(controlResult)}.`);
421
- }
422
404
  if (!["idle", "ready", "busy"].includes(controlResult.snapshot.state)) {
423
- broker.revoke(request.runtimeGenerationId);
405
+ broker.revoke(reservation.ticket);
424
406
  if (["starting", "settling", "delivery-unknown"].includes(controlResult.snapshot.state)) {
425
- // The right generation is present but not yet deliverable. This
426
- // is transient backpressure, so leave the Host running and let
427
- // the caller retry rather than terminalizing the Turn.
428
- throw new RuntimeHostContentionError("provider-child-active", `The Agent Host for ${request.owner.roleName} is still ${controlResult.snapshot.state} on this exact generation${describeHostFailure(controlResult)}.`);
407
+ // A temporarily unavailable Session preserves the pending input.
408
+ throw new RuntimeHostContentionError("provider-child-active", `The Agent Host for ${request.owner.roleName} is still ${controlResult.snapshot.state}${describeHostFailure(controlResult)}.`);
429
409
  }
430
410
  // This launch is unusable. It did not create this Host, so failure
431
411
  // is not authority to clean its resources or unknown execution.
432
- throw new RuntimeHostUnavailableError(reservation.runtimeGenerationId, controlResult.snapshot.state, `Agent Host reached ${controlResult.snapshot.state} for ${reservation.runtimeGenerationId}${describeHostFailure(controlResult)}.`, { cause: controlResult.failure ?? controlResult.snapshot });
412
+ throw new RuntimeHostUnavailableError(controlResult.snapshot.state, `Agent Host reached ${controlResult.snapshot.state}${describeHostFailure(controlResult)}.`, { cause: controlResult.failure ?? controlResult.snapshot });
433
413
  }
434
414
  providerSnapshot = controlResult.snapshot;
435
- providerDispatchObserved = true;
436
415
  }
437
416
  }
438
417
  catch (error) {
439
- broker.revoke(request.runtimeGenerationId);
440
- if (hostCreated && !providerDispatchObserved) {
441
- try {
442
- await stopExactRole(this.tmux, hostId, request.owner.roleName);
443
- }
444
- catch (stopError) {
445
- throw new Error(`Managed Provider launch failed and its disposable Agent Host could not be stopped: ${stopError instanceof Error ? stopError.message : String(stopError)}`, { cause: stopError });
446
- }
447
- }
418
+ broker.revoke(reservation.ticket);
448
419
  throw error;
449
420
  }
450
- if (providerDispatchObserved
451
- // A fresh Host always starts a Provider process. mode=new also starts
452
- // one inside a reused Host by replacing (or creating) the native
453
- // Conversation. Same-Conversation resume must retain its inherited key.
454
- && (hostCreated || request.mode === "new")
455
- && request.owner.scope === "task"
456
- && planned.launch.env.YUI_JOB_CALLER_KEY !== undefined
457
- && this.planner.commitTaskCallerKey !== undefined) {
458
- this.planner.commitTaskCallerKey({
459
- taskId: request.owner.taskId,
460
- roleName: request.owner.roleName,
461
- agentId: request.agentId,
462
- callerKey: planned.launch.env.YUI_JOB_CALLER_KEY
463
- });
464
- }
465
421
  const binding = createRuntimeBinding({
466
422
  id: bindingId,
467
- runtimeGenerationId: request.runtimeGenerationId,
468
423
  owner: request.owner,
469
424
  agentId: request.agentId,
470
425
  adapterId: request.adapterId,
@@ -519,12 +474,7 @@ export class TmuxSessionHost {
519
474
  return await Promise.race([discovery, monitor]);
520
475
  }
521
476
  catch (error) {
522
- try {
523
- await stopExactRole(this.tmux, hostId, request.owner.roleName);
524
- }
525
- catch {
526
- // Preserve the discovery failure; durable cleanup owns later retries.
527
- }
477
+ // Missing discovery is not evidence that the running process is unwanted.
528
478
  throw toRuntimeLaunchFailure(error, "native-session-discovery", context);
529
479
  }
530
480
  finally {
@@ -565,7 +515,7 @@ function describeHostFailure(result) {
565
515
  const detail = result.failure?.detail ?? result.snapshot.detail;
566
516
  return detail === undefined ? "" : `; detail=${detail}`;
567
517
  }
568
- /** Structured managed-Turn input; tmux remains presentation/liveness only. */
518
+ /** Structured managed-AgentRun input; tmux remains presentation/liveness only. */
569
519
  export class AgentHostPromptPushAdapter {
570
520
  home;
571
521
  constructor(home) {
@@ -579,7 +529,7 @@ export class AgentHostPromptPushAdapter {
579
529
  return promptPushOutcome("unavailable");
580
530
  }
581
531
  try {
582
- const result = await sendAgentHostTurnControl({
532
+ const result = await sendAgentHostRunControl({
583
533
  home: this.home,
584
534
  scope: "task",
585
535
  taskId: ref.hostId,
@@ -587,11 +537,11 @@ export class AgentHostPromptPushAdapter {
587
537
  control: {
588
538
  protocol: AGENT_HOST_CONTROL_PROTOCOL,
589
539
  type: "submit-turn",
590
- runtimeGenerationId: request.binding.runtimeGenerationId,
591
540
  nativeSessionId: request.binding.nativeSessionId,
592
- turnId: request.envelope.source.localId,
541
+ ...(request.envelope.source.kind === "notification"
542
+ ? {} : { runId: request.envelope.source.localId }),
593
543
  authority: request.binding.providerAuthority,
594
- turn: {
544
+ run: {
595
545
  attemptId: request.envelope.id,
596
546
  boundedText: request.envelope.text
597
547
  }
@@ -599,6 +549,8 @@ export class AgentHostPromptPushAdapter {
599
549
  });
600
550
  // The Host attaches its own structured cause to every non-delivery.
601
551
  const failure = result.failure;
552
+ if (result.outcome === "pending")
553
+ return promptPushOutcome("pending");
602
554
  if (result.snapshot.state === "delivery-unknown") {
603
555
  return promptPushOutcome("delivery-unknown", failure);
604
556
  }
@@ -612,7 +564,7 @@ export class AgentHostPromptPushAdapter {
612
564
  : promptPushOutcome("unavailable", failure);
613
565
  }
614
566
  if (result.snapshot.state === "ready")
615
- return promptPushOutcome("delivered");
567
+ return promptPushOutcome(result.snapshot.inputAcceptance === "provider" ? "delivered" : "pending");
616
568
  return result.snapshot.state === "starting" || result.snapshot.state === "settling"
617
569
  ? promptPushOutcome("busy", failure)
618
570
  : promptPushOutcome("unavailable", failure);
@@ -631,20 +583,21 @@ export class AgentHostPromptPushAdapter {
631
583
  control: {
632
584
  protocol: AGENT_HOST_CONTROL_PROTOCOL,
633
585
  type: "steer-turn",
634
- runtimeGenerationId: request.runtimeGenerationId,
635
586
  nativeSessionId: request.nativeSessionId,
636
587
  nativeTurnId: request.nativeTurnId,
637
588
  authority: request.providerAuthority,
638
- turn: {
589
+ run: {
639
590
  attemptId: request.envelope.id,
640
591
  boundedText: request.envelope.text
641
592
  }
642
593
  }
643
594
  });
595
+ if (result.outcome === "pending")
596
+ return promptPushOutcome("pending");
644
597
  if (result.outcome === "accepted")
645
598
  return promptPushOutcome("delivered");
646
599
  const failure = result.failure;
647
- if (result.snapshot.state === "delivery-unknown") {
600
+ if (failure?.inputDisposition === "unknown" || result.snapshot.state === "delivery-unknown") {
648
601
  return promptPushOutcome("delivery-unknown", failure);
649
602
  }
650
603
  if (result.snapshot.state === "busy")