@zq-silk/yui 0.13.9 → 0.14.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 +69 -428
- package/README.md +108 -298
- package/dist/agent/managedRuntimeEnvironment.js +2 -2
- package/dist/cli/commandCatalog.js +39 -77
- package/dist/cli/interactionCandidates.js +4 -4
- package/dist/cli/interactionPolicy.js +7 -10
- package/dist/cli/invocationRouter.js +1 -1
- package/dist/cli/updateCommand.js +6 -27
- package/dist/cli/updateOrchestrator.js +63 -484
- package/dist/cli/updatePorts.js +15 -333
- package/dist/cli/upgradeCommand.js +8 -65
- package/dist/cli.js +57 -242
- package/dist/commands/configCommands.js +11 -62
- package/dist/commands/executionAuditCommands.js +23 -23
- package/dist/commands/globalRoleCommands.js +2 -7
- package/dist/commands/jobCommands.js +1 -4
- package/dist/commands/projectCommands.js +5 -5
- package/dist/commands/releaseCommands.js +3 -10
- package/dist/commands/resourcesCommands.js +2 -2
- package/dist/commands/sessionCommands.js +2 -2
- package/dist/commands/taskActor.js +31 -39
- package/dist/commands/taskChangeSetCommands.js +5 -12
- package/dist/commands/taskCommands.js +464 -1249
- package/dist/commands/taskContextCommand.js +35 -36
- package/dist/commands/taskExecutionCommands.js +33 -46
- package/dist/commands/taskInputCommands.js +20 -42
- package/dist/commands/taskNextActionCommand.js +9 -9
- package/dist/commands/taskOverviewCommand.js +56 -95
- package/dist/commands/taskRoleRuntimeStatus.js +77 -107
- package/dist/commands/taskUpstreamCommands.js +3 -3
- package/dist/commands/taskWorkspaceCommands.js +7 -79
- package/dist/commands/telemetryCommands.js +32 -124
- package/dist/commands/workflowCommands.js +3 -3
- package/dist/completion/fileCompletionManager.js +1 -1
- package/dist/config/configCatalog.js +4 -6
- package/dist/config/yuiConfig.js +6 -43
- package/dist/context/dispatchContext.js +14 -30
- package/dist/context/roleSessionContext.js +2 -2
- package/dist/context/sessionBootstrapManifest.js +2 -2
- package/dist/context/{runContextPack.js → turnContextPack.js} +58 -73
- package/dist/context/turnInputContract.js +204 -0
- package/dist/context/wakeNotification.js +2 -2
- package/dist/controller/agentRuntimeObserver.js +18 -18
- package/dist/controller/clientRuntime.js +13 -20
- package/dist/controller/controller.js +89 -116
- package/dist/controller/fileSchedulerStoreAdapter.js +511 -742
- package/dist/controller/jobControl.js +17 -17
- package/dist/controller/resourceInventory.js +6 -6
- package/dist/controller/resourceInventoryLinux.js +38 -59
- package/dist/controller/resourceInventoryRpc.js +3 -3
- package/dist/controller/resourceInventoryWorker.js +1 -1
- package/dist/controller/runtime.js +46 -53
- package/dist/controller/runtimeEventInbox.js +23 -31
- package/dist/controller/runtimeEventProcessor.js +15 -15
- package/dist/controller/{runtimeHookRunFence.js → runtimeHookTurnFence.js} +87 -81
- package/dist/controller/runtimeLaunchCoordinator.js +3 -3
- package/dist/controller/runtimeObservationHook.js +11 -8
- package/dist/controller/sessionNotify.js +11 -11
- package/dist/controller/structuredProviderObservation.js +89 -16
- package/dist/coordination/workMailbox.js +309 -579
- package/dist/coordination/workMailboxQueue.js +5 -6
- package/dist/core/controllerClient.js +1 -91
- package/dist/core/controllerServer.js +3 -6
- package/dist/doctor/doctor.js +51 -314
- package/dist/execution/candidateConvergence.js +3 -3
- package/dist/execution/executionGroup.js +32 -33
- package/dist/execution/executionHealth.js +36 -38
- package/dist/execution/resourceBroker.js +12 -12
- package/dist/executor/agentExecutor.js +30 -265
- package/dist/executor/effectiveLaunch.js +9 -19
- package/dist/executor/executorRegistry.js +43 -17
- package/dist/executor/fileRoleLaunchPlanner.js +56 -56
- package/dist/executor/launchPlan.js +3 -3
- package/dist/executor/workspacePreflightClassification.js +16 -16
- package/dist/grant/capabilityGrant.js +20 -25
- package/dist/input/inputRequest.js +12 -12
- package/dist/integration/changeSet.js +9 -13
- package/dist/integration/changeSetManifest.js +1 -1
- package/dist/integration/gitIntegrationService.js +2 -2
- package/dist/integration/integrationQueueService.js +5 -21
- package/dist/integration/overlapDiagnostics.js +2 -2
- package/dist/interaction/operatorPresentation.js +1 -1
- package/dist/job/jobRunner.js +1 -1
- package/dist/lifecycle/canonicalLifecycleEvent.js +25 -25
- package/dist/lifecycle/{exactRunTerminalization.js → exactTurnTerminalization.js} +116 -232
- package/dist/message/message.js +6 -6
- package/dist/observability/executionAudit.js +74 -86
- package/dist/observability/faultClassification.js +7 -24
- package/dist/observability/orchestrationMetrics.js +5 -5
- package/dist/observability/runtimeIdentity.js +34 -101
- package/dist/profile/agentProfile.js +1 -1
- package/dist/release/cliHomeReleaseFence.js +3 -3
- package/dist/release/releaseWorkflowEngine.js +6 -10
- package/dist/release/releaseWorkflowPorts.js +2 -2
- package/dist/release/workflowFileLock.js +1 -1
- package/dist/repository/checkoutSwap.js +1 -1
- package/dist/repository/gitWorkspace.js +0 -13
- package/dist/repository/project.js +1 -1
- package/dist/repository/projectMaintenanceLock.js +1 -2
- package/dist/repository/taskBaseFreshness.js +13 -13
- package/dist/repository/taskWorkspaceCoordinator.js +21 -25
- package/dist/repository/taskWorkspaceIdentity.js +8 -21
- package/dist/repository/taskWorkspacePreparer.js +63 -620
- package/dist/resources/autoResourceGc.js +3 -3
- package/dist/resources/liveReferences.js +1 -1
- package/dist/resources/resourceGc.js +1 -1
- package/dist/resources/sqliteResourceRegistry.js +1 -1
- package/dist/review/reviewDecision.js +7 -7
- package/dist/review/reviewFindingLedger.js +1 -1
- package/dist/review/reviewOutcomeClassifier.js +35 -50
- package/dist/review/reviewRound.js +14 -25
- package/dist/review/reviewerAvailability.js +4 -4
- package/dist/review/taskFinalReviewContractResolution.js +41 -0
- package/dist/role/role.js +6 -3
- package/dist/runtime/agentDriver.js +4 -0
- package/dist/runtime/agentHost.js +151 -36
- package/dist/runtime/builtinAgentDrivers.js +79 -2
- package/dist/runtime/codexAppServerRuntime.js +122 -0
- package/dist/runtime/continuationManager.js +3 -5
- package/dist/runtime/exactControlPlane.js +17 -42
- package/dist/runtime/firstProgressAdvisory.js +1 -1
- package/dist/runtime/index.js +2 -2
- package/dist/runtime/launchDiagnostics.js +2 -2
- package/dist/runtime/lifecycleReservation.js +4 -4
- package/dist/runtime/processExitObservation.js +1 -1
- package/dist/runtime/processExitOutbox.js +0 -32
- package/dist/runtime/promptEnvelope.js +9 -9
- package/dist/runtime/providerContinuation.js +2 -2
- package/dist/runtime/providerContinuationReconciliationService.js +2 -2
- package/dist/runtime/providerRuntimeIdentity.js +76 -24
- package/dist/runtime/recentTurnIds.js +38 -0
- package/dist/runtime/runtimeContinuationProjection.js +2 -2
- package/dist/runtime/runtimeHealthPolicy.js +1 -1
- package/dist/runtime/runtimeObservation.js +58 -21
- package/dist/runtime/runtimeProjection.js +19 -27
- package/dist/runtime/sessionLaunchRequest.js +2 -2
- package/dist/runtime/structuredProviderHost.js +177 -12
- package/dist/runtime/tmuxAdapters.js +46 -11
- package/dist/scheduler/activeRoleTurnDelivery.js +245 -0
- package/dist/scheduler/leaderWakeupProcessor.js +147 -445
- package/dist/scheduler/operatorEvent.js +4 -6
- package/dist/scheduler/resourceQueueProjection.js +71 -0
- package/dist/scheduler/{roleRunLiveness.js → roleTurnLiveness.js} +24 -28
- package/dist/scheduler/{roleRunStall.js → roleTurnStall.js} +162 -247
- package/dist/scheduler/taskExecutionProjection.js +99 -99
- package/dist/scheduler/taskObservabilityProjection.js +10 -10
- package/dist/scheduler/taskWake.js +4 -4
- package/dist/scheduler/wakeReason.js +6 -10
- package/dist/scheduler/wakeupQueue.js +0 -9
- package/dist/setup/setupCommand.js +2 -2
- package/dist/storage/currentTaskStore.js +46 -0
- package/dist/storage/persistenceWorker.js +1 -1
- package/dist/storage/sqliteSchema.js +81 -485
- package/dist/storage/sqliteStore.js +206 -365
- package/dist/storage/storageSchema.js +1 -15
- package/dist/storage/storageVersions.js +8 -9
- package/dist/storage/storeRpc.js +10 -34
- package/dist/storage/taskStore.js +63 -3415
- package/dist/storage/upgrade/recordVersions.js +55 -149
- package/dist/storage/upgrade/upgradeOrchestrator.js +89 -1752
- package/dist/task/completionReadiness.js +5 -5
- package/dist/task/deliveryGuard.js +10 -10
- package/dist/task/nextAction.js +74 -77
- package/dist/task/task.js +2 -4
- package/dist/task/taskRecordReference.js +3 -3
- package/dist/task/taskRecordRetirement.js +1 -1
- package/dist/telemetry/sqliteTelemetryStore.js +53 -53
- package/dist/telemetry/telemetryConfig.js +14 -14
- package/dist/telemetry/telemetryWiring.js +8 -14
- package/dist/turn/turn.js +356 -0
- package/dist/{run/runIdentity.js → turn/turnIdentity.js} +4 -4
- package/dist/verification/gateArtifactStore.js +2 -2
- package/dist/web/assets/client/app.js +1 -1
- package/dist/web/assets/client/components.js +29 -54
- package/dist/web/assets/client/i18n.js +17 -37
- package/dist/web/assets/client/view.js +37 -37
- package/dist/web/assets/shell.js +1 -1
- package/dist/web/assets/styles/cards.js +5 -5
- package/dist/web/assets/styles/widgets.js +1 -2
- package/dist/web/webSnapshot.js +65 -60
- package/dist/workItem/workItem.js +11 -11
- package/dist/workspace/workItemChangeSetManager.js +1 -1
- package/docs/task-local-identity.md +5 -5
- package/i18n/README.zh-CN.md +41 -54
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +85 -83
- package/skills/yui-operator/SKILL.md +16 -16
- package/skills/yui-reviewer/SKILL.md +10 -10
- package/skills/yui-runtime/SKILL.md +17 -18
- package/skills/yui-worker/SKILL.md +16 -18
- package/dist/context/runContextContract.js +0 -162
- package/dist/executor/turnCompletion.js +0 -126
- package/dist/review/taskFinalReviewContractEvent.js +0 -1
- package/dist/review/taskFinalReviewContractRebind.js +0 -367
- package/dist/run/agentRun.js +0 -356
- package/dist/run/rejectedYieldAttempt.js +0 -221
- package/dist/run/runControlRequest.js +0 -50
- package/dist/run/yieldReceipt.js +0 -65
- package/dist/runtime/turnCompletion.js +0 -3
- package/dist/scheduler/actionability.js +0 -323
- package/dist/scheduler/activeRoleRunDelivery.js +0 -868
- package/dist/scheduler/activeTaskProgress.js +0 -126
- package/dist/storage/compatibleTaskStore.js +0 -248
- package/dist/storage/migration/baseline.js +0 -78
- package/dist/storage/migration/classifier.js +0 -51
- package/dist/storage/migration/compatibleCodec.js +0 -53
- package/dist/storage/migration/engine.js +0 -147
- package/dist/storage/migration/index.js +0 -33
- package/dist/storage/migration/planner.js +0 -154
- package/dist/storage/migration/productionRegistry.js +0 -3931
- package/dist/storage/migration/registry.js +0 -169
- package/dist/storage/migration/report.js +0 -54
- package/dist/storage/migration/types.js +0 -31
- package/dist/storage/upgrade/homeClassification.js +0 -353
- package/dist/storage/upgrade/homeMigrationTarget.js +0 -595
- package/dist/storage/upgrade/migrationReceipt.js +0 -67
- package/dist/storage/upgrade/offlineUpgradeInventory.js +0 -453
- package/dist/storage/upgrade/productionMigrationRegistry.js +0 -6
- package/dist/storage/upgrade/pseudoLayoutRepair.js +0 -241
- package/dist/storage/upgrade/recordVersionScan.js +0 -176
- package/dist/storage/upgrade/sqliteFileSet.js +0 -50
- package/dist/storage/upgrade/sqliteMigrationTarget.js +0 -375
- package/dist/storage/upgrade/sqliteRecordMigrationTarget.js +0 -305
- package/dist/storage/upgrade/sqliteStateMigration.js +0 -918
- package/dist/storage/upgrade/switchProgress.js +0 -80
- package/dist/storage/upgrade/upgradeReceipt.js +0 -161
- package/dist/storage/upgradeCoordination.js +0 -187
- package/dist/storage/upgradeFence.js +0 -366
- package/dist/telemetry/telemetryCompaction.js +0 -252
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { taskNotFound, usageError } from "../errors/cliError.js";
|
|
2
2
|
import { taskMessageAuthorLabel } from "../message/message.js";
|
|
3
3
|
import { formatTimestamp } from "../output/timePresentation.js";
|
|
4
|
-
import {
|
|
4
|
+
import { isRoleTurnStalled, latestStallProgressAt } from "../scheduler/roleTurnStall.js";
|
|
5
5
|
import { buildTaskExecutionProjection } from "../scheduler/taskExecutionProjection.js";
|
|
6
6
|
import { projectNextAction } from "../task/nextAction.js";
|
|
7
7
|
import { summarizeExecutionGroup } from "../execution/executionGroup.js";
|
|
@@ -43,7 +43,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
43
43
|
}))
|
|
44
44
|
].filter((mailbox) => mailbox !== null);
|
|
45
45
|
const events = reader.listEvents(task.id);
|
|
46
|
-
const
|
|
46
|
+
const turns = chronological(operationalTaskRecords(reader.listTurns(task.id), events, "turn"));
|
|
47
47
|
const reviewRounds = chronological(reader.listReviewRounds(task.id));
|
|
48
48
|
const reviewConfig = reader.getReviewConfig();
|
|
49
49
|
const changeSets = chronological(reader.listChangeSets(task.id));
|
|
@@ -61,7 +61,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
61
61
|
store: reader,
|
|
62
62
|
task,
|
|
63
63
|
roles,
|
|
64
|
-
|
|
64
|
+
turns,
|
|
65
65
|
rounds: reviewRounds,
|
|
66
66
|
reviewConfig,
|
|
67
67
|
currentCandidate: currentTaskReviewCandidate
|
|
@@ -75,7 +75,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
75
75
|
roleSessionSets,
|
|
76
76
|
coordinationMailboxes,
|
|
77
77
|
workItems,
|
|
78
|
-
|
|
78
|
+
turns,
|
|
79
79
|
reviewRounds,
|
|
80
80
|
changeSets,
|
|
81
81
|
integrations,
|
|
@@ -91,13 +91,13 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
91
91
|
})
|
|
92
92
|
};
|
|
93
93
|
});
|
|
94
|
-
const { task, execution, reviewConfig, reviewDecision, brief, activeDecisions, milestones, roles, managedWorkspaces, roleSessionSets, coordinationMailboxes, workItems,
|
|
94
|
+
const { task, execution, reviewConfig, reviewDecision, brief, activeDecisions, milestones, roles, managedWorkspaces, roleSessionSets, coordinationMailboxes, workItems, turns, reviewRounds, changeSets, integrations, publications, messages, openInputRequests, resolvedInputRequests, events, nextAction } = data;
|
|
95
95
|
const timeZone = store.getConfig().timeZone;
|
|
96
96
|
const displayedActiveDecisions = activeDecisions.slice(-RECENT_RECORD_LIMIT);
|
|
97
97
|
const displayedWorkItems = currentAndRecentWorkItems(workItems);
|
|
98
98
|
const displayedOpenInputRequests = openInputRequests.slice(-RECENT_RECORD_LIMIT);
|
|
99
99
|
const displayedResolvedInputRequests = resolvedInputRequests.slice(-RECENT_RECORD_LIMIT);
|
|
100
|
-
const
|
|
100
|
+
const displayedActiveTurns = execution.activeTurns;
|
|
101
101
|
const executionGroupsById = new Map(execution.executionGroups.map((group) => [
|
|
102
102
|
group.groupId,
|
|
103
103
|
group
|
|
@@ -141,10 +141,10 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
141
141
|
` Attention: ${execution.attention.length === 0
|
|
142
142
|
? "none"
|
|
143
143
|
: execution.attention.map(({ kind, owner }) => `${kind}/${owner}`).join(", ")}`,
|
|
144
|
-
` Active
|
|
145
|
-
...(
|
|
144
|
+
` Active Turns (${displayedActiveTurns.length}):`,
|
|
145
|
+
...(displayedActiveTurns.length === 0
|
|
146
146
|
? [" None."]
|
|
147
|
-
:
|
|
147
|
+
: displayedActiveTurns.map((run) => (` ${run.roleName}: ${run.id} [${run.status}/${run.purpose}; ${`provider-${run.providerSession}`}${run.workItemId === undefined ? "" : `; work-item=${run.workItemId}`}${run.reviewRoundId === undefined ? "" : `; review-round=${run.reviewRoundId}`}${run.executionGroupId === undefined ? "" : `; group=${run.executionGroupId}`}${run.executionLaneId === undefined ? "" : `; lane=${run.executionLaneId}`}]`))),
|
|
148
148
|
"Observability:",
|
|
149
149
|
` DAG: ${observability.dag.nodes.length} node(s), ${observability.dag.edges.length} edge(s); ready=${observability.dag.readyIds.join(", ") || "none"}; blocked=${observability.dag.blockedIds.join(", ") || "none"}`,
|
|
150
150
|
` Cost: tokens=${resourceUsageLabel(observability.cost.tokens, undefined, observability.cost.tokensObservable)}; tools=${resourceUsageLabel(observability.cost.toolCalls, undefined, observability.cost.toolCallsObservable)}; wall=${observability.cost.wallClockSeconds}s; lanes=${observability.cost.laneCount}; groups=${observability.cost.groupCount}; retries=${observability.cost.retryCount}; marginal-value=unavailable`,
|
|
@@ -200,7 +200,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
200
200
|
` Reviewer slots: ${reviewDecision.reviewers.length === 0
|
|
201
201
|
? "none configured"
|
|
202
202
|
: reviewDecision.reviewers.map((reviewer) => (`${reviewer.reviewerRoleName}=${reviewer.status}`
|
|
203
|
-
+ `${reviewer.
|
|
203
|
+
+ `${reviewer.activeTurnId === undefined ? "" : `(${reviewer.activeTurnId})`}`)).join(", ")}`,
|
|
204
204
|
` Accepted baseline: ${reviewDecision.latestAcceptedBaseline === null
|
|
205
205
|
? "none"
|
|
206
206
|
: `${reviewDecision.latestAcceptedBaseline.reviewRoundId}`
|
|
@@ -242,14 +242,14 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
242
242
|
? [" None."]
|
|
243
243
|
: roles.flatMap((role) => {
|
|
244
244
|
const binding = role.agentBindings[role.activeAgentId];
|
|
245
|
-
const
|
|
245
|
+
const activeTurn = turns.find((run) => (run.roleName === role.name && run.status === "active"));
|
|
246
246
|
const sessions = roleSessionSets.find((set) => set.owner.roleName === role.name);
|
|
247
247
|
const activeSession = sessions?.sessions[sessions.activeAgentId];
|
|
248
|
-
const effective =
|
|
249
|
-
const effectiveSource =
|
|
248
|
+
const effective = activeTurn?.effective ?? activeSession?.effective;
|
|
249
|
+
const effectiveSource = activeTurn === undefined ? "Session" : "Turn";
|
|
250
250
|
const creation = [...events].reverse().find((event) => (event.type === "role.added" && event.payload.role === role.name));
|
|
251
251
|
return [
|
|
252
|
-
` ${role.name} [${
|
|
252
|
+
` ${role.name} [${activeTurn === undefined ? "idle" : "running"}]: ${role.activeAgentId}/${binding.adapterId}`,
|
|
253
253
|
` Desired: r${role.launchRevision}; Profile intent: ${role.defaultAccess}; Model: ${binding.config.model ?? "default"}; effort: ${binding.config.effort ?? "default"}; permission: ${binding.config.permission.strategy}`,
|
|
254
254
|
` Effective: ${effective === undefined
|
|
255
255
|
? "not started"
|
|
@@ -274,8 +274,8 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
274
274
|
...(displayedWorkItems.length === 0
|
|
275
275
|
? [" None."]
|
|
276
276
|
: displayedWorkItems.flatMap((item) => {
|
|
277
|
-
const itemRuns =
|
|
278
|
-
const
|
|
277
|
+
const itemRuns = turns.filter((run) => run.workItemId === item.id);
|
|
278
|
+
const latestTurn = itemRuns.at(-1);
|
|
279
279
|
return [
|
|
280
280
|
` ${item.id} [${item.status}]: ${compactText(item.title)}`,
|
|
281
281
|
` Objective: ${compactText(item.objective)}`,
|
|
@@ -294,7 +294,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
294
294
|
...(item.candidates.length === 0
|
|
295
295
|
? []
|
|
296
296
|
: item.candidates.flatMap((candidate) => [
|
|
297
|
-
` Candidate ${candidate.sequence}: ${candidate.id}${item.status === "awaiting_acceptance" && candidate === item.candidates.at(-1) ? " [current]" : ""} (${candidate.source.type === "
|
|
297
|
+
` Candidate ${candidate.sequence}: ${candidate.id}${item.status === "awaiting_acceptance" && candidate === item.candidates.at(-1) ? " [current]" : ""} (${candidate.source.type === "turn" ? candidate.source.turnId : "direct"})`,
|
|
298
298
|
` Review policy: ${candidate.reviewPolicy === undefined ? "none" : `${candidate.reviewPolicy.roleName} (${candidate.reviewPolicy.trigger})`}`,
|
|
299
299
|
` Task-final contract: ${candidate.taskFinalReviewContract === undefined
|
|
300
300
|
? "none"
|
|
@@ -304,14 +304,14 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
304
304
|
: `${candidate.gitSnapshot.reviewBaseCommit} (${candidate.gitSnapshot.projects.length} Projects)`}`,
|
|
305
305
|
` Summary: ${compactText(candidate.summary)}`
|
|
306
306
|
])),
|
|
307
|
-
...(
|
|
308
|
-
? ["
|
|
307
|
+
...(latestTurn === undefined
|
|
308
|
+
? [" Turns: none."]
|
|
309
309
|
: [
|
|
310
|
-
`
|
|
311
|
-
` Assignment: ${
|
|
312
|
-
...(
|
|
310
|
+
` Turns: ${itemRuns.length}; latest ${latestTurn.id} [${latestTurn.status}] ${latestTurn.effective.agentId}/${latestTurn.effective.adapterId} · effective r${latestTurn.effective.sourceDesiredRevision}/${latestTurn.effective.profileAccess}/${latestTurn.effective.permission.strategy}`,
|
|
311
|
+
` Assignment: ${latestTurn.inputs[0].input.source.channel}${latestTurn.inputs[0].input.directive === undefined ? "" : ` · ${compactText(latestTurn.inputs[0].input.directive)}`}`,
|
|
312
|
+
...(latestTurn.result === undefined
|
|
313
313
|
? []
|
|
314
|
-
: [` Summary: ${compactText(
|
|
314
|
+
: [` Summary: ${compactText(latestTurn.result.output)}`])
|
|
315
315
|
]),
|
|
316
316
|
...renderReviewRounds(reviewRounds.filter((round) => round.workItemId === item.id), executionGroupsById)
|
|
317
317
|
];
|
|
@@ -320,21 +320,21 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
|
|
|
320
320
|
"Task-final reviews:",
|
|
321
321
|
...renderReviewRounds(reviewRounds.filter((round) => (round.scope ?? "work-item") === "task"), executionGroupsById),
|
|
322
322
|
"",
|
|
323
|
-
...recentSection("
|
|
323
|
+
...recentSection("Turns", turns, (run) => [
|
|
324
324
|
` ${run.id} [${run.status}/${run.purpose}] ${run.roleName} via ${run.effective.agentId}/${run.effective.adapterId}`,
|
|
325
325
|
` Effective: r${run.effective.sourceDesiredRevision}; Profile intent: ${run.effective.profileAccess}; permission: ${run.effective.permission.strategy}; model: ${run.effective.model ?? "default"}; effort: ${run.effective.effort ?? "default"}`,
|
|
326
|
-
...(run.
|
|
326
|
+
...(run.result === undefined ? [] : [` Result: ${compactText(run.result.output)}`])
|
|
327
327
|
]),
|
|
328
328
|
"",
|
|
329
329
|
"Runtime health:",
|
|
330
330
|
...(() => {
|
|
331
|
-
const stalled =
|
|
331
|
+
const stalled = turns.filter((run) => (run.status === "active" && isRoleTurnStalled(events, run.id)));
|
|
332
332
|
return stalled.length === 0
|
|
333
|
-
? [" No needs-attention
|
|
333
|
+
? [" No needs-attention Turns."]
|
|
334
334
|
: stalled.flatMap((run) => [
|
|
335
335
|
` ${run.id} [needs-attention] ${run.roleName}`,
|
|
336
336
|
` Durable progress: ${formatTimestamp(latestStallProgressAt(events, run.id) ?? run.updatedAt, timeZone)}`,
|
|
337
|
-
` Cause: ${latestStallKind(events, run.id)} with no new semantic
|
|
337
|
+
` Cause: ${latestStallKind(events, run.id)} with no new semantic Turn evidence in the stall window`,
|
|
338
338
|
" Next: inspect Task context/Role status; no automatic retry or Session replacement was performed."
|
|
339
339
|
]);
|
|
340
340
|
})(),
|
|
@@ -401,18 +401,17 @@ function renderCoordinationMailbox(mailbox) {
|
|
|
401
401
|
const target = mailbox.target.kind === "role"
|
|
402
402
|
? `role/${mailbox.target.roleName}`
|
|
403
403
|
: mailbox.target.kind;
|
|
404
|
-
const pending =
|
|
405
|
-
.filter((batch) => batch !== null);
|
|
404
|
+
const pending = mailbox.pending === null ? [] : [mailbox.pending];
|
|
406
405
|
return [
|
|
407
|
-
` ${target}:
|
|
408
|
-
`
|
|
406
|
+
` ${target}: next=${mailbox.nextSequence}`,
|
|
407
|
+
` Processing: ${mailbox.processing?.batchId ?? "none"}; pending batches: ${pending.length}`,
|
|
409
408
|
...pending.map((batch) => (` Pending ${batch.fromSequence}-${batch.toSequence}: ${batch.reasons.join(", ")} · refs ${batch.refs.map((ref) => `${ref.type}:${ref.id}`).join(", ") || "none"}`))
|
|
410
409
|
];
|
|
411
410
|
}
|
|
412
|
-
function latestStallKind(events,
|
|
411
|
+
function latestStallKind(events, turnId) {
|
|
413
412
|
const event = [...events]
|
|
414
|
-
.filter((candidate) => candidate.type === "
|
|
415
|
-
&& candidate.payload.
|
|
413
|
+
.filter((candidate) => candidate.type === "turn.stalled"
|
|
414
|
+
&& candidate.payload.turnId === turnId
|
|
416
415
|
&& candidate.payload.status !== "diagnostic-only")
|
|
417
416
|
.sort((left, right) => Date.parse(right.createdAt) - Date.parse(left.createdAt))[0];
|
|
418
417
|
return event?.payload.kind ?? "workflow-not-progressing";
|
|
@@ -576,7 +575,7 @@ function renderExecutionGroup(group, projected) {
|
|
|
576
575
|
...summary.laneSummaries.flatMap((lane) => {
|
|
577
576
|
const laneHealth = projected?.laneSummaries.find(({ laneId }) => laneId === lane.laneId);
|
|
578
577
|
return [
|
|
579
|
-
` Lane ${lane.laneId} (#${lane.ordinal}, ${lane.roleName}${lane.
|
|
578
|
+
` Lane ${lane.laneId} (#${lane.ordinal}, ${lane.roleName}${lane.turnId === undefined ? "" : `, run ${lane.turnId}`}) [${lane.status}${laneHealth?.runtimeHealth === undefined ? "" : `/${laneHealth.runtimeHealth}`}]${lane.summary === undefined ? "" : `: ${compactText(lane.summary)}`}`,
|
|
580
579
|
...(lane.effective === undefined
|
|
581
580
|
? []
|
|
582
581
|
: [` Config: ${lane.effective.adapterId}/${lane.effective.model ?? "default"}/${lane.effective.effort ?? "default"}; profile=${lane.effective.profileAccess}`]),
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { createTaskEvent } from "../event/taskEvent.js";
|
|
2
|
-
import { terminalizeTaskRoleRunSession } from "../executor/agentExecutor.js";
|
|
3
2
|
import { recordExecutionLaneResult } from "../execution/executionGroup.js";
|
|
4
3
|
import { usageError } from "../errors/cliError.js";
|
|
5
4
|
import { requestDurableJobCancel } from "../job/durableJob.js";
|
|
6
5
|
import { finishReviewRound, updateReviewExecutionGroup } from "../review/reviewRound.js";
|
|
7
|
-
import {
|
|
6
|
+
import { failTurn } from "../turn/turn.js";
|
|
8
7
|
import { queueLeaderWakeup } from "../scheduler/wakeupQueue.js";
|
|
9
8
|
import { startTaskExecution, stopTaskExecution } from "../task/task.js";
|
|
10
9
|
import { updateWorkItemExecutionGroup, workItemExecutionGroupById } from "../workItem/workItem.js";
|
|
@@ -61,33 +60,29 @@ export function stopTaskExecutionCommand(request, store, options = {}) {
|
|
|
61
60
|
}
|
|
62
61
|
const changed = task.executionGate.state !== "stopped";
|
|
63
62
|
tx.saveTask(stopTaskExecution(task, now));
|
|
64
|
-
const
|
|
63
|
+
const activeTurns = tx.listTurns(task.id).filter((run) => run.status === "active");
|
|
65
64
|
const activeJobs = tx.listDurableJobs(task.id)
|
|
66
65
|
.filter((job) => job.status === "queued" || job.status === "running");
|
|
67
66
|
for (const job of activeJobs) {
|
|
68
67
|
tx.saveDurableJob(task.id, requestDurableJobCancel(job, now));
|
|
69
68
|
}
|
|
70
|
-
failExecutionAttempts(tx, task.id,
|
|
71
|
-
for (const run of
|
|
72
|
-
tx.
|
|
69
|
+
failExecutionAttempts(tx, task.id, activeTurns, request.reason, now);
|
|
70
|
+
for (const run of activeTurns) {
|
|
71
|
+
tx.saveTurn(failTurn(run, "cancelled", `Task execution stopped: ${request.reason}`, now));
|
|
73
72
|
if (run.executionGroupId !== undefined && run.executionLaneId !== undefined) {
|
|
74
|
-
tx.
|
|
73
|
+
tx.clearActiveExecutionLaneTurn(task.id, run.executionGroupId, run.executionLaneId);
|
|
75
74
|
}
|
|
76
|
-
tx.
|
|
75
|
+
tx.clearActiveTurn(task.id, run.roleName);
|
|
77
76
|
}
|
|
78
|
-
const roleNames = taskRuntimeRoleNames(tx, task.id,
|
|
77
|
+
const roleNames = taskRuntimeRoleNames(tx, task.id, activeTurns);
|
|
79
78
|
for (const roleName of roleNames) {
|
|
80
|
-
tx.
|
|
81
|
-
const sessions = tx.getTaskRoleSessionSet(task.id, roleName);
|
|
82
|
-
if (sessions !== null && sessions.inFlight !== null) {
|
|
83
|
-
tx.saveTaskRoleSessionSet(terminalizeCurrentRun(sessions, now));
|
|
84
|
-
}
|
|
79
|
+
tx.clearActiveTurn(task.id, roleName);
|
|
85
80
|
}
|
|
86
81
|
// A stop is allowed to discard stale pointer projections even when their
|
|
87
|
-
// historical
|
|
88
|
-
for (const run of tx.
|
|
82
|
+
// historical Turns are already terminal.
|
|
83
|
+
for (const run of tx.listTurns(task.id)) {
|
|
89
84
|
if (run.executionGroupId !== undefined && run.executionLaneId !== undefined) {
|
|
90
|
-
tx.
|
|
85
|
+
tx.clearActiveExecutionLaneTurn(task.id, run.executionGroupId, run.executionLaneId);
|
|
91
86
|
}
|
|
92
87
|
}
|
|
93
88
|
for (const mailbox of tx.listWorkMailboxes()) {
|
|
@@ -99,17 +94,17 @@ export function stopTaskExecutionCommand(request, store, options = {}) {
|
|
|
99
94
|
tx.saveEvent(task.id, createTaskEvent(tx.nextEventId(task.id), task.id, "task.execution-stopped", {
|
|
100
95
|
by: actor,
|
|
101
96
|
reason: request.reason,
|
|
102
|
-
terminatedRuns: String(
|
|
97
|
+
terminatedRuns: String(activeTurns.length)
|
|
103
98
|
}, now));
|
|
104
99
|
return {
|
|
105
100
|
taskId: task.id,
|
|
106
101
|
changed,
|
|
107
102
|
roleNames,
|
|
108
|
-
|
|
103
|
+
terminatedTurnIds: activeTurns.map(({ id }) => id),
|
|
109
104
|
cancelledJobIds: activeJobs.map(({ id }) => id),
|
|
110
105
|
output: changed
|
|
111
106
|
? `Stopped Task execution: ${task.id}. Progress was preserved; `
|
|
112
|
-
+ `${
|
|
107
|
+
+ `${activeTurns.length} active attempt(s) were terminated and `
|
|
113
108
|
+ `${activeJobs.length} DurableJob(s) were cancelled.`
|
|
114
109
|
: `Task execution is already stopped: ${task.id}. Runtime cleanup will be verified.`
|
|
115
110
|
};
|
|
@@ -129,7 +124,7 @@ export function startTaskExecutionCommand(taskId, store, options = {}) {
|
|
|
129
124
|
if (task.executionGate.state === "enabled") {
|
|
130
125
|
return { taskId: task.id, changed: false, output: `Task execution is already enabled: ${task.id}.` };
|
|
131
126
|
}
|
|
132
|
-
if (tx.
|
|
127
|
+
if (tx.listTurns(task.id).some((run) => run.status === "active")
|
|
133
128
|
|| tx.listDurableJobs(task.id).some((job) => job.status === "queued" || job.status === "running")) {
|
|
134
129
|
throw usageError(`Task still has an active execution attempt: ${task.id}.`);
|
|
135
130
|
}
|
|
@@ -173,20 +168,12 @@ function requireOperatorOrUser(environment, taskId) {
|
|
|
173
168
|
}
|
|
174
169
|
return actor;
|
|
175
170
|
}
|
|
176
|
-
function
|
|
177
|
-
const inFlight = sessions.inFlight;
|
|
178
|
-
return terminalizeTaskRoleRunSession(sessions, {
|
|
179
|
-
agentId: inFlight.agentId,
|
|
180
|
-
runId: inFlight.runId,
|
|
181
|
-
receiptId: inFlight.receiptId
|
|
182
|
-
}, now);
|
|
183
|
-
}
|
|
184
|
-
function taskRuntimeRoleNames(store, taskId, runs) {
|
|
171
|
+
function taskRuntimeRoleNames(store, taskId, turns) {
|
|
185
172
|
const names = new Set(store.listRoles(taskId).map(({ name }) => name));
|
|
186
173
|
for (const sessions of store.listRoleSessionSets(taskId))
|
|
187
174
|
names.add(sessions.owner.roleName);
|
|
188
|
-
for (const
|
|
189
|
-
names.add(
|
|
175
|
+
for (const turn of turns)
|
|
176
|
+
names.add(turn.roleName);
|
|
190
177
|
for (const owner of store.listSessionOwners()) {
|
|
191
178
|
if (owner.owner.scope === "task" && owner.owner.taskId === taskId) {
|
|
192
179
|
names.add(owner.owner.roleName);
|
|
@@ -194,36 +181,36 @@ function taskRuntimeRoleNames(store, taskId, runs) {
|
|
|
194
181
|
}
|
|
195
182
|
return [...names].sort();
|
|
196
183
|
}
|
|
197
|
-
function failExecutionAttempts(store, taskId,
|
|
184
|
+
function failExecutionAttempts(store, taskId, turns, reason, now) {
|
|
198
185
|
const summary = `Task execution stopped: ${reason}`;
|
|
199
186
|
const workItems = new Map(store.listWorkItems(taskId).map((item) => [item.id, item]));
|
|
200
187
|
const reviewRounds = new Map(store.listReviewRounds(taskId).map((round) => [round.id, round]));
|
|
201
188
|
const affectedReviewRoundIds = new Set();
|
|
202
|
-
for (const
|
|
203
|
-
if (
|
|
189
|
+
for (const turn of turns) {
|
|
190
|
+
if (turn.executionGroupId === undefined || turn.executionLaneId === undefined)
|
|
204
191
|
continue;
|
|
205
|
-
if (
|
|
206
|
-
const item = workItems.get(
|
|
192
|
+
if (turn.workItemId !== undefined) {
|
|
193
|
+
const item = workItems.get(turn.workItemId);
|
|
207
194
|
const group = item === undefined
|
|
208
195
|
? undefined
|
|
209
|
-
: workItemExecutionGroupById(item,
|
|
210
|
-
const lane = group?.lanes.find(({ id }) => id ===
|
|
196
|
+
: workItemExecutionGroupById(item, turn.executionGroupId);
|
|
197
|
+
const lane = group?.lanes.find(({ id }) => id === turn.executionLaneId);
|
|
211
198
|
if (item !== undefined && group !== undefined && lane !== undefined
|
|
212
199
|
&& item.currentExecutionGroupId === group.id
|
|
213
|
-
&& !["
|
|
200
|
+
&& !["completed", "failed", "skipped"].includes(lane.status)) {
|
|
214
201
|
const updated = updateWorkItemExecutionGroup(item, recordExecutionLaneResult(group, lane.id, { summary }, "failed", now), now);
|
|
215
202
|
workItems.set(item.id, updated);
|
|
216
203
|
}
|
|
217
204
|
}
|
|
218
|
-
if (
|
|
219
|
-
affectedReviewRoundIds.add(
|
|
220
|
-
const round = reviewRounds.get(
|
|
221
|
-
const group = round?.executionGroup?.id ===
|
|
205
|
+
if (turn.reviewRoundId !== undefined) {
|
|
206
|
+
affectedReviewRoundIds.add(turn.reviewRoundId);
|
|
207
|
+
const round = reviewRounds.get(turn.reviewRoundId);
|
|
208
|
+
const group = round?.executionGroup?.id === turn.executionGroupId
|
|
222
209
|
? round.executionGroup
|
|
223
210
|
: undefined;
|
|
224
|
-
const lane = group?.lanes.find(({ id }) => id ===
|
|
211
|
+
const lane = group?.lanes.find(({ id }) => id === turn.executionLaneId);
|
|
225
212
|
if (round !== undefined && group !== undefined && lane !== undefined
|
|
226
|
-
&& !["
|
|
213
|
+
&& !["completed", "failed", "skipped"].includes(lane.status)) {
|
|
227
214
|
reviewRounds.set(round.id, updateReviewExecutionGroup(round, recordExecutionLaneResult(group, lane.id, { summary }, "failed", now)));
|
|
228
215
|
}
|
|
229
216
|
}
|
|
@@ -4,10 +4,8 @@ import { activeLiveRoleAgentSession } from "../executor/agentExecutor.js";
|
|
|
4
4
|
import { answerInputRequest, cancelInputRequest, createInputRequest } from "../input/inputRequest.js";
|
|
5
5
|
import { defaultTableWidth, renderTable } from "../output/table.js";
|
|
6
6
|
import { formatTimestamp } from "../output/timePresentation.js";
|
|
7
|
-
import { agentRunDeliveryReceiptId } from "../run/agentRun.js";
|
|
8
7
|
import { enqueueWork } from "../coordination/workMailboxQueue.js";
|
|
9
|
-
import {
|
|
10
|
-
import { terminalizeExactTaskRun } from "../lifecycle/exactRunTerminalization.js";
|
|
8
|
+
import { isRoleTurnStalled, TURN_RECOVERED_EVENT } from "../scheduler/roleTurnStall.js";
|
|
11
9
|
import { hasRuntimeCleanupObligation, isRuntimeLaunchReservation, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
12
10
|
import { isLinuxProcessLive, listOwnedProcessTree } from "../runtime/sessionOwnerIdentity.js";
|
|
13
11
|
import { resolveTaskRecordReference } from "../task/taskRecordReference.js";
|
|
@@ -63,36 +61,17 @@ function createRequest(args, store, options) {
|
|
|
63
61
|
validateBlockedInputOwnership(tx, task.id, blockedRefs);
|
|
64
62
|
const origin = requireLeaderInputOrigin(tx, task.id, options.environment);
|
|
65
63
|
const created = createInputRequest(tx.nextInputRequestId(task.id), task.id, origin.requester, { question, choices, blockedRefs, policy }, now);
|
|
66
|
-
const wasStalled =
|
|
64
|
+
const wasStalled = isRoleTurnStalled(tx.listEvents(task.id), origin.turn.id);
|
|
67
65
|
tx.saveInputRequest(task.id, created);
|
|
68
66
|
enqueueWork(tx, { kind: "operator" }, "input-requested", now, [
|
|
69
67
|
{ type: "input", taskId: task.id, id: created.id }
|
|
70
68
|
], {
|
|
71
69
|
source: "input-request",
|
|
72
|
-
dedupeKey: `operator-input:${task.id}:${created.id}
|
|
73
|
-
deliveryMode: "followup",
|
|
74
|
-
lane: "normal"
|
|
70
|
+
dedupeKey: `operator-input:${task.id}:${created.id}`
|
|
75
71
|
});
|
|
76
|
-
const terminal = terminalizeExactTaskRun(tx, {
|
|
77
|
-
taskId: task.id,
|
|
78
|
-
roleName: LEADER_ROLE,
|
|
79
|
-
agentId: origin.run.effective.agentId,
|
|
80
|
-
runId: origin.run.id,
|
|
81
|
-
receiptId: agentRunDeliveryReceiptId(origin.run),
|
|
82
|
-
...(origin.requester.nativeSessionId === undefined
|
|
83
|
-
? {}
|
|
84
|
-
: { nativeSessionId: origin.requester.nativeSessionId }),
|
|
85
|
-
outcome: {
|
|
86
|
-
status: "yielded",
|
|
87
|
-
summary: `Waiting for input ${created.id}: ${created.question}`
|
|
88
|
-
}
|
|
89
|
-
}, now);
|
|
90
|
-
if (terminal.disposition !== "applied") {
|
|
91
|
-
throw usageError(`Task Leader Run changed while requesting input: ${origin.run.id}/${terminal.reason}.`);
|
|
92
|
-
}
|
|
93
72
|
if (wasStalled) {
|
|
94
|
-
recordTaskEvent(tx, task.id,
|
|
95
|
-
|
|
73
|
+
recordTaskEvent(tx, task.id, TURN_RECOVERED_EVENT, {
|
|
74
|
+
turnId: origin.turn.id,
|
|
96
75
|
roleName: LEADER_ROLE,
|
|
97
76
|
progressAt: now.toISOString(),
|
|
98
77
|
kind: "input-request"
|
|
@@ -100,7 +79,7 @@ function createRequest(args, store, options) {
|
|
|
100
79
|
}
|
|
101
80
|
recordTaskEvent(tx, task.id, "input.requested", {
|
|
102
81
|
requestId: created.id,
|
|
103
|
-
|
|
82
|
+
requesterTurnId: created.requester.turnId,
|
|
104
83
|
policy: created.policy.kind
|
|
105
84
|
}, now);
|
|
106
85
|
return created;
|
|
@@ -222,33 +201,32 @@ function cancelRequest(args, store, options) {
|
|
|
222
201
|
function requireLeaderInputOrigin(store, taskId, environment) {
|
|
223
202
|
const env = environment ?? {};
|
|
224
203
|
const role = requireRole(store, taskId, LEADER_ROLE);
|
|
225
|
-
const
|
|
204
|
+
const turn = store.getActiveTurn(taskId, LEADER_ROLE);
|
|
226
205
|
if (env.YUI_SESSION_SCOPE !== "task"
|
|
227
206
|
|| env.YUI_TASK_ID !== taskId
|
|
228
207
|
|| env.YUI_ROLE !== LEADER_ROLE
|
|
229
|
-
||
|
|
230
|
-
|| env.YUI_AGENT_ID !==
|
|
231
|
-
||
|
|
232
|
-
||
|
|
233
|
-
|
|
234
|
-
throw usageError("Task input request requires the active Leader Run environment.");
|
|
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.");
|
|
235
213
|
}
|
|
236
214
|
const sessions = store.getTaskRoleSessionSet(taskId, LEADER_ROLE);
|
|
237
215
|
const nativeSessionId = trimmed(env.YUI_NATIVE_SESSION_ID);
|
|
238
216
|
if (nativeSessionId !== undefined
|
|
239
|
-
&& sessions?.sessions[
|
|
217
|
+
&& sessions?.sessions[turn.effective.agentId]?.nativeSessionId !== nativeSessionId) {
|
|
240
218
|
throw usageError("Task input request native session does not match the active Leader session.");
|
|
241
219
|
}
|
|
242
220
|
return {
|
|
243
221
|
requester: {
|
|
244
222
|
taskId,
|
|
245
223
|
roleName: "leader",
|
|
246
|
-
agentId:
|
|
247
|
-
|
|
224
|
+
agentId: turn.effective.agentId,
|
|
225
|
+
turnId: turn.id,
|
|
248
226
|
...(nativeSessionId === undefined ? {} : { nativeSessionId })
|
|
249
227
|
},
|
|
250
228
|
role,
|
|
251
|
-
|
|
229
|
+
turn,
|
|
252
230
|
sessions
|
|
253
231
|
};
|
|
254
232
|
}
|
|
@@ -364,8 +342,8 @@ function parseInputBlockedRef(value, taskId) {
|
|
|
364
342
|
const separator = value.indexOf(":");
|
|
365
343
|
const type = value.slice(0, separator);
|
|
366
344
|
const id = value.slice(separator + 1).trim();
|
|
367
|
-
if ((type !== "work-item" && type !== "
|
|
368
|
-
throw usageError("--blocks must use work-item:<id> or
|
|
345
|
+
if ((type !== "work-item" && type !== "turn") || separator <= 0 || id.length === 0) {
|
|
346
|
+
throw usageError("--blocks must use work-item:<id> or turn:<id>.");
|
|
369
347
|
}
|
|
370
348
|
return { type, taskId, id };
|
|
371
349
|
}
|
|
@@ -373,7 +351,7 @@ function validateBlockedInputOwnership(store, taskId, references) {
|
|
|
373
351
|
for (const reference of references) {
|
|
374
352
|
const record = reference.type === "work-item"
|
|
375
353
|
? store.getWorkItem(taskId, reference.id)
|
|
376
|
-
: store.
|
|
354
|
+
: store.getTurn(taskId, reference.id);
|
|
377
355
|
if (record === null)
|
|
378
356
|
throw dataError(`Blocked ${reference.type} not found: ${reference.id}.`);
|
|
379
357
|
}
|
|
@@ -408,7 +386,7 @@ function renderInputRequest(request, timeZone) {
|
|
|
408
386
|
`Task: ${request.taskId}`,
|
|
409
387
|
`Status: ${request.status}`,
|
|
410
388
|
`Question: ${request.question}`,
|
|
411
|
-
`Requested by: ${request.requester.agentId}/${request.requester.
|
|
389
|
+
`Requested by: ${request.requester.agentId}/${request.requester.turnId}`,
|
|
412
390
|
...(request.choices.length === 0
|
|
413
391
|
? ["Answer type: text"]
|
|
414
392
|
: ["Choices:", ...request.choices.map((choice) => ` ${choice.key}: ${choice.label}`)]),
|
|
@@ -70,20 +70,20 @@ export function runTaskNextActionCommand(args, store, currentTaskReviewCandidate
|
|
|
70
70
|
}
|
|
71
71
|
const events = reader.listEvents(taskId);
|
|
72
72
|
const task = reader.getTask(taskId);
|
|
73
|
-
const
|
|
73
|
+
const operationalTurns = operationalTaskRecords(reader.listTurns(taskId), events, "turn");
|
|
74
74
|
const reviewRounds = reader.listReviewRounds(taskId);
|
|
75
75
|
const reviewDecision = projectReviewDecision({
|
|
76
76
|
store: reader,
|
|
77
77
|
task,
|
|
78
78
|
roles: reader.listRoles(taskId),
|
|
79
|
-
|
|
79
|
+
turns: operationalTurns,
|
|
80
80
|
rounds: reviewRounds,
|
|
81
81
|
reviewConfig: reader.getReviewConfig(),
|
|
82
82
|
currentCandidate: currentTaskReviewCandidate
|
|
83
83
|
});
|
|
84
84
|
const orchestration = projectTaskOrchestration({
|
|
85
85
|
task,
|
|
86
|
-
|
|
86
|
+
turns: operationalTurns,
|
|
87
87
|
roleSessionSets: reader.listRoleSessionSets(taskId),
|
|
88
88
|
workItems: reader.listWorkItems(taskId),
|
|
89
89
|
changeSets: reader.listChangeSets(taskId),
|
|
@@ -141,10 +141,10 @@ function renderNextAction(action, taskType, repairWave, completionReadiness, kno
|
|
|
141
141
|
`Next action: ${action.kind}`,
|
|
142
142
|
`Reason: ${action.reason}`,
|
|
143
143
|
`Execution view: ${execution.status}; owner/action=${execution.owner}/${execution.action}; reason=${execution.reason}; ${execution.summary}`,
|
|
144
|
-
`Active
|
|
145
|
-
...(execution.
|
|
144
|
+
`Active Turns (${execution.activeTurns.length}):`,
|
|
145
|
+
...(execution.activeTurns.length === 0
|
|
146
146
|
? [" none"]
|
|
147
|
-
: execution.
|
|
147
|
+
: execution.activeTurns.map((run) => ` ${renderActiveTurn(run)}`)),
|
|
148
148
|
...(action.refs.length === 0
|
|
149
149
|
? ["Refs: none"]
|
|
150
150
|
: ["Refs:", ...action.refs.map((ref) => ` ${ref.kind}: ${ref.id}`)]),
|
|
@@ -217,14 +217,14 @@ function renderNextAction(action, taskType, repairWave, completionReadiness, kno
|
|
|
217
217
|
}
|
|
218
218
|
return `${lines.join("\n")}\n`;
|
|
219
219
|
}
|
|
220
|
-
function
|
|
220
|
+
function renderActiveTurn(run) {
|
|
221
221
|
const subject = run.reviewRoundId === undefined
|
|
222
222
|
? run.workItemId === undefined ? "task" : `work-item=${run.workItemId}`
|
|
223
223
|
: `review-round=${run.reviewRoundId}`;
|
|
224
224
|
const lane = run.executionGroupId === undefined
|
|
225
225
|
? ""
|
|
226
226
|
: `; group=${run.executionGroupId}${run.executionLaneId === undefined ? "" : `; lane=${run.executionLaneId}`}`;
|
|
227
|
-
return `${run.id} [${run.purpose}/${run.status}; role=${run.roleName}; ${run.
|
|
227
|
+
return `${run.id} [${run.purpose}/${run.status}; role=${run.roleName}; ${`provider-${run.providerSession}`}; ${subject}${lane}]`;
|
|
228
228
|
}
|
|
229
229
|
function nextActionExecutionView(execution) {
|
|
230
230
|
return {
|
|
@@ -233,6 +233,6 @@ function nextActionExecutionView(execution) {
|
|
|
233
233
|
action: execution.action,
|
|
234
234
|
reason: execution.reason,
|
|
235
235
|
summary: execution.summary,
|
|
236
|
-
|
|
236
|
+
activeTurns: execution.activeTurns
|
|
237
237
|
};
|
|
238
238
|
}
|