@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,10 +1,11 @@
1
1
  import { isDeepStrictEqual } from "node:util";
2
2
  import { agentNotFound, usageError } from "../errors/cliError.js";
3
3
  import { defaultTableWidth, renderTable } from "../output/table.js";
4
+ import { isAgentAdapterId, supportedAgentAdapterIds } from "../agent/adapterCatalog.js";
5
+ import { adapterIdForExecutionComponent, agentExecutionComponentLabel, defaultExecutionComponentForAdapter, isAgentExecutionComponentId, supportedAgentExecutionComponentIds } from "../agent/executionComponents.js";
4
6
  import { createConfiguredAgent, validateConfiguredAgent } from "../agent/agent.js";
5
7
  import { LIVE_SESSION_ACKNOWLEDGEMENT_OPTION } from "./roleRuntimeGuard.js";
6
8
  import { hasRuntimeLifecycleWork, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
7
- const SUPPORTED_ADAPTERS = Object.freeze(["codex", "claude"]);
8
9
  export function runAgentCommand(args, store) {
9
10
  const [command, ...rest] = args;
10
11
  switch (command) {
@@ -23,16 +24,24 @@ function addAgent(args, store) {
23
24
  const [rawId, ...tail] = args;
24
25
  const id = agentId(rawId);
25
26
  const parsed = parseAgentOptions(tail, "add");
26
- const adapterId = parsed.one("--adapter") ?? (SUPPORTED_ADAPTERS.includes(id) ? id : undefined);
27
- if (adapterId === undefined)
28
- throw usageError("--adapter is required.");
27
+ const component = parsed.one("--component")?.trim();
28
+ if (component !== undefined)
29
+ assertComponent(component);
30
+ // Naming the component is enough: it determines its own connection plan, so
31
+ // there is one fact to state rather than a pair that could contradict.
32
+ const adapterId = parsed.one("--adapter")
33
+ ?? (component === undefined ? undefined : adapterIdForExecutionComponent(component))
34
+ ?? (isAgentAdapterId(id) ? id : undefined);
35
+ if (adapterId === undefined) {
36
+ throw usageError("--component or --adapter is required.");
37
+ }
29
38
  assertAdapter(adapterId);
30
39
  const command = parsed.one("--command")?.trim();
31
40
  if (command === undefined || command.length === 0)
32
41
  throw usageError("--command is required.");
33
42
  let agent;
34
43
  try {
35
- agent = createConfiguredAgent(id, adapterId, command, parsed.many("--arg"), parsed.many("--env").map(parseEnvironmentBinding), new Date());
44
+ agent = createConfiguredAgent(id, adapterId, command, parsed.many("--arg"), parsed.many("--env").map(parseEnvironmentBinding), new Date(), component);
36
45
  }
37
46
  catch (error) {
38
47
  throw usageError(error instanceof Error ? error.message : String(error));
@@ -50,11 +59,13 @@ function listAgents(args, store) {
50
59
  return "No agents configured.\n";
51
60
  return `${renderTable("Agents", [
52
61
  { header: "Agent", minWidth: 5, maxWidth: 24 },
62
+ { header: "Component", minWidth: 9, maxWidth: 20 },
53
63
  { header: "Adapter", minWidth: 7, maxWidth: 12 },
54
64
  { header: "Command", minWidth: 7, maxWidth: 48 },
55
65
  { header: "Environment", minWidth: 11, maxWidth: 32 }
56
66
  ], agents.map((agent) => [
57
67
  agent.id,
68
+ agent.component,
58
69
  agent.adapterId,
59
70
  [agent.command, ...agent.baseArgs].join(" "),
60
71
  agent.environment.map((binding) => `${binding.target}<-${binding.sourceName}`).join(", ")
@@ -86,11 +97,25 @@ function updateAgent(args, store) {
86
97
  const adapterId = parsed.one("--adapter")?.trim();
87
98
  if (adapterId !== undefined)
88
99
  assertAdapter(adapterId);
100
+ const component = parsed.one("--component")?.trim();
101
+ if (component !== undefined)
102
+ assertComponent(component);
103
+ if (component !== undefined && adapterId !== undefined
104
+ && adapterIdForExecutionComponent(component) !== adapterId) {
105
+ throw usageError(`Agent execution component ${component} is reached over the `
106
+ + `${adapterIdForExecutionComponent(component)} connection plan, not ${adapterId}. `
107
+ + "Pass --component alone to move the Agent onto its own plan.");
108
+ }
89
109
  const command = parsed.one("--command")?.trim();
90
110
  if (command !== undefined && command.length === 0)
91
111
  throw usageError("--command is required.");
92
- const patch = {
112
+ const requestedPatch = {
93
113
  ...(adapterId === undefined ? {} : { adapterId }),
114
+ // Changing the component can move the Agent onto its plan, which is the one
115
+ // way the two stay consistent without asking the operator to restate both.
116
+ ...(component === undefined
117
+ ? {}
118
+ : { component, adapterId: adapterIdForExecutionComponent(component) }),
94
119
  ...(command === undefined ? {} : { command }),
95
120
  ...(parsed.has("--arg")
96
121
  ? { baseArgs: parsed.many("--arg") }
@@ -104,6 +129,14 @@ function updateAgent(args, store) {
104
129
  const existing = tx.getConfiguredAgent(id);
105
130
  if (existing === null)
106
131
  return null;
132
+ // Derive a default only when actually leaving the stored plan. Restating
133
+ // the same plan must preserve an explicitly identified ACP component.
134
+ const patch = {
135
+ ...requestedPatch,
136
+ ...(component === undefined && adapterId !== undefined && adapterId !== existing.adapterId
137
+ ? { component: defaultExecutionComponentForAdapter(adapterId) }
138
+ : {})
139
+ };
107
140
  const changes = actualAgentChanges(existing, patch);
108
141
  if (!changes.operational) {
109
142
  return { status: "unchanged", agent: existing };
@@ -117,22 +150,37 @@ function updateAgent(args, store) {
117
150
  const liveSession = findNonStoppedSessionReference(tx, id);
118
151
  if (liveSession !== null && !parsed.has(LIVE_SESSION_ACKNOWLEDGEMENT_OPTION)) {
119
152
  throw usageError(`${describeReference(liveSession)} runs a live native session (${liveSession.status}) on `
120
- + `Agent ${id}, so this change applies to its next Host activation instead of the `
153
+ + `Agent ${id}, so this change applies to its next Host process instead of the `
121
154
  + "running one.\n"
122
155
  + `Re-run with ${LIVE_SESSION_ACKNOWLEDGEMENT_OPTION} to record the change and keep that `
123
156
  + "session.\n"
124
157
  + "Stop the affected Role session first to apply it to a fresh session instead.");
125
158
  }
126
- if (changes.adapter) {
159
+ // A component change is refused on a referenced Agent for the same reason
160
+ // an adapter change is, and the reason is not symmetry: the product identity
161
+ // is copied into Role bindings and frozen into every Session snapshot at
162
+ // launch. Rewriting only the Agent leaves those copies asserting the old
163
+ // product while the new command runs, so a Session resumes against one
164
+ // product under another's name. Rewriting the copies instead would relabel
165
+ // history that really did run the old product. Neither is correctable here,
166
+ // so the change is refused and the operator binds a new Agent explicitly —
167
+ // which leaves existing Sessions pinned to what they actually ran.
168
+ const identityChange = changes.adapter
169
+ ? { axis: "adapter", target: "adapter" }
170
+ : changes.component ? { axis: "execution component", target: "component" } : null;
171
+ if (identityChange !== null) {
127
172
  const profile = findAgentProfileReference(tx, id);
128
173
  if (profile !== null) {
129
- throw usageError(`Agent ${id} adapter cannot change because Agent Profile ${profile.id} references it. `
174
+ throw usageError(`Agent ${id} ${identityChange.axis} cannot change because Agent Profile `
175
+ + `${profile.id} references it. `
130
176
  + "Update that explicit Profile or create a new Agent ID instead.");
131
177
  }
132
178
  const binding = findRoleBindingReference(tx, id);
133
179
  if (binding !== null) {
134
- throw usageError(`Agent ${id} adapter cannot change because ${describeReference(binding)} references it. `
135
- + "Create a new Agent ID with the target adapter and bind the Role to it instead.");
180
+ throw usageError(`Agent ${id} ${identityChange.axis} cannot change because `
181
+ + `${describeReference(binding)} references it. `
182
+ + `Create a new Agent ID with the target ${identityChange.target} and bind the Role `
183
+ + "to it instead.");
136
184
  }
137
185
  }
138
186
  assertValidAgentCandidate(existing, patch, now);
@@ -184,12 +232,14 @@ function removeAgent(args, store) {
184
232
  }
185
233
  function actualAgentChanges(existing, patch) {
186
234
  const adapter = patch.adapterId !== undefined && patch.adapterId !== existing.adapterId;
235
+ const component = patch.component !== undefined && patch.component !== existing.component;
187
236
  const operational = adapter
237
+ || component
188
238
  || (patch.command !== undefined && patch.command !== existing.command)
189
239
  || (patch.baseArgs !== undefined && !isDeepStrictEqual(patch.baseArgs, existing.baseArgs))
190
240
  || (patch.environment !== undefined
191
241
  && !isDeepStrictEqual(patch.environment, existing.environment));
192
- return { adapter, operational };
242
+ return { adapter, component, operational };
193
243
  }
194
244
  function assertValidAgentCandidate(existing, patch, now) {
195
245
  try {
@@ -274,6 +324,7 @@ function describeReference(reference) {
274
324
  function parseAgentOptions(args, mode) {
275
325
  const valueOptions = new Map([
276
326
  ["--adapter", { repeatable: false, allowOptionLikeValue: false }],
327
+ ["--component", { repeatable: false, allowOptionLikeValue: false }],
277
328
  ["--command", { repeatable: false, allowOptionLikeValue: false }],
278
329
  ["--arg", { repeatable: true, allowOptionLikeValue: true }],
279
330
  ["--env", { repeatable: true, allowOptionLikeValue: false }]
@@ -339,8 +390,14 @@ function agentId(value) {
339
390
  return value.trim();
340
391
  }
341
392
  function assertAdapter(value) {
342
- if (!SUPPORTED_ADAPTERS.includes(value)) {
343
- throw usageError(`Agent adapter is not supported: ${value}. Supported adapters: ${SUPPORTED_ADAPTERS.join(", ")}.`);
393
+ if (!isAgentAdapterId(value)) {
394
+ throw usageError(`Agent adapter is not supported: ${value}. Supported adapters: ${supportedAgentAdapterIds().join(", ")}.`);
395
+ }
396
+ }
397
+ function assertComponent(value) {
398
+ if (!isAgentExecutionComponentId(value)) {
399
+ throw usageError(`Agent execution component is not supported: ${value}. Supported components: `
400
+ + `${supportedAgentExecutionComponentIds().join(", ")}.`);
344
401
  }
345
402
  }
346
403
  function assertNoArguments(args, message) {
@@ -350,6 +407,7 @@ function assertNoArguments(args, message) {
350
407
  function renderAgent(title, agent) {
351
408
  return [
352
409
  title,
410
+ `Component: ${agent.component} (${agentExecutionComponentLabel(agent.component)})`,
353
411
  `Adapter: ${agent.adapterId}`,
354
412
  `Executable: ${agent.command}`,
355
413
  `Arguments: ${agent.baseArgs.join(" ")}`,
@@ -3,9 +3,10 @@ import { resolveJobCaller } from "./taskActor.js";
3
3
  import { callFileTaskController } from "../controller/clientRuntime.js";
4
4
  export async function runCapabilityCommand(args, home, environment) {
5
5
  const [action, ...rest] = args;
6
- const usage = "yui capability search [query] --task <id> | describe <name> --task <id> [--provider <id>] [--version <version>] | call <name> --task <id> --input <json> [--provider <id>] [--version <version>] [--request-id <id>]";
7
- if (!["search", "describe", "call"].includes(action))
6
+ const usage = "yui capability search [query] --task <id> | commands --task <id> | panels --task <id> | describe <name> --task <id> [--provider <id>] [--version <version>] | call <name> --task <id> --input <json> [--provider <id>] [--version <version>] [--request-id <id>]";
7
+ if (!["search", "commands", "panels", "describe", "call"].includes(action))
8
8
  throw usageError(usage);
9
+ const surfaceList = action === "commands" || action === "panels";
9
10
  const flags = new Map();
10
11
  const positionals = [];
11
12
  const allowed = new Set(["--task", "--provider", "--version", "--input", "--request-id"]);
@@ -22,9 +23,11 @@ export async function runCapabilityCommand(args, home, environment) {
22
23
  flags.set(arg, next);
23
24
  }
24
25
  const taskId = flags.get("--task") ?? environment.YUI_TASK_ID;
25
- if (!taskId || positionals.length > 1 || (action !== "search" && !positionals.length))
26
+ if (!taskId || positionals.length > 1
27
+ || (!surfaceList && action !== "search" && !positionals.length)
28
+ || (surfaceList && positionals.length))
26
29
  throw usageError(usage);
27
- if (action === "search" && [...flags.keys()].some((key) => key !== "--task"))
30
+ if ((action === "search" || surfaceList) && [...flags.keys()].some((key) => key !== "--task"))
28
31
  throw usageError(usage);
29
32
  if (action === "describe" && (flags.has("--input") || flags.has("--request-id")))
30
33
  throw usageError(usage);
@@ -39,9 +42,9 @@ export async function runCapabilityCommand(args, home, environment) {
39
42
  throw usageError("Invalid capability JSON input.");
40
43
  }
41
44
  }
42
- return callFileTaskController(home, `capability.${action}`, {
45
+ return callFileTaskController(home, `capability.${surfaceList ? "search" : action}`, {
43
46
  taskId, caller: resolveJobCaller(environment, taskId),
44
- ...(action === "search" ? { query: positionals[0] ?? "" } : {
47
+ ...(surfaceList ? { surface: action } : action === "search" ? { query: positionals[0] ?? "" } : {
45
48
  request: {
46
49
  name: positionals[0],
47
50
  ...(input === undefined ? {} : { input }),
@@ -1,7 +1,7 @@
1
1
  import { mkdirSync, realpathSync } from "node:fs";
2
2
  import { isAbsolute, relative, resolve } from "node:path";
3
3
  import { usageError } from "../errors/cliError.js";
4
- import { DEFAULT_AGENT_LAUNCH_INACTIVITY_TIMEOUT_SECONDS, DEFAULT_CONTROLLER_TASK_CONCURRENCY, DEFAULT_DELIVERY_TIMEOUT_SECONDS, DEFAULT_LEADER_NEXT_ACTION_MODE, DEFAULT_LEADER_SEMANTIC_BUDGET_TURNS, DEFAULT_RECONCILIATION_INTERVAL_SECONDS, DEFAULT_RESOURCES_GC_MODE, DEFAULT_RESOURCES_QUARANTINE_TTL_HOURS, DEFAULT_TMUX_HISTORY_LIMIT, LEADER_NEXT_ACTION_MODES, reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveLeaderNextActionMode, resolveLeaderSemanticBudgetTurns, resolveResourcesGcAutoQuarantine, resolveResourcesGcMode, resolveResourcesQuarantineTtlHours, resolveRuntimeHealth, resolveTelemetryEnabled, resolveTelemetryTurnCap, resolveTelemetryTerminalKeep, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
4
+ import { DEFAULT_AGENT_LAUNCH_INACTIVITY_TIMEOUT_SECONDS, DEFAULT_CONTROLLER_TASK_CONCURRENCY, DEFAULT_DELIVERY_TIMEOUT_SECONDS, DEFAULT_LEADER_NEXT_ACTION_MODE, DEFAULT_LEADER_SEMANTIC_BUDGET_RUNS, DEFAULT_RECONCILIATION_INTERVAL_SECONDS, DEFAULT_RESOURCES_GC_MODE, DEFAULT_RESOURCES_QUARANTINE_TTL_HOURS, DEFAULT_TMUX_HISTORY_LIMIT, LEADER_NEXT_ACTION_MODES, reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveLeaderNextActionMode, resolveLeaderSemanticBudgetRuns, resolveResourcesGcAutoQuarantine, resolveResourcesGcMode, resolveResourcesQuarantineTtlHours, resolveRuntimeHealth, resolveTelemetryEnabled, resolveTelemetryRunCap, resolveTelemetryTerminalKeep, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
5
5
  import { CONFIG_DEFINITIONS, CONFIG_KEYS, configDefinition, configDefinitionsForDomain } from "../config/configCatalog.js";
6
6
  import { resolveTimeZone } from "../output/timePresentation.js";
7
7
  import { defaultTableWidth, renderTable } from "../output/table.js";
@@ -77,12 +77,12 @@ export function effectiveConfigData(config, domain) {
77
77
  controllerTaskConcurrency: resolveControllerTaskConcurrency(config.controllerTaskConcurrency),
78
78
  agentLaunchInactivityTimeoutSeconds: resolveAgentLaunchInactivityTimeoutSeconds(config.agentLaunchInactivityTimeoutSeconds),
79
79
  deliveryTimeoutSeconds: resolveDeliveryTimeoutSeconds(config.deliveryTimeoutSeconds),
80
- leaderSemanticBudgetTurns: resolveLeaderSemanticBudgetTurns(config.leaderSemanticBudgetTurns),
80
+ leaderSemanticBudgetRuns: resolveLeaderSemanticBudgetRuns(config.leaderSemanticBudgetRuns),
81
81
  tmuxBin: resolveTmuxBin(config.tmuxBin),
82
82
  tmuxHistoryLimit: resolveTmuxHistoryLimit(config.tmuxHistoryLimit),
83
83
  telemetryEnabled: resolveTelemetryEnabled(config.telemetryEnabled),
84
84
  telemetryTerminalKeep: resolveTelemetryTerminalKeep(config.telemetryTerminalKeep),
85
- telemetryTurnCap: resolveTelemetryTurnCap(config.telemetryTurnCap),
85
+ telemetryRunCap: resolveTelemetryRunCap(config.telemetryRunCap),
86
86
  review: config.review === undefined
87
87
  ? null
88
88
  : {
@@ -263,23 +263,23 @@ const CONFIG_KEY_HANDLERS = [
263
263
  }
264
264
  },
265
265
  {
266
- key: "leader-semantic-budget-turns",
266
+ key: "leader-semantic-budget-runs",
267
267
  showLabel: "Leader semantic budget",
268
- showValue: (config) => `${resolveLeaderSemanticBudgetTurns(config.leaderSemanticBudgetTurns)} turns`,
268
+ showValue: (config) => `${resolveLeaderSemanticBudgetRuns(config.leaderSemanticBudgetRuns)} runs`,
269
269
  set(args, store) {
270
- const usage = "Workflow config set usage: yui config workflow set leader-semantic-budget-turns <1-20>.";
270
+ const usage = "Workflow config set usage: yui config workflow set leader-semantic-budget-runs <1-20>.";
271
271
  if (args.length !== 1)
272
272
  throw usageError(usage);
273
- const leaderSemanticBudgetTurns = validatedConfigValue(() => resolveLeaderSemanticBudgetTurns(Number(args[0])), usage);
274
- saveConfigKey(store, (config) => ({ ...config, leaderSemanticBudgetTurns }));
275
- return `Leader semantic budget set to ${leaderSemanticBudgetTurns} turns\n`;
273
+ const leaderSemanticBudgetRuns = validatedConfigValue(() => resolveLeaderSemanticBudgetRuns(Number(args[0])), usage);
274
+ saveConfigKey(store, (config) => ({ ...config, leaderSemanticBudgetRuns }));
275
+ return `Leader semantic budget set to ${leaderSemanticBudgetRuns} runs\n`;
276
276
  },
277
277
  clear(store) {
278
278
  saveConfigKey(store, (config) => {
279
- const { leaderSemanticBudgetTurns: _removed, ...rest } = config;
279
+ const { leaderSemanticBudgetRuns: _removed, ...rest } = config;
280
280
  return rest;
281
281
  });
282
- return `Leader semantic budget reset to ${DEFAULT_LEADER_SEMANTIC_BUDGET_TURNS} turns\n`;
282
+ return `Leader semantic budget reset to ${DEFAULT_LEADER_SEMANTIC_BUDGET_RUNS} runs\n`;
283
283
  }
284
284
  },
285
285
  {
@@ -520,22 +520,22 @@ const CONFIG_KEY_HANDLERS = [
520
520
  }
521
521
  },
522
522
  {
523
- key: "telemetry-turn-cap",
524
- showLabel: "Telemetry Turn cap",
525
- showValue: (config) => String(resolveTelemetryTurnCap(config.telemetryTurnCap)),
523
+ key: "telemetry-run-cap",
524
+ showLabel: "Telemetry AgentRun cap",
525
+ showValue: (config) => String(resolveTelemetryRunCap(config.telemetryRunCap)),
526
526
  set(args, store) {
527
527
  if (args.length !== 1)
528
- throw usageError("Tools config set usage: yui config tools set telemetry-turn-cap <n>.");
529
- const telemetryTurnCap = validatedConfigValue(() => resolveTelemetryTurnCap(Number(args[0])), "Tools config set usage: yui config tools set telemetry-turn-cap <n>.");
530
- saveConfigKey(store, (config) => ({ ...config, telemetryTurnCap }));
531
- return `Telemetry Turn cap set to ${telemetryTurnCap}\n`;
528
+ throw usageError("Tools config set usage: yui config tools set telemetry-run-cap <n>.");
529
+ const telemetryRunCap = validatedConfigValue(() => resolveTelemetryRunCap(Number(args[0])), "Tools config set usage: yui config tools set telemetry-run-cap <n>.");
530
+ saveConfigKey(store, (config) => ({ ...config, telemetryRunCap }));
531
+ return `Telemetry AgentRun cap set to ${telemetryRunCap}\n`;
532
532
  },
533
533
  clear(store) {
534
534
  saveConfigKey(store, (config) => {
535
- const { telemetryTurnCap: _removed, ...rest } = config;
535
+ const { telemetryRunCap: _removed, ...rest } = config;
536
536
  return rest;
537
537
  });
538
- return "Telemetry Turn cap reset to default\n";
538
+ return "Telemetry AgentRun cap reset to default\n";
539
539
  }
540
540
  },
541
541
  {
@@ -1,4 +1,4 @@
1
- import { resolveLeaderNextActionMode, resolveLeaderSemanticBudgetTurns } from "../config/yuiConfig.js";
1
+ import { resolveLeaderNextActionMode, resolveLeaderSemanticBudgetRuns } from "../config/yuiConfig.js";
2
2
  import { usageError } from "../errors/cliError.js";
3
3
  import { detectDeliveryDuplicates, evaluateDeliveryGuard, evaluateSemanticBudget, formatDeliveryDuplicate } from "../task/deliveryGuard.js";
4
4
  export function runDeliveryGuardPreflight(store, taskId, intent, options = {}) {
@@ -15,7 +15,7 @@ export function runDeliveryGuardPreflight(store, taskId, intent, options = {}) {
15
15
  + "Reuse the existing proof, or set leader.nextActionMode=warn to proceed with a warning.");
16
16
  }
17
17
  if (options.budget === true) {
18
- const budget = evaluateSemanticBudget(facts, resolveLeaderSemanticBudgetTurns(store.getConfig().leaderSemanticBudgetTurns));
18
+ const budget = evaluateSemanticBudget(facts, resolveLeaderSemanticBudgetRuns(store.getConfig().leaderSemanticBudgetRuns));
19
19
  if (budget.exhausted) {
20
20
  warnings.push(`Semantic progress budget: ${budget.reason}`);
21
21
  }
@@ -92,26 +92,26 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
92
92
  else {
93
93
  lines.push("", ...sectionError("tasks", report));
94
94
  }
95
- if (report.turns.status === "ok" && report.turns.data !== undefined) {
96
- const turns = report.turns.data;
97
- lines.push("", `Turns: ${turns.total} total · ${turns.failed} failed (${(turns.failureRate * 100).toFixed(1)}%) · ${turns.completed} completed · ${turns.active} active`, `Duration: ${formatDuration(turns.cumulativeDurationMs)} total · ${formatDuration(turns.failedDurationMs)} in failed Turns`, `By role: ${turns.byRole.leader} leader · ${turns.byRole.reviewer} reviewer · ${turns.byRole.implementer} implementer/worker · ${turns.byRole.other} other`, `By purpose: ${turns.byPurpose.execution} execution · ${turns.byPurpose.review} review`);
98
- const faultRows = Object.entries(turns.faultClasses)
95
+ if (report.runs.status === "ok" && report.runs.data !== undefined) {
96
+ const runs = report.runs.data;
97
+ lines.push("", `AgentRuns: ${runs.total} total · ${runs.failed} failed (${(runs.failureRate * 100).toFixed(1)}%) · ${runs.completed} completed · ${runs.active} active`, `Duration: ${formatDuration(runs.cumulativeDurationMs)} total · ${formatDuration(runs.failedDurationMs)} in failed AgentRuns`, `By role: ${runs.byRole.leader} leader · ${runs.byRole.reviewer} reviewer · ${runs.byRole.implementer} implementer/worker · ${runs.byRole.other} other`, `By purpose: ${runs.byPurpose.execution} execution · ${runs.byPurpose.review} review`);
98
+ const faultRows = Object.entries(runs.faultClasses)
99
99
  .filter(([, count]) => count > 0)
100
100
  .sort((left, right) => right[1] - left[1]);
101
101
  if (faultRows.length > 0) {
102
- lines.push(renderTable("Turn failure classes", [
102
+ lines.push(renderTable("AgentRun failure classes", [
103
103
  { header: "Class", minWidth: 24, maxWidth: 40 },
104
104
  { header: "Count", minWidth: 5, maxWidth: 8 }
105
105
  ], faultRows.map(([name, count]) => [name, String(count)]), width));
106
106
  }
107
- if (turns.launchFailures.total > 0) {
108
- const phaseRows = Object.entries(turns.launchFailures.byPhase)
107
+ if (runs.launchFailures.total > 0) {
108
+ const phaseRows = Object.entries(runs.launchFailures.byPhase)
109
109
  .filter(([, count]) => count > 0)
110
110
  .sort((left, right) => right[1] - left[1]);
111
- const kindRows = Object.entries(turns.launchFailures.byKind)
111
+ const kindRows = Object.entries(runs.launchFailures.byKind)
112
112
  .filter(([, count]) => count > 0)
113
113
  .sort((left, right) => right[1] - left[1]);
114
- lines.push("", `Launch failures: ${turns.launchFailures.total}`, `By phase: ${phaseRows.map(([name, count]) => `${name}=${count}`).join(" · ")}`, `By kind: ${kindRows.map(([name, count]) => `${name}=${count}`).join(" · ")}`);
114
+ lines.push("", `Launch failures: ${runs.launchFailures.total}`, `By phase: ${phaseRows.map(([name, count]) => `${name}=${count}`).join(" · ")}`, `By kind: ${kindRows.map(([name, count]) => `${name}=${count}`).join(" · ")}`);
115
115
  }
116
116
  }
117
117
  else {
@@ -119,9 +119,9 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
119
119
  }
120
120
  if (report.wakes.status === "ok" && report.wakes.data !== undefined) {
121
121
  const wakes = report.wakes.data;
122
- lines.push("", `Leader wakes: ${wakes.leaderTurns} Turns · ${wakes.withWakeReasons} with reasons`);
122
+ lines.push("", `Leader wakes: ${wakes.leaderRuns} AgentRuns · ${wakes.withWakeReasons} with reasons`);
123
123
  if (wakes.suppressedWakes.status === "ok") {
124
- lines.push(`Suppressed wakes: ${wakes.suppressedWakes.data ?? 0} (scheduler single-flight, not failed Turns)`);
124
+ lines.push(`Suppressed wakes: ${wakes.suppressedWakes.data ?? 0} (scheduler single-flight, not failed AgentRuns)`);
125
125
  }
126
126
  else if (wakes.suppressedWakes.status === "unsupported") {
127
127
  lines.push("Suppressed wakes: unsupported (no quiescence producer in this build)");
@@ -139,11 +139,11 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
139
139
  }
140
140
  if (report.sessions.status === "ok" && report.sessions.data !== undefined) {
141
141
  const sessions = report.sessions.data;
142
- lines.push("", `Sessions: ${sessions.generations} generations · ${sessions.broken} broken · ${sessions.stopped} stopped · ${sessions.other} other`, `Resets: ${sessions.resets} · Historical conversation switches ${sessions.conversationSwitches}`
143
- + ` · lifecycle events ${sessions.lifecycleEvents} · stop failures ${sessions.stopFailures}`, `Terminal by Turn relation: ${sessions.terminalByTurnRelation.postTurnCompleted} post-turn-completed`
144
- + ` · ${sessions.terminalByTurnRelation.turnFailed} turn-failed`
145
- + ` · ${sessions.terminalByTurnRelation.activeTurn} active-turn`
146
- + ` · ${sessions.terminalByTurnRelation.noTurn} no-turn`);
142
+ lines.push("", `Sessions: ${sessions.count} count · ${sessions.broken} broken · ${sessions.stopped} stopped · ${sessions.other} other`, `Resets: ${sessions.resets} · Historical conversation switches ${sessions.conversationSwitches}`
143
+ + ` · lifecycle events ${sessions.lifecycleEvents} · stop failures ${sessions.stopFailures}`, `Terminal by AgentRun relation: ${sessions.terminalByRunRelation.postRunCompleted} post-turn-completed`
144
+ + ` · ${sessions.terminalByRunRelation.runFailed} turn-failed`
145
+ + ` · ${sessions.terminalByRunRelation.activeRun} active-turn`
146
+ + ` · ${sessions.terminalByRunRelation.noRun} no-turn`);
147
147
  }
148
148
  else {
149
149
  lines.push("", ...sectionError("sessions", report));
@@ -185,7 +185,7 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
185
185
  .map(([category, count]) => `${category}:${count}`).join(", ")}`);
186
186
  lines.push(renderTable("Agent errors", [
187
187
  { header: "Task", minWidth: 8, maxWidth: 14 },
188
- { header: "Turn", minWidth: 14, maxWidth: 24 },
188
+ { header: "AgentRun", minWidth: 14, maxWidth: 24 },
189
189
  { header: "Role", minWidth: 8, maxWidth: 12 },
190
190
  { header: "Category", minWidth: 12, maxWidth: 20 },
191
191
  { header: "Code", minWidth: 16, maxWidth: 32 },
@@ -194,7 +194,7 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
194
194
  { header: "Session", minWidth: 12, maxWidth: 16 }
195
195
  ], errors.entries.map((entry) => [
196
196
  entry.taskId,
197
- entry.turnId,
197
+ entry.runId,
198
198
  entry.roleName,
199
199
  entry.category,
200
200
  entry.code,
@@ -223,7 +223,7 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
223
223
  lines.push(renderTable("Task orchestration metrics", [
224
224
  { header: "Task", minWidth: 7, maxWidth: 14 },
225
225
  { header: "Type", minWidth: 8, maxWidth: 12 },
226
- { header: "Turns", minWidth: 4, maxWidth: 6 },
226
+ { header: "AgentRuns", minWidth: 4, maxWidth: 6 },
227
227
  { header: "WIs", minWidth: 3, maxWidth: 5 },
228
228
  { header: "Review F/D/X", minWidth: 12, maxWidth: 16 },
229
229
  { header: "Integration A/F/R", minWidth: 17, maxWidth: 20 },
@@ -233,11 +233,11 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
233
233
  ], orchestration.tasks.map((task) => [
234
234
  task.taskId,
235
235
  task.taskType ?? "unspecified",
236
- String(task.turns.total),
236
+ String(task.runs.total),
237
237
  String(task.workItems),
238
238
  `${task.reviews.full}/${task.reviews.delta}/${task.reviews.failed}`,
239
239
  `${task.integrations.attempts}/${task.integrations.failed}/${task.integrations.repeatedIdentities}`,
240
- String(task.providerGenerationsBeforeFirstProgress),
240
+ String(task.providerSessionsBeforeFirstProgress),
241
241
  String(task.terminalWorkspaceCount),
242
242
  String(task.advisories.length)
243
243
  ]), width));
@@ -276,15 +276,15 @@ export function renderExecutionAudit(report, width = defaultTableWidth()) {
276
276
  if (report.topLongRunning.status === "ok" && report.topLongRunning.data !== undefined) {
277
277
  const entries = report.topLongRunning.data;
278
278
  if (entries.length > 0) {
279
- lines.push("", renderTable("Top long-running Turns", [
279
+ lines.push("", renderTable("Top long-running AgentRuns", [
280
280
  { header: "Task", minWidth: 8, maxWidth: 14 },
281
- { header: "Turn", minWidth: 14, maxWidth: 24 },
281
+ { header: "AgentRun", minWidth: 14, maxWidth: 24 },
282
282
  { header: "Role", minWidth: 10, maxWidth: 20 },
283
283
  { header: "Status", minWidth: 8, maxWidth: 10 },
284
284
  { header: "Duration", minWidth: 8, maxWidth: 10 }
285
285
  ], entries.map((entry) => [
286
286
  entry.taskId,
287
- entry.turnId,
287
+ entry.runId,
288
288
  entry.roleName,
289
289
  entry.status,
290
290
  formatDuration(entry.durationMs)
@@ -248,7 +248,7 @@ function bindRole(args, store) {
248
248
  const activeSession = existingSet?.sessions[existingSet.activeAgentId];
249
249
  try {
250
250
  const switched = switchActiveRoleAgent(withBinding, existingSet ?? createRoleSessionSet({ scope: "global", roleName: name }, role.activeAgentId, now), agentId, {
251
- activeTurn: false,
251
+ activeRun: false,
252
252
  nativeProcessRunning: activeSession !== undefined
253
253
  && activeSession.status === "active"
254
254
  }, now);
@@ -67,13 +67,13 @@ function issueGrant(args, store, options) {
67
67
  * Grant issue and revoke carry irreversible authority: they mint or revoke
68
68
  * the capability that lets a managed Agent perform irreversible site changes.
69
69
  * The only accepted origin is the authenticated global Operator Session,
70
- * whose env claims are verified against the durable live session binding by
70
+ * whose native conversation ID is matched against the durable live binding by
71
71
  * isCurrentGlobalOperator.
72
72
  *
73
73
  * Absence of YUI identity vars is deliberately NOT treated as user authority:
74
74
  * a managed Agent can clear its child-process environment, so a "clean"
75
75
  * environment is indistinguishable from a scrubbed managed one. A Task-scoped
76
- * Session, a partial managed identity, and a stale/forged global binding are
76
+ * Session, an absent conversation identity, and a replaced global conversation are
77
77
  * all refused. Caller-supplied --granter/--by labels are not identity; the
78
78
  * recorded granter/revoker is bound to the Operator Session instead.
79
79
  */
@@ -83,8 +83,8 @@ function authorizeGrantOrigin(store, env, usage) {
83
83
  "session. A managed Agent cannot self-issue or self-revoke a " +
84
84
  "capability grant, and a clean environment is not user authority.", usage);
85
85
  }
86
- // isCurrentGlobalOperator verified YUI_AGENT_ID against the durable binding.
87
- return `operator:${env.YUI_AGENT_ID ?? "unknown"}`;
86
+ // Identity comes from the matched durable conversation, not an env label.
87
+ return `operator:${store.getGlobalRole("operator").activeAgentId}`;
88
88
  }
89
89
  function showGrant(args, store) {
90
90
  const usage = "Task grant show usage: yui task grant show <task> <grant-id>.";
@@ -1,4 +1,5 @@
1
1
  import { usageError } from "../errors/cliError.js";
2
+ import { agentAdapterLabel as adapterLabel } from "../agent/adapterCatalog.js";
2
3
  import { createRoleSessionSet } from "../executor/agentExecutor.js";
3
4
  import { listOperatorSessions, projectOperatorStatus, prepareOperatorNewSession, prepareOperatorResumeSession } from "../operator/operatorSessionHistory.js";
4
5
  import { defaultTableWidth, renderTable } from "../output/table.js";
@@ -214,13 +215,6 @@ function requireOperator(store) {
214
215
  throw usageError("Operator is not configured. Run yui setup first.");
215
216
  return role;
216
217
  }
217
- function adapterLabel(adapterId) {
218
- return adapterId === "codex"
219
- ? "Codex"
220
- : adapterId === "claude"
221
- ? "Claude"
222
- : adapterId;
223
- }
224
218
  function requiredValue(value, option) {
225
219
  if (value === undefined || value.startsWith("--") || value.trim().length === 0) {
226
220
  throw usageError(`${option} is required.`);
@@ -555,7 +555,7 @@ function assertNoActiveTaskBinding(store, project, action) {
555
555
  if (references.activeTaskIds.length > 0) {
556
556
  const delivery = [
557
557
  ...references.unresolvedWorkItemRefs,
558
- ...references.activeTurnRefs,
558
+ ...references.activeRunRefs,
559
559
  ...references.unresolvedIntegrationRefs
560
560
  ];
561
561
  throw usageError(`Project cannot be ${action} while an active Task binds it: ${project.id}. `
@@ -846,7 +846,7 @@ async function replaceProject(args, store, options) {
846
846
  }
847
847
  /**
848
848
  * Auditable soft deprecation. The catalog record, checkout, and every
849
- * historical Task/Turn/Review/Integration/Publication reference are retained;
849
+ * historical Task/AgentRun/Review/Integration/Publication reference are retained;
850
850
  * the Project can no longer be bound to new work or maintained. Hard removal
851
851
  * is a separate `project delete` decision.
852
852
  */
@@ -871,7 +871,7 @@ function retireProjectCommand(args, store, options) {
871
871
  `Retired project ${retired.project.id} (${retired.project.name})`,
872
872
  `Reason: ${parsed.reason}`,
873
873
  `Retired by: ${retiredBy} at ${retired.project.retirement?.retiredAt ?? "?"}`,
874
- "The catalog record, checkout, and historical Task/Turn/Review/Integration/Publication evidence are retained.",
874
+ "The catalog record, checkout, and historical Task/AgentRun/Review/Integration/Publication evidence are retained.",
875
875
  ...(retired.references.boundTaskIds.length === 0
876
876
  ? []
877
877
  : [`Historical Task bindings retained: ${retired.references.boundTaskIds.join(", ")}.`]),
@@ -998,7 +998,7 @@ function removeRetiredProjectRecord(store, projectId) {
998
998
  if (references.boundTaskIds.length > 0) {
999
999
  throw usageError(`Project cannot be deleted while Task records reference it: ${latest.id}. `
1000
1000
  + `Bound Tasks: ${references.boundTaskIds.join(", ")}. `
1001
- + "Historical Task/Turn/Review/Integration/Publication evidence must stay resolvable; keep the Project retired instead.");
1001
+ + "Historical Task/AgentRun/Review/Integration/Publication evidence must stay resolvable; keep the Project retired instead.");
1002
1002
  }
1003
1003
  if (!tx.removeProject(latest.id)) {
1004
1004
  throw new Error(`Project was already removed: ${latest.id}.`);
@@ -123,11 +123,11 @@ function collectTaskStatuses(store) {
123
123
  }
124
124
  return statuses;
125
125
  }
126
- /** Workspace paths claimed by active durable Jobs (Turns). */
126
+ /** Workspace paths claimed by active durable Jobs (AgentRuns). */
127
127
  function collectActiveWorkspaceOwnerPaths(store) {
128
128
  const paths = [];
129
129
  for (const task of store.listTasks()) {
130
- for (const run of store.listTurns(task.id)) {
130
+ for (const run of store.listRuns(task.id)) {
131
131
  if (run.status !== "active")
132
132
  continue;
133
133
  const workspace = run.workspace;
@@ -187,7 +187,12 @@ function permissionPatch(binding, parsed) {
187
187
  }
188
188
  const current = binding.config.permission;
189
189
  if (selected !== "configured" && !nativeOptions) {
190
- return structuredClone(current ?? { strategy: "bypass" });
190
+ // Nothing about permission was named, so the binding keeps what it already
191
+ // had. The fallback applies only to a binding that somehow carries no
192
+ // permission at all, and it must be the adapter's own default rather than a
193
+ // fixed `bypass`: ACP defaults to `default`, and defaulting it to bypass
194
+ // here would widen authority the user never granted.
195
+ return structuredClone(current ?? defaultRoleAgentConfig(binding.adapterId).permission);
191
196
  }
192
197
  const permission = current?.strategy === "configured"
193
198
  ? structuredClone(current)
@@ -199,6 +204,15 @@ function permissionPatch(binding, parsed) {
199
204
  if (parsed.has("--approval"))
200
205
  permission.approval = requiredText(parsed.one("--approval"));
201
206
  }
207
+ else if (binding.adapterId === "acp") {
208
+ // An ACP Session's configured permission is exactly one mode id, matched
209
+ // against what the Agent enumerates at launch. Tool rules are a Claude
210
+ // launch-flag concept with no ACP equivalent, so they are excluded above
211
+ // rather than silently written into a config the adapter would reject.
212
+ if (parsed.has("--permission-mode")) {
213
+ permission.mode = requiredText(parsed.one("--permission-mode"));
214
+ }
215
+ }
202
216
  else {
203
217
  if (parsed.has("--permission-mode")) {
204
218
  permission.mode = requiredText(parsed.one("--permission-mode"));
@@ -242,16 +256,22 @@ function assertAgentOptionConflicts(parsed) {
242
256
  }
243
257
  function assertAdapterOptions(adapterId, parsed) {
244
258
  const codex = ["--sandbox", "--approval", "--search", "--clear-search"];
245
- const claude = [
246
- "--permission-mode",
259
+ const tools = [
247
260
  "--allowed-tool", "--clear-allowed-tools",
248
261
  "--disallowed-tool", "--clear-disallowed-tools"
249
262
  ];
250
263
  if (adapterId !== "codex" && codex.some((option) => parsed.has(option))) {
251
264
  throw usageError("Sandbox, approval, and search settings are only supported by Codex.");
252
265
  }
253
- if (adapterId !== "claude" && claude.some((option) => parsed.has(option))) {
254
- throw usageError("Permission mode and tool rules are only supported by Claude.");
266
+ if (adapterId !== "claude" && tools.some((option) => parsed.has(option))) {
267
+ throw usageError("Tool rules are only supported by Claude.");
268
+ }
269
+ // `--permission-mode` is shared: Claude takes its own permission mode as a
270
+ // launch flag, and ACP selects a session mode the Agent enumerated. Codex has
271
+ // neither, so it stays excluded. Which mode ids are valid is not decided here
272
+ // — for ACP only the live Session can say, and that check happens there.
273
+ if (adapterId !== "claude" && adapterId !== "acp" && parsed.has("--permission-mode")) {
274
+ throw usageError("Permission mode is only supported by Claude and ACP Agents.");
255
275
  }
256
276
  }
257
277
  function assertPairs(parsed, pairs) {