@zq-silk/yui 0.15.7 → 0.15.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/ARCHITECTURE.md +192 -399
  2. package/README.md +127 -1149
  3. package/dist/agent/adapterCatalog.js +15 -2
  4. package/dist/agent/agent.js +23 -3
  5. package/dist/agent/argumentPolicy.js +7 -1
  6. package/dist/agent/connectionPlan.js +62 -0
  7. package/dist/agent/executionComponents.js +158 -0
  8. package/dist/agent/launchEnvironment.js +31 -3
  9. package/dist/agent/managedRuntimeEnvironment.js +3 -5
  10. package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
  11. package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
  12. package/dist/brief/taskBrief.js +12 -0
  13. package/dist/cli/agentConfigurationPicker.js +13 -0
  14. package/dist/cli/commandCatalog.js +157 -70
  15. package/dist/cli/interactionCandidates.js +5 -5
  16. package/dist/cli/interactionPolicy.js +38 -8
  17. package/dist/cli/invocationRouter.js +1 -1
  18. package/dist/cli/managedDiagnostics.js +28 -0
  19. package/dist/cli/operatorWizard.js +1 -7
  20. package/dist/cli/roleOptionOrder.js +27 -0
  21. package/dist/cli/roleWizard.js +50 -14
  22. package/dist/cli/updateOrchestrator.js +1 -1
  23. package/dist/cli/updatePorts.js +3 -4
  24. package/dist/cli.js +178 -95
  25. package/dist/commands/agentCommands.js +72 -14
  26. package/dist/commands/capabilityCommands.js +9 -6
  27. package/dist/commands/configCommands.js +20 -20
  28. package/dist/commands/deliveryGuardPreflight.js +2 -2
  29. package/dist/commands/executionAuditCommands.js +24 -24
  30. package/dist/commands/globalRoleCommands.js +1 -1
  31. package/dist/commands/grantCommands.js +4 -4
  32. package/dist/commands/operatorCommands.js +1 -7
  33. package/dist/commands/projectCommands.js +4 -4
  34. package/dist/commands/resourcesCommands.js +2 -2
  35. package/dist/commands/roleConfiguration.js +25 -5
  36. package/dist/commands/roleRuntimeGuard.js +4 -5
  37. package/dist/commands/sessionCommands.js +3 -7
  38. package/dist/commands/taskActivationCommands.js +259 -0
  39. package/dist/commands/taskActor.js +28 -49
  40. package/dist/commands/taskCommands.js +1188 -710
  41. package/dist/commands/taskContextCommand.js +39 -583
  42. package/dist/commands/taskExecutionCommands.js +32 -32
  43. package/dist/commands/taskInputCommands.js +40 -104
  44. package/dist/commands/taskIntegrationCommands.js +3 -2
  45. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  46. package/dist/commands/taskNextActionCommand.js +8 -8
  47. package/dist/commands/taskOverviewCommand.js +33 -45
  48. package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
  49. package/dist/commands/taskRoleRuntimeStatus.js +133 -102
  50. package/dist/commands/telemetryCommands.js +36 -38
  51. package/dist/config/configCatalog.js +4 -4
  52. package/dist/config/yuiConfig.js +8 -8
  53. package/dist/context/contextSnapshot.js +10 -10
  54. package/dist/context/dispatchContext.js +11 -11
  55. package/dist/context/roleSessionContext.js +6 -3
  56. package/dist/context/{turnContextPack.js → runContextPack.js} +146 -81
  57. package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
  58. package/dist/context/sessionBootstrapManifest.js +21 -2
  59. package/dist/context/sourceRunContext.js +30 -0
  60. package/dist/context/taskContext.js +458 -0
  61. package/dist/context/wakeNotification.js +27 -27
  62. package/dist/controller/agentRuntimeObserver.js +21 -24
  63. package/dist/controller/capabilityBridge.js +17 -6
  64. package/dist/controller/clientRuntime.js +65 -92
  65. package/dist/controller/controller.js +114 -188
  66. package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
  67. package/dist/controller/jobControl.js +54 -85
  68. package/dist/controller/resourceInventory.js +8 -27
  69. package/dist/controller/resourceInventoryLinux.js +12 -13
  70. package/dist/controller/runtime.js +529 -479
  71. package/dist/controller/runtimeEventInbox.js +55 -25
  72. package/dist/controller/runtimeEventProcessor.js +22 -31
  73. package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
  74. package/dist/controller/runtimeLaunchCoordinator.js +80 -426
  75. package/dist/controller/runtimeObservationHook.js +14 -18
  76. package/dist/controller/sessionNotify.js +16 -24
  77. package/dist/controller/sessionOwnerReconciliation.js +168 -50
  78. package/dist/controller/structuredProviderObservation.js +138 -99
  79. package/dist/coordination/workMailbox.js +3 -3
  80. package/dist/coordination/workMailboxQueue.js +36 -33
  81. package/dist/core/boundedRpc.js +8 -1
  82. package/dist/core/controllerClient.js +20 -1
  83. package/dist/core/controllerServer.js +4 -4
  84. package/dist/doctor/doctor.js +13 -2
  85. package/dist/domain/agentResultTransport.js +9 -9
  86. package/dist/execution/codexThreadNaming.js +2 -8
  87. package/dist/execution/executionHealth.js +51 -63
  88. package/dist/execution/reviewMainRun.js +137 -0
  89. package/dist/execution/workItemExecution.js +28 -29
  90. package/dist/execution/workItemExecutionProjection.js +99 -107
  91. package/dist/execution/workItemMainRun.js +141 -0
  92. package/dist/executor/agentAdapter.js +227 -20
  93. package/dist/executor/agentConfigurationCatalog.js +126 -4
  94. package/dist/executor/agentConfigurationProbe.js +162 -4
  95. package/dist/executor/agentExecutor.js +79 -78
  96. package/dist/executor/effectiveLaunch.js +105 -18
  97. package/dist/executor/executorRegistry.js +29 -44
  98. package/dist/executor/fileRoleLaunchPlanner.js +229 -154
  99. package/dist/executor/workspacePreflightClassification.js +16 -16
  100. package/dist/grant/capabilityGrant.js +6 -3
  101. package/dist/input/inputRequest.js +12 -10
  102. package/dist/integration/gitIntegrationService.js +4 -11
  103. package/dist/integration/integrationQueueService.js +4 -4
  104. package/dist/interaction/operatorPresentation.js +1 -1
  105. package/dist/kernel/builtinCapabilities.js +247 -12
  106. package/dist/kernel/capabilityRegistry.js +64 -18
  107. package/dist/kernel/instanceHost.js +12 -1
  108. package/dist/kernel/kernelPorts.js +2 -2
  109. package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
  110. package/dist/lifecycle/exactRunTerminalization.js +449 -0
  111. package/dist/message/message.js +62 -6
  112. package/dist/message/messageContinuation.js +204 -0
  113. package/dist/observability/executionAudit.js +70 -72
  114. package/dist/observability/faultClassification.js +2 -2
  115. package/dist/observability/orchestrationMetrics.js +8 -8
  116. package/dist/operator/operatorSessionHistory.js +1 -7
  117. package/dist/output/agentConfigurationPresentation.js +8 -3
  118. package/dist/output/agentRunConfigurationPresentation.js +128 -0
  119. package/dist/output/rolePresentation.js +54 -3
  120. package/dist/plugins/pluginChild.js +104 -0
  121. package/dist/plugins/pluginIntent.js +26 -0
  122. package/dist/plugins/pluginInterpreter.js +43 -0
  123. package/dist/plugins/pluginPackage.js +101 -0
  124. package/dist/plugins/pluginProcess.js +112 -0
  125. package/dist/plugins/pluginService.js +380 -0
  126. package/dist/profile/agentProfile.js +1 -1
  127. package/dist/repository/gitWorkspace.js +26 -4
  128. package/dist/repository/project.js +19 -4
  129. package/dist/repository/taskBaseFreshness.js +13 -13
  130. package/dist/repository/taskWorkspaceCoordinator.js +20 -27
  131. package/dist/repository/taskWorkspacePreparer.js +344 -83
  132. package/dist/resources/autoResourceGc.js +3 -3
  133. package/dist/resources/liveReferences.js +3 -3
  134. package/dist/resources/projectResource.js +123 -0
  135. package/dist/resources/projectResourceService.js +421 -0
  136. package/dist/resources/resourceDiscovery.js +6 -6
  137. package/dist/resources/resourceGc.js +1 -1
  138. package/dist/resources/resourceRegistrar.js +1 -1
  139. package/dist/resources/resourceTypes.js +1 -1
  140. package/dist/review/deltaRecheck.js +3 -3
  141. package/dist/review/reviewAcceptance.js +16 -16
  142. package/dist/review/reviewDecision.js +7 -7
  143. package/dist/review/reviewRound.js +21 -20
  144. package/dist/review/reviewerAvailability.js +2 -2
  145. package/dist/role/role.js +51 -7
  146. package/dist/role/taskRoleUpdate.js +30 -0
  147. package/dist/runtime/acpProtocol.js +425 -0
  148. package/dist/runtime/acpSession.js +731 -0
  149. package/dist/runtime/acpSessionConfiguration.js +260 -0
  150. package/dist/runtime/agentDriver.js +30 -11
  151. package/dist/runtime/agentEndpoint.js +278 -0
  152. package/dist/runtime/agentEndpointIdentity.js +86 -0
  153. package/dist/runtime/agentEndpointOwnership.js +239 -0
  154. package/dist/runtime/agentError.js +2 -10
  155. package/dist/runtime/agentHost.js +565 -314
  156. package/dist/runtime/agentRunConfiguration.js +258 -0
  157. package/dist/runtime/builtinAgentDrivers.js +134 -18
  158. package/dist/runtime/builtinAgentErrorMappers.js +55 -3
  159. package/dist/runtime/builtinTranscriptUsage.js +1 -1
  160. package/dist/runtime/claude-process-owner +0 -0
  161. package/dist/runtime/codexAppServerRuntime.js +38 -30
  162. package/dist/runtime/codexInteractiveHost.js +41 -6
  163. package/dist/runtime/continuationManager.js +2 -6
  164. package/dist/runtime/executionEnvironment.js +30 -0
  165. package/dist/runtime/firstProgressAdvisory.js +11 -11
  166. package/dist/runtime/index.js +4 -3
  167. package/dist/runtime/jsonLineChannel.js +109 -0
  168. package/dist/runtime/launchBroker.js +91 -16
  169. package/dist/runtime/launchDiagnostics.js +2 -2
  170. package/dist/runtime/lifecycleReservation.js +10 -18
  171. package/dist/runtime/managedCaller.js +61 -17
  172. package/dist/runtime/nativeSessionControl.js +102 -0
  173. package/dist/runtime/ports.js +6 -21
  174. package/dist/runtime/processExitObservation.js +8 -7
  175. package/dist/runtime/promptEnvelope.js +17 -6
  176. package/dist/runtime/providerContinuation.js +3 -9
  177. package/dist/runtime/providerContinuationReconciliationService.js +4 -13
  178. package/dist/runtime/providerControl.js +2 -7
  179. package/dist/runtime/providerRuntimeIdentity.js +110 -222
  180. package/dist/runtime/providerRuntimeReconciler.js +5 -9
  181. package/dist/runtime/runtimeBinding.js +0 -1
  182. package/dist/runtime/runtimeContinuationProjection.js +4 -7
  183. package/dist/runtime/runtimeDeadlines.js +9 -0
  184. package/dist/runtime/runtimeHealthPolicy.js +1 -1
  185. package/dist/runtime/runtimeObservation.js +29 -65
  186. package/dist/runtime/runtimeProjection.js +43 -51
  187. package/dist/runtime/runtimeSessionCandidate.js +1 -3
  188. package/dist/runtime/sessionLaunchRequest.js +3 -7
  189. package/dist/runtime/sessionOwnerIdentity.js +7 -54
  190. package/dist/runtime/sessionOwnerRegistry.js +22 -17
  191. package/dist/runtime/sessionReconciliation.js +4 -8
  192. package/dist/runtime/sessionTerminationGuard.js +70 -259
  193. package/dist/runtime/sessionTokenMetrics.js +5 -16
  194. package/dist/runtime/structuredProviderHost.js +237 -117
  195. package/dist/runtime/taskRuntimeIsolation.js +39 -122
  196. package/dist/runtime/tmuxAdapters.js +39 -86
  197. package/dist/scheduler/activeRoleRunDelivery.js +354 -0
  198. package/dist/scheduler/leaderWakeupProcessor.js +75 -266
  199. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  200. package/dist/scheduler/ports.js +80 -9
  201. package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
  202. package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
  203. package/dist/scheduler/taskExecutionProjection.js +120 -124
  204. package/dist/scheduler/taskObservabilityProjection.js +29 -29
  205. package/dist/scheduler/taskWake.js +11 -4
  206. package/dist/scheduler/wakeReason.js +9 -1
  207. package/dist/setup/setupCommand.js +1 -0
  208. package/dist/storage/migrations/agentRunContract.js +159 -0
  209. package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
  210. package/dist/storage/sqliteSchema.js +431 -5
  211. package/dist/storage/sqliteStore.js +375 -220
  212. package/dist/storage/storageVersions.js +1 -1
  213. package/dist/storage/storeRpc.js +10 -5
  214. package/dist/storage/taskStore.js +13 -11
  215. package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
  216. package/dist/surface/surfaceContributions.js +102 -0
  217. package/dist/task/completionReadiness.js +32 -6
  218. package/dist/task/deliveryGuard.js +16 -16
  219. package/dist/task/draftPlan.js +72 -12
  220. package/dist/task/nextAction.js +144 -128
  221. package/dist/task/remoteDelivery.js +6 -6
  222. package/dist/task/task.js +184 -18
  223. package/dist/task/taskActivation.js +301 -0
  224. package/dist/task/taskActivationService.js +392 -0
  225. package/dist/task/taskRecordReference.js +5 -4
  226. package/dist/task/taskRecordRetirement.js +1 -1
  227. package/dist/telemetry/sqliteTelemetryStore.js +55 -68
  228. package/dist/telemetry/telemetryConfig.js +14 -14
  229. package/dist/telemetry/telemetryWiring.js +2 -2
  230. package/dist/web/assets/assetManifest.js +2 -0
  231. package/dist/web/assets/client/app.js +120 -20
  232. package/dist/web/assets/client/components.js +87 -54
  233. package/dist/web/assets/client/i18n.js +83 -41
  234. package/dist/web/assets/client/markdown.js +1 -1
  235. package/dist/web/assets/client/taskSurface.js +353 -0
  236. package/dist/web/assets/client/view.js +49 -44
  237. package/dist/web/assets/shell.js +1 -1
  238. package/dist/web/assets/styles/cards.js +22 -4
  239. package/dist/web/controllerWeb.js +60 -0
  240. package/dist/web/webMutation.js +28 -0
  241. package/dist/web/webServer.js +118 -8
  242. package/dist/web/webSnapshot.js +81 -74
  243. package/dist/web/webTaskSurface.js +64 -0
  244. package/dist/workItem/dependencyGate.js +1 -1
  245. package/dist/workItem/workItem.js +80 -48
  246. package/dist/workspace/workItemChangeSetManager.js +16 -9
  247. package/docs/agent-result-consumption.md +94 -0
  248. package/docs/agent-runtime-drivers.md +91 -0
  249. package/docs/architecture/README.md +38 -0
  250. package/docs/architecture/capabilities-and-resources.md +79 -0
  251. package/docs/managed-turn-and-session-runtime.md +222 -0
  252. package/docs/observability/README.md +81 -0
  253. package/docs/plugin-sdk.md +290 -0
  254. package/docs/provider-runtime.md +163 -0
  255. package/docs/release-workflow.md +303 -0
  256. package/docs/roles-and-configuration.md +113 -0
  257. package/docs/sqlite-control-plane-design.md +76 -0
  258. package/docs/task-dag-semantics.md +57 -0
  259. package/docs/task-delivery.md +103 -0
  260. package/docs/task-local-identity.md +6 -6
  261. package/docs/testing/verification-levels.md +86 -0
  262. package/i18n/README.zh-CN.md +98 -739
  263. package/package.json +2 -2
  264. package/skills/yui-leader/SKILL.md +130 -103
  265. package/skills/yui-leader/references/integration.md +39 -0
  266. package/skills/yui-leader/references/replicated-execution.md +42 -0
  267. package/skills/yui-leader/references/task-plugins.md +33 -0
  268. package/skills/yui-operator/SKILL.md +30 -59
  269. package/skills/yui-reviewer/SKILL.md +35 -36
  270. package/skills/yui-runtime/SKILL.md +88 -24
  271. package/skills/yui-runtime/references/publication.md +22 -0
  272. package/skills/yui-runtime/references/recovery.md +64 -0
  273. package/skills/yui-worker/SKILL.md +37 -39
  274. package/dist/cli/roleOptionCatalog.js +0 -68
  275. package/dist/context/sourceTurnContext.js +0 -30
  276. package/dist/execution/reviewMainTurn.js +0 -161
  277. package/dist/execution/workItemMainTurn.js +0 -164
  278. package/dist/lifecycle/exactTurnTerminalization.js +0 -407
  279. package/dist/runtime/preallocatedNativeSession.js +0 -13
  280. package/dist/runtime/runtimeStopReceipt.js +0 -42
  281. package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
@@ -1,22 +1,41 @@
1
1
  import { validateEffectiveLaunchSnapshot } from "../executor/effectiveLaunch.js";
2
2
  import { validateTaskRecordReference } from "../task/taskRecordReference.js";
3
3
  import { validateManagedWorkspace } from "../worktree/managedWorkspace.js";
4
- import { createTurnInput, createTurnInputEnvelope, validateTurnInput } from "../context/turnInputContract.js";
5
- import { boundedTurnFailureDiagnostic, MAX_TURN_FAILURE_DIAGNOSTIC_BYTES, MAX_TURN_RESULT_OUTPUT_BYTES } from "../domain/agentResultTransport.js";
6
- export { boundedTurnFailureDiagnostic, MAX_TURN_FAILURE_DIAGNOSTIC_BYTES, MAX_TURN_RESULT_OUTPUT_BYTES, transportAgentResult } from "../domain/agentResultTransport.js";
7
- export function createTurn(id, taskId, roleName, mode, input, now, context) {
4
+ import { createRunInput, createRunInputEnvelope, validateRunInput } from "../context/runInputContract.js";
5
+ import { boundedRunFailureDiagnostic, MAX_RUN_FAILURE_DIAGNOSTIC_BYTES, MAX_RUN_RESULT_OUTPUT_BYTES } from "../domain/agentResultTransport.js";
6
+ export { boundedRunFailureDiagnostic, MAX_RUN_FAILURE_DIAGNOSTIC_BYTES, MAX_RUN_RESULT_OUTPUT_BYTES, transportAgentResult } from "../domain/agentResultTransport.js";
7
+ /** Record lifecycle and observed delivery are separate read-only facts. */
8
+ export function runExecutionObservation(run, binding, events = []) {
9
+ const current = binding?.run?.runId === run.id ? binding.run : undefined;
10
+ let delivery = current?.status ?? run.result?.provider?.status ?? "unobserved";
11
+ const lastError = events.filter((event) => event.type === "runtime.agent-error"
12
+ && event.payload.runId === run.id && event.payload.phase === "turn-submit"
13
+ && (current === undefined || event.payload.attemptId === current.attemptId)).at(-1);
14
+ if ((delivery === "unobserved" || delivery === "submitting") && lastError?.payload.inputDisposition === "unknown") {
15
+ delivery = "delivery-unknown";
16
+ }
17
+ return {
18
+ recordStatus: run.status,
19
+ delivery,
20
+ ...(current === undefined ? {} : {
21
+ attemptId: current.attemptId, observedAt: current.updatedAt,
22
+ ...(current.nativeTurnId === undefined ? {} : { nativeTurnId: current.nativeTurnId })
23
+ })
24
+ };
25
+ }
26
+ export function createRun(id, taskId, roleName, mode, input, now, context) {
8
27
  if (mode !== "new" && mode !== "resume") {
9
- throw new Error(`Turn dispatch mode is invalid: ${mode}.`);
28
+ throw new Error(`AgentRun dispatch mode is invalid: ${mode}.`);
10
29
  }
11
30
  const timestamp = now.toISOString();
12
- const normalizedInput = validateTurnInput(input);
31
+ const normalizedInput = validateRunInput(input);
13
32
  return {
14
33
  schemaVersion: 5,
15
- id: requireSafeIdentity(id, "Turn id"),
34
+ id: requireSafeIdentity(id, "AgentRun id"),
16
35
  taskId: requireSafeIdentity(taskId, "Task id"),
17
36
  roleName: requireSafeIdentity(roleName, "Role name"),
18
37
  mode,
19
- inputs: [turnInputRecord(normalizedInput, 1, timestamp)],
38
+ inputs: [runInputRecord(normalizedInput, 1, timestamp)],
20
39
  purpose: context.purpose ?? "execution",
21
40
  ...(context.workItemId === undefined
22
41
  ? {}
@@ -44,48 +63,64 @@ export function createTurn(id, taskId, roleName, mode, input, now, context) {
44
63
  updatedAt: timestamp
45
64
  };
46
65
  }
47
- export function isActiveTurn(run) {
66
+ export function isActiveRun(run) {
48
67
  return run.status === "active";
49
68
  }
69
+ /**
70
+ * The Task lifecycle a Turn of this purpose may run in.
71
+ *
72
+ * Delivery requires an active Task with execution admitted. Planning is the
73
+ * Draft Leader's own conversation, so it is also admitted while the Task is
74
+ * still a Draft; the execution gate still applies, because a stopped Task must
75
+ * not gain a live process through the planning door. Nothing here relaxes the
76
+ * workspace fence — a planning Turn simply has no workspace to be ready.
77
+ */
78
+ export function runPurposeAdmitsTaskState(purpose, task) {
79
+ if (task.executionGate.state !== "enabled")
80
+ return false;
81
+ return purpose === "planning"
82
+ ? task.status === "draft" || task.status === "active"
83
+ : task.status === "active";
84
+ }
50
85
  /** Binds a freshly created, not-yet-persisted Turn to its frozen Context. */
51
- export function withTurnContextSnapshot(run, snapshot, deltaRefIds = []) {
86
+ export function withRunContextSnapshot(run, snapshot, deltaRefIds = []) {
52
87
  const initial = run.inputs[0];
53
88
  if (run.status !== "active" || initial.input.contextSnapshotRef !== undefined) {
54
- throw new Error(`Cannot replace the Turn Context Snapshot: ${run.id}.`);
89
+ throw new Error(`Cannot replace the AgentRun Context Snapshot: ${run.id}.`);
55
90
  }
56
- const input = createTurnInput({
91
+ const input = createRunInput({
57
92
  ...initial.input,
58
93
  contextSnapshotRef: snapshot,
59
94
  deltaRefIds
60
95
  });
61
- return validateTurn(Object.freeze({
96
+ return validateRun(Object.freeze({
62
97
  ...run,
63
- inputs: [turnInputRecord(input, 1, initial.submittedAt), ...run.inputs.slice(1)]
98
+ inputs: [runInputRecord(input, 1, initial.submittedAt), ...run.inputs.slice(1)]
64
99
  }));
65
100
  }
66
- export function appendTurnInput(run, input, now) {
67
- validateTurn(run);
101
+ export function appendRunInput(run, input, now) {
102
+ validateRun(run);
68
103
  if (run.status !== "active")
69
- throw new Error(`Cannot append input to terminal Turn: ${run.id}.`);
104
+ throw new Error(`Cannot append input to terminal AgentRun: ${run.id}.`);
70
105
  const timestamp = now.toISOString();
71
106
  if (Date.parse(timestamp) < Date.parse(run.updatedAt)) {
72
- throw new Error("Turn input timestamp moved backwards.");
107
+ throw new Error("AgentRun input timestamp moved backwards.");
73
108
  }
74
- return validateTurn({
109
+ return validateRun({
75
110
  ...run,
76
- inputs: [...run.inputs, turnInputRecord(input, run.inputs.length + 1, timestamp)],
111
+ inputs: [...run.inputs, runInputRecord(input, run.inputs.length + 1, timestamp)],
77
112
  updatedAt: timestamp
78
113
  });
79
114
  }
80
- /** Derives Provider-visible identity from the Turn, the sole semantic owner. */
81
- export function turnInputEnvelope(run, sequence = 1) {
82
- validateTurn(run);
115
+ /** Derives Provider-visible identity from the AgentRun, the sole semantic owner. */
116
+ export function runInputEnvelope(run, sequence = 1) {
117
+ validateRun(run);
83
118
  const record = run.inputs[sequence - 1];
84
119
  if (record === undefined)
85
- throw new Error(`Turn input does not exist: ${run.id}/${sequence}.`);
86
- return createTurnInputEnvelope(turnEnvelopeContext(run), record.input);
120
+ throw new Error(`AgentRun input does not exist: ${run.id}/${sequence}.`);
121
+ return createRunInputEnvelope(runEnvelopeContext(run), record.input);
87
122
  }
88
- export function validateTurn(run) {
123
+ export function validateRun(run) {
89
124
  rejectUnknownFields(run, [
90
125
  "schemaVersion",
91
126
  "id",
@@ -105,28 +140,28 @@ export function validateTurn(run) {
105
140
  "result",
106
141
  "createdAt",
107
142
  "updatedAt"
108
- ], "Turn");
143
+ ], "AgentRun");
109
144
  if (run.schemaVersion !== 5)
110
- throw new Error("Turn must use schemaVersion 5.");
111
- validateTaskRecordReference({ taskId: run.taskId, localId: run.id }, "turn");
145
+ throw new Error("AgentRun must use schemaVersion 5.");
146
+ validateTaskRecordReference({ taskId: run.taskId, localId: run.id }, "run");
112
147
  requireSafeIdentity(run.roleName, "Role name");
113
148
  if (run.mode !== "new" && run.mode !== "resume") {
114
- throw new Error(`Turn dispatch mode is invalid: ${String(run.mode)}.`);
149
+ throw new Error(`AgentRun dispatch mode is invalid: ${String(run.mode)}.`);
115
150
  }
116
151
  if (!Array.isArray(run.inputs) || run.inputs.length === 0) {
117
- throw new Error("Turn requires at least one input.");
152
+ throw new Error("AgentRun requires at least one input.");
118
153
  }
119
154
  for (const [index, record] of run.inputs.entries()) {
120
155
  if (record.sequence !== index + 1)
121
- throw new Error("Turn input sequence is invalid.");
122
- requireTimestamp(record.submittedAt, "Turn input submittedAt");
123
- validateTurnInput(record.input);
156
+ throw new Error("AgentRun input sequence is invalid.");
157
+ requireTimestamp(record.submittedAt, "AgentRun input submittedAt");
158
+ validateRunInput(record.input);
124
159
  if (index > 0 && Date.parse(record.submittedAt) < Date.parse(run.inputs[index - 1].submittedAt)) {
125
- throw new Error("Turn input timestamps moved backwards.");
160
+ throw new Error("AgentRun input timestamps moved backwards.");
126
161
  }
127
162
  }
128
- if (!["execution", "review"].includes(run.purpose)) {
129
- throw new Error(`Turn purpose is invalid: ${String(run.purpose)}.`);
163
+ if (!["execution", "review", "planning"].includes(run.purpose)) {
164
+ throw new Error(`AgentRun purpose is invalid: ${String(run.purpose)}.`);
130
165
  }
131
166
  if (run.workItemId !== undefined) {
132
167
  validateTaskRecordReference({ taskId: run.taskId, localId: run.workItemId }, "workItem");
@@ -135,7 +170,7 @@ export function validateTurn(run) {
135
170
  validateTaskRecordReference({ taskId: run.taskId, localId: run.reviewRoundId }, "reviewRound");
136
171
  }
137
172
  if ((run.executionGroupId === undefined) !== (run.executionLaneId === undefined)) {
138
- throw new Error("Turn execution lineage is incomplete.");
173
+ throw new Error("AgentRun execution lineage is incomplete.");
139
174
  }
140
175
  if (run.executionGroupId !== undefined) {
141
176
  requireSafeIdentity(run.executionGroupId, "ExecutionGroup id");
@@ -143,54 +178,77 @@ export function validateTurn(run) {
143
178
  }
144
179
  if (run.sourceExecutionGroupId !== undefined) {
145
180
  requireSafeIdentity(run.sourceExecutionGroupId, "Source ExecutionGroup id");
181
+ if (run.purpose === "planning") {
182
+ throw new Error("A planning Turn cannot aggregate an Execution Lane group.");
183
+ }
146
184
  if ((run.purpose === "execution" && run.workItemId === undefined)
147
185
  || (run.purpose === "review" && run.reviewRoundId === undefined)) {
148
- throw new Error("A source ExecutionGroup requires a main execution or review Turn.");
186
+ throw new Error("A source ExecutionGroup requires a main execution or review AgentRun.");
187
+ }
188
+ if (run.executionGroupId !== undefined || run.executionLaneId !== undefined) {
189
+ throw new Error("A main AgentRun cannot also be an Execution Lane AgentRun.");
190
+ }
191
+ }
192
+ if (run.purpose === "planning") {
193
+ if (run.effective.executionAuthority !== "planning") {
194
+ throw new Error("A planning AgentRun cannot hold delivery authority.");
195
+ }
196
+ // Draft planning is deliberately delivery-free: no WorkItem, ReviewRound,
197
+ // Lane or workspace. That is what keeps a planning result from ever being
198
+ // read as execution evidence or promoted into a Candidate.
199
+ if (run.workItemId !== undefined) {
200
+ throw new Error("A planning Turn cannot reference a Work Item.");
201
+ }
202
+ if (run.reviewRoundId !== undefined) {
203
+ throw new Error("A planning Turn cannot reference a ReviewRound.");
149
204
  }
150
205
  if (run.executionGroupId !== undefined || run.executionLaneId !== undefined) {
151
- throw new Error("A main Turn cannot also be an Execution Lane Turn.");
206
+ throw new Error("A planning Turn cannot be an Execution Lane Turn.");
207
+ }
208
+ if (run.workspace !== undefined) {
209
+ throw new Error("A planning Turn cannot own a managed workspace.");
152
210
  }
153
211
  }
154
212
  if (run.workspace !== undefined) {
155
213
  validateManagedWorkspace(run.workspace);
156
214
  if (run.workspace.owner.taskId !== run.taskId) {
157
- throw new Error("Turn workspace belongs to another Task.");
215
+ throw new Error("AgentRun workspace belongs to another Task.");
158
216
  }
159
217
  if (run.workspace.owner.type === "work-item"
160
218
  && run.workspace.owner.workItemId !== run.workItemId) {
161
- throw new Error("Turn workspace belongs to another Work Item.");
219
+ throw new Error("AgentRun workspace belongs to another Work Item.");
162
220
  }
163
221
  if (run.workspace.owner.type === "work-item" && run.workItemId === undefined) {
164
- throw new Error("A WorkItem workspace requires a WorkItem Turn reference.");
222
+ throw new Error("A WorkItem workspace requires a WorkItem AgentRun reference.");
165
223
  }
166
224
  if (run.workspace.owner.type === "review-round" && run.purpose !== "review") {
167
- throw new Error("A ReviewRound workspace requires a review Turn.");
225
+ throw new Error("A ReviewRound workspace requires a review AgentRun.");
168
226
  }
169
227
  if (run.workspace.owner.type === "integration-attempt") {
170
- throw new Error("An IntegrationAttempt workspace cannot be used by a Turn.");
228
+ throw new Error("An IntegrationAttempt workspace cannot be used by a AgentRun.");
171
229
  }
172
230
  if (run.workspace.owner.type === "execution-lane") {
173
231
  if (run.workspace.owner.executionGroupId !== run.executionGroupId
174
232
  || run.workspace.owner.executionLaneId !== run.executionLaneId) {
175
- throw new Error("Turn Execution Lane workspace lineage does not match the Turn.");
233
+ throw new Error("AgentRun Execution Lane workspace lineage does not match the AgentRun.");
176
234
  }
177
235
  if (run.workspace.owner.purpose === "execution"
178
236
  && run.workspace.owner.workItemId !== run.workItemId) {
179
- throw new Error("Turn Execution Lane workspace WorkItem does not match the Turn.");
237
+ throw new Error("AgentRun Execution Lane workspace WorkItem does not match the AgentRun.");
180
238
  }
181
239
  if (run.workspace.owner.purpose === "review"
182
240
  && run.workspace.owner.reviewRoundId !== run.reviewRoundId) {
183
- throw new Error("Turn review Lane workspace ReviewRound does not match the Turn.");
241
+ throw new Error("AgentRun review Lane workspace ReviewRound does not match the AgentRun.");
184
242
  }
185
243
  }
186
244
  if (run.workspace.owner.type === "review-round"
187
245
  && run.workspace.owner.reviewRoundId !== run.reviewRoundId) {
188
- throw new Error(`Turn ReviewRound workspace owner does not match ${run.reviewRoundId ?? "none"}.`);
246
+ throw new Error(`AgentRun ReviewRound workspace owner does not match ${run.reviewRoundId ?? "none"}.`);
189
247
  }
190
248
  }
191
249
  if (run.purpose === "review") {
192
250
  if (run.reviewRoundId === undefined) {
193
- throw new Error("A review Turn requires a ReviewRound reference.");
251
+ throw new Error("A review AgentRun requires a ReviewRound reference.");
194
252
  }
195
253
  if (run.workspace === undefined
196
254
  || !((run.workspace.owner.type === "review-round"
@@ -198,86 +256,86 @@ export function validateTurn(run) {
198
256
  || (run.workspace.owner.type === "execution-lane"
199
257
  && run.workspace.owner.purpose === "review"
200
258
  && run.workspace.owner.reviewRoundId === run.reviewRoundId))) {
201
- throw new Error(`A review Turn requires its exact ReviewRound workspace owner: ${run.reviewRoundId}.`);
259
+ throw new Error(`A review AgentRun requires its exact ReviewRound workspace owner: ${run.reviewRoundId}.`);
202
260
  }
203
261
  if (run.workspace.entries.length === 0
204
262
  || run.workspace.entries.some(({ access }) => access !== "write")) {
205
- throw new Error("A review Turn requires only isolated writable workspace entries.");
263
+ throw new Error("A review AgentRun requires only isolated writable workspace entries.");
206
264
  }
207
265
  }
208
266
  else {
209
267
  if (run.reviewRoundId !== undefined) {
210
- throw new Error("An execution Turn cannot reference a ReviewRound.");
268
+ throw new Error("An execution AgentRun cannot reference a ReviewRound.");
211
269
  }
212
270
  if (run.workspace?.owner.type === "review-round") {
213
- throw new Error("An execution Turn cannot use a ReviewRound-owned workspace.");
271
+ throw new Error("An execution AgentRun cannot use a ReviewRound-owned workspace.");
214
272
  }
215
273
  if (run.workspace?.owner.type === "execution-lane" && run.workspace.owner.purpose !== "execution") {
216
- throw new Error("An execution Turn cannot use a review Lane workspace.");
274
+ throw new Error("An execution AgentRun cannot use a review Lane workspace.");
217
275
  }
218
276
  }
219
277
  validateEffectiveLaunchSnapshot(run.effective);
220
278
  if (run.workspace !== undefined
221
279
  && (run.effective.workspace.root !== run.workspace.root
222
280
  || JSON.stringify(run.effective.workspace.entries) !== JSON.stringify(run.workspace.entries))) {
223
- throw new Error("Turn effective workspace does not match its managed workspace.");
281
+ throw new Error("AgentRun effective workspace does not match its managed workspace.");
224
282
  }
225
283
  if (run.purpose === "review") {
226
284
  if (run.effective.reviewRoundId !== run.reviewRoundId) {
227
- throw new Error("Review Turn effective provenance does not match its ReviewRound.");
285
+ throw new Error("Review AgentRun effective provenance does not match its ReviewRound.");
228
286
  }
229
287
  if (!run.workspace.entries.some(({ baseCommit }) => baseCommit === run.effective.reviewBaseCommit)) {
230
- throw new Error("Review Turn effective base does not match its workspace.");
288
+ throw new Error("Review AgentRun effective base does not match its workspace.");
231
289
  }
232
290
  }
233
291
  else if (run.effective.reviewRoundId !== undefined) {
234
- throw new Error("Execution Turn cannot carry Review effective provenance.");
292
+ throw new Error("Execution AgentRun cannot carry Review effective provenance.");
235
293
  }
236
294
  for (const record of run.inputs) {
237
- createTurnInputEnvelope(turnEnvelopeContext(run), record.input);
295
+ createRunInputEnvelope(runEnvelopeContext(run), record.input);
238
296
  }
239
297
  if (!["active", "completed", "failed"].includes(run.status)) {
240
- throw new Error(`Turn status is invalid: ${String(run.status)}.`);
298
+ throw new Error(`AgentRun status is invalid: ${String(run.status)}.`);
241
299
  }
242
- requireTimestamp(run.createdAt, "Turn createdAt");
243
- requireTimestamp(run.updatedAt, "Turn updatedAt");
300
+ requireTimestamp(run.createdAt, "AgentRun createdAt");
301
+ requireTimestamp(run.updatedAt, "AgentRun updatedAt");
244
302
  if (run.status === "active") {
245
303
  if (run.result !== undefined)
246
- throw new Error("An active Turn cannot have a result.");
304
+ throw new Error("An active AgentRun cannot have a result.");
247
305
  }
248
306
  else {
249
- const result = validateTurnResult(run.result);
307
+ const result = validateRunResult(run.result);
250
308
  if (run.status === "failed") {
251
- if (!isTurnFailureReason(result.failureReason)) {
252
- throw new Error(`Failed Turn reason is invalid: ${String(result.failureReason)}.`);
309
+ if (!isRunFailureReason(result.failureReason)) {
310
+ throw new Error(`Failed AgentRun reason is invalid: ${String(result.failureReason)}.`);
253
311
  }
254
312
  if (result.diagnostic === undefined) {
255
- throw new Error("A failed Turn requires a Core diagnostic.");
313
+ throw new Error("A failed AgentRun requires a Core diagnostic.");
256
314
  }
257
315
  if (result.systemEvidence !== undefined) {
258
- throw new Error("A failed Turn cannot carry successful system evidence.");
316
+ throw new Error("A failed AgentRun cannot carry successful system evidence.");
259
317
  }
260
318
  }
261
319
  else {
262
320
  if (result.output === undefined) {
263
- throw new Error("A completed Turn requires an Agent result.");
321
+ throw new Error("A completed AgentRun requires an Agent result.");
264
322
  }
265
323
  if (result.failureReason !== undefined || result.diagnostic !== undefined) {
266
- throw new Error("A completed Turn cannot carry failure metadata.");
324
+ throw new Error("A completed AgentRun cannot carry failure metadata.");
267
325
  }
268
326
  }
269
327
  }
270
328
  return run;
271
329
  }
272
- export function completeTurn(run, output, now, provider, systemEvidence) {
273
- return finishTurn(run, "completed", output, now, undefined, provider, systemEvidence);
330
+ export function completeRun(run, output, now, provider, systemEvidence) {
331
+ return finishRun(run, "completed", output, now, undefined, provider, systemEvidence);
274
332
  }
275
- export function failTurn(run, reason, diagnostic, now, provider, output) {
276
- return finishTurn(run, "failed", output, now, reason, provider, undefined, boundedTurnFailureDiagnostic(diagnostic));
333
+ export function failRun(run, reason, diagnostic, now, provider, output) {
334
+ return finishRun(run, "failed", output, now, reason, provider, undefined, boundedRunFailureDiagnostic(diagnostic));
277
335
  }
278
- function finishTurn(run, status, output, now, failureReason, provider, systemEvidence, diagnostic) {
336
+ function finishRun(run, status, output, now, failureReason, provider, systemEvidence, diagnostic) {
279
337
  if (run.status !== "active") {
280
- throw new Error(`Turn is already terminal: ${run.id}.`);
338
+ throw new Error(`AgentRun is already terminal: ${run.id}.`);
281
339
  }
282
340
  const timestamp = now.toISOString();
283
341
  const terminal = {
@@ -285,24 +343,24 @@ function finishTurn(run, status, output, now, failureReason, provider, systemEvi
285
343
  status,
286
344
  result: {
287
345
  schemaVersion: 2,
288
- ...(output === undefined ? {} : { output: requireResultText(output, "Turn result output") }),
346
+ ...(output === undefined ? {} : { output: requireResultText(output, "AgentRun result output") }),
289
347
  ...(diagnostic === undefined
290
348
  ? {}
291
- : { diagnostic: requireDiagnosticText(diagnostic, "Turn result diagnostic") }),
349
+ : { diagnostic: requireDiagnosticText(diagnostic, "AgentRun result diagnostic") }),
292
350
  completedAt: timestamp,
293
- ...(provider === undefined ? {} : { provider: validateTurnProviderResult(provider) }),
351
+ ...(provider === undefined ? {} : { provider: validateRunProviderResult(provider) }),
294
352
  ...(systemEvidence === undefined
295
353
  ? {}
296
- : { systemEvidence: validateTurnSystemEvidence(systemEvidence) }),
354
+ : { systemEvidence: validateRunSystemEvidence(systemEvidence) }),
297
355
  ...(failureReason === undefined ? {} : { failureReason })
298
356
  },
299
357
  updatedAt: timestamp,
300
358
  };
301
- return validateTurn(terminal);
359
+ return validateRun(terminal);
302
360
  }
303
- function validateTurnResult(result) {
361
+ function validateRunResult(result) {
304
362
  if (result === undefined || result.schemaVersion !== 2) {
305
- throw new Error("A terminal Turn requires TurnResult schemaVersion 2.");
363
+ throw new Error("A terminal AgentRun requires AgentRunResult schemaVersion 2.");
306
364
  }
307
365
  rejectUnknownFields(result, [
308
366
  "schemaVersion",
@@ -312,48 +370,47 @@ function validateTurnResult(result) {
312
370
  "provider",
313
371
  "systemEvidence",
314
372
  "failureReason"
315
- ], "Turn result");
373
+ ], "AgentRun result");
316
374
  if (result.output !== undefined)
317
- requireResultText(result.output, "Turn result output");
375
+ requireResultText(result.output, "AgentRun result output");
318
376
  if (result.diagnostic !== undefined) {
319
- requireDiagnosticText(result.diagnostic, "Turn result diagnostic");
377
+ requireDiagnosticText(result.diagnostic, "AgentRun result diagnostic");
320
378
  }
321
- requireTimestamp(result.completedAt, "Turn result completedAt");
379
+ requireTimestamp(result.completedAt, "AgentRun result completedAt");
322
380
  if (result.provider !== undefined)
323
- validateTurnProviderResult(result.provider);
381
+ validateRunProviderResult(result.provider);
324
382
  if (result.systemEvidence !== undefined)
325
- validateTurnSystemEvidence(result.systemEvidence);
383
+ validateRunSystemEvidence(result.systemEvidence);
326
384
  return result;
327
385
  }
328
- function validateTurnSystemEvidence(evidence) {
386
+ function validateRunSystemEvidence(evidence) {
329
387
  rejectUnknownFields(evidence, [
330
388
  "workspaceSnapshot"
331
- ], "Turn system evidence");
389
+ ], "AgentRun system evidence");
332
390
  if (evidence.workspaceSnapshot !== undefined) {
333
391
  const snapshot = evidence.workspaceSnapshot;
334
392
  if (snapshot.schemaVersion !== 1 || !Array.isArray(snapshot.projects)) {
335
- throw new Error("Turn workspace snapshot is invalid.");
393
+ throw new Error("AgentRun workspace snapshot is invalid.");
336
394
  }
337
395
  const projectIds = new Set();
338
396
  for (const project of snapshot.projects) {
339
- requireSafeIdentity(project.projectId, "Turn workspace snapshot Project id");
397
+ requireSafeIdentity(project.projectId, "AgentRun workspace snapshot Project id");
340
398
  if (projectIds.has(project.projectId)) {
341
- throw new Error("Turn workspace snapshot Project ids must be unique.");
399
+ throw new Error("AgentRun workspace snapshot Project ids must be unique.");
342
400
  }
343
401
  projectIds.add(project.projectId);
344
402
  if (!/^[0-9a-f]{40}$/u.test(project.headCommit)) {
345
- throw new Error("Turn workspace snapshot commit is invalid.");
403
+ throw new Error("AgentRun workspace snapshot commit is invalid.");
346
404
  }
347
- requireText(project.branch, "Turn workspace snapshot branch");
405
+ requireText(project.branch, "AgentRun workspace snapshot branch");
348
406
  }
349
407
  }
350
408
  return evidence;
351
409
  }
352
- function validateTurnProviderResult(provider) {
410
+ function validateRunProviderResult(provider) {
353
411
  requireText(provider.providerNamespace, "Provider namespace");
354
412
  requireText(provider.accountScope, "Provider account scope");
355
413
  requireText(provider.conversationId, "Provider Conversation id");
356
- requireText(provider.activationId, "Provider Activation id");
357
414
  if (provider.nativeTurnId !== undefined)
358
415
  requireText(provider.nativeTurnId, "Provider native Turn id");
359
416
  if (provider.attemptId !== undefined)
@@ -362,21 +419,21 @@ function validateTurnProviderResult(provider) {
362
419
  throw new Error("Provider result requires a native Turn or exact attempt identity.");
363
420
  }
364
421
  if (!["completed", "failed", "cancelled"].includes(provider.status)) {
365
- throw new Error(`Provider Turn result status is invalid: ${String(provider.status)}.`);
422
+ throw new Error(`Provider AgentRun result status is invalid: ${String(provider.status)}.`);
366
423
  }
367
424
  return provider;
368
425
  }
369
- function turnInputRecord(input, sequence, submittedAt) {
370
- const normalized = validateTurnInput(input);
426
+ function runInputRecord(input, sequence, submittedAt) {
427
+ const normalized = validateRunInput(input);
371
428
  return Object.freeze({
372
429
  sequence,
373
430
  submittedAt,
374
431
  input: normalized
375
432
  });
376
433
  }
377
- function turnEnvelopeContext(run) {
434
+ function runEnvelopeContext(run) {
378
435
  return {
379
- turnId: run.id,
436
+ runId: run.id,
380
437
  roleName: run.roleName,
381
438
  purpose: run.purpose,
382
439
  subject: {
@@ -415,8 +472,8 @@ function requireResultText(value, label) {
415
472
  throw new Error(`${label} is invalid.`);
416
473
  if (value.trim().length === 0)
417
474
  throw new Error(`${label} is required.`);
418
- if (Buffer.byteLength(value, "utf8") > MAX_TURN_RESULT_OUTPUT_BYTES) {
419
- throw new Error(`${label} exceeds ${MAX_TURN_RESULT_OUTPUT_BYTES} bytes.`);
475
+ if (Buffer.byteLength(value, "utf8") > MAX_RUN_RESULT_OUTPUT_BYTES) {
476
+ throw new Error(`${label} exceeds ${MAX_RUN_RESULT_OUTPUT_BYTES} bytes.`);
420
477
  }
421
478
  return value;
422
479
  }
@@ -425,8 +482,8 @@ function requireDiagnosticText(value, label) {
425
482
  throw new Error(`${label} is invalid.`);
426
483
  if (value.trim().length === 0)
427
484
  throw new Error(`${label} is required.`);
428
- if (Buffer.byteLength(value, "utf8") > MAX_TURN_FAILURE_DIAGNOSTIC_BYTES) {
429
- throw new Error(`${label} exceeds ${MAX_TURN_FAILURE_DIAGNOSTIC_BYTES} bytes.`);
485
+ if (Buffer.byteLength(value, "utf8") > MAX_RUN_FAILURE_DIAGNOSTIC_BYTES) {
486
+ throw new Error(`${label} exceeds ${MAX_RUN_FAILURE_DIAGNOSTIC_BYTES} bytes.`);
430
487
  }
431
488
  return value;
432
489
  }
@@ -435,7 +492,7 @@ function requireTimestamp(value, label) {
435
492
  throw new Error(`${label} must be an ISO timestamp.`);
436
493
  }
437
494
  }
438
- function isTurnFailureReason(value) {
495
+ function isRunFailureReason(value) {
439
496
  return [
440
497
  "startup-failed",
441
498
  "runtime-failed",
@@ -1,22 +1,22 @@
1
1
  import { MAX_SESSION_TITLE_LENGTH } from "../runtime/sessionTitle.js";
2
2
  /**
3
3
  * Prefixes managed launch input with its session title. The bootstrap body
4
- * exposes the exact current Turn identity to the Agent, while structured
4
+ * exposes the exact current AgentRun identity to the Agent, while structured
5
5
  * delivery metadata and control hooks retain the delivery fence.
6
6
  */
7
7
  export function prefixYuiTitleInput(input, title) {
8
8
  const text = input.replace(/\r/g, "").trim();
9
9
  if (text.length === 0)
10
10
  throw new Error("Managed input body is required.");
11
- return `${requireTurnTitle(title)}\n\n${text}`;
11
+ return `${requireRunTitle(title)}\n\n${text}`;
12
12
  }
13
- function requireTurnTitle(value) {
13
+ function requireRunTitle(value) {
14
14
  const title = value.trim();
15
15
  if (title.length === 0
16
16
  || title.length > MAX_SESSION_TITLE_LENGTH
17
17
  || /[\r\n\0]/u.test(title)
18
18
  || !title.startsWith("Yui ")) {
19
- throw new Error("Turn title is invalid.");
19
+ throw new Error("AgentRun title is invalid.");
20
20
  }
21
21
  return title;
22
22
  }
@@ -11,6 +11,7 @@ export function createTaskBrief(input, now) {
11
11
  };
12
12
  }
13
13
  export function updateTaskBrief(brief, patch, updatedBy, now) {
14
+ validateTaskBrief(brief);
14
15
  return createTaskBrief({
15
16
  objective: patch.objective ?? brief.objective,
16
17
  boundaries: patch.boundaries ?? brief.boundaries,
@@ -20,6 +21,17 @@ export function updateTaskBrief(brief, patch, updatedBy, now) {
20
21
  updatedBy
21
22
  }, now);
22
23
  }
24
+ export function validateTaskBrief(brief) {
25
+ if (brief.schemaVersion !== 2) {
26
+ throw new Error("Task Brief requires schemaVersion 2.");
27
+ }
28
+ if (!Array.isArray(brief.boundaries) || typeof brief.technicalApproach !== "string"
29
+ || typeof brief.updatedAt !== "string" || !Number.isFinite(Date.parse(brief.updatedAt))) {
30
+ throw new Error("Task Brief content or timestamp is invalid.");
31
+ }
32
+ createTaskBrief(brief, new Date(brief.updatedAt));
33
+ return brief;
34
+ }
23
35
  function normalizeBoundaries(values) {
24
36
  const normalized = values.map((value) => {
25
37
  if (typeof value !== "string" || value.includes("\0")) {
@@ -78,6 +78,19 @@ export async function selectAgentPermission(resolved, io, current) {
78
78
  const mode = await selectPermissionField(resolved, io, "permission.mode", claude?.mode, claude === undefined ? undefined : OMIT);
79
79
  if (mode.kind === "cancelled")
80
80
  return mode;
81
+ // ACP's configured permission is exactly the mode, and its adapter requires
82
+ // one: the value is matched against what the Agent enumerates at launch, so
83
+ // there is no "configured with nothing set" to fall back to. Claude's remains
84
+ // optional because its other native options can carry the configuration
85
+ // instead.
86
+ if (resolved.catalog.adapterId === "acp") {
87
+ return mode.value === undefined
88
+ ? { kind: "cancelled" }
89
+ : {
90
+ kind: "selected",
91
+ permission: { strategy: "configured", mode: mode.value }
92
+ };
93
+ }
81
94
  const permission = {
82
95
  ...(claude ?? { strategy: "configured" })
83
96
  };