@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,57 +1,60 @@
1
- import { reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveRuntimeHealth, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
2
1
  import { isDeepStrictEqual } from "node:util";
3
- import { controllerSocketPath } from "../core/controllerEndpoint.js";
4
2
  import { AGENT_OPERATIONAL_ENVIRONMENT_NAMES, NATIVE_AGENT_ENVIRONMENT_NAMES, nativeAgentEnvironmentNames, YUI_MANAGED_RUNTIME_ENVIRONMENT_NAMES } from "../agent/launchEnvironment.js";
5
- import { hasRuntimeCleanupObligation, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
6
- import { agentProcessReadinessProbe, ExecutorRegistry } from "../executor/executorRegistry.js";
7
- import { activeLiveRoleAgentSession, roleAgentSessionResumeMode } from "../executor/agentExecutor.js";
8
- import { roleSessionMayContinue, effectiveLaunchConfig, resolveEffectiveLaunch } from "../executor/effectiveLaunch.js";
3
+ import { runPurposeAdmitsTaskState } from "../agentRun/agentRun.js";
4
+ import { reconciliationIntervalMilliseconds, resolveAgentLaunchInactivityTimeoutSeconds, resolveControllerTaskConcurrency, resolveDeliveryTimeoutSeconds, resolveRuntimeHealth, resolveTmuxBin, resolveTmuxHistoryLimit } from "../config/yuiConfig.js";
5
+ import { controllerSocketPath } from "../core/controllerEndpoint.js";
6
+ import { createTaskEvent } from "../event/taskEvent.js";
9
7
  import { AgentConfigurationCatalogService, validateAgentLaunchConfiguration } from "../executor/agentConfigurationCatalog.js";
10
- import { isTaskOwnedWorkspace, sameManagedWorkspaceIdentity } from "../worktree/managedWorkspace.js";
8
+ import { activeLiveRoleAgentSession, roleAgentSessionResumeMode } from "../executor/agentExecutor.js";
9
+ import { effectiveLaunchConfig, resolveEffectiveLaunch, roleSessionMayContinue } from "../executor/effectiveLaunch.js";
10
+ import { agentProcessReadinessProbe, ExecutorRegistry } from "../executor/executorRegistry.js";
11
11
  import { FileRoleLaunchPlanner } from "../executor/fileRoleLaunchPlanner.js";
12
+ import { createKernelPorts } from "../kernel/kernelPorts.js";
13
+ import { createGlobalRoleMessage } from "../message/message.js";
14
+ import { FileTaskWorkspacePreparer } from "../repository/taskWorkspacePreparer.js";
15
+ import { createResourceAutoGc } from "../resources/autoResourceGc.js";
16
+ import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
17
+ import { assertExecutionEnvironmentCurrent } from "../runtime/executionEnvironment.js";
18
+ import { appendGlobalProcessExitObservation } from "../runtime/globalProcessExitStore.js";
19
+ import { AgentHostPromptPushAdapter, FileTaskRuntimeIsolation, ProviderContinuationReconciliationService, TmuxSessionHost } from "../runtime/index.js";
20
+ import { launchBrokerForHome } from "../runtime/launchBroker.js";
21
+ import { hasRuntimeCleanupObligation, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
22
+ import { classifyRuntimeProcessExit, validateRuntimeProcessExitObservation } from "../runtime/processExitObservation.js";
23
+ import { replayRuntimeProcessExitOutbox } from "../runtime/processExitOutbox.js";
24
+ import { providerRetryPrompt } from "../runtime/providerRetry.js";
25
+ import { createRuntimeObservation, runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
12
26
  import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
13
27
  import { managedRuntimeRoot } from "../storage/homeLayout.js";
14
28
  import { SqliteTaskStore } from "../storage/sqliteStore.js";
15
29
  import { AsyncTaskStoreClient, resolveStoreWorkerEnabledForHome } from "../storage/storeRpc.js";
16
- import { FileTaskWorkspacePreparer } from "../repository/taskWorkspacePreparer.js";
30
+ import { SurfaceContributions } from "../surface/surfaceContributions.js";
31
+ import { taskOwnsManagedWorkspace } from "../task/task.js";
32
+ import { openSchedulerTelemetry } from "../telemetry/telemetryWiring.js";
17
33
  import { NodeCommandExecutor } from "../tmux/commandExecutor.js";
18
34
  import { TmuxManager, yuiTmuxServerName } from "../tmux/tmuxManager.js";
19
- import { AgentHostPromptPushAdapter, FileTaskRuntimeIsolation, TmuxSessionHost, ProviderContinuationReconciliationService } from "../runtime/index.js";
20
- import { startFileTaskController } from "./controller.js";
21
- import { AgentHostProviderTurnFenceError, AgentHostProviderSessionBusyError, FileSchedulerStoreAdapter } from "./fileSchedulerStoreAdapter.js";
22
- import { openSchedulerTelemetry } from "../telemetry/telemetryWiring.js";
23
- import { createFileArtifactPort, createLinuxProcessPort, DurableJobSupervisor } from "./jobSupervisor.js";
24
- import { authorizeJobStart } from "./jobControl.js";
25
- import { createKernelPorts } from "../kernel/kernelPorts.js";
26
- import { createCapabilityDispatcher } from "./capabilityBridge.js";
27
35
  import { createControllerWeb } from "../web/controllerWeb.js";
28
- import { createWebTaskSurface } from "../web/webTaskSurface.js";
29
- import { SurfaceContributions } from "../surface/surfaceContributions.js";
30
36
  import { TmuxWebTerminalService } from "../web/tmuxWebTerminal.js";
31
- import { FileTaskWorkflowRuntime } from "./clientRuntime.js";
32
- import { FileRuntimeEventInbox } from "./runtimeEventInbox.js";
37
+ import { createWebTaskSurface } from "../web/webTaskSurface.js";
38
+ import { isTaskOwnedWorkspace, sameManagedWorkspaceIdentity } from "../worktree/managedWorkspace.js";
33
39
  import { AgentRuntimeObserver } from "./agentRuntimeObserver.js";
34
- import { AsyncRuntimeEventProcessor, FileRuntimeEventProcessor, createAsyncRuntimeObserver } from "./runtimeEventProcessor.js";
35
- import { RuntimeLaunchCoordinator } from "./runtimeLaunchCoordinator.js";
40
+ import { createCapabilityDispatcher } from "./capabilityBridge.js";
41
+ import { FileTaskWorkflowRuntime } from "./clientRuntime.js";
42
+ import { startFileTaskController } from "./controller.js";
36
43
  import { ephemeralDomainFromEnvironment, recordEphemeralTmuxTarget } from "./domainIdentity.js";
37
44
  import { createEphemeralResourceReaper } from "./ephemeralResourceReaper.js";
45
+ import { AgentHostProviderSessionBusyError, AgentHostProviderTurnFenceError, FileSchedulerStoreAdapter } from "./fileSchedulerStoreAdapter.js";
46
+ import { deliverGlobalInputs } from "./globalInputDelivery.js";
47
+ import { authorizeJobStart } from "./jobControl.js";
48
+ import { createFileArtifactPort, createLinuxProcessPort, DurableJobSupervisor } from "./jobSupervisor.js";
49
+ import { createProviderRetryHooks } from "./providerRetryDelivery.js";
50
+ import { createRuntimeResourceActivityTracker } from "./resourceInventory.js";
38
51
  import { scanControllerResourceInventory } from "./resourceInventoryLinux.js";
39
52
  import { ResourceInventoryClient } from "./resourceInventoryRpc.js";
40
- import { createResourceAutoGc } from "../resources/autoResourceGc.js";
41
- import { createRuntimeResourceActivityTracker } from "./resourceInventory.js";
53
+ import { FileRuntimeEventInbox } from "./runtimeEventInbox.js";
54
+ import { AsyncRuntimeEventProcessor, createAsyncRuntimeObserver, FileRuntimeEventProcessor } from "./runtimeEventProcessor.js";
55
+ import { RuntimeLaunchCoordinator } from "./runtimeLaunchCoordinator.js";
42
56
  import { SessionOwnerReconciliation } from "./sessionOwnerReconciliation.js";
43
- import { launchBrokerForHome } from "../runtime/launchBroker.js";
44
- import { assertExecutionEnvironmentCurrent } from "../runtime/executionEnvironment.js";
45
- import { classifyRuntimeProcessExit, validateRuntimeProcessExitObservation } from "../runtime/processExitObservation.js";
46
- import { replayRuntimeProcessExitOutbox } from "../runtime/processExitOutbox.js";
47
- import { appendGlobalProcessExitObservation } from "../runtime/globalProcessExitStore.js";
48
- import { deliverGlobalInputs } from "./globalInputDelivery.js";
49
- import { createGlobalRoleMessage } from "../message/message.js";
50
- import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
51
- import { createRuntimeObservation, runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
52
- import { createTaskEvent } from "../event/taskEvent.js";
53
- import { runPurposeAdmitsTaskState } from "../agentRun/agentRun.js";
54
- import { taskOwnsManagedWorkspace } from "../task/task.js";
57
+ import { readTaskAgentCapabilities } from "./agentCapabilities.js";
55
58
  /** Production composition root for the current SQLite TaskStore + tmux Controller. */
56
59
  export async function startFileTaskControllerRuntime(home, options = {}) {
57
60
  // The current Home always uses SQLite. The persistence worker is enabled by
@@ -84,9 +87,13 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
84
87
  : undefined;
85
88
  let closeKernel = async () => { };
86
89
  let closeWeb = async () => { };
90
+ let closeTelemetry = async () => { };
87
91
  try {
92
+ const telemetry = options.schedulerStore === undefined
93
+ ? openSchedulerTelemetry(home, store.getConfig(), asyncStoreClient) : null;
94
+ closeTelemetry = () => telemetry?.sink.close() ?? Promise.resolve();
88
95
  const schedulerStore = options.schedulerStore
89
- ?? new FileSchedulerStoreAdapter(store, openSchedulerTelemetry(home, store.getConfig()));
96
+ ?? new FileSchedulerStoreAdapter(store, telemetry);
90
97
  const domainIdentity = options.domainIdentity
91
98
  ?? ephemeralDomainFromEnvironment(options.environment ?? process.env);
92
99
  const planner = options.planner ?? new FileRoleLaunchPlanner(home, store, {
@@ -385,7 +392,6 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
385
392
  environment: options.environment ?? process.env, onError: options.onError
386
393
  });
387
394
  const webSurface = createWebTaskSurface(store, { runtime: {
388
- notifyStateChanged: (taskId) => runningRuntime?.signal(`task:${taskId}`),
389
395
  notifyMailboxChanged: (target) => {
390
396
  if (target.kind === "role")
391
397
  runningRuntime?.signal(`role:${target.taskId}/${target.roleName}`);
@@ -452,8 +458,10 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
452
458
  const continuationReconciler = options.continuationMetadata === undefined
453
459
  ? undefined
454
460
  : new ProviderContinuationReconciliationService(store, schedulerStore, options.continuationMetadata);
455
- const running = await startFileTaskController(home, schedulerStore, delivery, (method, params) => method === "web.start" || method === "web.stop" || method === "web.status"
456
- ? web.dispatch(method, params) : lifecycleDispatcher(method, params), {
461
+ const running = await startFileTaskController(home, schedulerStore, delivery, (method, params) => method === "task.role-capabilities"
462
+ ? readTaskAgentCapabilities(store, catalogs, params)
463
+ : method === "web.start" || method === "web.stop" || method === "web.status"
464
+ ? web.dispatch(method, params) : lifecycleDispatcher(method, params), {
457
465
  intervalMs: options.intervalMs
458
466
  ?? reconciliationIntervalMilliseconds(store.getConfig().reconciliationIntervalSeconds),
459
467
  signalWindowMs: options.signalWindowMs,
@@ -470,6 +478,26 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
470
478
  now: options.now,
471
479
  onError: options.onError,
472
480
  lifecycleHost,
481
+ providerRetry: createProviderRetryHooks(home, store, {
482
+ now: options.now,
483
+ onError: options.onError,
484
+ snapshotTaskCandidate: async (run) => {
485
+ if (run.purpose !== "review" || run.reviewRoundId === undefined)
486
+ return undefined;
487
+ const round = store.getReviewRound(run.taskId, run.reviewRoundId);
488
+ if (round?.scope !== "task")
489
+ return undefined;
490
+ const task = store.getTask(run.taskId);
491
+ const workspace = store.getTaskWorkspace(run.taskId);
492
+ if (task === null || workspace === null || !(workspacePreparer instanceof FileTaskWorkspacePreparer)) {
493
+ throw new Error("Task-final retry requires an observable authoritative Task workspace.");
494
+ }
495
+ const snapshot = await workspacePreparer.snapshotDirectTaskMain(workspace, task.projectBindings.map(p => p.projectId));
496
+ return { schemaVersion: 1, projects: snapshot.projects.map(p => ({
497
+ projectId: p.projectId, commit: p.headCommit
498
+ })) };
499
+ }
500
+ }),
473
501
  jobSupervisor,
474
502
  globalInputDelivery: () => deliverGlobalInputs(home, store, async (roleName) => {
475
503
  await lifecycleDispatcher("runtime.ensure-role-session", { scope: "global", roleName });
@@ -521,12 +549,12 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
521
549
  }
522
550
  let resourceClose;
523
551
  const closeResources = () => {
524
- resourceClose ??= Promise.all([
552
+ resourceClose ??= closeTelemetry().finally(() => Promise.all([
525
553
  web.close(),
526
554
  kernel.close(),
527
555
  asyncStoreClient?.close() ?? Promise.resolve(),
528
556
  inventoryClient?.close() ?? Promise.resolve()
529
- ]).then(() => undefined).finally(() => {
557
+ ])).then(() => undefined).finally(() => {
530
558
  ownedStore?.close();
531
559
  });
532
560
  return resourceClose;
@@ -561,6 +589,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
561
589
  catch (error) {
562
590
  // The socket may never have opened. Startup failure must still release
563
591
  // this attempt's workers/instances instead of leaving an uncallable process.
592
+ await closeTelemetry().catch(() => undefined);
564
593
  await Promise.allSettled([
565
594
  closeWeb(),
566
595
  closeKernel(),
@@ -617,6 +646,8 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
617
646
  authorityEpoch: value.authorityEpoch,
618
647
  authorityOwner: value.authorityOwner,
619
648
  holderId: value.holderId,
649
+ boundedText: value.boundedText,
650
+ retrySupported: value.retrySupported,
620
651
  now: value.now
621
652
  });
622
653
  }
@@ -628,7 +659,15 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
628
659
  }
629
660
  throw error;
630
661
  }
631
- return { recorded: true };
662
+ const binding = (value.taskId === undefined
663
+ ? store.getGlobalRoleSessionSet(value.roleName)
664
+ : store.getTaskRoleSessionSet(value.taskId, value.roleName))?.providerBinding;
665
+ const retry = binding?.retry;
666
+ return { recorded: true, ...(retry?.currentAttemptId === value.attemptId && value.boundedText !== undefined
667
+ ? { retryInput: {
668
+ text: providerRetryPrompt(retry, value.boundedText),
669
+ ...(retry.failedNativeTurnId === undefined ? {} : { expectedFailedNativeTurnId: retry.failedNativeTurnId })
670
+ } } : {}) };
632
671
  }
633
672
  if (method === "runtime.provider-turn-submission-resolve") {
634
673
  const value = providerTurnControlParams(params);
@@ -648,6 +687,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
648
687
  status,
649
688
  reason,
650
689
  raw,
690
+ noProviderWrite: params.providerWrite === "not-issued",
651
691
  now: value.now
652
692
  });
653
693
  return { recorded: true };
@@ -1207,6 +1247,8 @@ function providerTurnControlParams(params) {
1207
1247
  authorityEpoch: authorityEpoch,
1208
1248
  authorityOwner,
1209
1249
  holderId: requiredParam(value.holderId),
1250
+ ...(value.boundedText === undefined ? {} : { boundedText: requiredParam(value.boundedText) }),
1251
+ ...(value.retrySupport === undefined ? {} : { retrySupported: value.retrySupport === "codex-failed-turn-v1" }),
1210
1252
  now: new Date(observedAt)
1211
1253
  };
1212
1254
  }
@@ -1,18 +1,15 @@
1
1
  import { isRuntimeTokenEvidence } from "../runtime/runtimeObservation.js";
2
- import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
3
2
  const DEFAULT_MAX_RUNTIME_EVENTS_PER_DRAIN = 64;
4
3
  /** Folds immutable Hook facts in one bounded transaction before acknowledging them. */
5
4
  export class FileRuntimeEventProcessor {
6
5
  inbox;
7
6
  observer;
8
7
  options;
9
- drivers;
10
8
  drainLaneCursor = 0;
11
9
  constructor(inbox, observer, options = {}) {
12
10
  this.inbox = inbox;
13
11
  this.observer = observer;
14
12
  this.options = options;
15
- this.drivers = options.drivers ?? builtinAgentDriverRegistry();
16
13
  }
17
14
  drain(now) {
18
15
  const acknowledgedEventIds = [];
@@ -540,13 +537,11 @@ export class AsyncRuntimeEventProcessor {
540
537
  inbox;
541
538
  observer;
542
539
  options;
543
- drivers;
544
540
  drainLaneCursor = 0;
545
541
  constructor(inbox, observer, options = {}) {
546
542
  this.inbox = inbox;
547
543
  this.observer = observer;
548
544
  this.options = options;
549
- this.drivers = options.drivers ?? builtinAgentDriverRegistry();
550
545
  }
551
546
  async drainAsync(now) {
552
547
  const acknowledgedEventIds = [];
@@ -132,6 +132,11 @@ export class SessionOwnerReconciliation {
132
132
  }
133
133
  const result = await terminateSessionOwners(owner, records, this.#terminationPorts(), options);
134
134
  if (result.outcome === "stop-confirmed") {
135
+ // A signalled Host exits into a retained tmux pane. Explicit release
136
+ // removes that window too, after physical exit proof, not on observation.
137
+ if (records.length > 0) {
138
+ this.#tmux?.killRole(owner.scope === "task" ? owner.taskId : "operator", owner.roleName);
139
+ }
135
140
  for (const record of result.confirmed) {
136
141
  this.#store.removeSessionOwner(sessionOwnerProcessKey(record));
137
142
  }
@@ -0,0 +1,35 @@
1
+ import { createTaskEvent } from "../event/taskEvent.js";
2
+ import { redactAgentErrorText } from "../runtime/agentError.js";
3
+ import { captureAgentFailureContext } from "../runtime/agentFailureContext.js";
4
+ /** One persistence boundary. Ingress owns Provider classification, execution
5
+ * fences and routing; this writer never invents an execution or recovery plan. */
6
+ export function recordTaskAgentError(store, input, now) {
7
+ return store.transaction(tx => {
8
+ const error = input.error;
9
+ const payload = {
10
+ ...Object.fromEntries(Object.entries(input.evidence ?? {}).filter((entry) => typeof entry[1] === "string" && (entry[0] === "lastOutput" || entry[1].trim().length > 0))),
11
+ sourceEventId: input.sourceEventId, roleName: input.roleName,
12
+ agentId: input.agentId, adapterId: input.adapterId, driverId: input.driverId,
13
+ source: error.source, phase: error.phase, category: error.category, code: error.code,
14
+ message: redactAgentErrorText(error.message), raw: redactAgentErrorText(error.raw),
15
+ inputDisposition: error.inputDisposition, sessionDisposition: error.sessionDisposition,
16
+ ...(error.retryAfterMs === undefined ? {} : { retryAfterMs: String(error.retryAfterMs) })
17
+ };
18
+ const identity = ["sourceEventId", "roleName", "agentId", "adapterId", "driverId",
19
+ "source", "phase", "category", "code", "inputDisposition", "sessionDisposition",
20
+ "runId", "attemptId", "nativeSessionId", "nativeTurnId", "observationEventId",
21
+ "message", "errorName", "causeName", "hostState", "registrationDisposition",
22
+ "retryAfterMs", "lastOutput", ...(payload.attemptId === undefined ? ["raw"] : [])];
23
+ const duplicate = [...tx.listEventsByType(input.taskId, ["runtime.agent-error"])].reverse().find(event => identity.every(key => event.payload[key] === payload[key]));
24
+ // Keep the first original raw cause/configuration for a fixed failure.
25
+ // Changed normalized facts are distinct evidence, not a replay.
26
+ if (duplicate !== undefined)
27
+ return { event: duplicate, created: false };
28
+ const event = createTaskEvent(tx.nextEventId(input.taskId), input.taskId, "runtime.agent-error", {
29
+ ...payload,
30
+ capabilityContext: captureAgentFailureContext(input.effective, input.effective === undefined ? null : tx.getConfiguredAgent(input.effective.agentId))
31
+ }, now);
32
+ tx.saveEvent(input.taskId, event);
33
+ return { event, created: true };
34
+ });
35
+ }
@@ -1,18 +1,11 @@
1
1
  import { completeProcessing, consumePendingBatch, createWorkMailbox, enqueueSignal, mailboxBatches, mailboxEntityRefKey } from "./workMailbox.js";
2
- const LEGACY_ROLE_RUN_DISPATCH_REASONS = new Set([
3
- "turn-dispatched",
4
- "turn-retried",
5
- "review-requested",
6
- "workitem-synthesis-ready",
7
- "review-synthesis-ready"
8
- ]);
9
2
  /** Atomically useful when called inside the caller's TaskStore transaction. */
10
3
  export function enqueueWork(store, target, reason, occurredAt, refs = [], metadata = {}) {
11
4
  const mailbox = store.getWorkMailbox(target) ?? createWorkMailbox(target);
12
5
  // Archive is an admission boundary, not an acknowledgement of old input.
13
6
  // Runtime cleanup mailboxes remain usable for exact-owner recovery.
14
7
  if ((target.kind === "task" || target.kind === "role")
15
- && store.getTask?.(target.taskId)?.status === "archived")
8
+ && store.getTask(target.taskId)?.status === "archived")
16
9
  return mailbox;
17
10
  const queued = enqueueSignal(mailbox, {
18
11
  reason,
@@ -79,26 +72,11 @@ export function captureRoleRunDispatch(mailbox, input) {
79
72
  };
80
73
  }
81
74
  }
82
- // Valid earlier dispatches used sequence-generated dedupe keys and could
83
- // include a companion WorkItem ref. Consume that complete legacy batch once
84
- // the exact AgentRun reaches an accepted or terminal boundary.
85
- if (pending.requestCount === 1
86
- && pending.sources.length === 1
87
- && pending.sources[0] === "yui"
88
- && pending.reasons.some((reason) => LEGACY_ROLE_RUN_DISPATCH_REASONS.has(reason))
89
- && pending.refs.some((ref) => (mailboxEntityRefKey(ref) === mailboxEntityRefKey(exactRef)))) {
90
- return {
91
- kind: "pending",
92
- fromSequence: pending.fromSequence,
93
- toSequence: pending.toSequence
94
- };
95
- }
96
75
  return null;
97
76
  }
98
77
  /**
99
78
  * Settles one exact ordinary Role AgentRun dispatch. Provider acceptance is the
100
- * normal boundary; terminalization calls the same operation for conclusively
101
- * unaccepted and valid earlier dispatches.
79
+ * normal boundary; terminalization uses the same exact dispatch identity.
102
80
  */
103
81
  export function settleRoleRunDispatch(store, input, expected) {
104
82
  if (expected === null)
@@ -2,10 +2,10 @@ import { randomUUID } from "node:crypto";
2
2
  import { lstat, readFile } from "node:fs/promises";
3
3
  import { createConnection } from "node:net";
4
4
  import { join } from "node:path";
5
- import { CONTROLLER_DISCOVERY_PATH, FILE_TASK_CONTROLLER_PROTOCOL_VERSION, MAX_CONTROLLER_MESSAGE_BYTES, ControllerProtocolError, encodeControllerRequest, parseControllerDiscovery, parseControllerResponse } from "./protocol.js";
6
5
  import { isControllerSocketPathForHome } from "./controllerEndpoint.js";
7
- import { readHomeFilesystemId } from "./homeFilesystemIdentity.js";
8
6
  import { findLiveControllerProcessForHome, inspectLiveControllerProcess } from "./controllerProcessIdentity.js";
7
+ import { readHomeFilesystemId } from "./homeFilesystemIdentity.js";
8
+ import { CONTROLLER_DISCOVERY_PATH, ControllerProtocolError, encodeControllerRequest, FILE_TASK_CONTROLLER_PROTOCOL_VERSION, MAX_CONTROLLER_MESSAGE_BYTES, parseControllerDiscovery, parseControllerResponse } from "./protocol.js";
9
9
  export class ControllerClientError extends Error {
10
10
  code;
11
11
  constructor(code, message) {
@@ -0,0 +1,74 @@
1
+ import { lstatSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ /** One process generation, shared by file-lock producers and reclaim checks. */
4
+ export function currentFileLockOwner() {
5
+ return `${process.pid}:${readProcessStart(process.pid)}`;
6
+ }
7
+ /**
8
+ * False requires proof of absence or a different process generation.
9
+ * Missing publication, invalid identity and unavailable OS evidence are not
10
+ * dead owners: callers retain the lock and report the bounded diagnosis.
11
+ */
12
+ export function fileLockOwnerIsLive(lock) {
13
+ let owner;
14
+ try {
15
+ owner = readFileSync(join(lock, "owner"), "utf8").trim();
16
+ }
17
+ catch (error) {
18
+ if (hasCode(error, "ENOENT")) {
19
+ try {
20
+ lstatSync(lock);
21
+ }
22
+ catch (statError) {
23
+ if (hasCode(statError, "ENOENT"))
24
+ return false;
25
+ }
26
+ }
27
+ throw unverified(lock);
28
+ }
29
+ const match = /^([1-9][0-9]*):(0|[1-9][0-9]{0,31})$/u.exec(owner);
30
+ const pid = Number(match?.[1]);
31
+ if (match === null || !Number.isSafeInteger(pid))
32
+ throw unverified(lock);
33
+ try {
34
+ return processGenerationIsLive(pid, match[2]);
35
+ }
36
+ catch {
37
+ throw unverified(lock);
38
+ }
39
+ }
40
+ /** A known generation is live, provably gone, or unverified (throws). */
41
+ export function processGenerationIsLive(pid, startIdentity) {
42
+ if (!Number.isSafeInteger(pid) || pid < 1 || !/^(0|[1-9][0-9]{0,31})$/u.test(startIdentity)) {
43
+ throw new Error(`Unverified process generation for PID ${pid}.`);
44
+ }
45
+ try {
46
+ return readProcessStart(pid) === startIdentity;
47
+ }
48
+ catch {
49
+ // PID liveness can prove a process is gone, never prove its generation.
50
+ try {
51
+ process.kill(pid, 0);
52
+ }
53
+ catch (error) {
54
+ if (hasCode(error, "ESRCH"))
55
+ return false;
56
+ }
57
+ throw new Error(`Unverified process generation for PID ${pid}; OS identity could not be read.`);
58
+ }
59
+ }
60
+ function readProcessStart(pid) {
61
+ const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
62
+ const close = stat.lastIndexOf(")");
63
+ const start = close < 0 ? undefined : stat.slice(close + 2).trim().split(/\s+/u)[19];
64
+ if (start === undefined || !/^(0|[1-9][0-9]{0,31})$/u.test(start)) {
65
+ throw new Error(`Process start identity is unavailable for PID ${pid}.`);
66
+ }
67
+ return start;
68
+ }
69
+ function unverified(lock) {
70
+ return new Error(`Unverified lock owner identity: ${lock}. Preserve the lock and inspect its owner before cleanup.`);
71
+ }
72
+ function hasCode(error, code) {
73
+ return error instanceof Error && "code" in error && error.code === code;
74
+ }
@@ -1,4 +1,21 @@
1
1
  import { validateTaskRecordReference } from "../task/taskRecordReference.js";
2
+ import { requireTimestamp } from "../domain/validation.js";
3
+ export function validateDecision(decision) {
4
+ if (decision.schemaVersion !== 1)
5
+ throw new Error("Decision must use schemaVersion 1.");
6
+ validateTaskRecordReference({ taskId: decision.taskId, localId: decision.id }, "decision");
7
+ requireText(decision.title, "Decision title");
8
+ requireText(decision.rationale, "Decision rationale");
9
+ requireTimestamp(decision.createdAt, "Decision createdAt");
10
+ requireTimestamp(decision.updatedAt, "Decision updatedAt");
11
+ if (decision.status !== "active" && decision.status !== "superseded")
12
+ throw new Error("Decision status is invalid.");
13
+ if (decision.status === "superseded") {
14
+ requireText(decision.supersededReason, "Decision supersede reason");
15
+ requireTimestamp(decision.supersededAt, "Decision supersededAt");
16
+ }
17
+ return decision;
18
+ }
2
19
  export function createDecision(id, taskId, title, rationale, now) {
3
20
  const timestamp = now.toISOString();
4
21
  return {
@@ -3,20 +3,20 @@ import { isAbsolute, join } from "node:path";
3
3
  import Database from "better-sqlite3";
4
4
  import { configuredAgentToDefinition, resolveAgentEnvironment } from "../agent/agent.js";
5
5
  import { operationalAgentEnvironment } from "../agent/launchEnvironment.js";
6
+ import { resolveTmuxBin } from "../config/yuiConfig.js";
7
+ import { compileRoleSessionContext } from "../context/roleSessionContext.js";
8
+ import { EPHEMERAL_DOMAIN_GRACE_MS, readEphemeralDomainIdentity, readLinuxProcessStartIdentity } from "../controller/domainIdentity.js";
9
+ import { usageError } from "../errors/cliError.js";
6
10
  import { inspectAgentCapabilities, resolveAgentAdapter } from "../executor/agentAdapter.js";
7
11
  import { assertCodexLaunchOverridesAvailable, inspectCodexLaunchConfig } from "../executor/codexConfigConflict.js";
8
- import { nativeAdditionalDirectories, nativeAgentWorkspace, withNativeProjectDirectories } from "../executor/fileRoleLaunchPlanner.js";
9
12
  import { resolveEffectiveLaunch } from "../executor/effectiveLaunch.js";
10
- import { compileRoleSessionContext } from "../context/roleSessionContext.js";
11
- import { usageError } from "../errors/cliError.js";
13
+ import { nativeAdditionalDirectories, nativeAgentWorkspace, withNativeProjectDirectories } from "../executor/fileRoleLaunchPlanner.js";
12
14
  import { defaultTableWidth, renderTable } from "../output/table.js";
13
- import { resolveYuiHome } from "../storage/taskStore.js";
14
15
  import { CURRENT_DATABASE_FILENAME, openCurrentTaskStore } from "../storage/currentTaskStore.js";
15
16
  import { inspectStorageSchema } from "../storage/storageSchema.js";
16
17
  import { resolveStoreWorkerEnabledForHome } from "../storage/storeRpc.js";
17
- import { resolveTmuxBin } from "../config/yuiConfig.js";
18
+ import { resolveYuiHome } from "../storage/taskStore.js";
18
19
  import { CommandExecutionError } from "../tmux/commandExecutor.js";
19
- import { EPHEMERAL_DOMAIN_GRACE_MS, readEphemeralDomainIdentity, readLinuxProcessStartIdentity } from "../controller/domainIdentity.js";
20
20
  /**
21
21
  * The storage-relevant doctor checks, in the order they are produced. Post-update
22
22
  * verification (P1-3) keys off exactly these: a green `yui doctor` for the update
@@ -243,7 +243,7 @@ function checkSchema(state) {
243
243
  }
244
244
  }
245
245
  /** Diagnose admission to the exact current storage contract without repair. */
246
- function inspectCompatibility(home, homeCheck, schema) {
246
+ function inspectCompatibility(_home, homeCheck, schema) {
247
247
  const name = "storage compatibility";
248
248
  if (homeCheck.status !== "ok") {
249
249
  return { check: { name, status: homeCheck.status, detail: homeCheck.detail } };
@@ -311,8 +311,10 @@ function inspectState(home, homeCheck, schema, compatibility) {
311
311
  if (!existsSync(databasePath)) {
312
312
  return blockedStorage("invalid", "Current storage is incomplete: yui.db is missing.");
313
313
  }
314
+ let ownedStore;
314
315
  try {
315
- const store = openCurrentTaskStore(home);
316
+ const store = ownedStore = openCurrentTaskStore(home);
317
+ store.validateCurrentRecords();
316
318
  const config = store.getConfig();
317
319
  const agents = store.listConfiguredAgents();
318
320
  const tasks = store.listTasks();
@@ -346,6 +348,9 @@ function inspectState(home, homeCheck, schema, compatibility) {
346
348
  catch (error) {
347
349
  return blockedStorage("invalid", errorMessage(error));
348
350
  }
351
+ finally {
352
+ ownedStore?.close();
353
+ }
349
354
  }
350
355
  function storageBlockerDetail(check) {
351
356
  const corruptionPrefix = "unsupported (CORRUPTED): ";
@@ -755,8 +760,9 @@ function errorMessage(error) {
755
760
  * the Home store cannot be opened (the doctor must still run on broken Homes).
756
761
  */
757
762
  function readDurableConfigSafely(home) {
763
+ let ownedStore;
758
764
  try {
759
- const store = openCurrentTaskStore(home);
765
+ const store = ownedStore = openCurrentTaskStore(home);
760
766
  const config = store.getConfig();
761
767
  return {
762
768
  tmuxBin: resolveTmuxBin(config.tmuxBin),
@@ -766,4 +772,7 @@ function readDurableConfigSafely(home) {
766
772
  catch {
767
773
  return { tmuxBin: "tmux", gitBin: "git" };
768
774
  }
775
+ finally {
776
+ ownedStore?.close();
777
+ }
769
778
  }
@@ -1,4 +1,5 @@
1
1
  import { validateTaskRecordReference } from "../task/taskRecordReference.js";
2
+ import { requireTimestamp } from "../domain/validation.js";
2
3
  export function createTaskEvent(id, taskId, type, payload, now) {
3
4
  const event = {
4
5
  schemaVersion: 2,
@@ -8,7 +9,18 @@ export function createTaskEvent(id, taskId, type, payload, now) {
8
9
  payload: normalizePayload(payload),
9
10
  createdAt: now.toISOString()
10
11
  };
12
+ return validateTaskEvent(event);
13
+ }
14
+ export function validateTaskEvent(event) {
15
+ if (event.schemaVersion !== 2)
16
+ throw new Error("Task Event must use schemaVersion 2.");
11
17
  validateTaskRecordReference({ taskId: event.taskId, localId: event.id }, "event");
18
+ requireText(event.type, "Task event type");
19
+ if (event.payload === null || typeof event.payload !== "object" || Array.isArray(event.payload)) {
20
+ throw new Error("Task event payload must be an object.");
21
+ }
22
+ normalizePayload(event.payload);
23
+ requireTimestamp(event.createdAt, "Task event createdAt");
12
24
  return event;
13
25
  }
14
26
  /**
@@ -1,5 +1,5 @@
1
- import { governingWorkItemCandidate, currentWorkItemExecutionGroup } from "../workItem/workItem.js";
2
1
  import { synthesisSourceRunIds } from "../context/runContextPack.js";
2
+ import { currentWorkItemExecutionGroup, governingWorkItemCandidate } from "../workItem/workItem.js";
3
3
  export function projectWorkItemExecution(item, runs, sessionSets = [], sourceStore) {
4
4
  const group = currentWorkItemExecutionGroup(item);
5
5
  const relevantRuns = runs.filter((run) => run.workItemId === item.id);
@@ -164,7 +164,7 @@ function projectMainRun(item, group, runs, sessionsByRole) {
164
164
  observation: run.result === undefined ? "unobserved" : "observed"
165
165
  });
166
166
  }
167
- function projectSynthesis(group, lanes, mainRun) {
167
+ function projectSynthesis(group, _lanes, mainRun) {
168
168
  if (group === undefined) {
169
169
  return Object.freeze({
170
170
  status: "not-applicable",
@@ -0,0 +1,43 @@
1
+ import { isAbsolute } from "node:path";
2
+ import { isAgentAdapterId } from "../agent/adapterCatalog.js";
3
+ /** Project an existing Role/launch config without changing its native values. */
4
+ export function projectAgentCapabilityConfig(config) {
5
+ return validateAgentCapabilityConfig({
6
+ adapterId: config.adapterId,
7
+ ...(config.model === undefined ? {} : { model: config.model }),
8
+ ...(config.effort === undefined ? {} : { effort: config.effort }),
9
+ ...(config.adapterId !== "codex" || config.profile === undefined ? {} : { profile: config.profile }),
10
+ ...(config.adapterId !== "claude" || config.settingsFile === undefined ? {} : { settingsFile: config.settingsFile }),
11
+ ...(config.adapterId !== "claude" || config.settingsSources === undefined ? {} : { settingsSources: [...config.settingsSources] })
12
+ });
13
+ }
14
+ export function validateAgentCapabilityConfig(value) {
15
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
16
+ throw new Error("Agent capability configuration is invalid.");
17
+ }
18
+ const config = value;
19
+ if (!isAgentAdapterId(config.adapterId))
20
+ throw new Error("Agent capability adapter is invalid.");
21
+ const keys = ["adapterId", "model", "effort",
22
+ ...(config.adapterId === "codex" ? ["profile"] : []),
23
+ ...(config.adapterId === "claude" ? ["settingsFile", "settingsSources"] : [])];
24
+ if (Object.keys(config).some(key => !keys.includes(key))) {
25
+ throw new Error("Agent capability configuration contains execution-only or unsupported fields.");
26
+ }
27
+ for (const key of ["model", "effort", "profile", "settingsFile"]) {
28
+ const field = config[key];
29
+ if (field !== undefined && (typeof field !== "string" || field.trim().length === 0 || field.includes("\0"))) {
30
+ throw new Error(`Agent capability ${key} is invalid.`);
31
+ }
32
+ }
33
+ if (config.settingsFile !== undefined && !isAbsolute(config.settingsFile)) {
34
+ throw new Error("Agent capability settings file must be absolute.");
35
+ }
36
+ const sources = config.settingsSources;
37
+ if (sources !== undefined && (!Array.isArray(sources)
38
+ || sources.some(source => typeof source !== "string" || source.trim().length === 0 || source.includes("\0"))
39
+ || new Set(sources).size !== sources.length)) {
40
+ throw new Error("Agent capability settings sources are invalid.");
41
+ }
42
+ return config;
43
+ }