@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
@@ -14,6 +14,7 @@ import { acknowledgeUnknownDurableJob, createDurableJob, durableJobIdempotencyKe
14
14
  import { activeLiveRoleAgentSession } from "../executor/agentExecutor.js";
15
15
  import { CallAuthority } from "../kernel/callAuthority.js";
16
16
  import { redactLaunchText } from "../runtime/launchDiagnostics.js";
17
+ import { requireManagedTaskCaller } from "../runtime/managedCaller.js";
17
18
  export function createDurableJobControl(store) {
18
19
  const authority = createJobCallAuthority(store);
19
20
  return {
@@ -158,16 +159,22 @@ function jobAuthorityBinding(store, scope, roleName, taskId) {
158
159
  // Authenticate the live launch at ingress, but bind accepted Jobs to the
159
160
  // caller's durable Session identity, not its disposable Host generation.
160
161
  if (scope === "task") {
161
- const role = store.getRole(taskId, roleName);
162
162
  const sessions = store.getTaskRoleSessionSet(taskId, roleName);
163
163
  const session = activeLiveRoleAgentSession(sessions);
164
- const hash = role === null ? null : store.getJobCallerKeyHash(taskId, roleName, role.activeAgentId);
165
- if (hash === null || role === null || sessions?.activeAgentId !== role.activeAgentId
166
- || session === null || session.agentId !== role.activeAgentId) {
164
+ if (session === null) {
167
165
  throw jobDomainError("Current Job caller Session is unavailable.");
168
166
  }
167
+ try {
168
+ requireManagedTaskCaller(store, {
169
+ YUI_SESSION_SCOPE: "task", YUI_TASK_ID: taskId, YUI_ROLE: roleName,
170
+ YUI_NATIVE_SESSION_ID: session.nativeSessionId
171
+ });
172
+ }
173
+ catch {
174
+ throw jobDomainError("Job caller binding was revoked; no execution was started.");
175
+ }
169
176
  return createHash("sha256").update(JSON.stringify([
170
- hash, session.agentId, session.adapterId, session.nativeSessionId
177
+ session.agentId, session.adapterId, session.nativeSessionId
171
178
  ])).digest("hex");
172
179
  }
173
180
  const role = store.getGlobalRole(roleName);
@@ -212,6 +219,12 @@ function assertNonSecretJobInput(params) {
212
219
  function validateStartParams(store, params) {
213
220
  validateJobTarget(store, params);
214
221
  assertCallerAuthorized(store, params.caller, params.taskId);
222
+ if (params.caller.scope === "task") {
223
+ const session = store.getTaskRoleSessionSet(params.taskId, params.caller.role);
224
+ if (session?.sessions[session.activeAgentId]?.effective.executionAuthority !== "delivery") {
225
+ throw jobControlError("UNAUTHORIZED", "Managed workspace Jobs require a delivery Session; Task activation does not upgrade planning authority.");
226
+ }
227
+ }
215
228
  }
216
229
  function validateJobTarget(store, params) {
217
230
  // The Task must be active — a terminal Task cannot run jobs.
@@ -303,69 +316,39 @@ function validateJobTarget(store, params) {
303
316
  /**
304
317
  * rr8/rr12: Bind the declared job owner to the caller's managed identity. The
305
318
  * Controller validates the declared owner/workspace and verifies the caller
306
- * against durable Turn/Session state — a self-reported role or scope is never
319
+ * against durable AgentRun/Session state — a self-reported role or scope is never
307
320
  * authority on its own. The rules:
308
321
  *
309
322
  * - `user` (non-managed): rejected because it has no managed Session identity.
310
323
  * - `global`: full Task authority after current Role Session verification.
311
324
  * - `task` + mismatched taskId: rejected.
312
- * - `task` + missing `turnId`: rejected (a managed caller must bind to a Turn).
313
- * - `task` + Turn not found / not active / `roleName !== role`: rejected — the
314
- * claimed Role must be the real Role of an active Turn.
315
- * - `task`: full authority inside the matching Task after active Turn and
316
- * per-Session caller-key verification; Role does not narrow it.
325
+ * - A non-Leader Task caller requires its current active Assignment.
326
+ * - A Leader Task caller requires its current, unrevoked native Session.
327
+ * - `task`: authority inside the matching Task after current Session and
328
+ * native Session verification; Role does not narrow it.
317
329
  */
318
330
  /**
319
- * rr13: `job.start`/`job.cancel` caller authorization at the Controller
320
- * boundary. Every identity claim the Controller can verify from durable state
321
- * (role and turnId) is replayable by any client in the
322
- * same authoritative Controller. The channel itself is therefore not
323
- * authenticated by those claims alone. A non-replayable per-Session caller key
324
- * closes the gap:
325
- *
326
- * - `user` scope: **rejected outright** for start/cancel. A bare shell or a
327
- * managed Session that sheds its identity has no managed Session binding.
328
- * - `global` scope: verified against the current global Role Session.
329
- * - `task` scope: the caller must present `callerKey` — the
330
- * `YUI_JOB_CALLER_KEY` injected at its native Session launch. The Controller
331
- * hashes it (SHA-256) and compares against the durable `jobCallerKeyHashes`
332
- * map for the caller's Role + Agent. An absent hash or a
333
- * mismatched key is UNAUTHORIZED.
334
- *
335
- * The existing Turn binding checks run after the key check, so a forged
336
- * identity that also lacks the key is rejected at the channel boundary.
331
+ * Verify the caller's current native Session and Task scope. This local Home
332
+ * identity contract does not defend against another process with the same
333
+ * user's filesystem access. Bare user calls cannot start or cancel Jobs.
337
334
  */
338
335
  function assertCallerAuthorized(store, caller, taskId) {
339
336
  if (caller.scope === "user") {
340
337
  // rr13: A user-scope caller has no per-Session channel binding. Every
341
338
  // durable-state claim it could carry is replayable
342
339
  // by any client in the same Home. Reject outright (fail-closed).
343
- throw jobControlError("UNAUTHORIZED", "job.start/job.cancel requires a managed Session caller key; user scope is rejected.");
340
+ throw jobControlError("UNAUTHORIZED", "job.start/job.cancel requires a managed native Session; user scope is rejected.");
344
341
  }
345
342
  if (caller.scope === "global") {
346
343
  const roleName = caller.role;
347
- const agentId = caller.agentId;
344
+ const agentId = roleName === undefined ? undefined : store.getGlobalRole(roleName)?.activeAgentId;
348
345
  const role = roleName === undefined ? null : store.getGlobalRole(roleName);
349
346
  const binding = role === null || agentId === undefined
350
347
  ? undefined
351
348
  : role.agentBindings[role.activeAgentId];
352
349
  const sessions = roleName === undefined ? null : store.getGlobalRoleSessionSet(roleName);
353
350
  const session = activeLiveRoleAgentSession(sessions);
354
- if (role === null
355
- || binding === undefined
356
- || agentId === undefined
357
- || caller.adapterId === undefined
358
- || caller.runtimeGenerationId === undefined
359
- || sessions === null
360
- || sessions.activeAgentId !== role.activeAgentId
361
- || session === null
362
- || binding.agentId !== agentId
363
- || binding.adapterId !== caller.adapterId
364
- || session.agentId !== agentId
365
- || session.adapterId !== caller.adapterId
366
- || session.runtimeGenerationId !== caller.runtimeGenerationId
367
- || (caller.nativeSessionId !== undefined
368
- && session.nativeSessionId !== caller.nativeSessionId)) {
351
+ if (role === null || binding === undefined || agentId === undefined || sessions === null || sessions.activeAgentId !== role.activeAgentId || session === null || binding.agentId !== agentId || session.agentId !== agentId || session.adapterId !== binding.adapterId || caller.nativeSessionId === undefined || session.nativeSessionId !== caller.nativeSessionId) {
369
352
  throw jobControlError("UNAUTHORIZED", "DurableJob control requires the current managed global Agent Session.");
370
353
  }
371
354
  return;
@@ -373,37 +356,29 @@ function assertCallerAuthorized(store, caller, taskId) {
373
356
  if (caller.taskId !== taskId) {
374
357
  throw jobControlError("UNAUTHORIZED", "A managed Task Session may not start or cancel Jobs for a different Task.");
375
358
  }
376
- // The Turn is resolved from durable state rather than presented by the
377
- // caller: a long-lived Session process cannot hold a current Turn in its
378
- // frozen environment, and its own claim would add nothing the store does
379
- // not already own.
380
- const run = caller.role === undefined ? null : store.getActiveTurn(taskId, caller.role);
381
- const currentRole = caller.role === undefined ? null : store.getRole(taskId, caller.role);
382
- if (run === null || run.status !== "active" || currentRole === null
383
- || currentRole.activeAgentId !== run.effective.agentId) {
384
- throw jobControlError("UNAUTHORIZED", "A managed Task Session's Role is not bound to an active Turn.");
385
- }
386
- const sessions = store.getTaskRoleSessionSet(taskId, currentRole.name);
359
+ // A long-lived Session is the Leader's identity, not its execution
360
+ // occupancy. Non-Leader callers still require their active Assignment.
361
+ const current = (() => {
362
+ try {
363
+ return requireManagedTaskCaller(store, {
364
+ YUI_SESSION_SCOPE: "task", YUI_TASK_ID: taskId, YUI_ROLE: caller.role,
365
+ YUI_NATIVE_SESSION_ID: caller.nativeSessionId
366
+ });
367
+ }
368
+ catch (error) {
369
+ throw jobControlError("UNAUTHORIZED", error instanceof Error ? error.message : String(error));
370
+ }
371
+ })();
372
+ if (current.roleName !== "leader" && current.currentRunId === undefined) {
373
+ throw jobControlError("UNAUTHORIZED", "A managed Task Session's Role is not bound to an active AgentRun.");
374
+ }
375
+ const sessions = store.getTaskRoleSessionSet(taskId, current.roleName);
387
376
  const session = activeLiveRoleAgentSession(sessions);
388
- if (sessions?.activeAgentId !== currentRole.activeAgentId || session === null
389
- || session.agentId !== run.effective.agentId || session.adapterId !== run.effective.adapterId) {
377
+ if (sessions?.activeAgentId !== current.agentId || session === null
378
+ || session.agentId !== current.agentId || session.adapterId !== current.adapterId
379
+ || caller.nativeSessionId === undefined || session.nativeSessionId !== caller.nativeSessionId) {
390
380
  throw jobControlError("UNAUTHORIZED", "DurableJob control requires the current live Task Session.");
391
381
  }
392
- // rr13: Verify the non-replayable per-Session caller key. The key is injected
393
- // at native Session launch and never persisted in plaintext; only its SHA-256
394
- // hash is durable. A client with database read access can see the hash but cannot
395
- // recover the key.
396
- if (caller.callerKey === undefined) {
397
- throw jobControlError("UNAUTHORIZED", "job.start/job.cancel requires a managed Session caller key.");
398
- }
399
- const expectedHash = store.getJobCallerKeyHash(taskId, caller.role ?? "", currentRole.activeAgentId);
400
- if (expectedHash === null) {
401
- throw jobControlError("UNAUTHORIZED", "The managed Session has no durable caller key; it must be relaunched.");
402
- }
403
- const presentedHash = createHash("sha256").update(caller.callerKey).digest("hex");
404
- if (presentedHash !== expectedHash) {
405
- throw jobControlError("UNAUTHORIZED", "The managed Session caller key does not match the durable hash.");
406
- }
407
382
  }
408
383
  /**
409
384
  * Resolve the managed workspace for the job's owner. Returns null if no
@@ -448,7 +423,7 @@ function readGitHead(path) {
448
423
  }
449
424
  }
450
425
  function isTerminalWorkItemStatus(status) {
451
- return status === "completed" || status === "failed" || status === "retired";
426
+ return status === "accepted" || status === "retired";
452
427
  }
453
428
  /**
454
429
  * Strict `job.start` params parsing. Throws CoreApplicationError-shaped errors
@@ -617,8 +592,8 @@ function parseCaller(value) {
617
592
  }
618
593
  const record = value;
619
594
  const allowed = new Set([
620
- "scope", "taskId", "role", "agentId", "adapterId", "runtimeGenerationId", "nativeSessionId",
621
- "turnId", "callerKey"
595
+ "scope", "taskId", "role", "agentId", "adapterId", "nativeSessionId",
596
+ "runId"
622
597
  ]);
623
598
  for (const key of Object.keys(record)) {
624
599
  if (!allowed.has(key)) {
@@ -638,22 +613,16 @@ function parseCaller(value) {
638
613
  const role = optionalId("role");
639
614
  const agentId = optionalId("agentId");
640
615
  const adapterId = optionalId("adapterId");
641
- const runtimeGenerationId = optionalId("runtimeGenerationId");
642
616
  const nativeSessionId = optionalId("nativeSessionId");
643
- const turnId = optionalId("turnId");
644
- const callerKey = record.callerKey === undefined
645
- ? undefined
646
- : requiredId(record.callerKey, "job caller callerKey");
617
+ const runId = optionalId("runId");
647
618
  return {
648
619
  scope: record.scope,
649
620
  ...(taskId === undefined ? {} : { taskId }),
650
621
  ...(role === undefined ? {} : { role }),
651
622
  ...(agentId === undefined ? {} : { agentId }),
652
623
  ...(adapterId === undefined ? {} : { adapterId }),
653
- ...(runtimeGenerationId === undefined ? {} : { runtimeGenerationId }),
654
624
  ...(nativeSessionId === undefined ? {} : { nativeSessionId }),
655
- ...(turnId === undefined ? {} : { turnId }),
656
- ...(callerKey === undefined ? {} : { callerKey })
625
+ ...(runId === undefined ? {} : { runId })
657
626
  };
658
627
  }
659
628
  function parseStringMap(value, label) {
@@ -32,11 +32,10 @@ export function createRuntimeResourceActivityTracker() {
32
32
  || roleKey === undefined)
33
33
  return reject();
34
34
  const identityKey = JSON.stringify([
35
- identity.turnId,
35
+ identity.runId,
36
36
  identity.agentId,
37
37
  identity.adapterId,
38
- identity.nativeSessionId ?? null,
39
- identity.runtimeGenerationId ?? null
38
+ identity.nativeSessionId ?? null
40
39
  ]);
41
40
  const current = {
42
41
  identity: identityKey,
@@ -113,7 +112,7 @@ export function buildControllerResourceInventory(facts) {
113
112
  for (const process of paneProcesses)
114
113
  claimed.add(process.pid);
115
114
  const role = findRole(homeFact.roles, pane);
116
- const terminalIsolation = role?.taskStatus === "retired"
115
+ const terminalIsolation = (role?.taskStatus === "cancelled" && role.taskRetirementIsolated === true)
117
116
  || role?.taskStatus === "archived";
118
117
  resources.push(processResource({
119
118
  kind: "agent-session",
@@ -123,7 +122,7 @@ export function buildControllerResourceInventory(facts) {
123
122
  : terminalIsolation ? "safe" : "protected",
124
123
  reasonCode: role === undefined
125
124
  ? pane.dead ? "dead-orphan-pane" : "orphan-pane"
126
- : terminalIsolation ? `${role.taskStatus}-task-pane` : "owned-role-pane",
125
+ : terminalIsolation ? (role.taskStatus === "cancelled" ? "retired-task-pane" : "archived-task-pane") : "owned-role-pane",
127
126
  yuiHome,
128
127
  owner: role === undefined ? { kind: "none" } : roleOwner(role),
129
128
  processes: paneProcesses,
@@ -261,8 +260,7 @@ function roleOwner(role) {
261
260
  agentId: role.agentId,
262
261
  ...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
263
262
  ...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
264
- ...(role.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: role.runtimeGenerationId }),
265
- ...(role.turnId === undefined ? {} : { turnId: role.turnId })
263
+ ...(role.runId === undefined ? {} : { runId: role.runId })
266
264
  };
267
265
  }
268
266
  return {
@@ -274,8 +272,7 @@ function roleOwner(role) {
274
272
  agentId: role.agentId,
275
273
  ...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
276
274
  ...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
277
- ...(role.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: role.runtimeGenerationId }),
278
- ...(role.turnId === undefined ? {} : { turnId: role.turnId })
275
+ ...(role.runId === undefined ? {} : { runId: role.runId })
279
276
  };
280
277
  }
281
278
  function processTree(processes, rootPid) {
@@ -432,34 +429,18 @@ function optionalCounterFields(processes, field) {
432
429
  : { ioWriteBytes: sum(values) };
433
430
  }
434
431
  function matchesResourceIdentity(identity, owner) {
435
- if (identity === undefined
436
- || typeof identity.taskId !== "string"
437
- || identity.taskId.length === 0
438
- || typeof identity.roleName !== "string"
439
- || identity.roleName.length === 0
440
- || typeof identity.turnId !== "string"
441
- || identity.turnId.length === 0
442
- || typeof identity.agentId !== "string"
443
- || identity.agentId.length === 0
444
- || typeof identity.adapterId !== "string"
445
- || identity.adapterId.length === 0
446
- || (identity.nativeSessionId !== undefined && !hasIdentityText(identity.nativeSessionId))
447
- || (identity.runtimeGenerationId !== undefined && !hasIdentityText(identity.runtimeGenerationId)))
432
+ if (identity === undefined || typeof identity.taskId !== "string" || identity.taskId.length === 0 || typeof identity.roleName !== "string" || identity.roleName.length === 0 || typeof identity.runId !== "string" || identity.runId.length === 0 || typeof identity.agentId !== "string" || identity.agentId.length === 0 || typeof identity.adapterId !== "string" || identity.adapterId.length === 0 || !hasIdentityText(identity.nativeSessionId))
448
433
  return false;
449
434
  if (owner.kind !== "task-role"
450
435
  || owner.taskId !== identity.taskId
451
436
  || owner.roleName !== identity.roleName
452
- || owner.turnId !== identity.turnId
437
+ || owner.runId !== identity.runId
453
438
  || owner.agentId !== identity.agentId
454
439
  || owner.adapterId !== identity.adapterId)
455
440
  return false;
456
- if (!hasIdentityText(identity.nativeSessionId) && !hasIdentityText(identity.runtimeGenerationId))
457
- return false;
458
441
  if (identity.nativeSessionId !== undefined
459
442
  && owner.nativeSessionId !== identity.nativeSessionId)
460
443
  return false;
461
- if (identity.runtimeGenerationId !== undefined && owner.runtimeGenerationId !== identity.runtimeGenerationId)
462
- return false;
463
444
  return true;
464
445
  }
465
446
  function hasIdentityText(value) {
@@ -14,7 +14,7 @@ import { readHomeFilesystemId } from "../core/homeFilesystemIdentity.js";
14
14
  import { buildControllerResourceInventory } from "./resourceInventory.js";
15
15
  import { CONTROLLER_DOMAIN_PATH, EPHEMERAL_DOMAIN_GRACE_MS, ephemeralDomainFingerprint, readEphemeralDomainIdentity, readLinuxProcessStartIdentity } from "./domainIdentity.js";
16
16
  const LINUX_PROCESS_SCAN_BATCH_SIZE = 64;
17
- export const INVENTORY_EVENT_LOOP_TURN_BUDGET_MS = 25;
17
+ export const INVENTORY_EVENT_LOOP_RUN_BUDGET_MS = 25;
18
18
  export async function scanControllerResourceInventory(options) {
19
19
  const currentHome = resolve(options.currentHome);
20
20
  const environment = options.environment ?? process.env;
@@ -282,17 +282,17 @@ export async function forEachInEventLoopBatches(entries, batchSize, visit, timin
282
282
  throw new Error("Event-loop batch size must be a positive integer.");
283
283
  }
284
284
  const now = timing.now ?? (() => performance.now());
285
- let turnStartedAt = now();
286
- let entriesInTurn = 0;
285
+ let runStartedAt = now();
286
+ let entriesInRun = 0;
287
287
  for (let index = 0; index < entries.length; index += 1) {
288
288
  visit(entries[index], index);
289
- entriesInTurn += 1;
289
+ entriesInRun += 1;
290
290
  if (index + 1 < entries.length
291
- && (entriesInTurn >= batchSize
292
- || now() - turnStartedAt >= INVENTORY_EVENT_LOOP_TURN_BUDGET_MS)) {
291
+ && (entriesInRun >= batchSize
292
+ || now() - runStartedAt >= INVENTORY_EVENT_LOOP_RUN_BUDGET_MS)) {
293
293
  await new Promise((resolve) => setImmediate(resolve));
294
- turnStartedAt = now();
295
- entriesInTurn = 0;
294
+ runStartedAt = now();
295
+ entriesInRun = 0;
296
296
  }
297
297
  }
298
298
  }
@@ -634,13 +634,12 @@ function loadHomeState(home, warnings, options) {
634
634
  agentId,
635
635
  ...(adapterId === undefined ? {} : { adapterId }),
636
636
  ...(session === null ? {} : { nativeSessionId: session.nativeSessionId }),
637
- ...(session?.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId })
638
637
  };
639
638
  });
640
639
  const appendTaskRole = (task, role) => {
641
640
  const session = activeLiveRoleAgentSession(store.getRoleSessionSet(task.id, role.name));
642
641
  const binding = role.agentBindings[role.activeAgentId];
643
- const run = store.getActiveTurn(task.id, role.name);
642
+ const run = store.getActiveRun(task.id, role.name);
644
643
  const agentId = session?.effective.agentId ?? role.activeAgentId;
645
644
  const adapterId = session?.effective.adapterId ?? binding?.adapterId;
646
645
  roles.push({
@@ -648,17 +647,17 @@ function loadHomeState(home, warnings, options) {
648
647
  taskId: task.id,
649
648
  taskTitle: task.title,
650
649
  taskStatus: task.status,
650
+ taskRetirementIsolated: task.retirementIsolation === true,
651
651
  roleName: role.name,
652
652
  agentId,
653
653
  ...(adapterId === undefined ? {} : { adapterId }),
654
654
  ...(session === null ? {} : { nativeSessionId: session.nativeSessionId }),
655
- ...(session?.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId }),
656
- ...(run === null ? {} : { turnId: run.id })
655
+ ...(run === null ? {} : { runId: run.id })
657
656
  });
658
657
  };
659
658
  // The current SQLite store owns bounded active-Task and current-Session
660
659
  // indexes. Use them only as selectors, then point-read the authoritative
661
- // Task/Role/Session/Turn records so an index row cannot bypass ownership
660
+ // Task/Role/Session/AgentRun records so an index row cannot bypass ownership
662
661
  // fences.
663
662
  const indexedTaskIds = [...new Set(store.listActiveTaskIds())].sort(numericCompare);
664
663
  const sessionCandidates = store.listRuntimeSessionCandidates({ scope: "task" });