@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
@@ -13,20 +13,17 @@ export async function runSessionNotifyCommand(payloadArgument, environment = pro
13
13
  if (params.scope === "global")
14
14
  return;
15
15
  const home = requireText(environment.YUI_HOME, "YUI_HOME");
16
- // A Codex process outlives its Turn, so the notify envelope cannot say which
17
- // Turn or runtime generation is current. Durable Session state answers both;
18
- // the envelope's runtime generation id is used only before a Session has been projected.
19
- const current = currentNotifyGeneration(home, params);
20
- const enqueued = new FileRuntimeEventInbox(home).enqueueTurnTerminal({
16
+ // The caller reports native identity; durable state supplies the current AgentRun.
17
+ const current = currentNotifyRun(home, params);
18
+ const enqueued = new FileRuntimeEventInbox(home).enqueueRunTerminal({
21
19
  scope: params.scope,
22
20
  ...(params.scope === "task" ? { taskId: params.taskId } : {}),
23
21
  roleName: params.roleName,
24
22
  agentId: params.agentId,
25
23
  adapterId: params.adapterId,
26
- ...(current.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: current.runtimeGenerationId }),
27
24
  nativeSessionId: params.nativeSessionId,
28
25
  nativeTurnId: params.nativeTurnId,
29
- ...(current.turnId === undefined ? {} : { turnId: current.turnId }),
26
+ ...(current.runId === undefined ? {} : { runId: current.runId }),
30
27
  ...(params.title === undefined ? {} : { title: params.title }),
31
28
  providerStatus: "completed",
32
29
  outcome: params.outcome
@@ -45,34 +42,32 @@ export async function runSessionNotifyCommand(payloadArgument, environment = pro
45
42
  roleName: params.roleName
46
43
  })
47
44
  }, { timeoutMs: 100 }).catch(() => { });
48
- if (enqueued.created && shouldSetThreadName(home, params, current.turnId)) {
45
+ if (enqueued.created && shouldSetThreadName(home, params, current.runId)) {
49
46
  const request = threadNameRequest(params, environment);
50
47
  if (request !== null)
51
48
  await setThreadName(request).catch(() => { });
52
49
  }
53
50
  }
54
51
  /**
55
- * Reads the durable runtime generation and active Turn for the notifying
56
- * Session. The envelope's runtime generation id only applies before Yui has projected a
57
- * Session for this Role, which is the one moment durable state cannot answer.
52
+ * Resolve the active AgentRun only when the notifying native Session matches.
58
53
  */
59
- function currentNotifyGeneration(home, params) {
54
+ function currentNotifyRun(home, params) {
60
55
  if (params.scope !== "task" || params.taskId === undefined) {
61
- return params.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: params.runtimeGenerationId };
56
+ return {};
62
57
  }
63
58
  try {
64
59
  const store = openCurrentTaskStore(home);
65
60
  const session = store.getTaskRoleSessionSet(params.taskId, params.roleName)
66
61
  ?.sessions[params.agentId];
67
- const activeTurn = store.getActiveTurn(params.taskId, params.roleName);
68
- const runtimeGenerationId = session?.runtimeGenerationId ?? params.runtimeGenerationId;
62
+ const activeRun = store.getActiveRun(params.taskId, params.roleName);
63
+ if (session?.nativeSessionId !== params.nativeSessionId)
64
+ return {};
69
65
  return {
70
- ...(runtimeGenerationId === undefined ? {} : { runtimeGenerationId }),
71
- ...(activeTurn === null ? {} : { turnId: activeTurn.id })
66
+ ...(activeRun === null ? {} : { runId: activeRun.id })
72
67
  };
73
68
  }
74
69
  catch {
75
- return params.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: params.runtimeGenerationId };
70
+ return {};
76
71
  }
77
72
  }
78
73
  export function parseCodexSessionNotification(payloadArgument, environment) {
@@ -95,9 +90,6 @@ export function parseCodexSessionNotification(payloadArgument, environment) {
95
90
  roleName: requireText(environment.YUI_ROLE, "YUI_ROLE"),
96
91
  agentId: requireText(environment.YUI_AGENT_ID, "YUI_AGENT_ID"),
97
92
  adapterId: requireCodexAdapter(environment.YUI_ADAPTER_ID),
98
- ...(environment.YUI_RUNTIME_GENERATION_ID === undefined
99
- ? {}
100
- : { runtimeGenerationId: requireText(environment.YUI_RUNTIME_GENERATION_ID, "YUI_RUNTIME_GENERATION_ID") }),
101
93
  nativeSessionId,
102
94
  nativeTurnId,
103
95
  ...(title === undefined ? {} : { title }),
@@ -138,14 +130,14 @@ function requireText(value, label) {
138
130
  throw new Error(`${label} is invalid.`);
139
131
  return text;
140
132
  }
141
- function shouldSetThreadName(home, params, turnId) {
133
+ function shouldSetThreadName(home, params, runId) {
142
134
  if (params.scope !== "task"
143
135
  || params.title === undefined
144
- || turnId === undefined)
136
+ || runId === undefined)
145
137
  return false;
146
138
  try {
147
139
  const store = openCurrentTaskStore(home);
148
- return store.getTurn(params.taskId, turnId)?.mode === "new";
140
+ return store.getRun(params.taskId, runId)?.mode === "new";
149
141
  }
150
142
  catch {
151
143
  return false;
@@ -1,8 +1,16 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  import { createTaskEvent } from "../event/taskEvent.js";
4
- import { createSessionOwnerIdentity, discoverProviderRootByLaunchEnv, isLinuxProcessLive, listLaunchFencedProcesses, listOwnedProcessTree, readLinuxProcessIdentity, reconcileSessionOwners, terminateSessionOwners } from "../runtime/index.js";
5
- import { removeRuntimeStopReceipt, writeRuntimeStopReceipt } from "../runtime/runtimeStopReceipt.js";
4
+ import { createSessionOwnerIdentity, isLinuxProcessLive, listOwnedProcessTree, readLinuxProcessIdentity, reconcileSessionOwners, terminateSessionOwners } from "../runtime/index.js";
5
+ import { sessionOwnerProcessKey } from "../runtime/sessionOwnerIdentity.js";
6
+ import { AGENT_HOST_CONTROL_PROTOCOL, sendAgentHostCancelControl } from "../runtime/agentHost.js";
7
+ import { settleProviderTurn, cancelQuiescentProviderInput, clearProviderGoal } from "../runtime/providerRuntimeIdentity.js";
8
+ import { updateTaskRoleProviderRuntime, taskRoleControlTarget } from "../executor/agentExecutor.js";
9
+ import { FileRoleLaunchPlanner } from "../executor/fileRoleLaunchPlanner.js";
10
+ import { stopCodexNativeSession } from "../runtime/nativeSessionControl.js";
11
+ import { routeRoleEvent } from "../scheduler/operatorEvent.js";
12
+ import { redactAgentErrorText } from "../runtime/agentError.js";
13
+ import { runtimeCleanupDisposition, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
6
14
  import { tmuxSocketDirectory } from "../tmux/tmuxSocketEndpoint.js";
7
15
  import { yuiTmuxServerName, yuiTmuxSessionName, yuiTmuxTarget } from "../tmux/tmuxManager.js";
8
16
  /**
@@ -16,29 +24,33 @@ export class SessionOwnerReconciliation {
16
24
  #environment;
17
25
  #tmux;
18
26
  #onWarning;
27
+ #cancelInput;
28
+ #nativeConnection;
29
+ #stopNative;
19
30
  constructor(deps) {
20
31
  this.#home = deps.home;
21
32
  this.#store = deps.store;
22
33
  this.#environment = deps.environment ?? process.env;
23
34
  this.#tmux = deps.tmux;
24
35
  this.#onWarning = deps.onWarning ?? (() => undefined);
36
+ this.#cancelInput = deps.cancelInput ?? sendAgentHostCancelControl;
37
+ this.#nativeConnection = deps.nativeConnection ?? ((taskId, roleName) => new FileRoleLaunchPlanner(this.#home, this.#store, { environment: this.#environment })
38
+ .planNativeControl(taskId, roleName));
39
+ this.#stopNative = deps.stopNative ?? stopCodexNativeSession;
25
40
  }
26
41
  /**
27
- * Persists the exact physical owner identity after a host created a new
28
- * Provider process. The Provider root is attributed by the exact
29
- * YUI_RUNTIME_GENERATION_ID environment fence; the tmux pane PID is only a weaker
30
- * fallback when the fence cannot be read.
42
+ * Capture the created pane's concrete process identity. No inherited
43
+ * environment marker is used to discover or claim other applications.
31
44
  */
32
45
  recordHostOwner(input) {
33
- const discovered = discoverProviderRootByLaunchEnv(input.runtimeGenerationId);
34
- const fallback = discovered === undefined && input.panePid !== undefined
46
+ const observed = input.panePid !== undefined
35
47
  ? readLinuxProcessIdentity(input.panePid)
36
48
  : undefined;
37
- const root = discovered ?? (fallback === undefined
49
+ const root = observed === undefined
38
50
  ? undefined
39
- : { pid: fallback.pid, identity: fallback });
51
+ : { pid: observed.pid, identity: observed };
40
52
  if (root === undefined) {
41
- this.#onWarning(`Session owner identity could not attribute a Provider root for launch ${input.runtimeGenerationId}; `
53
+ this.#onWarning(`Session owner identity could not read the Host process for ${input.owner.roleName}; `
42
54
  + "no owner record was written.");
43
55
  return;
44
56
  }
@@ -52,7 +64,6 @@ export class SessionOwnerReconciliation {
52
64
  },
53
65
  agentId: input.agentId,
54
66
  adapterId: input.adapterId,
55
- runtimeGenerationId: input.runtimeGenerationId,
56
67
  ...(input.nativeSessionId === undefined
57
68
  ? {}
58
69
  : { nativeSessionId: input.nativeSessionId }),
@@ -74,7 +85,7 @@ export class SessionOwnerReconciliation {
74
85
  ...(root.identity.processSessionId === undefined
75
86
  ? {}
76
87
  : { processSessionId: root.identity.processSessionId }),
77
- attribution: discovered === undefined ? "pane-pid" : "launch-env"
88
+ attribution: "pane-pid"
78
89
  },
79
90
  ...(input.runtimeRoot === undefined ? {} : { runtimeRoot: input.runtimeRoot }),
80
91
  recordedAt: new Date()
@@ -98,7 +109,7 @@ export class SessionOwnerReconciliation {
98
109
  return undefined;
99
110
  }
100
111
  },
101
- lastStopOutcome: (taskId, roleName, runtimeGenerationId) => (lastSessionTerminationOutcome(this.#store, taskId, roleName, runtimeGenerationId)),
112
+ lastStopOutcome: (taskId, roleName) => (lastSessionTerminationOutcome(this.#store, taskId, roleName)),
102
113
  now: new Date()
103
114
  });
104
115
  }
@@ -108,7 +119,27 @@ export class SessionOwnerReconciliation {
108
119
  */
109
120
  async terminateOwner(owner, options = {}) {
110
121
  const records = this.#store.listSessionOwnersForOwner(owner);
111
- const ports = {
122
+ // Killing a proxy is not cancelling its remote Turn. Settle the exact
123
+ // owned native input before any Host signal or owner-record removal.
124
+ try {
125
+ await this.#quiesceInput(owner);
126
+ }
127
+ catch (error) {
128
+ this.#recordTerminationEvent({ owner, stage: "stop-blocked",
129
+ detail: redactAgentErrorText(error instanceof Error ? error.message : String(error)).slice(0, 2000),
130
+ at: new Date() });
131
+ throw error;
132
+ }
133
+ const result = await terminateSessionOwners(owner, records, this.#terminationPorts(), options);
134
+ if (result.outcome === "stop-confirmed") {
135
+ for (const record of result.confirmed) {
136
+ this.#store.removeSessionOwner(sessionOwnerProcessKey(record));
137
+ }
138
+ }
139
+ return result;
140
+ }
141
+ #terminationPorts() {
142
+ return {
112
143
  gracefulStop: async (target) => {
113
144
  if (this.#tmux === undefined)
114
145
  return false;
@@ -130,52 +161,149 @@ export class SessionOwnerReconciliation {
130
161
  return false;
131
162
  }
132
163
  },
133
- listLaunchFencedProcesses: (runtimeGenerationId) => listLaunchFencedProcesses(runtimeGenerationId),
134
164
  signalProcess: (pid, signal) => process.kill(pid, signal),
135
- signalProcessGroup: (processGroupId, signal) => {
136
- try {
137
- process.kill(-processGroupId, signal);
138
- }
139
- catch (error) {
140
- if (error.code !== "ESRCH")
141
- throw error;
142
- }
143
- },
144
165
  sleep: (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)),
145
166
  emit: (event) => this.#recordTerminationEvent(event),
146
167
  now: () => new Date()
147
168
  };
148
- const result = await terminateSessionOwners(owner, records, ports, options);
149
- if (result.outcome === "stop-confirmed") {
150
- for (const record of result.confirmed) {
151
- this.#store.removeSessionOwner(record.runtimeGenerationId);
152
- removeRuntimeStopReceipt(this.#home, record.runtimeGenerationId);
169
+ }
170
+ async #quiesceInput(owner) {
171
+ if (owner.scope !== "task")
172
+ return;
173
+ if (runtimeCleanupDisposition(this.#store.getWorkMailbox(runtimeLifecycleTarget(owner))) === "detach-host")
174
+ return;
175
+ const set = this.#store.getTaskRoleSessionSet(owner.taskId, owner.roleName);
176
+ const binding = set?.providerBinding;
177
+ const input = binding?.run;
178
+ const unsettled = input != null && ["submitting", "accepted", "delivery-unknown"].includes(input.status);
179
+ const hasGoal = binding?.goal != null && binding.goal.status !== "complete";
180
+ const selected = taskRoleControlTarget(set);
181
+ if (set == null || (!unsettled && !hasGoal && selected?.adapterId !== "codex"))
182
+ return;
183
+ if (selected === undefined) {
184
+ throw new Error("Cannot identify the native execution to stop.");
185
+ }
186
+ const request = this.#store.listEvents(owner.taskId).filter(event => ["runtime.session-replacement-requested", "runtime.session-stop-requested"].includes(event.type)
187
+ && event.payload.roleName === owner.roleName
188
+ && event.payload.nativeSessionId === selected.nativeSessionId).at(-1);
189
+ const operatorStop = this.#store.getTask(owner.taskId)?.executionGate.state === "stopped"
190
+ || (request !== undefined && ["user", "operator"].includes(request.payload.requestedBy));
191
+ if (binding?.authority.owner === "human" && !operatorStop) {
192
+ throw new Error("This native Session is under human control; Operator/user must request its stop or replacement.");
193
+ }
194
+ let terminal;
195
+ try {
196
+ const result = unsettled && binding?.authority.owner === "controller" && binding.authority.holderId !== undefined ? await this.#cancelInput({
197
+ home: this.#home, scope: "task", taskId: owner.taskId, roleName: owner.roleName,
198
+ control: {
199
+ protocol: AGENT_HOST_CONTROL_PROTOCOL, type: "cancel",
200
+ nativeSessionId: selected.nativeSessionId,
201
+ attemptId: input.attemptId, authority: {
202
+ epoch: binding.authority.epoch, owner: "controller", holderId: binding.authority.holderId
203
+ }
204
+ }
205
+ }) : undefined;
206
+ const proof = result?.cancellation?.terminal;
207
+ if (result?.cancellation?.status !== "unknown" && proof?.clientOwned
208
+ && proof.attemptId === input?.attemptId && proof.nativeSessionId === selected.nativeSessionId
209
+ && (input?.nativeTurnId === undefined || proof.nativeTurnId === input.nativeTurnId))
210
+ terminal = proof;
211
+ }
212
+ catch {
213
+ // Recovery follows the recorded native identity, not the availability of
214
+ // the disposable Host which used to own its control socket.
215
+ }
216
+ if (terminal === undefined || hasGoal || selected.adapterId === "codex") {
217
+ if (selected.adapterId === "codex") {
218
+ await this.#stopNative(this.#nativeConnection(owner.taskId, owner.roleName), {
219
+ conversationId: selected.nativeSessionId,
220
+ nativeTurnId: unsettled && terminal === undefined ? input?.nativeTurnId : undefined,
221
+ clearGoal: true
222
+ });
223
+ }
224
+ else if (selected.adapterId === "claude") {
225
+ const records = this.#store.listSessionOwnersForOwner(owner);
226
+ const children = records.filter(record => record.nativeSessionId === selected.nativeSessionId
227
+ && record.providerRoot.attribution === "owned-child");
228
+ if (children.length > 0) {
229
+ const stopped = await terminateSessionOwners(owner, children, this.#terminationPorts());
230
+ if (stopped.outcome !== "stop-confirmed")
231
+ throw new Error("Dedicated native execution is still draining; no resource was released.");
232
+ }
233
+ else if (selected.status !== "ended"
234
+ || records.some(ownerRootIsLive)
235
+ || this.#tmux?.probeRoleStatus(owner.taskId, owner.roleName) !== "exited") {
236
+ throw new Error("Native process custody is unavailable; inspect the exact local execution before reusing its workspace.");
237
+ }
238
+ }
239
+ else {
240
+ throw new Error("This Provider has no detached native control proof; inspect its execution resources before replacement.");
153
241
  }
154
242
  }
155
- return result;
243
+ this.#store.transaction(tx => {
244
+ const current = tx.getTaskRoleSessionSet(owner.taskId, owner.roleName);
245
+ const provider = current?.providerBinding;
246
+ if (current == null || provider?.run?.attemptId !== input?.attemptId
247
+ || (selected.fromBinding
248
+ ? current.providerBinding?.conversations.find(entry => entry.status === "current")?.conversationId
249
+ : current.sessions[current.activeAgentId]?.nativeSessionId) !== selected.nativeSessionId
250
+ || provider?.authority.epoch !== binding?.authority.epoch) {
251
+ throw new Error("Native input identity changed while confirming its stop.");
252
+ }
253
+ if (provider != null && (provider.run != null && ["submitting", "accepted", "delivery-unknown"].includes(provider.run.status)
254
+ || hasGoal || selected.adapterId === "codex")) {
255
+ const now = new Date();
256
+ let stopped = provider;
257
+ if (unsettled && input != null) {
258
+ stopped = terminal !== undefined && provider.run?.status === "accepted"
259
+ ? settleProviderTurn(provider, { attemptId: input.attemptId, nativeTurnId: terminal.nativeTurnId,
260
+ status: terminal.status, settledAt: now.toISOString() })
261
+ : cancelQuiescentProviderInput(provider, { attemptId: input.attemptId, cancelledAt: now.toISOString(),
262
+ reason: "Explicit Session stop; native execution quiescence independently verified." });
263
+ }
264
+ if (hasGoal || selected.adapterId === "codex")
265
+ stopped = clearProviderGoal(stopped);
266
+ tx.saveTaskRoleSessionSet(updateTaskRoleProviderRuntime(current, stopped, now));
267
+ tx.saveEvent(owner.taskId, createTaskEvent(tx.nextEventId(owner.taskId), owner.taskId, "runtime.input-stop-confirmed", {
268
+ roleName: owner.roleName, ...(input == null ? {} : { attemptId: input.attemptId }),
269
+ nativeSessionId: selected.nativeSessionId, status: stopped.run?.status ?? "quiescent",
270
+ evidence: terminal === undefined ? "native-resource-inspection" : "native-terminal",
271
+ ...(input?.nativeTurnId === undefined ? {} : { nativeTurnId: input.nativeTurnId })
272
+ }, now));
273
+ }
274
+ else if (selected.adapterId === "codex") {
275
+ tx.saveEvent(owner.taskId, createTaskEvent(tx.nextEventId(owner.taskId), owner.taskId, "runtime.input-stop-confirmed", {
276
+ roleName: owner.roleName, nativeSessionId: selected.nativeSessionId,
277
+ status: "quiescent", evidence: "native-resource-inspection"
278
+ }, new Date()));
279
+ }
280
+ });
156
281
  }
157
282
  #recordTerminationEvent(event) {
158
283
  const owner = event.owner;
159
- if (event.stage === "stop-requested" && event.runtimeGenerationId !== undefined) {
160
- writeRuntimeStopReceipt(this.#home, event.runtimeGenerationId, event.at);
161
- }
162
284
  if (owner.scope !== "task")
163
285
  return;
164
286
  try {
165
- this.#store.saveEvent(owner.taskId, createTaskEvent(this.#store.nextEventId(owner.taskId), owner.taskId, "runtime.session-termination", {
287
+ const last = this.#store.listEvents(owner.taskId).filter(entry => entry.type === "runtime.session-termination" && entry.payload.roleName === owner.roleName).at(-1);
288
+ if (event.stage === "stop-blocked" && last?.payload.outcome === event.stage
289
+ && last.payload.detail === event.detail)
290
+ return;
291
+ const fact = createTaskEvent(this.#store.nextEventId(owner.taskId), owner.taskId, "runtime.session-termination", {
166
292
  roleName: owner.roleName,
167
- runtimeGenerationId: event.runtimeGenerationId ?? "",
168
293
  nativeSessionId: event.nativeSessionId ?? "",
169
294
  outcome: event.stage,
170
295
  ...(event.detail === undefined ? {} : { detail: event.detail })
171
- }, event.at));
296
+ }, event.at);
297
+ this.#store.saveEvent(owner.taskId, fact);
298
+ if (event.stage === "stop-blocked")
299
+ routeRoleEvent(this.#store, fact, owner.roleName, "session-recovery-blocked", event.at);
172
300
  }
173
301
  catch (error) {
174
302
  this.#onWarning(`Session termination event could not be persisted: ${error instanceof Error ? error.message : String(error)}`);
175
303
  }
176
304
  }
177
305
  }
178
- /** Projects every durable Role runtime generation for reconciliation. */
306
+ /** Projects every durable Role runtime for reconciliation. */
179
307
  export function durableSessionFacts(store) {
180
308
  const facts = [];
181
309
  for (const task of store.listTasks()) {
@@ -187,7 +315,6 @@ export function durableSessionFacts(store) {
187
315
  roleName: set.owner.roleName,
188
316
  agentId,
189
317
  adapterId: session.adapterId,
190
- ...(session.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId }),
191
318
  ...(session.nativeSessionId === undefined
192
319
  ? {}
193
320
  : { nativeSessionId: session.nativeSessionId }),
@@ -202,7 +329,6 @@ export function durableSessionFacts(store) {
202
329
  roleName: set.owner.roleName,
203
330
  agentId: history.agentId,
204
331
  adapterId: history.adapterId,
205
- ...(history.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: history.runtimeGenerationId }),
206
332
  ...(history.nativeSessionId === undefined
207
333
  ? {}
208
334
  : { nativeSessionId: history.nativeSessionId }),
@@ -219,7 +345,6 @@ export function durableSessionFacts(store) {
219
345
  roleName: set.owner.roleName,
220
346
  agentId,
221
347
  adapterId: session.adapterId,
222
- ...(session.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId }),
223
348
  ...(session.nativeSessionId === undefined
224
349
  ? {}
225
350
  : { nativeSessionId: session.nativeSessionId }),
@@ -234,7 +359,6 @@ export function durableSessionFacts(store) {
234
359
  roleName: set.owner.roleName,
235
360
  agentId: session.agentId,
236
361
  adapterId: session.adapterId,
237
- ...(session.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId }),
238
362
  ...(session.nativeSessionId === undefined
239
363
  ? {}
240
364
  : { nativeSessionId: session.nativeSessionId }),
@@ -296,8 +420,8 @@ export function observeSessionOwnerPhysical(record) {
296
420
  childCount: Math.max(0, tree.length - 1)
297
421
  };
298
422
  }
299
- /** Reads the latest termination outcome recorded for one generation. */
300
- export function lastSessionTerminationOutcome(store, taskId, roleName, runtimeGenerationId) {
423
+ /** Reads the latest termination outcome recorded for one Role. */
424
+ export function lastSessionTerminationOutcome(store, taskId, roleName) {
301
425
  if (taskId === undefined)
302
426
  return undefined;
303
427
  let latest;
@@ -306,12 +430,6 @@ export function lastSessionTerminationOutcome(store, taskId, roleName, runtimeGe
306
430
  continue;
307
431
  if (event.payload.roleName !== roleName)
308
432
  continue;
309
- if (runtimeGenerationId !== ""
310
- && event.payload.runtimeGenerationId !== undefined
311
- && event.payload.runtimeGenerationId !== ""
312
- && event.payload.runtimeGenerationId !== runtimeGenerationId) {
313
- continue;
314
- }
315
433
  latest = event.payload.outcome;
316
434
  }
317
435
  return latest;