@zq-silk/yui 0.15.7 → 0.15.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/ARCHITECTURE.md +192 -399
  2. package/README.md +127 -1149
  3. package/dist/agent/adapterCatalog.js +15 -2
  4. package/dist/agent/agent.js +23 -3
  5. package/dist/agent/argumentPolicy.js +7 -1
  6. package/dist/agent/connectionPlan.js +62 -0
  7. package/dist/agent/executionComponents.js +158 -0
  8. package/dist/agent/launchEnvironment.js +31 -3
  9. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  10. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  11. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  12. package/dist/brief/taskBrief.js +12 -0
  13. package/dist/cli/agentConfigurationPicker.js +13 -0
  14. package/dist/cli/commandCatalog.js +157 -70
  15. package/dist/cli/interactionCandidates.js +5 -5
  16. package/dist/cli/interactionPolicy.js +38 -8
  17. package/dist/cli/invocationRouter.js +1 -1
  18. package/dist/cli/managedDiagnostics.js +28 -0
  19. package/dist/cli/operatorWizard.js +1 -7
  20. package/dist/cli/roleOptionOrder.js +27 -0
  21. package/dist/cli/roleWizard.js +50 -14
  22. package/dist/cli/updateOrchestrator.js +1 -1
  23. package/dist/cli/updatePorts.js +3 -4
  24. package/dist/cli.js +178 -95
  25. package/dist/commands/agentCommands.js +72 -14
  26. package/dist/commands/capabilityCommands.js +9 -6
  27. package/dist/commands/configCommands.js +20 -20
  28. package/dist/commands/deliveryGuardPreflight.js +2 -2
  29. package/dist/commands/executionAuditCommands.js +24 -24
  30. package/dist/commands/globalRoleCommands.js +1 -1
  31. package/dist/commands/grantCommands.js +4 -4
  32. package/dist/commands/operatorCommands.js +1 -7
  33. package/dist/commands/projectCommands.js +4 -4
  34. package/dist/commands/resourcesCommands.js +2 -2
  35. package/dist/commands/roleConfiguration.js +25 -5
  36. package/dist/commands/roleRuntimeGuard.js +4 -5
  37. package/dist/commands/sessionCommands.js +3 -7
  38. package/dist/commands/taskActivationCommands.js +259 -0
  39. package/dist/commands/taskActor.js +28 -49
  40. package/dist/commands/taskCommands.js +1188 -710
  41. package/dist/commands/taskContextCommand.js +39 -583
  42. package/dist/commands/taskExecutionCommands.js +32 -32
  43. package/dist/commands/taskInputCommands.js +40 -104
  44. package/dist/commands/taskIntegrationCommands.js +3 -2
  45. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  46. package/dist/commands/taskNextActionCommand.js +8 -8
  47. package/dist/commands/taskOverviewCommand.js +33 -45
  48. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  49. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  50. package/dist/commands/telemetryCommands.js +36 -38
  51. package/dist/config/configCatalog.js +4 -4
  52. package/dist/config/yuiConfig.js +8 -8
  53. package/dist/context/contextSnapshot.js +10 -10
  54. package/dist/context/dispatchContext.js +11 -11
  55. package/dist/context/roleSessionContext.js +6 -3
  56. package/dist/context/{turnContextPack.js → runContextPack.js} +146 -81
  57. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  58. package/dist/context/sessionBootstrapManifest.js +21 -2
  59. package/dist/context/sourceRunContext.js +30 -0
  60. package/dist/context/taskContext.js +458 -0
  61. package/dist/context/wakeNotification.js +27 -27
  62. package/dist/controller/agentRuntimeObserver.js +21 -24
  63. package/dist/controller/capabilityBridge.js +17 -6
  64. package/dist/controller/clientRuntime.js +65 -92
  65. package/dist/controller/controller.js +114 -188
  66. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  67. package/dist/controller/jobControl.js +54 -85
  68. package/dist/controller/resourceInventory.js +8 -27
  69. package/dist/controller/resourceInventoryLinux.js +12 -13
  70. package/dist/controller/runtime.js +529 -479
  71. package/dist/controller/runtimeEventInbox.js +55 -25
  72. package/dist/controller/runtimeEventProcessor.js +22 -31
  73. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  74. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  75. package/dist/controller/runtimeObservationHook.js +14 -18
  76. package/dist/controller/sessionNotify.js +16 -24
  77. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  78. package/dist/controller/structuredProviderObservation.js +138 -99
  79. package/dist/coordination/workMailbox.js +3 -3
  80. package/dist/coordination/workMailboxQueue.js +36 -33
  81. package/dist/core/boundedRpc.js +8 -1
  82. package/dist/core/controllerClient.js +20 -1
  83. package/dist/core/controllerServer.js +4 -4
  84. package/dist/doctor/doctor.js +13 -2
  85. package/dist/domain/agentResultTransport.js +9 -9
  86. package/dist/execution/codexThreadNaming.js +2 -8
  87. package/dist/execution/executionHealth.js +51 -63
  88. package/dist/execution/reviewMainRun.js +137 -0
  89. package/dist/execution/workItemExecution.js +28 -29
  90. package/dist/execution/workItemExecutionProjection.js +99 -107
  91. package/dist/execution/workItemMainRun.js +141 -0
  92. package/dist/executor/agentAdapter.js +227 -20
  93. package/dist/executor/agentConfigurationCatalog.js +126 -4
  94. package/dist/executor/agentConfigurationProbe.js +162 -4
  95. package/dist/executor/agentExecutor.js +79 -78
  96. package/dist/executor/effectiveLaunch.js +105 -18
  97. package/dist/executor/executorRegistry.js +29 -44
  98. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  99. package/dist/executor/workspacePreflightClassification.js +16 -16
  100. package/dist/grant/capabilityGrant.js +6 -3
  101. package/dist/input/inputRequest.js +12 -10
  102. package/dist/integration/gitIntegrationService.js +4 -11
  103. package/dist/integration/integrationQueueService.js +4 -4
  104. package/dist/interaction/operatorPresentation.js +1 -1
  105. package/dist/kernel/builtinCapabilities.js +247 -12
  106. package/dist/kernel/capabilityRegistry.js +64 -18
  107. package/dist/kernel/instanceHost.js +12 -1
  108. package/dist/kernel/kernelPorts.js +2 -2
  109. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  110. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  111. package/dist/message/message.js +62 -6
  112. package/dist/message/messageContinuation.js +204 -0
  113. package/dist/observability/executionAudit.js +70 -72
  114. package/dist/observability/faultClassification.js +2 -2
  115. package/dist/observability/orchestrationMetrics.js +8 -8
  116. package/dist/operator/operatorSessionHistory.js +1 -7
  117. package/dist/output/agentConfigurationPresentation.js +8 -3
  118. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  119. package/dist/output/rolePresentation.js +54 -3
  120. package/dist/plugins/pluginChild.js +104 -0
  121. package/dist/plugins/pluginIntent.js +26 -0
  122. package/dist/plugins/pluginInterpreter.js +43 -0
  123. package/dist/plugins/pluginPackage.js +101 -0
  124. package/dist/plugins/pluginProcess.js +112 -0
  125. package/dist/plugins/pluginService.js +380 -0
  126. package/dist/profile/agentProfile.js +1 -1
  127. package/dist/repository/gitWorkspace.js +26 -4
  128. package/dist/repository/project.js +19 -4
  129. package/dist/repository/taskBaseFreshness.js +13 -13
  130. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  131. package/dist/repository/taskWorkspacePreparer.js +344 -83
  132. package/dist/resources/autoResourceGc.js +3 -3
  133. package/dist/resources/liveReferences.js +3 -3
  134. package/dist/resources/projectResource.js +123 -0
  135. package/dist/resources/projectResourceService.js +421 -0
  136. package/dist/resources/resourceDiscovery.js +6 -6
  137. package/dist/resources/resourceGc.js +1 -1
  138. package/dist/resources/resourceRegistrar.js +1 -1
  139. package/dist/resources/resourceTypes.js +1 -1
  140. package/dist/review/deltaRecheck.js +3 -3
  141. package/dist/review/reviewAcceptance.js +16 -16
  142. package/dist/review/reviewDecision.js +7 -7
  143. package/dist/review/reviewRound.js +21 -20
  144. package/dist/review/reviewerAvailability.js +2 -2
  145. package/dist/role/role.js +51 -7
  146. package/dist/role/taskRoleUpdate.js +30 -0
  147. package/dist/runtime/acpProtocol.js +425 -0
  148. package/dist/runtime/acpSession.js +731 -0
  149. package/dist/runtime/acpSessionConfiguration.js +260 -0
  150. package/dist/runtime/agentDriver.js +30 -11
  151. package/dist/runtime/agentEndpoint.js +278 -0
  152. package/dist/runtime/agentEndpointIdentity.js +86 -0
  153. package/dist/runtime/agentEndpointOwnership.js +239 -0
  154. package/dist/runtime/agentError.js +2 -10
  155. package/dist/runtime/agentHost.js +565 -314
  156. package/dist/runtime/agentRunConfiguration.js +258 -0
  157. package/dist/runtime/builtinAgentDrivers.js +134 -18
  158. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  159. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  160. package/dist/runtime/claude-process-owner +0 -0
  161. package/dist/runtime/codexAppServerRuntime.js +38 -30
  162. package/dist/runtime/codexInteractiveHost.js +41 -6
  163. package/dist/runtime/continuationManager.js +2 -6
  164. package/dist/runtime/executionEnvironment.js +30 -0
  165. package/dist/runtime/firstProgressAdvisory.js +11 -11
  166. package/dist/runtime/index.js +4 -3
  167. package/dist/runtime/jsonLineChannel.js +109 -0
  168. package/dist/runtime/launchBroker.js +91 -16
  169. package/dist/runtime/launchDiagnostics.js +2 -2
  170. package/dist/runtime/lifecycleReservation.js +10 -18
  171. package/dist/runtime/managedCaller.js +61 -17
  172. package/dist/runtime/nativeSessionControl.js +102 -0
  173. package/dist/runtime/ports.js +6 -21
  174. package/dist/runtime/processExitObservation.js +8 -7
  175. package/dist/runtime/promptEnvelope.js +17 -6
  176. package/dist/runtime/providerContinuation.js +3 -9
  177. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  178. package/dist/runtime/providerControl.js +2 -7
  179. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  180. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  181. package/dist/runtime/runtimeBinding.js +0 -1
  182. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  183. package/dist/runtime/runtimeDeadlines.js +9 -0
  184. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  185. package/dist/runtime/runtimeObservation.js +29 -65
  186. package/dist/runtime/runtimeProjection.js +43 -51
  187. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  188. package/dist/runtime/sessionLaunchRequest.js +3 -7
  189. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  190. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  191. package/dist/runtime/sessionReconciliation.js +4 -8
  192. package/dist/runtime/sessionTerminationGuard.js +70 -259
  193. package/dist/runtime/sessionTokenMetrics.js +5 -16
  194. package/dist/runtime/structuredProviderHost.js +237 -117
  195. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  196. package/dist/runtime/tmuxAdapters.js +39 -86
  197. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  198. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  199. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  200. package/dist/scheduler/ports.js +80 -9
  201. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  202. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  203. package/dist/scheduler/taskExecutionProjection.js +120 -124
  204. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  205. package/dist/scheduler/taskWake.js +11 -4
  206. package/dist/scheduler/wakeReason.js +9 -1
  207. package/dist/setup/setupCommand.js +1 -0
  208. package/dist/storage/migrations/agentRunContract.js +159 -0
  209. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  210. package/dist/storage/sqliteSchema.js +431 -5
  211. package/dist/storage/sqliteStore.js +375 -220
  212. package/dist/storage/storageVersions.js +1 -1
  213. package/dist/storage/storeRpc.js +10 -5
  214. package/dist/storage/taskStore.js +13 -11
  215. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  216. package/dist/surface/surfaceContributions.js +102 -0
  217. package/dist/task/completionReadiness.js +32 -6
  218. package/dist/task/deliveryGuard.js +16 -16
  219. package/dist/task/draftPlan.js +72 -12
  220. package/dist/task/nextAction.js +144 -128
  221. package/dist/task/remoteDelivery.js +6 -6
  222. package/dist/task/task.js +184 -18
  223. package/dist/task/taskActivation.js +301 -0
  224. package/dist/task/taskActivationService.js +392 -0
  225. package/dist/task/taskRecordReference.js +5 -4
  226. package/dist/task/taskRecordRetirement.js +1 -1
  227. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  228. package/dist/telemetry/telemetryConfig.js +14 -14
  229. package/dist/telemetry/telemetryWiring.js +2 -2
  230. package/dist/web/assets/assetManifest.js +2 -0
  231. package/dist/web/assets/client/app.js +120 -20
  232. package/dist/web/assets/client/components.js +87 -54
  233. package/dist/web/assets/client/i18n.js +83 -41
  234. package/dist/web/assets/client/markdown.js +1 -1
  235. package/dist/web/assets/client/taskSurface.js +353 -0
  236. package/dist/web/assets/client/view.js +49 -44
  237. package/dist/web/assets/shell.js +1 -1
  238. package/dist/web/assets/styles/cards.js +22 -4
  239. package/dist/web/controllerWeb.js +60 -0
  240. package/dist/web/webMutation.js +28 -0
  241. package/dist/web/webServer.js +118 -8
  242. package/dist/web/webSnapshot.js +81 -74
  243. package/dist/web/webTaskSurface.js +64 -0
  244. package/dist/workItem/dependencyGate.js +1 -1
  245. package/dist/workItem/workItem.js +80 -48
  246. package/dist/workspace/workItemChangeSetManager.js +16 -9
  247. package/docs/agent-result-consumption.md +94 -0
  248. package/docs/agent-runtime-drivers.md +91 -0
  249. package/docs/architecture/README.md +38 -0
  250. package/docs/architecture/capabilities-and-resources.md +79 -0
  251. package/docs/managed-turn-and-session-runtime.md +222 -0
  252. package/docs/observability/README.md +81 -0
  253. package/docs/plugin-sdk.md +290 -0
  254. package/docs/provider-runtime.md +163 -0
  255. package/docs/release-workflow.md +303 -0
  256. package/docs/roles-and-configuration.md +113 -0
  257. package/docs/sqlite-control-plane-design.md +76 -0
  258. package/docs/task-dag-semantics.md +57 -0
  259. package/docs/task-delivery.md +103 -0
  260. package/docs/task-local-identity.md +6 -6
  261. package/docs/testing/verification-levels.md +86 -0
  262. package/i18n/README.zh-CN.md +98 -739
  263. package/package.json +2 -2
  264. package/skills/yui-leader/SKILL.md +130 -103
  265. package/skills/yui-leader/references/integration.md +39 -0
  266. package/skills/yui-leader/references/replicated-execution.md +42 -0
  267. package/skills/yui-leader/references/task-plugins.md +33 -0
  268. package/skills/yui-operator/SKILL.md +30 -59
  269. package/skills/yui-reviewer/SKILL.md +35 -36
  270. package/skills/yui-runtime/SKILL.md +88 -24
  271. package/skills/yui-runtime/references/publication.md +22 -0
  272. package/skills/yui-runtime/references/recovery.md +64 -0
  273. package/skills/yui-worker/SKILL.md +37 -39
  274. package/dist/cli/roleOptionCatalog.js +0 -68
  275. package/dist/context/sourceTurnContext.js +0 -30
  276. package/dist/execution/reviewMainTurn.js +0 -161
  277. package/dist/execution/workItemMainTurn.js +0 -164
  278. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  279. package/dist/runtime/preallocatedNativeSession.js +0 -13
  280. package/dist/runtime/runtimeStopReceipt.js +0 -42
  281. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -1,21 +1,32 @@
1
1
  import { isDeepStrictEqual } from "node:util";
2
+ import { validateExecutionEnvironmentSnapshot } from "../resources/projectResource.js";
2
3
  import { validateManagedWorkspace } from "../worktree/managedWorkspace.js";
3
4
  import { resolveAgentAdapter } from "./agentAdapter.js";
4
5
  import { roleSessionKind } from "../context/roleSessionContext.js";
6
+ import { isAgentAdapterId } from "../agent/adapterCatalog.js";
7
+ import { adapterIdForExecutionComponent, isAgentExecutionComponentId, resolveAgentExecutionComponent } from "../agent/executionComponents.js";
5
8
  import { SESSION_BOOTSTRAP_MANIFEST_SCHEMA_VERSION, sessionManifestCompatibilityDigest } from "../context/sessionProtocolIdentity.js";
6
9
  export function resolveEffectiveLaunch(input) {
10
+ if (input.purpose === "planning" && input.executionAuthority === "delivery") {
11
+ throw new Error("Planning cannot request delivery authority.");
12
+ }
7
13
  validateDesiredRole(input.role);
8
14
  const binding = input.role.agentBindings[input.role.activeAgentId];
9
15
  const workspace = snapshotWorkspace(input.role.workspace, input.workspace);
10
16
  const writeProjectIds = effectiveWriteProjects(input, workspace);
11
17
  const config = resolveAgentAdapter(binding.adapterId).canonicalizeConfig(clone(binding.config));
12
18
  return snapshotFromConfig({
19
+ executionAuthority: input.executionAuthority ?? (input.purpose === "planning" ? "planning" : "delivery"),
13
20
  sourceDesiredRevision: input.role.launchRevision,
14
21
  agentId: binding.agentId,
22
+ component: resolveAgentExecutionComponent(binding.adapterId, binding.component),
15
23
  config,
16
24
  profileAccess: input.role.defaultAccess,
17
25
  writeProjectIds,
18
26
  workspace,
27
+ ...("taskId" in input.role && input.role.executionEnvironment !== undefined
28
+ ? { executionEnvironment: input.role.executionEnvironment }
29
+ : {}),
19
30
  context: snapshotContext(input.role),
20
31
  contextProtocolVersion: SESSION_BOOTSTRAP_MANIFEST_SCHEMA_VERSION,
21
32
  sessionManifestCompatibilityDigest: sessionManifestCompatibilityDigest(input.role.name, roleSessionKind(input.role, "taskId" in input.role
@@ -69,6 +80,24 @@ function claudeConfigFromSnapshot(snapshot) {
69
80
  : { settingsSources: [...snapshot.settingsSources] })
70
81
  };
71
82
  }
83
+ function acpConfigFromSnapshot(snapshot) {
84
+ // Model and effort round-trip because they are ACP session config options
85
+ // that this launch pushes and confirms. Settings deliberately do not: the
86
+ // protocol defines no client-side settings file or settings source, so the
87
+ // snapshot type keeps those permanently absent.
88
+ return {
89
+ adapterId: "acp",
90
+ ...(snapshot.model === undefined ? {} : { model: snapshot.model }),
91
+ ...(snapshot.effort === undefined ? {} : { effort: snapshot.effort }),
92
+ permission: clone(snapshot.permission),
93
+ ...(snapshot.additionalDirectories === undefined
94
+ ? {}
95
+ : { additionalDirectories: [...snapshot.additionalDirectories] }),
96
+ ...(snapshot.advanced === undefined
97
+ ? {}
98
+ : { advanced: clone(snapshot.advanced) })
99
+ };
100
+ }
72
101
  /**
73
102
  * Exactness fence for one launch: the same resolved launch must be observed by
74
103
  * every participant of that launch. Desired-revision bookkeeping is provenance
@@ -89,12 +118,12 @@ export function sameEffectiveLaunch(existing, desired) {
89
118
  * Only facts that make continuation impossible participate: the Session
90
119
  * protocol, the provider identity that owns the conversation, and the physical
91
120
  * workspace the Session runs in. Launch configuration such as model, effort,
92
- * permission, Role context, declared write scope, and Turn-scoped facts like
93
- * ReviewRound identity or candidate commits shape the next Host activation
121
+ * permission, Role context, declared write scope, and AgentRun-scoped facts like
122
+ * ReviewRound identity or candidate commits shape the next Host process
94
123
  * instead of ending the Session; that divergence is acknowledged where the
95
124
  * configuration changes and stays visible as launch provenance.
96
125
  *
97
- * Session kind needs no separate check: a Role's review Turns run in their own
126
+ * Session kind needs no separate check: a Role's review AgentRuns run in their own
98
127
  * ReviewRound workspace, so the physical workspace already separates a review
99
128
  * Session from an execution Session.
100
129
  */
@@ -108,7 +137,7 @@ export function effectiveLaunchWithTaskMainWorkspace(existing, workspace) {
108
137
  validateEffectiveLaunchSnapshot(existing);
109
138
  validateManagedWorkspace(workspace);
110
139
  if (workspace.owner.type !== "task") {
111
- throw new Error("Only a Task-owned main workspace may refresh fixed Session Turn evidence.");
140
+ throw new Error("Only a Task-owned main workspace may refresh fixed Session AgentRun evidence.");
112
141
  }
113
142
  return validateEffectiveLaunchSnapshot({
114
143
  ...existing,
@@ -121,9 +150,15 @@ export function effectiveLaunchWithTaskMainWorkspace(existing, workspace) {
121
150
  function sessionContinuitySnapshot(snapshot) {
122
151
  return {
123
152
  schemaVersion: snapshot.schemaVersion,
153
+ executionAuthority: snapshot.executionAuthority,
124
154
  contextProtocolVersion: snapshot.contextProtocolVersion,
125
155
  agentId: snapshot.agentId,
156
+ // Two products on one connection plan are two different conversations. A
157
+ // Session that started against an unidentified ACP Agent must not silently
158
+ // continue against the Claude Agent SDK just because both speak ACP.
159
+ component: snapshot.component,
126
160
  adapterId: snapshot.adapterId,
161
+ executionEnvironment: snapshot.executionEnvironment,
127
162
  workspace: {
128
163
  root: snapshot.workspace.root,
129
164
  entries: snapshot.workspace.entries.map((entry) => ({
@@ -137,11 +172,18 @@ function sessionContinuitySnapshot(snapshot) {
137
172
  };
138
173
  }
139
174
  export function validateEffectiveLaunchSnapshot(snapshot) {
140
- if (snapshot.schemaVersion !== 3) {
141
- throw new Error("Effective launch snapshot must use schemaVersion 3.");
175
+ if (snapshot.schemaVersion !== 4) {
176
+ throw new Error("Effective launch snapshot must use schemaVersion 4.");
177
+ }
178
+ if (snapshot.executionAuthority !== "planning" && snapshot.executionAuthority !== "delivery") {
179
+ throw new Error("Effective launch requires its captured execution authority.");
142
180
  }
143
181
  positiveInteger(snapshot.sourceDesiredRevision, "Source desired revision");
144
182
  identity(snapshot.agentId, "Effective Agent id");
183
+ if (!isAgentExecutionComponentId(snapshot.component)
184
+ || adapterIdForExecutionComponent(snapshot.component) !== snapshot.adapterId) {
185
+ throw new Error(`Effective launch execution component is invalid: ${String(snapshot.component)}.`);
186
+ }
145
187
  if (snapshot.profileAccess !== "read" && snapshot.profileAccess !== "write") {
146
188
  throw new Error(`Effective launch Profile access is invalid: ${String(snapshot.profileAccess)}.`);
147
189
  }
@@ -172,6 +214,19 @@ export function validateEffectiveLaunchSnapshot(snapshot) {
172
214
  throw new Error("Effective launch Session Manifest compatibility digest is invalid.");
173
215
  }
174
216
  validateWorkspace(snapshot.workspace);
217
+ if (snapshot.executionEnvironment !== undefined) {
218
+ validateExecutionEnvironmentSnapshot(snapshot.executionEnvironment);
219
+ if (snapshot.executionEnvironment.access === "read") {
220
+ if (snapshot.adapterId !== "codex") {
221
+ throw new Error("Read-only execution environments require a native filesystem sandbox; Claude is unsupported.");
222
+ }
223
+ if (snapshot.permission.strategy !== "configured"
224
+ || snapshot.permission.sandbox !== "read-only"
225
+ || snapshot.permission.approval !== "never") {
226
+ throw new Error("Read-only execution environments require Codex configured sandbox read-only and approval never.");
227
+ }
228
+ }
229
+ }
175
230
  cloneContext(snapshot.context);
176
231
  const config = effectiveLaunchConfigUnchecked(snapshot);
177
232
  resolveAgentAdapter(snapshot.adapterId).canonicalizeConfig(config);
@@ -182,6 +237,7 @@ export function effectiveRoleForLaunch(role, snapshot) {
182
237
  const config = effectiveLaunchConfig(snapshot);
183
238
  const binding = {
184
239
  agentId: snapshot.agentId,
240
+ component: snapshot.component,
185
241
  adapterId: snapshot.adapterId,
186
242
  config
187
243
  };
@@ -194,6 +250,19 @@ export function effectiveRoleForLaunch(role, snapshot) {
194
250
  defaultAccess: snapshot.profileAccess,
195
251
  workspace: snapshot.workspace.root
196
252
  };
253
+ if ("taskId" in result) {
254
+ if (snapshot.executionEnvironment === undefined)
255
+ delete result.executionEnvironment;
256
+ else {
257
+ if (snapshot.executionEnvironment.taskId !== result.taskId) {
258
+ throw new Error("Effective execution environment belongs to another Task.");
259
+ }
260
+ result.executionEnvironment = clone(snapshot.executionEnvironment);
261
+ }
262
+ }
263
+ else if (snapshot.executionEnvironment !== undefined) {
264
+ throw new Error("Only a Task Role may use an execution environment.");
265
+ }
197
266
  clearMissingContext(result, snapshot.context);
198
267
  return result;
199
268
  }
@@ -209,9 +278,11 @@ function snapshotFromConfig(input) {
209
278
  reviewBaseCommit: commit(input.reviewBaseCommit ?? "", "Review base commit")
210
279
  };
211
280
  const common = {
212
- schemaVersion: 3,
281
+ schemaVersion: 4,
282
+ executionAuthority: input.executionAuthority,
213
283
  sourceDesiredRevision: positiveInteger(input.sourceDesiredRevision, "Source desired revision"),
214
284
  agentId: identity(input.agentId, "Effective Agent id"),
285
+ component: input.component,
215
286
  profileAccess: input.profileAccess,
216
287
  ...(config.model === undefined ? {} : { model: config.model }),
217
288
  ...(config.effort === undefined ? {} : { effort: config.effort }),
@@ -222,6 +293,9 @@ function snapshotFromConfig(input) {
222
293
  ...(config.advanced === undefined ? {} : { advanced: clone(config.advanced) }),
223
294
  writeProjectIds: [...input.writeProjectIds],
224
295
  workspace: cloneWorkspace(input.workspace),
296
+ ...(input.executionEnvironment === undefined
297
+ ? {}
298
+ : { executionEnvironment: clone(input.executionEnvironment) }),
225
299
  context: cloneContext(input.context),
226
300
  contextProtocolVersion: input.contextProtocolVersion,
227
301
  sessionManifestCompatibilityDigest: input.sessionManifestCompatibilityDigest,
@@ -234,21 +308,25 @@ function snapshotFromConfig(input) {
234
308
  permission: clone(config.permission),
235
309
  ...(config.profile === undefined ? {} : { profile: config.profile })
236
310
  }
237
- : {
238
- ...common,
239
- adapterId: "claude",
240
- permission: clone(config.permission),
241
- ...(config.settingsFile === undefined ? {} : { settingsFile: config.settingsFile }),
242
- ...(config.settingsSources === undefined
243
- ? {}
244
- : { settingsSources: [...config.settingsSources] })
245
- };
311
+ : config.adapterId === "acp"
312
+ ? { ...common, adapterId: "acp", permission: clone(config.permission) }
313
+ : {
314
+ ...common,
315
+ adapterId: "claude",
316
+ permission: clone(config.permission),
317
+ ...(config.settingsFile === undefined ? {} : { settingsFile: config.settingsFile }),
318
+ ...(config.settingsSources === undefined
319
+ ? {}
320
+ : { settingsSources: [...config.settingsSources] })
321
+ };
246
322
  return validateEffectiveLaunchSnapshot(snapshot);
247
323
  }
248
324
  function effectiveLaunchConfigUnchecked(snapshot) {
249
325
  return snapshot.adapterId === "codex"
250
326
  ? codexConfigFromSnapshot(snapshot)
251
- : claudeConfigFromSnapshot(snapshot);
327
+ : snapshot.adapterId === "acp"
328
+ ? acpConfigFromSnapshot(snapshot)
329
+ : claudeConfigFromSnapshot(snapshot);
252
330
  }
253
331
  function effectiveWriteProjects(input, workspace) {
254
332
  if (input.purpose === "review") {
@@ -367,10 +445,19 @@ function validateDesiredRole(role) {
367
445
  if (role.defaultAccess !== "read" && role.defaultAccess !== "write") {
368
446
  throw new Error("Role default access is invalid.");
369
447
  }
448
+ if ("executionEnvironment" in role && role.executionEnvironment !== undefined) {
449
+ if (!("taskId" in role))
450
+ throw new Error("Only a Task Role may use an execution environment.");
451
+ validateExecutionEnvironmentSnapshot(role.executionEnvironment);
452
+ if (role.executionEnvironment.taskId !== role.taskId) {
453
+ throw new Error("Role execution environment belongs to another Task.");
454
+ }
455
+ }
370
456
  const binding = role.agentBindings[role.activeAgentId];
371
457
  if (binding === undefined)
372
458
  throw new Error("Role active Agent binding is missing.");
373
- if (binding.adapterId !== "codex" && binding.adapterId !== "claude") {
459
+ // Adapter support is the catalog's fact, not a second list to keep in sync.
460
+ if (!isAgentAdapterId(binding.adapterId)) {
374
461
  throw new Error(`Role Agent adapter is unsupported: ${binding.adapterId}.`);
375
462
  }
376
463
  }
@@ -1,10 +1,11 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { createPromptEnvelope, createSessionLaunchRequest } from "../runtime/index.js";
3
- import { formatTurnReceiptId } from "../task/taskRecordReference.js";
3
+ import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
4
+ import { formatRunReceiptId } from "../task/taskRecordReference.js";
4
5
  /**
5
6
  * rr13/test: Test-only liveness seam. Integration tests that spawn a real
6
7
  * Controller subprocess cannot inject a fake TmuxDeliveryPort, and a saved
7
- * active Leader Turn would be reaped by the startup liveness pass without a
8
+ * active Leader AgentRun would be reaped by the startup liveness pass without a
8
9
  * real tmux role. When this env var is "1", every role reads "present"
9
10
  * without probing tmux. The Controller subprocess inherits it from the
10
11
  * test's CLI env. Never set in production.
@@ -38,7 +39,7 @@ export class ExecutorRegistry {
38
39
  agentId: input.agentId,
39
40
  adapterId: input.adapterId,
40
41
  mode: input.mode,
41
- ...(input.turnId === undefined ? {} : { turnId: input.turnId })
42
+ ...(input.runId === undefined ? {} : { runId: input.runId })
42
43
  };
43
44
  const cached = this.#prepared.get(deliveryBase.deliveryId);
44
45
  if (cached !== undefined)
@@ -49,16 +50,6 @@ export class ExecutorRegistry {
49
50
  if (this.runtimePorts === undefined) {
50
51
  planned = this.planner.plan(input);
51
52
  sessionStarted = this.tmux.ensureRoleWindow(input.taskId, planned.role, planned.launch);
52
- if (sessionStarted
53
- && planned.launch.env.YUI_JOB_CALLER_KEY !== undefined
54
- && this.planner.commitTaskCallerKey !== undefined) {
55
- this.planner.commitTaskCallerKey({
56
- taskId: input.taskId,
57
- roleName: input.roleName,
58
- agentId: input.agentId,
59
- callerKey: planned.launch.env.YUI_JOB_CALLER_KEY
60
- });
61
- }
62
53
  session = planned.session;
63
54
  }
64
55
  else {
@@ -71,10 +62,11 @@ export class ExecutorRegistry {
71
62
  ...(input.managedWorkspace === undefined
72
63
  ? {}
73
64
  : { managedWorkspace: input.managedWorkspace }),
65
+ ...(input.workspaceFree === true ? { workspaceFree: true } : {}),
74
66
  ...(input.runtimePolicy === undefined
75
67
  ? {}
76
68
  : { runtimePolicy: input.runtimePolicy }),
77
- ...(input.turnId === undefined ? {} : { turnId: input.turnId })
69
+ ...(input.runId === undefined ? {} : { runId: input.runId })
78
70
  };
79
71
  if (this.runtimePorts.launchCoordinator !== undefined) {
80
72
  binding = await this.runtimePorts.launchCoordinator.prepare(input.mode === "new"
@@ -83,21 +75,16 @@ export class ExecutorRegistry {
83
75
  ...common,
84
76
  mode: "resume",
85
77
  nativeSessionId: input.nativeSessionId,
86
- ...(input.hostActivationId === undefined
87
- ? {}
88
- : { hostActivationId: input.hostActivationId })
89
- }, "deferred", undefined, input.beforeHostStart);
78
+ }, undefined, input.beforeHostStart);
90
79
  }
91
80
  else {
92
81
  const request = input.mode === "new"
93
82
  ? createSessionLaunchRequest({
94
83
  ...common,
95
- runtimeGenerationId: deliveryBase.deliveryId,
96
84
  mode: "new"
97
85
  })
98
86
  : createSessionLaunchRequest({
99
87
  ...common,
100
- runtimeGenerationId: deliveryBase.deliveryId,
101
88
  mode: "resume",
102
89
  nativeSessionId: input.nativeSessionId
103
90
  });
@@ -118,7 +105,6 @@ export class ExecutorRegistry {
118
105
  }
119
106
  const delivery = {
120
107
  ...deliveryBase,
121
- ...(binding === undefined ? {} : { runtimeGenerationId: binding.runtimeGenerationId }),
122
108
  sessionStarted,
123
109
  session,
124
110
  };
@@ -141,18 +127,20 @@ export class ExecutorRegistry {
141
127
  async sendOnce(input) {
142
128
  const prepared = this.requirePrepared(input.delivery.prepared);
143
129
  if (prepared.binding !== undefined && this.runtimePorts !== undefined) {
144
- const turnId = input.delivery.prepared.turnId;
145
- if (turnId === undefined) {
146
- throw new Error("Runtime prompt delivery requires a Task-local Turn id.");
130
+ const runId = input.delivery.prepared.runId;
131
+ if (runId === undefined && input.notificationId === undefined) {
132
+ throw new Error("Runtime prompt delivery requires a Task-local AgentRun id.");
147
133
  }
148
134
  const outcome = await this.runtimePorts.promptPush.tryPush({
149
135
  binding: prepared.binding,
150
136
  envelope: createPromptEnvelope({
151
137
  id: input.receiptId,
152
- source: {
153
- kind: input.receiptId === formatTurnReceiptId(input.delivery.prepared.taskId, turnId) ? "turn" : "turn-input",
138
+ source: input.notificationId !== undefined ? {
139
+ kind: "notification", taskId: input.delivery.prepared.taskId, localId: input.notificationId
140
+ } : {
141
+ kind: input.receiptId === formatRunReceiptId(input.delivery.prepared.taskId, runId) || input.receiptId.startsWith(`${formatRunReceiptId(input.delivery.prepared.taskId, runId)}/attempt/`) ? "run" : "turn-input",
154
142
  taskId: input.delivery.prepared.taskId,
155
- localId: turnId
143
+ localId: runId
156
144
  },
157
145
  text: input.text,
158
146
  createdAt: new Date()
@@ -174,7 +162,6 @@ export class ExecutorRegistry {
174
162
  return { status: "unavailable" };
175
163
  const outcome = await this.runtimePorts.promptPush.trySteer({
176
164
  owner: { scope: "task", taskId: input.taskId, roleName: input.roleName },
177
- runtimeGenerationId: input.runtimeGenerationId,
178
165
  agentId: input.agentId,
179
166
  adapterId: input.adapterId,
180
167
  nativeSessionId: input.nativeSessionId,
@@ -182,7 +169,7 @@ export class ExecutorRegistry {
182
169
  providerAuthority: input.authority,
183
170
  envelope: createPromptEnvelope({
184
171
  id: input.receiptId,
185
- source: { kind: "turn-input", taskId: input.taskId, localId: activeTurnId(input.receiptId) },
172
+ source: { kind: "turn-input", taskId: input.taskId, localId: activeRunId(input.receiptId) },
186
173
  text: input.text,
187
174
  createdAt: new Date()
188
175
  })
@@ -198,12 +185,7 @@ export class ExecutorRegistry {
198
185
  forgetPrepared(input) {
199
186
  for (const [deliveryId, prepared] of this.#prepared) {
200
187
  const delivery = prepared.delivery;
201
- if (delivery.taskId !== input.taskId
202
- || delivery.roleName !== input.roleName
203
- || (input.turnId !== undefined
204
- && delivery.turnId !== input.turnId)
205
- || (input.runtimeGenerationId !== undefined
206
- && delivery.runtimeGenerationId !== input.runtimeGenerationId)) {
188
+ if (delivery.taskId !== input.taskId || delivery.roleName !== input.roleName || (input.runId !== undefined && delivery.runId !== input.runId)) {
207
189
  continue;
208
190
  }
209
191
  this.#prepared.delete(deliveryId);
@@ -260,13 +242,12 @@ export class ExecutorRegistry {
260
242
  const requested = resourceInputs ?? inputs.map((input) => ({
261
243
  taskId: input.taskId,
262
244
  roleName: input.roleName,
263
- ...(input.turnId === undefined ? {} : { turnId: input.turnId }),
245
+ ...(input.runId === undefined ? {} : { runId: input.runId }),
264
246
  agentId: input.agentId,
265
247
  adapterId: input.adapterId,
266
248
  ...(input.nativeSessionId === undefined
267
249
  ? {}
268
250
  : { nativeSessionId: input.nativeSessionId }),
269
- ...(input.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: input.runtimeGenerationId }),
270
251
  ...(input.progressAt === undefined ? {} : { progressAt: input.progressAt })
271
252
  }));
272
253
  if (this.runtimePorts?.roleResourceInventory !== undefined
@@ -328,10 +309,10 @@ export class ExecutorRegistry {
328
309
  return planned;
329
310
  }
330
311
  }
331
- function activeTurnId(receiptId) {
312
+ function activeRunId(receiptId) {
332
313
  const match = /^turn-input:[^/]+\/([^/]+)\/[1-9]\d*$/u.exec(receiptId);
333
314
  if (match === null)
334
- throw new Error("Turn steer receipt is invalid.");
315
+ throw new Error("AgentRun steer receipt is invalid.");
335
316
  return decodeURIComponent(match[1]);
336
317
  }
337
318
  /**
@@ -346,10 +327,15 @@ function deliveryReport(outcome) {
346
327
  };
347
328
  }
348
329
  export function agentProcessReadinessProbe(adapterId, _surface = "role") {
349
- if (adapterId !== "codex" && adapterId !== "claude") {
330
+ // A tmux pane probe is only meaningful for an Agent that actually has an
331
+ // interactive CLI surface. Asking a protocol-only Agent whether its pane
332
+ // looks alive would answer a question about the wrong thing, so the refusal
333
+ // is derived from the declared surface rather than from an adapter name.
334
+ const driver = builtinAgentDriverRegistry().findByAdapterId(adapterId);
335
+ if (driver === null || !driver.capabilities.surfaces.includes("interactive-cli")) {
350
336
  throw new Error(`No tmux readiness probe is registered for Agent adapter: ${adapterId}.`);
351
337
  }
352
- // Turn state and receipt fences decide whether delivery is allowed. Provider
338
+ // AgentRun state and receipt fences decide whether delivery is allowed. Provider
353
339
  // terminal contents are display-only evidence and never lifecycle input.
354
340
  return livePane;
355
341
  }
@@ -364,9 +350,8 @@ function preparedDeliveryId(input) {
364
350
  input.adapterId,
365
351
  input.effective,
366
352
  input.mode,
367
- input.turnId ?? null,
368
- input.nativeSessionId ?? null,
369
- input.hostActivationId ?? null
353
+ input.runId ?? null,
354
+ input.nativeSessionId ?? null
370
355
  ])).digest("hex");
371
356
  }
372
357
  function hasText(value) {