@zq-silk/yui 0.15.7 → 0.15.9

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 (308) hide show
  1. package/ARCHITECTURE.md +194 -399
  2. package/ARCHITECTURE.zh-CN.md +151 -0
  3. package/README.md +306 -1131
  4. package/dist/agent/adapterCatalog.js +15 -2
  5. package/dist/agent/agent.js +23 -3
  6. package/dist/agent/argumentPolicy.js +7 -1
  7. package/dist/agent/connectionPlan.js +62 -0
  8. package/dist/agent/executionComponents.js +158 -0
  9. package/dist/agent/launchEnvironment.js +31 -3
  10. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  11. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  12. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  13. package/dist/artifacts/artifactCapability.js +74 -0
  14. package/dist/artifacts/artifactCommitLock.js +249 -0
  15. package/dist/artifacts/artifactPaths.js +151 -0
  16. package/dist/artifacts/gitArtifactRef.js +146 -0
  17. package/dist/artifacts/managedGit.js +332 -0
  18. package/dist/artifacts/taskArtifactRepository.js +277 -0
  19. package/dist/brief/taskBrief.js +12 -0
  20. package/dist/cli/agentConfigurationPicker.js +13 -0
  21. package/dist/cli/commandCatalog.js +165 -74
  22. package/dist/cli/interactionCandidates.js +5 -5
  23. package/dist/cli/interactionPolicy.js +38 -8
  24. package/dist/cli/invocationRouter.js +1 -1
  25. package/dist/cli/managedDiagnostics.js +28 -0
  26. package/dist/cli/operatorWizard.js +1 -7
  27. package/dist/cli/roleOptionOrder.js +27 -0
  28. package/dist/cli/roleWizard.js +50 -14
  29. package/dist/cli/updateOrchestrator.js +1 -1
  30. package/dist/cli/updatePorts.js +3 -4
  31. package/dist/cli.js +245 -95
  32. package/dist/commands/agentCommands.js +72 -14
  33. package/dist/commands/capabilityCommands.js +9 -6
  34. package/dist/commands/configCommands.js +20 -20
  35. package/dist/commands/deliveryGuardPreflight.js +2 -2
  36. package/dist/commands/executionAuditCommands.js +24 -24
  37. package/dist/commands/globalRoleCommands.js +1 -1
  38. package/dist/commands/grantCommands.js +4 -4
  39. package/dist/commands/operatorCommands.js +34 -9
  40. package/dist/commands/projectCommands.js +4 -4
  41. package/dist/commands/resourcesCommands.js +2 -2
  42. package/dist/commands/roleConfiguration.js +25 -5
  43. package/dist/commands/roleRuntimeGuard.js +4 -5
  44. package/dist/commands/sessionCommands.js +3 -7
  45. package/dist/commands/taskActivationCommands.js +281 -0
  46. package/dist/commands/taskActor.js +28 -49
  47. package/dist/commands/taskCommands.js +1461 -720
  48. package/dist/commands/taskContextCommand.js +39 -583
  49. package/dist/commands/taskExecutionCommands.js +32 -32
  50. package/dist/commands/taskInputCommands.js +40 -104
  51. package/dist/commands/taskIntegrationCommands.js +3 -2
  52. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  53. package/dist/commands/taskNextActionCommand.js +8 -8
  54. package/dist/commands/taskOverviewCommand.js +33 -45
  55. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  56. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  57. package/dist/commands/telemetryCommands.js +36 -38
  58. package/dist/config/configCatalog.js +4 -4
  59. package/dist/config/yuiConfig.js +8 -8
  60. package/dist/context/contextSnapshot.js +10 -10
  61. package/dist/context/dispatchContext.js +11 -11
  62. package/dist/context/roleSessionContext.js +6 -3
  63. package/dist/context/{turnContextPack.js → runContextPack.js} +158 -81
  64. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  65. package/dist/context/sessionBootstrapManifest.js +21 -2
  66. package/dist/context/sourceRunContext.js +30 -0
  67. package/dist/context/taskContext.js +481 -0
  68. package/dist/context/wakeNotification.js +27 -27
  69. package/dist/controller/agentRuntimeObserver.js +21 -24
  70. package/dist/controller/capabilityBridge.js +17 -6
  71. package/dist/controller/clientRuntime.js +65 -92
  72. package/dist/controller/controller.js +120 -188
  73. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  74. package/dist/controller/jobControl.js +54 -85
  75. package/dist/controller/resourceInventory.js +8 -27
  76. package/dist/controller/resourceInventoryLinux.js +12 -13
  77. package/dist/controller/runtime.js +529 -479
  78. package/dist/controller/runtimeEventInbox.js +55 -25
  79. package/dist/controller/runtimeEventProcessor.js +22 -31
  80. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  81. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  82. package/dist/controller/runtimeObservationHook.js +14 -18
  83. package/dist/controller/sessionNotify.js +16 -24
  84. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  85. package/dist/controller/structuredProviderObservation.js +138 -99
  86. package/dist/coordination/workMailbox.js +3 -3
  87. package/dist/coordination/workMailboxQueue.js +36 -33
  88. package/dist/core/boundedRpc.js +8 -1
  89. package/dist/core/controllerClient.js +20 -1
  90. package/dist/core/controllerServer.js +4 -4
  91. package/dist/doctor/doctor.js +13 -2
  92. package/dist/domain/agentResultTransport.js +9 -9
  93. package/dist/execution/codexThreadNaming.js +2 -8
  94. package/dist/execution/executionHealth.js +51 -63
  95. package/dist/execution/reviewMainRun.js +137 -0
  96. package/dist/execution/workItemExecution.js +28 -29
  97. package/dist/execution/workItemExecutionProjection.js +99 -107
  98. package/dist/execution/workItemMainRun.js +141 -0
  99. package/dist/executor/agentAdapter.js +227 -20
  100. package/dist/executor/agentConfigurationCatalog.js +126 -4
  101. package/dist/executor/agentConfigurationProbe.js +162 -4
  102. package/dist/executor/agentExecutor.js +79 -78
  103. package/dist/executor/effectiveLaunch.js +105 -18
  104. package/dist/executor/executorRegistry.js +29 -44
  105. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  106. package/dist/executor/workspacePreflightClassification.js +16 -16
  107. package/dist/grant/capabilityGrant.js +6 -3
  108. package/dist/input/inputRequest.js +12 -10
  109. package/dist/integration/gitIntegrationService.js +4 -11
  110. package/dist/integration/integrationQueueService.js +4 -4
  111. package/dist/interaction/operatorPresentation.js +1 -1
  112. package/dist/kernel/builtinCapabilities.js +255 -12
  113. package/dist/kernel/capabilityRegistry.js +64 -18
  114. package/dist/kernel/instanceHost.js +12 -1
  115. package/dist/kernel/kernelPorts.js +2 -2
  116. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  117. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  118. package/dist/message/message.js +118 -6
  119. package/dist/message/messageContinuation.js +204 -0
  120. package/dist/observability/executionAudit.js +70 -72
  121. package/dist/observability/faultClassification.js +2 -2
  122. package/dist/observability/orchestrationMetrics.js +8 -8
  123. package/dist/operator/operatorSessionHistory.js +1 -7
  124. package/dist/output/agentConfigurationPresentation.js +8 -3
  125. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  126. package/dist/output/rolePresentation.js +54 -3
  127. package/dist/plugins/pluginChild.js +104 -0
  128. package/dist/plugins/pluginIntent.js +26 -0
  129. package/dist/plugins/pluginInterpreter.js +43 -0
  130. package/dist/plugins/pluginPackage.js +101 -0
  131. package/dist/plugins/pluginProcess.js +112 -0
  132. package/dist/plugins/pluginService.js +388 -0
  133. package/dist/profile/agentProfile.js +1 -1
  134. package/dist/repository/gitWorkspace.js +26 -4
  135. package/dist/repository/project.js +19 -4
  136. package/dist/repository/taskBaseFreshness.js +13 -13
  137. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  138. package/dist/repository/taskWorkspacePreparer.js +344 -83
  139. package/dist/resources/autoResourceGc.js +3 -3
  140. package/dist/resources/liveReferences.js +3 -3
  141. package/dist/resources/projectResource.js +75 -0
  142. package/dist/resources/projectResourceService.js +343 -0
  143. package/dist/resources/resourceDiscovery.js +6 -6
  144. package/dist/resources/resourceGc.js +1 -1
  145. package/dist/resources/resourceRegistrar.js +1 -1
  146. package/dist/resources/resourceTypes.js +1 -1
  147. package/dist/review/deltaRecheck.js +3 -3
  148. package/dist/review/reviewAcceptance.js +16 -16
  149. package/dist/review/reviewDecision.js +7 -7
  150. package/dist/review/reviewRound.js +21 -20
  151. package/dist/review/reviewerAvailability.js +2 -2
  152. package/dist/role/role.js +51 -7
  153. package/dist/role/taskRoleUpdate.js +30 -0
  154. package/dist/runtime/acpProtocol.js +425 -0
  155. package/dist/runtime/acpSession.js +731 -0
  156. package/dist/runtime/acpSessionConfiguration.js +260 -0
  157. package/dist/runtime/agentDriver.js +30 -11
  158. package/dist/runtime/agentEndpoint.js +278 -0
  159. package/dist/runtime/agentEndpointIdentity.js +86 -0
  160. package/dist/runtime/agentEndpointOwnership.js +239 -0
  161. package/dist/runtime/agentError.js +2 -10
  162. package/dist/runtime/agentHost.js +565 -314
  163. package/dist/runtime/agentRunConfiguration.js +258 -0
  164. package/dist/runtime/builtinAgentDrivers.js +134 -18
  165. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  166. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  167. package/dist/runtime/claude-process-owner +0 -0
  168. package/dist/runtime/codexAppServerRuntime.js +38 -30
  169. package/dist/runtime/codexInteractiveHost.js +41 -6
  170. package/dist/runtime/continuationManager.js +2 -6
  171. package/dist/runtime/executionEnvironment.js +30 -0
  172. package/dist/runtime/firstProgressAdvisory.js +11 -11
  173. package/dist/runtime/index.js +4 -3
  174. package/dist/runtime/jsonLineChannel.js +109 -0
  175. package/dist/runtime/launchBroker.js +91 -16
  176. package/dist/runtime/launchDiagnostics.js +2 -2
  177. package/dist/runtime/lifecycleReservation.js +10 -18
  178. package/dist/runtime/managedCaller.js +61 -17
  179. package/dist/runtime/nativeSessionControl.js +102 -0
  180. package/dist/runtime/ports.js +6 -21
  181. package/dist/runtime/processExitObservation.js +8 -7
  182. package/dist/runtime/promptEnvelope.js +17 -6
  183. package/dist/runtime/providerContinuation.js +3 -9
  184. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  185. package/dist/runtime/providerControl.js +2 -7
  186. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  187. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  188. package/dist/runtime/runtimeBinding.js +0 -1
  189. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  190. package/dist/runtime/runtimeDeadlines.js +9 -0
  191. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  192. package/dist/runtime/runtimeObservation.js +29 -65
  193. package/dist/runtime/runtimeProjection.js +43 -51
  194. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  195. package/dist/runtime/sessionLaunchRequest.js +3 -7
  196. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  197. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  198. package/dist/runtime/sessionReconciliation.js +4 -8
  199. package/dist/runtime/sessionTerminationGuard.js +70 -259
  200. package/dist/runtime/sessionTokenMetrics.js +5 -16
  201. package/dist/runtime/structuredProviderHost.js +237 -117
  202. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  203. package/dist/runtime/tmuxAdapters.js +39 -86
  204. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  205. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  206. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  207. package/dist/scheduler/ports.js +80 -9
  208. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  209. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  210. package/dist/scheduler/taskExecutionProjection.js +120 -124
  211. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  212. package/dist/scheduler/taskWake.js +11 -4
  213. package/dist/scheduler/wakeReason.js +9 -1
  214. package/dist/setup/setupCommand.js +3 -7
  215. package/dist/storage/migrations/agentRunContract.js +159 -0
  216. package/dist/storage/migrations/artifactsToGit.js +338 -0
  217. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  218. package/dist/storage/migrations/submitIntent.js +126 -0
  219. package/dist/storage/sqliteSchema.js +467 -7
  220. package/dist/storage/sqliteStore.js +355 -220
  221. package/dist/storage/storageVersions.js +1 -1
  222. package/dist/storage/storeRpc.js +10 -5
  223. package/dist/storage/taskStore.js +13 -11
  224. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  225. package/dist/surface/surfaceContributions.js +102 -0
  226. package/dist/task/completionReadiness.js +32 -6
  227. package/dist/task/deliveryGuard.js +16 -16
  228. package/dist/task/draftPlan.js +72 -12
  229. package/dist/task/nextAction.js +144 -128
  230. package/dist/task/remoteDelivery.js +6 -6
  231. package/dist/task/task.js +184 -18
  232. package/dist/task/taskActivation.js +327 -0
  233. package/dist/task/taskActivationService.js +408 -0
  234. package/dist/task/taskRecordReference.js +5 -4
  235. package/dist/task/taskRecordRetirement.js +1 -1
  236. package/dist/task/taskSubmission.js +236 -0
  237. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  238. package/dist/telemetry/telemetryConfig.js +14 -14
  239. package/dist/telemetry/telemetryWiring.js +2 -2
  240. package/dist/web/assets/assetManifest.js +2 -0
  241. package/dist/web/assets/client/app.js +121 -20
  242. package/dist/web/assets/client/components.js +87 -54
  243. package/dist/web/assets/client/i18n.js +83 -41
  244. package/dist/web/assets/client/markdown.js +1 -1
  245. package/dist/web/assets/client/taskSurface.js +442 -0
  246. package/dist/web/assets/client/view.js +49 -44
  247. package/dist/web/assets/shell.js +1 -1
  248. package/dist/web/assets/styles/cards.js +22 -4
  249. package/dist/web/controllerWeb.js +60 -0
  250. package/dist/web/webMutation.js +28 -0
  251. package/dist/web/webServer.js +133 -8
  252. package/dist/web/webSnapshot.js +81 -74
  253. package/dist/web/webTaskSurface.js +64 -0
  254. package/dist/workItem/dependencyGate.js +1 -1
  255. package/dist/workItem/workItem.js +84 -48
  256. package/dist/workspace/workItemChangeSetManager.js +16 -9
  257. package/docs/agent-result-consumption.md +96 -0
  258. package/docs/agent-result-consumption.zh-CN.md +81 -0
  259. package/docs/agent-runtime-drivers.md +93 -0
  260. package/docs/agent-runtime-drivers.zh-CN.md +77 -0
  261. package/docs/architecture/README.md +50 -0
  262. package/docs/architecture/README.zh-CN.md +43 -0
  263. package/docs/architecture/capabilities-and-resources.md +118 -0
  264. package/docs/architecture/capabilities-and-resources.zh-CN.md +83 -0
  265. package/docs/managed-turn-and-session-runtime.md +224 -0
  266. package/docs/managed-turn-and-session-runtime.zh-CN.md +180 -0
  267. package/docs/observability/README.md +83 -0
  268. package/docs/observability/README.zh-CN.md +71 -0
  269. package/docs/plugin-sdk.md +393 -0
  270. package/docs/plugin-sdk.zh-CN.md +293 -0
  271. package/docs/provider-runtime.md +165 -0
  272. package/docs/provider-runtime.zh-CN.md +132 -0
  273. package/docs/release-workflow.md +305 -0
  274. package/docs/release-workflow.zh-CN.md +237 -0
  275. package/docs/roles-and-configuration.md +115 -0
  276. package/docs/roles-and-configuration.zh-CN.md +96 -0
  277. package/docs/sqlite-control-plane-design.md +78 -0
  278. package/docs/sqlite-control-plane-design.zh-CN.md +62 -0
  279. package/docs/task-dag-semantics.md +80 -0
  280. package/docs/task-dag-semantics.zh-CN.md +59 -0
  281. package/docs/task-delivery.md +105 -0
  282. package/docs/task-delivery.zh-CN.md +82 -0
  283. package/docs/task-local-identity.md +8 -6
  284. package/docs/task-local-identity.zh-CN.md +58 -0
  285. package/docs/testing/verification-levels.md +88 -0
  286. package/docs/testing/verification-levels.zh-CN.md +69 -0
  287. package/i18n/README.zh-CN.md +270 -722
  288. package/package.json +3 -2
  289. package/skills/yui-leader/SKILL.md +88 -304
  290. package/skills/yui-leader/references/execution.md +303 -0
  291. package/skills/yui-leader/references/integration.md +39 -0
  292. package/skills/yui-leader/references/planning.md +109 -0
  293. package/skills/yui-leader/references/replicated-execution.md +42 -0
  294. package/skills/yui-leader/references/task-plugins.md +37 -0
  295. package/skills/yui-operator/SKILL.md +46 -62
  296. package/skills/yui-reviewer/SKILL.md +35 -36
  297. package/skills/yui-runtime/SKILL.md +88 -24
  298. package/skills/yui-runtime/references/publication.md +22 -0
  299. package/skills/yui-runtime/references/recovery.md +64 -0
  300. package/skills/yui-worker/SKILL.md +37 -39
  301. package/dist/cli/roleOptionCatalog.js +0 -68
  302. package/dist/context/sourceTurnContext.js +0 -30
  303. package/dist/execution/reviewMainTurn.js +0 -161
  304. package/dist/execution/workItemMainTurn.js +0 -164
  305. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  306. package/dist/runtime/preallocatedNativeSession.js +0 -13
  307. package/dist/runtime/runtimeStopReceipt.js +0 -42
  308. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -20,7 +20,7 @@ function ownerLabel(owner) {
20
20
  * This is a read-only check: it never mutates Git state, creates Sessions, or
21
21
  * writes recovery records.
22
22
  */
23
- export function classifyWorkspacePreflight(store, task, roleName, activeTurn, inspectPhysical) {
23
+ export function classifyWorkspacePreflight(store, task, roleName, activeRun, inspectPhysical) {
24
24
  const main = store.getTaskWorkspace(task.id);
25
25
  const bindings = task.projectBindings.map(({ projectId, directory }) => ({ projectId, directory }));
26
26
  // 1. Owner validation: the Task main workspace must be a durable,
@@ -41,26 +41,26 @@ export function classifyWorkspacePreflight(store, task, roleName, activeTurn, in
41
41
  actual
42
42
  };
43
43
  }
44
- // 2. Turn snapshot validation: when the active Turn carries a workspace
44
+ // 2. AgentRun snapshot validation: when the active AgentRun carries a workspace
45
45
  // snapshot its launch-stable identity must match the durable
46
46
  // ManagedWorkspace. Audit timestamps may change without changing the
47
- // owner, root, or Project entries authorized for the Turn.
48
- if (activeTurn?.workspace !== undefined) {
49
- const durableRunWorkspace = store.getManagedWorkspace(activeTurn.workspace.owner);
47
+ // owner, root, or Project entries authorized for the AgentRun.
48
+ if (activeRun?.workspace !== undefined) {
49
+ const durableRunWorkspace = store.getManagedWorkspace(activeRun.workspace.owner);
50
50
  if (durableRunWorkspace === null
51
- || !sameManagedWorkspaceIdentity(durableRunWorkspace, activeTurn.workspace)) {
51
+ || !sameManagedWorkspaceIdentity(durableRunWorkspace, activeRun.workspace)) {
52
52
  const diff = [];
53
53
  if (durableRunWorkspace === null) {
54
- diff.push(`durable ManagedWorkspace for owner ${JSON.stringify(activeTurn.workspace.owner)} is missing`);
54
+ diff.push(`durable ManagedWorkspace for owner ${JSON.stringify(activeRun.workspace.owner)} is missing`);
55
55
  }
56
56
  else {
57
- if (durableRunWorkspace.root !== activeTurn.workspace.root) {
58
- diff.push(`root: durable=${durableRunWorkspace.root} run=${activeTurn.workspace.root}`);
57
+ if (durableRunWorkspace.root !== activeRun.workspace.root) {
58
+ diff.push(`root: durable=${durableRunWorkspace.root} run=${activeRun.workspace.root}`);
59
59
  }
60
- if (durableRunWorkspace.entries.length !== activeTurn.workspace.entries.length) {
61
- diff.push(`entries: durable=${durableRunWorkspace.entries.length} run=${activeTurn.workspace.entries.length}`);
60
+ if (durableRunWorkspace.entries.length !== activeRun.workspace.entries.length) {
61
+ diff.push(`entries: durable=${durableRunWorkspace.entries.length} run=${activeRun.workspace.entries.length}`);
62
62
  }
63
- for (const [index, entry] of activeTurn.workspace.entries.entries()) {
63
+ for (const [index, entry] of activeRun.workspace.entries.entries()) {
64
64
  const durableEntry = durableRunWorkspace.entries[index];
65
65
  if (durableEntry === undefined) {
66
66
  diff.push(`entry[${index}] ${entry.projectId}: missing from durable`);
@@ -76,10 +76,10 @@ export function classifyWorkspacePreflight(store, task, roleName, activeTurn, in
76
76
  }
77
77
  return {
78
78
  kind: "workspace-stale",
79
- reason: `Role Turn workspace is not the durable owner: ${task.id}/${roleName}.`,
79
+ reason: `Role AgentRun workspace is not the durable owner: ${task.id}/${roleName}.`,
80
80
  taskId: task.id,
81
81
  roleName,
82
- turnId: activeTurn.id,
82
+ runId: activeRun.id,
83
83
  diff
84
84
  };
85
85
  }
@@ -89,7 +89,7 @@ export function classifyWorkspacePreflight(store, task, roleName, activeTurn, in
89
89
  // from that immutable boundary. A reset/repoint outside the lineage is
90
90
  // physical drift and must fail before Provider launch.
91
91
  if (inspectPhysical !== undefined) {
92
- const effective = activeTurn?.workspace ?? main;
92
+ const effective = activeRun?.workspace ?? main;
93
93
  for (const entry of effective.entries) {
94
94
  const physical = inspectPhysical(entry);
95
95
  if (!physical.recordedBaseIsAncestor) {
@@ -121,7 +121,7 @@ export function formatWorkspacePreflightError(classification) {
121
121
  + "` to inspect the binding, ManagedWorkspace, and physical HEAD.");
122
122
  break;
123
123
  case "workspace-stale":
124
- lines.push(` Turn ${classification.turnId} snapshot differs from the durable ManagedWorkspace:`);
124
+ lines.push(` AgentRun ${classification.runId} snapshot differs from the durable ManagedWorkspace:`);
125
125
  for (const entry of classification.diff) {
126
126
  lines.push(` - ${entry}`);
127
127
  }
@@ -68,8 +68,8 @@ export function grantUseReservations(grant) {
68
68
  }
69
69
  /**
70
70
  * Record one use against the grant, failing closed once the limit is reached.
71
- * The reservation key is appended to the grant's durable reservations so a
72
- * later resume recognizes this exact attempt and avoids a double charge.
71
+ * Supply a reservation key when a later resume must recognize the attempt.
72
+ * Non-resumable calls only advance the counter; historical keys stay intact.
73
73
  */
74
74
  export function recordGrantUse(grant, now, reservationKey) {
75
75
  validateCapabilityGrant(grant);
@@ -79,7 +79,10 @@ export function recordGrantUse(grant, now, reservationKey) {
79
79
  return validateCapabilityGrant({
80
80
  ...grant,
81
81
  usesUsed: grant.usesUsed + 1,
82
- useReservations: Object.freeze([...grantUseReservations(grant), reservationKey]),
82
+ useReservations: Object.freeze([
83
+ ...grantUseReservations(grant),
84
+ ...(reservationKey === undefined ? [] : [reservationKey])
85
+ ]),
83
86
  updatedAt: now.toISOString()
84
87
  });
85
88
  }
@@ -89,12 +89,11 @@ export function validateInputRequest(value) {
89
89
  updatedAt: requireTimestamp(request.updatedAt, "Input request updatedAt")
90
90
  };
91
91
  validateTaskRecordReference({ taskId: base.taskId, localId: base.id }, "inputRequest");
92
- validateTaskRecordReference({
93
- taskId: base.requester.taskId,
94
- localId: base.requester.turnId
95
- }, "turn");
92
+ if (base.requester.runId !== undefined) {
93
+ validateTaskRecordReference({ taskId: base.requester.taskId, localId: base.requester.runId }, "run");
94
+ }
96
95
  for (const reference of base.blockedRefs) {
97
- validateTaskRecordReference({ taskId: reference.taskId, localId: reference.id }, reference.type === "turn" ? "turn" : "workItem");
96
+ validateTaskRecordReference({ taskId: reference.taskId, localId: reference.id }, reference.type === "run" ? "run" : "workItem");
98
97
  }
99
98
  if (base.requester.taskId !== base.taskId
100
99
  || base.blockedRefs.some(({ taskId }) => taskId !== base.taskId)) {
@@ -175,7 +174,7 @@ function normalizeBlockedRefs(value) {
175
174
  const references = value.map((reference) => {
176
175
  const item = record(reference, "Input blocked reference");
177
176
  exact(item, ["type", "taskId", "id"], "Input blocked reference");
178
- if (item.type !== "work-item" && item.type !== "turn") {
177
+ if (item.type !== "work-item" && item.type !== "run") {
179
178
  throw new Error("Input blocked reference type must be work-item or turn.");
180
179
  }
181
180
  return {
@@ -223,16 +222,19 @@ function validateBlockedRefs(value) {
223
222
  }
224
223
  function normalizeRequester(value) {
225
224
  const requester = record(value, "Input requester");
226
- exact(requester, requester.nativeSessionId === undefined
227
- ? ["taskId", "roleName", "agentId", "turnId"]
228
- : ["taskId", "roleName", "agentId", "turnId", "nativeSessionId"], "Input requester");
225
+ exact(requester, ["taskId", "roleName", "agentId",
226
+ ...(requester.runId === undefined ? [] : ["runId"]),
227
+ ...(requester.nativeSessionId === undefined ? [] : ["nativeSessionId"])], "Input requester");
229
228
  if (requester.roleName !== "leader")
230
229
  throw new Error("Input requester must be the Task Leader.");
230
+ if (requester.runId === undefined && requester.nativeSessionId === undefined) {
231
+ throw new Error("Input requester requires an originating Run or native Session.");
232
+ }
231
233
  return {
232
234
  taskId: requireIdentity(requester.taskId, "Input requester Task id"),
233
235
  roleName: "leader",
234
236
  agentId: requireIdentity(requester.agentId, "Input requester Agent id"),
235
- turnId: requireIdentity(requester.turnId, "Input requester Turn id"),
237
+ ...(requester.runId === undefined ? {} : { runId: requireIdentity(requester.runId, "Input requester AgentRun id") }),
236
238
  ...(requester.nativeSessionId === undefined
237
239
  ? {}
238
240
  : { nativeSessionId: requireIdentity(requester.nativeSessionId, "Input requester native session id") })
@@ -549,8 +549,6 @@ export class GitIntegrationService {
549
549
  #runtimePreparation(attempt, workspace) {
550
550
  return this.runtimeIsolation.preflight({
551
551
  workspace,
552
- runtimeGenerationId: integrationRuntimeRuntimeGenerationId(this.home, attempt.id),
553
- generationId: "integration-checks",
554
552
  allowExactActive: true
555
553
  });
556
554
  }
@@ -1083,7 +1081,7 @@ function isNodeCode(error, code) {
1083
1081
  function defaultIntegrationRuntimeIsolation(home, homeId) {
1084
1082
  const controlHome = resolve(home);
1085
1083
  return new FileTaskRuntimeIsolation({
1086
- runtimeRoot: integrationRuntimeRoot(),
1084
+ runtimeRoot: integrationRuntimeRoot(controlHome),
1087
1085
  pathLayout: "compact",
1088
1086
  controlPlane: {
1089
1087
  yuiHome: controlHome,
@@ -1093,15 +1091,10 @@ function defaultIntegrationRuntimeIsolation(home, homeId) {
1093
1091
  }
1094
1092
  });
1095
1093
  }
1096
- function integrationRuntimeRoot() {
1094
+ function integrationRuntimeRoot(home) {
1097
1095
  const uid = typeof process.getuid === "function" ? process.getuid() : 0;
1098
- return join("/tmp", `yi-${uid.toString(36)}`);
1099
- }
1100
- function integrationRuntimeRuntimeGenerationId(home, integrationId) {
1101
- const homeDigest = createHash("sha256")
1102
- .update(resolve(home))
1103
- .digest("hex");
1104
- return `${integrationId}-${homeDigest}`;
1096
+ const homeDigest = createHash("sha256").update(resolve(home)).digest("hex").slice(0, 16);
1097
+ return join("/tmp", `yi-${uid.toString(36)}-${homeDigest}`);
1105
1098
  }
1106
1099
  /**
1107
1100
  * Reuse is enabled only for an immutable installed release. Development
@@ -3,6 +3,7 @@ import { workspaceProjectEntry } from "../worktree/managedWorkspace.js";
3
3
  import { createIntegrationAttempt, recordResolutionDecision, updateIntegrationAttempt } from "./integrationAttempt.js";
4
4
  import { createConvergedIntegrationQueueEntry, createIntegrationQueueEntry, markIntegrationQueueBlocked, markIntegrationQueueCommitted, markIntegrationQueueRequeued, markIntegrationQueueRunning, markIntegrationQueueSuperseded, recordIntegrationQueueAffectedPaths, recordIntegrationQueueAttempt } from "./integrationQueueEntry.js";
5
5
  import { GitIntegrationService } from "./gitIntegrationService.js";
6
+ import { governingWorkItemCandidate } from "../workItem/workItem.js";
6
7
  /**
7
8
  * Producer WorkItem statuses that close the WorkItem lifecycle. A ChangeSet
8
9
  * captured from a WorkItem that reached one of these without ever producing a
@@ -11,8 +12,7 @@ import { GitIntegrationService } from "./gitIntegrationService.js";
11
12
  * Candidate.
12
13
  */
13
14
  const TERMINAL_PRODUCER_STATUSES = new Set([
14
- "completed",
15
- "failed",
15
+ "accepted",
16
16
  "retired"
17
17
  ]);
18
18
  /**
@@ -59,11 +59,11 @@ function assertCurrentCandidateInStore(store, taskId, changeSet) {
59
59
  throw new Error(`ChangeSet producer WorkItem not found: ${changeSet.workItemId}.`);
60
60
  }
61
61
  // A running WorkItem has no current Candidate: a new one is expected.
62
- if (workItem.status === "running") {
62
+ if (workItem.status === "open" && workItem.currentCandidateId === undefined) {
63
63
  throw new Error(`ChangeSet ${changeSet.id} has no current Candidate: `
64
64
  + `WorkItem ${workItem.id} is running.`);
65
65
  }
66
- const latestCandidate = workItem.candidates.at(-1);
66
+ const latestCandidate = governingWorkItemCandidate(workItem);
67
67
  if (latestCandidate !== undefined) {
68
68
  const snapshotHead = candidateHeadCommit(latestCandidate, changeSet.projectId);
69
69
  if (snapshotHead !== undefined && snapshotHead !== changeSet.headCommit) {
@@ -34,7 +34,7 @@ function eventLabel(event) {
34
34
  case "task.completed": return "Task completed";
35
35
  case "task.retired": return "Task retired";
36
36
  case "leader.attention-required": return "Task Leader needs attention";
37
- case "turn.stalled": return "Task Leader stalled";
37
+ case "run.stalled": return "Task Leader stalled";
38
38
  default: return `Task event ${event.type}`;
39
39
  }
40
40
  }
@@ -1,21 +1,119 @@
1
- import { updateTaskMetadataCommand } from "../commands/taskCommands.js";
1
+ import { updateTaskMetadataCommand, sendTaskMessageCommand } from "../commands/taskCommands.js";
2
2
  import { runConfigCommand } from "../commands/configCommands.js";
3
+ import { readTaskContext, readTaskContextDelta, inspectTaskContext, withContextObservations } from "../context/taskContext.js";
3
4
  import { CONFIG_DOMAINS } from "../config/configCatalog.js";
4
5
  import { createJobCallAuthority, parseDurableJobStartParams } from "../controller/jobControl.js";
5
6
  import { inspectJobOperation } from "./kernelPorts.js";
6
7
  import { CapabilityRegistry, } from "./capabilityRegistry.js";
8
+ import { createProjectResources } from "../resources/projectResourceService.js";
9
+ import { saveArtifactCapability, readArtifactCapability, listArtifactsCapability } from "../artifacts/artifactCapability.js";
10
+ import { createPluginService } from "../plugins/pluginService.js";
7
11
  const text = { type: "string", minLength: 1 };
8
12
  const strings = { type: "object", additionalProperties: { type: "string" } };
9
13
  const object = (properties, required = Object.keys(properties)) => ({
10
14
  type: "object", properties, required, additionalProperties: false
11
15
  });
12
16
  const taskInput = object({ taskId: text });
17
+ const recordOutput = { type: "object" };
13
18
  const taskOutput = { type: "object", required: ["id", "status", "title"], properties: {
14
19
  id: text, status: text, title: text
15
20
  } };
16
21
  const provider = Object.freeze({ id: "yui:builtin-capabilities", generation: "1" });
17
22
  /** Source locators identify the existing semantic owner, not a new Store. */
18
23
  const definitions = [
24
+ {
25
+ name: "message.send", summary: "Save collaboration for Leader or continue the same dispatched work owner.",
26
+ effect: "local-mutation", requiredPermissions: ["task:read"], source: "sendTaskMessageCommand",
27
+ inputSchema: object({ taskId: text, body: text,
28
+ intent: { enum: ["record", "discuss", "develop"] },
29
+ wakePolicy: { enum: ["leader", "none"] },
30
+ recipient: object({ roleName: text, workItemId: text, reviewRoundId: text }, ["roleName"])
31
+ }, ["taskId", "body"]), outputSchema: recordOutput
32
+ },
33
+ {
34
+ name: "context.read", summary: "Read a bounded authorized Task working set and atomic core cursor.",
35
+ effect: "query", requiredPermissions: ["task:read"], source: "readTaskContext",
36
+ inputSchema: taskInput, outputSchema: { type: "object", required: ["records", "coreCursor", "omitted"] }
37
+ },
38
+ {
39
+ name: "context.delta", summary: "Read immutable Task events with a fixed pagination upper bound.",
40
+ effect: "query", requiredPermissions: ["task:read"], source: "readTaskContextDelta",
41
+ inputSchema: object({ taskId: text, after: text, continuation: text, limit: { type: "integer" } }, ["taskId", "after"]),
42
+ outputSchema: { type: "object", required: ["events", "throughCursor"] }
43
+ },
44
+ {
45
+ name: "context.inspect", summary: "Expand an authorized current record; optionally require its exact digest.",
46
+ effect: "query", requiredPermissions: ["task:read"], source: "inspectTaskContext",
47
+ inputSchema: object({ taskId: text, store: text, refId: text, digest: text }, ["taskId", "store", "refId"]),
48
+ outputSchema: { type: "object", required: ["ref", "value", "coreCursor"] }
49
+ },
50
+ {
51
+ name: "artifact.save", summary: "Save a file artifact by relativePath into the Task's local Git repository; returns a commit-pinned reference.",
52
+ effect: "local-mutation", requiredPermissions: ["task:read"], source: "artifacts.saveArtifactCapability",
53
+ inputSchema: object({ taskId: text, relativePath: text, content: { type: "string" }, message: text, expectedHead: text }, ["taskId", "relativePath", "content"]),
54
+ outputSchema: { type: "object", required: ["taskId", "commit", "relativePath"] }
55
+ },
56
+ {
57
+ name: "artifact.read", summary: "Read a file artifact at HEAD, or at a pinned commit for frozen evidence, without starting a Runtime or plugin.",
58
+ effect: "query", requiredPermissions: ["task:read"], source: "artifacts.readArtifactCapability",
59
+ inputSchema: object({ taskId: text, relativePath: text, commit: text }, ["taskId", "relativePath"]),
60
+ outputSchema: { type: "object", required: ["taskId", "relativePath", "commit", "content"] }
61
+ },
62
+ {
63
+ name: "artifact.list", summary: "List this Task's tracked file artifacts at HEAD.",
64
+ effect: "query", requiredPermissions: ["task:read"], source: "artifacts.listArtifactsCapability",
65
+ inputSchema: taskInput, outputSchema: { type: "array", items: recordOutput }
66
+ },
67
+ {
68
+ name: "environment.prepare", summary: "Prepare empty, Task-owned scratch, or explicitly granted trusted-local directory; does not adopt it or create a sandbox.",
69
+ effect: "local-mutation", requiredPermissions: ["task:manage"], source: "ProjectResources.prepare",
70
+ inputSchema: object({ taskId: text, plan: { anyOf: [
71
+ object({ kind: { const: "empty" } }), object({ kind: { const: "scratch" } }),
72
+ object({ kind: { const: "local" }, resourceId: text, access: { enum: ["read", "write"] } })
73
+ ] } }), outputSchema: recordOutput
74
+ },
75
+ {
76
+ name: "environment.adopt", summary: "Recheck current resource intent, grants and conflicts, then record Task ownership.",
77
+ effect: "local-mutation", requiredPermissions: ["task:manage"], source: "ProjectResources.adopt",
78
+ inputSchema: object({ taskId: text, preparationId: text }), outputSchema: recordOutput
79
+ },
80
+ {
81
+ name: "environment.bind", summary: "Select an adopted environment for a Role's next native Session; null restores managed workspace. Active Sessions keep their environment.",
82
+ effect: "local-mutation", requiredPermissions: ["task:manage"], source: "ProjectResources.bindEnvironment",
83
+ inputSchema: object({ taskId: text, roleName: text, preparationId: { anyOf: [text, { const: null }] } }),
84
+ outputSchema: recordOutput
85
+ },
86
+ {
87
+ name: "environment.release", summary: "Release exact preparation; adopted resources need actual quiescence evidence. Never deletes user directories.",
88
+ effect: "local-mutation", requiredPermissions: ["task:manage"], source: "ProjectResources.release",
89
+ inputSchema: object({ taskId: text, preparationId: text, quiescence: text }, ["taskId", "preparationId"]), outputSchema: recordOutput
90
+ },
91
+ {
92
+ name: "environment.list", summary: "Read preparation/adoption facts, not inferred process state.",
93
+ effect: "query", requiredPermissions: ["task:read"], source: "TaskStore.listEnvironmentPreparations",
94
+ inputSchema: taskInput, outputSchema: { type: "array", items: recordOutput }
95
+ },
96
+ {
97
+ name: "resource.local.register", summary: "Register a user-owned local directory by canonical identity (Operator); registration does not grant use.",
98
+ effect: "local-mutation", requiredPermissions: ["resource:register"], source: "ProjectResources.registerLocalDirectory",
99
+ inputSchema: object({ displayName: text, path: text }), outputSchema: recordOutput
100
+ },
101
+ {
102
+ name: "resource.local.read", summary: "Read an explicitly granted local resource.",
103
+ effect: "query", requiredPermissions: ["task:read"], source: "ProjectResources.readLocalResource",
104
+ inputSchema: object({ taskId: text, resourceId: text }), outputSchema: recordOutput
105
+ },
106
+ {
107
+ name: "project.context", summary: "Read Project Knowledge, resource references and default Provider references; no credential grant.",
108
+ effect: "query", requiredPermissions: ["task:read"], source: "TaskStore.getProject",
109
+ inputSchema: object({ taskId: text, projectId: text }), outputSchema: recordOutput
110
+ },
111
+ {
112
+ name: "project.resources.configure", summary: "Configure existing Project resource and Provider references (Operator).",
113
+ effect: "local-mutation", requiredPermissions: ["resource:register"], source: "ProjectResources.configureProject",
114
+ inputSchema: object({ projectId: text, resourceRefs: { type: "array", items: text }, defaultCapabilityProviders: strings }),
115
+ outputSchema: recordOutput
116
+ },
19
117
  {
20
118
  name: "task.read", summary: "Read the current Task record.", effect: "query",
21
119
  inputSchema: taskInput, outputSchema: taskOutput, requiredPermissions: ["task:read"],
@@ -41,6 +139,11 @@ const definitions = [
41
139
  inputSchema: object({ domain: { enum: CONFIG_DOMAINS } }),
42
140
  outputSchema: { type: "object" }
43
141
  },
142
+ {
143
+ name: "resource.git.result", summary: "Read an original fixed Git ChangeSet and its external-version reference.",
144
+ effect: "query", requiredPermissions: ["task:read"], source: "TaskStore.getChangeSet",
145
+ inputSchema: object({ taskId: text, changeSetId: text }), outputSchema: recordOutput
146
+ },
44
147
  {
45
148
  name: "resource.workspaces", summary: "Read the Task's managed workspace resources.",
46
149
  effect: "query", requiredPermissions: ["task:read"],
@@ -73,23 +176,58 @@ const definitions = [
73
176
  }, ["taskId", "projectId", "head", "workspace", "owner", "env", "steps"]),
74
177
  outputSchema: { type: "object", required: ["job", "created", "operation"], properties: { created: { type: "boolean" } } }
75
178
  },
76
- ...["create", "validate", "activate", "disable"].map((action) => ({
77
- name: `plugin.${action}`, summary: "Plugin SDK management is not implemented.",
179
+ ...[
180
+ { action: "create", summary: "Create an independent data or trusted-local package in an adopted environment; executes no author code.",
181
+ inputSchema: object({ preparationId: text, id: text, kind: { enum: ["declarative", "trusted-local"] } }) },
182
+ { action: "validate", summary: "Validate captured package bytes in an explicit environment; author build/test code needs a separate execution grant.",
183
+ inputSchema: object({ preparationId: text, directory: text }) },
184
+ { action: "activate", summary: "Recheck validated bytes, current authority and dependencies; publish one complete Task-local provider.",
185
+ inputSchema: object({ validationId: text }) },
186
+ { action: "disable", summary: "Stop new plugin calls and drain the exact Host instance before disposal.",
187
+ inputSchema: object({ id: text }) }
188
+ ].map(({ action, summary, inputSchema }) => ({
189
+ name: `plugin.${action}`, summary, inputSchema,
78
190
  effect: "local-mutation", requiredPermissions: ["plugin:manage"],
79
- source: "T09 (not implemented)", inputSchema: object({}), outputSchema: object({}),
80
- unavailable: "The executable plugin SDK is not implemented. Existing Agent Drivers and Project Skills retain their typed management interfaces."
81
- }))
191
+ source: "PluginService", outputSchema: recordOutput
192
+ })),
193
+ {
194
+ name: "plugin.scan", summary: "Data-only package digest and manifest inspection; never executes author code.",
195
+ effect: "query", requiredPermissions: ["plugin:manage"], source: "PluginService.scan",
196
+ inputSchema: object({ preparationId: text, directory: text }), outputSchema: recordOutput
197
+ },
198
+ {
199
+ name: "plugin.validation", summary: "Read immutable validation evidence without starting the plugin.",
200
+ effect: "query", requiredPermissions: ["task:read"], source: "PluginService.inspect",
201
+ inputSchema: object({ validationId: text }), outputSchema: recordOutput
202
+ },
203
+ {
204
+ name: "plugin.inspect", summary: "Read durable desired selection, actual Host selection/references and latest intent failure; never activates code.",
205
+ effect: "query", requiredPermissions: ["task:read"], source: "PluginService.current",
206
+ inputSchema: object({ id: text }), outputSchema: recordOutput
207
+ },
208
+ {
209
+ name: "plugin.list", summary: "List this Task's explicit plugin choices and current Host observations without executing code.",
210
+ effect: "query", requiredPermissions: ["task:read"], source: "PluginService.list",
211
+ inputSchema: object({}), outputSchema: { type: "array", items: recordOutput }
212
+ }
82
213
  ];
83
214
  export const BUILTIN_CAPABILITIES = definitions.map((entry) => ({
84
215
  ...entry, contractVersion: "1", provider, scope: { kind: "global" }
85
216
  }));
86
- /** Authenticated managed bridge. Socket possession/scope JSON is not a grant.
87
- * A future user/Web ingress must provide its own verified identity adapter;
88
- * this one deliberately accepts only the existing managed credentials. */
89
- export function createBuiltinCapabilities(host, store, jobs, signal = () => undefined) {
217
+ /** One registry with separate managed credentials and in-process Web query
218
+ * issuance. Socket possession or caller-scope JSON never issues a Web context. */
219
+ export function createBuiltinCapabilities(host, store, jobs, signal = () => undefined, contextProviders = []) {
90
220
  const authority = createJobCallAuthority(store);
221
+ const resources = createProjectResources(store);
91
222
  const callers = new WeakMap();
223
+ // Issued only by the Controller's in-process, token-authenticated Web root.
224
+ // This is not accepted by the managed RPC credential adapter.
225
+ const webQueries = new WeakSet();
92
226
  const current = (context) => {
227
+ if (webQueries.has(context)) {
228
+ requireTask(store, context.targetId);
229
+ return { scope: "user" };
230
+ }
93
231
  authority.authorize(context, context.targetId);
94
232
  const caller = callers.get(context);
95
233
  if (!caller)
@@ -104,10 +242,92 @@ export function createBuiltinCapabilities(host, store, jobs, signal = () => unde
104
242
  throw new Error("Capability target is outside the authenticated Task.");
105
243
  }
106
244
  const taskId = invocation.context.targetId;
245
+ if (name === "message.send") {
246
+ // A managed Task Session resolves to Leader/role authority and never
247
+ // gains develop from an intent argument; only a global Operator Session
248
+ // (user-authority) may carry one. sendTaskMessageCommand enforces this,
249
+ // so the capability just forwards the optional intent unchanged.
250
+ const result = sendTaskMessageCommand(store, taskId, params.body, params.wakePolicy, { environment: callerEnvironment(caller) }, params.recipient, params.intent);
251
+ signal(taskId);
252
+ return result.message;
253
+ }
254
+ if (name === "plugin.create")
255
+ return plugins.create(taskId, params.preparationId, params.id, params.kind);
256
+ if (name === "plugin.scan")
257
+ return plugins.scan(taskId, params.preparationId, params.directory);
258
+ if (name === "plugin.validate")
259
+ return plugins.validate(invocation.context, params.preparationId, params.directory);
260
+ if (name === "plugin.validation")
261
+ return plugins.inspect(taskId, params.validationId);
262
+ if (name === "plugin.inspect")
263
+ return plugins.current(taskId, params.id);
264
+ if (name === "plugin.list")
265
+ return plugins.list(taskId);
266
+ if (name === "plugin.activate")
267
+ return plugins.activate(invocation.context, params.validationId);
268
+ if (name === "plugin.disable")
269
+ return plugins.disable(taskId, params.id);
270
+ if (name === "context.read") {
271
+ const core = readTaskContext(store, taskId, callerEnvironment(caller));
272
+ return withContextObservations(core, contextProviders);
273
+ }
274
+ if (name === "context.delta")
275
+ return readTaskContextDelta(store, taskId, {
276
+ after: params.after, continuation: params.continuation,
277
+ limit: params.limit
278
+ }, callerEnvironment(caller));
279
+ if (name === "context.inspect")
280
+ return inspectTaskContext(store, taskId, {
281
+ store: params.store, refId: params.refId, digest: params.digest
282
+ }, callerEnvironment(caller));
283
+ // File/directory artifacts live in the Task's local Git repository, not
284
+ // the DB. Save commits exactly one path and returns a self-certifying
285
+ // commit-pinned reference; read/list are ordinary current reads. These
286
+ // are the async Git path (the capability layer awaits invoke()).
287
+ if (name === "artifact.save")
288
+ return saveArtifactCapability(store.rootDirectory(), taskId, {
289
+ relativePath: params.relativePath, content: params.content,
290
+ ...(params.message === undefined ? {} : { message: params.message }),
291
+ ...(params.expectedHead === undefined ? {} : { expectedHead: params.expectedHead })
292
+ });
293
+ if (name === "artifact.read")
294
+ return readArtifactCapability(store.rootDirectory(), taskId, {
295
+ relativePath: params.relativePath,
296
+ ...(params.commit === undefined ? {} : { commit: params.commit })
297
+ });
298
+ if (name === "artifact.list")
299
+ return listArtifactsCapability(store.rootDirectory(), taskId);
300
+ if (name === "environment.prepare")
301
+ return resources.prepare(taskId, params.plan);
302
+ if (name === "environment.adopt")
303
+ return resources.adopt(taskId, params.preparationId);
304
+ if (name === "environment.bind") {
305
+ const role = resources.bindEnvironment(taskId, params.roleName, params.preparationId, {
306
+ source: name, actorId: invocation.context.actorId, requestId: invocation.requestId
307
+ });
308
+ signal(taskId);
309
+ return role;
310
+ }
311
+ if (name === "environment.release") {
312
+ plugins.assertEnvironmentUnused(taskId, params.preparationId);
313
+ return resources.release(taskId, params.preparationId, params.quiescence === undefined ? undefined : { quiescence: params.quiescence });
314
+ }
315
+ if (name === "environment.list")
316
+ return store.listEnvironmentPreparations(taskId);
317
+ if (name === "resource.local.register")
318
+ return resources.registerLocalDirectory(params.displayName, params.path);
319
+ if (name === "resource.local.read")
320
+ return resources.readLocalResource(taskId, params.resourceId);
321
+ if (name === "project.context")
322
+ return resources.projectContext(taskId, params.projectId);
323
+ if (name === "project.resources.configure")
324
+ return resources.configureProject(params.projectId, params.resourceRefs, params.defaultCapabilityProviders);
107
325
  if (name === "task.read")
108
326
  return requireTask(store, taskId);
109
327
  if (name === "resource.workspaces")
110
328
  return store.listManagedWorkspaces(taskId);
329
+ if (name === "resource.git.result")
330
+ return resources.gitResult(taskId, params.changeSetId);
111
331
  if (name === "config.read")
112
332
  return runConfigCommand(params.domain, ["show"], store).data;
113
333
  if (name === "task.update") {
@@ -147,24 +367,45 @@ export function createBuiltinCapabilities(host, store, jobs, signal = () => unde
147
367
  const registry = new CapabilityRegistry(host, (context, descriptor, input) => {
148
368
  const caller = current(context);
149
369
  const task = requireTask(store, context.targetId);
370
+ if (caller.scope === "user" && descriptor !== undefined && descriptor.effect !== "query") {
371
+ throw new Error("Web panels may only query capabilities.");
372
+ }
150
373
  if (typeof input === "object" && input !== null && "taskId" in input && input.taskId !== task.id) {
151
374
  throw new Error("Capability target is outside the authenticated Task.");
152
375
  }
153
376
  for (const permission of descriptor?.requiredPermissions ?? []) {
377
+ if (permission === "job:start" && caller.scope === "task") {
378
+ const sessions = store.getTaskRoleSessionSet(task.id, caller.role);
379
+ if (sessions?.sessions[sessions.activeAgentId]?.effective.executionAuthority !== "delivery") {
380
+ throw new Error("Planning Sessions cannot start delivery Jobs.");
381
+ }
382
+ }
154
383
  if (permission === "task:read" || permission === "job:start")
155
384
  continue;
156
385
  if (permission === "task:manage" && ((caller.scope === "task" && caller.role === "leader")
157
386
  || (caller.scope === "global" && caller.role === "operator")))
158
387
  continue;
159
- if ((permission === "config:read" || permission === "plugin:manage")
388
+ // PluginService binds every management target to this authenticated
389
+ // Task. This admits package management, not author-code execution:
390
+ // adopted environments and exact plugin.execute grants remain separate.
391
+ if (permission === "plugin:manage" && caller.scope === "task" && caller.role === "leader")
392
+ continue;
393
+ if ((permission === "config:read" || permission === "plugin:manage" || permission === "resource:register")
160
394
  && caller.scope === "global" && caller.role === "operator")
161
395
  continue;
162
396
  throw new Error(`Permission unavailable: ${permission}.`);
163
397
  }
164
398
  return { taskIds: [task.id], projectIds: task.projectBindings.map((binding) => binding.projectId) };
165
399
  }, BUILTIN_CAPABILITIES);
400
+ const plugins = createPluginService(store, host, registry);
166
401
  return {
167
402
  registry,
403
+ authenticateWebQuery(taskId) {
404
+ requireTask(store, taskId);
405
+ const context = Object.freeze({ actorId: "local-web-user", targetId: taskId });
406
+ webQueries.add(context);
407
+ return context;
408
+ },
168
409
  authenticate(caller, taskId) {
169
410
  const credential = Object.freeze({ ...caller });
170
411
  const context = authority.authenticate(credential, taskId);
@@ -180,9 +421,11 @@ function requireTask(store, taskId) {
180
421
  return task;
181
422
  }
182
423
  function callerEnvironment(caller) {
424
+ if (caller.scope === "user")
425
+ return {};
183
426
  return {
184
427
  YUI_SESSION_SCOPE: caller.scope, YUI_TASK_ID: caller.taskId,
185
428
  YUI_ROLE: caller.role, YUI_AGENT_ID: caller.agentId,
186
- YUI_ADAPTER_ID: caller.adapterId, YUI_JOB_CALLER_KEY: caller.callerKey
429
+ YUI_ADAPTER_ID: caller.adapterId, YUI_NATIVE_SESSION_ID: caller.nativeSessionId
187
430
  };
188
431
  }