@zq-silk/yui 0.15.6 → 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 (282) 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 +167 -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 +188 -95
  25. package/dist/commands/agentCommands.js +72 -14
  26. package/dist/commands/capabilityCommands.js +57 -0
  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 +1216 -730
  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 +77 -0
  64. package/dist/controller/clientRuntime.js +65 -92
  65. package/dist/controller/controller.js +127 -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 +530 -476
  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 +423 -0
  106. package/dist/kernel/capabilityRegistry.js +314 -0
  107. package/dist/kernel/capabilitySchema.js +91 -0
  108. package/dist/kernel/instanceHost.js +18 -1
  109. package/dist/kernel/kernelPorts.js +4 -1
  110. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  111. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  112. package/dist/message/message.js +62 -6
  113. package/dist/message/messageContinuation.js +204 -0
  114. package/dist/observability/executionAudit.js +70 -72
  115. package/dist/observability/faultClassification.js +2 -2
  116. package/dist/observability/orchestrationMetrics.js +8 -8
  117. package/dist/operator/operatorSessionHistory.js +1 -7
  118. package/dist/output/agentConfigurationPresentation.js +8 -3
  119. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  120. package/dist/output/rolePresentation.js +54 -3
  121. package/dist/plugins/pluginChild.js +104 -0
  122. package/dist/plugins/pluginIntent.js +26 -0
  123. package/dist/plugins/pluginInterpreter.js +43 -0
  124. package/dist/plugins/pluginPackage.js +101 -0
  125. package/dist/plugins/pluginProcess.js +112 -0
  126. package/dist/plugins/pluginService.js +380 -0
  127. package/dist/profile/agentProfile.js +1 -1
  128. package/dist/repository/gitWorkspace.js +26 -4
  129. package/dist/repository/project.js +19 -4
  130. package/dist/repository/taskBaseFreshness.js +13 -13
  131. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  132. package/dist/repository/taskWorkspacePreparer.js +344 -83
  133. package/dist/resources/autoResourceGc.js +3 -3
  134. package/dist/resources/liveReferences.js +3 -3
  135. package/dist/resources/projectResource.js +123 -0
  136. package/dist/resources/projectResourceService.js +421 -0
  137. package/dist/resources/resourceDiscovery.js +6 -6
  138. package/dist/resources/resourceGc.js +1 -1
  139. package/dist/resources/resourceRegistrar.js +1 -1
  140. package/dist/resources/resourceTypes.js +1 -1
  141. package/dist/review/deltaRecheck.js +3 -3
  142. package/dist/review/reviewAcceptance.js +16 -16
  143. package/dist/review/reviewDecision.js +7 -7
  144. package/dist/review/reviewRound.js +21 -20
  145. package/dist/review/reviewerAvailability.js +2 -2
  146. package/dist/role/role.js +51 -7
  147. package/dist/role/taskRoleUpdate.js +30 -0
  148. package/dist/runtime/acpProtocol.js +425 -0
  149. package/dist/runtime/acpSession.js +731 -0
  150. package/dist/runtime/acpSessionConfiguration.js +260 -0
  151. package/dist/runtime/agentDriver.js +30 -11
  152. package/dist/runtime/agentEndpoint.js +278 -0
  153. package/dist/runtime/agentEndpointIdentity.js +86 -0
  154. package/dist/runtime/agentEndpointOwnership.js +239 -0
  155. package/dist/runtime/agentError.js +2 -10
  156. package/dist/runtime/agentHost.js +565 -314
  157. package/dist/runtime/agentRunConfiguration.js +258 -0
  158. package/dist/runtime/builtinAgentDrivers.js +134 -18
  159. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  160. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  161. package/dist/runtime/claude-process-owner +0 -0
  162. package/dist/runtime/codexAppServerRuntime.js +38 -30
  163. package/dist/runtime/codexInteractiveHost.js +41 -6
  164. package/dist/runtime/continuationManager.js +2 -6
  165. package/dist/runtime/executionEnvironment.js +30 -0
  166. package/dist/runtime/firstProgressAdvisory.js +11 -11
  167. package/dist/runtime/index.js +4 -3
  168. package/dist/runtime/jsonLineChannel.js +109 -0
  169. package/dist/runtime/launchBroker.js +91 -16
  170. package/dist/runtime/launchDiagnostics.js +2 -2
  171. package/dist/runtime/lifecycleReservation.js +10 -18
  172. package/dist/runtime/managedCaller.js +61 -17
  173. package/dist/runtime/nativeSessionControl.js +102 -0
  174. package/dist/runtime/ports.js +6 -21
  175. package/dist/runtime/processExitObservation.js +8 -7
  176. package/dist/runtime/promptEnvelope.js +17 -6
  177. package/dist/runtime/providerContinuation.js +3 -9
  178. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  179. package/dist/runtime/providerControl.js +2 -7
  180. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  181. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  182. package/dist/runtime/runtimeBinding.js +0 -1
  183. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  184. package/dist/runtime/runtimeDeadlines.js +9 -0
  185. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  186. package/dist/runtime/runtimeObservation.js +29 -65
  187. package/dist/runtime/runtimeProjection.js +43 -51
  188. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  189. package/dist/runtime/sessionLaunchRequest.js +3 -7
  190. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  191. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  192. package/dist/runtime/sessionReconciliation.js +4 -8
  193. package/dist/runtime/sessionTerminationGuard.js +70 -259
  194. package/dist/runtime/sessionTokenMetrics.js +5 -16
  195. package/dist/runtime/structuredProviderHost.js +237 -117
  196. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  197. package/dist/runtime/tmuxAdapters.js +39 -86
  198. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  199. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  200. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  201. package/dist/scheduler/ports.js +80 -9
  202. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  203. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  204. package/dist/scheduler/taskExecutionProjection.js +120 -124
  205. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  206. package/dist/scheduler/taskWake.js +11 -4
  207. package/dist/scheduler/wakeReason.js +9 -1
  208. package/dist/setup/setupCommand.js +1 -0
  209. package/dist/storage/migrations/agentRunContract.js +159 -0
  210. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  211. package/dist/storage/sqliteSchema.js +431 -5
  212. package/dist/storage/sqliteStore.js +375 -220
  213. package/dist/storage/storageVersions.js +1 -1
  214. package/dist/storage/storeRpc.js +10 -5
  215. package/dist/storage/taskStore.js +13 -11
  216. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  217. package/dist/surface/surfaceContributions.js +102 -0
  218. package/dist/task/completionReadiness.js +32 -6
  219. package/dist/task/deliveryGuard.js +16 -16
  220. package/dist/task/draftPlan.js +72 -12
  221. package/dist/task/nextAction.js +144 -128
  222. package/dist/task/remoteDelivery.js +6 -6
  223. package/dist/task/task.js +184 -18
  224. package/dist/task/taskActivation.js +301 -0
  225. package/dist/task/taskActivationService.js +392 -0
  226. package/dist/task/taskRecordReference.js +5 -4
  227. package/dist/task/taskRecordRetirement.js +1 -1
  228. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  229. package/dist/telemetry/telemetryConfig.js +14 -14
  230. package/dist/telemetry/telemetryWiring.js +2 -2
  231. package/dist/web/assets/assetManifest.js +2 -0
  232. package/dist/web/assets/client/app.js +120 -20
  233. package/dist/web/assets/client/components.js +87 -54
  234. package/dist/web/assets/client/i18n.js +83 -41
  235. package/dist/web/assets/client/markdown.js +1 -1
  236. package/dist/web/assets/client/taskSurface.js +353 -0
  237. package/dist/web/assets/client/view.js +49 -44
  238. package/dist/web/assets/shell.js +1 -1
  239. package/dist/web/assets/styles/cards.js +22 -4
  240. package/dist/web/controllerWeb.js +60 -0
  241. package/dist/web/webMutation.js +28 -0
  242. package/dist/web/webServer.js +118 -8
  243. package/dist/web/webSnapshot.js +81 -74
  244. package/dist/web/webTaskSurface.js +64 -0
  245. package/dist/workItem/dependencyGate.js +1 -1
  246. package/dist/workItem/workItem.js +80 -48
  247. package/dist/workspace/workItemChangeSetManager.js +16 -9
  248. package/docs/agent-result-consumption.md +94 -0
  249. package/docs/agent-runtime-drivers.md +91 -0
  250. package/docs/architecture/README.md +38 -0
  251. package/docs/architecture/capabilities-and-resources.md +79 -0
  252. package/docs/managed-turn-and-session-runtime.md +222 -0
  253. package/docs/observability/README.md +81 -0
  254. package/docs/plugin-sdk.md +290 -0
  255. package/docs/provider-runtime.md +163 -0
  256. package/docs/release-workflow.md +303 -0
  257. package/docs/roles-and-configuration.md +113 -0
  258. package/docs/sqlite-control-plane-design.md +76 -0
  259. package/docs/task-dag-semantics.md +57 -0
  260. package/docs/task-delivery.md +103 -0
  261. package/docs/task-local-identity.md +6 -6
  262. package/docs/testing/verification-levels.md +86 -0
  263. package/i18n/README.zh-CN.md +98 -739
  264. package/package.json +5 -5
  265. package/skills/yui-leader/SKILL.md +130 -103
  266. package/skills/yui-leader/references/integration.md +39 -0
  267. package/skills/yui-leader/references/replicated-execution.md +42 -0
  268. package/skills/yui-leader/references/task-plugins.md +33 -0
  269. package/skills/yui-operator/SKILL.md +30 -59
  270. package/skills/yui-reviewer/SKILL.md +35 -36
  271. package/skills/yui-runtime/SKILL.md +88 -24
  272. package/skills/yui-runtime/references/publication.md +22 -0
  273. package/skills/yui-runtime/references/recovery.md +64 -0
  274. package/skills/yui-worker/SKILL.md +37 -39
  275. package/dist/cli/roleOptionCatalog.js +0 -68
  276. package/dist/context/sourceTurnContext.js +0 -30
  277. package/dist/execution/reviewMainTurn.js +0 -161
  278. package/dist/execution/workItemMainTurn.js +0 -164
  279. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  280. package/dist/runtime/preallocatedNativeSession.js +0 -13
  281. package/dist/runtime/runtimeStopReceipt.js +0 -42
  282. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -7,7 +7,7 @@ import { validateDeltaRecheckRecord } from "./reviewRound.js";
7
7
  export async function assessDeltaRecheck(input) {
8
8
  const { repositoryPaths, previousRound, candidate, git } = input;
9
9
  if (previousRound.status !== "completed"
10
- || previousRound.reviewerTurnId === undefined
10
+ || previousRound.reviewerRunId === undefined
11
11
  || (previousRound.scope ?? "work-item") !== "task") {
12
12
  return {
13
13
  kind: "ineligible",
@@ -129,8 +129,8 @@ export function buildDeltaRecheckDispatchContext(input) {
129
129
  " semantic change, evidence doubt). This is the safe default.",
130
130
  "Yui verified only the technical delta boundary; a Task-control Agent selected this mode.",
131
131
  `Previous accepted ReviewRound: ${previousRound.id}@${record.previousBaseCommit}`,
132
- `Previous Reviewer Turn: ${previousRound.reviewerTurnId ?? "unavailable"}`,
133
- "Read that exact source Turn's original result from the frozen Context Snapshot.",
132
+ `Previous Reviewer AgentRun: ${previousRound.reviewerRunId ?? "unavailable"}`,
133
+ "Read that exact source AgentRun's original result from the frozen Context Snapshot.",
134
134
  ...(round.taskCandidate?.projects.map((project) => {
135
135
  const previous = previousRound.taskCandidate?.projects
136
136
  .find((entry) => entry.projectId === project.projectId)?.commit;
@@ -1,29 +1,29 @@
1
- export function isCompletedReviewExecutionFromTurns(round, turns) {
2
- if (round.status !== "completed" || round.reviewerTurnId === undefined)
1
+ export function isCompletedReviewExecutionFromRuns(round, runs) {
2
+ if (round.status !== "completed" || round.reviewerRunId === undefined)
3
3
  return false;
4
- const turn = turns.find(({ id }) => id === round.reviewerTurnId);
5
- return turn !== undefined
6
- && turn.status === "completed"
7
- && turn.result !== undefined
8
- && turn.purpose === "review"
9
- && turn.taskId === round.taskId
10
- && turn.reviewRoundId === round.id
11
- && turn.roleName === round.reviewerRoleName
12
- && turn.executionGroupId === undefined
13
- && turn.effective.reviewBaseCommit === round.reviewBaseCommit;
4
+ const run = runs.find(({ id }) => id === round.reviewerRunId);
5
+ return run !== undefined
6
+ && run.status === "completed"
7
+ && run.result !== undefined
8
+ && run.purpose === "review"
9
+ && run.taskId === round.taskId
10
+ && run.reviewRoundId === round.id
11
+ && run.roleName === round.reviewerRoleName
12
+ && run.executionGroupId === undefined
13
+ && run.effective.reviewBaseCommit === round.reviewBaseCommit;
14
14
  }
15
15
  /**
16
- * Whether a Task-final ReviewRound has one exact completed main Reviewer Turn.
16
+ * Whether a Task-final ReviewRound has one exact completed main Reviewer AgentRun.
17
17
  * This is structural evidence only and never means the Leader accepted it.
18
18
  */
19
19
  export function isCompletedTaskReviewEvidence(store, round) {
20
- return isCompletedTaskReviewEvidenceFromTurns(round, store.listTurns(round.taskId));
20
+ return isCompletedTaskReviewEvidenceFromRuns(round, store.listRuns(round.taskId));
21
21
  }
22
- export function isCompletedTaskReviewEvidenceFromTurns(round, turns) {
22
+ export function isCompletedTaskReviewEvidenceFromRuns(round, runs) {
23
23
  if ((round.scope ?? "work-item") !== "task"
24
24
  || round.taskCandidate === undefined
25
25
  || round.taskCandidate.projects.length === 0) {
26
26
  return false;
27
27
  }
28
- return isCompletedReviewExecutionFromTurns(round, turns);
28
+ return isCompletedReviewExecutionFromRuns(round, runs);
29
29
  }
@@ -3,7 +3,7 @@ import { isCompletedTaskReviewEvidence } from "./reviewAcceptance.js";
3
3
  import { projectReviewerAvailability } from "./reviewerAvailability.js";
4
4
  /** Read-only facts for Leader judgment; this projection never blocks an action. */
5
5
  export function projectReviewDecision(input) {
6
- const { store, task, roles, turns, rounds, reviewConfig, currentCandidate } = input;
6
+ const { store, task, roles, runs, rounds, reviewConfig, currentCandidate } = input;
7
7
  const taskRounds = rounds.filter((round) => (round.scope ?? "work-item") === "task");
8
8
  const accepted = [...taskRounds]
9
9
  .filter((round) => isCompletedTaskReviewEvidence(store, round))
@@ -20,15 +20,15 @@ export function projectReviewDecision(input) {
20
20
  const activeReviews = taskRounds
21
21
  .filter((round) => (round.status === "pending" || round.status === "running"))
22
22
  .map((round) => {
23
- const activeTurn = turns.find((turn) => (turn.status === "active" && turn.reviewRoundId === round.id));
24
- const workspaceRoot = round.workspace?.root ?? activeTurn?.workspace?.root;
23
+ const activeRun = runs.find((run) => (run.status === "active" && run.reviewRoundId === round.id));
24
+ const workspaceRoot = round.workspace?.root ?? activeRun?.workspace?.root;
25
25
  return {
26
26
  reviewRoundId: round.id,
27
27
  reviewerRoleName: round.reviewerRoleName,
28
28
  mode: round.deltaRecheck === undefined ? "full" : "delta-recheck",
29
29
  status: round.status,
30
- ...(activeTurn === undefined ? {} : { activeTurnId: activeTurn.id }),
31
- startedAt: activeTurn?.createdAt ?? round.createdAt,
30
+ ...(activeRun === undefined ? {} : { activeRunId: activeRun.id }),
31
+ startedAt: activeRun?.createdAt ?? round.createdAt,
32
32
  frozenCandidate: round.taskCandidate ?? null,
33
33
  candidateRelation: candidateRelation(round.taskCandidate ?? null, currentCandidate),
34
34
  ...(workspaceRoot === undefined ? {} : { workspaceRoot })
@@ -62,9 +62,9 @@ export function projectReviewDecision(input) {
62
62
  reviewerRoleName,
63
63
  status: "busy",
64
64
  phase: availability.phase,
65
- ...(availability.activeTurnId === undefined
65
+ ...(availability.activeRunId === undefined
66
66
  ? {}
67
- : { activeTurnId: availability.activeTurnId }),
67
+ : { activeRunId: availability.activeRunId }),
68
68
  ...(availability.activeReviewRoundId === undefined
69
69
  ? {}
70
70
  : { activeReviewRoundId: availability.activeReviewRoundId }),
@@ -78,12 +78,12 @@ export function attachReviewRoundWorkspace(round, workspace) {
78
78
  }
79
79
  return validateReviewRound({ ...round, workspace });
80
80
  }
81
- export function startReviewRound(round, reviewerTurnId) {
81
+ export function startReviewRound(round, reviewerRunId) {
82
82
  validateReviewRound(round);
83
83
  if (round.status !== "pending"
84
84
  && !(round.status === "running"
85
85
  && round.executionGroup !== undefined
86
- && round.reviewerTurnId === undefined)) {
86
+ && round.reviewerRunId === undefined)) {
87
87
  throw new Error(`ReviewRound cannot start from ${round.status}: ${round.id}.`);
88
88
  }
89
89
  if (round.workspace === undefined) {
@@ -91,7 +91,7 @@ export function startReviewRound(round, reviewerTurnId) {
91
91
  }
92
92
  return validateReviewRound({
93
93
  ...round,
94
- reviewerTurnId: requireIdentity(reviewerTurnId, "Reviewer Turn id"),
94
+ reviewerRunId: requireIdentity(reviewerRunId, "Reviewer AgentRun id"),
95
95
  status: "running"
96
96
  });
97
97
  }
@@ -125,7 +125,7 @@ export function finishReviewRound(round, status, now, failure) {
125
125
  }
126
126
  /**
127
127
  * Retry a failed review execution attempt under the same semantic Round
128
- * identity. Turn history remains the attempt trail; the Round itself returns
128
+ * identity. AgentRun history remains the attempt trail; the Round itself returns
129
129
  * to pending so infrastructure retries do not manufacture a new semantic
130
130
  * ReviewRound or duplicate findings.
131
131
  */
@@ -172,12 +172,13 @@ export function retryReviewRound(round, requestedBy, now) {
172
172
  deletedLines: round.deltaRecheck.deletedLines
173
173
  })
174
174
  }),
175
- // A replicated retry preserves settled successful Producers and reopens
176
- // only failed Lanes. If every Producer succeeded, only the main Reviewer
177
- // Turn is retried.
175
+ // A main retry consumes its already selected sources and leaves every
176
+ // Producer attempt untouched. A pre-main retry reopens failed Lanes only.
178
177
  ...(round.executionGroup === undefined
179
178
  ? {}
180
- : { executionGroup: retryFailedExecutionLanes(round.executionGroup, now) }),
179
+ : { executionGroup: round.reviewerRunId === undefined
180
+ ? retryFailedExecutionLanes(round.executionGroup, now)
181
+ : round.executionGroup }),
181
182
  requestedBy: validateReviewRequestSource(requestedBy),
182
183
  status: "pending",
183
184
  ...(round.workspace === undefined ? {} : { workspace: round.workspace }),
@@ -191,16 +192,16 @@ export function retryTaskReviewRound(round, requestedBy, now) {
191
192
  }
192
193
  return retryReviewRound(round, requestedBy, now);
193
194
  }
194
- /** A failed producer attempt leaves its logical Lane open for another Turn. */
195
- export function retryRunningReviewExecutionLane(round, executionLaneId, turnId) {
195
+ /** A failed producer attempt leaves its logical Lane open for another AgentRun. */
196
+ export function retryRunningReviewExecutionLane(round, executionLaneId, runId) {
196
197
  validateReviewRound(round);
197
198
  if (round.status !== "running" || round.executionGroup === undefined) {
198
199
  throw new Error(`ReviewRound ${round.id} has no running ExecutionGroup.`);
199
200
  }
200
201
  const lane = round.executionGroup.lanes.find(({ id }) => id === executionLaneId);
201
- if (lane === undefined || lane.disposition !== "open" || lane.currentTurnId !== turnId) {
202
+ if (lane === undefined || lane.disposition !== "open" || lane.currentRunId !== runId) {
202
203
  throw new Error(`Review retry does not target the current failed Lane attempt: `
203
- + `${round.executionGroup.id}/${executionLaneId}/${turnId}.`);
204
+ + `${round.executionGroup.id}/${executionLaneId}/${runId}.`);
204
205
  }
205
206
  return round;
206
207
  }
@@ -268,7 +269,7 @@ export function validateReviewRound(round) {
268
269
  "workItemId",
269
270
  "candidateId",
270
271
  "reviewerRoleName",
271
- "reviewerTurnId",
272
+ "reviewerRunId",
272
273
  "reviewBaseCommit",
273
274
  "scope",
274
275
  "taskCandidate",
@@ -338,19 +339,19 @@ export function validateReviewRound(round) {
338
339
  }
339
340
  validateDeltaRecheckRecord(round.deltaRecheck);
340
341
  }
341
- if (round.reviewerTurnId !== undefined) {
342
+ if (round.reviewerRunId !== undefined) {
342
343
  validateTaskRecordReference({
343
344
  taskId: round.taskId,
344
- localId: round.reviewerTurnId
345
- }, "turn");
345
+ localId: round.reviewerRunId
346
+ }, "run");
346
347
  }
347
348
  if (round.workspace !== undefined)
348
349
  validateReviewWorkspace(round, round.workspace);
349
350
  requireTimestamp(round.createdAt, "ReviewRound createdAt");
350
351
  const terminal = round.status === "completed" || round.status === "failed";
351
352
  if (terminal) {
352
- if (round.status === "completed" && round.reviewerTurnId === undefined) {
353
- throw new Error("A completed ReviewRound requires its exact main Reviewer Turn.");
353
+ if (round.status === "completed" && round.reviewerRunId === undefined) {
354
+ throw new Error("A completed ReviewRound requires its exact main Reviewer AgentRun.");
354
355
  }
355
356
  if (round.status === "completed" && round.failure !== undefined) {
356
357
  throw new Error("A completed ReviewRound cannot carry failure metadata.");
@@ -370,9 +371,9 @@ export function validateReviewRound(round) {
370
371
  throw new Error("A running ReviewRound requires its main Reviewer workspace.");
371
372
  }
372
373
  if (round.status === "running"
373
- && round.reviewerTurnId === undefined
374
+ && round.reviewerRunId === undefined
374
375
  && round.executionGroup === undefined) {
375
- throw new Error("A running ReviewRound requires a direct Reviewer Turn or replicated Group.");
376
+ throw new Error("A running ReviewRound requires a direct Reviewer AgentRun or replicated Group.");
376
377
  }
377
378
  if (round.workspaceDisposition !== undefined) {
378
379
  if (!terminal || round.workspace === undefined) {
@@ -2,13 +2,13 @@ import { nextPendingBatch, mailboxHasWork } from "../coordination/workMailbox.js
2
2
  import { runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
3
3
  /** One authoritative read-only projection for a Task Reviewer Role slot. */
4
4
  export function projectReviewerAvailability(store, taskId, reviewerRoleName) {
5
- const active = store.getActiveTurn(taskId, reviewerRoleName);
5
+ const active = store.getActiveRun(taskId, reviewerRoleName);
6
6
  if (active !== null) {
7
7
  return {
8
8
  kind: "busy",
9
9
  reviewerRoleName,
10
10
  phase: "active-turn",
11
- activeTurnId: active.id,
11
+ activeRunId: active.id,
12
12
  ...(active.reviewRoundId === undefined
13
13
  ? {}
14
14
  : { activeReviewRoundId: active.reviewRoundId }),
package/dist/role/role.js CHANGED
@@ -1,9 +1,20 @@
1
1
  import { isDeepStrictEqual } from "node:util";
2
+ import { validateExecutionEnvironmentSnapshot } from "../resources/projectResource.js";
3
+ import { isAgentAdapterId } from "../agent/adapterCatalog.js";
4
+ import { adapterIdForExecutionComponent, resolveAgentExecutionComponent } from "../agent/executionComponents.js";
2
5
  import { defaultRoleAgentConfig, resolveAgentAdapter } from "../executor/agentAdapter.js";
3
6
  import { validateRoleSessionSet } from "../executor/agentExecutor.js";
7
+ /**
8
+ * The Agent argument is the stored record, not a hand-picked pair of fields.
9
+ * `component` is required for exactly that reason: an Agent registered as the
10
+ * Claude Agent SDK that reached a Role binding as `unknown-acp-agent` would be
11
+ * silently demoted, and an optional parameter makes that a quiet default
12
+ * instead of a compile error at the call site that forgot it.
13
+ */
4
14
  export function createRoleAgentBinding(agent, config) {
5
15
  const agentId = requireSafeIdentity(agent.id, "Role Agent id");
6
16
  const adapterId = requireSupportedAdapterId(agent.adapterId);
17
+ const component = resolveAgentExecutionComponent(adapterId, agent.component);
7
18
  const defaults = defaultRoleAgentConfig(adapterId);
8
19
  const effectiveConfig = config === undefined
9
20
  ? defaults
@@ -13,7 +24,7 @@ export function createRoleAgentBinding(agent, config) {
13
24
  if (effectiveConfig.adapterId !== adapterId) {
14
25
  throw new Error(`Role Agent config adapter does not match Agent: ${agentId}.`);
15
26
  }
16
- return cloneBinding({ agentId, adapterId, config: effectiveConfig });
27
+ return cloneBinding({ agentId, component, adapterId, config: effectiveConfig });
17
28
  }
18
29
  export function createRole(taskId, name, bindings, activeAgentId, workspace, now, profile = {}, defaultAccess = "write") {
19
30
  const owner = createRoleOwner(name, bindings, activeAgentId, workspace, now, profile, defaultAccess);
@@ -72,6 +83,11 @@ export function updateRole(role, patch, now) {
72
83
  ...cloneRolePatch(patch),
73
84
  updatedAt: now.toISOString()
74
85
  };
86
+ if (patch.executionEnvironment === null)
87
+ delete updated.executionEnvironment;
88
+ else if (patch.executionEnvironment !== undefined) {
89
+ updated.executionEnvironment = cloneJson(patch.executionEnvironment);
90
+ }
75
91
  clearProfileFields(updated, patch);
76
92
  updated.launchRevision = isDeepStrictEqual(desiredBefore, desiredLaunchProjection(updated))
77
93
  ? role.launchRevision
@@ -93,7 +109,7 @@ export function switchActiveRoleAgent(role, sessions, targetAgentId, runtime, no
93
109
  : updateGlobalRole(role, { activeAgentId: normalizedTarget }, now);
94
110
  // A running process keeps its immutable effective identity. The desired
95
111
  // switch becomes visible only when the next launch is planned.
96
- const updatedSessions = runtime.activeTurn || runtime.nativeProcessRunning
112
+ const updatedSessions = runtime.activeRun || runtime.nativeProcessRunning
97
113
  ? sessions
98
114
  : {
99
115
  ...sessions,
@@ -129,11 +145,11 @@ export function unbindRoleAgent(role, sessions, agentId, now) {
129
145
  const taskSessions = sessions.owner.scope === "task"
130
146
  ? sessions
131
147
  : null;
132
- if (taskSessions?.providerBinding?.turn !== null
133
- && taskSessions?.providerBinding?.turn !== undefined
148
+ if (taskSessions?.providerBinding?.run !== null
149
+ && taskSessions?.providerBinding?.run !== undefined
134
150
  && taskSessions.activeAgentId === normalizedAgentId
135
- && ["submitting", "accepted", "running"].includes(taskSessions.providerBinding.turn.status)) {
136
- throw new Error(`Cannot unbind Role Agent with an active Turn: ${normalizedAgentId}.`);
151
+ && ["submitting", "accepted", "running"].includes(taskSessions.providerBinding.run.status)) {
152
+ throw new Error(`Cannot unbind Role Agent with an active AgentRun: ${normalizedAgentId}.`);
137
153
  }
138
154
  const targetSession = sessions.sessions[normalizedAgentId];
139
155
  if (targetSession !== undefined && targetSession.status === "active") {
@@ -215,6 +231,14 @@ function validateRoleOwner(role) {
215
231
  requireSafeIdentity(role.name, "Role name");
216
232
  requireSafeIdentity(role.activeAgentId, "Role active Agent id");
217
233
  requireText(role.workspace, "Role workspace");
234
+ if ("executionEnvironment" in role && role.executionEnvironment !== undefined) {
235
+ if (!("taskId" in role))
236
+ throw new Error("Only a Task Role may bind an execution environment.");
237
+ validateExecutionEnvironmentSnapshot(role.executionEnvironment);
238
+ if (role.executionEnvironment.taskId !== role.taskId) {
239
+ throw new Error("Role execution environment belongs to another Task.");
240
+ }
241
+ }
218
242
  const entries = Object.entries(role.agentBindings);
219
243
  if (entries.length === 0)
220
244
  throw new Error("Role requires at least one Agent binding.");
@@ -232,6 +256,16 @@ function validateRoleOwner(role) {
232
256
  function validateRoleAgentBinding(binding) {
233
257
  const agentId = requireSafeIdentity(binding.agentId, "Role Agent id");
234
258
  const adapterId = requireSupportedAdapterId(binding.adapterId);
259
+ // Storage 10 backfilled every stored binding, so a missing component here is
260
+ // a corrupt record rather than an old one. Defaulting it would invent a
261
+ // product identity for data that never lost one.
262
+ if (binding.component === undefined) {
263
+ throw new Error(`Role Agent binding is missing its execution component: ${agentId}.`);
264
+ }
265
+ const component = resolveAgentExecutionComponent(adapterId, binding.component);
266
+ if (adapterIdForExecutionComponent(component) !== adapterId) {
267
+ throw new Error(`Role Agent binding execution component is inconsistent: ${agentId}.`);
268
+ }
235
269
  if (binding.config === null || typeof binding.config !== "object" || Array.isArray(binding.config)) {
236
270
  throw new Error(`Role Agent config is invalid: ${agentId}.`);
237
271
  }
@@ -272,6 +306,9 @@ function desiredLaunchProjection(role) {
272
306
  agentBindings: role.agentBindings,
273
307
  workspace: role.workspace,
274
308
  defaultAccess: role.defaultAccess,
309
+ ...("taskId" in role && role.executionEnvironment !== undefined
310
+ ? { executionEnvironment: role.executionEnvironment }
311
+ : {}),
275
312
  ...cloneProfile(role)
276
313
  };
277
314
  }
@@ -281,6 +318,10 @@ function cloneBindings(bindings) {
281
318
  function cloneBinding(binding) {
282
319
  return {
283
320
  agentId: binding.agentId,
321
+ // Copied, never re-derived. Cloning is not the place to decide what an
322
+ // absent component means: validation above already refuses that record,
323
+ // and resolving here would hide the refusal behind a plausible default.
324
+ component: binding.component,
284
325
  adapterId: binding.adapterId,
285
326
  config: cloneJson(binding.config)
286
327
  };
@@ -313,7 +354,10 @@ function cloneJson(value) {
313
354
  }
314
355
  function requireSupportedAdapterId(value) {
315
356
  const normalized = requireText(value, "Role Agent adapter id");
316
- if (normalized !== "codex" && normalized !== "claude") {
357
+ // The catalog defines which adapters exist. A second list here would let a
358
+ // catalogued adapter be registered as an Agent and then rejected when a Role
359
+ // binds to it, which reads as corruption rather than as the missing entry.
360
+ if (!isAgentAdapterId(normalized)) {
317
361
  throw new Error(`Role Agent adapter is unsupported: ${normalized}.`);
318
362
  }
319
363
  return normalized;
@@ -0,0 +1,30 @@
1
+ import { createTaskEvent } from "../event/taskEvent.js";
2
+ import { enqueueWork } from "../coordination/workMailboxQueue.js";
3
+ /** Called inside the owner's transaction, after authorization and validation.
4
+ * Current Role, history and durable wake are one mutation. Runtime notification
5
+ * belongs to the entry point, only after the outer transaction commits.
6
+ */
7
+ export function saveTaskRoleUpdate(store, previous, current, now, source) {
8
+ store.saveRole(current.taskId, current);
9
+ store.saveEvent(current.taskId, createTaskEvent(store.nextEventId(current.taskId), current.taskId, "role.updated", {
10
+ ...source,
11
+ role: current.name,
12
+ ...roleLaunchEventPayload(current, store.getTaskRoleSessionSet(current.taskId, current.name)),
13
+ previous: JSON.stringify(previous),
14
+ current: JSON.stringify(current)
15
+ }, now));
16
+ enqueueWork(store, { kind: "task", taskId: current.taskId }, "role-updated", now, [{ type: "task", id: current.taskId }]);
17
+ }
18
+ export function roleLaunchEventPayload(role, sessions) {
19
+ const effective = sessions?.sessions[sessions.activeAgentId]?.effective;
20
+ return {
21
+ desiredRevision: String(role.launchRevision),
22
+ defaultAccess: role.defaultAccess,
23
+ effectiveRevision: effective === undefined ? "none" : String(effective.sourceDesiredRevision),
24
+ profileAccess: effective?.profileAccess ?? "none",
25
+ effectivePermission: effective?.permission.strategy ?? "none",
26
+ desiredDrift: effective === undefined
27
+ ? "not-started"
28
+ : effective.sourceDesiredRevision === role.launchRevision ? "none" : "pending-next-launch"
29
+ };
30
+ }