@zq-silk/yui 0.15.11 → 0.16.0

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 (280) hide show
  1. package/ARCHITECTURE.md +11 -6
  2. package/ARCHITECTURE.zh-CN.md +8 -4
  3. package/README.md +13 -5
  4. package/dist/agentRun/agentRun.js +3 -0
  5. package/dist/artifacts/artifactCommitLock.js +16 -55
  6. package/dist/artifacts/taskArtifactRepository.js +3 -3
  7. package/dist/cli/agentConfigurationPicker.js +1 -1
  8. package/dist/cli/commandCatalog.js +92 -48
  9. package/dist/cli/completion.js +18 -18
  10. package/dist/cli/completionWizard.js +1 -1
  11. package/dist/cli/dynamicCompletion.js +1 -1
  12. package/dist/cli/interactionPolicy.js +11 -3
  13. package/dist/cli/invocationAuthority.js +64 -0
  14. package/dist/cli/managedDiagnostics.js +2 -2
  15. package/dist/cli/parseRepeatable.js +35 -0
  16. package/dist/cli/updatePorts.js +26 -5
  17. package/dist/cli.js +1303 -1235
  18. package/dist/commands/agentCommands.js +4 -4
  19. package/dist/commands/capabilityCommands.js +1 -1
  20. package/dist/commands/configCommands.js +6 -57
  21. package/dist/commands/configOverview.js +2 -2
  22. package/dist/commands/durableJobCommands.js +12 -6
  23. package/dist/commands/executionAuditCommands.js +10 -0
  24. package/dist/commands/globalRoleCommands.js +78 -29
  25. package/dist/commands/grantCommands.js +0 -3
  26. package/dist/commands/jobCommands.js +1 -4
  27. package/dist/commands/operatorCommands.js +3 -3
  28. package/dist/commands/projectCommands.js +45 -25
  29. package/dist/commands/resourcesCommands.js +10 -40
  30. package/dist/commands/roleConfiguration.js +2 -6
  31. package/dist/commands/taskActivationCommands.js +4 -8
  32. package/dist/commands/taskAgentCapabilities.js +9 -0
  33. package/dist/commands/taskCommandSupport.js +155 -0
  34. package/dist/commands/taskCommandTypes.js +1 -0
  35. package/dist/commands/taskCommands.js +355 -732
  36. package/dist/commands/taskCompletionGate.js +1 -1
  37. package/dist/commands/taskExecutionCommands.js +1 -1
  38. package/dist/commands/taskFactCommands.js +325 -0
  39. package/dist/commands/taskInputCommands.js +12 -42
  40. package/dist/commands/taskIntegrationCommands.js +20 -58
  41. package/dist/commands/taskNextActionCommand.js +7 -6
  42. package/dist/commands/taskPublicationAdoptCommand.js +127 -0
  43. package/dist/commands/taskPublicationCommands.js +12 -3
  44. package/dist/commands/taskPublicationVerifyCommand.js +24 -40
  45. package/dist/commands/taskRemoteDeliveryCommand.js +5 -86
  46. package/dist/commands/taskUpstreamCommands.js +19 -8
  47. package/dist/commands/workflowCommands.js +6 -1
  48. package/dist/completion/completionInstaller.js +26 -26
  49. package/dist/completion/completionState.js +26 -26
  50. package/dist/completion/fileCompletionManager.js +6 -11
  51. package/dist/config/configCatalog.js +0 -2
  52. package/dist/config/timeZone.js +14 -0
  53. package/dist/config/yuiConfig.js +0 -29
  54. package/dist/context/runContextPack.js +5 -3
  55. package/dist/context/taskCatalog.js +185 -0
  56. package/dist/context/taskContext.js +152 -151
  57. package/dist/context/wakeRunReferences.js +11 -0
  58. package/dist/controller/agentCapabilities.js +58 -0
  59. package/dist/controller/agentRuntimeObserver.js +6 -11
  60. package/dist/controller/clientRuntime.js +22 -14
  61. package/dist/controller/controller.js +20 -24
  62. package/dist/controller/fileSchedulerStoreAdapter.js +191 -225
  63. package/dist/controller/globalInputDelivery.js +13 -0
  64. package/dist/controller/jobClient.js +4 -4
  65. package/dist/controller/jobControl.js +60 -25
  66. package/dist/controller/jobSupervisor.js +4 -4
  67. package/dist/controller/providerRetryAdmission.js +100 -0
  68. package/dist/controller/providerRetryDelivery.js +218 -0
  69. package/dist/controller/runtime.js +85 -43
  70. package/dist/controller/runtimeEventProcessor.js +0 -5
  71. package/dist/controller/sessionOwnerReconciliation.js +5 -0
  72. package/dist/controller/taskAgentError.js +35 -0
  73. package/dist/coordination/workMailboxQueue.js +2 -24
  74. package/dist/core/controllerClient.js +2 -2
  75. package/dist/core/fileLockOwner.js +74 -0
  76. package/dist/decision/decision.js +17 -0
  77. package/dist/doctor/doctor.js +18 -9
  78. package/dist/event/taskEvent.js +12 -0
  79. package/dist/execution/workItemExecutionProjection.js +2 -2
  80. package/dist/executor/agentCapabilityConfig.js +43 -0
  81. package/dist/executor/agentConfigurationCatalog.js +49 -11
  82. package/dist/executor/agentExecutor.js +5 -8
  83. package/dist/executor/fileRoleLaunchPlanner.js +11 -53
  84. package/dist/executor/taskAgentCapabilities.js +64 -0
  85. package/dist/integration/deliveryObligation.js +1 -69
  86. package/dist/integration/gitIntegrationService.js +79 -90
  87. package/dist/integration/integrationAttempt.js +3 -14
  88. package/dist/integration/integrationSourceApplication.js +4 -12
  89. package/dist/integration/manifestTags.js +2 -2
  90. package/dist/job/durableJob.js +4 -25
  91. package/dist/job/jobAssignmentScope.js +22 -0
  92. package/dist/job/jobOperation.js +16 -0
  93. package/dist/job/jobRunner.js +2 -1
  94. package/dist/job/stepDirectory.js +15 -0
  95. package/dist/kernel/builtinCapabilities.js +15 -11
  96. package/dist/kernel/kernelPorts.js +1 -17
  97. package/dist/lifecycle/exactRunTerminalization.js +5 -10
  98. package/dist/message/globalProviderRetry.js +15 -0
  99. package/dist/message/inputControlResolution.js +3 -4
  100. package/dist/message/message.js +17 -20
  101. package/dist/message/messageContinuation.js +1 -1
  102. package/dist/milestone/milestone.js +11 -0
  103. package/dist/observability/executionAudit.js +19 -0
  104. package/dist/observability/orchestrationMetrics.js +24 -1
  105. package/dist/observability/runtimeIdentity.js +1 -17
  106. package/dist/output/agentConfigurationPresentation.js +2 -0
  107. package/dist/output/timePresentation.js +1 -14
  108. package/dist/plugins/pluginService.js +12 -4
  109. package/dist/release/releaseWorkflowPorts.js +45 -96
  110. package/dist/release/runtimeRelease.js +9 -15
  111. package/dist/repository/gitWorkspace.js +371 -105
  112. package/dist/repository/projectMaintenanceLock.js +98 -82
  113. package/dist/repository/taskBaseFreshness.js +1 -1
  114. package/dist/repository/taskWorkspaceCoordinator.js +82 -144
  115. package/dist/repository/taskWorkspacePreparer.js +113 -47
  116. package/dist/repository/workspaceCleanupInspection.js +187 -0
  117. package/dist/resources/autoResourceGc.js +4 -77
  118. package/dist/resources/liveReferences.js +7 -54
  119. package/dist/resources/resourceDiscovery.js +5 -118
  120. package/dist/resources/resourceGc.js +233 -181
  121. package/dist/resources/resourceRegistrar.js +5 -4
  122. package/dist/resources/resourceRegistry.js +3 -37
  123. package/dist/resources/resourceRegistryStore.js +13 -36
  124. package/dist/resources/sqliteResourceRegistry.js +43 -26
  125. package/dist/review/deltaRecheck.js +1 -1
  126. package/dist/review/reviewAcceptance.js +1 -1
  127. package/dist/review/reviewDecision.js +1 -1
  128. package/dist/review/reviewRound.js +8 -7
  129. package/dist/review/taskFinalReviewContractResolution.js +1 -1
  130. package/dist/runtime/acpProtocol.js +4 -51
  131. package/dist/runtime/acpSession.js +10 -75
  132. package/dist/runtime/acpSessionConfiguration.js +1 -8
  133. package/dist/runtime/agentEndpoint.js +3 -2
  134. package/dist/runtime/agentError.js +5 -3
  135. package/dist/runtime/agentFailureContext.js +43 -0
  136. package/dist/runtime/agentHost.js +42 -25
  137. package/dist/runtime/builtinAgentErrorMappers.js +91 -0
  138. package/dist/runtime/codexAppServerRuntime.js +34 -3
  139. package/dist/runtime/codexInteractiveHost.js +2 -2
  140. package/dist/runtime/index.js +0 -1
  141. package/dist/runtime/managedCaller.js +21 -1
  142. package/dist/runtime/providerControl.js +5 -1
  143. package/dist/runtime/providerErrors.js +38 -0
  144. package/dist/runtime/providerRetry.js +198 -0
  145. package/dist/runtime/providerRuntimeIdentity.js +28 -2
  146. package/dist/runtime/runtimeObservation.js +0 -5
  147. package/dist/runtime/runtimeSessionCandidate.js +2 -3
  148. package/dist/runtime/sessionOwnerIdentity.js +1 -1
  149. package/dist/runtime/sessionTokenMetrics.js +15 -5
  150. package/dist/runtime/structuredProviderHost.js +10 -43
  151. package/dist/runtime/taskUsageMetrics.js +275 -0
  152. package/dist/runtime/tmuxAdapters.js +6 -8
  153. package/dist/scheduler/activeRoleRunDelivery.js +19 -7
  154. package/dist/scheduler/leaderWakeupProcessor.js +24 -6
  155. package/dist/scheduler/operatorEvent.js +12 -20
  156. package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
  157. package/dist/scheduler/ports.js +5 -8
  158. package/dist/scheduler/roleRunLiveness.js +4 -4
  159. package/dist/scheduler/roleRunStall.js +16 -23
  160. package/dist/scheduler/taskExecutionProjection.js +49 -36
  161. package/dist/scheduler/taskObservabilityProjection.js +6 -45
  162. package/dist/scheduler/taskWake.js +5 -10
  163. package/dist/scheduler/wakeReason.js +2 -0
  164. package/dist/scheduler/wakeupQueue.js +2 -4
  165. package/dist/setup/setupCommand.js +1 -1
  166. package/dist/storage/contextRecords.js +106 -0
  167. package/dist/storage/currentTaskStore.js +1 -1
  168. package/dist/storage/homeLayout.js +13 -17
  169. package/dist/storage/migrations/agentFailureContext.js +22 -0
  170. package/dist/storage/migrations/currentInputContract.js +86 -0
  171. package/dist/storage/migrations/currentRuntimeContract.js +228 -0
  172. package/dist/storage/migrations/historicalVerificationPlan.js +35 -0
  173. package/dist/storage/migrations/integrationContinuation.js +5 -4
  174. package/dist/storage/migrations/narrowAgentFailureContext.js +65 -0
  175. package/dist/storage/migrations/notificationOnlyWakes.js +74 -0
  176. package/dist/storage/migrations/verificationPlanV1.js +162 -0
  177. package/dist/storage/migrations/verificationPolicy.js +74 -0
  178. package/dist/storage/migrations/workItemHistory.js +46 -0
  179. package/dist/storage/persistenceWorker.js +12 -4
  180. package/dist/storage/recordValidation.js +87 -0
  181. package/dist/storage/sqliteSchema.js +173 -1
  182. package/dist/storage/sqliteStore.js +172 -161
  183. package/dist/storage/storageSchema.js +2 -14
  184. package/dist/storage/storageVersions.js +1 -1
  185. package/dist/storage/storeRpc.js +16 -7
  186. package/dist/storage/taskCatalog.js +123 -0
  187. package/dist/storage/taskStore.js +5 -7
  188. package/dist/storage/upgrade/upgradeOrchestrator.js +25 -37
  189. package/dist/task/archiveDiagnostics.js +1 -0
  190. package/dist/task/archivePreflight.js +124 -0
  191. package/dist/task/completionReadiness.js +5 -24
  192. package/dist/task/draftPlan.js +0 -53
  193. package/dist/task/nextAction.js +7 -13
  194. package/dist/task/publicationAdoption.js +56 -0
  195. package/dist/task/publicationReference.js +10 -0
  196. package/dist/task/remoteDelivery.js +31 -16
  197. package/dist/task/remoteDeliveryService.js +89 -0
  198. package/dist/task/taskActivation.js +2 -25
  199. package/dist/task/taskActivationService.js +0 -2
  200. package/dist/task/taskRecordReference.js +0 -1
  201. package/dist/task/taskSubmission.js +3 -14
  202. package/dist/telemetry/sqliteTelemetryBatch.js +29 -0
  203. package/dist/telemetry/sqliteTelemetryStore.js +49 -49
  204. package/dist/telemetry/telemetryWiring.js +4 -3
  205. package/dist/tmux/tmuxManager.js +29 -20
  206. package/dist/verification/gateArtifact.js +15 -24
  207. package/dist/verification/gateArtifactStore.js +14 -7
  208. package/dist/verification/verificationGateService.js +29 -88
  209. package/dist/verification/verificationPlan.js +27 -72
  210. package/dist/web/assets/client/app.js +92 -17
  211. package/dist/web/assets/client/components.js +55 -13
  212. package/dist/web/assets/client/i18n.js +72 -4
  213. package/dist/web/assets/client/taskSurface.js +6 -5
  214. package/dist/web/assets/client/view.js +35 -7
  215. package/dist/web/assets/shell.js +6 -0
  216. package/dist/web/assets/styles/layout.js +7 -0
  217. package/dist/web/webServer.js +12 -3
  218. package/dist/web/webSnapshot.js +14 -85
  219. package/dist/web/webTaskSurface.js +17 -46
  220. package/dist/workItem/workItem.js +1 -12
  221. package/dist/workspace/cleanupInspection.js +63 -0
  222. package/dist/workspace/workItemChangeSetManager.js +110 -50
  223. package/docs/agent-result-consumption.md +4 -0
  224. package/docs/agent-result-consumption.zh-CN.md +3 -0
  225. package/docs/agent-runtime-drivers.md +7 -0
  226. package/docs/agent-runtime-drivers.zh-CN.md +5 -0
  227. package/docs/architecture/README.md +2 -0
  228. package/docs/architecture/README.zh-CN.md +3 -1
  229. package/docs/architecture/capabilities-and-resources.md +42 -5
  230. package/docs/architecture/capabilities-and-resources.zh-CN.md +33 -3
  231. package/docs/managed-turn-and-session-runtime.md +121 -1
  232. package/docs/managed-turn-and-session-runtime.zh-CN.md +96 -2
  233. package/docs/observability/README.md +62 -0
  234. package/docs/observability/README.zh-CN.md +47 -0
  235. package/docs/plugin-sdk.md +4 -2
  236. package/docs/project-refresh.md +77 -0
  237. package/docs/project-refresh.zh-CN.md +59 -0
  238. package/docs/provider-retry.md +70 -0
  239. package/docs/provider-runtime.md +3 -1
  240. package/docs/provider-runtime.zh-CN.md +4 -2
  241. package/docs/release-workflow.md +190 -7
  242. package/docs/release-workflow.zh-CN.md +139 -5
  243. package/docs/roles-and-configuration.md +29 -0
  244. package/docs/roles-and-configuration.zh-CN.md +21 -0
  245. package/docs/sqlite-control-plane-design.md +16 -3
  246. package/docs/sqlite-control-plane-design.zh-CN.md +13 -2
  247. package/docs/task-dag-semantics.md +3 -3
  248. package/docs/task-dag-semantics.zh-CN.md +2 -2
  249. package/docs/task-delivery.md +223 -17
  250. package/docs/task-delivery.zh-CN.md +171 -14
  251. package/docs/task-discovery.md +101 -0
  252. package/docs/task-discovery.zh-CN.md +85 -0
  253. package/docs/testing/verification-levels.md +161 -9
  254. package/docs/testing/verification-levels.zh-CN.md +116 -9
  255. package/i18n/README.zh-CN.md +13 -7
  256. package/package.json +1 -1
  257. package/skills/yui-leader/SKILL.md +5 -0
  258. package/skills/yui-leader/references/execution.md +3 -2
  259. package/skills/yui-leader/references/integration.md +9 -5
  260. package/skills/yui-leader/references/planning.md +9 -3
  261. package/skills/yui-operator/SKILL.md +24 -8
  262. package/skills/yui-reviewer/SKILL.md +4 -0
  263. package/skills/yui-runtime/SKILL.md +17 -2
  264. package/skills/yui-runtime/references/publication.md +26 -4
  265. package/skills/yui-runtime/references/recovery.md +71 -0
  266. package/dist/agent/agentRegistry.js +0 -10
  267. package/dist/agentRun/runIdentity.js +0 -22
  268. package/dist/commands/deliveryGuardPreflight.js +0 -30
  269. package/dist/commands/taskIntegrationQueueCommands.js +0 -226
  270. package/dist/commands/taskOverviewCommand.js +0 -376
  271. package/dist/completion/completionWizard.js +0 -125
  272. package/dist/context/dispatchContext.js +0 -110
  273. package/dist/context/wakeNotification.js +0 -144
  274. package/dist/integration/integrationCheckEvidenceReuse.js +0 -53
  275. package/dist/integration/integrationQueueEntry.js +0 -191
  276. package/dist/integration/integrationQueueService.js +0 -810
  277. package/dist/release/fakeReleasePorts.js +0 -55
  278. package/dist/runtime/sessionOwnerRegistry.js +0 -137
  279. package/dist/task/deliveryGuard.js +0 -226
  280. /package/dist/{commands/taskActor.js → task/taskAuthority.js} +0 -0
@@ -1,44 +1,46 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
- import { prepareMessageContinuations, interruptThenTerminalState } from "../message/messageContinuation.js";
3
- import { freezeRunContextSnapshot } from "../context/runContextPack.js";
4
- import { contextSnapshotRef } from "../context/contextSnapshot.js";
5
2
  import { isDeepStrictEqual } from "node:util";
3
+ import { contextSnapshotRef } from "../context/contextSnapshot.js";
4
+ import { freezeRunContextSnapshot } from "../context/runContextPack.js";
5
+ import { settleGlobalRetryInput } from "../message/globalProviderRetry.js";
6
+ import { interruptThenTerminalState, prepareMessageContinuations } from "../message/messageContinuation.js";
6
7
  import { assertExecutionEnvironmentCurrent } from "../runtime/executionEnvironment.js";
7
- import { resolveAgentHostObservation, recordAgentHostConnection, AgentHostObservationDeferred } from "./agentHostObservation.js";
8
+ import { deferProviderRetry, providerRetryPending, recordProviderFailure } from "../runtime/providerRetry.js";
9
+ import { AgentHostObservationDeferred, recordAgentHostConnection, resolveAgentHostObservation } from "./agentHostObservation.js";
10
+ import { admitOwnedProviderInput, ownedProviderInput } from "./providerRetryAdmission.js";
8
11
  import { RuntimeHookRunFenceError } from "./runtimeHookRunFence.js";
9
- import { activeLiveRoleAgentSession, bindTaskRoleProviderRuntime, bindGlobalRoleProviderRuntime, createRoleSessionSet, recordRoleAgentSession, replaceTaskRoleAgentSession, recordTaskRoleNativeTurnBoundary, rememberRoleAgentCompletedTurn, detachRoleAgentSessionHost, updateRoleAgentSessionStatus, updateTaskRoleProviderRuntime, updateGlobalRoleProviderRuntime, selectNewTaskRoleSession, taskRoleControlTarget } from "../executor/agentExecutor.js";
10
- import { acceptProviderTurn, cancelQuiescentProviderInput, beginProviderTurn, createProviderRuntimeBinding, currentProviderConversation, managedProviderTurnId, clearProviderGoal, settleProviderTurnSubmission, settleProviderTurn, transferProviderAuthority, supersedeProviderConversation, updateProviderConversationRecoverability, updateProviderGoal } from "../runtime/providerRuntimeIdentity.js";
12
+ import { appendRunInput, createRun, runPurposeAdmitsTaskState, withRunContextSnapshot } from "../agentRun/agentRun.js";
13
+ import { createRunInput } from "../context/runInputContract.js";
14
+ import { bindExecution, claimPending, completeProcessing, consumePendingBatch, mailboxHasWork, releaseProcessing } from "../coordination/workMailbox.js";
15
+ import { enqueueWork, settleRoleRunDispatch as settleRoleRunDispatchMailbox } from "../coordination/workMailboxQueue.js";
16
+ import { transportAgentResult } from "../domain/agentResultTransport.js";
11
17
  import { createTaskEvent } from "../event/taskEvent.js";
12
- import { operationalTaskRecords } from "../task/taskRecordRetirement.js";
13
- import { buildTaskWakeEnvelope } from "../context/wakeNotification.js";
14
- import { createTaskWake, fallbackWakeCursor, latestTaskWake, markTaskWakeConsumed } from "../scheduler/taskWake.js";
18
+ import { activeLiveRoleAgentSession, bindGlobalRoleProviderRuntime, bindTaskRoleProviderRuntime, createRoleSessionSet, detachRoleAgentSessionHost, recordRoleAgentSession, recordTaskRoleNativeTurnBoundary, rememberRoleAgentCompletedTurn, replaceTaskRoleAgentSession, selectNewTaskRoleSession, taskRoleControlTarget, updateGlobalRoleProviderRuntime, updateRoleAgentSessionStatus, updateTaskRoleProviderRuntime } from "../executor/agentExecutor.js";
19
+ import { effectiveLaunchWithTaskMainWorkspace, resolveEffectiveLaunch, roleSessionMayContinue, validateEffectiveLaunchSnapshot } from "../executor/effectiveLaunch.js";
15
20
  import { answerInputRequest } from "../input/inputRequest.js";
21
+ import { createCanonicalLifecycleEvent, foldCanonicalLifecycleEvent } from "../lifecycle/canonicalLifecycleEvent.js";
22
+ import { cancelQuiescentRoleRuns, terminalizeExactTaskRun } from "../lifecycle/exactRunTerminalization.js";
23
+ import { markGlobalRoleMessageDelivered, markGlobalRoleMessageNotDelivered, recordTaskMessageControlOutcome } from "../message/message.js";
24
+ import { snapshotExecutionLaneWorkspaceSync } from "../repository/executionLaneGitSnapshot.js";
16
25
  import { activeRoleAgentBinding } from "../role/role.js";
17
- import { effectiveLaunchWithTaskMainWorkspace, roleSessionMayContinue, resolveEffectiveLaunch, validateEffectiveLaunchSnapshot } from "../executor/effectiveLaunch.js";
18
26
  import { SYSTEM_OPERATOR_ROLE } from "../role/systemRoles.js";
19
- import { appendRunInput, createRun, withRunContextSnapshot, runPurposeAdmitsTaskState } from "../agentRun/agentRun.js";
20
- import { transportAgentResult } from "../domain/agentResultTransport.js";
21
- import { createRunInput } from "../context/runInputContract.js";
22
- import { recordTaskMessageControlOutcome, markGlobalRoleMessageDelivered, markGlobalRoleMessageNotDelivered } from "../message/message.js";
27
+ import { standardAgentError } from "../runtime/agentError.js";
28
+ import { recordTaskAgentError } from "./taskAgentError.js";
29
+ import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
30
+ import { RUNTIME_CLEANUP_REQUIRED_REASON, RUNTIME_HOST_DETACH_REQUIRED_REASON, RUNTIME_LIFECYCLE_OWNER, hasRuntimeCleanupObligation, hasRuntimeLifecycleWork, isRuntimeCleanupReason, runtimeCleanupDisposition, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
23
31
  import { classifyRuntimeProcessExit, validateRuntimeProcessExitObservation } from "../runtime/processExitObservation.js";
24
- import { terminalizeExactTaskRun, cancelQuiescentRoleRuns } from "../lifecycle/exactRunTerminalization.js";
25
- import { createCanonicalLifecycleEvent, foldCanonicalLifecycleEvent } from "../lifecycle/canonicalLifecycleEvent.js";
32
+ import { providerContinuationKey } from "../runtime/providerContinuation.js";
33
+ import { acceptProviderTurn, beginProviderTurn, cancelQuiescentProviderInput, clearProviderGoal, createProviderRuntimeBinding, currentProviderConversation, managedProviderTurnId, settleProviderTurn, settleProviderTurnSubmission, supersedeProviderConversation, transferProviderAuthority, updateProviderConversationRecoverability, updateProviderGoal } from "../runtime/providerRuntimeIdentity.js";
34
+ import { projectProviderContinuations } from "../runtime/runtimeContinuationProjection.js";
35
+ import { RUNTIME_OBSERVATION_TASK_EVENT, createRuntimeObservation, isRuntimeTokenEvidence, runtimeObservationFenceMatches, runtimeObservationFromTaskEvent, runtimeObservationRunFenceMatches, runtimeObservationTaskEventPayload } from "../runtime/runtimeObservation.js";
26
36
  import { recordLeaderFailure } from "../scheduler/leaderFailure.js";
27
- import { recordLeaderAttentionRequired, routeRoleEvent } from "../scheduler/operatorEvent.js";
28
- import { queueLeaderWakeup } from "../scheduler/wakeupQueue.js";
37
+ import { enqueueSupervisorEvent, recordLeaderAttentionRequired, routeRoleEvent } from "../scheduler/operatorEvent.js";
38
+ import { RUN_DIAGNOSTIC_FINISHED_EVENT, RUN_PROGRESS_EVENT, RUN_RECOVERED_EVENT, RUN_STALLED_EVENT, foldRunProgressFacts, isRoleRunStalled, latestRunDurableProgressAt, latestRunEventTime, latestStallEvidenceKey } from "../scheduler/roleRunStall.js";
39
+ import { createTaskWake, latestTaskWake, markTaskWakeConsumed } from "../scheduler/taskWake.js";
29
40
  import { wakeReason } from "../scheduler/wakeReason.js";
30
- import { foldRunProgressFacts, latestRunDurableProgressAt, latestRunEventTime, latestStallEvidenceKey, isRoleRunStalled, RUN_PROGRESS_EVENT, RUN_DIAGNOSTIC_FINISHED_EVENT, RUN_RECOVERED_EVENT, RUN_STALLED_EVENT } from "../scheduler/roleRunStall.js";
41
+ import { queueLeaderWakeup } from "../scheduler/wakeupQueue.js";
31
42
  import { pendingWakeupProjection } from "../storage/taskStore.js";
32
- import { projectProviderContinuations } from "../runtime/runtimeContinuationProjection.js";
33
- import { providerContinuationKey } from "../runtime/providerContinuation.js";
34
43
  import { formatRunReceiptId } from "../task/taskRecordReference.js";
35
- import { bindExecution, claimPending, completeProcessing, consumePendingBatch, mailboxHasWork, releaseProcessing } from "../coordination/workMailbox.js";
36
- import { enqueueWork, settleRoleRunDispatch as settleRoleRunDispatchMailbox } from "../coordination/workMailboxQueue.js";
37
- import { RUNTIME_CLEANUP_REQUIRED_REASON, RUNTIME_HOST_DETACH_REQUIRED_REASON, RUNTIME_LIFECYCLE_OWNER, hasRuntimeCleanupObligation, hasRuntimeLifecycleWork, isRuntimeCleanupReason, runtimeCleanupDisposition, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
38
- import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
39
- import { standardAgentError } from "../runtime/agentError.js";
40
- import { RUNTIME_OBSERVATION_TASK_EVENT, createRuntimeObservation, isRuntimeTokenEvidence, runtimeObservationFenceMatches, runtimeObservationFromTaskEvent, runtimeObservationRunFenceMatches, runtimeObservationTaskEventPayload } from "../runtime/runtimeObservation.js";
41
- import { snapshotExecutionLaneWorkspaceSync } from "../repository/executionLaneGitSnapshot.js";
42
44
  export class AgentHostProviderTurnFenceError extends Error {
43
45
  constructor(message) {
44
46
  super(message);
@@ -404,7 +406,9 @@ export class FileSchedulerStoreAdapter {
404
406
  }
405
407
  else if (binding.run?.status !== "accepted")
406
408
  return "applied";
407
- const message = store.listGlobalRoleMessages(fence.roleName).find(entry => receipt === `global-input:${fence.roleName}/${entry.id}`);
409
+ const message = store.listGlobalRoleMessages(fence.roleName).find(entry => receipt === `global-input:${fence.roleName}/${entry.id}`
410
+ || binding?.retry?.currentAttemptId === receipt && binding.retry.input.kind === "message"
411
+ && binding.retry.input.messageId === entry.id);
408
412
  if (message !== undefined)
409
413
  store.updateGlobalRoleMessage(markGlobalRoleMessageDelivered(message, new Date(at)));
410
414
  }
@@ -417,7 +421,9 @@ export class FileSchedulerStoreAdapter {
417
421
  if (input.kind === "turn.completed" && binding.run != null
418
422
  && ["submitting", "delivery-unknown"].includes(binding.run.status)) {
419
423
  binding = acceptProviderTurn(binding, { attemptId: receipt, nativeTurnId: fence.nativeTurnId, acceptedAt: at });
420
- const message = store.listGlobalRoleMessages(fence.roleName).find(entry => receipt === `global-input:${fence.roleName}/${entry.id}`);
424
+ const message = store.listGlobalRoleMessages(fence.roleName).find(entry => receipt === `global-input:${fence.roleName}/${entry.id}`
425
+ || binding?.retry?.currentAttemptId === receipt && binding.retry.input.kind === "message"
426
+ && binding.retry.input.messageId === entry.id);
421
427
  if (message !== undefined)
422
428
  store.updateGlobalRoleMessage(markGlobalRoleMessageDelivered(message, new Date(at)));
423
429
  }
@@ -449,7 +455,13 @@ export class FileSchedulerStoreAdapter {
449
455
  else if (input.kind === "conversation.observed" && input.payload.recoverability !== undefined) {
450
456
  binding = updateProviderConversationRecoverability(binding, input.payload.recoverability);
451
457
  }
458
+ if (input.kind === "turn.failed" && matches && input.payload.failure !== undefined) {
459
+ binding = recordProviderFailure(binding, {
460
+ error: input.payload.failure.error, failureRef: input.eventId, at: now.getTime()
461
+ });
462
+ }
452
463
  store.saveGlobalRoleSessionSet(updateGlobalRoleProviderRuntime(sessions, binding, now));
464
+ settleGlobalRetryInput(store, fence.roleName, binding, now);
453
465
  return "applied";
454
466
  });
455
467
  }
@@ -727,31 +739,25 @@ export class FileSchedulerStoreAdapter {
727
739
  const run = input.fence.runId === undefined
728
740
  ? null
729
741
  : store.getRun(taskId, input.fence.runId);
730
- const errorEvent = createTaskEvent(store.nextEventId(taskId), taskId, "runtime.agent-error", {
731
- sourceEventId: input.eventId,
732
- observationEventId,
733
- runId: input.fence.runId ?? "",
734
- roleName: input.fence.roleName,
735
- agentId: input.fence.agentId,
736
- adapterId: run?.effective.adapterId ?? "unknown",
737
- driverId: input.fence.driverId,
738
- nativeSessionId: input.fence.nativeSessionId ?? "",
739
- nativeTurnId: input.fence.nativeTurnId ?? "",
740
- source: error.source,
741
- phase: error.phase,
742
- category: error.category,
743
- code: error.code,
744
- message: error.message,
745
- raw: error.raw,
746
- inputDisposition: error.inputDisposition,
747
- sessionDisposition: error.sessionDisposition,
748
- ...(error.retryAfterMs === undefined
749
- ? {}
750
- : { retryAfterMs: String(error.retryAfterMs) }),
751
- ...(failure.lastOutput === undefined ? {} : { lastOutput: failure.lastOutput })
742
+ const errorSessions = store.getTaskRoleSessionSet(taskId, input.fence.roleName);
743
+ const errorSession = [...Object.values(errorSessions?.sessions ?? {}), ...(errorSessions?.history ?? [])]
744
+ .find(session => session.nativeSessionId === input.fence.nativeSessionId
745
+ && session.agentId === input.fence.agentId);
746
+ const effective = run?.effective ?? errorSession?.effective;
747
+ const { event: errorEvent, created } = recordTaskAgentError(store, {
748
+ taskId, roleName: input.fence.roleName, sourceEventId: input.eventId,
749
+ agentId: input.fence.agentId, adapterId: effective?.adapterId ?? "unknown",
750
+ driverId: input.fence.driverId, error, effective,
751
+ evidence: {
752
+ observationEventId,
753
+ runId: input.fence.runId,
754
+ nativeSessionId: input.fence.nativeSessionId,
755
+ nativeTurnId: input.fence.nativeTurnId,
756
+ lastOutput: failure.lastOutput
757
+ },
752
758
  }, now);
753
- store.saveEvent(taskId, errorEvent);
754
- routeRoleEvent(store, errorEvent, input.fence.roleName, wakeReason("agent-error", errorEvent.id), now);
759
+ if (created && !providerRetryPending(store.getTaskRoleSessionSet(taskId, input.fence.roleName)?.providerBinding))
760
+ routeRoleEvent(store, errorEvent, input.fence.roleName, wakeReason("agent-error", errorEvent.id), now);
755
761
  }
756
762
  if ((input.kind === "operation.completed" || input.kind === "operation.failed")
757
763
  && input.payload.operation === "subagent") {
@@ -841,29 +847,6 @@ export class FileSchedulerStoreAdapter {
841
847
  getTaskBrief(taskId) { return this.store.getTaskBrief(taskId); }
842
848
  listDecisions(taskId) { return this.store.listDecisions(taskId); }
843
849
  listMilestones(taskId) { return this.store.listMilestones(taskId); }
844
- getTaskWakeEnvelope(taskId) {
845
- return this.store.transaction((reader) => {
846
- const pending = reader.getPendingWakeup(taskId);
847
- if (pending === null)
848
- return null;
849
- const task = reader.getTask(taskId);
850
- if (task === null)
851
- return null;
852
- const latest = latestTaskWake(reader.listTaskWakes(taskId));
853
- const fromCursor = latest?.toCursor ?? fallbackWakeCursor({
854
- taskCreatedAt: task.createdAt,
855
- leaderRunCreatedAt: operationalTaskRecords(reader.listRuns(taskId), reader.listEvents(taskId), "run")
856
- .filter((run) => run.roleName === "leader")
857
- .at(-1)?.createdAt
858
- });
859
- return buildTaskWakeEnvelope(reader, {
860
- taskId,
861
- wakeId: reader.peekNextTaskWakeId(taskId),
862
- reasons: pending.reasons,
863
- fromCursor
864
- });
865
- });
866
- }
867
850
  listRoles(taskId) {
868
851
  return this.store.listRoles(taskId).map((role) => mapRole(this.store, role));
869
852
  }
@@ -1092,7 +1075,7 @@ export class FileSchedulerStoreAdapter {
1092
1075
  throw new AgentHostProviderTurnFenceError("Global Session admission is stopped.");
1093
1076
  }
1094
1077
  const sessions = store.getGlobalRoleSessionSet(input.roleName);
1095
- const binding = sessions?.providerBinding;
1078
+ let binding = sessions?.providerBinding;
1096
1079
  const session = sessions?.sessions[input.agentId];
1097
1080
  if (sessions === null || binding == null || session === undefined
1098
1081
  || sessions.activeAgentId !== input.agentId || session.status !== "active"
@@ -1104,8 +1087,10 @@ export class FileSchedulerStoreAdapter {
1104
1087
  throw new AgentHostProviderTurnFenceError("Global input carries a stale Session or writer fence.");
1105
1088
  }
1106
1089
  const turn = binding.run;
1107
- if (turn?.attemptId === input.attemptId && turn.status === "submitting")
1090
+ if (turn?.attemptId === input.attemptId && turn.status === "submitting") {
1091
+ admitOwnedProviderInput(store, binding, input);
1108
1092
  return;
1093
+ }
1109
1094
  if (turn != null && ["submitting", "accepted", "delivery-unknown"].includes(turn.status)) {
1110
1095
  throw new AgentHostProviderSessionBusyError("Global Conversation has an unsettled input.");
1111
1096
  }
@@ -1139,7 +1124,10 @@ export class FileSchedulerStoreAdapter {
1139
1124
  receiptId: input.attemptId, outcome: "pending", observedAt: input.now.toISOString()
1140
1125
  } });
1141
1126
  }
1127
+ binding = admitOwnedProviderInput(store, binding, input);
1142
1128
  store.saveGlobalRoleSessionSet(updateGlobalRoleProviderRuntime(sessions, beginProviderTurn(binding, { attemptId: input.attemptId,
1129
+ input: binding.retry?.currentAttemptId === input.attemptId ? binding.retry.input : ownedProviderInput(input),
1130
+ retrySupported: input.retrySupported,
1143
1131
  authorityEpoch: input.authorityEpoch, submittedAt: input.now.toISOString() }), input.now));
1144
1132
  });
1145
1133
  return;
@@ -1157,7 +1145,7 @@ export class FileSchedulerStoreAdapter {
1157
1145
  }
1158
1146
  const sessions = store.getTaskRoleSessionSet(input.taskId, input.roleName);
1159
1147
  const session = sessions?.sessions[input.agentId];
1160
- const binding = sessions?.providerBinding;
1148
+ let binding = sessions?.providerBinding;
1161
1149
  const active = store.getActiveRun(input.taskId, input.roleName);
1162
1150
  if (sessions === null || sessions === undefined || binding === null || binding === undefined || (input.runId !== undefined && (active?.id !== input.runId || active.effective.agentId !== input.agentId)) || session === undefined || session.nativeSessionId !== input.nativeSessionId || currentProviderConversation(binding).conversationId !== input.nativeSessionId || binding.authority.owner !== input.authorityOwner || binding.authority.epoch !== input.authorityEpoch || binding.authority.holderId !== input.holderId) {
1163
1151
  throw new AgentHostProviderTurnFenceError("Agent Host Provider Turn carries a stale durable writer fence. Release and reacquire Provider authority before retrying input.");
@@ -1214,11 +1202,14 @@ export class FileSchedulerStoreAdapter {
1214
1202
  }
1215
1203
  }
1216
1204
  }
1205
+ binding = admitOwnedProviderInput(store, binding, input);
1217
1206
  store.saveTaskRoleSessionSet(updateTaskRoleProviderRuntime(sessions, beginProviderTurn(binding, {
1218
1207
  ...(input.runId === undefined ? {} : { runId: input.runId }),
1219
1208
  attemptId: input.attemptId,
1220
1209
  authorityEpoch: input.authorityEpoch,
1221
- submittedAt: input.now.toISOString()
1210
+ submittedAt: input.now.toISOString(),
1211
+ input: binding.retry?.currentAttemptId === input.attemptId ? binding.retry.input : ownedProviderInput(input),
1212
+ retrySupported: input.retrySupported
1222
1213
  }), input.now));
1223
1214
  });
1224
1215
  }
@@ -1230,8 +1221,11 @@ export class FileSchedulerStoreAdapter {
1230
1221
  if (input.runId !== undefined || sessions == null || binding?.run?.attemptId !== input.attemptId) {
1231
1222
  throw new Error("Global input submission is no longer current.");
1232
1223
  }
1233
- store.saveGlobalRoleSessionSet(updateGlobalRoleProviderRuntime(sessions, settleProviderTurnSubmission(binding, { attemptId: input.attemptId, status: input.status,
1234
- reason: input.reason, resolvedAt: input.now.toISOString() }), input.now));
1224
+ let resolved = settleProviderTurnSubmission(binding, { attemptId: input.attemptId, status: input.status,
1225
+ reason: input.reason, resolvedAt: input.now.toISOString() });
1226
+ resolved = this.retrySubmissionResolution(resolved, input, sessions.sessions[sessions.activeAgentId]?.adapterId);
1227
+ store.saveGlobalRoleSessionSet(updateGlobalRoleProviderRuntime(sessions, resolved, input.now));
1228
+ settleGlobalRetryInput(store, input.roleName, resolved, input.now);
1235
1229
  const message = store.listGlobalRoleMessages(input.roleName).find(entry => input.attemptId === `global-input:${input.roleName}/${entry.id}`);
1236
1230
  if (message !== undefined && message.delivery?.via !== "provider") {
1237
1231
  const outcome = input.status === "delivery-unknown" ? "delivery-unknown" : "rejected";
@@ -1239,7 +1233,7 @@ export class FileSchedulerStoreAdapter {
1239
1233
  requestId: message.inputControl?.requestId ?? message.interruptThen.requestId,
1240
1234
  receiptId: input.attemptId, outcome, observedAt: input.now.toISOString()
1241
1235
  } };
1242
- store.updateGlobalRoleMessage(input.status === "rejected" && updated.delivery === undefined
1236
+ store.updateGlobalRoleMessage(input.status === "rejected" && updated.delivery === undefined && !providerRetryPending(resolved)
1243
1237
  ? markGlobalRoleMessageNotDelivered(updated, input.reason, input.now) : updated);
1244
1238
  }
1245
1239
  });
@@ -1257,20 +1251,18 @@ export class FileSchedulerStoreAdapter {
1257
1251
  || binding.run?.attemptId !== input.attemptId) {
1258
1252
  throw new Error("Agent Host Provider Turn submission is no longer current.");
1259
1253
  }
1260
- const updated = settleProviderTurnSubmission(binding, {
1254
+ let updated = settleProviderTurnSubmission(binding, {
1261
1255
  attemptId: input.attemptId,
1262
1256
  status: input.status,
1263
1257
  reason: input.reason,
1264
1258
  resolvedAt: input.now.toISOString()
1265
1259
  });
1260
+ updated = this.retrySubmissionResolution(updated, input, sessions.sessions[sessions.activeAgentId]?.adapterId);
1266
1261
  store.saveTaskRoleSessionSet(updateTaskRoleProviderRuntime(sessions, updated, input.now));
1267
- if (input.runId === undefined)
1268
- return;
1269
- const run = store.getRun(input.taskId, input.runId);
1262
+ const run = input.runId === undefined ? null : store.getRun(input.taskId, input.runId);
1270
1263
  const session = sessions.sessions[sessions.activeAgentId];
1271
- const driver = run === null
1272
- ? null
1273
- : this.drivers.findByAdapterId(run.effective.adapterId);
1264
+ const adapterId = run?.effective.adapterId ?? session?.adapterId;
1265
+ const driver = adapterId === undefined ? null : this.drivers.findByAdapterId(adapterId);
1274
1266
  const error = standardAgentError({
1275
1267
  source: "driver",
1276
1268
  phase: "turn-submit",
@@ -1282,41 +1274,46 @@ export class FileSchedulerStoreAdapter {
1282
1274
  raw: input.raw,
1283
1275
  inputDisposition: input.status === "delivery-unknown" ? "unknown" : "not-accepted"
1284
1276
  });
1285
- const errorEvent = createTaskEvent(store.nextEventId(input.taskId), input.taskId, "runtime.agent-error", {
1286
- sourceEventId: input.attemptId,
1287
- runId: input.runId,
1288
- roleName: input.roleName,
1277
+ const { event: errorEvent, created } = recordTaskAgentError(store, {
1278
+ taskId: input.taskId, roleName: input.roleName, sourceEventId: input.attemptId,
1289
1279
  agentId: run?.effective.agentId ?? sessions.activeAgentId,
1290
- adapterId: run?.effective.adapterId ?? session?.adapterId ?? "unknown",
1291
- driverId: driver?.id ?? "unknown",
1292
- // No native Turn exists at submission resolution, and the Session
1293
- // facts may be absent. An unknown fact is an absent key: an empty
1294
- // string reads back as a real value and cannot be told apart from
1295
- // one the Provider genuinely reported.
1296
- ...optionalEventFields({
1280
+ adapterId: adapterId ?? "unknown", driverId: driver?.id ?? "unknown",
1281
+ error, effective: run?.effective ?? session?.effective,
1282
+ evidence: {
1283
+ attemptId: input.attemptId,
1284
+ runId: input.runId,
1297
1285
  nativeSessionId: session?.nativeSessionId
1298
- }),
1299
- source: error.source,
1300
- phase: error.phase,
1301
- category: error.category,
1302
- code: error.code,
1303
- message: error.message,
1304
- raw: error.raw,
1305
- inputDisposition: error.inputDisposition,
1306
- sessionDisposition: error.sessionDisposition
1286
+ }
1307
1287
  }, input.now);
1308
- store.saveEvent(input.taskId, errorEvent);
1309
- if (input.status === "deferred")
1288
+ if (!created || input.status === "deferred" || providerRetryPending(updated))
1310
1289
  return;
1311
- const route = input.roleName === "leader"
1312
- ? { kind: "operator" }
1313
- : { kind: "role", taskId: input.taskId, roleName: "leader" };
1314
- enqueueWork(store, route, input.roleName === "leader"
1290
+ enqueueSupervisorEvent(store, errorEvent, input.roleName === "leader" ? "operator" : "leader", input.roleName === "leader"
1315
1291
  ? "leader-turn-submission-error"
1316
- : wakeReason("agent-error", errorEvent.id), input.now, [{ type: "event", taskId: input.taskId, id: errorEvent.id }], {
1317
- source: driver?.id ?? "agent-host",
1318
- dedupeKey: `agent-error:${input.taskId}:${input.attemptId}`
1319
- });
1292
+ : wakeReason("agent-error", errorEvent.id), input.now);
1293
+ });
1294
+ }
1295
+ retrySubmissionResolution(binding, input, adapterId) {
1296
+ if (input.status === "deferred")
1297
+ return deferProviderRetry(binding, input.now.getTime());
1298
+ const driver = adapterId === undefined ? null : this.drivers.findByAdapterId(adapterId);
1299
+ const classification = driver?.runtime.mapError({ message: input.reason, raw: input.raw });
1300
+ const error = standardAgentError({
1301
+ source: "driver", phase: "turn-submit", classification,
1302
+ message: input.reason, raw: input.raw,
1303
+ inputDisposition: input.status === "delivery-unknown" ? "unknown" : "not-accepted"
1304
+ });
1305
+ // Native preflight issued no mutation. Transient metadata failures may
1306
+ // cool down within the same deadline; unavailable proof needs an Agent.
1307
+ const noProviderWrite = input.status === "rejected" && input.noProviderWrite === true;
1308
+ if (noProviderWrite && classification?.retryable !== true) {
1309
+ const recorded = binding.run === null ? binding : {
1310
+ ...binding, run: { ...binding.run, failure: { error, ref: input.attemptId } }
1311
+ };
1312
+ return deferProviderRetry(recorded, input.now.getTime(), input.reason);
1313
+ }
1314
+ return recordProviderFailure(binding, {
1315
+ error,
1316
+ failureRef: input.attemptId, at: input.now.getTime(), noProviderWrite
1320
1317
  });
1321
1318
  }
1322
1319
  getProviderAuthorityFence(input) {
@@ -1356,15 +1353,19 @@ export class FileSchedulerStoreAdapter {
1356
1353
  }
1357
1354
  recordAgentError(input, now) {
1358
1355
  return this.store.transaction((store) => {
1359
- const run = store.getRun(input.taskId, input.runId);
1356
+ if (input.runId === undefined && input.attemptId === undefined) {
1357
+ throw new Error("An Agent error needs an exact Run or notification attempt.");
1358
+ }
1359
+ const run = input.runId === undefined ? null : store.getRun(input.taskId, input.runId);
1360
1360
  const sessionSet = store.getTaskRoleSessionSet(input.taskId, input.roleName);
1361
- const sessionAgentId = run?.effective.agentId ?? sessionSet?.activeAgentId;
1361
+ const effective = input.effective ?? run?.effective;
1362
+ const sessionAgentId = effective?.agentId ?? sessionSet?.activeAgentId;
1362
1363
  const session = sessionAgentId === undefined
1363
1364
  ? undefined
1364
1365
  : sessionSet?.sessions[sessionAgentId];
1365
- const driver = run === null
1366
+ const driver = effective === undefined
1366
1367
  ? null
1367
- : this.drivers.findByAdapterId(run.effective.adapterId);
1368
+ : this.drivers.findByAdapterId(effective.adapterId);
1368
1369
  const error = standardAgentError({
1369
1370
  source: input.source,
1370
1371
  phase: input.phase,
@@ -1381,57 +1382,22 @@ export class FileSchedulerStoreAdapter {
1381
1382
  ? {}
1382
1383
  : { sessionDisposition: input.sessionDisposition })
1383
1384
  });
1384
- const duplicate = [...store.listEvents(input.taskId)].reverse().find((event) => (event.type === "runtime.agent-error"
1385
- && event.payload.runId === input.runId
1386
- && event.payload.roleName === input.roleName
1387
- && event.payload.phase === input.phase
1388
- && event.payload.attemptId === input.attemptId
1389
- && event.payload.source === error.source
1390
- && event.payload.inputDisposition === error.inputDisposition
1391
- && event.payload.sessionDisposition === error.sessionDisposition
1392
- && event.payload.registrationDisposition === input.registrationDisposition
1393
- && event.payload.hostState === input.hostState
1394
- && (input.attemptId === undefined
1395
- ? event.payload.raw === error.raw
1396
- : event.payload.message === error.message
1397
- && event.payload.errorName === input.errorName
1398
- && event.payload.causeName === input.causeName)));
1399
- // Re-reading one failed attempt may add a different caller stack, not a
1400
- // new execution fact. Preserve its first full cause without multiplying
1401
- // notifications; changed disposition/identity/diagnostic remains visible.
1402
- if (duplicate !== undefined)
1403
- return duplicate.id;
1404
- const event = createTaskEvent(store.nextEventId(input.taskId), input.taskId, "runtime.agent-error", {
1405
- sourceEventId: `${input.runId}:${input.phase}${input.attemptId === undefined ? "" : `:${input.attemptId}`}`,
1406
- runId: input.runId,
1407
- roleName: input.roleName,
1408
- agentId: run?.effective.agentId ?? session?.agentId ?? "unknown",
1409
- adapterId: run?.effective.adapterId ?? session?.adapterId ?? "unknown",
1410
- driverId: driver?.id ?? "unknown",
1411
- source: error.source,
1412
- phase: error.phase,
1413
- category: error.category,
1414
- code: error.code,
1415
- message: error.message,
1416
- raw: error.raw,
1417
- inputDisposition: error.inputDisposition,
1418
- sessionDisposition: error.sessionDisposition,
1419
- // Structured facts from the failing operation. Absent keys stay
1420
- // absent rather than becoming an empty string, so a reader can tell
1421
- // "the Host did not report this" from "the Host reported nothing".
1422
- // The Session identities follow the same rule: this failure can
1423
- // happen before any Session record exists, and there is no native
1424
- // AgentRun to name at all.
1425
- ...optionalEventFields({
1426
- nativeSessionId: session?.nativeSessionId,
1427
- errorName: input.errorName,
1428
- causeName: input.causeName,
1429
- hostState: input.hostState,
1430
- attemptId: input.attemptId,
1385
+ const { event, created } = recordTaskAgentError(store, {
1386
+ taskId: input.taskId, roleName: input.roleName,
1387
+ sourceEventId: `${input.runId ?? input.attemptId}:${input.phase}${input.runId === undefined || input.attemptId === undefined ? "" : `:${input.attemptId}`}`,
1388
+ agentId: effective?.agentId ?? session?.agentId ?? "unknown",
1389
+ adapterId: effective?.adapterId ?? session?.adapterId ?? "unknown",
1390
+ driverId: driver?.id ?? "unknown", error, effective,
1391
+ evidence: {
1392
+ runId: input.runId, attemptId: input.attemptId, nativeSessionId: session?.nativeSessionId,
1393
+ errorName: input.errorName, causeName: input.causeName, hostState: input.hostState,
1431
1394
  registrationDisposition: input.registrationDisposition
1432
- })
1395
+ }
1433
1396
  }, now);
1434
- store.saveEvent(input.taskId, event);
1397
+ if (!created)
1398
+ return event.id;
1399
+ if (store.getTask(input.taskId)?.status === "archived")
1400
+ return event.id;
1435
1401
  if (input.phase === "turn-submit" && error.inputDisposition === "unknown"
1436
1402
  && input.attemptId !== undefined && sessionSet?.providerBinding?.run?.attemptId === input.attemptId
1437
1403
  && sessionSet.providerBinding.run.status === "submitting") {
@@ -1445,18 +1411,7 @@ export class FileSchedulerStoreAdapter {
1445
1411
  return event.id;
1446
1412
  const leaderCannotReceive = input.roleName === "leader"
1447
1413
  && ["host-start", "session-start", "session-restore", "turn-submit"].includes(input.phase);
1448
- if (!leaderCannotReceive) {
1449
- enqueueWork(store, { kind: "role", taskId: input.taskId, roleName: "leader" }, wakeReason("agent-error", event.id), now, [{ type: "event", taskId: input.taskId, id: event.id }], {
1450
- source: driver?.id ?? input.source,
1451
- dedupeKey: `agent-error:${input.taskId}:${input.runId}:${input.phase}:${event.id}`
1452
- });
1453
- }
1454
- if (leaderCannotReceive) {
1455
- enqueueWork(store, { kind: "operator" }, "leader-agent-error", now, [{ type: "event", taskId: input.taskId, id: event.id }], {
1456
- source: driver?.id ?? input.source,
1457
- dedupeKey: `leader-agent-error:${input.taskId}:${input.runId}:${event.id}`
1458
- });
1459
- }
1414
+ enqueueSupervisorEvent(store, event, leaderCannotReceive ? "operator" : "leader", leaderCannotReceive ? "leader-agent-error" : wakeReason("agent-error", event.id), now);
1460
1415
  return event.id;
1461
1416
  });
1462
1417
  }
@@ -1750,6 +1705,13 @@ export class FileSchedulerStoreAdapter {
1750
1705
  const task = store.getTask(taskId);
1751
1706
  if (task == null || !["active", "draft"].includes(task.status) || task.executionGate.state !== "enabled")
1752
1707
  return null;
1708
+ // Admission refuses input while this Session is being cleaned up.
1709
+ // Leave the original batch pending for its successor instead of
1710
+ // claiming a notification that cannot legally reach the Provider.
1711
+ if (hasRuntimeCleanupObligation(store.getWorkMailbox(runtimeLifecycleTarget({
1712
+ scope: "task", taskId, roleName: "leader"
1713
+ }))))
1714
+ return null;
1753
1715
  const target = { kind: "role", taskId, roleName: "leader" };
1754
1716
  let mailbox = store.getWorkMailbox(target);
1755
1717
  if (mailbox === null)
@@ -1775,8 +1737,10 @@ export class FileSchedulerStoreAdapter {
1775
1737
  return null;
1776
1738
  }
1777
1739
  if (native?.status === "rejected" || previous?.payload.outcome === "rejected") {
1778
- this.settleLeaderNotification(taskId, attemptId, "rejected", now);
1779
- return null;
1740
+ if (previous?.payload.outcome !== "rejected") {
1741
+ this.settleLeaderNotification(taskId, attemptId, "rejected", now);
1742
+ }
1743
+ return { wakeId, attemptId, disposition: "rejected" };
1780
1744
  }
1781
1745
  if (native?.status === "submitting")
1782
1746
  return { wakeId, attemptId, disposition: "pending" };
@@ -1851,7 +1815,7 @@ export class FileSchedulerStoreAdapter {
1851
1815
  return { wakeId, attemptId, disposition: "submit" };
1852
1816
  });
1853
1817
  }
1854
- settleLeaderNotification(taskId, attemptId, outcome, now, detail) {
1818
+ settleLeaderNotification(taskId, attemptId, outcome, now, detail, failure) {
1855
1819
  this.store.transaction((store) => {
1856
1820
  const target = { kind: "role", taskId, roleName: "leader" };
1857
1821
  const mailbox = store.getWorkMailbox(target);
@@ -1861,19 +1825,35 @@ export class FileSchedulerStoreAdapter {
1861
1825
  return;
1862
1826
  if (!store.listEvents(taskId).some((event) => event.type === "notification.delivery"
1863
1827
  && event.payload.attemptId === attemptId && event.payload.outcome === outcome)) {
1864
- store.saveEvent(taskId, createTaskEvent(store.nextEventId(taskId), taskId, "notification.delivery", { attemptId, outcome, ...(detail === undefined ? {} : { detail }) }, now));
1828
+ // Native ingress may already have persisted the same rejection. Reuse
1829
+ // that original failure rather than reporting it twice from the caller.
1830
+ const existing = store.listEventsByType(taskId, ["runtime.agent-error"])
1831
+ .find(event => event.payload.roleName === "leader"
1832
+ && (event.payload.attemptId === attemptId || event.payload.sourceEventId === attemptId));
1833
+ const errorEventId = existing?.id ?? (failure !== undefined
1834
+ && (outcome === "rejected" || outcome === "unknown")
1835
+ ? this.recordAgentError({
1836
+ taskId, roleName: "leader", attemptId, effective: failure.effective,
1837
+ source: "host", phase: failure.phase,
1838
+ message: detail ?? `Notification ${outcome}.`, raw: failure.raw,
1839
+ inputDisposition: outcome === "unknown" ? "unknown" : "not-accepted",
1840
+ ...(failure.phase === "session-start" ? { registrationDisposition: "not-committed" } : {})
1841
+ }, now) : undefined);
1842
+ store.saveEvent(taskId, createTaskEvent(store.nextEventId(taskId), taskId, "notification.delivery", { attemptId, outcome, ...(detail === undefined ? {} : { detail }),
1843
+ ...(errorEventId === undefined ? {} : { errorEventId }) }, now));
1865
1844
  }
1866
1845
  if (store.getTask(taskId)?.status === "archived")
1867
1846
  return;
1868
- if (outcome !== "accepted" && outcome !== "rejected")
1847
+ // Rejection proves nondelivery, not consumption of the original input.
1848
+ // Keep the exact claim as the existing recovery/completion boundary.
1849
+ // An explicit retry or Session replacement can release it later.
1850
+ if (outcome !== "accepted")
1869
1851
  return;
1870
1852
  store.saveWorkMailbox(completeProcessing(mailbox, attemptId));
1871
- if (outcome === "accepted") {
1872
- const wakeId = processing.owner.slice("leader-notification:".length);
1873
- const wake = store.listTaskWakes(taskId).find((entry) => entry.id === wakeId);
1874
- if (wake !== undefined)
1875
- store.saveTaskWake(taskId, markTaskWakeConsumed(wake, now));
1876
- }
1853
+ const wakeId = processing.owner.slice("leader-notification:".length);
1854
+ const wake = store.listTaskWakes(taskId).find((entry) => entry.id === wakeId);
1855
+ if (wake !== undefined)
1856
+ store.saveTaskWake(taskId, markTaskWakeConsumed(wake, now));
1877
1857
  });
1878
1858
  }
1879
1859
  saveRoleRunPrepared(input) {
@@ -2085,12 +2065,6 @@ export class FileSchedulerStoreAdapter {
2085
2065
  let sessions = store.getTaskRoleSessionSet(input.taskId, input.roleName)
2086
2066
  ?? createRoleSessionSet({ scope: "task", taskId: input.taskId, roleName: input.roleName }, input.agentId, now);
2087
2067
  const canonicalRunId = input.nativeTurnId ?? resolved.nativeTurnId;
2088
- const existing = sessions.sessions[input.agentId];
2089
- const owner = {
2090
- scope: "task",
2091
- taskId: input.taskId,
2092
- roleName: input.roleName
2093
- };
2094
2068
  assertConsistentTerminal(store, input, observedRun);
2095
2069
  // A historical operation failure stays failed. The immutable terminal
2096
2070
  // observation retains the late report for explicit Leader adoption.
@@ -2140,6 +2114,12 @@ export class FileSchedulerStoreAdapter {
2140
2114
  && sessions.providerBinding !== null) {
2141
2115
  sessions = updateTaskRoleProviderRuntime(sessions, updateProviderConversationRecoverability(sessions.providerBinding, "unrecoverable"), now);
2142
2116
  }
2117
+ if (input.observation?.kind === "turn.failed" && input.observation.payload.failure !== undefined
2118
+ && sessions.providerBinding !== null) {
2119
+ sessions = updateTaskRoleProviderRuntime(sessions, recordProviderFailure(sessions.providerBinding, {
2120
+ error: input.observation.payload.failure.error, failureRef: input.observation.eventId, at: now.getTime()
2121
+ }), now);
2122
+ }
2143
2123
  store.saveTaskRoleSessionSet(sessions);
2144
2124
  let terminalRun;
2145
2125
  if (recordedProviderTurn && observedRun?.status === "active") {
@@ -2482,6 +2462,14 @@ export class FileSchedulerStoreAdapter {
2482
2462
  return "obsolete";
2483
2463
  }
2484
2464
  store.saveTaskRoleSessionSet(recordStructuredProviderAcceptance(sessions, input, now));
2465
+ const retry = binding.retry;
2466
+ if (retry?.currentAttemptId === ordinaryAttemptId && retry.input.kind === "wake") {
2467
+ const originalWakeId = retry.input.wakeId;
2468
+ const original = store.listTaskWakes(input.fence.taskId).find(w => w.id === originalWakeId);
2469
+ if (original !== undefined && original.status !== "consumed") {
2470
+ store.saveTaskWake(input.fence.taskId, markTaskWakeConsumed(original, now));
2471
+ }
2472
+ }
2485
2473
  return "applied";
2486
2474
  }
2487
2475
  }
@@ -3149,28 +3137,6 @@ function requireRole(store, taskId, roleName) {
3149
3137
  throw new Error(`Role not found: ${taskId}/${roleName}.`);
3150
3138
  return role;
3151
3139
  }
3152
- function runLaunchEventPayload(run) {
3153
- return {
3154
- runId: run.id,
3155
- role: run.roleName,
3156
- purpose: run.purpose,
3157
- mode: run.mode,
3158
- agent: `${run.effective.agentId}/${run.effective.adapterId}`,
3159
- component: run.effective.component,
3160
- effectiveRevision: String(run.effective.sourceDesiredRevision),
3161
- profileAccess: run.effective.profileAccess,
3162
- effectivePermission: run.effective.permission.strategy,
3163
- writeProjectIds: run.effective.writeProjectIds.join(",") || "none"
3164
- };
3165
- }
3166
- /**
3167
- * Keeps only the fields the caller actually knew. Event payloads are a
3168
- * string map, so an unknown fact has to be an absent key: writing `""` would
3169
- * claim the Host reported an empty value.
3170
- */
3171
- function optionalEventFields(fields) {
3172
- return Object.fromEntries(Object.entries(fields).filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0));
3173
- }
3174
3140
  function runtimeObservationTelemetryEntry(input) {
3175
3141
  return {
3176
3142
  taskId: input.fence.taskId,