@zq-silk/yui 0.15.6 → 0.15.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (282) hide show
  1. package/ARCHITECTURE.md +192 -399
  2. package/README.md +127 -1149
  3. package/dist/agent/adapterCatalog.js +15 -2
  4. package/dist/agent/agent.js +23 -3
  5. package/dist/agent/argumentPolicy.js +7 -1
  6. package/dist/agent/connectionPlan.js +62 -0
  7. package/dist/agent/executionComponents.js +158 -0
  8. package/dist/agent/launchEnvironment.js +31 -3
  9. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  10. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  11. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  12. package/dist/brief/taskBrief.js +12 -0
  13. package/dist/cli/agentConfigurationPicker.js +13 -0
  14. package/dist/cli/commandCatalog.js +167 -70
  15. package/dist/cli/interactionCandidates.js +5 -5
  16. package/dist/cli/interactionPolicy.js +38 -8
  17. package/dist/cli/invocationRouter.js +1 -1
  18. package/dist/cli/managedDiagnostics.js +28 -0
  19. package/dist/cli/operatorWizard.js +1 -7
  20. package/dist/cli/roleOptionOrder.js +27 -0
  21. package/dist/cli/roleWizard.js +50 -14
  22. package/dist/cli/updateOrchestrator.js +1 -1
  23. package/dist/cli/updatePorts.js +3 -4
  24. package/dist/cli.js +188 -95
  25. package/dist/commands/agentCommands.js +72 -14
  26. package/dist/commands/capabilityCommands.js +57 -0
  27. package/dist/commands/configCommands.js +20 -20
  28. package/dist/commands/deliveryGuardPreflight.js +2 -2
  29. package/dist/commands/executionAuditCommands.js +24 -24
  30. package/dist/commands/globalRoleCommands.js +1 -1
  31. package/dist/commands/grantCommands.js +4 -4
  32. package/dist/commands/operatorCommands.js +1 -7
  33. package/dist/commands/projectCommands.js +4 -4
  34. package/dist/commands/resourcesCommands.js +2 -2
  35. package/dist/commands/roleConfiguration.js +25 -5
  36. package/dist/commands/roleRuntimeGuard.js +4 -5
  37. package/dist/commands/sessionCommands.js +3 -7
  38. package/dist/commands/taskActivationCommands.js +259 -0
  39. package/dist/commands/taskActor.js +28 -49
  40. package/dist/commands/taskCommands.js +1216 -730
  41. package/dist/commands/taskContextCommand.js +39 -583
  42. package/dist/commands/taskExecutionCommands.js +32 -32
  43. package/dist/commands/taskInputCommands.js +40 -104
  44. package/dist/commands/taskIntegrationCommands.js +3 -2
  45. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  46. package/dist/commands/taskNextActionCommand.js +8 -8
  47. package/dist/commands/taskOverviewCommand.js +33 -45
  48. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  49. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  50. package/dist/commands/telemetryCommands.js +36 -38
  51. package/dist/config/configCatalog.js +4 -4
  52. package/dist/config/yuiConfig.js +8 -8
  53. package/dist/context/contextSnapshot.js +10 -10
  54. package/dist/context/dispatchContext.js +11 -11
  55. package/dist/context/roleSessionContext.js +6 -3
  56. package/dist/context/{turnContextPack.js → runContextPack.js} +146 -81
  57. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  58. package/dist/context/sessionBootstrapManifest.js +21 -2
  59. package/dist/context/sourceRunContext.js +30 -0
  60. package/dist/context/taskContext.js +458 -0
  61. package/dist/context/wakeNotification.js +27 -27
  62. package/dist/controller/agentRuntimeObserver.js +21 -24
  63. package/dist/controller/capabilityBridge.js +77 -0
  64. package/dist/controller/clientRuntime.js +65 -92
  65. package/dist/controller/controller.js +127 -188
  66. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  67. package/dist/controller/jobControl.js +54 -85
  68. package/dist/controller/resourceInventory.js +8 -27
  69. package/dist/controller/resourceInventoryLinux.js +12 -13
  70. package/dist/controller/runtime.js +530 -476
  71. package/dist/controller/runtimeEventInbox.js +55 -25
  72. package/dist/controller/runtimeEventProcessor.js +22 -31
  73. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  74. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  75. package/dist/controller/runtimeObservationHook.js +14 -18
  76. package/dist/controller/sessionNotify.js +16 -24
  77. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  78. package/dist/controller/structuredProviderObservation.js +138 -99
  79. package/dist/coordination/workMailbox.js +3 -3
  80. package/dist/coordination/workMailboxQueue.js +36 -33
  81. package/dist/core/boundedRpc.js +8 -1
  82. package/dist/core/controllerClient.js +20 -1
  83. package/dist/core/controllerServer.js +4 -4
  84. package/dist/doctor/doctor.js +13 -2
  85. package/dist/domain/agentResultTransport.js +9 -9
  86. package/dist/execution/codexThreadNaming.js +2 -8
  87. package/dist/execution/executionHealth.js +51 -63
  88. package/dist/execution/reviewMainRun.js +137 -0
  89. package/dist/execution/workItemExecution.js +28 -29
  90. package/dist/execution/workItemExecutionProjection.js +99 -107
  91. package/dist/execution/workItemMainRun.js +141 -0
  92. package/dist/executor/agentAdapter.js +227 -20
  93. package/dist/executor/agentConfigurationCatalog.js +126 -4
  94. package/dist/executor/agentConfigurationProbe.js +162 -4
  95. package/dist/executor/agentExecutor.js +79 -78
  96. package/dist/executor/effectiveLaunch.js +105 -18
  97. package/dist/executor/executorRegistry.js +29 -44
  98. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  99. package/dist/executor/workspacePreflightClassification.js +16 -16
  100. package/dist/grant/capabilityGrant.js +6 -3
  101. package/dist/input/inputRequest.js +12 -10
  102. package/dist/integration/gitIntegrationService.js +4 -11
  103. package/dist/integration/integrationQueueService.js +4 -4
  104. package/dist/interaction/operatorPresentation.js +1 -1
  105. package/dist/kernel/builtinCapabilities.js +423 -0
  106. package/dist/kernel/capabilityRegistry.js +314 -0
  107. package/dist/kernel/capabilitySchema.js +91 -0
  108. package/dist/kernel/instanceHost.js +18 -1
  109. package/dist/kernel/kernelPorts.js +4 -1
  110. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  111. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  112. package/dist/message/message.js +62 -6
  113. package/dist/message/messageContinuation.js +204 -0
  114. package/dist/observability/executionAudit.js +70 -72
  115. package/dist/observability/faultClassification.js +2 -2
  116. package/dist/observability/orchestrationMetrics.js +8 -8
  117. package/dist/operator/operatorSessionHistory.js +1 -7
  118. package/dist/output/agentConfigurationPresentation.js +8 -3
  119. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  120. package/dist/output/rolePresentation.js +54 -3
  121. package/dist/plugins/pluginChild.js +104 -0
  122. package/dist/plugins/pluginIntent.js +26 -0
  123. package/dist/plugins/pluginInterpreter.js +43 -0
  124. package/dist/plugins/pluginPackage.js +101 -0
  125. package/dist/plugins/pluginProcess.js +112 -0
  126. package/dist/plugins/pluginService.js +380 -0
  127. package/dist/profile/agentProfile.js +1 -1
  128. package/dist/repository/gitWorkspace.js +26 -4
  129. package/dist/repository/project.js +19 -4
  130. package/dist/repository/taskBaseFreshness.js +13 -13
  131. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  132. package/dist/repository/taskWorkspacePreparer.js +344 -83
  133. package/dist/resources/autoResourceGc.js +3 -3
  134. package/dist/resources/liveReferences.js +3 -3
  135. package/dist/resources/projectResource.js +123 -0
  136. package/dist/resources/projectResourceService.js +421 -0
  137. package/dist/resources/resourceDiscovery.js +6 -6
  138. package/dist/resources/resourceGc.js +1 -1
  139. package/dist/resources/resourceRegistrar.js +1 -1
  140. package/dist/resources/resourceTypes.js +1 -1
  141. package/dist/review/deltaRecheck.js +3 -3
  142. package/dist/review/reviewAcceptance.js +16 -16
  143. package/dist/review/reviewDecision.js +7 -7
  144. package/dist/review/reviewRound.js +21 -20
  145. package/dist/review/reviewerAvailability.js +2 -2
  146. package/dist/role/role.js +51 -7
  147. package/dist/role/taskRoleUpdate.js +30 -0
  148. package/dist/runtime/acpProtocol.js +425 -0
  149. package/dist/runtime/acpSession.js +731 -0
  150. package/dist/runtime/acpSessionConfiguration.js +260 -0
  151. package/dist/runtime/agentDriver.js +30 -11
  152. package/dist/runtime/agentEndpoint.js +278 -0
  153. package/dist/runtime/agentEndpointIdentity.js +86 -0
  154. package/dist/runtime/agentEndpointOwnership.js +239 -0
  155. package/dist/runtime/agentError.js +2 -10
  156. package/dist/runtime/agentHost.js +565 -314
  157. package/dist/runtime/agentRunConfiguration.js +258 -0
  158. package/dist/runtime/builtinAgentDrivers.js +134 -18
  159. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  160. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  161. package/dist/runtime/claude-process-owner +0 -0
  162. package/dist/runtime/codexAppServerRuntime.js +38 -30
  163. package/dist/runtime/codexInteractiveHost.js +41 -6
  164. package/dist/runtime/continuationManager.js +2 -6
  165. package/dist/runtime/executionEnvironment.js +30 -0
  166. package/dist/runtime/firstProgressAdvisory.js +11 -11
  167. package/dist/runtime/index.js +4 -3
  168. package/dist/runtime/jsonLineChannel.js +109 -0
  169. package/dist/runtime/launchBroker.js +91 -16
  170. package/dist/runtime/launchDiagnostics.js +2 -2
  171. package/dist/runtime/lifecycleReservation.js +10 -18
  172. package/dist/runtime/managedCaller.js +61 -17
  173. package/dist/runtime/nativeSessionControl.js +102 -0
  174. package/dist/runtime/ports.js +6 -21
  175. package/dist/runtime/processExitObservation.js +8 -7
  176. package/dist/runtime/promptEnvelope.js +17 -6
  177. package/dist/runtime/providerContinuation.js +3 -9
  178. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  179. package/dist/runtime/providerControl.js +2 -7
  180. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  181. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  182. package/dist/runtime/runtimeBinding.js +0 -1
  183. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  184. package/dist/runtime/runtimeDeadlines.js +9 -0
  185. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  186. package/dist/runtime/runtimeObservation.js +29 -65
  187. package/dist/runtime/runtimeProjection.js +43 -51
  188. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  189. package/dist/runtime/sessionLaunchRequest.js +3 -7
  190. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  191. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  192. package/dist/runtime/sessionReconciliation.js +4 -8
  193. package/dist/runtime/sessionTerminationGuard.js +70 -259
  194. package/dist/runtime/sessionTokenMetrics.js +5 -16
  195. package/dist/runtime/structuredProviderHost.js +237 -117
  196. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  197. package/dist/runtime/tmuxAdapters.js +39 -86
  198. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  199. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  200. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  201. package/dist/scheduler/ports.js +80 -9
  202. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  203. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  204. package/dist/scheduler/taskExecutionProjection.js +120 -124
  205. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  206. package/dist/scheduler/taskWake.js +11 -4
  207. package/dist/scheduler/wakeReason.js +9 -1
  208. package/dist/setup/setupCommand.js +1 -0
  209. package/dist/storage/migrations/agentRunContract.js +159 -0
  210. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  211. package/dist/storage/sqliteSchema.js +431 -5
  212. package/dist/storage/sqliteStore.js +375 -220
  213. package/dist/storage/storageVersions.js +1 -1
  214. package/dist/storage/storeRpc.js +10 -5
  215. package/dist/storage/taskStore.js +13 -11
  216. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  217. package/dist/surface/surfaceContributions.js +102 -0
  218. package/dist/task/completionReadiness.js +32 -6
  219. package/dist/task/deliveryGuard.js +16 -16
  220. package/dist/task/draftPlan.js +72 -12
  221. package/dist/task/nextAction.js +144 -128
  222. package/dist/task/remoteDelivery.js +6 -6
  223. package/dist/task/task.js +184 -18
  224. package/dist/task/taskActivation.js +301 -0
  225. package/dist/task/taskActivationService.js +392 -0
  226. package/dist/task/taskRecordReference.js +5 -4
  227. package/dist/task/taskRecordRetirement.js +1 -1
  228. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  229. package/dist/telemetry/telemetryConfig.js +14 -14
  230. package/dist/telemetry/telemetryWiring.js +2 -2
  231. package/dist/web/assets/assetManifest.js +2 -0
  232. package/dist/web/assets/client/app.js +120 -20
  233. package/dist/web/assets/client/components.js +87 -54
  234. package/dist/web/assets/client/i18n.js +83 -41
  235. package/dist/web/assets/client/markdown.js +1 -1
  236. package/dist/web/assets/client/taskSurface.js +353 -0
  237. package/dist/web/assets/client/view.js +49 -44
  238. package/dist/web/assets/shell.js +1 -1
  239. package/dist/web/assets/styles/cards.js +22 -4
  240. package/dist/web/controllerWeb.js +60 -0
  241. package/dist/web/webMutation.js +28 -0
  242. package/dist/web/webServer.js +118 -8
  243. package/dist/web/webSnapshot.js +81 -74
  244. package/dist/web/webTaskSurface.js +64 -0
  245. package/dist/workItem/dependencyGate.js +1 -1
  246. package/dist/workItem/workItem.js +80 -48
  247. package/dist/workspace/workItemChangeSetManager.js +16 -9
  248. package/docs/agent-result-consumption.md +94 -0
  249. package/docs/agent-runtime-drivers.md +91 -0
  250. package/docs/architecture/README.md +38 -0
  251. package/docs/architecture/capabilities-and-resources.md +79 -0
  252. package/docs/managed-turn-and-session-runtime.md +222 -0
  253. package/docs/observability/README.md +81 -0
  254. package/docs/plugin-sdk.md +290 -0
  255. package/docs/provider-runtime.md +163 -0
  256. package/docs/release-workflow.md +303 -0
  257. package/docs/roles-and-configuration.md +113 -0
  258. package/docs/sqlite-control-plane-design.md +76 -0
  259. package/docs/task-dag-semantics.md +57 -0
  260. package/docs/task-delivery.md +103 -0
  261. package/docs/task-local-identity.md +6 -6
  262. package/docs/testing/verification-levels.md +86 -0
  263. package/i18n/README.zh-CN.md +98 -739
  264. package/package.json +5 -5
  265. package/skills/yui-leader/SKILL.md +130 -103
  266. package/skills/yui-leader/references/integration.md +39 -0
  267. package/skills/yui-leader/references/replicated-execution.md +42 -0
  268. package/skills/yui-leader/references/task-plugins.md +33 -0
  269. package/skills/yui-operator/SKILL.md +30 -59
  270. package/skills/yui-reviewer/SKILL.md +35 -36
  271. package/skills/yui-runtime/SKILL.md +88 -24
  272. package/skills/yui-runtime/references/publication.md +22 -0
  273. package/skills/yui-runtime/references/recovery.md +64 -0
  274. package/skills/yui-worker/SKILL.md +37 -39
  275. package/dist/cli/roleOptionCatalog.js +0 -68
  276. package/dist/context/sourceTurnContext.js +0 -30
  277. package/dist/execution/reviewMainTurn.js +0 -161
  278. package/dist/execution/workItemMainTurn.js +0 -164
  279. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  280. package/dist/runtime/preallocatedNativeSession.js +0 -13
  281. package/dist/runtime/runtimeStopReceipt.js +0 -42
  282. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -22,7 +22,7 @@ const MAX_DETAIL_CHARS = 1_000;
22
22
  const SECRET_VALUE_PATTERN = /(api[_-]?key|access[_-]?token|refresh[_-]?token|secret|password|passwd|cookie|authorization)(\s*[=:]\s*)([^\s,;]+)/gi;
23
23
  // Word boundary keeps "task-5-…" workspace paths from being mistaken for keys.
24
24
  const OPENAI_KEY_PATTERN = /\bsk-[A-Za-z0-9_-]{6,}/gu;
25
- /** A bounded, single-line, secret-redacted launch failure for Turn summaries. */
25
+ /** A bounded, single-line, secret-redacted launch failure for AgentRun summaries. */
26
26
  export class RuntimeLaunchFailure extends Error {
27
27
  diagnostic;
28
28
  name = "RuntimeLaunchFailure";
@@ -84,7 +84,7 @@ export function formatRuntimeLaunchDiagnostic(diagnostic) {
84
84
  }
85
85
  if (diagnostic.hint !== undefined)
86
86
  fields.push(`hint=${JSON.stringify(diagnostic.hint)}`);
87
- return `Role Turn could not start: ${fields.join(" ")}`;
87
+ return `Role AgentRun could not start: ${fields.join(" ")}`;
88
88
  }
89
89
  export function redactLaunchArgument(value) {
90
90
  return tail(redactLaunchText(value), MAX_ARGUMENT_CHARS);
@@ -1,14 +1,14 @@
1
1
  import { mailboxHasWork } from "../coordination/workMailbox.js";
2
2
  export const RUNTIME_LIFECYCLE_OWNER = "runtime-lifecycle";
3
- export const RUNTIME_LAUNCH_RESERVED_REASON = "runtime-launch-reserved";
4
3
  export const RUNTIME_CLEANUP_REQUIRED_REASON = "runtime-cleanup-required";
5
4
  export const RUNTIME_HOST_DETACH_REQUIRED_REASON = "runtime-host-detach-required";
5
+ export const RUNTIME_SESSION_REPLACE_REQUIRED_REASON = "runtime-session-replace-required";
6
6
  /**
7
- * A Role runtime lifecycle lane already holds an in-flight operation (a
8
- * launch reservation or a cleanup obligation). This is scheduler
9
- * backpressure: the equivalent wake/Turn must be retried after the lane
10
- * settles. It is never grounds to terminalize a Turn, because the contention
11
- * happens before (or outside) any semantic Turn launch.
7
+ * A Role runtime lifecycle lane already holds an explicit cleanup obligation.
8
+ * This is scheduler
9
+ * backpressure: the equivalent wake/AgentRun must be retried after the lane
10
+ * settles. It is never grounds to terminalize a AgentRun, because the contention
11
+ * happens before (or outside) any semantic AgentRun launch.
12
12
  */
13
13
  export class RuntimeLifecycleBusyError extends Error {
14
14
  name = "RuntimeLifecycleBusyError";
@@ -33,15 +33,6 @@ export function runtimeLifecycleSignalKey(owner) {
33
33
  ? `role:${encodeURIComponent(owner.taskId)}/${encodeURIComponent(owner.roleName)}`
34
34
  : `global-role:${encodeURIComponent(owner.roleName)}`;
35
35
  }
36
- export function isRuntimeLaunchReservation(processing, runtimeGenerationId) {
37
- return processing?.owner === RUNTIME_LIFECYCLE_OWNER
38
- && processing.batch.reasons.length === 1
39
- && processing.batch.reasons[0] === RUNTIME_LAUNCH_RESERVED_REASON
40
- && (runtimeGenerationId === undefined || processing.batchId === runtimeGenerationId);
41
- }
42
- export function hasRuntimeLaunchReservation(mailbox) {
43
- return isRuntimeLaunchReservation(mailbox?.processing);
44
- }
45
36
  export function hasRuntimeCleanupObligation(mailbox) {
46
37
  return runtimeCleanupDisposition(mailbox) !== null;
47
38
  }
@@ -49,10 +40,10 @@ export function hasRuntimeCleanupObligation(mailbox) {
49
40
  export function runtimeCleanupDisposition(mailbox) {
50
41
  const reasons = [
51
42
  ...(mailbox?.pending?.reasons ?? []),
52
- ...(!isRuntimeLaunchReservation(mailbox?.processing)
53
- ? mailbox?.processing?.batch.reasons ?? []
54
- : [])
43
+ ...(mailbox?.processing?.batch.reasons ?? [])
55
44
  ];
45
+ if (reasons.includes(RUNTIME_SESSION_REPLACE_REQUIRED_REASON))
46
+ return "replace-session";
56
47
  if (reasons.includes(RUNTIME_CLEANUP_REQUIRED_REASON))
57
48
  return "end-session";
58
49
  if (reasons.includes(RUNTIME_HOST_DETACH_REQUIRED_REASON))
@@ -61,6 +52,7 @@ export function runtimeCleanupDisposition(mailbox) {
61
52
  }
62
53
  export function isRuntimeCleanupReason(reason) {
63
54
  return reason === RUNTIME_CLEANUP_REQUIRED_REASON
55
+ || reason === RUNTIME_SESSION_REPLACE_REQUIRED_REASON
64
56
  || reason === RUNTIME_HOST_DETACH_REQUIRED_REASON;
65
57
  }
66
58
  export function hasRuntimeLifecycleWork(mailbox) {
@@ -1,7 +1,7 @@
1
- import { createHash } from "node:crypto";
2
1
  import { activeRoleAgentBinding } from "../role/role.js";
3
- /** Per-process credential injected at native Session launch. */
4
- export const MANAGED_CALLER_KEY_ENV = "YUI_JOB_CALLER_KEY";
2
+ import { currentProviderConversation } from "./providerRuntimeIdentity.js";
3
+ /** Native Session identity supplied by the Agent transport. */
4
+ export const MANAGED_NATIVE_SESSION_ENV = "YUI_NATIVE_SESSION_ID";
5
5
  /**
6
6
  * A managed Session presented valid self-identity but is no longer the current
7
7
  * runtime of its Task Role. This is a bounded diagnosis rather than a bare
@@ -25,12 +25,12 @@ export function managedTaskSessionIdentity(environment) {
25
25
  throw new ManagedRuntimeDriftError("Managed Task Session identity is incomplete: YUI_TASK_ID and YUI_ROLE are required.");
26
26
  }
27
27
  const workspace = identity(env.YUI_WORKSPACE);
28
- const callerKey = identity(env[MANAGED_CALLER_KEY_ENV]);
28
+ const nativeSessionId = identity(env.CODEX_THREAD_ID ?? env[MANAGED_NATIVE_SESSION_ENV]);
29
29
  return Object.freeze({
30
30
  taskId,
31
31
  roleName,
32
32
  ...(workspace === undefined ? {} : { workspace }),
33
- ...(callerKey === undefined ? {} : { callerKey })
33
+ ...(nativeSessionId === undefined ? {} : { nativeSessionId })
34
34
  });
35
35
  }
36
36
  /**
@@ -52,6 +52,29 @@ export function requireManagedTaskCaller(store, environment) {
52
52
  }
53
53
  return caller;
54
54
  }
55
+ export function resolveManagedTaskReader(store, environment) {
56
+ const self = managedTaskSessionIdentity(environment);
57
+ if (self === undefined)
58
+ return undefined;
59
+ try {
60
+ return requireCurrentRuntime(store, self);
61
+ }
62
+ catch (error) {
63
+ const set = store.getTaskRoleSessionSet(self.taskId, self.roleName);
64
+ const session = [...Object.values(set?.sessions ?? {}), ...(set?.history ?? [])]
65
+ .find(candidate => candidate.nativeSessionId === self.nativeSessionId
66
+ && (self.workspace === undefined || candidate.effective.workspace.root === self.workspace));
67
+ if (session === undefined) {
68
+ const binding = set?.providerBinding;
69
+ if (binding == null || currentProviderConversation(binding).conversationId !== self.nativeSessionId)
70
+ throw error;
71
+ return { taskId: self.taskId, roleName: self.roleName, nativeSessionId: self.nativeSessionId };
72
+ }
73
+ return Object.freeze({
74
+ taskId: self.taskId, roleName: self.roleName, nativeSessionId: session.nativeSessionId
75
+ });
76
+ }
77
+ }
55
78
  /**
56
79
  * The current runtime authority for one Task Role, or undefined. Used by
57
80
  * command authorization that must not fail the whole invocation, only decline
@@ -71,36 +94,57 @@ export function currentManagedRuntime(store, environment, taskId, roleName) {
71
94
  return undefined;
72
95
  return caller;
73
96
  }
97
+ /** Select execution identity, not a credential or grant. Workers retain their
98
+ * active Assignment; Leader management follows the current Role selection. */
99
+ export function taskRoleRuntimeIdentity(role, activeRun) {
100
+ const effective = role.name !== "leader" && activeRun?.status === "active"
101
+ ? activeRun.effective
102
+ : undefined;
103
+ return {
104
+ agentId: effective?.agentId ?? role.activeAgentId,
105
+ adapterId: effective?.adapterId ?? activeRoleAgentBinding(role).adapterId
106
+ };
107
+ }
74
108
  function requireCurrentRuntime(store, self) {
75
109
  const role = store.getRole(self.taskId, self.roleName);
76
110
  if (role === null) {
77
111
  throw new ManagedRuntimeDriftError(`This managed Session belongs to ${self.taskId}/${self.roleName}, which no longer exists. `
78
112
  + "A new Session must be launched to act on this Task.");
79
113
  }
80
- const agentId = role.activeAgentId;
81
- if (self.callerKey === undefined) {
82
- throw new ManagedRuntimeDriftError(`This managed Session carries no ${MANAGED_CALLER_KEY_ENV}, so it cannot be recognized `
114
+ const activeRun = store.getActiveRun(self.taskId, self.roleName);
115
+ const { agentId, adapterId } = taskRoleRuntimeIdentity(role, activeRun);
116
+ const sessions = store.getTaskRoleSessionSet(self.taskId, self.roleName);
117
+ const session = sessions?.sessions[agentId];
118
+ if (self.nativeSessionId === undefined) {
119
+ throw new ManagedRuntimeDriftError(`This managed Session carries no native session id, so it cannot be recognized `
83
120
  + `as the current runtime of ${self.taskId}/${self.roleName}.`);
84
121
  }
85
- const expectedHash = store.getJobCallerKeyHash(self.taskId, self.roleName, agentId);
86
- if (expectedHash === null
87
- || createHash("sha256").update(self.callerKey).digest("hex") !== expectedHash) {
122
+ if (role.name === "leader" && store.listEvents(self.taskId).some((event) => event.type === "role.agent-bound" && event.payload.role === role.name
123
+ && event.payload.revokedNativeSessionId === self.nativeSessionId)) {
124
+ throw new ManagedRuntimeDriftError("This Leader native Session's management authority was explicitly revoked.");
125
+ }
126
+ if (sessions?.activeAgentId !== agentId || session === undefined || session.status !== "active"
127
+ || session.nativeSessionId !== self.nativeSessionId
128
+ || session.adapterId !== adapterId
129
+ || (self.workspace !== undefined && self.workspace !== session.effective.workspace.root)) {
88
130
  throw new ManagedRuntimeDriftError(`This managed Session is no longer the current runtime of ${self.taskId}/${self.roleName} `
89
- + `(the Role now runs Agent ${agentId}). Its native Session was replaced or its Role was `
90
- + "rebound, so its durable caller key no longer matches. Nothing was changed. Read the "
131
+ + `(the authorized runtime uses Agent ${agentId}). Its native Session was replaced or its Role was `
132
+ + "rebound, so its native session id no longer matches. Nothing was changed. Read the "
91
133
  + `current state with \`yui task show ${self.taskId}\`; acting requires the Session Yui `
92
134
  + "launched for the current runtime.");
93
135
  }
94
- const activeTurn = store.getActiveTurn(self.taskId, self.roleName);
95
136
  return Object.freeze({
96
137
  taskId: self.taskId,
97
138
  roleName: self.roleName,
98
139
  agentId,
99
- adapterId: activeRoleAgentBinding(role).adapterId,
140
+ adapterId,
141
+ nativeSessionId: session.nativeSessionId,
142
+ executionAuthority: session.effective.executionAuthority,
100
143
  ...(self.workspace === undefined ? {} : { workspace: self.workspace }),
101
- ...(activeTurn === null || activeTurn.status !== "active"
144
+ ...(activeRun === null || activeRun.status !== "active"
145
+ || activeRun.effective.agentId !== agentId
102
146
  ? {}
103
- : { currentTurnId: activeTurn.id })
147
+ : { currentRunId: activeRun.id })
104
148
  });
105
149
  }
106
150
  function identity(value) {
@@ -0,0 +1,102 @@
1
+ import { openCodexInteractiveConnection } from "./structuredProviderHost.js";
2
+ import { CodexAppServerRuntime, codexAppServerErrorIsMissing, codexClientInitialization } from "./codexAppServerRuntime.js";
3
+ import { realpathSync } from "node:fs";
4
+ import { isAbsolute } from "node:path";
5
+ /** A disposable metadata/control client, not an Agent Session or a new Run.
6
+ * Never calls thread/start, thread/resume or turn/start. A lost Host cannot be
7
+ * the only way to stop an existing native execution. */
8
+ export async function stopCodexNativeSession(launch, input, connect = openCodexInteractiveConnection) {
9
+ const channel = await connect(launch);
10
+ try {
11
+ const initialized = await channel.request("initialize", codexClientInitialization());
12
+ await channel.notify("initialized");
13
+ if (launch.expectedAccountHome !== undefined && !isAbsolute(launch.expectedAccountHome)) {
14
+ throw new Error("Recorded native account Home is invalid.");
15
+ }
16
+ const actualHome = typeof initialized.codexHome === "string" && isAbsolute(initialized.codexHome)
17
+ ? initialized.codexHome : undefined;
18
+ const sameAccount = launch.expectedAccountHome !== undefined && actualHome !== undefined
19
+ && accountPath(launch.expectedAccountHome) === accountPath(actualHome);
20
+ if (launch.expectedAccountHome !== undefined && actualHome !== undefined && !sameAccount) {
21
+ throw new Error("Native recovery connected to a different account Home; restore the recorded connection.");
22
+ }
23
+ const runtime = new CodexAppServerRuntime(channel);
24
+ const latestTurn = async () => {
25
+ const page = await channel.request("thread/turns/list", {
26
+ threadId: input.conversationId, limit: 1, sortDirection: "desc", itemsView: "notLoaded"
27
+ });
28
+ return Array.isArray(page.data) ? page.data[0] : undefined;
29
+ };
30
+ const read = async () => {
31
+ try {
32
+ return await runtime.readConversation(input.conversationId, { includeTurns: false });
33
+ }
34
+ catch (error) {
35
+ if (codexAppServerErrorIsMissing(error) && sameAccount)
36
+ return null;
37
+ throw error;
38
+ }
39
+ };
40
+ let snapshot = await read();
41
+ if (snapshot === null)
42
+ return;
43
+ if (input.clearGoal && await runtime.readGoal(input.conversationId) !== null) {
44
+ await channel.request("thread/goal/clear", { threadId: input.conversationId });
45
+ }
46
+ let active = snapshot.activeTurnId ?? input.nativeTurnId;
47
+ if (snapshot.status === "active" && active === undefined) {
48
+ // Receipt loss does not justify loading an unbounded transcript or
49
+ // guessing which Turn ran. Ask for one metadata-only native record.
50
+ const latest = await latestTurn();
51
+ if (latest?.status === "inProgress" && typeof latest.id === "string")
52
+ active = latest.id;
53
+ }
54
+ if (snapshot.status === "active" && active !== undefined) {
55
+ if (input.nativeTurnId !== undefined && snapshot.activeTurnId !== undefined && active !== input.nativeTurnId) {
56
+ throw new Error("The native conversation has a different active Turn; inspect its owner before stopping it.");
57
+ }
58
+ const interrupted = await runtime.interruptTurn({ conversationId: input.conversationId, turnId: active });
59
+ if (interrupted !== "interrupted") {
60
+ snapshot = await read();
61
+ if (snapshot?.status === "active")
62
+ throw new Error("The exact native Turn could not be stopped; another execution may be active.");
63
+ }
64
+ }
65
+ const deadline = Date.now() + 8000;
66
+ for (;;) {
67
+ snapshot = await read();
68
+ if (snapshot === null || snapshot.status === "notLoaded")
69
+ return;
70
+ // A native error can leave the Thread in systemError after its Turn
71
+ // failed. Prove the exact latest Turn is terminal, then drain any
72
+ // background tools; the diagnostic label must not prevent replacement.
73
+ const errorTurn = snapshot.status === "systemError" ? await latestTurn() : undefined;
74
+ const erroredAndTerminal = errorTurn !== undefined && typeof errorTurn.id === "string"
75
+ && ["completed", "failed", "interrupted"].includes(errorTurn.status);
76
+ if (snapshot.status === "systemError" && !erroredAndTerminal) {
77
+ throw new Error("Native systemError has no proven terminal latest Turn; inspect native execution before replacing it.");
78
+ }
79
+ if (snapshot.status === "idle" || erroredAndTerminal) {
80
+ await channel.request("thread/backgroundTerminals/clean", { threadId: input.conversationId });
81
+ const terminals = await channel.request("thread/backgroundTerminals/list", { threadId: input.conversationId, limit: 1 });
82
+ if (Array.isArray(terminals.data) && terminals.data.length === 0 && terminals.nextCursor == null)
83
+ return;
84
+ }
85
+ if (Date.now() >= deadline) {
86
+ throw new Error(`Native conversation ${input.conversationId} is not confirmed quiescent (${snapshot.status}).`);
87
+ }
88
+ await new Promise(resolve => setTimeout(resolve, 100));
89
+ }
90
+ }
91
+ finally {
92
+ channel.close();
93
+ }
94
+ }
95
+ function accountPath(path) {
96
+ try {
97
+ return realpathSync(path);
98
+ }
99
+ catch {
100
+ return path;
101
+ }
102
+ }
@@ -1,43 +1,28 @@
1
- /** A persisted launch is either temporarily unavailable or permanently lost. */
1
+ /** A Session launch may be temporarily unavailable or fail with a diagnosis. */
2
2
  export class RuntimeLaunchError extends Error {
3
3
  retryable;
4
- runtimeGenerationId;
5
4
  reason;
6
5
  name = "RuntimeLaunchError";
7
- constructor(retryable, runtimeGenerationId, message, reason, options) {
6
+ constructor(retryable, message, reason, options) {
8
7
  super(message, options);
9
8
  this.retryable = retryable;
10
- this.runtimeGenerationId = runtimeGenerationId;
11
9
  this.reason = reason;
12
10
  }
13
11
  }
14
12
  /** A host-side contention check that occurs before planning or process start. */
15
- export class RuntimeHostContentionError extends Error {
13
+ export class RuntimeHostContentionError extends RuntimeLaunchError {
16
14
  reason;
17
15
  name = "RuntimeHostContentionError";
18
16
  constructor(reason, message) {
19
- super(message);
17
+ super(true, message, reason);
20
18
  this.reason = reason;
21
19
  }
22
20
  }
23
- /** A reused Agent Host acknowledged a different runtime generation. */
24
- export class RuntimeGenerationMismatchError extends Error {
25
- expectedRuntimeGenerationId;
26
- observedRuntimeGenerationId;
27
- hostState;
28
- name = "RuntimeGenerationMismatchError";
29
- constructor(expectedRuntimeGenerationId, observedRuntimeGenerationId, hostState, message) {
30
- super(message);
31
- this.expectedRuntimeGenerationId = expectedRuntimeGenerationId;
32
- this.observedRuntimeGenerationId = observedRuntimeGenerationId;
33
- this.hostState = hostState;
34
- }
35
- }
36
21
  /** A reused Host reported an unusable state; this operation did not create it. */
37
22
  export class RuntimeHostUnavailableError extends RuntimeLaunchError {
38
23
  hostState;
39
- constructor(runtimeGenerationId, hostState, message, options) {
40
- super(false, runtimeGenerationId, message, undefined, options);
24
+ constructor(hostState, message, options) {
25
+ super(false, message, undefined, options);
41
26
  this.hostState = hostState;
42
27
  }
43
28
  }
@@ -9,8 +9,7 @@ export function validateRuntimeProcessExitObservation(observation) {
9
9
  optionalIdentity(observation.providerProcessInstanceId, "providerProcessInstanceId");
10
10
  optionalIdentity(observation.taskId, "taskId");
11
11
  identity(observation.roleName, "roleName");
12
- optionalIdentity(observation.turnId, "turnId");
13
- identity(observation.runtimeGenerationId, "runtimeGenerationId");
12
+ optionalIdentity(observation.runId, "runId");
14
13
  optionalIdentity(observation.nativeSessionId, "nativeSessionId");
15
14
  if (observation.processKind !== "agent-host" && observation.processKind !== "provider-child") {
16
15
  throw new Error("Runtime process kind is invalid.");
@@ -26,22 +25,24 @@ export function validateRuntimeProcessExitObservation(observation) {
26
25
  if (!Number.isFinite(Date.parse(observation.observedAt))) {
27
26
  throw new Error("Runtime process observedAt is invalid.");
28
27
  }
29
- optionalIdentity(observation.stopReceiptId, "stopReceiptId");
28
+ if (observation.stopRequested !== undefined && typeof observation.stopRequested !== "boolean") {
29
+ throw new Error("stopRequested must be boolean.");
30
+ }
30
31
  optionalIdentity(observation.lastProviderEventId, "lastProviderEventId");
31
32
  optionalIdentity(observation.diagnosticTailRef, "diagnosticTailRef");
32
33
  return Object.freeze({ ...observation });
33
34
  }
34
35
  export function classifyRuntimeProcessExit(observation, input) {
35
36
  validateRuntimeProcessExitObservation(observation);
36
- if (observation.stopReceiptId !== undefined)
37
- return "yui-requested-stop";
38
- if (observation.processKind === "provider-child" && input.turnFailureObserved === true) {
37
+ if (observation.stopRequested === true)
38
+ return "stop-requested";
39
+ if (observation.processKind === "provider-child" && input.runFailureObserved === true) {
39
40
  return "provider-turn-failed";
40
41
  }
41
42
  if (observation.processKind === "provider-child"
42
43
  && input.childLifecycle === "per-turn"
43
44
  && observation.exitCode === 0
44
- && input.turnTerminalObserved === true) {
45
+ && input.runTerminalObserved === true) {
45
46
  return "expected-per-turn-exit";
46
47
  }
47
48
  if ((observation.exitCode !== undefined && observation.exitCode !== 0)
@@ -1,15 +1,16 @@
1
1
  import { requireText, requireTimestamp } from "./validation.js";
2
- import { formatTurnReceiptId, formatInputRequestReceiptId, validateTaskRecordReference } from "../task/taskRecordReference.js";
2
+ import { formatRunReceiptId, formatInputRequestReceiptId, validateTaskRecordReference } from "../task/taskRecordReference.js";
3
3
  export function createPromptEnvelope(input) {
4
- if (input.source.kind !== "turn"
4
+ if (input.source.kind !== "run"
5
5
  && input.source.kind !== "turn-input"
6
- && input.source.kind !== "input-request") {
6
+ && input.source.kind !== "input-request" && input.source.kind !== "notification") {
7
7
  throw new Error("Prompt source kind is invalid.");
8
8
  }
9
9
  const source = validateTaskRecordReference({
10
10
  taskId: input.source.taskId,
11
11
  localId: input.source.localId
12
- }, input.source.kind === "input-request" ? "inputRequest" : "turn");
12
+ }, input.source.kind === "input-request" ? "inputRequest"
13
+ : input.source.kind === "notification" ? "taskWake" : "run");
13
14
  const id = requireQualifiedReceiptId(input.id, input.source.kind, source.taskId, source.localId);
14
15
  return {
15
16
  id,
@@ -23,8 +24,15 @@ export function createPromptEnvelope(input) {
23
24
  };
24
25
  }
25
26
  function requireQualifiedReceiptId(value, kind, taskId, localId) {
26
- const expected = kind === "turn"
27
- ? formatTurnReceiptId(taskId, localId)
27
+ if (kind === "notification") {
28
+ const prefix = `notification:${taskId}/${localId}/`;
29
+ if (!value.startsWith(prefix) || !/^[a-zA-Z0-9-]+$/.test(value.slice(prefix.length))) {
30
+ throw new Error("Notification attempt does not match its wake.");
31
+ }
32
+ return value;
33
+ }
34
+ const expected = kind === "run"
35
+ ? formatRunReceiptId(taskId, localId)
28
36
  : kind === "input-request"
29
37
  ? formatInputRequestReceiptId(taskId, localId)
30
38
  : `turn-input:${taskId}/${localId}/`;
@@ -35,6 +43,9 @@ function requireQualifiedReceiptId(value, kind, taskId, localId) {
35
43
  }
36
44
  return value;
37
45
  }
46
+ if (kind === "run" && value.startsWith(`${expected}/attempt/`)
47
+ && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(value.slice(`${expected}/attempt/`.length)))
48
+ return value;
38
49
  if (value !== expected)
39
50
  throw new Error("Prompt envelope id does not match its source.");
40
51
  return expected;
@@ -4,9 +4,7 @@ export function providerContinuationKey(identity) {
4
4
  normalized.providerNamespace,
5
5
  normalized.accountScope,
6
6
  normalized.conversationId,
7
- normalized.activationId,
8
- normalized.continuationId,
9
- normalized.generation
7
+ normalized.continuationId
10
8
  ].join("\u0000");
11
9
  }
12
10
  export function createProviderContinuation(input) {
@@ -14,7 +12,7 @@ export function createProviderContinuation(input) {
14
12
  schemaVersion: 1,
15
13
  taskId: text(input.taskId, "Task id"),
16
14
  roleName: text(input.roleName, "Role name"),
17
- turnId: text(input.turnId, "Turn id"),
15
+ runId: text(input.runId, "AgentRun id"),
18
16
  identity: validateProviderContinuationIdentity(input.identity),
19
17
  ...(input.parentContinuationId === undefined
20
18
  ? {}
@@ -152,7 +150,7 @@ export function validateProviderContinuation(value) {
152
150
  throw new Error("Provider Continuation schemaVersion must be 1.");
153
151
  text(value.taskId, "Task id");
154
152
  text(value.roleName, "Role name");
155
- text(value.turnId, "Turn id");
153
+ text(value.runId, "AgentRun id");
156
154
  validateProviderContinuationIdentity(value.identity);
157
155
  if (!["active", "quiescent", "unknown"].includes(value.execution)) {
158
156
  throw new Error("Provider Continuation execution is invalid.");
@@ -203,11 +201,7 @@ export function validateProviderContinuationIdentity(value) {
203
201
  text(value.providerNamespace, "Provider namespace");
204
202
  text(value.accountScope, "Provider account scope");
205
203
  text(value.conversationId, "Provider Conversation id");
206
- text(value.activationId, "Provider Activation id");
207
204
  text(value.continuationId, "Provider Continuation id");
208
- if (!Number.isSafeInteger(value.generation) || value.generation < 1) {
209
- throw new Error("Provider Continuation generation is invalid.");
210
- }
211
205
  return value;
212
206
  }
213
207
  function validateProviderReport(value) {
@@ -89,18 +89,11 @@ function groupDetachedContinuations(continuations, observations) {
89
89
  const key = [
90
90
  continuation.identity.providerNamespace,
91
91
  continuation.identity.accountScope,
92
- continuation.identity.conversationId,
93
- continuation.identity.activationId
92
+ continuation.identity.conversationId
94
93
  ].join("\u0000");
95
- const source = [...observations].reverse().find((observation) => (observation.kind.startsWith("continuation.")
96
- && observation.fence.driverId === continuation.identity.providerNamespace
97
- && observation.fence.agentId === continuation.identity.accountScope
98
- && observation.fence.conversationId === continuation.identity.conversationId
99
- && observation.fence.activationId === continuation.identity.activationId
100
- && observation.fence.continuationId === continuation.identity.continuationId
101
- && observation.fence.continuationGeneration === continuation.identity.generation));
94
+ const source = [...observations].reverse().find((observation) => (observation.kind.startsWith("continuation.") && observation.fence.driverId === continuation.identity.providerNamespace && observation.fence.agentId === continuation.identity.accountScope && observation.fence.conversationId === continuation.identity.conversationId && observation.fence.continuationId === continuation.identity.continuationId));
102
95
  // A projected continuation without its original durable fence cannot be
103
- // safely attached to a live Turn. Keep ownership conservative and let the
96
+ // safely attached to a live AgentRun. Keep ownership conservative and let the
104
97
  // malformed identity remain visible instead of synthesizing a receipt.
105
98
  if (source === undefined)
106
99
  continue;
@@ -149,14 +142,12 @@ function reconciliationObservation(continuation, sourceFence, now) {
149
142
  ...sourceFence,
150
143
  taskId: continuation.taskId,
151
144
  roleName: continuation.roleName,
152
- turnId: continuation.turnId,
145
+ runId: continuation.runId,
153
146
  agentId: continuation.identity.accountScope,
154
147
  driverId: continuation.identity.providerNamespace,
155
148
  conversationId: continuation.identity.conversationId,
156
- activationId: continuation.identity.activationId,
157
149
  nativeSessionId: continuation.identity.conversationId,
158
150
  continuationId: continuation.identity.continuationId,
159
- continuationGeneration: continuation.identity.generation,
160
151
  ...(continuation.parentContinuationId === undefined
161
152
  ? {}
162
153
  : { parentContinuationId: continuation.parentContinuationId })
@@ -1,4 +1,4 @@
1
- import { currentProviderActivation, currentProviderAuthority, currentProviderConversation, validateProviderRuntimeBinding } from "./providerRuntimeIdentity.js";
1
+ import { currentProviderAuthority, currentProviderConversation, validateProviderRuntimeBinding } from "./providerRuntimeIdentity.js";
2
2
  /**
3
3
  * Applies the durable single-writer fence before any Provider mutation. The
4
4
  * Adapter never receives authority to infer or repair identity.
@@ -33,13 +33,8 @@ export class FencedProviderControl {
33
33
  const normalized = validateProviderRuntimeBinding(binding);
34
34
  this.#assertNamespace(normalized);
35
35
  const conversation = currentProviderConversation(normalized);
36
- const activation = currentProviderActivation(normalized);
37
36
  const authority = currentProviderAuthority(normalized);
38
- if (conversation.conversationId !== fence.conversationId
39
- || activation?.activationId !== fence.activationId
40
- || authority.epoch !== fence.authorityEpoch
41
- || authority.owner !== fence.authorityOwner
42
- || authority.holderId !== fence.holderId) {
37
+ if (conversation.conversationId !== fence.conversationId || authority.epoch !== fence.authorityEpoch || authority.owner !== fence.authorityOwner || authority.holderId !== fence.holderId) {
43
38
  throw new Error("Provider writer fence is stale.");
44
39
  }
45
40
  }