@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
@@ -2,7 +2,7 @@ import { usageError } from "../errors/cliError.js";
2
2
  import { activeLiveRoleAgentSession } from "../executor/agentExecutor.js";
3
3
  import { hasRuntimeLifecycleWork, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
4
4
  /**
5
- * Runtime launch reservation and cleanup are ownership obligations for a Role
5
+ * Explicit runtime cleanup is an ownership obligation for a Role
6
6
  * identity. Mutating or recreating that identity while either obligation is
7
7
  * queued can make the controller act on a different launch configuration.
8
8
  */
@@ -17,7 +17,7 @@ export const LIVE_SESSION_ACKNOWLEDGEMENT_OPTION = "--yes";
17
17
  * the desired configuration is therefore a decision about the next Host
18
18
  * activation, and the Agent making the change is the one that knows whether the
19
19
  * running Session should keep going or be replaced. Report that fact once, here,
20
- * instead of refusing the Turn that later resumes the Session.
20
+ * instead of refusing the AgentRun that later resumes the Session.
21
21
  */
22
22
  export function assertLiveRoleSessionAcknowledged(input) {
23
23
  if (input.acknowledged)
@@ -28,12 +28,11 @@ export function assertLiveRoleSessionAcknowledged(input) {
28
28
  throw usageError([
29
29
  input.endsSession === true
30
30
  ? `Role ${input.roleName} has a live native Session that cannot continue after this `
31
- + "change; its next Turn will need a new Session."
31
+ + "change; its next AgentRun will need a new Session."
32
32
  : `Role ${input.roleName} has a live native Session, so this change applies to its `
33
- + "next Host activation instead of the running one.",
33
+ + "next Host process instead of the running one.",
34
34
  ` Agent: ${session.agentId} (${session.adapterId})`,
35
35
  ` Native Session: ${session.nativeSessionId}`,
36
- ` Host activation: ${session.runtimeGenerationId ?? "not recorded"}`,
37
36
  ` Session launched from desired revision r${session.effective.sourceDesiredRevision}; `
38
37
  + `current desired revision r${input.desiredRevision}`,
39
38
  `Re-run with ${LIVE_SESSION_ACKNOWLEDGEMENT_OPTION} to record the change and keep the Session.`,
@@ -28,7 +28,7 @@ export async function runSessionStopCommand(input) {
28
28
  // lifecycle work that may exist without a current Session candidate.
29
29
  await input.runtime.drainController();
30
30
  await input.runtime.stopController();
31
- // Re-read the authoritative facts after the drain because a Turn that was
31
+ // Re-read the authoritative facts after the drain because a AgentRun that was
32
32
  // already inside a pass may have changed state meanwhile.
33
33
  const settled = input.runtime.snapshot();
34
34
  const blockedAfterDrain = blockedSessions(settled);
@@ -80,7 +80,7 @@ function blockedSessions(input) {
80
80
  });
81
81
  }
82
82
  function blockedStopResult(blocked) {
83
- const details = blocked.map(({ session }) => (`- ${renderSessionOwner(session)} (an active Turn or lifecycle operation is still pending)`));
83
+ const details = blocked.map(({ session }) => (`- ${renderSessionOwner(session)} (an active AgentRun or lifecycle operation is still pending)`));
84
84
  return {
85
85
  output: [
86
86
  `Cannot stop managed Sessions: ${blocked.length} Session(s) are still busy.`,
@@ -101,11 +101,7 @@ function sameStopCandidate(session, candidate) {
101
101
  && session.owner.taskId !== candidate.owner.taskId) {
102
102
  return false;
103
103
  }
104
- return session.agentId === candidate.agentId
105
- && session.adapterId === candidate.adapterId
106
- && session.nativeSessionId === candidate.nativeSessionId
107
- && session.runtimeGenerationId === candidate.runtimeGenerationId
108
- && session.sessionUpdatedAt === candidate.sessionUpdatedAt;
104
+ return session.agentId === candidate.agentId && session.adapterId === candidate.adapterId && session.nativeSessionId === candidate.nativeSessionId && session.sessionUpdatedAt === candidate.sessionUpdatedAt;
109
105
  }
110
106
  function renderSessionOwner(session) {
111
107
  return session.owner.scope === "task"
@@ -0,0 +1,259 @@
1
+ import { createHash } from "node:crypto";
2
+ import { usageError } from "../errors/cliError.js";
3
+ import { currentManagedRuntime } from "../runtime/managedCaller.js";
4
+ import { enqueueWork } from "../coordination/workMailboxQueue.js";
5
+ import { SYSTEM_LEADER_ROLE } from "../role/systemRoles.js";
6
+ import { describeEnvironmentPlan } from "../task/taskActivation.js";
7
+ import { cancelTaskActivation, requestTaskActivation, taskActivationOperationRef } from "../task/taskActivationService.js";
8
+ import { taskLocalActor } from "./taskActor.js";
9
+ /**
10
+ * Explicit Activation requests.
11
+ *
12
+ * Requesting is not activating: this family only records durable intent and
13
+ * returns its operation reference. Adoption stays at the single activation
14
+ * boundary (`yui task activate`, or the Controller once a deferred request is
15
+ * released), where the Task status change and the resource facts commit
16
+ * together.
17
+ */
18
+ export function runTaskActivationCommand(args, store, options) {
19
+ const [command, ...rest] = args;
20
+ switch (command) {
21
+ case "request": return requestActivation(rest, store, options);
22
+ case "cancel": return cancelActivation(rest, store, options);
23
+ case "show": return showActivation(rest, store);
24
+ default:
25
+ throw usageError(command === undefined
26
+ ? "Task activation command is required."
27
+ : `Unknown command: task activation ${command}`);
28
+ }
29
+ }
30
+ const REQUEST_USAGE = "Task activation request usage: yui task activation request <task> "
31
+ + "--request-id <id> --environment <empty|scratch|local:<resource>:<read|write>>.";
32
+ /**
33
+ * Records the request and returns its reference immediately.
34
+ *
35
+ * When the caller is the Leader's own running planning Turn the request is
36
+ * stored as deferred and this command still returns right away: a synchronous
37
+ * tool must never wait for the Turn it is running inside. The Turn keeps going
38
+ * and the request is adopted after it terminates, against the facts that are
39
+ * current then.
40
+ */
41
+ function requestActivation(args, store, options) {
42
+ const parsed = parseTail(args, new Set(["--request-id", "--environment"]), REQUEST_USAGE);
43
+ exactPositionals(parsed.positionals, 1, REQUEST_USAGE);
44
+ const taskId = parsed.positionals[0];
45
+ const requestId = requiredOption(parsed.options, "--request-id", REQUEST_USAGE);
46
+ const environmentPlan = parseEnvironmentPlan(requiredOption(parsed.options, "--environment", REQUEST_USAGE), REQUEST_USAGE);
47
+ const now = options.now?.() ?? new Date();
48
+ const caller = activationCaller(store, options, taskId);
49
+ const result = attempt(REQUEST_USAGE, () => requestTaskActivation(store, {
50
+ taskId,
51
+ requestId,
52
+ actorId: caller.actorId,
53
+ authorityRef: caller.authorityRef,
54
+ environmentPlan,
55
+ ...(caller.planningRunId === undefined ? {} : { callerRunId: caller.planningRunId })
56
+ }, now));
57
+ // An immediate request has nothing left to wait for, so ask the Controller to
58
+ // pick it up. A deferred one is released by its planning Turn's termination.
59
+ // The signal is only promptness: the durable request is what is authoritative.
60
+ if (result.created && result.startMode === "immediate") {
61
+ store.transaction((tx) => {
62
+ enqueueWork(tx, { kind: "task", taskId }, "activation-requested", now, [{ type: "task", id: taskId }]);
63
+ });
64
+ void options.runtime?.notifyMailboxChanged?.({ kind: "task", taskId });
65
+ }
66
+ const request = result.request;
67
+ const lines = [
68
+ `${result.created ? "Requested" : "Existing"} activation ${result.operationRef}`,
69
+ `Task: ${taskId} (draft)`,
70
+ `Start: ${result.startMode}${result.afterPlanningRun === undefined ? "" : ` after ${taskId}/${result.afterPlanningRun}`}`,
71
+ `Environment: ${describeEnvironmentPlan(request.environmentPlan)}`,
72
+ `Disposition: ${request.disposition}`,
73
+ result.startMode === "after-planning-turn"
74
+ ? "This reference is returned now; the request is adopted after the planning Turn ends."
75
+ : `Adopt it with: yui task activate ${taskId}`
76
+ ];
77
+ return output(`${lines.join("\n")}\n`, {
78
+ operationRef: result.operationRef,
79
+ created: result.created,
80
+ startMode: result.startMode,
81
+ ...(result.afterPlanningRun === undefined
82
+ ? {}
83
+ : { afterPlanningRun: result.afterPlanningRun }),
84
+ request
85
+ });
86
+ }
87
+ /** A cancelled request is never adopted, even if the same id is retried. */
88
+ function cancelActivation(args, store, options) {
89
+ const usage = "Task activation cancel usage: yui task activation cancel <task> "
90
+ + "--request-id <id> --reason <text>.";
91
+ const parsed = parseTail(args, new Set(["--request-id", "--reason"]), usage);
92
+ exactPositionals(parsed.positionals, 1, usage);
93
+ const taskId = parsed.positionals[0];
94
+ const requestId = requiredOption(parsed.options, "--request-id", usage);
95
+ const reason = requiredOption(parsed.options, "--reason", usage);
96
+ // Cancelling is a Task-local decision: the same authority that may request
97
+ // activation may withdraw it, and withdrawal is always the safe direction.
98
+ taskLocalActor(store, options.environment, taskId);
99
+ const now = options.now?.() ?? new Date();
100
+ const request = attempt(usage, () => cancelTaskActivation(store, taskId, requestId, reason, now));
101
+ return output(`Cancelled activation ${taskActivationOperationRef(taskId, requestId)}\n`
102
+ + `Reason: ${request.outcome ?? reason}\n`, { request });
103
+ }
104
+ function showActivation(args, store) {
105
+ const usage = "Task activation show usage: yui task activation show <task>.";
106
+ const parsed = parseTail(args, new Set(), usage);
107
+ exactPositionals(parsed.positionals, 1, usage);
108
+ const task = requireTask(store, parsed.positionals[0]);
109
+ const request = task.activationRequest;
110
+ // The recent terminal requests the Task still displays. The refusal itself is
111
+ // enforced from the durable activation event ledger, not this bounded list;
112
+ // showing it just lets an Operator diagnosing a refusal see the recent
113
+ // outcomes at a glance instead of only the latest request. An id can be
114
+ // refused without appearing here once it has aged out of the display bound.
115
+ const settled = task.settledActivationRequests ?? [];
116
+ const settledLines = settled.length === 0 ? [] : [
117
+ "",
118
+ `Earlier requests (${settled.length}, oldest first):`,
119
+ ...settled.map((entry) => (` ${entry.operation.requestId}: ${entry.disposition}`
120
+ + ` / effect ${entry.operation.effect}`
121
+ + ` / ${describeEnvironmentPlan(entry.environmentPlan)}`
122
+ + `${entry.outcome === undefined ? "" : ` — ${entry.outcome}`}`))
123
+ ];
124
+ if (request === undefined) {
125
+ return output(`No activation request exists for ${task.id} (${task.status}).\n`
126
+ + (settledLines.length === 0 ? "" : `${settledLines.join("\n")}\n`), { task, request: null, settledRequests: settled });
127
+ }
128
+ const lines = [
129
+ `Activation ${taskActivationOperationRef(task.id, request.operation.requestId)}`,
130
+ `Task: ${task.id} (${task.status})`,
131
+ `Start: ${request.startMode}${request.afterPlanningRun === undefined ? "" : ` after ${task.id}/${request.afterPlanningRun}`}`,
132
+ `Environment: ${describeEnvironmentPlan(request.environmentPlan)}`,
133
+ `Disposition: ${request.disposition}`,
134
+ `Effect: ${request.operation.effect}`,
135
+ ...(request.preparationId === undefined
136
+ ? []
137
+ : [`Adopted environment: ${request.preparationId}`]),
138
+ ...(request.outcome === undefined ? [] : [`Outcome: ${request.outcome}`]),
139
+ `Requested at: ${request.requestedAt}`,
140
+ ...settledLines
141
+ ];
142
+ return output(`${lines.join("\n")}\n`, { task, request, settledRequests: settled });
143
+ }
144
+ /**
145
+ * Resolves who is requesting, and whether they are running inside this Task's
146
+ * own planning Turn.
147
+ *
148
+ * The start mode is derived from that fact rather than accepted from the
149
+ * caller: a request can only defer to a Turn the caller is actually in, and a
150
+ * Turn that is not an active planning Turn is simply not a deferral target.
151
+ */
152
+ function activationCaller(store, options, taskId) {
153
+ const actor = taskLocalActor(store, options.environment, taskId);
154
+ if (actor === "leader") {
155
+ const runtime = currentManagedRuntime(store, options.environment, taskId, SYSTEM_LEADER_ROLE);
156
+ if (runtime === undefined) {
157
+ throw usageError(`Task-local Leader authority requires the current Provider AgentRun: ${taskId}.`);
158
+ }
159
+ const current = runtime.currentRunId === undefined
160
+ ? null
161
+ : store.getRun(taskId, runtime.currentRunId);
162
+ return {
163
+ actorId: `task:${taskId}/role:${SYSTEM_LEADER_ROLE}`,
164
+ // Non-secret binding fingerprint of the live Session, matching the Job
165
+ // boundary: reattaching the same Session keeps it, replacing it does not.
166
+ authorityRef: fingerprint([
167
+ runtime.agentId,
168
+ runtime.adapterId,
169
+ runtime.nativeSessionId
170
+ ]),
171
+ ...(current?.status === "active" && current.purpose === "planning"
172
+ ? { planningRunId: current.id }
173
+ : {})
174
+ };
175
+ }
176
+ if (actor === "operator") {
177
+ return {
178
+ actorId: "global:operator",
179
+ authorityRef: fingerprint([
180
+ "operator",
181
+ store.getGlobalRole("operator")?.activeAgentId ?? "operator"
182
+ ])
183
+ };
184
+ }
185
+ return { actorId: "user:local", authorityRef: fingerprint(["user", "local-terminal"]) };
186
+ }
187
+ function parseEnvironmentPlan(value, usage) {
188
+ if (value === "empty")
189
+ return { kind: "empty" };
190
+ if (value === "scratch")
191
+ return { kind: "scratch" };
192
+ const local = /^local:(?<resourceId>[^:]+):(?<access>read|write)$/u.exec(value);
193
+ if (local?.groups !== undefined) {
194
+ return {
195
+ kind: "local",
196
+ resourceId: local.groups.resourceId,
197
+ access: local.groups.access
198
+ };
199
+ }
200
+ throw usageError(`Environment plan is invalid: ${value}. Use empty, scratch, or local:<resource>:<read|write>.`, usage);
201
+ }
202
+ function fingerprint(parts) {
203
+ return createHash("sha256").update(JSON.stringify(parts)).digest("hex");
204
+ }
205
+ /** Domain rejections are caller mistakes here, so they carry the usage text. */
206
+ function attempt(usage, action) {
207
+ try {
208
+ return action();
209
+ }
210
+ catch (error) {
211
+ throw usageError(error instanceof Error ? error.message : String(error), usage);
212
+ }
213
+ }
214
+ function requireTask(store, taskId) {
215
+ const task = store.getTask(taskId);
216
+ if (task === null)
217
+ throw usageError(`Task not found: ${taskId}.`);
218
+ return task;
219
+ }
220
+ function parseTail(args, valueOptions, usage) {
221
+ const positionals = [];
222
+ const options = new Map();
223
+ for (let index = 0; index < args.length; index += 1) {
224
+ const value = args[index];
225
+ if (!value.startsWith("--")) {
226
+ positionals.push(value);
227
+ continue;
228
+ }
229
+ if (!valueOptions.has(value))
230
+ throw usageError(`Unsupported option: ${value}.`, usage);
231
+ if (options.has(value)) {
232
+ throw usageError(`Option may only be specified once: ${value}.`, usage);
233
+ }
234
+ const optionValue = args[index + 1];
235
+ if (optionValue === undefined || optionValue.startsWith("--")) {
236
+ throw usageError(`${value} is required.`, usage);
237
+ }
238
+ options.set(value, optionValue);
239
+ index += 1;
240
+ }
241
+ return { positionals, options };
242
+ }
243
+ function exactPositionals(values, count, usage) {
244
+ if (values.length !== count || values.some((value) => value.trim().length === 0)) {
245
+ throw usageError(usage);
246
+ }
247
+ }
248
+ function requiredOption(options, name, usage) {
249
+ const value = options.get(name)?.trim();
250
+ if (value === undefined || value.length === 0) {
251
+ throw usageError(`${name} is required.`, usage);
252
+ }
253
+ return value;
254
+ }
255
+ function output(value, data) {
256
+ return data === undefined
257
+ ? { kind: "output", output: value }
258
+ : { kind: "output", output: value, data };
259
+ }
@@ -1,5 +1,5 @@
1
1
  import { usageError } from "../errors/cliError.js";
2
- import { MANAGED_CALLER_KEY_ENV, currentManagedRuntime } from "../runtime/managedCaller.js";
2
+ import { MANAGED_NATIVE_SESSION_ENV, currentManagedRuntime } from "../runtime/managedCaller.js";
3
3
  const LEADER_ROLE = "leader";
4
4
  export function taskActor(environment, taskId) {
5
5
  const env = environment ?? {};
@@ -18,7 +18,7 @@ export function taskActor(environment, taskId) {
18
18
  }
19
19
  if (env.YUI_ROLE !== undefined
20
20
  || env.YUI_AGENT_ID !== undefined
21
- || env[MANAGED_CALLER_KEY_ENV] !== undefined) {
21
+ || env[MANAGED_NATIVE_SESSION_ENV] !== undefined) {
22
22
  throw usageError("Managed Agent identity is incomplete; refusing to infer user authority.");
23
23
  }
24
24
  return "user";
@@ -27,15 +27,28 @@ export function taskActor(environment, taskId) {
27
27
  * Resolve authority for a recoverable Task-local mutation. A managed Leader
28
28
  * does not gain that authority from long-lived process environment alone. Its
29
29
  * process proves only that Yui launched it for this Task Role; whether it is
30
- * still the current runtime, and which Turn is current, are read from durable
31
- * state at command time. Plain-user and global-Operator behavior is unchanged.
30
+ * still the current Session is read from durable state at command time.
31
+ * Execution occupancy is not management authority.
32
32
  */
33
33
  export function taskLocalActor(store, environment, taskId) {
34
34
  const actor = taskActor(environment, taskId);
35
35
  if (actor !== "leader")
36
36
  return actor;
37
- if (taskLeaderActionTurnId(store, taskId, environment) === undefined) {
38
- throw usageError(`Task-local Leader authority requires the current Provider Turn: ${taskId}.`);
37
+ if (currentManagedRuntime(store, environment, taskId, LEADER_ROLE) === undefined) {
38
+ throw usageError(`Task-local Leader authority requires the current native Session: ${taskId}.`);
39
+ }
40
+ return actor;
41
+ }
42
+ /** Planning conversations may save facts; delivery checks the immutable
43
+ * native Session authority, not the Task's newly activated status.
44
+ */
45
+ export function assertTaskDeliveryAuthority(store, environment, taskId) {
46
+ const actor = taskLocalActor(store, environment, taskId);
47
+ if (actor !== "leader")
48
+ return actor;
49
+ const caller = currentManagedRuntime(store, environment, taskId, LEADER_ROLE);
50
+ if (caller?.executionAuthority !== "delivery") {
51
+ throw usageError("This native Session has planning authority, not delivery authority. Use a delivery Session for this operation.");
39
52
  }
40
53
  return actor;
41
54
  }
@@ -50,31 +63,15 @@ export function projectActor(environment) {
50
63
  }
51
64
  if (env.YUI_ROLE !== undefined
52
65
  || env.YUI_AGENT_ID !== undefined
53
- || env[MANAGED_CALLER_KEY_ENV] !== undefined) {
66
+ || env[MANAGED_NATIVE_SESSION_ENV] !== undefined) {
54
67
  throw usageError("Managed Agent identity is incomplete; refusing to infer user authority.");
55
68
  }
56
69
  return "user";
57
70
  }
58
71
  /**
59
- * rr8: Resolve the caller identity for a `job.start`/`job.cancel` request from
60
- * the managed Session environment. The Controller verifies the Agent Session
61
- * and its scope; Role does not narrow Task control authority.
62
- *
63
- * The identity is Controller-verified rather than self-reported. A managed
64
- * Task Session reports only its immutable self-identity (Task, Role, caller
65
- * key); the Controller resolves the current Turn from durable state, so no
66
- * Turn is ever carried across Turns in a long-lived process environment.
67
- *
68
- * rr13: A managed Task Session also carries `callerKey` — the
69
- * `YUI_JOB_CALLER_KEY` injected at its native Session launch. The Controller
70
- * hashes it and compares against the durable `jobCallerKeyHashes` map, so a
71
- * client that reads durable state cannot replay the caller. A `user`-scope
72
- * caller is rejected outright for job.start/job.cancel (fail-closed); a
73
- * managed global Agent carries its own durable Session identity.
74
- *
75
- * A managed Task Session may only start jobs for its own Task. An incomplete
76
- * managed identity (role/agent/caller-key vars without a scope) is rejected
77
- * rather than silently downgraded to user authority.
72
+ * Resolve the caller's Task, Role and native Session identity. The Controller
73
+ * verifies it against durable state and supplies the current AgentRun. A Task
74
+ * caller cannot control another Task; an incomplete identity is not a user.
78
75
  */
79
76
  export function resolveJobCaller(environment, taskId) {
80
77
  const env = environment ?? {};
@@ -83,17 +80,14 @@ export function resolveJobCaller(environment, taskId) {
83
80
  throw usageError("A managed Task Session may not start Jobs for a different Task.");
84
81
  }
85
82
  const role = env.YUI_ROLE;
86
- // rr13: Carry the per-Session caller key so the Controller can verify the
87
- // channel binding. Absent on a managed Session = fail-closed at the
88
- // Controller boundary.
89
- const callerKey = env[MANAGED_CALLER_KEY_ENV];
90
- // The Turn is deliberately absent: the Controller reads the current Turn
83
+ const nativeSessionId = env.CODEX_THREAD_ID ?? env.YUI_NATIVE_SESSION_ID;
84
+ // The AgentRun is deliberately absent: the Controller reads the current AgentRun
91
85
  // for this Task Role from durable state when it authorizes the request.
92
86
  return {
93
87
  scope: "task",
94
88
  taskId,
95
89
  role,
96
- ...(callerKey === undefined ? {} : { callerKey })
90
+ ...(nativeSessionId === undefined ? {} : { nativeSessionId })
97
91
  };
98
92
  }
99
93
  if (env.YUI_SESSION_SCOPE === "global") {
@@ -102,28 +96,13 @@ export function resolveJobCaller(environment, taskId) {
102
96
  role: env.YUI_ROLE,
103
97
  agentId: env.YUI_AGENT_ID,
104
98
  adapterId: env.YUI_ADAPTER_ID,
105
- runtimeGenerationId: env.YUI_RUNTIME_GENERATION_ID,
106
- nativeSessionId: env.YUI_NATIVE_SESSION_ID
99
+ nativeSessionId: env.CODEX_THREAD_ID ?? env.YUI_NATIVE_SESSION_ID
107
100
  };
108
101
  }
109
102
  if (env.YUI_ROLE !== undefined
110
103
  || env.YUI_AGENT_ID !== undefined
111
- || env[MANAGED_CALLER_KEY_ENV] !== undefined) {
104
+ || env[MANAGED_NATIVE_SESSION_ENV] !== undefined) {
112
105
  throw usageError("Managed Agent identity is incomplete; refusing to infer user authority.");
113
106
  }
114
107
  return { scope: "user" };
115
108
  }
116
- /**
117
- * Resolve the current Task Leader Turn for event attribution and Task-local
118
- * Leader authority.
119
- *
120
- * A long-lived managed process cannot carry this: its environment is frozen at
121
- * launch, so any Turn it holds is stale the moment Yui advances the Task. The
122
- * Turn is therefore read from durable state, and the process only has to prove
123
- * that it is still the current runtime of the Leader Role through its
124
- * per-Session caller key. When the Role has no active Turn, or the process has
125
- * been superseded, there is simply no Leader action window.
126
- */
127
- export function taskLeaderActionTurnId(store, taskId, environment) {
128
- return currentManagedRuntime(store, environment, taskId, LEADER_ROLE)?.currentTurnId;
129
- }