@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.
- package/ARCHITECTURE.md +11 -6
- package/ARCHITECTURE.zh-CN.md +8 -4
- package/README.md +13 -5
- package/dist/agentRun/agentRun.js +3 -0
- package/dist/artifacts/artifactCommitLock.js +16 -55
- package/dist/artifacts/taskArtifactRepository.js +3 -3
- package/dist/cli/agentConfigurationPicker.js +1 -1
- package/dist/cli/commandCatalog.js +92 -48
- package/dist/cli/completion.js +18 -18
- package/dist/cli/completionWizard.js +1 -1
- package/dist/cli/dynamicCompletion.js +1 -1
- package/dist/cli/interactionPolicy.js +11 -3
- package/dist/cli/invocationAuthority.js +64 -0
- package/dist/cli/managedDiagnostics.js +2 -2
- package/dist/cli/parseRepeatable.js +35 -0
- package/dist/cli/updatePorts.js +26 -5
- package/dist/cli.js +1303 -1235
- package/dist/commands/agentCommands.js +4 -4
- package/dist/commands/capabilityCommands.js +1 -1
- package/dist/commands/configCommands.js +6 -57
- package/dist/commands/configOverview.js +2 -2
- package/dist/commands/durableJobCommands.js +12 -6
- package/dist/commands/executionAuditCommands.js +10 -0
- package/dist/commands/globalRoleCommands.js +78 -29
- package/dist/commands/grantCommands.js +0 -3
- package/dist/commands/jobCommands.js +1 -4
- package/dist/commands/operatorCommands.js +3 -3
- package/dist/commands/projectCommands.js +45 -25
- package/dist/commands/resourcesCommands.js +10 -40
- package/dist/commands/roleConfiguration.js +2 -6
- package/dist/commands/taskActivationCommands.js +4 -8
- package/dist/commands/taskAgentCapabilities.js +9 -0
- package/dist/commands/taskCommandSupport.js +155 -0
- package/dist/commands/taskCommandTypes.js +1 -0
- package/dist/commands/taskCommands.js +355 -732
- package/dist/commands/taskCompletionGate.js +1 -1
- package/dist/commands/taskExecutionCommands.js +1 -1
- package/dist/commands/taskFactCommands.js +325 -0
- package/dist/commands/taskInputCommands.js +12 -42
- package/dist/commands/taskIntegrationCommands.js +20 -58
- package/dist/commands/taskNextActionCommand.js +7 -6
- package/dist/commands/taskPublicationAdoptCommand.js +127 -0
- package/dist/commands/taskPublicationCommands.js +12 -3
- package/dist/commands/taskPublicationVerifyCommand.js +24 -40
- package/dist/commands/taskRemoteDeliveryCommand.js +5 -86
- package/dist/commands/taskUpstreamCommands.js +19 -8
- package/dist/commands/workflowCommands.js +6 -1
- package/dist/completion/completionInstaller.js +26 -26
- package/dist/completion/completionState.js +26 -26
- package/dist/completion/fileCompletionManager.js +6 -11
- package/dist/config/configCatalog.js +0 -2
- package/dist/config/timeZone.js +14 -0
- package/dist/config/yuiConfig.js +0 -29
- package/dist/context/runContextPack.js +5 -3
- package/dist/context/taskCatalog.js +185 -0
- package/dist/context/taskContext.js +152 -151
- package/dist/context/wakeRunReferences.js +11 -0
- package/dist/controller/agentCapabilities.js +58 -0
- package/dist/controller/agentRuntimeObserver.js +6 -11
- package/dist/controller/clientRuntime.js +22 -14
- package/dist/controller/controller.js +20 -24
- package/dist/controller/fileSchedulerStoreAdapter.js +191 -225
- package/dist/controller/globalInputDelivery.js +13 -0
- package/dist/controller/jobClient.js +4 -4
- package/dist/controller/jobControl.js +60 -25
- package/dist/controller/jobSupervisor.js +4 -4
- package/dist/controller/providerRetryAdmission.js +100 -0
- package/dist/controller/providerRetryDelivery.js +218 -0
- package/dist/controller/runtime.js +85 -43
- package/dist/controller/runtimeEventProcessor.js +0 -5
- package/dist/controller/sessionOwnerReconciliation.js +5 -0
- package/dist/controller/taskAgentError.js +35 -0
- package/dist/coordination/workMailboxQueue.js +2 -24
- package/dist/core/controllerClient.js +2 -2
- package/dist/core/fileLockOwner.js +74 -0
- package/dist/decision/decision.js +17 -0
- package/dist/doctor/doctor.js +18 -9
- package/dist/event/taskEvent.js +12 -0
- package/dist/execution/workItemExecutionProjection.js +2 -2
- package/dist/executor/agentCapabilityConfig.js +43 -0
- package/dist/executor/agentConfigurationCatalog.js +49 -11
- package/dist/executor/agentExecutor.js +5 -8
- package/dist/executor/fileRoleLaunchPlanner.js +11 -53
- package/dist/executor/taskAgentCapabilities.js +64 -0
- package/dist/integration/deliveryObligation.js +1 -69
- package/dist/integration/gitIntegrationService.js +79 -90
- package/dist/integration/integrationAttempt.js +3 -14
- package/dist/integration/integrationSourceApplication.js +4 -12
- package/dist/integration/manifestTags.js +2 -2
- package/dist/job/durableJob.js +4 -25
- package/dist/job/jobAssignmentScope.js +22 -0
- package/dist/job/jobOperation.js +16 -0
- package/dist/job/jobRunner.js +2 -1
- package/dist/job/stepDirectory.js +15 -0
- package/dist/kernel/builtinCapabilities.js +15 -11
- package/dist/kernel/kernelPorts.js +1 -17
- package/dist/lifecycle/exactRunTerminalization.js +5 -10
- package/dist/message/globalProviderRetry.js +15 -0
- package/dist/message/inputControlResolution.js +3 -4
- package/dist/message/message.js +17 -20
- package/dist/message/messageContinuation.js +1 -1
- package/dist/milestone/milestone.js +11 -0
- package/dist/observability/executionAudit.js +19 -0
- package/dist/observability/orchestrationMetrics.js +24 -1
- package/dist/observability/runtimeIdentity.js +1 -17
- package/dist/output/agentConfigurationPresentation.js +2 -0
- package/dist/output/timePresentation.js +1 -14
- package/dist/plugins/pluginService.js +12 -4
- package/dist/release/releaseWorkflowPorts.js +45 -96
- package/dist/release/runtimeRelease.js +9 -15
- package/dist/repository/gitWorkspace.js +371 -105
- package/dist/repository/projectMaintenanceLock.js +98 -82
- package/dist/repository/taskBaseFreshness.js +1 -1
- package/dist/repository/taskWorkspaceCoordinator.js +82 -144
- package/dist/repository/taskWorkspacePreparer.js +113 -47
- package/dist/repository/workspaceCleanupInspection.js +187 -0
- package/dist/resources/autoResourceGc.js +4 -77
- package/dist/resources/liveReferences.js +7 -54
- package/dist/resources/resourceDiscovery.js +5 -118
- package/dist/resources/resourceGc.js +233 -181
- package/dist/resources/resourceRegistrar.js +5 -4
- package/dist/resources/resourceRegistry.js +3 -37
- package/dist/resources/resourceRegistryStore.js +13 -36
- package/dist/resources/sqliteResourceRegistry.js +43 -26
- package/dist/review/deltaRecheck.js +1 -1
- package/dist/review/reviewAcceptance.js +1 -1
- package/dist/review/reviewDecision.js +1 -1
- package/dist/review/reviewRound.js +8 -7
- package/dist/review/taskFinalReviewContractResolution.js +1 -1
- package/dist/runtime/acpProtocol.js +4 -51
- package/dist/runtime/acpSession.js +10 -75
- package/dist/runtime/acpSessionConfiguration.js +1 -8
- package/dist/runtime/agentEndpoint.js +3 -2
- package/dist/runtime/agentError.js +5 -3
- package/dist/runtime/agentFailureContext.js +43 -0
- package/dist/runtime/agentHost.js +42 -25
- package/dist/runtime/builtinAgentErrorMappers.js +91 -0
- package/dist/runtime/codexAppServerRuntime.js +34 -3
- package/dist/runtime/codexInteractiveHost.js +2 -2
- package/dist/runtime/index.js +0 -1
- package/dist/runtime/managedCaller.js +21 -1
- package/dist/runtime/providerControl.js +5 -1
- package/dist/runtime/providerErrors.js +38 -0
- package/dist/runtime/providerRetry.js +198 -0
- package/dist/runtime/providerRuntimeIdentity.js +28 -2
- package/dist/runtime/runtimeObservation.js +0 -5
- package/dist/runtime/runtimeSessionCandidate.js +2 -3
- package/dist/runtime/sessionOwnerIdentity.js +1 -1
- package/dist/runtime/sessionTokenMetrics.js +15 -5
- package/dist/runtime/structuredProviderHost.js +10 -43
- package/dist/runtime/taskUsageMetrics.js +275 -0
- package/dist/runtime/tmuxAdapters.js +6 -8
- package/dist/scheduler/activeRoleRunDelivery.js +19 -7
- package/dist/scheduler/leaderWakeupProcessor.js +24 -6
- package/dist/scheduler/operatorEvent.js +12 -20
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +5 -8
- package/dist/scheduler/roleRunLiveness.js +4 -4
- package/dist/scheduler/roleRunStall.js +16 -23
- package/dist/scheduler/taskExecutionProjection.js +49 -36
- package/dist/scheduler/taskObservabilityProjection.js +6 -45
- package/dist/scheduler/taskWake.js +5 -10
- package/dist/scheduler/wakeReason.js +2 -0
- package/dist/scheduler/wakeupQueue.js +2 -4
- package/dist/setup/setupCommand.js +1 -1
- package/dist/storage/contextRecords.js +106 -0
- package/dist/storage/currentTaskStore.js +1 -1
- package/dist/storage/homeLayout.js +13 -17
- package/dist/storage/migrations/agentFailureContext.js +22 -0
- package/dist/storage/migrations/currentInputContract.js +86 -0
- package/dist/storage/migrations/currentRuntimeContract.js +228 -0
- package/dist/storage/migrations/historicalVerificationPlan.js +35 -0
- package/dist/storage/migrations/integrationContinuation.js +5 -4
- package/dist/storage/migrations/narrowAgentFailureContext.js +65 -0
- package/dist/storage/migrations/notificationOnlyWakes.js +74 -0
- package/dist/storage/migrations/verificationPlanV1.js +162 -0
- package/dist/storage/migrations/verificationPolicy.js +74 -0
- package/dist/storage/migrations/workItemHistory.js +46 -0
- package/dist/storage/persistenceWorker.js +12 -4
- package/dist/storage/recordValidation.js +87 -0
- package/dist/storage/sqliteSchema.js +173 -1
- package/dist/storage/sqliteStore.js +172 -161
- package/dist/storage/storageSchema.js +2 -14
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +16 -7
- package/dist/storage/taskCatalog.js +123 -0
- package/dist/storage/taskStore.js +5 -7
- package/dist/storage/upgrade/upgradeOrchestrator.js +25 -37
- package/dist/task/archiveDiagnostics.js +1 -0
- package/dist/task/archivePreflight.js +124 -0
- package/dist/task/completionReadiness.js +5 -24
- package/dist/task/draftPlan.js +0 -53
- package/dist/task/nextAction.js +7 -13
- package/dist/task/publicationAdoption.js +56 -0
- package/dist/task/publicationReference.js +10 -0
- package/dist/task/remoteDelivery.js +31 -16
- package/dist/task/remoteDeliveryService.js +89 -0
- package/dist/task/taskActivation.js +2 -25
- package/dist/task/taskActivationService.js +0 -2
- package/dist/task/taskRecordReference.js +0 -1
- package/dist/task/taskSubmission.js +3 -14
- package/dist/telemetry/sqliteTelemetryBatch.js +29 -0
- package/dist/telemetry/sqliteTelemetryStore.js +49 -49
- package/dist/telemetry/telemetryWiring.js +4 -3
- package/dist/tmux/tmuxManager.js +29 -20
- package/dist/verification/gateArtifact.js +15 -24
- package/dist/verification/gateArtifactStore.js +14 -7
- package/dist/verification/verificationGateService.js +29 -88
- package/dist/verification/verificationPlan.js +27 -72
- package/dist/web/assets/client/app.js +92 -17
- package/dist/web/assets/client/components.js +55 -13
- package/dist/web/assets/client/i18n.js +72 -4
- package/dist/web/assets/client/taskSurface.js +6 -5
- package/dist/web/assets/client/view.js +35 -7
- package/dist/web/assets/shell.js +6 -0
- package/dist/web/assets/styles/layout.js +7 -0
- package/dist/web/webServer.js +12 -3
- package/dist/web/webSnapshot.js +14 -85
- package/dist/web/webTaskSurface.js +17 -46
- package/dist/workItem/workItem.js +1 -12
- package/dist/workspace/cleanupInspection.js +63 -0
- package/dist/workspace/workItemChangeSetManager.js +110 -50
- package/docs/agent-result-consumption.md +4 -0
- package/docs/agent-result-consumption.zh-CN.md +3 -0
- package/docs/agent-runtime-drivers.md +7 -0
- package/docs/agent-runtime-drivers.zh-CN.md +5 -0
- package/docs/architecture/README.md +2 -0
- package/docs/architecture/README.zh-CN.md +3 -1
- package/docs/architecture/capabilities-and-resources.md +42 -5
- package/docs/architecture/capabilities-and-resources.zh-CN.md +33 -3
- package/docs/managed-turn-and-session-runtime.md +121 -1
- package/docs/managed-turn-and-session-runtime.zh-CN.md +96 -2
- package/docs/observability/README.md +62 -0
- package/docs/observability/README.zh-CN.md +47 -0
- package/docs/plugin-sdk.md +4 -2
- package/docs/project-refresh.md +77 -0
- package/docs/project-refresh.zh-CN.md +59 -0
- package/docs/provider-retry.md +70 -0
- package/docs/provider-runtime.md +3 -1
- package/docs/provider-runtime.zh-CN.md +4 -2
- package/docs/release-workflow.md +190 -7
- package/docs/release-workflow.zh-CN.md +139 -5
- package/docs/roles-and-configuration.md +29 -0
- package/docs/roles-and-configuration.zh-CN.md +21 -0
- package/docs/sqlite-control-plane-design.md +16 -3
- package/docs/sqlite-control-plane-design.zh-CN.md +13 -2
- package/docs/task-dag-semantics.md +3 -3
- package/docs/task-dag-semantics.zh-CN.md +2 -2
- package/docs/task-delivery.md +223 -17
- package/docs/task-delivery.zh-CN.md +171 -14
- package/docs/task-discovery.md +101 -0
- package/docs/task-discovery.zh-CN.md +85 -0
- package/docs/testing/verification-levels.md +161 -9
- package/docs/testing/verification-levels.zh-CN.md +116 -9
- package/i18n/README.zh-CN.md +13 -7
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +5 -0
- package/skills/yui-leader/references/execution.md +3 -2
- package/skills/yui-leader/references/integration.md +9 -5
- package/skills/yui-leader/references/planning.md +9 -3
- package/skills/yui-operator/SKILL.md +24 -8
- package/skills/yui-reviewer/SKILL.md +4 -0
- package/skills/yui-runtime/SKILL.md +17 -2
- package/skills/yui-runtime/references/publication.md +26 -4
- package/skills/yui-runtime/references/recovery.md +71 -0
- package/dist/agent/agentRegistry.js +0 -10
- package/dist/agentRun/runIdentity.js +0 -22
- package/dist/commands/deliveryGuardPreflight.js +0 -30
- package/dist/commands/taskIntegrationQueueCommands.js +0 -226
- package/dist/commands/taskOverviewCommand.js +0 -376
- package/dist/completion/completionWizard.js +0 -125
- package/dist/context/dispatchContext.js +0 -110
- package/dist/context/wakeNotification.js +0 -144
- package/dist/integration/integrationCheckEvidenceReuse.js +0 -53
- package/dist/integration/integrationQueueEntry.js +0 -191
- package/dist/integration/integrationQueueService.js +0 -810
- package/dist/release/fakeReleasePorts.js +0 -55
- package/dist/runtime/sessionOwnerRegistry.js +0 -137
- package/dist/task/deliveryGuard.js +0 -226
- /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 {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
32
|
-
import {
|
|
37
|
+
import { createWebTaskSurface } from "../web/webTaskSurface.js";
|
|
38
|
+
import { isTaskOwnedWorkspace, sameManagedWorkspaceIdentity } from "../worktree/managedWorkspace.js";
|
|
33
39
|
import { AgentRuntimeObserver } from "./agentRuntimeObserver.js";
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
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 {
|
|
41
|
-
import {
|
|
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 {
|
|
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,
|
|
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 === "
|
|
456
|
-
?
|
|
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
|
-
|
|
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
|
|
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
|
|
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 {
|
package/dist/doctor/doctor.js
CHANGED
|
@@ -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 {
|
|
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 {
|
|
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(
|
|
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
|
}
|
package/dist/event/taskEvent.js
CHANGED
|
@@ -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,
|
|
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
|
+
}
|