@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
@@ -1,3 +1,4 @@
1
+ import { validateGitArtifactRef } from "../artifacts/gitArtifactRef.js";
1
2
  import { normalizedUniqueIdentities, normalizedUniqueText, requireIdentity, requireText, requireTimestamp } from "../domain/validation.js";
2
3
  import { validateReviewConfig } from "../review/reviewConfig.js";
3
4
  import { taskFinalReviewConfig, validateTaskFinalReviewContract } from "../review/taskFinalReviewContract.js";
@@ -5,8 +6,7 @@ import { validateManagedWorkspace } from "../worktree/managedWorkspace.js";
5
6
  import { validateTaskRecordReference } from "../task/taskRecordReference.js";
6
7
  import { assertWorkItemExecutionGroupTransition, validateWorkItemExecutionGroup as validateExecutionGroupRecord, workItemExecutionGroupSettled } from "../execution/workItemExecution.js";
7
8
  const TERMINAL_STATUSES = [
8
- "completed",
9
- "failed",
9
+ "accepted",
10
10
  "retired"
11
11
  ];
12
12
  export function createWorkItem(id, taskId, input, now) {
@@ -31,21 +31,18 @@ export function createWorkItem(id, taskId, input, now) {
31
31
  ...(input.assignee === undefined
32
32
  ? {}
33
33
  : { assignee: requireIdentity(input.assignee, "Work item assignee") }),
34
- status: "pending",
34
+ status: "open",
35
35
  candidates: [],
36
36
  createdAt: timestamp,
37
37
  updatedAt: timestamp
38
38
  });
39
39
  }
40
- /** Replace the mutable definition of an execution-free Draft WorkItem. */
41
- export function editDraftWorkItemDefinition(workItem, update, now) {
40
+ /** Edit current open-work requirements; frozen Assignments are separate records.
41
+ * The command boundary owns Task authority and workspace/assignee constraints. */
42
+ export function editWorkItemDefinition(workItem, update, now) {
42
43
  validateWorkItem(workItem);
43
- if (workItem.status !== "pending"
44
- || workItem.executionGroups.length > 0
45
- || workItem.candidates.length > 0
46
- || workItem.disposition !== undefined
47
- || workItem.workspaceDisposition !== undefined) {
48
- throw new Error(`Work Item has execution or retirement facts: ${workItem.id}.`);
44
+ if (workItem.status !== "open") {
45
+ throw new Error(`Only open Work Item definitions may change: ${workItem.id} (${workItem.status}).`);
49
46
  }
50
47
  const next = {
51
48
  ...workItem,
@@ -87,7 +84,7 @@ export function editDraftWorkItemDefinition(workItem, update, now) {
87
84
  }
88
85
  export function submitWorkItemCandidate(workItem, input, now) {
89
86
  validateWorkItem(workItem);
90
- if (workItem.status !== "running") {
87
+ if (workItem.status !== "open") {
91
88
  throw new Error(`Work Item candidate can only be submitted from running: ${workItem.id}/${workItem.status}.`);
92
89
  }
93
90
  const revision = workItem.revision + 1;
@@ -116,26 +113,28 @@ export function submitWorkItemCandidate(workItem, input, now) {
116
113
  ...(input.taskMainSnapshot === undefined
117
114
  ? {}
118
115
  : { taskMainSnapshot: input.taskMainSnapshot }),
116
+ ...(input.artifactRefs === undefined ? {} : { artifactRefs: input.artifactRefs.map((ref) => validateGitArtifactRef(ref)) }),
119
117
  createdAt: now.toISOString()
120
118
  });
121
119
  const { outcome: _outcome, endedAt: _endedAt, ...base } = workItem;
122
120
  return validateWorkItem({
123
121
  ...base,
124
- status: "awaiting_acceptance",
122
+ status: "open",
125
123
  candidates: [...workItem.candidates, candidate],
124
+ currentCandidateId: candidate.id,
126
125
  revision,
127
126
  updatedAt: now.toISOString()
128
127
  });
129
128
  }
130
- export function updateWorkItemStatus(workItem, status, now, outcome) {
129
+ export function updateWorkItemStatus(workItem, status, now, outcome, candidateId) {
131
130
  validateWorkItem(workItem);
132
131
  validateStatus(status);
133
132
  const alreadyTerminal = isTerminalStatus(workItem.status);
134
133
  if (workItem.disposition !== undefined && status !== workItem.status) {
135
134
  throw new Error(`Retired Work Item status cannot change: ${workItem.id}.`);
136
135
  }
137
- const closingFailedWork = workItem.status === "failed" && status === "retired";
138
- if (alreadyTerminal && status !== workItem.status && !closingFailedWork) {
136
+ const withdrawingAcceptance = workItem.status === "accepted" && status === "open";
137
+ if (alreadyTerminal && status !== workItem.status && !withdrawingAcceptance) {
139
138
  throw new Error(`Terminal Work Item status cannot change: ${workItem.id}.`);
140
139
  }
141
140
  const terminal = isTerminalStatus(status);
@@ -154,16 +153,19 @@ export function updateWorkItemStatus(workItem, status, now, outcome) {
154
153
  updatedAt: timestamp
155
154
  });
156
155
  }
157
- const { endedAt: _endedAt, outcome: _outcome, workspaceDisposition, ...base } = workItem;
156
+ const { endedAt: _endedAt, outcome: _outcome, workspaceDisposition, acceptedCandidateId, currentCandidateId, ...base } = workItem;
158
157
  return validateWorkItem({
159
158
  ...base,
160
159
  status,
161
160
  revision: workItem.revision + 1,
162
161
  ...(normalizedOutcome === undefined ? {} : { outcome: normalizedOutcome }),
163
162
  // Isolated workspace cleanup remains durable evidence after retirement.
164
- ...(closingFailedWork && workspaceDisposition !== undefined
163
+ ...(workspaceDisposition !== undefined
165
164
  ? { workspaceDisposition }
166
165
  : {}),
166
+ ...(status === "accepted" && (candidateId ?? acceptedCandidateId ?? currentCandidateId) !== undefined
167
+ ? { acceptedCandidateId: candidateId ?? acceptedCandidateId ?? currentCandidateId } : {}),
168
+ ...(status === "open" && !withdrawingAcceptance && currentCandidateId !== undefined ? { currentCandidateId } : {}),
167
169
  updatedAt: timestamp,
168
170
  ...(terminal ? { endedAt: timestamp } : {})
169
171
  });
@@ -172,7 +174,7 @@ export function updateWorkItemStatus(workItem, status, now, outcome) {
172
174
  export function attachWorkItemExecutionGroup(workItem, executionGroup, now) {
173
175
  validateWorkItem(workItem);
174
176
  const checked = validateWorkItemExecutionGroup(executionGroup, workItem.taskId, workItem.id);
175
- if (workItem.status === "completed" || workItem.status === "failed" || workItem.status === "retired") {
177
+ if (workItem.status !== "open") {
176
178
  throw new Error(`A terminal Work Item cannot attach an ExecutionGroup: ${workItem.id}.`);
177
179
  }
178
180
  const existing = workItemExecutionGroupById(workItem, checked.id);
@@ -235,11 +237,10 @@ export function retireWorkItem(workItem, input, now) {
235
237
  }
236
238
  throw new Error(`Work Item already has an explicit disposition: ${workItem.id}.`);
237
239
  }
238
- if (workItem.status === "completed") {
240
+ if (workItem.status === "accepted") {
239
241
  throw new Error(`Completed Work Item cannot be retired: ${workItem.id}.`);
240
242
  }
241
243
  if (isTerminalStatus(workItem.status)
242
- && workItem.status !== "failed"
243
244
  && workItem.status !== "retired") {
244
245
  throw new Error(`Terminal Work Item status cannot change: ${workItem.id}.`);
245
246
  }
@@ -254,15 +255,15 @@ export function retireWorkItem(workItem, input, now) {
254
255
  endedAt: timestamp
255
256
  });
256
257
  }
257
- export function retryFailedWorkItem(workItem, now) {
258
+ export function prepareWorkItemDispatch(workItem, now) {
258
259
  validateWorkItem(workItem);
259
- if (workItem.status !== "failed") {
260
+ if (workItem.status !== "open") {
260
261
  throw new Error(`Work item is not retryable from ${workItem.status}: ${workItem.id}.`);
261
262
  }
262
263
  if (workItem.workspaceDisposition !== undefined) {
263
264
  throw new Error(`Work item workspace is already settled: ${workItem.id}.`);
264
265
  }
265
- const { outcome: _outcome, endedAt: _endedAt, ...base } = workItem;
266
+ const { outcome: _outcome, endedAt: _endedAt, currentCandidateId: _candidate, ...base } = workItem;
266
267
  // Keep every historical Group. A settled current Group is cleared only as
267
268
  // the current pointer; redispatch appends a fresh immutable Group.
268
269
  const current = currentWorkItemExecutionGroup(workItem);
@@ -271,7 +272,7 @@ export function retryFailedWorkItem(workItem, now) {
271
272
  : (({ currentExecutionGroupId: _currentExecutionGroupId, ...history }) => history)(base);
272
273
  return validateWorkItem({
273
274
  ...retryBase,
274
- status: "running",
275
+ status: "open",
275
276
  revision: workItem.revision + 1,
276
277
  updatedAt: now.toISOString()
277
278
  });
@@ -316,7 +317,10 @@ export function validateWorkItem(workItem) {
316
317
  "workspaceDisposition",
317
318
  "createdAt",
318
319
  "updatedAt",
319
- "endedAt"
320
+ "endedAt",
321
+ "acceptedCandidateId",
322
+ "currentCandidateId",
323
+ "historicalState"
320
324
  ], "WorkItem");
321
325
  if (workItem.schemaVersion !== 15)
322
326
  throw new Error("WorkItem must use schemaVersion 15.");
@@ -381,9 +385,27 @@ export function validateWorkItem(workItem) {
381
385
  throw new Error("Work Item candidate revision cannot exceed the Work Item revision.");
382
386
  }
383
387
  });
384
- const currentCandidate = currentWorkItemCandidate(workItem);
385
- if (workItem.status === "awaiting_acceptance" && currentCandidate === undefined) {
386
- throw new Error("A Work Item awaiting acceptance requires a candidate.");
388
+ if (workItem.acceptedCandidateId !== undefined
389
+ && !candidateIds.has(workItem.acceptedCandidateId))
390
+ throw new Error("Accepted Candidate is missing.");
391
+ if (workItem.acceptedCandidateId !== undefined && workItem.status !== "accepted") {
392
+ throw new Error("Only an accepted Work Item may select an accepted Candidate.");
393
+ }
394
+ if (workItem.status === "accepted" && workItem.candidates.length > 0 && workItem.acceptedCandidateId === undefined) {
395
+ throw new Error("Accepted Work Item must identify its selected Candidate.");
396
+ }
397
+ if (workItem.currentCandidateId !== undefined
398
+ && !candidateIds.has(workItem.currentCandidateId))
399
+ throw new Error("Current Candidate is missing.");
400
+ if (workItem.historicalState !== undefined) {
401
+ const historical = workItem.historicalState;
402
+ if (!["pending", "running", "awaiting_acceptance", "completed", "failed", "retired"].includes(historical.status)) {
403
+ throw new Error("Historical Work Item status is invalid.");
404
+ }
405
+ if (historical.outcome !== undefined)
406
+ requireText(historical.outcome, "Historical outcome");
407
+ if (historical.endedAt !== undefined)
408
+ requireTimestamp(historical.endedAt, "Historical endedAt");
387
409
  }
388
410
  if (workItem.outcome !== undefined)
389
411
  requireText(workItem.outcome, "Work item outcome");
@@ -406,9 +428,6 @@ export function validateWorkItem(workItem) {
406
428
  if (!["integrated", "abandoned"].includes(workItem.workspaceDisposition)) {
407
429
  throw new Error("Work item workspaceDisposition is invalid.");
408
430
  }
409
- if (!terminal) {
410
- throw new Error("Only a terminal Work Item can record workspace cleanup.");
411
- }
412
431
  }
413
432
  if (workItem.disposition !== undefined) {
414
433
  validateDisposition(workItem.disposition);
@@ -433,7 +452,7 @@ export function workItemExecutionGroupById(workItem, executionGroupId) {
433
452
  return workItem.executionGroups.find(({ id }) => id === executionGroupId);
434
453
  }
435
454
  /**
436
- * True when a Turn failure belongs to the WorkItem's current unresolved Lane.
455
+ * True when a AgentRun failure belongs to the WorkItem's current unresolved Lane.
437
456
  * Such a failure is Lane-bounded: the WorkItem remains running so the Leader
438
457
  * can reuse completed siblings and retry only this failed attempt.
439
458
  */
@@ -445,7 +464,7 @@ export function workItemOwnsUnresolvedExecutionLane(workItem, executionGroupId,
445
464
  const group = workItem.executionGroups.find(({ id }) => id === executionGroupId);
446
465
  return group !== undefined
447
466
  && !workItemExecutionGroupSettled(group)
448
- && group.lanes.some(({ id, disposition, currentTurnId }) => (id === executionLaneId && disposition === "open" && currentTurnId !== undefined));
467
+ && group.lanes.some(({ id, disposition, currentRunId }) => (id === executionLaneId && disposition === "open" && currentRunId !== undefined));
449
468
  }
450
469
  function validateWorkItemExecutionGroup(group, taskId, workItemId) {
451
470
  validateExecutionGroupRecord(group);
@@ -481,17 +500,36 @@ export function validateWorkItemCandidate(candidate) {
481
500
  throw new Error("Work Item candidate revision must be a positive integer.");
482
501
  }
483
502
  requireText(candidate.summary, "Work Item candidate summary");
503
+ if (candidate.artifactRefs !== undefined) {
504
+ if (!Array.isArray(candidate.artifactRefs))
505
+ throw new Error("Candidate Artifact refs must be an array.");
506
+ const identities = new Set();
507
+ for (const ref of candidate.artifactRefs) {
508
+ // Pure, no-I/O shape check: the commit self-certifies the frozen bytes,
509
+ // so a valid pinned reference is complete evidence on its own. Existence
510
+ // is proven lazily when the bytes are resolved on the async read path.
511
+ const valid = validateGitArtifactRef(ref);
512
+ if (valid.taskId !== candidate.taskId) {
513
+ throw new Error("Candidate Artifact scope, commit or path is invalid.");
514
+ }
515
+ const identity = `${valid.commit}:${valid.relativePath}`;
516
+ if (identities.has(identity)) {
517
+ throw new Error("Candidate Artifact scope, commit or path is invalid.");
518
+ }
519
+ identities.add(identity);
520
+ }
521
+ }
484
522
  if (typeof candidate.source !== "object" || candidate.source === null) {
485
523
  throw new Error("Work Item candidate source is required.");
486
524
  }
487
- if (candidate.source.type !== "direct" && candidate.source.type !== "turn") {
525
+ if (candidate.source.type !== "direct" && candidate.source.type !== "run") {
488
526
  throw new Error("Work Item candidate source is invalid.");
489
527
  }
490
- if (candidate.source.type === "turn") {
528
+ if (candidate.source.type === "run") {
491
529
  validateTaskRecordReference({
492
530
  taskId: candidate.taskId,
493
- localId: candidate.source.turnId
494
- }, "turn");
531
+ localId: candidate.source.runId
532
+ }, "run");
495
533
  }
496
534
  if ((candidate.executionGroupId === undefined) !== (candidate.executionLaneId === undefined)) {
497
535
  throw new Error("Work Item candidate execution lineage is incomplete.");
@@ -647,8 +685,8 @@ function requireCommit(value, label) {
647
685
  return commit;
648
686
  }
649
687
  export function currentWorkItemCandidate(workItem) {
650
- return workItem.status === "awaiting_acceptance"
651
- ? workItem.candidates.at(-1)
688
+ return workItem.status === "open"
689
+ ? workItem.candidates.find(({ id }) => id === workItem.currentCandidateId)
652
690
  : undefined;
653
691
  }
654
692
  /**
@@ -659,9 +697,10 @@ export function currentWorkItemCandidate(workItem) {
659
697
  * Candidates on the same WorkItem are superseded by its latest Candidate.
660
698
  */
661
699
  export function governingWorkItemCandidate(workItem) {
662
- return workItem.status === "awaiting_acceptance" || workItem.status === "completed"
663
- ? workItem.candidates.at(-1)
664
- : undefined;
700
+ if (workItem.status === "accepted" && workItem.acceptedCandidateId !== undefined) {
701
+ return workItem.candidates.find(({ id }) => id === workItem.acceptedCandidateId);
702
+ }
703
+ return currentWorkItemCandidate(workItem);
665
704
  }
666
705
  export function updateWorkItemWriteProjects(workItem, writeProjectIds, now) {
667
706
  validateWorkItem(workItem);
@@ -690,11 +729,8 @@ function isTerminalStatus(status) {
690
729
  }
691
730
  function validateStatus(status) {
692
731
  if (![
693
- "pending",
694
- "running",
695
- "awaiting_acceptance",
696
- "completed",
697
- "failed",
732
+ "open",
733
+ "accepted",
698
734
  "retired"
699
735
  ].includes(status)) {
700
736
  throw new Error(`Work Item status is invalid: ${String(status)}.`);
@@ -8,9 +8,8 @@ import { governingWorkItemCandidate } from "../workItem/workItem.js";
8
8
  import { managedWorkspaceKey } from "../worktree/managedWorkspace.js";
9
9
  import { captureManagedGitChanges } from "./gitChangeSetCapture.js";
10
10
  const CAPTURABLE_WORK_ITEM_STATUSES = new Set([
11
- "awaiting_acceptance",
12
- "completed",
13
- "failed",
11
+ "open",
12
+ "accepted",
14
13
  "retired"
15
14
  ]);
16
15
  export class WorkItemChangeSetManager {
@@ -44,10 +43,15 @@ export class WorkItemChangeSetManager {
44
43
  }
45
44
  return captured;
46
45
  }
47
- async assertIntegrated(taskId, workItemId) {
46
+ async assertIntegrated(taskId, workItemId, candidateId) {
48
47
  const item = this.store.getWorkItem(taskId, workItemId);
49
48
  if (item === null)
50
49
  throw new Error(`Work item not found: ${taskId}/${workItemId}.`);
50
+ const candidate = candidateId === undefined ? governingWorkItemCandidate(item)
51
+ : item.candidates.find(({ id }) => id === candidateId);
52
+ if (candidateId !== undefined && candidate === undefined) {
53
+ throw new Error(`Candidate not found: ${taskId}/${workItemId}/${candidateId}.`);
54
+ }
51
55
  const workspace = this.store.getWorkItemWorkspace(item.taskId, item.id);
52
56
  if (workspace === null
53
57
  || workspace.owner.type !== "work-item"
@@ -59,14 +63,17 @@ export class WorkItemChangeSetManager {
59
63
  if (!await git.isClean(entry.path)) {
60
64
  throw new Error(`WorkItem Project workspace is not clean: ${item.id}/${entry.projectId}.`);
61
65
  }
62
- const headCommit = (await git.inspect(entry.path, "HEAD")).baseCommit;
63
- const candidate = governingWorkItemCandidate(item);
66
+ const workspaceHeadCommit = (await git.inspect(entry.path, "HEAD")).baseCommit;
64
67
  const resultCommit = candidate?.gitSnapshot?.projects.find(({ projectId }) => projectId === entry.projectId)?.commit;
65
68
  if (candidate?.workspace === undefined
66
69
  || !isDeepStrictEqual(candidate.workspace, workspace)
67
- || resultCommit !== headCommit) {
70
+ || resultCommit === undefined
71
+ || (candidateId === undefined && resultCommit !== workspaceHeadCommit)) {
68
72
  throw new Error(`WorkItem Project no longer matches its frozen result: ${item.id}/${entry.projectId}.`);
69
73
  }
74
+ // An explicit historical selection is proved against its immutable
75
+ // integrated commit, not mislabeled as the workspace's current HEAD.
76
+ const headCommit = resultCommit;
70
77
  const integrated = this.store.listIntegrationAttempts(item.taskId).some((integration) => (integration.status === "committed"
71
78
  && integration.projectId === entry.projectId
72
79
  && integration.source.kind === "work-item"
@@ -282,7 +289,7 @@ function requireCapturableContext(store, taskId, workItemId, taskFinalReviewCont
282
289
  if (taskFinalReviewContract === undefined) {
283
290
  throw new Error(`Work item has no managed workspace: ${item.id}.`);
284
291
  }
285
- const candidate = item.candidates.at(-1);
292
+ const candidate = governingWorkItemCandidate(item);
286
293
  if (candidate === undefined
287
294
  || !sameTaskFinalReviewContract(candidate.taskFinalReviewContract, taskFinalReviewContract)) {
288
295
  throw new Error(`Work item has no matching exact Task-final direct Candidate: ${item.id}.`);
@@ -346,7 +353,7 @@ function assertCaptureStillCurrent(store, expected) {
346
353
  const workspace = expected.source === "task-main"
347
354
  ? store.getTaskWorkspace(expected.taskId)
348
355
  : store.getWorkItemWorkspace(expected.taskId, expected.workItemId);
349
- const candidate = item?.candidates.at(-1);
356
+ const candidate = item === null ? undefined : governingWorkItemCandidate(item);
350
357
  if (task?.status !== "active"
351
358
  || item === null
352
359
  || item.revision !== expected.expectedRevision
@@ -0,0 +1,96 @@
1
+ <p align="right"><strong>English</strong> | <a href="./agent-result-consumption.zh-CN.md">简体中文</a></p>
2
+
3
+ # Agent result consumption
4
+
5
+ Every explicitly dispatched AgentRun produces one durable original result.
6
+ Ordinary notification and native conversation do not implicitly create Runs.
7
+ The next Agent in the ownership chain reads the exact result and decides what
8
+ it means.
9
+
10
+ ## One original result
11
+
12
+ `AgentRunResult.output` is the Agent-authored report. Core preserves its bytes
13
+ and does not parse, classify or validate semantic content. Markdown, JSON and
14
+ ordinary prose are all legal; omitted headings or an unconvincing conclusion are
15
+ quality evidence, not a runtime failure.
16
+
17
+ Core separately records Provider identity/status, completion time, diagnostics,
18
+ failure reasons and system-owned workspace evidence. Non-empty output must fit
19
+ the current transport limit and contain no NUL. Missing or untransportable text
20
+ fails the Run without fabricated prose. An arrived report can remain on a failed
21
+ Run when a later Core-owned boundary fails.
22
+
23
+ One reference Message is saved with the terminal result.
24
+ `task message show <task/message>` and Context inspect expand the same
25
+ `resultRef`. ReviewRound does not hold a second report. Files and durable
26
+ business outputs belong to Artifacts or managed Git results.
27
+
28
+ ## Execution is not acceptance
29
+
30
+ Run lifecycle is `active / completed / failed`. Provider outcome, input
31
+ acceptance and resource quiescence are separate facts. A completed Run means
32
+ its required Core execution boundaries succeeded, not that its answer is
33
+ correct or the WorkItem accepted.
34
+
35
+ Writable replicated Lanes require their exact Core-owned workspace evidence.
36
+ A wrong branch, dirty snapshot, mismatched owner or scope fails that boundary
37
+ without replacing an already arrived original report.
38
+
39
+ Only the Leader decides whether evidence warrants acceptance, further work,
40
+ another review or abandonment. Core never derives findings, votes or repair
41
+ topology from Agent text.
42
+
43
+ ## Direct and replicated execution
44
+
45
+ Direct WorkItem execution uses one main Run and no ExecutionGroup. Direct
46
+ Review likewise uses one main Reviewer Run.
47
+
48
+ Replicated execution uses distinct Producer Lanes over one frozen Assignment.
49
+ Each Producer retains its own original result and exact lineage. Leader
50
+ explicitly supplies distinct terminal source Run references to synthesis.
51
+ Sources must belong to the exact Group/Lane and have a result; they may be
52
+ completed or failed. There is no automatic synthesis, vote, minimum successful
53
+ Producer count or requirement to wait for all Lanes before choosing sources.
54
+
55
+ The synthesis snapshot retains the selected source order and bounded views of
56
+ their original outputs, diagnostics and provenance. It does not copy complete
57
+ transcripts. Only the main synthesis result can supply the WorkItem Candidate
58
+ or authoritative replicated Review result. Producers never enter Integration
59
+ or acceptance directly. Retry targets the failed exact execution; it does not
60
+ silently rerun successful Producers.
61
+
62
+ ## Review
63
+
64
+ ReviewRound owns frozen Candidate or Task-head identity, workspace provenance,
65
+ execution topology, exact main Reviewer Run, lifecycle and Core diagnostics.
66
+ Its completed state is structural execution evidence, not a “pass” extracted
67
+ from the report.
68
+
69
+ Candidate review follows its captured review rule. Task-final review can be
70
+ explicitly requested or required by the immutable final-review contract. A
71
+ requested review is evidence, not an automatic new policy requiring review
72
+ after every subsequent change. When current delivery requires a review, it
73
+ must cover the exact governing candidate or heads and completed main Run.
74
+
75
+ The Reviewer should inspect the complete bounded scope and report material
76
+ findings together. The Leader reads the full report, routes findings to the
77
+ original owner, fixes small Task-main issues directly, and creates a new
78
+ WorkItem only for substantial independent work.
79
+
80
+ ## Leader consumption
81
+
82
+ Wake windows point to result-bearing events, including a Run created before
83
+ the window but completed inside it. Read the exact source:
84
+
85
+ ```sh
86
+ yui task wake show <task> <wake>
87
+ yui task run show <task/run>
88
+ yui task message show <task/message>
89
+ ```
90
+
91
+ An optional report layout is outcome, changes/findings, verification, uncertainty
92
+ and next action. It is communication guidance, not a machine protocol.
93
+
94
+ Acceptance and Task completion remain explicit operations with current Git,
95
+ review, scope and resource checks. See [Session and AgentRun](managed-turn-and-session-runtime.md)
96
+ and [Task dependencies](task-dag-semantics.md).
@@ -0,0 +1,81 @@
1
+ <p align="right"><a href="./agent-result-consumption.md">English</a> | <strong>简体中文</strong></p>
2
+
3
+ # Agent 结果消费
4
+
5
+ 每一次显式派发的 AgentRun 都产生一个持久的原始结果。普通通知和原生对话不会
6
+ 隐式创建 Run。所有权链上的下一个 Agent 读取这个精确结果并判断它意味着什么。
7
+
8
+ ## 唯一的原始结果
9
+
10
+ `AgentRunResult.output` 是 Agent 撰写的报告。Core 保留其字节,不解析、不分类、
11
+ 也不校验语义内容。Markdown、JSON 和普通散文都是合法的;缺少标题或结论不够有力
12
+ 都是质量证据,而不是运行时失败。
13
+
14
+ Core 另外记录 Provider 身份/状态、完成时间、诊断、失败原因和系统拥有的工作区
15
+ 证据。非空输出必须符合当前传输上限且不含 NUL。缺失或不可传输的文本会让 Run
16
+ 失败,而不编造散文。当之后某个 Core 拥有的边界失败时,一份已到达的报告仍可以
17
+ 留在一个 failed 的 Run 上。
18
+
19
+ 终态结果会附带保存一条引用 Message。`task message show <task/message>` 和
20
+ Context inspect 展开同一个 `resultRef`。ReviewRound 不持有第二份报告。文件和
21
+ 持久业务产物归 Artifact 或受管 Git 结果。
22
+
23
+ ## 执行不等于验收
24
+
25
+ Run 生命周期是 `active / completed / failed`。Provider 结果、输入接受和资源静止
26
+ 是彼此独立的事实。Run completed 只表示它所需的 Core 执行边界成功,而不表示答案
27
+ 正确或 WorkItem 已验收。
28
+
29
+ 可写的 replicated Lane 需要其精确的、Core 拥有的工作区证据。分支错误、快照脏、
30
+ owner 不符或范围不符都会让该边界失败,但不会替换一份已到达的原始报告。
31
+
32
+ 只有 Leader 决定证据是否足以验收、继续工作、再审查或放弃。Core 从不从 Agent
33
+ 文本中推导 findings、投票或修复拓扑。
34
+
35
+ ## 直接执行与复制执行
36
+
37
+ 直接的 WorkItem 执行使用一个 main Run,没有 ExecutionGroup。直接 Review 同样
38
+ 使用一个 main Reviewer Run。
39
+
40
+ 复制执行在一个冻结 Assignment 上使用彼此不同的 Producer Lane。每个 Producer
41
+ 保留自己的原始结果和精确血缘。Leader 显式地把彼此不同的终态来源 Run 引用交给
42
+ 综合。来源必须属于确切的 Group/Lane 且有结果,可以是 completed 或 failed。不存在
43
+ 自动综合、投票、最少成功 Producer 数,也不要求在选择来源前等待所有 Lane。
44
+
45
+ 综合快照保留所选来源顺序,以及它们原始输出、诊断和来源的有界视图,不复制完整
46
+ transcript。只有 main 综合结果能提供 WorkItem Candidate 或权威的 replicated
47
+ Review 结果。Producer 从不直接进入 Integration 或验收。重试针对失败的那次精确
48
+ 执行,不会静默重跑已成功的 Producer。
49
+
50
+ ## Review
51
+
52
+ ReviewRound 拥有冻结的 Candidate 或 Task-head 身份、工作区来源、执行拓扑、精确
53
+ 的 main Reviewer Run、生命周期和 Core 诊断。它的 completed 状态是结构性执行证据,
54
+ 而不是从报告里提取出来的“通过”。
55
+
56
+ Candidate 审查遵循其捕获的审查规则。Task-final 审查可以被显式请求,或由不可变的
57
+ final-review 合同要求。一次被请求的审查是证据,而不是要求此后每次改动都审查的
58
+ 自动新策略。当前交付需要审查时,它必须覆盖确切的治理候选或 head 以及 completed
59
+ 的 main Run。
60
+
61
+ Reviewer 应检查完整的有界范围,并把重要 findings 一并报告。Leader 读取完整报告,
62
+ 把 findings 路由给原 owner,直接修复 Task-main 上的小问题,只为有独立价值的实质
63
+ 工作创建新的 WorkItem。
64
+
65
+ ## Leader 消费
66
+
67
+ 唤醒窗口指向带结果的事件,包括在窗口之前创建、但在窗口之内完成的 Run。读取精确
68
+ 来源:
69
+
70
+ ```sh
71
+ yui task wake show <task> <wake>
72
+ yui task run show <task/run>
73
+ yui task message show <task/message>
74
+ ```
75
+
76
+ 一个可选的报告结构是:结果、改动/发现、验证、不确定性和下一步动作。它是沟通
77
+ 建议,不是机器协议。
78
+
79
+ 验收与 Task 完成仍是显式操作,并带有当前 Git、审查、范围和资源检查。参见
80
+ [执行与会话](managed-turn-and-session-runtime.zh-CN.md)和
81
+ [Task 依赖](task-dag-semantics.zh-CN.md)。
@@ -0,0 +1,93 @@
1
+ <p align="right"><strong>English</strong> | <a href="./agent-runtime-drivers.zh-CN.md">简体中文</a></p>
2
+
3
+ # Agent runtime Drivers
4
+
5
+ AgentEndpoint supplies the common execution boundary. Drivers translate native
6
+ events, errors and supported observation sources into `RuntimeObservation`;
7
+ Controller, Store, CLI and Web consume that shared contract.
8
+
9
+ ## Responsibilities
10
+
11
+ The connection implementation owns launch, protocol, prompt delivery, resume and
12
+ interrupt. Driver owns native identity extraction, observation capabilities,
13
+ event/error mapping and usage normalization. Core owns authority, exact request
14
+ correlation, durable folding and projections; Agents choose recovery and judge
15
+ semantic progress.
16
+
17
+ Built-in Driver identities are `openai/codex`, `anthropic/claude-code` and
18
+ `acp/agent-client-protocol`. ACP is a protocol Driver, not a product label.
19
+ Adding an ACP peer does not require another business-state model.
20
+
21
+ Capabilities must be stated truthfully. Unknown resume, cancellation, activity
22
+ or usage behavior cannot be inferred from a product name.
23
+
24
+ ## Observation path
25
+
26
+ Native structured facts pass the exact Session/request fence, enter the runtime
27
+ inbox, and fold into durable observations and original results. A separately
28
+ sampled usage source can feed the same canonical contract. Driver cannot choose
29
+ another actor, assign a successor Run, or bypass the fence.
30
+
31
+ Yui Run identity and Provider native Turn identity are not interchangeable.
32
+ An explicitly dispatched Run retains its accepted native correlation; direct
33
+ native chat is not another implicit Run. Replay is deduplicated by exact fact
34
+ identity, and late events cannot terminalize a successor.
35
+
36
+ Managed Codex uses App Server events. Claude maps its structured stream and
37
+ supported Hook/source payloads. ACP maps protocol Session updates and prompt
38
+ responses. Terminal text, trust dialogs and prompt glyphs are not lifecycle facts.
39
+
40
+ ## State and error evidence
41
+
42
+ Persistent Run lifecycle is `active / completed / failed`. Input disposition,
43
+ native waiting/activity, Goal, Session lifecycle and process presence answer
44
+ different questions. UI projections must not present a queued request as proof
45
+ that the Agent is busy, or a live process as acceptance.
46
+
47
+ Standard Agent errors preserve source, phase, category, code, input disposition,
48
+ Session disposition and the serialized native error. Categories include
49
+ availability, rate-limit, transport, access, invalid-request, context, session,
50
+ runtime, conflict, cancelled and unknown. A mapping reports evidence, not a
51
+ retry policy. Unrecognized errors stay unknown.
52
+
53
+ Runtime activity and workflow progress use separate evidence. A tool boundary
54
+ may show native activity; a durable accepted result shows semantic progress.
55
+ Tokens, CPU, RSS and pane presence cannot substitute for either acceptance or
56
+ Task completion.
57
+
58
+ ## Usage
59
+
60
+ Usage is read-only and scoped to the exact native Session. Input/output totals
61
+ are distinguished from cache/reasoning breakdowns, request context and remaining
62
+ capacity. Stable activity IDs deduplicate request snapshots; cumulative deltas
63
+ are used only with valid ordered same-Session evidence.
64
+
65
+ Missing, partial, mixed or rolled-back observations remain unobserved rather
66
+ than guessed. Incremental observers report health and coverage; sampling does
67
+ not block lifecycle events. Metrics never trigger model selection, wake, retry,
68
+ resource release or acceptance.
69
+
70
+ ## Native children
71
+
72
+ Native subagents are collaboration inside a parent conversation, not Yui Roles,
73
+ Lanes or independent managed workspace owners. Continuation observations may
74
+ record lineage and result references when the Provider exposes them.
75
+
76
+ Best-effort child results return through the parent. Only a persisted content
77
+ receipt justifies `durable-result`; a live child or claimed success does not.
78
+ Reported results remain untrusted data. A lost best-effort conversation may
79
+ require redoing the work. Choose a managed WorkItem execution when independent
80
+ durability and acceptance are needed; replication is a separate choice.
81
+
82
+ ## Integration and validation
83
+
84
+ A new connection implementation must supply truthful control/observation
85
+ capabilities and pair them with exact identity, error and terminal mapping.
86
+ Provider-specific protocol details stay at the edge, not in Task planning,
87
+ Store semantics or Web business rules.
88
+
89
+ Change-specific disposable evidence should cover the changed correlation,
90
+ permission, cancellation or observation boundary. Keep permanent tests to the
91
+ primary paths in the [verification policy](testing/verification-levels.md).
92
+ Real Provider/model validation requires explicit authorization and must distinguish
93
+ native process evidence from fixture output.