@zq-silk/yui 0.15.7 → 0.15.9

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 (308) hide show
  1. package/ARCHITECTURE.md +194 -399
  2. package/ARCHITECTURE.zh-CN.md +151 -0
  3. package/README.md +306 -1131
  4. package/dist/agent/adapterCatalog.js +15 -2
  5. package/dist/agent/agent.js +23 -3
  6. package/dist/agent/argumentPolicy.js +7 -1
  7. package/dist/agent/connectionPlan.js +62 -0
  8. package/dist/agent/executionComponents.js +158 -0
  9. package/dist/agent/launchEnvironment.js +31 -3
  10. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  11. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  12. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  13. package/dist/artifacts/artifactCapability.js +74 -0
  14. package/dist/artifacts/artifactCommitLock.js +249 -0
  15. package/dist/artifacts/artifactPaths.js +151 -0
  16. package/dist/artifacts/gitArtifactRef.js +146 -0
  17. package/dist/artifacts/managedGit.js +332 -0
  18. package/dist/artifacts/taskArtifactRepository.js +277 -0
  19. package/dist/brief/taskBrief.js +12 -0
  20. package/dist/cli/agentConfigurationPicker.js +13 -0
  21. package/dist/cli/commandCatalog.js +165 -74
  22. package/dist/cli/interactionCandidates.js +5 -5
  23. package/dist/cli/interactionPolicy.js +38 -8
  24. package/dist/cli/invocationRouter.js +1 -1
  25. package/dist/cli/managedDiagnostics.js +28 -0
  26. package/dist/cli/operatorWizard.js +1 -7
  27. package/dist/cli/roleOptionOrder.js +27 -0
  28. package/dist/cli/roleWizard.js +50 -14
  29. package/dist/cli/updateOrchestrator.js +1 -1
  30. package/dist/cli/updatePorts.js +3 -4
  31. package/dist/cli.js +245 -95
  32. package/dist/commands/agentCommands.js +72 -14
  33. package/dist/commands/capabilityCommands.js +9 -6
  34. package/dist/commands/configCommands.js +20 -20
  35. package/dist/commands/deliveryGuardPreflight.js +2 -2
  36. package/dist/commands/executionAuditCommands.js +24 -24
  37. package/dist/commands/globalRoleCommands.js +1 -1
  38. package/dist/commands/grantCommands.js +4 -4
  39. package/dist/commands/operatorCommands.js +34 -9
  40. package/dist/commands/projectCommands.js +4 -4
  41. package/dist/commands/resourcesCommands.js +2 -2
  42. package/dist/commands/roleConfiguration.js +25 -5
  43. package/dist/commands/roleRuntimeGuard.js +4 -5
  44. package/dist/commands/sessionCommands.js +3 -7
  45. package/dist/commands/taskActivationCommands.js +281 -0
  46. package/dist/commands/taskActor.js +28 -49
  47. package/dist/commands/taskCommands.js +1461 -720
  48. package/dist/commands/taskContextCommand.js +39 -583
  49. package/dist/commands/taskExecutionCommands.js +32 -32
  50. package/dist/commands/taskInputCommands.js +40 -104
  51. package/dist/commands/taskIntegrationCommands.js +3 -2
  52. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  53. package/dist/commands/taskNextActionCommand.js +8 -8
  54. package/dist/commands/taskOverviewCommand.js +33 -45
  55. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  56. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  57. package/dist/commands/telemetryCommands.js +36 -38
  58. package/dist/config/configCatalog.js +4 -4
  59. package/dist/config/yuiConfig.js +8 -8
  60. package/dist/context/contextSnapshot.js +10 -10
  61. package/dist/context/dispatchContext.js +11 -11
  62. package/dist/context/roleSessionContext.js +6 -3
  63. package/dist/context/{turnContextPack.js → runContextPack.js} +158 -81
  64. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  65. package/dist/context/sessionBootstrapManifest.js +21 -2
  66. package/dist/context/sourceRunContext.js +30 -0
  67. package/dist/context/taskContext.js +481 -0
  68. package/dist/context/wakeNotification.js +27 -27
  69. package/dist/controller/agentRuntimeObserver.js +21 -24
  70. package/dist/controller/capabilityBridge.js +17 -6
  71. package/dist/controller/clientRuntime.js +65 -92
  72. package/dist/controller/controller.js +120 -188
  73. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  74. package/dist/controller/jobControl.js +54 -85
  75. package/dist/controller/resourceInventory.js +8 -27
  76. package/dist/controller/resourceInventoryLinux.js +12 -13
  77. package/dist/controller/runtime.js +529 -479
  78. package/dist/controller/runtimeEventInbox.js +55 -25
  79. package/dist/controller/runtimeEventProcessor.js +22 -31
  80. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  81. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  82. package/dist/controller/runtimeObservationHook.js +14 -18
  83. package/dist/controller/sessionNotify.js +16 -24
  84. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  85. package/dist/controller/structuredProviderObservation.js +138 -99
  86. package/dist/coordination/workMailbox.js +3 -3
  87. package/dist/coordination/workMailboxQueue.js +36 -33
  88. package/dist/core/boundedRpc.js +8 -1
  89. package/dist/core/controllerClient.js +20 -1
  90. package/dist/core/controllerServer.js +4 -4
  91. package/dist/doctor/doctor.js +13 -2
  92. package/dist/domain/agentResultTransport.js +9 -9
  93. package/dist/execution/codexThreadNaming.js +2 -8
  94. package/dist/execution/executionHealth.js +51 -63
  95. package/dist/execution/reviewMainRun.js +137 -0
  96. package/dist/execution/workItemExecution.js +28 -29
  97. package/dist/execution/workItemExecutionProjection.js +99 -107
  98. package/dist/execution/workItemMainRun.js +141 -0
  99. package/dist/executor/agentAdapter.js +227 -20
  100. package/dist/executor/agentConfigurationCatalog.js +126 -4
  101. package/dist/executor/agentConfigurationProbe.js +162 -4
  102. package/dist/executor/agentExecutor.js +79 -78
  103. package/dist/executor/effectiveLaunch.js +105 -18
  104. package/dist/executor/executorRegistry.js +29 -44
  105. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  106. package/dist/executor/workspacePreflightClassification.js +16 -16
  107. package/dist/grant/capabilityGrant.js +6 -3
  108. package/dist/input/inputRequest.js +12 -10
  109. package/dist/integration/gitIntegrationService.js +4 -11
  110. package/dist/integration/integrationQueueService.js +4 -4
  111. package/dist/interaction/operatorPresentation.js +1 -1
  112. package/dist/kernel/builtinCapabilities.js +255 -12
  113. package/dist/kernel/capabilityRegistry.js +64 -18
  114. package/dist/kernel/instanceHost.js +12 -1
  115. package/dist/kernel/kernelPorts.js +2 -2
  116. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  117. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  118. package/dist/message/message.js +118 -6
  119. package/dist/message/messageContinuation.js +204 -0
  120. package/dist/observability/executionAudit.js +70 -72
  121. package/dist/observability/faultClassification.js +2 -2
  122. package/dist/observability/orchestrationMetrics.js +8 -8
  123. package/dist/operator/operatorSessionHistory.js +1 -7
  124. package/dist/output/agentConfigurationPresentation.js +8 -3
  125. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  126. package/dist/output/rolePresentation.js +54 -3
  127. package/dist/plugins/pluginChild.js +104 -0
  128. package/dist/plugins/pluginIntent.js +26 -0
  129. package/dist/plugins/pluginInterpreter.js +43 -0
  130. package/dist/plugins/pluginPackage.js +101 -0
  131. package/dist/plugins/pluginProcess.js +112 -0
  132. package/dist/plugins/pluginService.js +388 -0
  133. package/dist/profile/agentProfile.js +1 -1
  134. package/dist/repository/gitWorkspace.js +26 -4
  135. package/dist/repository/project.js +19 -4
  136. package/dist/repository/taskBaseFreshness.js +13 -13
  137. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  138. package/dist/repository/taskWorkspacePreparer.js +344 -83
  139. package/dist/resources/autoResourceGc.js +3 -3
  140. package/dist/resources/liveReferences.js +3 -3
  141. package/dist/resources/projectResource.js +75 -0
  142. package/dist/resources/projectResourceService.js +343 -0
  143. package/dist/resources/resourceDiscovery.js +6 -6
  144. package/dist/resources/resourceGc.js +1 -1
  145. package/dist/resources/resourceRegistrar.js +1 -1
  146. package/dist/resources/resourceTypes.js +1 -1
  147. package/dist/review/deltaRecheck.js +3 -3
  148. package/dist/review/reviewAcceptance.js +16 -16
  149. package/dist/review/reviewDecision.js +7 -7
  150. package/dist/review/reviewRound.js +21 -20
  151. package/dist/review/reviewerAvailability.js +2 -2
  152. package/dist/role/role.js +51 -7
  153. package/dist/role/taskRoleUpdate.js +30 -0
  154. package/dist/runtime/acpProtocol.js +425 -0
  155. package/dist/runtime/acpSession.js +731 -0
  156. package/dist/runtime/acpSessionConfiguration.js +260 -0
  157. package/dist/runtime/agentDriver.js +30 -11
  158. package/dist/runtime/agentEndpoint.js +278 -0
  159. package/dist/runtime/agentEndpointIdentity.js +86 -0
  160. package/dist/runtime/agentEndpointOwnership.js +239 -0
  161. package/dist/runtime/agentError.js +2 -10
  162. package/dist/runtime/agentHost.js +565 -314
  163. package/dist/runtime/agentRunConfiguration.js +258 -0
  164. package/dist/runtime/builtinAgentDrivers.js +134 -18
  165. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  166. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  167. package/dist/runtime/claude-process-owner +0 -0
  168. package/dist/runtime/codexAppServerRuntime.js +38 -30
  169. package/dist/runtime/codexInteractiveHost.js +41 -6
  170. package/dist/runtime/continuationManager.js +2 -6
  171. package/dist/runtime/executionEnvironment.js +30 -0
  172. package/dist/runtime/firstProgressAdvisory.js +11 -11
  173. package/dist/runtime/index.js +4 -3
  174. package/dist/runtime/jsonLineChannel.js +109 -0
  175. package/dist/runtime/launchBroker.js +91 -16
  176. package/dist/runtime/launchDiagnostics.js +2 -2
  177. package/dist/runtime/lifecycleReservation.js +10 -18
  178. package/dist/runtime/managedCaller.js +61 -17
  179. package/dist/runtime/nativeSessionControl.js +102 -0
  180. package/dist/runtime/ports.js +6 -21
  181. package/dist/runtime/processExitObservation.js +8 -7
  182. package/dist/runtime/promptEnvelope.js +17 -6
  183. package/dist/runtime/providerContinuation.js +3 -9
  184. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  185. package/dist/runtime/providerControl.js +2 -7
  186. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  187. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  188. package/dist/runtime/runtimeBinding.js +0 -1
  189. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  190. package/dist/runtime/runtimeDeadlines.js +9 -0
  191. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  192. package/dist/runtime/runtimeObservation.js +29 -65
  193. package/dist/runtime/runtimeProjection.js +43 -51
  194. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  195. package/dist/runtime/sessionLaunchRequest.js +3 -7
  196. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  197. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  198. package/dist/runtime/sessionReconciliation.js +4 -8
  199. package/dist/runtime/sessionTerminationGuard.js +70 -259
  200. package/dist/runtime/sessionTokenMetrics.js +5 -16
  201. package/dist/runtime/structuredProviderHost.js +237 -117
  202. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  203. package/dist/runtime/tmuxAdapters.js +39 -86
  204. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  205. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  206. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  207. package/dist/scheduler/ports.js +80 -9
  208. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  209. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  210. package/dist/scheduler/taskExecutionProjection.js +120 -124
  211. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  212. package/dist/scheduler/taskWake.js +11 -4
  213. package/dist/scheduler/wakeReason.js +9 -1
  214. package/dist/setup/setupCommand.js +3 -7
  215. package/dist/storage/migrations/agentRunContract.js +159 -0
  216. package/dist/storage/migrations/artifactsToGit.js +338 -0
  217. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  218. package/dist/storage/migrations/submitIntent.js +126 -0
  219. package/dist/storage/sqliteSchema.js +467 -7
  220. package/dist/storage/sqliteStore.js +355 -220
  221. package/dist/storage/storageVersions.js +1 -1
  222. package/dist/storage/storeRpc.js +10 -5
  223. package/dist/storage/taskStore.js +13 -11
  224. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  225. package/dist/surface/surfaceContributions.js +102 -0
  226. package/dist/task/completionReadiness.js +32 -6
  227. package/dist/task/deliveryGuard.js +16 -16
  228. package/dist/task/draftPlan.js +72 -12
  229. package/dist/task/nextAction.js +144 -128
  230. package/dist/task/remoteDelivery.js +6 -6
  231. package/dist/task/task.js +184 -18
  232. package/dist/task/taskActivation.js +327 -0
  233. package/dist/task/taskActivationService.js +408 -0
  234. package/dist/task/taskRecordReference.js +5 -4
  235. package/dist/task/taskRecordRetirement.js +1 -1
  236. package/dist/task/taskSubmission.js +236 -0
  237. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  238. package/dist/telemetry/telemetryConfig.js +14 -14
  239. package/dist/telemetry/telemetryWiring.js +2 -2
  240. package/dist/web/assets/assetManifest.js +2 -0
  241. package/dist/web/assets/client/app.js +121 -20
  242. package/dist/web/assets/client/components.js +87 -54
  243. package/dist/web/assets/client/i18n.js +83 -41
  244. package/dist/web/assets/client/markdown.js +1 -1
  245. package/dist/web/assets/client/taskSurface.js +442 -0
  246. package/dist/web/assets/client/view.js +49 -44
  247. package/dist/web/assets/shell.js +1 -1
  248. package/dist/web/assets/styles/cards.js +22 -4
  249. package/dist/web/controllerWeb.js +60 -0
  250. package/dist/web/webMutation.js +28 -0
  251. package/dist/web/webServer.js +133 -8
  252. package/dist/web/webSnapshot.js +81 -74
  253. package/dist/web/webTaskSurface.js +64 -0
  254. package/dist/workItem/dependencyGate.js +1 -1
  255. package/dist/workItem/workItem.js +84 -48
  256. package/dist/workspace/workItemChangeSetManager.js +16 -9
  257. package/docs/agent-result-consumption.md +96 -0
  258. package/docs/agent-result-consumption.zh-CN.md +81 -0
  259. package/docs/agent-runtime-drivers.md +93 -0
  260. package/docs/agent-runtime-drivers.zh-CN.md +77 -0
  261. package/docs/architecture/README.md +50 -0
  262. package/docs/architecture/README.zh-CN.md +43 -0
  263. package/docs/architecture/capabilities-and-resources.md +118 -0
  264. package/docs/architecture/capabilities-and-resources.zh-CN.md +83 -0
  265. package/docs/managed-turn-and-session-runtime.md +224 -0
  266. package/docs/managed-turn-and-session-runtime.zh-CN.md +180 -0
  267. package/docs/observability/README.md +83 -0
  268. package/docs/observability/README.zh-CN.md +71 -0
  269. package/docs/plugin-sdk.md +393 -0
  270. package/docs/plugin-sdk.zh-CN.md +293 -0
  271. package/docs/provider-runtime.md +165 -0
  272. package/docs/provider-runtime.zh-CN.md +132 -0
  273. package/docs/release-workflow.md +305 -0
  274. package/docs/release-workflow.zh-CN.md +237 -0
  275. package/docs/roles-and-configuration.md +115 -0
  276. package/docs/roles-and-configuration.zh-CN.md +96 -0
  277. package/docs/sqlite-control-plane-design.md +78 -0
  278. package/docs/sqlite-control-plane-design.zh-CN.md +62 -0
  279. package/docs/task-dag-semantics.md +80 -0
  280. package/docs/task-dag-semantics.zh-CN.md +59 -0
  281. package/docs/task-delivery.md +105 -0
  282. package/docs/task-delivery.zh-CN.md +82 -0
  283. package/docs/task-local-identity.md +8 -6
  284. package/docs/task-local-identity.zh-CN.md +58 -0
  285. package/docs/testing/verification-levels.md +88 -0
  286. package/docs/testing/verification-levels.zh-CN.md +69 -0
  287. package/i18n/README.zh-CN.md +270 -722
  288. package/package.json +3 -2
  289. package/skills/yui-leader/SKILL.md +88 -304
  290. package/skills/yui-leader/references/execution.md +303 -0
  291. package/skills/yui-leader/references/integration.md +39 -0
  292. package/skills/yui-leader/references/planning.md +109 -0
  293. package/skills/yui-leader/references/replicated-execution.md +42 -0
  294. package/skills/yui-leader/references/task-plugins.md +37 -0
  295. package/skills/yui-operator/SKILL.md +46 -62
  296. package/skills/yui-reviewer/SKILL.md +35 -36
  297. package/skills/yui-runtime/SKILL.md +88 -24
  298. package/skills/yui-runtime/references/publication.md +22 -0
  299. package/skills/yui-runtime/references/recovery.md +64 -0
  300. package/skills/yui-worker/SKILL.md +37 -39
  301. package/dist/cli/roleOptionCatalog.js +0 -68
  302. package/dist/context/sourceTurnContext.js +0 -30
  303. package/dist/execution/reviewMainTurn.js +0 -161
  304. package/dist/execution/workItemMainTurn.js +0 -164
  305. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  306. package/dist/runtime/preallocatedNativeSession.js +0 -13
  307. package/dist/runtime/runtimeStopReceipt.js +0 -42
  308. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { callController } from "../core/controllerClient.js";
2
+ import { callController, ControllerClientError } from "../core/controllerClient.js";
3
3
  import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
4
4
  import { standardAgentError } from "../runtime/agentError.js";
5
5
  import { transportAgentResult } from "../domain/agentResultTransport.js";
@@ -7,15 +7,75 @@ import { createRuntimeObservation, runtimeObservationSemanticKey } from "../runt
7
7
  import { runtimeLifecycleSignalKey } from "../runtime/lifecycleReservation.js";
8
8
  import { isForeignHandoverLockHeld } from "../release/runtimeRelease.js";
9
9
  import { FileRuntimeEventInbox } from "./runtimeEventInbox.js";
10
- import { resolveRuntimeHookTurnFence } from "./runtimeHookTurnFence.js";
11
- import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
10
+ import { resolveRuntimeHookRunFence } from "./runtimeHookRunFence.js";
12
11
  let structuredSequence = 0;
12
+ export async function publishStructuredProviderAttachmentExit(input) {
13
+ const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
14
+ const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
15
+ const owner = resolveRuntimeHookRunFence(input.environment, adapterId, input.nativeSessionId, {
16
+ terminal: true, attemptId: input.attemptId, nativeTurnId: input.nativeTurnId
17
+ });
18
+ await persistAndApply(input.home, [observation({
19
+ kind: input.failed ? "session.failed" : "session.ended", observedAt: input.observedAt,
20
+ sequence: nextStructuredSequence(), ordinal: 0,
21
+ fence: {
22
+ taskId: owner.taskId, roleName: owner.roleName, agentId: owner.agentId, driverId: driver.id,
23
+ nativeSessionId: input.nativeSessionId, conversationId: input.nativeSessionId,
24
+ ...(owner.runId === undefined ? {} : { runId: owner.runId }),
25
+ ...(input.attemptId === undefined ? {} : { receiptId: input.attemptId }),
26
+ ...(input.nativeTurnId === undefined ? {} : { nativeTurnId: input.nativeTurnId })
27
+ }
28
+ })], owner.taskId, owner.roleName);
29
+ }
30
+ export async function publishStructuredProviderActivity(input) {
31
+ const activity = input.activity;
32
+ const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
33
+ const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
34
+ const owner = resolveRuntimeHookRunFence(input.environment, adapterId, activity.nativeSessionId, {
35
+ nativeTurnId: activity.nativeTurnId, attemptId: activity.attemptId
36
+ });
37
+ const event = observation({
38
+ kind: activity.phase === "model" ? "activity.observed" : `operation.${activity.phase}`,
39
+ observedAt: activity.observedAt, sequence: nextStructuredSequence(), ordinal: 0,
40
+ fence: {
41
+ taskId: owner.taskId, roleName: owner.roleName,
42
+ ...(owner.runId === undefined ? {} : { runId: owner.runId }),
43
+ agentId: owner.agentId, driverId: driver.id,
44
+ nativeSessionId: activity.nativeSessionId, conversationId: activity.conversationId,
45
+ receiptId: activity.attemptId,
46
+ ...(activity.nativeTurnId === undefined ? {} : { nativeTurnId: activity.nativeTurnId })
47
+ },
48
+ payload: activity.phase === "model"
49
+ ? { activity: "model", activityId: activity.id }
50
+ : { operation: "tool", operationId: activity.id }
51
+ });
52
+ await persistAndApply(input.home, [event], owner.taskId, owner.roleName);
53
+ }
54
+ /** An exact provider item id is evidence of visible input, not an inferred
55
+ * human author. The original managed request is never replaced.
56
+ */
57
+ export async function publishStructuredProviderInputObserved(input) {
58
+ const observed = input.observed;
59
+ const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
60
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, observed.nativeSessionId, {
61
+ nativeTurnId: observed.nativeTurnId, terminal: true, sessionOnly: true
62
+ });
63
+ if (fence.runId === undefined)
64
+ return; // Ordinary chat need not be mirrored.
65
+ await persistAndApply(input.home, [observation({
66
+ kind: "input.accepted", observedAt: observed.observedAt, sequence: nextStructuredSequence(), ordinal: 0,
67
+ fence: { ...fence, driverId: builtinAgentDriverRegistry().requireByAdapterId(adapterId).id,
68
+ conversationId: observed.conversationId, nativeTurnId: observed.nativeTurnId,
69
+ receiptId: `native-input:${observed.nativeTurnId}/${observed.inputId}` },
70
+ payload: { input: observed.input }
71
+ })], fence.taskId, fence.roleName);
72
+ }
13
73
  export async function publishStructuredProviderStarted(input) {
14
74
  if (input.started.clientOwned)
15
75
  return;
16
76
  const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
17
77
  const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
18
- const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.started.nativeSessionId, {
78
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.started.nativeSessionId, {
19
79
  nativeTurnId: input.started.nativeTurnId,
20
80
  sessionOnly: true
21
81
  });
@@ -30,9 +90,7 @@ export async function publishStructuredProviderStarted(input) {
30
90
  roleName: fence.roleName,
31
91
  agentId: fence.agentId,
32
92
  driverId: driver.id,
33
- runtimeGenerationId: fence.runtimeGenerationId,
34
93
  conversationId: input.started.conversationId,
35
- activationId: requireIdentity(input.activationId, "Provider Activation id"),
36
94
  nativeSessionId: input.started.nativeSessionId,
37
95
  nativeTurnId: input.started.nativeTurnId,
38
96
  receiptId
@@ -45,7 +103,7 @@ export async function publishStructuredProviderAccepted(input) {
45
103
  const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
46
104
  const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
47
105
  const startupSession = driver.capabilities.observation.sessionBootstrap;
48
- const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.receipt.nativeSessionId, {
106
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.receipt.nativeSessionId, {
49
107
  startupSession,
50
108
  nativeTurnId: input.receipt.nativeTurnId,
51
109
  attemptId: input.receipt.attemptId
@@ -54,23 +112,21 @@ export async function publishStructuredProviderAccepted(input) {
54
112
  const commonFence = {
55
113
  taskId: fence.taskId,
56
114
  roleName: fence.roleName,
57
- ...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
115
+ ...(fence.runId === undefined ? {} : { runId: fence.runId }),
58
116
  agentId: fence.agentId,
59
117
  driverId: driver.id,
60
- runtimeGenerationId: fence.runtimeGenerationId,
61
118
  conversationId: input.receipt.conversationId,
62
- activationId: executionActivationId(input.home, fence, input.activationId, input.receipt.nativeSessionId),
63
119
  nativeSessionId: input.receipt.nativeSessionId,
64
120
  ...(input.receipt.nativeTurnId === undefined ? {} : {
65
121
  nativeTurnId: input.receipt.nativeTurnId
66
122
  }),
67
123
  // The structured Host owns the exact input attempt identity. Runtime
68
- // descriptor receipts name the Turn bootstrap and must not overwrite a
69
- // continuation or human-takeover Turn.
124
+ // descriptor receipts name the AgentRun bootstrap and must not overwrite a
125
+ // continuation or human-takeover AgentRun.
70
126
  receiptId: input.receipt.attemptId
71
127
  };
72
128
  const baseSequence = nextStructuredSequence();
73
- // Opening owns the Session/Activation lifecycle. A receipt arriving after
129
+ // Opening owns the Session lifecycle. A receipt arriving after
74
130
  // its terminal must not reopen either lifecycle as an acceptance side effect.
75
131
  const observations = [observation({
76
132
  kind: "turn.accepted",
@@ -82,20 +138,62 @@ export async function publishStructuredProviderAccepted(input) {
82
138
  })];
83
139
  await persistAndApply(input.home, observations, fence.taskId, fence.roleName);
84
140
  }
141
+ /** Steer settles an additional input, never the parent AgentRun's initial delivery. */
142
+ export async function publishStructuredProviderInputSettlement(input) {
143
+ const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
144
+ const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
145
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.nativeSessionId, {
146
+ nativeTurnId: input.nativeTurnId,
147
+ terminal: true
148
+ });
149
+ if (fence.runId === undefined)
150
+ throw new Error("Steer settlement has no exact original AgentRun.");
151
+ const entry = observation({
152
+ kind: input.status === "accepted" ? "input.accepted"
153
+ : input.status === "rejected" ? "input.rejected" : "input.delivery-unknown",
154
+ observedAt: new Date().toISOString(),
155
+ sequence: nextStructuredSequence(),
156
+ ordinal: 0,
157
+ fence: {
158
+ taskId: fence.taskId,
159
+ roleName: fence.roleName,
160
+ runId: fence.runId,
161
+ agentId: fence.agentId,
162
+ driverId: driver.id,
163
+ conversationId: input.nativeSessionId,
164
+ nativeSessionId: input.nativeSessionId,
165
+ nativeTurnId: input.nativeTurnId,
166
+ receiptId: input.attemptId
167
+ },
168
+ payload: {
169
+ input: input.boundedText,
170
+ ...(input.failure === undefined ? {} : {
171
+ failure: {
172
+ error: standardAgentError({
173
+ source: "host",
174
+ phase: "turn-submit",
175
+ message: input.failure.detail,
176
+ raw: input.failure.raw ?? input.failure.detail,
177
+ inputDisposition: input.status === "unknown" ? "unknown" : "not-accepted"
178
+ })
179
+ }
180
+ })
181
+ }
182
+ });
183
+ await persistAndApply(input.home, [entry], fence.taskId, fence.roleName);
184
+ }
85
185
  export async function publishStructuredProviderOpened(input) {
86
186
  const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
87
187
  const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
88
188
  const startupSession = driver.capabilities.observation.sessionBootstrap;
89
- const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.nativeSessionId, { startupSession });
189
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.nativeSessionId, { startupSession });
90
190
  const commonFence = {
91
191
  taskId: fence.taskId,
92
192
  roleName: fence.roleName,
93
- ...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
193
+ ...(fence.runId === undefined ? {} : { runId: fence.runId }),
94
194
  agentId: fence.agentId,
95
195
  driverId: driver.id,
96
- runtimeGenerationId: fence.runtimeGenerationId,
97
196
  conversationId: input.conversationId,
98
- activationId: requireIdentity(input.activationId, "Provider Activation id"),
99
197
  nativeSessionId: input.nativeSessionId,
100
198
  ...(fence.receiptId === undefined ? {} : { receiptId: fence.receiptId })
101
199
  };
@@ -113,19 +211,13 @@ export async function publishStructuredProviderOpened(input) {
113
211
  ordinal: 1,
114
212
  fence: commonFence,
115
213
  payload: { recoverability: input.recoverability }
116
- }), observation({
117
- kind: "activation.started",
118
- observedAt: input.observedAt,
119
- sequence,
120
- ordinal: 2,
121
- fence: commonFence
122
214
  })];
123
215
  await persistAndApply(input.home, observations, fence.taskId, fence.roleName);
124
216
  }
125
217
  export async function publishStructuredProviderGoal(input) {
126
218
  const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
127
219
  const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
128
- const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.conversationId, { sessionOnly: true });
220
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.conversationId, { sessionOnly: true });
129
221
  const goal = input.goal;
130
222
  const observedAt = input.observedAt ?? goal?.updatedAt ?? new Date().toISOString();
131
223
  const goalObservation = observation({
@@ -138,9 +230,7 @@ export async function publishStructuredProviderGoal(input) {
138
230
  roleName: fence.roleName,
139
231
  agentId: fence.agentId,
140
232
  driverId: driver.id,
141
- runtimeGenerationId: fence.runtimeGenerationId,
142
233
  conversationId: input.conversationId,
143
- activationId: requireIdentity(input.activationId, "Provider Activation id"),
144
234
  nativeSessionId: input.conversationId
145
235
  },
146
236
  payload: goal === null ? {} : {
@@ -156,27 +246,19 @@ export async function publishStructuredProviderGoal(input) {
156
246
  export async function publishStructuredConversationRecoverability(input) {
157
247
  const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
158
248
  const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
159
- const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.conversationId);
249
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.conversationId, { sessionOnly: true });
160
250
  const sequence = nextStructuredSequence();
161
251
  const observationFence = {
162
252
  taskId: fence.taskId,
163
253
  roleName: fence.roleName,
164
- ...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
254
+ ...(fence.runId === undefined ? {} : { runId: fence.runId }),
165
255
  agentId: fence.agentId,
166
256
  driverId: driver.id,
167
- runtimeGenerationId: fence.runtimeGenerationId,
168
257
  conversationId: input.conversationId,
169
- activationId: requireIdentity(input.activationId, "Provider Activation id"),
170
258
  nativeSessionId: input.conversationId,
171
259
  ...(fence.receiptId === undefined ? {} : { receiptId: fence.receiptId })
172
260
  };
173
261
  const observations = [observation({
174
- kind: "activation.started",
175
- observedAt: input.observedAt,
176
- sequence,
177
- ordinal: 0,
178
- fence: observationFence
179
- }), observation({
180
262
  kind: "conversation.observed",
181
263
  observedAt: input.observedAt,
182
264
  sequence,
@@ -184,22 +266,12 @@ export async function publishStructuredConversationRecoverability(input) {
184
266
  fence: observationFence,
185
267
  payload: { recoverability: input.recoverability }
186
268
  })];
187
- if (input.recoverability === "unrecoverable") {
188
- observations.push(observation({
189
- kind: "activation.failed",
190
- observedAt: input.observedAt,
191
- sequence,
192
- ordinal: 2,
193
- fence: observationFence,
194
- payload: {}
195
- }));
196
- }
197
269
  await persistAndApply(input.home, observations, fence.taskId, fence.roleName);
198
270
  }
199
271
  export async function publishStructuredProviderTerminal(input) {
200
272
  const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
201
273
  const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
202
- const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.terminal.nativeSessionId, {
274
+ const fence = resolveRuntimeHookRunFence(input.environment, adapterId, input.terminal.nativeSessionId, {
203
275
  terminal: true,
204
276
  nativeTurnId: input.terminal.nativeTurnId,
205
277
  attemptId: input.terminal.attemptId,
@@ -249,12 +321,10 @@ export async function publishStructuredProviderTerminal(input) {
249
321
  fence: {
250
322
  taskId: fence.taskId,
251
323
  roleName: fence.roleName,
252
- ...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
324
+ ...(fence.runId === undefined ? {} : { runId: fence.runId }),
253
325
  agentId: fence.agentId,
254
326
  driverId: driver.id,
255
- runtimeGenerationId: fence.runtimeGenerationId,
256
327
  conversationId: input.terminal.conversationId,
257
- activationId: executionActivationId(input.home, fence, input.activationId, input.terminal.nativeSessionId),
258
328
  nativeSessionId: input.terminal.nativeSessionId,
259
329
  ...(input.terminal.nativeTurnId === undefined ? {} : {
260
330
  nativeTurnId: input.terminal.nativeTurnId
@@ -263,35 +333,15 @@ export async function publishStructuredProviderTerminal(input) {
263
333
  ? fence.receiptId === undefined ? {} : { receiptId: fence.receiptId }
264
334
  : { receiptId: input.terminal.attemptId })
265
335
  },
266
- payload
336
+ payload: {
337
+ ...payload,
338
+ ...(kind !== "turn.completed" && transported.status === "completed"
339
+ ? { output: transported.output } : {}),
340
+ ...(input.terminal.input === undefined ? {} : { input: input.terminal.input })
341
+ }
267
342
  });
268
343
  await persistAndApply(input.home, [terminalObservation], fence.taskId, fence.roleName);
269
344
  }
270
- export async function publishStructuredProviderActivationTerminal(input) {
271
- const adapterId = requireIdentity(input.environment.YUI_ADAPTER_ID, "Agent adapter id");
272
- const driver = builtinAgentDriverRegistry().requireByAdapterId(adapterId);
273
- const fence = resolveRuntimeHookTurnFence(input.environment, adapterId, input.nativeSessionId, { sessionOnly: true });
274
- const terminal = observation({
275
- kind: input.status === "failed" ? "activation.failed" : "activation.ended",
276
- observedAt: input.observedAt,
277
- sequence: nextStructuredSequence(),
278
- ordinal: 0,
279
- fence: {
280
- taskId: fence.taskId,
281
- roleName: fence.roleName,
282
- ...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
283
- agentId: fence.agentId,
284
- driverId: driver.id,
285
- runtimeGenerationId: fence.runtimeGenerationId,
286
- conversationId: requireIdentity(input.conversationId, "Provider Conversation id"),
287
- activationId: requireIdentity(input.activationId, "Provider Activation id"),
288
- nativeSessionId: requireIdentity(input.nativeSessionId, "native Session id"),
289
- ...(fence.receiptId === undefined ? {} : { receiptId: fence.receiptId })
290
- },
291
- payload: {}
292
- });
293
- await persistAndApply(input.home, [terminal], fence.taskId, fence.roleName);
294
- }
295
345
  function observation(input) {
296
346
  const eventId = `agent-host-${randomUUID()}`;
297
347
  const partial = {
@@ -330,24 +380,6 @@ function requireIdentity(value, label) {
330
380
  }
331
381
  return value.trim();
332
382
  }
333
- function executionActivationId(home, fence, sourceActivationId, nativeSessionId) {
334
- const sourceId = requireIdentity(sourceActivationId, "Provider Activation id");
335
- const store = openCurrentTaskStore(home);
336
- try {
337
- const binding = store.getTaskRoleSessionSet(fence.taskId, fence.roleName)?.providerBinding;
338
- const source = binding?.activations.find(entry => entry.activationId === sourceId);
339
- const original = binding?.activations.find(entry => entry.activationId === fence.runtimeGenerationId);
340
- if (source?.conversationId !== nativeSessionId || original?.conversationId !== nativeSessionId) {
341
- throw new Error("Structured execution observation source does not belong to its native Conversation.");
342
- }
343
- // A reattached collector can observe the old execution, but its current
344
- // attachment must not replace that execution's durable Activation identity.
345
- return original.activationId;
346
- }
347
- finally {
348
- store.close();
349
- }
350
- }
351
383
  async function persistAndApply(home, observations, taskId, roleName) {
352
384
  const inbox = new FileRuntimeEventInbox(home);
353
385
  for (const entry of observations)
@@ -362,17 +394,24 @@ async function persistAndApply(home, observations, taskId, roleName) {
362
394
  let result;
363
395
  try {
364
396
  result = await callController(home, "runtime.observation-apply", entry, {
365
- timeoutMs: 10_000
397
+ // This is only an eager application hint after durable enqueue, not
398
+ // native admission. Bound it like the wake signal so a frozen
399
+ // Controller cannot serialize ten seconds of delay per tool event.
400
+ timeoutMs: 100
366
401
  });
367
402
  }
368
403
  catch (error) {
369
- // Close the race where the handover begins after the first check but
370
- // before this socket call. The durable entry remains pending for replay.
371
- if (isForeignHandoverLockHeld(home))
404
+ // Persistence already succeeded. A stopped, frozen or reconnecting
405
+ // Controller only delays applying this exact observation; it does not
406
+ // fail the native execution or poison its reusable Host.
407
+ if (isForeignHandoverLockHeld(home)
408
+ || (error instanceof ControllerClientError
409
+ && ["CONTROLLER_NOT_RUNNING", "CONTROLLER_UNAVAILABLE", "CONTROLLER_TIMEOUT",
410
+ "CONTROLLER_DELIVERY_UNKNOWN"].includes(error.code)))
372
411
  return;
373
412
  throw error;
374
413
  }
375
- // A fast Provider can accept the initial Turn before the scheduler call
414
+ // A fast Provider can accept the initial AgentRun before the scheduler call
376
415
  // that launched this Host has returned and committed `turn.pushed`. The
377
416
  // immutable inbox entry already makes that exact fenced fact durable;
378
417
  // `deferred` therefore means "retained for replay", not delivery failure.
@@ -315,7 +315,7 @@ function parseTarget(value) {
315
315
  function parseRef(value, label) {
316
316
  const ref = record(value, label);
317
317
  const types = [
318
- "task", "turn", "work-item", "input", "session", "message", "event"
318
+ "task", "run", "work-item", "input", "session", "message", "event"
319
319
  ];
320
320
  if (!types.includes(ref.type))
321
321
  throw new Error(`${label} type is invalid`);
@@ -358,7 +358,7 @@ function copyTarget(target) {
358
358
  };
359
359
  }
360
360
  }
361
- function copyRef(ref) {
361
+ export function copyRef(ref) {
362
362
  if (!("taskId" in ref)) {
363
363
  if (ref.type !== "task" && ref.type !== "session") {
364
364
  throw new Error(`entity reference taskId is required for ${ref.type}`);
@@ -373,7 +373,7 @@ function copyRef(ref) {
373
373
  }
374
374
  function mailboxTaskRecordKind(type) {
375
375
  switch (type) {
376
- case "turn": return "turn";
376
+ case "run": return "run";
377
377
  case "work-item": return "workItem";
378
378
  case "input": return "inputRequest";
379
379
  case "message": return "message";
@@ -1,5 +1,5 @@
1
1
  import { completeProcessing, consumePendingBatch, createWorkMailbox, enqueueSignal, mailboxBatches, mailboxEntityRefKey } from "./workMailbox.js";
2
- const LEGACY_ROLE_TURN_DISPATCH_REASONS = new Set([
2
+ const LEGACY_ROLE_RUN_DISPATCH_REASONS = new Set([
3
3
  "turn-dispatched",
4
4
  "turn-retried",
5
5
  "review-requested",
@@ -19,34 +19,33 @@ export function enqueueWork(store, target, reason, occurredAt, refs = [], metada
19
19
  return queued;
20
20
  }
21
21
  /**
22
- * The sole ordinary Role Turn wake shape. The Turn is durable execution
23
- * authority; this signal only asks the Controller to deliver that exact Turn.
22
+ * The sole ordinary Role AgentRun wake shape. The AgentRun is durable execution
23
+ * authority; this signal only asks the Controller to deliver that exact AgentRun.
24
24
  * Leader is deliberately excluded because its Role mailbox is reserved for
25
- * semantic event wakes and force-steer batches. A Leader active Turn is
25
+ * semantic event wakes and force-steer batches. A Leader active AgentRun is
26
26
  * selected directly from durable state by its targeted Controller pass.
27
27
  */
28
- export function enqueueRoleTurnDispatch(store, input) {
28
+ export function enqueueRoleRunDispatch(store, input) {
29
29
  if (input.roleName === "leader")
30
30
  return null;
31
- return enqueueWork(store, roleTurnTarget(input), input.reason, input.occurredAt, [roleTurnRef(input)], {
31
+ return enqueueWork(store, roleRunTarget(input), input.reason, input.occurredAt, [roleRunRef(input)], {
32
32
  source: "turn-dispatch",
33
- dedupeKey: roleTurnDispatchDedupeKey(input)
33
+ dedupeKey: roleRunDispatchDedupeKey(input)
34
34
  });
35
35
  }
36
36
  /**
37
- * Captures only the mailbox prefix that contains one exact Role Turn dispatch.
37
+ * Captures only the mailbox prefix that contains one exact Role AgentRun dispatch.
38
38
  * A later signal may append while Provider delivery is in flight; its suffix
39
39
  * remains pending when this token is settled.
40
40
  */
41
- export function captureRoleTurnDispatch(mailbox, input) {
42
- if (input.roleName === "leader"
43
- || mailbox === null
41
+ export function captureRoleRunDispatch(mailbox, input) {
42
+ if (mailbox === null
44
43
  || mailbox.target.kind !== "role"
45
44
  || mailbox.target.taskId !== input.taskId
46
45
  || mailbox.target.roleName !== input.roleName) {
47
46
  return null;
48
47
  }
49
- const exactRef = roleTurnRef(input);
48
+ const exactRef = roleRunRef(input);
50
49
  if (mailbox.processing?.executionRef !== undefined
51
50
  && mailboxEntityRefKey(mailbox.processing.executionRef) === mailboxEntityRefKey(exactRef)) {
52
51
  return {
@@ -54,30 +53,34 @@ export function captureRoleTurnDispatch(mailbox, input) {
54
53
  batchId: mailbox.processing.batchId
55
54
  };
56
55
  }
56
+ // A Leader's initial planning batch may be explicitly bound to its Run.
57
+ // Never infer a Leader dispatch from pending semantic notifications.
58
+ if (input.roleName === "leader")
59
+ return null;
57
60
  const pending = mailbox.pending;
58
61
  if (pending === null)
59
62
  return null;
60
- const dedupeKey = roleTurnDispatchDedupeKey(input);
63
+ const dedupeKey = roleRunDispatchDedupeKey(input);
61
64
  if (mailbox.recentDedupeKeys.includes(dedupeKey))
62
65
  return null;
63
66
  const keyIndex = pending.dedupeKeys.indexOf(dedupeKey);
64
67
  if (keyIndex >= 0 && pending.dedupeKeys.length === pending.requestCount) {
65
- const turnSequence = pending.fromSequence + keyIndex;
66
- if (turnSequence <= pending.toSequence) {
68
+ const runSequence = pending.fromSequence + keyIndex;
69
+ if (runSequence <= pending.toSequence) {
67
70
  return {
68
71
  kind: "pending",
69
72
  fromSequence: pending.fromSequence,
70
- toSequence: turnSequence
73
+ toSequence: runSequence
71
74
  };
72
75
  }
73
76
  }
74
77
  // Valid earlier dispatches used sequence-generated dedupe keys and could
75
78
  // include a companion WorkItem ref. Consume that complete legacy batch once
76
- // the exact Turn reaches an accepted or terminal boundary.
79
+ // the exact AgentRun reaches an accepted or terminal boundary.
77
80
  if (pending.requestCount === 1
78
81
  && pending.sources.length === 1
79
82
  && pending.sources[0] === "yui"
80
- && pending.reasons.some((reason) => LEGACY_ROLE_TURN_DISPATCH_REASONS.has(reason))
83
+ && pending.reasons.some((reason) => LEGACY_ROLE_RUN_DISPATCH_REASONS.has(reason))
81
84
  && pending.refs.some((ref) => (mailboxEntityRefKey(ref) === mailboxEntityRefKey(exactRef)))) {
82
85
  return {
83
86
  kind: "pending",
@@ -88,19 +91,19 @@ export function captureRoleTurnDispatch(mailbox, input) {
88
91
  return null;
89
92
  }
90
93
  /**
91
- * Settles one exact ordinary Role Turn dispatch. Provider acceptance is the
94
+ * Settles one exact ordinary Role AgentRun dispatch. Provider acceptance is the
92
95
  * normal boundary; terminalization calls the same operation for conclusively
93
96
  * unaccepted and valid earlier dispatches.
94
97
  */
95
- export function settleRoleTurnDispatch(store, input, expected) {
98
+ export function settleRoleRunDispatch(store, input, expected) {
96
99
  if (expected === null)
97
100
  return "absent";
98
- const target = roleTurnTarget(input);
101
+ const target = roleRunTarget(input);
99
102
  const mailbox = store.getWorkMailbox(target);
100
- const current = captureRoleTurnDispatch(mailbox, input);
103
+ const current = captureRoleRunDispatch(mailbox, input);
101
104
  if (current === null || mailbox === null)
102
105
  return "absent";
103
- if (expected !== undefined && !sameRoleTurnDispatchToken(current, expected)) {
106
+ if (expected !== undefined && !sameRoleRunDispatchToken(current, expected)) {
104
107
  return "state-changed";
105
108
  }
106
109
  const token = expected ?? current;
@@ -135,9 +138,9 @@ export function completeWorkExecution(store, target, executionRef) {
135
138
  /**
136
139
  * Completes a mailbox execution or fails the surrounding transaction.
137
140
  *
138
- * A terminal Turn and its processing mailbox batch are one consistency
141
+ * A terminal AgentRun and its processing mailbox batch are one consistency
139
142
  * boundary. Silently accepting a missing or mismatched batch would leave
140
- * durable work stuck in `processing` after the Turn has already ended.
143
+ * durable work stuck in `processing` after the AgentRun has already ended.
141
144
  */
142
145
  export function requireCompleteWorkExecution(store, target, executionRef) {
143
146
  const mailbox = store.getWorkMailbox(target);
@@ -156,7 +159,7 @@ export function requireCompleteWorkExecution(store, target, executionRef) {
156
159
  + `${executionRef.type}/${executionRef.id}.`);
157
160
  }
158
161
  /**
159
- * Settles the exact Turn delivery boundary, including the short window before
162
+ * Settles the exact AgentRun delivery boundary, including the short window before
160
163
  * the scheduler has claimed its single pending dispatch. A merged pending
161
164
  * batch is never discarded because its signal-to-ref mapping is no longer
162
165
  * recoverable.
@@ -183,24 +186,24 @@ export function settleExactWorkExecution(store, target, executionRef) {
183
186
  function timestamp(value) {
184
187
  return value instanceof Date ? value.toISOString() : value;
185
188
  }
186
- function roleTurnTarget(input) {
189
+ function roleRunTarget(input) {
187
190
  return {
188
191
  kind: "role",
189
192
  taskId: input.taskId,
190
193
  roleName: input.roleName
191
194
  };
192
195
  }
193
- function roleTurnRef(input) {
196
+ function roleRunRef(input) {
194
197
  return {
195
- type: "turn",
198
+ type: "run",
196
199
  taskId: input.taskId,
197
- id: input.turnId
200
+ id: input.runId
198
201
  };
199
202
  }
200
- function roleTurnDispatchDedupeKey(input) {
201
- return `role-turn:${input.taskId}:${input.roleName}:${input.turnId}`;
203
+ function roleRunDispatchDedupeKey(input) {
204
+ return `role-turn:${input.taskId}:${input.roleName}:${input.runId}`;
202
205
  }
203
- function sameRoleTurnDispatchToken(left, right) {
206
+ function sameRoleRunDispatchToken(left, right) {
204
207
  return left.kind === right.kind
205
208
  && (left.kind === "pending"
206
209
  ? right.kind === "pending"
@@ -145,10 +145,15 @@ export class BoundedRpcClient {
145
145
  }
146
146
  #newReadyPromise() {
147
147
  this.#readyFired = false;
148
- return new Promise((resolve, reject) => {
148
+ const ready = new Promise((resolve, reject) => {
149
149
  this.#readyResolve = resolve;
150
150
  this.#readyReject = reject;
151
151
  });
152
+ // Closing during startup is legal even if no request has awaited ready.
153
+ // Observe that rejection without replacing the original promise: send()
154
+ // still receives the failure instead of an invented ready worker.
155
+ void ready.catch(() => undefined);
156
+ return ready;
152
157
  }
153
158
  #workerUrl() {
154
159
  return this.#workerScript instanceof URL
@@ -219,6 +224,8 @@ export class BoundedRpcClient {
219
224
  }
220
225
  // Brief backoff to avoid a hot crash loop.
221
226
  await new Promise((resolve) => setTimeout(resolve, this.#restartBackoffMs));
227
+ if (this.#closed)
228
+ return;
222
229
  this.#generation += 1;
223
230
  this.#port?.close();
224
231
  this.#ready = this.#newReadyPromise();
@@ -102,7 +102,7 @@ export async function callController(home, method, params = {}, options = {}) {
102
102
  * Home identity, PID, and process-start identity; an unprovable process is
103
103
  * never touched.
104
104
  */
105
- export async function stopOrphanedFileTaskController(home, timeoutMs) {
105
+ export async function stopOrphanedFileTaskController(home, timeoutMs, options = {}) {
106
106
  if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1) {
107
107
  throw new TypeError("Controller timeout must be a positive integer.");
108
108
  }
@@ -110,6 +110,11 @@ export async function stopOrphanedFileTaskController(home, timeoutMs) {
110
110
  const candidate = findLiveControllerProcessForHome(homeFilesystemId);
111
111
  if (candidate === undefined)
112
112
  return undefined;
113
+ if ((options.expectedPid !== undefined && candidate.pid !== options.expectedPid)
114
+ || (options.expectedProcessStartIdentity !== undefined
115
+ && candidate.processStartIdentity !== options.expectedProcessStartIdentity)) {
116
+ throw new Error("Controller ownership changed before physical recovery.");
117
+ }
113
118
  if (inspectLiveControllerProcess(candidate.pid, homeFilesystemId, candidate.processStartIdentity) === undefined)
114
119
  return undefined;
115
120
  try {
@@ -121,7 +126,21 @@ export async function stopOrphanedFileTaskController(home, timeoutMs) {
121
126
  throw error;
122
127
  }
123
128
  const deadline = Date.now() + timeoutMs;
129
+ const forceAt = Date.now() + Math.min(1000, timeoutMs / 2);
130
+ let forced = false;
124
131
  while (inspectLiveControllerProcess(candidate.pid, homeFilesystemId, candidate.processStartIdentity) !== undefined) {
132
+ if (options.force && !forced && Date.now() >= forceAt) {
133
+ // The loop revalidates UID, entrypoint, Home and process start identity
134
+ // immediately before escalation. Never signal a successor Controller.
135
+ try {
136
+ process.kill(candidate.pid, "SIGKILL");
137
+ }
138
+ catch (error) {
139
+ if (!isNodeError(error) || error.code !== "ESRCH")
140
+ throw error;
141
+ }
142
+ forced = true;
143
+ }
125
144
  if (Date.now() >= deadline) {
126
145
  throw new ControllerClientError("CONTROLLER_TIMEOUT", `Orphaned Controller did not stop within ${timeoutMs} ms.`);
127
146
  }