@zq-silk/yui 0.15.7 → 0.15.8
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 +192 -399
- package/README.md +127 -1149
- 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/brief/taskBrief.js +12 -0
- package/dist/cli/agentConfigurationPicker.js +13 -0
- package/dist/cli/commandCatalog.js +157 -70
- 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 +178 -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 +1 -7
- 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 +259 -0
- package/dist/commands/taskActor.js +28 -49
- package/dist/commands/taskCommands.js +1188 -710
- 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} +146 -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 +458 -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 +114 -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 +247 -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 +62 -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 +380 -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 +123 -0
- package/dist/resources/projectResourceService.js +421 -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 +1 -0
- package/dist/storage/migrations/agentRunContract.js +159 -0
- package/dist/storage/migrations/removeRuntimeGeneration.js +207 -0
- package/dist/storage/sqliteSchema.js +431 -5
- package/dist/storage/sqliteStore.js +375 -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 +301 -0
- package/dist/task/taskActivationService.js +392 -0
- package/dist/task/taskRecordReference.js +5 -4
- package/dist/task/taskRecordRetirement.js +1 -1
- 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 +120 -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 +353 -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 +118 -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 +80 -48
- package/dist/workspace/workItemChangeSetManager.js +16 -9
- package/docs/agent-result-consumption.md +94 -0
- package/docs/agent-runtime-drivers.md +91 -0
- package/docs/architecture/README.md +38 -0
- package/docs/architecture/capabilities-and-resources.md +79 -0
- package/docs/managed-turn-and-session-runtime.md +222 -0
- package/docs/observability/README.md +81 -0
- package/docs/plugin-sdk.md +290 -0
- package/docs/provider-runtime.md +163 -0
- package/docs/release-workflow.md +303 -0
- package/docs/roles-and-configuration.md +113 -0
- package/docs/sqlite-control-plane-design.md +76 -0
- package/docs/task-dag-semantics.md +57 -0
- package/docs/task-delivery.md +103 -0
- package/docs/task-local-identity.md +6 -6
- package/docs/testing/verification-levels.md +86 -0
- package/i18n/README.zh-CN.md +98 -739
- package/package.json +2 -2
- package/skills/yui-leader/SKILL.md +130 -103
- package/skills/yui-leader/references/integration.md +39 -0
- package/skills/yui-leader/references/replicated-execution.md +42 -0
- package/skills/yui-leader/references/task-plugins.md +33 -0
- package/skills/yui-operator/SKILL.md +30 -59
- 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
|
@@ -3,7 +3,7 @@ import { updateExecutionLane } from "../execution/workItemExecution.js";
|
|
|
3
3
|
import { usageError } from "../errors/cliError.js";
|
|
4
4
|
import { requestDurableJobCancel } from "../job/durableJob.js";
|
|
5
5
|
import { finishReviewRound, updateReviewExecutionGroup } from "../review/reviewRound.js";
|
|
6
|
-
import {
|
|
6
|
+
import { failRun } from "../agentRun/agentRun.js";
|
|
7
7
|
import { queueLeaderWakeup } from "../scheduler/wakeupQueue.js";
|
|
8
8
|
import { startTaskExecution, stopTaskExecution } from "../task/task.js";
|
|
9
9
|
import { taskActor } from "./taskActor.js";
|
|
@@ -54,34 +54,34 @@ export function stopTaskExecutionCommand(request, store, options = {}) {
|
|
|
54
54
|
const task = tx.getTask(request.taskId);
|
|
55
55
|
if (task === null)
|
|
56
56
|
throw usageError(`Task not found: ${request.taskId}.`);
|
|
57
|
-
if (task.status !== "active") {
|
|
58
|
-
throw usageError(`Only an
|
|
57
|
+
if (task.status !== "active" && task.status !== "draft") {
|
|
58
|
+
throw usageError(`Only an open Task can be stopped: ${task.id}.`);
|
|
59
59
|
}
|
|
60
60
|
const changed = task.executionGate.state !== "stopped";
|
|
61
61
|
tx.saveTask(stopTaskExecution(task, now));
|
|
62
|
-
const
|
|
62
|
+
const activeRuns = tx.listRuns(task.id).filter((run) => run.status === "active");
|
|
63
63
|
const activeJobs = tx.listDurableJobs(task.id)
|
|
64
64
|
.filter((job) => job.status === "queued" || job.status === "running");
|
|
65
65
|
for (const job of activeJobs) {
|
|
66
66
|
tx.saveDurableJob(task.id, requestDurableJobCancel(job, now));
|
|
67
67
|
}
|
|
68
|
-
failExecutionAttempts(tx, task.id,
|
|
69
|
-
for (const run of
|
|
70
|
-
tx.
|
|
68
|
+
failExecutionAttempts(tx, task.id, activeRuns, request.reason, now);
|
|
69
|
+
for (const run of activeRuns) {
|
|
70
|
+
tx.saveRun(failRun(run, "cancelled", `Task execution stopped: ${request.reason}`, now));
|
|
71
71
|
if (run.executionGroupId !== undefined && run.executionLaneId !== undefined) {
|
|
72
|
-
tx.
|
|
72
|
+
tx.clearActiveExecutionLaneRun(task.id, run.executionGroupId, run.executionLaneId);
|
|
73
73
|
}
|
|
74
|
-
tx.
|
|
74
|
+
tx.clearActiveRun(task.id, run.roleName);
|
|
75
75
|
}
|
|
76
|
-
const roleNames = taskRuntimeRoleNames(tx, task.id,
|
|
76
|
+
const roleNames = taskRuntimeRoleNames(tx, task.id, activeRuns);
|
|
77
77
|
for (const roleName of roleNames) {
|
|
78
|
-
tx.
|
|
78
|
+
tx.clearActiveRun(task.id, roleName);
|
|
79
79
|
}
|
|
80
80
|
// A stop is allowed to discard stale pointer projections even when their
|
|
81
|
-
// historical
|
|
82
|
-
for (const run of tx.
|
|
81
|
+
// historical AgentRuns are already terminal.
|
|
82
|
+
for (const run of tx.listRuns(task.id)) {
|
|
83
83
|
if (run.executionGroupId !== undefined && run.executionLaneId !== undefined) {
|
|
84
|
-
tx.
|
|
84
|
+
tx.clearActiveExecutionLaneRun(task.id, run.executionGroupId, run.executionLaneId);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
for (const mailbox of tx.listWorkMailboxes()) {
|
|
@@ -93,17 +93,17 @@ export function stopTaskExecutionCommand(request, store, options = {}) {
|
|
|
93
93
|
tx.saveEvent(task.id, createTaskEvent(tx.nextEventId(task.id), task.id, "task.execution-stopped", {
|
|
94
94
|
by: actor,
|
|
95
95
|
reason: request.reason,
|
|
96
|
-
terminatedRuns: String(
|
|
96
|
+
terminatedRuns: String(activeRuns.length)
|
|
97
97
|
}, now));
|
|
98
98
|
return {
|
|
99
99
|
taskId: task.id,
|
|
100
100
|
changed,
|
|
101
101
|
roleNames,
|
|
102
|
-
|
|
102
|
+
terminatedRunIds: activeRuns.map(({ id }) => id),
|
|
103
103
|
cancelledJobIds: activeJobs.map(({ id }) => id),
|
|
104
104
|
output: changed
|
|
105
105
|
? `Stopped Task execution: ${task.id}. Progress was preserved; `
|
|
106
|
-
+ `${
|
|
106
|
+
+ `${activeRuns.length} AgentRun record(s) were cancelled and `
|
|
107
107
|
+ `${activeJobs.length} DurableJob(s) were cancelled.`
|
|
108
108
|
: `Task execution is already stopped: ${task.id}. Runtime cleanup will be verified.`
|
|
109
109
|
};
|
|
@@ -117,13 +117,13 @@ export function startTaskExecutionCommand(taskId, store, options = {}) {
|
|
|
117
117
|
const task = tx.getTask(taskId);
|
|
118
118
|
if (task === null)
|
|
119
119
|
throw usageError(`Task not found: ${taskId}.`);
|
|
120
|
-
if (task.status !== "active") {
|
|
121
|
-
throw usageError(`Only an
|
|
120
|
+
if (task.status !== "active" && task.status !== "draft") {
|
|
121
|
+
throw usageError(`Only an open Task can be started: ${task.id}.`);
|
|
122
122
|
}
|
|
123
123
|
if (task.executionGate.state === "enabled") {
|
|
124
124
|
return { taskId: task.id, changed: false, output: `Task execution is already enabled: ${task.id}.` };
|
|
125
125
|
}
|
|
126
|
-
if (tx.
|
|
126
|
+
if (tx.listRuns(task.id).some((run) => run.status === "active")
|
|
127
127
|
|| tx.listDurableJobs(task.id).some((job) => job.status === "queued" || job.status === "running")) {
|
|
128
128
|
throw usageError(`Task still has an active execution attempt: ${task.id}.`);
|
|
129
129
|
}
|
|
@@ -167,12 +167,12 @@ function requireOperatorOrUser(environment, taskId) {
|
|
|
167
167
|
}
|
|
168
168
|
return actor;
|
|
169
169
|
}
|
|
170
|
-
function taskRuntimeRoleNames(store, taskId,
|
|
170
|
+
function taskRuntimeRoleNames(store, taskId, runs) {
|
|
171
171
|
const names = new Set(store.listRoles(taskId).map(({ name }) => name));
|
|
172
172
|
for (const sessions of store.listRoleSessionSets(taskId))
|
|
173
173
|
names.add(sessions.owner.roleName);
|
|
174
|
-
for (const
|
|
175
|
-
names.add(
|
|
174
|
+
for (const run of runs)
|
|
175
|
+
names.add(run.roleName);
|
|
176
176
|
for (const owner of store.listSessionOwners()) {
|
|
177
177
|
if (owner.owner.scope === "task" && owner.owner.taskId === taskId) {
|
|
178
178
|
names.add(owner.owner.roleName);
|
|
@@ -180,24 +180,24 @@ function taskRuntimeRoleNames(store, taskId, turns) {
|
|
|
180
180
|
}
|
|
181
181
|
return [...names].sort();
|
|
182
182
|
}
|
|
183
|
-
function failExecutionAttempts(store, taskId,
|
|
183
|
+
function failExecutionAttempts(store, taskId, runs, reason, now) {
|
|
184
184
|
const summary = `Task execution stopped: ${reason}`;
|
|
185
185
|
const reviewRounds = new Map(store.listReviewRounds(taskId).map((round) => [round.id, round]));
|
|
186
186
|
const affectedReviewRoundIds = new Set();
|
|
187
|
-
for (const
|
|
188
|
-
if (
|
|
189
|
-
affectedReviewRoundIds.add(
|
|
190
|
-
if (
|
|
187
|
+
for (const run of runs) {
|
|
188
|
+
if (run.reviewRoundId !== undefined) {
|
|
189
|
+
affectedReviewRoundIds.add(run.reviewRoundId);
|
|
190
|
+
if (run.executionGroupId === undefined || run.executionLaneId === undefined)
|
|
191
191
|
continue;
|
|
192
|
-
const round = reviewRounds.get(
|
|
193
|
-
const group = round?.executionGroup?.id ===
|
|
192
|
+
const round = reviewRounds.get(run.reviewRoundId);
|
|
193
|
+
const group = round?.executionGroup?.id === run.executionGroupId
|
|
194
194
|
? round.executionGroup
|
|
195
195
|
: undefined;
|
|
196
|
-
const lane = group?.lanes.find(({ id }) => id ===
|
|
196
|
+
const lane = group?.lanes.find(({ id }) => id === run.executionLaneId);
|
|
197
197
|
if (round !== undefined && group !== undefined && lane !== undefined
|
|
198
198
|
&& lane.disposition === "open") {
|
|
199
199
|
reviewRounds.set(round.id, updateReviewExecutionGroup(round, updateExecutionLane(group, lane.id, {
|
|
200
|
-
|
|
200
|
+
currentRunId: run.id,
|
|
201
201
|
disposition: "failed"
|
|
202
202
|
}, now)));
|
|
203
203
|
}
|
|
@@ -5,9 +5,8 @@ import { answerInputRequest, cancelInputRequest, createInputRequest } from "../i
|
|
|
5
5
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
6
6
|
import { formatTimestamp } from "../output/timePresentation.js";
|
|
7
7
|
import { enqueueWork } from "../coordination/workMailboxQueue.js";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { isLinuxProcessLive, listOwnedProcessTree } from "../runtime/sessionOwnerIdentity.js";
|
|
8
|
+
import { isRoleRunStalled, RUN_RECOVERED_EVENT } from "../scheduler/roleRunStall.js";
|
|
9
|
+
import { requireManagedTaskCaller } from "../runtime/managedCaller.js";
|
|
11
10
|
import { resolveTaskRecordReference } from "../task/taskRecordReference.js";
|
|
12
11
|
const LEADER_ROLE = "leader";
|
|
13
12
|
export function runTaskInputCommand(args, store, options) {
|
|
@@ -55,13 +54,13 @@ function createRequest(args, store, options) {
|
|
|
55
54
|
};
|
|
56
55
|
const request = store.transaction((tx) => {
|
|
57
56
|
const task = requireTask(tx, parsed.positionals[0]);
|
|
58
|
-
if (task.status !== "active")
|
|
57
|
+
if (task.status !== "active" && task.status !== "draft")
|
|
59
58
|
throw usageError(inactiveTaskMessage(task, "requesting input"));
|
|
60
59
|
const blockedRefs = blockedValues.map((value) => parseInputBlockedRef(value, task.id));
|
|
61
60
|
validateBlockedInputOwnership(tx, task.id, blockedRefs);
|
|
62
61
|
const origin = requireLeaderInputOrigin(tx, task.id, options.environment);
|
|
63
62
|
const created = createInputRequest(tx.nextInputRequestId(task.id), task.id, origin.requester, { question, choices, blockedRefs, policy }, now);
|
|
64
|
-
const wasStalled =
|
|
63
|
+
const wasStalled = origin.run !== null && isRoleRunStalled(tx.listEvents(task.id), origin.run.id);
|
|
65
64
|
tx.saveInputRequest(task.id, created);
|
|
66
65
|
enqueueWork(tx, { kind: "operator" }, "input-requested", now, [
|
|
67
66
|
{ type: "input", taskId: task.id, id: created.id }
|
|
@@ -69,9 +68,9 @@ function createRequest(args, store, options) {
|
|
|
69
68
|
source: "input-request",
|
|
70
69
|
dedupeKey: `operator-input:${task.id}:${created.id}`
|
|
71
70
|
});
|
|
72
|
-
if (wasStalled) {
|
|
73
|
-
recordTaskEvent(tx, task.id,
|
|
74
|
-
|
|
71
|
+
if (wasStalled && origin.run !== null) {
|
|
72
|
+
recordTaskEvent(tx, task.id, RUN_RECOVERED_EVENT, {
|
|
73
|
+
runId: origin.run.id,
|
|
75
74
|
roleName: LEADER_ROLE,
|
|
76
75
|
progressAt: now.toISOString(),
|
|
77
76
|
kind: "input-request"
|
|
@@ -79,7 +78,8 @@ function createRequest(args, store, options) {
|
|
|
79
78
|
}
|
|
80
79
|
recordTaskEvent(tx, task.id, "input.requested", {
|
|
81
80
|
requestId: created.id,
|
|
82
|
-
|
|
81
|
+
...(created.requester.runId === undefined ? {} : { requesterRunId: created.requester.runId }),
|
|
82
|
+
...(created.requester.nativeSessionId === undefined ? {} : { requesterNativeSessionId: created.requester.nativeSessionId }),
|
|
83
83
|
policy: created.policy.kind
|
|
84
84
|
}, now);
|
|
85
85
|
return created;
|
|
@@ -154,7 +154,7 @@ function answerRequest(args, store, options) {
|
|
|
154
154
|
if (current === null)
|
|
155
155
|
throw dataError(`Input request not found: ${located.id}.`);
|
|
156
156
|
const task = requireTask(tx, current.taskId);
|
|
157
|
-
if (task.status !== "active")
|
|
157
|
+
if (task.status !== "active" && task.status !== "draft")
|
|
158
158
|
throw usageError(inactiveTaskMessage(task, "answering input"));
|
|
159
159
|
const answered = answerInputRequest(current, answer, inputAnswerer(options.environment), now);
|
|
160
160
|
tx.saveInputRequest(task.id, answered);
|
|
@@ -176,7 +176,7 @@ function cancelRequest(args, store, options) {
|
|
|
176
176
|
const now = clock(options);
|
|
177
177
|
const request = store.transaction((tx) => {
|
|
178
178
|
const task = requireTask(tx, parsed.positionals[0]);
|
|
179
|
-
if (task.status !== "active")
|
|
179
|
+
if (task.status !== "active" && task.status !== "draft")
|
|
180
180
|
throw usageError(inactiveTaskMessage(task, "cancelling input"));
|
|
181
181
|
const current = tx.getInputRequest(task.id, parsed.positionals[1]);
|
|
182
182
|
if (current === null)
|
|
@@ -200,33 +200,24 @@ function cancelRequest(args, store, options) {
|
|
|
200
200
|
}
|
|
201
201
|
function requireLeaderInputOrigin(store, taskId, environment) {
|
|
202
202
|
const env = environment ?? {};
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|| env.YUI_TASK_ID !== taskId
|
|
207
|
-
|| env.YUI_ROLE !== LEADER_ROLE
|
|
208
|
-
|| turn === null
|
|
209
|
-
|| env.YUI_AGENT_ID !== turn.effective.agentId
|
|
210
|
-
|| turn.status !== "active"
|
|
211
|
-
|| turn.workItemId !== undefined) {
|
|
212
|
-
throw usageError("Task input request requires the active Leader Turn environment.");
|
|
203
|
+
const caller = requireManagedTaskCaller(store, env);
|
|
204
|
+
if (caller.taskId !== taskId || caller.roleName !== LEADER_ROLE) {
|
|
205
|
+
throw usageError("Only the current Task Leader may request user input.");
|
|
213
206
|
}
|
|
207
|
+
const role = requireRole(store, taskId, LEADER_ROLE);
|
|
208
|
+
const run = store.getActiveRun(taskId, LEADER_ROLE);
|
|
214
209
|
const sessions = store.getTaskRoleSessionSet(taskId, LEADER_ROLE);
|
|
215
|
-
const nativeSessionId =
|
|
216
|
-
if (nativeSessionId !== undefined
|
|
217
|
-
&& sessions?.sessions[turn.effective.agentId]?.nativeSessionId !== nativeSessionId) {
|
|
218
|
-
throw usageError("Task input request native session does not match the active Leader session.");
|
|
219
|
-
}
|
|
210
|
+
const nativeSessionId = caller.nativeSessionId;
|
|
220
211
|
return {
|
|
221
212
|
requester: {
|
|
222
213
|
taskId,
|
|
223
214
|
roleName: "leader",
|
|
224
|
-
agentId:
|
|
225
|
-
|
|
226
|
-
|
|
215
|
+
agentId: caller.agentId,
|
|
216
|
+
...(run === null ? {} : { runId: run.id }),
|
|
217
|
+
nativeSessionId
|
|
227
218
|
},
|
|
228
219
|
role,
|
|
229
|
-
|
|
220
|
+
run,
|
|
230
221
|
sessions
|
|
231
222
|
};
|
|
232
223
|
}
|
|
@@ -235,93 +226,38 @@ function assertInputCancelOrigin(store, request, environment) {
|
|
|
235
226
|
if (isCurrentGlobalOperator(store, env)) {
|
|
236
227
|
return "operator";
|
|
237
228
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|| env.YUI_AGENT_ID !== request.requester.agentId
|
|
242
|
-
|| (request.requester.nativeSessionId !== undefined
|
|
243
|
-
&& env.YUI_NATIVE_SESSION_ID !== request.requester.nativeSessionId)) {
|
|
244
|
-
throw usageError("Only the originating Leader may cancel this input request.");
|
|
229
|
+
const caller = requireManagedTaskCaller(store, env);
|
|
230
|
+
if (caller.taskId !== request.taskId || caller.roleName !== LEADER_ROLE) {
|
|
231
|
+
throw usageError("Only the current Task Leader or Operator may cancel this input request.");
|
|
245
232
|
}
|
|
246
233
|
return "leader";
|
|
247
234
|
}
|
|
248
235
|
export function isCurrentGlobalOperator(store, environment) {
|
|
249
|
-
if (environment.YUI_SESSION_SCOPE !== "global"
|
|
250
|
-
|| environment.YUI_ROLE !== "operator"
|
|
236
|
+
if ((environment.YUI_SESSION_SCOPE !== undefined && environment.YUI_SESSION_SCOPE !== "global")
|
|
237
|
+
|| (environment.YUI_ROLE !== undefined && environment.YUI_ROLE !== "operator")
|
|
251
238
|
|| environment.YUI_TASK_ID !== undefined)
|
|
252
239
|
return false;
|
|
253
240
|
const role = store.getGlobalRole("operator");
|
|
254
241
|
if (role === null)
|
|
255
242
|
return false;
|
|
256
|
-
const agentId = exactIdentity(environment.YUI_AGENT_ID);
|
|
257
|
-
const adapterId = exactIdentity(environment.YUI_ADAPTER_ID);
|
|
258
|
-
const runtimeGenerationId = exactIdentity(environment.YUI_RUNTIME_GENERATION_ID);
|
|
259
|
-
const nativeSessionId = exactIdentity(environment.YUI_NATIVE_SESSION_ID);
|
|
260
243
|
const binding = role.agentBindings[role.activeAgentId];
|
|
261
|
-
if (
|
|
262
|
-
|| adapterId === undefined
|
|
263
|
-
|| runtimeGenerationId === undefined
|
|
264
|
-
|| binding === undefined
|
|
265
|
-
|| binding.agentId !== agentId
|
|
266
|
-
|| binding.adapterId !== adapterId)
|
|
244
|
+
if (binding === undefined)
|
|
267
245
|
return false;
|
|
268
246
|
const sessions = store.getGlobalRoleSessionSet(role.name);
|
|
269
247
|
const session = activeLiveRoleAgentSession(sessions);
|
|
270
248
|
if (sessions === null || session === null || sessions.activeAgentId !== role.activeAgentId) {
|
|
271
|
-
|
|
272
|
-
// that narrow bootstrap window, authenticate against the durable launch
|
|
273
|
-
// reservation and its strongly attributed live process owner instead.
|
|
274
|
-
return nativeSessionId === undefined
|
|
275
|
-
&& binding.adapterId === "codex"
|
|
276
|
-
&& currentProcessBelongsToReservedGlobalLaunch(store, {
|
|
277
|
-
roleName: role.name,
|
|
278
|
-
agentId,
|
|
279
|
-
adapterId,
|
|
280
|
-
runtimeGenerationId
|
|
281
|
-
});
|
|
249
|
+
return false;
|
|
282
250
|
}
|
|
283
|
-
//
|
|
284
|
-
//
|
|
285
|
-
//
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const nativeSessionMatches = binding !== undefined && (nativeSessionId === session.nativeSessionId
|
|
290
|
-
|| (nativeSessionId === undefined
|
|
291
|
-
&& binding.adapterId === "codex"
|
|
292
|
-
&& session.adapterId === "codex"
|
|
293
|
-
&& session.runtimeGenerationId !== undefined
|
|
294
|
-
&& session.runtimeGenerationId === runtimeGenerationId));
|
|
251
|
+
// The provider's conversation survives Host restarts and entry-point changes.
|
|
252
|
+
// Prefer its command-time identity over a launch-time environment snapshot.
|
|
253
|
+
// A launch reservation alone is not a registered Operator conversation.
|
|
254
|
+
const nativeSessionId = exactIdentity(binding.adapterId === "codex"
|
|
255
|
+
? environment.CODEX_THREAD_ID ?? environment.YUI_NATIVE_SESSION_ID
|
|
256
|
+
: environment.YUI_NATIVE_SESSION_ID);
|
|
295
257
|
return binding.agentId === session.agentId
|
|
296
258
|
&& binding.adapterId === session.adapterId
|
|
297
|
-
&&
|
|
298
|
-
&&
|
|
299
|
-
&& session.runtimeGenerationId !== undefined
|
|
300
|
-
&& session.runtimeGenerationId === runtimeGenerationId
|
|
301
|
-
&& nativeSessionMatches;
|
|
302
|
-
}
|
|
303
|
-
function currentProcessBelongsToReservedGlobalLaunch(store, input) {
|
|
304
|
-
if (store.getSessionOwner === undefined || store.getWorkMailbox === undefined)
|
|
305
|
-
return false;
|
|
306
|
-
const mailbox = store.getWorkMailbox(runtimeLifecycleTarget({
|
|
307
|
-
scope: "global",
|
|
308
|
-
roleName: input.roleName
|
|
309
|
-
}));
|
|
310
|
-
if (!isRuntimeLaunchReservation(mailbox?.processing, input.runtimeGenerationId)
|
|
311
|
-
|| hasRuntimeCleanupObligation(mailbox))
|
|
312
|
-
return false;
|
|
313
|
-
const owner = store.getSessionOwner(input.runtimeGenerationId);
|
|
314
|
-
if (owner === null
|
|
315
|
-
|| owner.owner.scope !== "global"
|
|
316
|
-
|| owner.owner.roleName !== input.roleName
|
|
317
|
-
|| owner.agentId !== input.agentId
|
|
318
|
-
|| owner.adapterId !== input.adapterId
|
|
319
|
-
|| owner.runtimeGenerationId !== input.runtimeGenerationId
|
|
320
|
-
|| owner.providerRoot.attribution !== "launch-env"
|
|
321
|
-
|| !isLinuxProcessLive(owner.providerRoot.pid, owner.providerRoot.startIdentity)) {
|
|
322
|
-
return false;
|
|
323
|
-
}
|
|
324
|
-
return listOwnedProcessTree(owner.providerRoot.pid, owner.providerRoot.processGroupId).some(({ pid }) => pid === process.pid);
|
|
259
|
+
&& nativeSessionId !== undefined
|
|
260
|
+
&& nativeSessionId === session.nativeSessionId;
|
|
325
261
|
}
|
|
326
262
|
function inputAnswerer(environment) {
|
|
327
263
|
const env = environment ?? {};
|
|
@@ -342,7 +278,7 @@ function parseInputBlockedRef(value, taskId) {
|
|
|
342
278
|
const separator = value.indexOf(":");
|
|
343
279
|
const type = value.slice(0, separator);
|
|
344
280
|
const id = value.slice(separator + 1).trim();
|
|
345
|
-
if ((type !== "work-item" && type !== "
|
|
281
|
+
if ((type !== "work-item" && type !== "run") || separator <= 0 || id.length === 0) {
|
|
346
282
|
throw usageError("--blocks must use work-item:<id> or turn:<id>.");
|
|
347
283
|
}
|
|
348
284
|
return { type, taskId, id };
|
|
@@ -351,7 +287,7 @@ function validateBlockedInputOwnership(store, taskId, references) {
|
|
|
351
287
|
for (const reference of references) {
|
|
352
288
|
const record = reference.type === "work-item"
|
|
353
289
|
? store.getWorkItem(taskId, reference.id)
|
|
354
|
-
: store.
|
|
290
|
+
: store.getRun(taskId, reference.id);
|
|
355
291
|
if (record === null)
|
|
356
292
|
throw dataError(`Blocked ${reference.type} not found: ${reference.id}.`);
|
|
357
293
|
}
|
|
@@ -386,7 +322,7 @@ function renderInputRequest(request, timeZone) {
|
|
|
386
322
|
`Task: ${request.taskId}`,
|
|
387
323
|
`Status: ${request.status}`,
|
|
388
324
|
`Question: ${request.question}`,
|
|
389
|
-
`Requested by: ${request.requester.agentId}/${request.requester.
|
|
325
|
+
`Requested by: ${request.requester.agentId}/${request.requester.runId ?? request.requester.nativeSessionId}`,
|
|
390
326
|
...(request.choices.length === 0
|
|
391
327
|
? ["Answer type: text"]
|
|
392
328
|
: ["Choices:", ...request.choices.map((choice) => ` ${choice.key}: ${choice.label}`)]),
|
|
@@ -435,7 +371,7 @@ function inactiveTaskMessage(task, action) {
|
|
|
435
371
|
if (task.status === "completed") {
|
|
436
372
|
return `Task ${task.id} is completed; reopen it before ${action}.`;
|
|
437
373
|
}
|
|
438
|
-
if (task.status === "
|
|
374
|
+
if (task.status === "cancelled")
|
|
439
375
|
return `Task ${task.id} is retired; it cannot resume ${action}.`;
|
|
440
376
|
return `Task is archived: ${task.id}.`;
|
|
441
377
|
}
|
|
@@ -7,8 +7,9 @@ import { createIntegrationAttempt, recordResolutionDecision, supersedeIntegratio
|
|
|
7
7
|
import { GitIntegrationService } from "../integration/gitIntegrationService.js";
|
|
8
8
|
import { FileTaskWorkspacePreparer } from "../repository/taskWorkspacePreparer.js";
|
|
9
9
|
import { runTaskIntegrationQueueCommand } from "./taskIntegrationQueueCommands.js";
|
|
10
|
-
import { taskLocalActor } from "./taskActor.js";
|
|
10
|
+
import { assertTaskDeliveryAuthority as taskLocalActor } from "./taskActor.js";
|
|
11
11
|
import { resolveTaskRecordReference } from "../task/taskRecordReference.js";
|
|
12
|
+
import { governingWorkItemCandidate } from "../workItem/workItem.js";
|
|
12
13
|
export async function runTaskIntegrationCommand(args, store, home, options = {}) {
|
|
13
14
|
const now = options.now ?? (() => new Date());
|
|
14
15
|
const [command, ...rest] = args;
|
|
@@ -101,7 +102,7 @@ async function start(args, store, home, now, options) {
|
|
|
101
102
|
const workItem = store.getWorkItem(task.id, workItemId);
|
|
102
103
|
if (workItem === null)
|
|
103
104
|
throw usageError(`WorkItem not found: ${workItemId}.`);
|
|
104
|
-
const candidate = workItem
|
|
105
|
+
const candidate = governingWorkItemCandidate(workItem);
|
|
105
106
|
if (candidate?.gitSnapshot === undefined || candidate.workspace === undefined) {
|
|
106
107
|
throw usageError(`WorkItem has no committed result snapshot: ${workItem.id}.`);
|
|
107
108
|
}
|
|
@@ -3,7 +3,7 @@ import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
|
3
3
|
import { resolveProject } from "../repository/project.js";
|
|
4
4
|
import { NodeGitWorkspace } from "../repository/gitWorkspace.js";
|
|
5
5
|
import { enqueueIntegrationQueueEntry, processIntegrationQueue, reconcileIntegrationQueueEntry, requeueIntegrationQueueEntry, supersedeIntegrationQueueEntry } from "../integration/integrationQueueService.js";
|
|
6
|
-
import { taskLocalActor } from "./taskActor.js";
|
|
6
|
+
import { assertTaskDeliveryAuthority as taskLocalActor } from "./taskActor.js";
|
|
7
7
|
import { parseRepeatable } from "./taskIntegrationCommands.js";
|
|
8
8
|
import { resolveTaskRecordReference } from "../task/taskRecordReference.js";
|
|
9
9
|
/**
|
|
@@ -69,20 +69,20 @@ export function runTaskNextActionCommand(args, store, currentTaskReviewCandidate
|
|
|
69
69
|
const events = reader.listEvents(taskId);
|
|
70
70
|
const task = reader.getTask(taskId);
|
|
71
71
|
const remoteDelivery = projectTaskRemoteDeliveryFromStore(reader, task, currentTaskReviewCandidate);
|
|
72
|
-
const
|
|
72
|
+
const operationalRuns = operationalTaskRecords(reader.listRuns(taskId), events, "run");
|
|
73
73
|
const reviewRounds = reader.listReviewRounds(taskId);
|
|
74
74
|
const reviewDecision = projectReviewDecision({
|
|
75
75
|
store: reader,
|
|
76
76
|
task,
|
|
77
77
|
roles: reader.listRoles(taskId),
|
|
78
|
-
|
|
78
|
+
runs: operationalRuns,
|
|
79
79
|
rounds: reviewRounds,
|
|
80
80
|
reviewConfig: reader.getReviewConfig(),
|
|
81
81
|
currentCandidate: currentTaskReviewCandidate
|
|
82
82
|
});
|
|
83
83
|
const orchestration = projectTaskOrchestration({
|
|
84
84
|
task,
|
|
85
|
-
|
|
85
|
+
runs: operationalRuns,
|
|
86
86
|
roleSessionSets: reader.listRoleSessionSets(taskId),
|
|
87
87
|
workItems: reader.listWorkItems(taskId),
|
|
88
88
|
changeSets: reader.listChangeSets(taskId),
|
|
@@ -125,10 +125,10 @@ function renderNextAction(action, taskType, completionReadiness, knowledgePropos
|
|
|
125
125
|
`Next action: ${action.kind}`,
|
|
126
126
|
`Reason: ${action.reason}`,
|
|
127
127
|
`Execution view: ${execution.status}; owner/action=${execution.owner}/${execution.action}; reason=${execution.reason}; ${execution.summary}`,
|
|
128
|
-
`Active
|
|
129
|
-
...(execution.
|
|
128
|
+
`Active AgentRuns (${execution.activeRuns.length}):`,
|
|
129
|
+
...(execution.activeRuns.length === 0
|
|
130
130
|
? [" none"]
|
|
131
|
-
: execution.
|
|
131
|
+
: execution.activeRuns.map((run) => ` ${renderActiveRun(run)}`)),
|
|
132
132
|
...(action.refs.length === 0
|
|
133
133
|
? ["Refs: none"]
|
|
134
134
|
: ["Refs:", ...action.refs.map((ref) => ` ${ref.kind}: ${ref.id}`)]),
|
|
@@ -196,7 +196,7 @@ function renderNextAction(action, taskType, completionReadiness, knowledgePropos
|
|
|
196
196
|
}
|
|
197
197
|
return `${lines.join("\n")}\n`;
|
|
198
198
|
}
|
|
199
|
-
function
|
|
199
|
+
function renderActiveRun(run) {
|
|
200
200
|
const subject = run.reviewRoundId === undefined
|
|
201
201
|
? run.workItemId === undefined ? "task" : `work-item=${run.workItemId}`
|
|
202
202
|
: `review-round=${run.reviewRoundId}`;
|
|
@@ -212,6 +212,6 @@ function nextActionExecutionView(execution) {
|
|
|
212
212
|
action: execution.action,
|
|
213
213
|
reason: execution.reason,
|
|
214
214
|
summary: execution.summary,
|
|
215
|
-
|
|
215
|
+
activeRuns: execution.activeRuns
|
|
216
216
|
};
|
|
217
217
|
}
|