@zq-silk/yui 0.15.7 → 0.15.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +194 -399
- package/ARCHITECTURE.zh-CN.md +151 -0
- package/README.md +306 -1131
- package/dist/agent/adapterCatalog.js +15 -2
- package/dist/agent/agent.js +23 -3
- package/dist/agent/argumentPolicy.js +7 -1
- package/dist/agent/connectionPlan.js +62 -0
- package/dist/agent/executionComponents.js +158 -0
- package/dist/agent/launchEnvironment.js +31 -3
- package/dist/agent/managedRuntimeEnvironment.js +3 -5
- package/dist/{turn/turn.js → agentRun/agentRun.js} +166 -109
- package/dist/{turn/turnIdentity.js → agentRun/runIdentity.js} +4 -4
- package/dist/artifacts/artifactCapability.js +74 -0
- package/dist/artifacts/artifactCommitLock.js +249 -0
- package/dist/artifacts/artifactPaths.js +151 -0
- package/dist/artifacts/gitArtifactRef.js +146 -0
- package/dist/artifacts/managedGit.js +332 -0
- package/dist/artifacts/taskArtifactRepository.js +277 -0
- package/dist/brief/taskBrief.js +12 -0
- package/dist/cli/agentConfigurationPicker.js +13 -0
- package/dist/cli/commandCatalog.js +165 -74
- package/dist/cli/interactionCandidates.js +5 -5
- package/dist/cli/interactionPolicy.js +38 -8
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/managedDiagnostics.js +28 -0
- package/dist/cli/operatorWizard.js +1 -7
- package/dist/cli/roleOptionOrder.js +27 -0
- package/dist/cli/roleWizard.js +50 -14
- package/dist/cli/updateOrchestrator.js +1 -1
- package/dist/cli/updatePorts.js +3 -4
- package/dist/cli.js +245 -95
- package/dist/commands/agentCommands.js +72 -14
- package/dist/commands/capabilityCommands.js +9 -6
- package/dist/commands/configCommands.js +20 -20
- package/dist/commands/deliveryGuardPreflight.js +2 -2
- package/dist/commands/executionAuditCommands.js +24 -24
- package/dist/commands/globalRoleCommands.js +1 -1
- package/dist/commands/grantCommands.js +4 -4
- package/dist/commands/operatorCommands.js +34 -9
- package/dist/commands/projectCommands.js +4 -4
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/roleConfiguration.js +25 -5
- package/dist/commands/roleRuntimeGuard.js +4 -5
- package/dist/commands/sessionCommands.js +3 -7
- package/dist/commands/taskActivationCommands.js +281 -0
- package/dist/commands/taskActor.js +28 -49
- package/dist/commands/taskCommands.js +1461 -720
- package/dist/commands/taskContextCommand.js +39 -583
- package/dist/commands/taskExecutionCommands.js +32 -32
- package/dist/commands/taskInputCommands.js +40 -104
- package/dist/commands/taskIntegrationCommands.js +3 -2
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -8
- package/dist/commands/taskOverviewCommand.js +33 -45
- package/dist/commands/taskRemoteDeliveryCommand.js +2 -2
- package/dist/commands/taskRoleRuntimeStatus.js +133 -102
- package/dist/commands/telemetryCommands.js +36 -38
- package/dist/config/configCatalog.js +4 -4
- package/dist/config/yuiConfig.js +8 -8
- package/dist/context/contextSnapshot.js +10 -10
- package/dist/context/dispatchContext.js +11 -11
- package/dist/context/roleSessionContext.js +6 -3
- package/dist/context/{turnContextPack.js → runContextPack.js} +158 -81
- package/dist/context/{turnInputContract.js → runInputContract.js} +73 -60
- package/dist/context/sessionBootstrapManifest.js +21 -2
- package/dist/context/sourceRunContext.js +30 -0
- package/dist/context/taskContext.js +481 -0
- package/dist/context/wakeNotification.js +27 -27
- package/dist/controller/agentRuntimeObserver.js +21 -24
- package/dist/controller/capabilityBridge.js +17 -6
- package/dist/controller/clientRuntime.js +65 -92
- package/dist/controller/controller.js +120 -188
- package/dist/controller/fileSchedulerStoreAdapter.js +787 -887
- package/dist/controller/jobControl.js +54 -85
- package/dist/controller/resourceInventory.js +8 -27
- package/dist/controller/resourceInventoryLinux.js +12 -13
- package/dist/controller/runtime.js +529 -479
- package/dist/controller/runtimeEventInbox.js +55 -25
- package/dist/controller/runtimeEventProcessor.js +22 -31
- package/dist/controller/{runtimeHookTurnFence.js → runtimeHookRunFence.js} +91 -115
- package/dist/controller/runtimeLaunchCoordinator.js +80 -426
- package/dist/controller/runtimeObservationHook.js +14 -18
- package/dist/controller/sessionNotify.js +16 -24
- package/dist/controller/sessionOwnerReconciliation.js +168 -50
- package/dist/controller/structuredProviderObservation.js +138 -99
- package/dist/coordination/workMailbox.js +3 -3
- package/dist/coordination/workMailboxQueue.js +36 -33
- package/dist/core/boundedRpc.js +8 -1
- package/dist/core/controllerClient.js +20 -1
- package/dist/core/controllerServer.js +4 -4
- package/dist/doctor/doctor.js +13 -2
- package/dist/domain/agentResultTransport.js +9 -9
- package/dist/execution/codexThreadNaming.js +2 -8
- package/dist/execution/executionHealth.js +51 -63
- package/dist/execution/reviewMainRun.js +137 -0
- package/dist/execution/workItemExecution.js +28 -29
- package/dist/execution/workItemExecutionProjection.js +99 -107
- package/dist/execution/workItemMainRun.js +141 -0
- package/dist/executor/agentAdapter.js +227 -20
- package/dist/executor/agentConfigurationCatalog.js +126 -4
- package/dist/executor/agentConfigurationProbe.js +162 -4
- package/dist/executor/agentExecutor.js +79 -78
- package/dist/executor/effectiveLaunch.js +105 -18
- package/dist/executor/executorRegistry.js +29 -44
- package/dist/executor/fileRoleLaunchPlanner.js +229 -154
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +6 -3
- package/dist/input/inputRequest.js +12 -10
- package/dist/integration/gitIntegrationService.js +4 -11
- package/dist/integration/integrationQueueService.js +4 -4
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/kernel/builtinCapabilities.js +255 -12
- package/dist/kernel/capabilityRegistry.js +64 -18
- package/dist/kernel/instanceHost.js +12 -1
- package/dist/kernel/kernelPorts.js +2 -2
- package/dist/lifecycle/canonicalLifecycleEvent.js +44 -49
- package/dist/lifecycle/exactRunTerminalization.js +449 -0
- package/dist/message/message.js +118 -6
- package/dist/message/messageContinuation.js +204 -0
- package/dist/observability/executionAudit.js +70 -72
- package/dist/observability/faultClassification.js +2 -2
- package/dist/observability/orchestrationMetrics.js +8 -8
- package/dist/operator/operatorSessionHistory.js +1 -7
- package/dist/output/agentConfigurationPresentation.js +8 -3
- package/dist/output/agentRunConfigurationPresentation.js +128 -0
- package/dist/output/rolePresentation.js +54 -3
- package/dist/plugins/pluginChild.js +104 -0
- package/dist/plugins/pluginIntent.js +26 -0
- package/dist/plugins/pluginInterpreter.js +43 -0
- package/dist/plugins/pluginPackage.js +101 -0
- package/dist/plugins/pluginProcess.js +112 -0
- package/dist/plugins/pluginService.js +388 -0
- package/dist/profile/agentProfile.js +1 -1
- package/dist/repository/gitWorkspace.js +26 -4
- package/dist/repository/project.js +19 -4
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +20 -27
- package/dist/repository/taskWorkspacePreparer.js +344 -83
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +3 -3
- package/dist/resources/projectResource.js +75 -0
- package/dist/resources/projectResourceService.js +343 -0
- package/dist/resources/resourceDiscovery.js +6 -6
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/resourceRegistrar.js +1 -1
- package/dist/resources/resourceTypes.js +1 -1
- package/dist/review/deltaRecheck.js +3 -3
- package/dist/review/reviewAcceptance.js +16 -16
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewRound.js +21 -20
- package/dist/review/reviewerAvailability.js +2 -2
- package/dist/role/role.js +51 -7
- package/dist/role/taskRoleUpdate.js +30 -0
- package/dist/runtime/acpProtocol.js +425 -0
- package/dist/runtime/acpSession.js +731 -0
- package/dist/runtime/acpSessionConfiguration.js +260 -0
- package/dist/runtime/agentDriver.js +30 -11
- package/dist/runtime/agentEndpoint.js +278 -0
- package/dist/runtime/agentEndpointIdentity.js +86 -0
- package/dist/runtime/agentEndpointOwnership.js +239 -0
- package/dist/runtime/agentError.js +2 -10
- package/dist/runtime/agentHost.js +565 -314
- package/dist/runtime/agentRunConfiguration.js +258 -0
- package/dist/runtime/builtinAgentDrivers.js +134 -18
- package/dist/runtime/builtinAgentErrorMappers.js +55 -3
- package/dist/runtime/builtinTranscriptUsage.js +1 -1
- package/dist/runtime/claude-process-owner +0 -0
- package/dist/runtime/codexAppServerRuntime.js +38 -30
- package/dist/runtime/codexInteractiveHost.js +41 -6
- package/dist/runtime/continuationManager.js +2 -6
- package/dist/runtime/executionEnvironment.js +30 -0
- package/dist/runtime/firstProgressAdvisory.js +11 -11
- package/dist/runtime/index.js +4 -3
- package/dist/runtime/jsonLineChannel.js +109 -0
- package/dist/runtime/launchBroker.js +91 -16
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +10 -18
- package/dist/runtime/managedCaller.js +61 -17
- package/dist/runtime/nativeSessionControl.js +102 -0
- package/dist/runtime/ports.js +6 -21
- package/dist/runtime/processExitObservation.js +8 -7
- package/dist/runtime/promptEnvelope.js +17 -6
- package/dist/runtime/providerContinuation.js +3 -9
- package/dist/runtime/providerContinuationReconciliationService.js +4 -13
- package/dist/runtime/providerControl.js +2 -7
- package/dist/runtime/providerRuntimeIdentity.js +110 -222
- package/dist/runtime/providerRuntimeReconciler.js +5 -9
- package/dist/runtime/runtimeBinding.js +0 -1
- package/dist/runtime/runtimeContinuationProjection.js +4 -7
- package/dist/runtime/runtimeDeadlines.js +9 -0
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +29 -65
- package/dist/runtime/runtimeProjection.js +43 -51
- package/dist/runtime/runtimeSessionCandidate.js +1 -3
- package/dist/runtime/sessionLaunchRequest.js +3 -7
- package/dist/runtime/sessionOwnerIdentity.js +7 -54
- package/dist/runtime/sessionOwnerRegistry.js +22 -17
- package/dist/runtime/sessionReconciliation.js +4 -8
- package/dist/runtime/sessionTerminationGuard.js +70 -259
- package/dist/runtime/sessionTokenMetrics.js +5 -16
- package/dist/runtime/structuredProviderHost.js +237 -117
- package/dist/runtime/taskRuntimeIsolation.js +39 -122
- package/dist/runtime/tmuxAdapters.js +39 -86
- package/dist/scheduler/activeRoleRunDelivery.js +354 -0
- package/dist/scheduler/leaderWakeupProcessor.js +75 -266
- package/dist/scheduler/operatorInputNotificationProcessor.js +1 -1
- package/dist/scheduler/ports.js +80 -9
- package/dist/scheduler/{roleTurnLiveness.js → roleRunLiveness.js} +26 -30
- package/dist/scheduler/{roleTurnStall.js → roleRunStall.js} +128 -139
- package/dist/scheduler/taskExecutionProjection.js +120 -124
- package/dist/scheduler/taskObservabilityProjection.js +29 -29
- package/dist/scheduler/taskWake.js +11 -4
- package/dist/scheduler/wakeReason.js +9 -1
- package/dist/setup/setupCommand.js +3 -7
- package/dist/storage/migrations/agentRunContract.js +159 -0
- package/dist/storage/migrations/artifactsToGit.js +338 -0
- package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
- package/dist/storage/migrations/submitIntent.js +126 -0
- package/dist/storage/sqliteSchema.js +467 -7
- package/dist/storage/sqliteStore.js +355 -220
- package/dist/storage/storageVersions.js +1 -1
- package/dist/storage/storeRpc.js +10 -5
- package/dist/storage/taskStore.js +13 -11
- package/dist/storage/upgrade/upgradeOrchestrator.js +5 -7
- package/dist/surface/surfaceContributions.js +102 -0
- package/dist/task/completionReadiness.js +32 -6
- package/dist/task/deliveryGuard.js +16 -16
- package/dist/task/draftPlan.js +72 -12
- package/dist/task/nextAction.js +144 -128
- package/dist/task/remoteDelivery.js +6 -6
- package/dist/task/task.js +184 -18
- package/dist/task/taskActivation.js +327 -0
- package/dist/task/taskActivationService.js +408 -0
- package/dist/task/taskRecordReference.js +5 -4
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/task/taskSubmission.js +236 -0
- package/dist/telemetry/sqliteTelemetryStore.js +55 -68
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +2 -2
- package/dist/web/assets/assetManifest.js +2 -0
- package/dist/web/assets/client/app.js +121 -20
- package/dist/web/assets/client/components.js +87 -54
- package/dist/web/assets/client/i18n.js +83 -41
- package/dist/web/assets/client/markdown.js +1 -1
- package/dist/web/assets/client/taskSurface.js +442 -0
- package/dist/web/assets/client/view.js +49 -44
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +22 -4
- package/dist/web/controllerWeb.js +60 -0
- package/dist/web/webMutation.js +28 -0
- package/dist/web/webServer.js +133 -8
- package/dist/web/webSnapshot.js +81 -74
- package/dist/web/webTaskSurface.js +64 -0
- package/dist/workItem/dependencyGate.js +1 -1
- package/dist/workItem/workItem.js +84 -48
- package/dist/workspace/workItemChangeSetManager.js +16 -9
- package/docs/agent-result-consumption.md +96 -0
- package/docs/agent-result-consumption.zh-CN.md +81 -0
- package/docs/agent-runtime-drivers.md +93 -0
- package/docs/agent-runtime-drivers.zh-CN.md +77 -0
- package/docs/architecture/README.md +50 -0
- package/docs/architecture/README.zh-CN.md +43 -0
- package/docs/architecture/capabilities-and-resources.md +118 -0
- package/docs/architecture/capabilities-and-resources.zh-CN.md +83 -0
- package/docs/managed-turn-and-session-runtime.md +224 -0
- package/docs/managed-turn-and-session-runtime.zh-CN.md +180 -0
- package/docs/observability/README.md +83 -0
- package/docs/observability/README.zh-CN.md +71 -0
- package/docs/plugin-sdk.md +393 -0
- package/docs/plugin-sdk.zh-CN.md +293 -0
- package/docs/provider-runtime.md +165 -0
- package/docs/provider-runtime.zh-CN.md +132 -0
- package/docs/release-workflow.md +305 -0
- package/docs/release-workflow.zh-CN.md +237 -0
- package/docs/roles-and-configuration.md +115 -0
- package/docs/roles-and-configuration.zh-CN.md +96 -0
- package/docs/sqlite-control-plane-design.md +78 -0
- package/docs/sqlite-control-plane-design.zh-CN.md +62 -0
- package/docs/task-dag-semantics.md +80 -0
- package/docs/task-dag-semantics.zh-CN.md +59 -0
- package/docs/task-delivery.md +105 -0
- package/docs/task-delivery.zh-CN.md +82 -0
- package/docs/task-local-identity.md +8 -6
- package/docs/task-local-identity.zh-CN.md +58 -0
- package/docs/testing/verification-levels.md +88 -0
- package/docs/testing/verification-levels.zh-CN.md +69 -0
- package/i18n/README.zh-CN.md +270 -722
- package/package.json +3 -2
- package/skills/yui-leader/SKILL.md +88 -304
- package/skills/yui-leader/references/execution.md +303 -0
- package/skills/yui-leader/references/integration.md +39 -0
- package/skills/yui-leader/references/planning.md +109 -0
- package/skills/yui-leader/references/replicated-execution.md +42 -0
- package/skills/yui-leader/references/task-plugins.md +37 -0
- package/skills/yui-operator/SKILL.md +46 -62
- package/skills/yui-reviewer/SKILL.md +35 -36
- package/skills/yui-runtime/SKILL.md +88 -24
- package/skills/yui-runtime/references/publication.md +22 -0
- package/skills/yui-runtime/references/recovery.md +64 -0
- package/skills/yui-worker/SKILL.md +37 -39
- package/dist/cli/roleOptionCatalog.js +0 -68
- package/dist/context/sourceTurnContext.js +0 -30
- package/dist/execution/reviewMainTurn.js +0 -161
- package/dist/execution/workItemMainTurn.js +0 -164
- package/dist/lifecycle/exactTurnTerminalization.js +0 -407
- package/dist/runtime/preallocatedNativeSession.js +0 -13
- package/dist/runtime/runtimeStopReceipt.js +0 -42
- package/dist/scheduler/activeRoleTurnDelivery.js +0 -315
|
@@ -1,407 +0,0 @@
|
|
|
1
|
-
import { isDeepStrictEqual } from "node:util";
|
|
2
|
-
import { completeProcessing } from "../coordination/workMailbox.js";
|
|
3
|
-
import { captureRoleTurnDispatch, settleRoleTurnDispatch } from "../coordination/workMailboxQueue.js";
|
|
4
|
-
import { finishReviewRound, updateReviewExecutionGroup } from "../review/reviewRound.js";
|
|
5
|
-
import { completeTurn, failTurn } from "../turn/turn.js";
|
|
6
|
-
import { boundedTurnFailureDiagnostic } from "../domain/agentResultTransport.js";
|
|
7
|
-
import { updateExecutionLane, updateWorkItemExecutionLane } from "../execution/workItemExecution.js";
|
|
8
|
-
import { reconcileWorkItemMainTurns } from "../execution/workItemMainTurn.js";
|
|
9
|
-
import { reconcileReviewMainTurns } from "../execution/reviewMainTurn.js";
|
|
10
|
-
import { isRuntimeLaunchReservation, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
11
|
-
import { managedProviderTurnId } from "../runtime/providerRuntimeIdentity.js";
|
|
12
|
-
import { latestTurnDurableProgressAt } from "../scheduler/roleTurnStall.js";
|
|
13
|
-
import { markTaskWakeConsumed } from "../scheduler/taskWake.js";
|
|
14
|
-
import { workItemExecutionGroupById, updateWorkItemExecutionGroup } from "../workItem/workItem.js";
|
|
15
|
-
/**
|
|
16
|
-
* Validate every immutable identity and frozen Project head needed before a
|
|
17
|
-
* review Turn can settle any mailbox or Round state. This is deliberately
|
|
18
|
-
* read-only: callers use it as the compare-and-swap fence immediately before
|
|
19
|
-
* their aggregate mutation.
|
|
20
|
-
*/
|
|
21
|
-
export function validateExactTurnReviewRound(store, turn, options = {}) {
|
|
22
|
-
if (turn.purpose !== "review")
|
|
23
|
-
return { disposition: "applied", round: null };
|
|
24
|
-
if (turn.reviewRoundId === undefined) {
|
|
25
|
-
return { disposition: "obsolete", round: null, reason: "review-round-missing" };
|
|
26
|
-
}
|
|
27
|
-
const round = store.getReviewRound(turn.taskId, turn.reviewRoundId);
|
|
28
|
-
if (round === null) {
|
|
29
|
-
return { disposition: "obsolete", round: null, reason: "review-round-missing" };
|
|
30
|
-
}
|
|
31
|
-
if (!options.allowTerminal
|
|
32
|
-
&& round.status !== "pending" && round.status !== "running") {
|
|
33
|
-
return { disposition: "obsolete", round, reason: "review-round-terminal" };
|
|
34
|
-
}
|
|
35
|
-
const lane = round.executionGroup?.lanes.find(({ id }) => id === turn.executionLaneId);
|
|
36
|
-
const exactReviewerTurn = round.reviewerTurnId === turn.id
|
|
37
|
-
|| lane?.currentTurnId === turn.id;
|
|
38
|
-
const exactReviewerRole = round.reviewerRoleName === turn.roleName || lane?.roleName === turn.roleName;
|
|
39
|
-
if (!exactReviewerTurn
|
|
40
|
-
|| !exactReviewerRole
|
|
41
|
-
|| round.workItemId !== turn.workItemId
|
|
42
|
-
|| round.reviewBaseCommit !== turn.effective.reviewBaseCommit) {
|
|
43
|
-
return { disposition: "obsolete", round, reason: "review-round-mismatch" };
|
|
44
|
-
}
|
|
45
|
-
const laneWorkspaceRoot = lane?.workspace?.root;
|
|
46
|
-
if (turn.workspace === undefined || round.workspace === undefined
|
|
47
|
-
|| (laneWorkspaceRoot === undefined && !isDeepStrictEqual(turn.workspace, round.workspace))
|
|
48
|
-
|| (laneWorkspaceRoot !== undefined && turn.workspace.root !== laneWorkspaceRoot)) {
|
|
49
|
-
return { disposition: "obsolete", round, reason: "review-workspace-mismatch" };
|
|
50
|
-
}
|
|
51
|
-
const storedWorkspace = turn.workspace.owner.type === "execution-lane"
|
|
52
|
-
? store.getManagedWorkspace(turn.workspace.owner)
|
|
53
|
-
: store.getReviewRoundWorkspace(turn.taskId, round.id);
|
|
54
|
-
if (storedWorkspace === null
|
|
55
|
-
|| (turn.workspace.owner.type !== "execution-lane"
|
|
56
|
-
&& !isDeepStrictEqual(storedWorkspace, round.workspace))
|
|
57
|
-
|| !isDeepStrictEqual(storedWorkspace, turn.workspace)) {
|
|
58
|
-
return { disposition: "obsolete", round, reason: "review-workspace-drift" };
|
|
59
|
-
}
|
|
60
|
-
if (turn.workspace.owner.type !== "execution-lane") {
|
|
61
|
-
if (storedWorkspace.owner.type !== "review-round"
|
|
62
|
-
|| storedWorkspace.owner.taskId !== turn.taskId
|
|
63
|
-
|| storedWorkspace.owner.reviewRoundId !== round.id) {
|
|
64
|
-
return { disposition: "obsolete", round, reason: "review-workspace-owner-mismatch" };
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
if (turn.workspace.owner.type === "execution-lane"
|
|
68
|
-
&& (turn.workspace.owner.purpose !== "review"
|
|
69
|
-
|| turn.workspace.owner.executionGroupId !== turn.executionGroupId
|
|
70
|
-
|| turn.workspace.owner.executionLaneId !== turn.executionLaneId
|
|
71
|
-
|| turn.workspace.owner.reviewRoundId !== round.id)) {
|
|
72
|
-
return { disposition: "obsolete", round, reason: "review-lane-workspace-owner-mismatch" };
|
|
73
|
-
}
|
|
74
|
-
if (turn.workspace.owner.type === "execution-lane") {
|
|
75
|
-
if (lane === undefined
|
|
76
|
-
|| lane.currentTurnId !== turn.id
|
|
77
|
-
|| lane.roleName !== turn.roleName
|
|
78
|
-
|| lane.workspace?.root !== turn.workspace.root
|
|
79
|
-
|| lane.workspace.writableProjectIds.length !== turn.workspace.entries.length
|
|
80
|
-
|| turn.workspace.entries.some((entry) => (entry.access !== "write"
|
|
81
|
-
|| !lane.workspace.writableProjectIds.includes(entry.projectId)))) {
|
|
82
|
-
return { disposition: "obsolete", round, reason: "review-lane-workspace-lineage-mismatch" };
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
const task = store.getTask(turn.taskId);
|
|
86
|
-
const taskScope = (round.scope ?? "work-item") === "task";
|
|
87
|
-
const item = taskScope || round.workItemId === undefined
|
|
88
|
-
? null
|
|
89
|
-
: store.getWorkItem(turn.taskId, round.workItemId);
|
|
90
|
-
if (!taskScope && item === null) {
|
|
91
|
-
return { disposition: "obsolete", round, reason: "review-work-item-missing" };
|
|
92
|
-
}
|
|
93
|
-
const candidate = taskScope
|
|
94
|
-
? undefined
|
|
95
|
-
: item.candidates.find(({ id }) => id === round.candidateId);
|
|
96
|
-
if (!taskScope && candidate === undefined) {
|
|
97
|
-
return { disposition: "obsolete", round, reason: "review-candidate-missing" };
|
|
98
|
-
}
|
|
99
|
-
const frozenProjects = taskScope
|
|
100
|
-
? round.taskCandidate?.projects
|
|
101
|
-
: candidate?.gitSnapshot?.projects;
|
|
102
|
-
if (taskScope) {
|
|
103
|
-
if (task === null || round.taskCandidate === undefined) {
|
|
104
|
-
return { disposition: "obsolete", round, reason: "review-task-candidate-missing" };
|
|
105
|
-
}
|
|
106
|
-
if (frozenProjects === undefined
|
|
107
|
-
|| new Set(frozenProjects.map(({ projectId }) => projectId)).size
|
|
108
|
-
!== task.projectBindings.length
|
|
109
|
-
|| task.projectBindings.some(({ projectId }) => (!frozenProjects.some((project) => project.projectId === projectId)))) {
|
|
110
|
-
return { disposition: "obsolete", round, reason: "review-frozen-project-scope-drift" };
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
else if (candidate?.gitSnapshot !== undefined
|
|
114
|
-
&& candidate.gitSnapshot.reviewBaseCommit !== round.reviewBaseCommit) {
|
|
115
|
-
return { disposition: "obsolete", round, reason: "review-candidate-snapshot-drift" };
|
|
116
|
-
}
|
|
117
|
-
if (!taskScope && frozenProjects === undefined) {
|
|
118
|
-
return { disposition: "applied", round };
|
|
119
|
-
}
|
|
120
|
-
if (frozenProjects === undefined
|
|
121
|
-
|| storedWorkspace.entries.length !== frozenProjects.length) {
|
|
122
|
-
return { disposition: "obsolete", round, reason: "review-frozen-project-scope-drift" };
|
|
123
|
-
}
|
|
124
|
-
const frozenByProject = new Map(frozenProjects.map(({ projectId, commit }) => [projectId, commit]));
|
|
125
|
-
if (storedWorkspace.entries.some((entry) => (entry.access !== "write"
|
|
126
|
-
|| frozenByProject.get(entry.projectId) !== entry.baseCommit
|
|
127
|
-
|| entry.baseRef !== entry.baseCommit))) {
|
|
128
|
-
return { disposition: "obsolete", round, reason: "review-frozen-head-drift" };
|
|
129
|
-
}
|
|
130
|
-
return { disposition: "applied", round };
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Atomically terminalizes the exact ReviewRound bound to a review Turn.
|
|
134
|
-
* The round must still be pending/running and its reviewer identity must match
|
|
135
|
-
* the Turn exactly. This is the sole review-round convergence primitive shared
|
|
136
|
-
* by the exact Turn terminalization path and the pre-delivery launch-failure
|
|
137
|
-
* path: a failed review Turn must never leave its Round stranded.
|
|
138
|
-
*/
|
|
139
|
-
export function terminalizeExactTurnReviewRound(store, input, now) {
|
|
140
|
-
const validation = validateExactTurnReviewRound(store, input.turn);
|
|
141
|
-
if (validation.disposition !== "applied" || validation.round === null) {
|
|
142
|
-
return validation;
|
|
143
|
-
}
|
|
144
|
-
const reviewRound = validation.round;
|
|
145
|
-
if (input.turn.executionGroupId !== undefined
|
|
146
|
-
&& input.turn.executionLaneId !== undefined) {
|
|
147
|
-
// Producer Turns own only their immutable Turn result. The unified Group
|
|
148
|
-
// is advanced after that result is validated and stored below.
|
|
149
|
-
return { disposition: "applied", round: reviewRound };
|
|
150
|
-
}
|
|
151
|
-
const terminal = finishReviewRound(reviewRound, input.outcome.status, now, input.outcome.status === "failed"
|
|
152
|
-
? { kind: "execution", message: input.outcome.diagnostic }
|
|
153
|
-
: undefined);
|
|
154
|
-
store.saveReviewRound(input.taskId, terminal);
|
|
155
|
-
return { disposition: "applied", round: terminal };
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Retire one stranded active Turn only after its exact Provider Turn is
|
|
159
|
-
* terminal and every durable execution fence is quiet. The caller owns the
|
|
160
|
-
* surrounding aggregate transaction so the Turn, ReviewRound/Lane, mailbox,
|
|
161
|
-
* Session, and append-only retirement record commit together.
|
|
162
|
-
*/
|
|
163
|
-
export function retireExactActiveTurn(store, input, now) {
|
|
164
|
-
const current = store.getTurn(input.taskId, input.turnId);
|
|
165
|
-
const stateChanged = (reason) => ({
|
|
166
|
-
disposition: "state-changed",
|
|
167
|
-
turn: current,
|
|
168
|
-
...(current === null ? {} : { progressAt: latestTurnDurableProgressAt(store, input.taskId, input.roleName, input.turnId)?.progressAt }),
|
|
169
|
-
reason
|
|
170
|
-
});
|
|
171
|
-
const task = store.getTask(input.taskId);
|
|
172
|
-
if (task === null)
|
|
173
|
-
return stateChanged("task-missing");
|
|
174
|
-
if (task.status !== "active")
|
|
175
|
-
return stateChanged("task-terminal");
|
|
176
|
-
if (current === null)
|
|
177
|
-
return stateChanged("turn-missing");
|
|
178
|
-
if (current.status !== "active")
|
|
179
|
-
return stateChanged("turn-terminal");
|
|
180
|
-
if (current.taskId !== input.taskId || current.roleName !== input.roleName) {
|
|
181
|
-
return stateChanged("turn-owner-mismatch");
|
|
182
|
-
}
|
|
183
|
-
if (current.effective.agentId !== input.agentId
|
|
184
|
-
|| current.effective.adapterId !== input.adapterId) {
|
|
185
|
-
return stateChanged("turn-launch-identity-mismatch");
|
|
186
|
-
}
|
|
187
|
-
const active = current.executionGroupId !== undefined && current.executionLaneId !== undefined
|
|
188
|
-
? store.getActiveExecutionLaneTurn(input.taskId, current.executionGroupId, current.executionLaneId)
|
|
189
|
-
: store.getActiveTurn(input.taskId, input.roleName);
|
|
190
|
-
if (active?.id !== current.id)
|
|
191
|
-
return stateChanged("active-turn-mismatch");
|
|
192
|
-
const progress = latestTurnDurableProgressAt(store, input.taskId, input.roleName, input.turnId);
|
|
193
|
-
if (progress === null)
|
|
194
|
-
return stateChanged("progress-unavailable");
|
|
195
|
-
if (progress.progressAt !== input.expectedProgressAt) {
|
|
196
|
-
return { ...stateChanged("progress-fence-mismatch"), progressAt: progress.progressAt };
|
|
197
|
-
}
|
|
198
|
-
const sessions = store.getTaskRoleSessionSet(input.taskId, input.roleName);
|
|
199
|
-
const terminalInput = {
|
|
200
|
-
taskId: input.taskId,
|
|
201
|
-
roleName: input.roleName,
|
|
202
|
-
agentId: input.agentId,
|
|
203
|
-
turnId: input.turnId,
|
|
204
|
-
...(input.nativeSessionId === undefined ? {} : { nativeSessionId: input.nativeSessionId }),
|
|
205
|
-
...(input.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: input.runtimeGenerationId }),
|
|
206
|
-
outcome: { status: "failed", diagnostic: input.reason, failureReason: "missing-result" }
|
|
207
|
-
};
|
|
208
|
-
const session = sessions?.sessions[input.agentId];
|
|
209
|
-
const providerBinding = sessions?.providerBinding;
|
|
210
|
-
const providerTurn = providerBinding?.turn;
|
|
211
|
-
const providerSettled = managedProviderTurnId(providerTurn) === current.id
|
|
212
|
-
&& (providerTurn?.status === "completed"
|
|
213
|
-
|| providerTurn?.status === "failed"
|
|
214
|
-
|| providerTurn?.status === "cancelled"
|
|
215
|
-
|| providerTurn?.status === "rejected");
|
|
216
|
-
if (session?.status === "active" && !providerSettled) {
|
|
217
|
-
return {
|
|
218
|
-
disposition: "blocked",
|
|
219
|
-
turn: current,
|
|
220
|
-
progressAt: progress.progressAt,
|
|
221
|
-
reason: "runtime-not-terminal"
|
|
222
|
-
};
|
|
223
|
-
}
|
|
224
|
-
const terminal = terminalizeExactTaskTurn(store, terminalInput, now);
|
|
225
|
-
if (terminal.disposition !== "applied" || terminal.turn === null) {
|
|
226
|
-
return stateChanged(terminal.reason ?? "terminalization-fence-mismatch");
|
|
227
|
-
}
|
|
228
|
-
return {
|
|
229
|
-
disposition: "applied",
|
|
230
|
-
turn: terminal.turn,
|
|
231
|
-
progressAt: progress.progressAt
|
|
232
|
-
};
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Applies one exact application-level terminal fact inside the caller's
|
|
236
|
-
* TaskStore transaction. All caller-owned outcome records can therefore
|
|
237
|
-
* be saved in the same aggregate commit.
|
|
238
|
-
*/
|
|
239
|
-
export function terminalizeExactTaskTurn(store, input, now) {
|
|
240
|
-
const turn = store.getTurn(input.taskId, input.turnId);
|
|
241
|
-
if (turn === null)
|
|
242
|
-
return obsolete(null, "turn-missing");
|
|
243
|
-
if (turn.status !== "active")
|
|
244
|
-
return obsolete(turn, "turn-terminal");
|
|
245
|
-
if (turn.taskId !== input.taskId || turn.roleName !== input.roleName) {
|
|
246
|
-
return obsolete(turn, "turn-owner-mismatch");
|
|
247
|
-
}
|
|
248
|
-
if (turn.effective.agentId !== input.agentId) {
|
|
249
|
-
return obsolete(turn, "turn-agent-mismatch");
|
|
250
|
-
}
|
|
251
|
-
const role = store.getRole(input.taskId, input.roleName);
|
|
252
|
-
if (role === null)
|
|
253
|
-
return obsolete(turn, "role-missing");
|
|
254
|
-
const active = turn.executionGroupId !== undefined && turn.executionLaneId !== undefined
|
|
255
|
-
? store.getActiveExecutionLaneTurn(input.taskId, turn.executionGroupId, turn.executionLaneId)
|
|
256
|
-
: store.getActiveTurn(input.taskId, input.roleName);
|
|
257
|
-
if (active?.id !== turn.id)
|
|
258
|
-
return obsolete(turn, "active-turn-mismatch");
|
|
259
|
-
const sessions = store.getTaskRoleSessionSet(input.taskId, input.roleName);
|
|
260
|
-
// Validate the exact ReviewRound, Candidate, stored workspace, and frozen
|
|
261
|
-
// Project heads before any mailbox or Round write.
|
|
262
|
-
const reviewValidation = validateExactTurnReviewRound(store, turn);
|
|
263
|
-
if (reviewValidation.disposition !== "applied") {
|
|
264
|
-
return obsolete(turn, reviewValidation.reason ?? "review-round-mismatch");
|
|
265
|
-
}
|
|
266
|
-
const requiredSnapshotProjects = [...new Set(turn.effective.writeProjectIds)].sort();
|
|
267
|
-
const observedSnapshotProjects = input.systemEvidence?.workspaceSnapshot?.projects
|
|
268
|
-
.map(({ projectId }) => projectId)
|
|
269
|
-
.sort();
|
|
270
|
-
const laneSnapshotRequired = input.outcome.status === "completed"
|
|
271
|
-
&& turn.executionGroupId !== undefined
|
|
272
|
-
&& turn.executionLaneId !== undefined
|
|
273
|
-
&& requiredSnapshotProjects.length > 0;
|
|
274
|
-
const missingLaneSnapshot = laneSnapshotRequired
|
|
275
|
-
&& (observedSnapshotProjects === undefined
|
|
276
|
-
|| !isDeepStrictEqual(observedSnapshotProjects, requiredSnapshotProjects));
|
|
277
|
-
const workspaceFailure = laneSnapshotRequired
|
|
278
|
-
? input.workspaceFailure ?? (missingLaneSnapshot
|
|
279
|
-
? {
|
|
280
|
-
failureReason: "workspace-unavailable",
|
|
281
|
-
diagnostic: "Core could not freeze the exact clean writable Lane workspace."
|
|
282
|
-
}
|
|
283
|
-
: undefined)
|
|
284
|
-
: undefined;
|
|
285
|
-
const effectiveOutcome = input.outcome.status === "completed" && workspaceFailure !== undefined
|
|
286
|
-
? {
|
|
287
|
-
status: "failed",
|
|
288
|
-
output: input.outcome.output,
|
|
289
|
-
diagnostic: workspaceFailure.diagnostic,
|
|
290
|
-
failureReason: workspaceFailure.failureReason,
|
|
291
|
-
...(input.outcome.provider === undefined ? {} : { provider: input.outcome.provider })
|
|
292
|
-
}
|
|
293
|
-
: input.outcome;
|
|
294
|
-
const terminalOutcome = effectiveOutcome.status === "failed"
|
|
295
|
-
? {
|
|
296
|
-
...effectiveOutcome,
|
|
297
|
-
diagnostic: boundedTurnFailureDiagnostic(effectiveOutcome.diagnostic)
|
|
298
|
-
}
|
|
299
|
-
: effectiveOutcome;
|
|
300
|
-
// All Turn, active-pointer, Session, launch, and mailbox fences have passed.
|
|
301
|
-
// Only now may the exact ReviewRound be terminalized alongside the Turn so a
|
|
302
|
-
// stale fence never leaves a Round written while the Turn stays active.
|
|
303
|
-
const reviewRoundTerminalization = terminalizeExactTurnReviewRound(store, {
|
|
304
|
-
taskId: input.taskId,
|
|
305
|
-
turn,
|
|
306
|
-
outcome: terminalOutcome
|
|
307
|
-
}, now);
|
|
308
|
-
if (reviewRoundTerminalization.disposition !== "applied") {
|
|
309
|
-
return obsolete(turn, reviewRoundTerminalization.reason ?? "review-round-mismatch");
|
|
310
|
-
}
|
|
311
|
-
const terminal = terminalOutcome.status === "completed"
|
|
312
|
-
? completeTurn(turn, terminalOutcome.output, now, terminalOutcome.provider, input.systemEvidence)
|
|
313
|
-
: failTurn(turn, terminalOutcome.failureReason, terminalOutcome.diagnostic, now, terminalOutcome.provider, terminalOutcome.output);
|
|
314
|
-
if (turn.executionGroupId !== undefined
|
|
315
|
-
&& turn.executionLaneId !== undefined
|
|
316
|
-
&& turn.purpose === "execution"
|
|
317
|
-
&& turn.workItemId !== undefined) {
|
|
318
|
-
const item = store.getWorkItem(input.taskId, turn.workItemId);
|
|
319
|
-
const group = item === null
|
|
320
|
-
? undefined
|
|
321
|
-
: workItemExecutionGroupById(item, turn.executionGroupId);
|
|
322
|
-
if (item !== null && group !== undefined) {
|
|
323
|
-
if (terminal.status === "completed") {
|
|
324
|
-
const grouped = updateWorkItemExecutionLane(group, turn.executionLaneId, {
|
|
325
|
-
currentTurnId: turn.id,
|
|
326
|
-
successfulTurnId: turn.id,
|
|
327
|
-
disposition: "succeeded"
|
|
328
|
-
}, now);
|
|
329
|
-
store.saveWorkItem(input.taskId, updateWorkItemExecutionGroup(item, grouped, now));
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
if (turn.executionGroupId !== undefined
|
|
334
|
-
&& turn.executionLaneId !== undefined
|
|
335
|
-
&& turn.purpose === "review"
|
|
336
|
-
&& turn.reviewRoundId !== undefined) {
|
|
337
|
-
const round = store.getReviewRound(input.taskId, turn.reviewRoundId);
|
|
338
|
-
const group = round?.executionGroup;
|
|
339
|
-
if (round !== null
|
|
340
|
-
&& round !== undefined
|
|
341
|
-
&& group !== undefined
|
|
342
|
-
&& group.id === turn.executionGroupId) {
|
|
343
|
-
if (terminal.status === "completed") {
|
|
344
|
-
const grouped = updateExecutionLane(group, turn.executionLaneId, {
|
|
345
|
-
currentTurnId: turn.id,
|
|
346
|
-
successfulTurnId: turn.id,
|
|
347
|
-
disposition: "succeeded"
|
|
348
|
-
}, now);
|
|
349
|
-
store.saveReviewRound(input.taskId, updateReviewExecutionGroup(round, grouped));
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
store.saveTurn(terminal);
|
|
354
|
-
const dispatchIdentity = {
|
|
355
|
-
taskId: terminal.taskId,
|
|
356
|
-
roleName: terminal.roleName,
|
|
357
|
-
turnId: terminal.id
|
|
358
|
-
};
|
|
359
|
-
const dispatchToken = captureRoleTurnDispatch(store.getWorkMailbox({
|
|
360
|
-
kind: "role",
|
|
361
|
-
taskId: terminal.taskId,
|
|
362
|
-
roleName: terminal.roleName
|
|
363
|
-
}), dispatchIdentity);
|
|
364
|
-
settleRoleTurnDispatch(store, dispatchIdentity, dispatchToken);
|
|
365
|
-
if (terminal.roleName === "leader") {
|
|
366
|
-
const wake = store.listTaskWakes(input.taskId)
|
|
367
|
-
.find((candidate) => candidate.turnId === terminal.id && candidate.status === "dispatched");
|
|
368
|
-
if (wake !== undefined) {
|
|
369
|
-
store.saveTaskWake(input.taskId, markTaskWakeConsumed(wake, now));
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
if (terminal.executionGroupId !== undefined && terminal.executionLaneId !== undefined) {
|
|
373
|
-
store.clearActiveExecutionLaneTurn(input.taskId, terminal.executionGroupId, terminal.executionLaneId);
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
store.clearActiveTurn(input.taskId, input.roleName);
|
|
377
|
-
}
|
|
378
|
-
settleLaunchReservation(store, sessions, input);
|
|
379
|
-
reconcileWorkItemMainTurns(store, input.taskId, now);
|
|
380
|
-
reconcileReviewMainTurns(store, input.taskId, now);
|
|
381
|
-
return { disposition: "applied", turn: terminal };
|
|
382
|
-
}
|
|
383
|
-
function settleLaunchReservation(store, sessions, input) {
|
|
384
|
-
const target = runtimeLifecycleTarget({
|
|
385
|
-
scope: "task",
|
|
386
|
-
taskId: input.taskId,
|
|
387
|
-
roleName: input.roleName
|
|
388
|
-
});
|
|
389
|
-
const mailbox = store.getWorkMailbox(target);
|
|
390
|
-
const reservation = mailbox?.processing;
|
|
391
|
-
const session = sessions?.sessions[input.agentId];
|
|
392
|
-
// A late result releases only its original launch, never a successor's
|
|
393
|
-
// reservation merely because both Turns reused the same native Session.
|
|
394
|
-
const runtimeGenerationId = input.runtimeGenerationId ?? session?.runtimeGenerationId;
|
|
395
|
-
if (runtimeGenerationId === undefined || !isRuntimeLaunchReservation(reservation, runtimeGenerationId))
|
|
396
|
-
return;
|
|
397
|
-
const settled = completeProcessing(mailbox, reservation.batchId);
|
|
398
|
-
if (settled.processing === null && settled.pending === null) {
|
|
399
|
-
store.removeWorkMailbox(target);
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
store.saveWorkMailbox(settled);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
function obsolete(turn, reason) {
|
|
406
|
-
return { disposition: "obsolete", turn, reason };
|
|
407
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { resolve } from "node:path";
|
|
3
|
-
import { requireText } from "./validation.js";
|
|
4
|
-
/** Deterministic native identity preallocated for one exact provider launch. */
|
|
5
|
-
export function nativeSessionIdForLaunch(home, runtimeGenerationId, agentId, adapterId) {
|
|
6
|
-
const hex = createHash("sha256").update(JSON.stringify([
|
|
7
|
-
resolve(requireText(home, "YUI_HOME")),
|
|
8
|
-
requireText(runtimeGenerationId, "Runtime generation id"),
|
|
9
|
-
requireText(agentId, "Agent id"),
|
|
10
|
-
requireText(adapterId, "Agent adapter id")
|
|
11
|
-
])).digest("hex");
|
|
12
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-a${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
|
|
13
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { join, resolve } from "node:path";
|
|
4
|
-
export function writeRuntimeStopReceipt(home, runtimeGenerationId, requestedAt) {
|
|
5
|
-
const receipt = Object.freeze({
|
|
6
|
-
schemaVersion: 1,
|
|
7
|
-
receiptId: `runtime-stop-${createHash("sha256")
|
|
8
|
-
.update(`${runtimeGenerationId}\0${requestedAt.toISOString()}`)
|
|
9
|
-
.digest("hex")}`,
|
|
10
|
-
runtimeGenerationId,
|
|
11
|
-
requestedAt: requestedAt.toISOString()
|
|
12
|
-
});
|
|
13
|
-
const path = stopReceiptPath(home, runtimeGenerationId);
|
|
14
|
-
mkdirSync(resolve(join(home, "runtime", "stop-receipts")), { recursive: true, mode: 0o700 });
|
|
15
|
-
const temporary = `${path}.tmp-${process.pid}`;
|
|
16
|
-
writeFileSync(temporary, `${JSON.stringify(receipt)}\n`, { mode: 0o600 });
|
|
17
|
-
renameSync(temporary, path);
|
|
18
|
-
chmodSync(path, 0o600);
|
|
19
|
-
return receipt;
|
|
20
|
-
}
|
|
21
|
-
export function readRuntimeStopReceipt(home, runtimeGenerationId) {
|
|
22
|
-
try {
|
|
23
|
-
const value = JSON.parse(readFileSync(stopReceiptPath(home, runtimeGenerationId), "utf8"));
|
|
24
|
-
if (value.schemaVersion !== 1 || value.runtimeGenerationId !== runtimeGenerationId
|
|
25
|
-
|| typeof value.receiptId !== "string" || !Number.isFinite(Date.parse(value.requestedAt))) {
|
|
26
|
-
throw new Error("Runtime stop receipt is invalid.");
|
|
27
|
-
}
|
|
28
|
-
return Object.freeze({ ...value });
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
if (error.code === "ENOENT")
|
|
32
|
-
return null;
|
|
33
|
-
throw error;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
export function removeRuntimeStopReceipt(home, runtimeGenerationId) {
|
|
37
|
-
rmSync(stopReceiptPath(home, runtimeGenerationId), { force: true });
|
|
38
|
-
}
|
|
39
|
-
function stopReceiptPath(home, runtimeGenerationId) {
|
|
40
|
-
const name = createHash("sha256").update(runtimeGenerationId).digest("hex");
|
|
41
|
-
return resolve(join(home, "runtime", "stop-receipts", `${name}.json`));
|
|
42
|
-
}
|