@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,16 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createRunAssignment, serializeRunBootstrapEnvelope } from "../context/runContextContract.js";
|
|
3
|
-
import { formatAgentRunReceiptId } from "../task/taskRecordReference.js";
|
|
1
|
+
import { createTurnInput } from "../context/turnInputContract.js";
|
|
4
2
|
import { effectiveLaunchSnapshotsCompatible, effectiveLaunchSnapshotsCompatibleForTaskSession } from "../executor/effectiveLaunch.js";
|
|
5
3
|
import { roleAgentSessionResumeMode } from "../executor/agentExecutor.js";
|
|
6
|
-
import {
|
|
4
|
+
import { createTurn } from "../turn/turn.js";
|
|
7
5
|
import { isSchedulerTaskWorkspaceReady } from "./ports.js";
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export const LEADER_WAKE_AGGREGATION_MS = 60_000;
|
|
7
|
+
export const LEADER_WAKE_FORCE_MS = 10 * 60_000;
|
|
8
|
+
/**
|
|
9
|
+
* Materializes durable Leader intent as a Turn. Provider lifecycle and
|
|
10
|
+
* Turn submission are handled by processActiveRoleTurnDeliveries, so every
|
|
11
|
+
* Role follows one launch, serialization, and failure path.
|
|
12
|
+
*/
|
|
10
13
|
export async function processLeaderWakeups(store, delivery, now, selection) {
|
|
11
14
|
const results = [];
|
|
12
15
|
const wakeups = selection === undefined || selection.full
|
|
13
|
-
? store.listPendingWakeups().filter((wakeup) =>
|
|
16
|
+
? store.listPendingWakeups().filter((wakeup) => !selection?.blockedTaskIds?.has(wakeup.taskId))
|
|
14
17
|
: [...selection.taskIds].flatMap((taskId) => {
|
|
15
18
|
if (selection.blockedTaskIds?.has(taskId))
|
|
16
19
|
return [];
|
|
@@ -27,8 +30,7 @@ export async function processLeaderWakeups(store, delivery, now, selection) {
|
|
|
27
30
|
results.push({ taskId: wakeup.taskId, status: "skipped", reason: "unavailable" });
|
|
28
31
|
continue;
|
|
29
32
|
}
|
|
30
|
-
|
|
31
|
-
if (!isSchedulerTaskWorkspaceReady(task, taskWorkspace)) {
|
|
33
|
+
if (!isSchedulerTaskWorkspaceReady(task, store.getTaskWorkspace(task.id))) {
|
|
32
34
|
results.push({ taskId: task.id, status: "skipped", reason: "workspace-not-ready" });
|
|
33
35
|
continue;
|
|
34
36
|
}
|
|
@@ -36,485 +38,185 @@ export async function processLeaderWakeups(store, delivery, now, selection) {
|
|
|
36
38
|
results.push({ taskId: task.id, status: "skipped", reason: "waiting-input" });
|
|
37
39
|
continue;
|
|
38
40
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
results.push({ taskId: task.id, status: "skipped", reason: "busy" });
|
|
41
|
+
const waitedMs = Math.max(0, now.getTime() - Date.parse(wakeup.firstRequestedAt));
|
|
42
|
+
if (waitedMs < LEADER_WAKE_AGGREGATION_MS) {
|
|
43
|
+
results.push({ taskId: task.id, status: "skipped", reason: "aggregating" });
|
|
43
44
|
continue;
|
|
44
45
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (
|
|
46
|
+
const active = store.getActiveTurn(task.id, role.name);
|
|
47
|
+
const leaderTarget = { kind: "role", taskId: task.id, roleName: role.name };
|
|
48
|
+
const claimedSteer = store.getWorkMailbox(leaderTarget)?.processing;
|
|
49
|
+
if (claimedSteer?.owner.startsWith("leader-steer:") === true
|
|
50
|
+
&& (active === null || claimedSteer.owner !== `leader-steer:${active.id}`)) {
|
|
51
|
+
store.releaseWorkMailbox(leaderTarget, claimedSteer.batchId);
|
|
52
|
+
results.push({ taskId: task.id, status: "skipped", reason: "state-changed" });
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (active !== null) {
|
|
56
|
+
if (waitedMs >= LEADER_WAKE_FORCE_MS && active !== null) {
|
|
57
|
+
results.push(await forceLeaderSteer(store, delivery, task.id, role.name, active, now));
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
49
60
|
results.push({ taskId: task.id, status: "skipped", reason: "busy" });
|
|
50
61
|
continue;
|
|
51
62
|
}
|
|
52
|
-
const reopening = wakeup.reasons.includes("task-reopened");
|
|
53
|
-
let existingSession = store.getRoleSession(task.id, role.name, reopening ? undefined : role.effective.agentId);
|
|
54
|
-
let effectiveSession = existingSession;
|
|
55
|
-
let claimed = false;
|
|
56
|
-
let deliveryAttempted = false;
|
|
57
|
-
let run = null;
|
|
58
|
-
let prepared;
|
|
59
|
-
let preStartFencePersisted = false;
|
|
60
|
-
let mode = "new";
|
|
61
63
|
try {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
&&
|
|
69
|
-
|
|
70
|
-
&& !
|
|
71
|
-
&& existingSession.status === "active") {
|
|
64
|
+
const reopening = wakeup.reasons.includes("task-reopened");
|
|
65
|
+
const existingSession = store.getRoleSession(task.id, role.name, reopening ? undefined : role.effective.agentId);
|
|
66
|
+
const compatible = existingSession !== null && (reopening
|
|
67
|
+
? effectiveLaunchSnapshotsCompatible(existingSession.effective, role.effective)
|
|
68
|
+
: effectiveLaunchSnapshotsCompatibleForTaskSession(existingSession.effective, role.effective));
|
|
69
|
+
if (hasNativeSession(existingSession)
|
|
70
|
+
&& existingSession.status === "active"
|
|
71
|
+
&& !compatible
|
|
72
|
+
&& !reopening) {
|
|
72
73
|
throw new Error(`Leader Session is incompatible with desired effective launch: ${task.id}/${role.name}.`);
|
|
73
74
|
}
|
|
74
|
-
const resumableSession = hasNativeSession(existingSession)
|
|
75
|
-
&& existingSession.status === "active";
|
|
76
|
-
// Reuse a healthy Session. A terminal Session is disposable and the next
|
|
77
|
-
// Run starts fresh without consulting historical recovery records.
|
|
78
75
|
const sessionSet = store.getTaskRoleSessionSet?.(task.id, role.name) ?? null;
|
|
79
|
-
mode =
|
|
76
|
+
const mode = reopening && !compatible
|
|
80
77
|
? "new"
|
|
81
78
|
: sessionSet === null
|
|
82
|
-
?
|
|
79
|
+
? hasNativeSession(existingSession) && existingSession.status === "active" && compatible
|
|
80
|
+
? "resume"
|
|
81
|
+
: "new"
|
|
83
82
|
: roleAgentSessionResumeMode(sessionSet, role.effective.agentId, role.effective);
|
|
84
|
-
const
|
|
85
|
-
const wakeEnvelope = resolveLeaderWakeEnvelope(store, task.id);
|
|
83
|
+
const turnId = store.peekNextTurnId(task.id);
|
|
86
84
|
const contextSnapshot = store.freezeLeaderContextSnapshot?.(task.id, role.name, now);
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
const input = createTurnInput({
|
|
86
|
+
source: leaderWakeInputSource(wakeup.reasons),
|
|
87
|
+
directive: [
|
|
88
|
+
`Wake reasons: ${wakeup.reasons.join(", ")}.`,
|
|
89
|
+
`Load exact context for ${task.id}/${turnId}.`,
|
|
90
|
+
"Before ending this Turn, judge the affected WorkItems and Task; persist any lifecycle or result changes you establish.",
|
|
91
|
+
"The final Turn response is evidence only and never updates WorkItem or Task state by itself."
|
|
92
|
+
].join(" "),
|
|
94
93
|
...(contextSnapshot === undefined ? {} : { contextSnapshotRef: contextSnapshot.ref }),
|
|
95
94
|
deltaRefIds: contextSnapshot?.deltaRefIds ?? []
|
|
96
95
|
});
|
|
97
|
-
|
|
98
|
-
...(role.managedWorkspace === undefined
|
|
99
|
-
? {}
|
|
100
|
-
: { workspace: role.managedWorkspace }),
|
|
96
|
+
const turn = createTurn(turnId, task.id, role.name, mode, input, now, {
|
|
97
|
+
...(role.managedWorkspace === undefined ? {} : { workspace: role.managedWorkspace }),
|
|
101
98
|
effective: role.effective
|
|
102
99
|
});
|
|
100
|
+
const envelope = store.getTaskWakeEnvelope?.(task.id) ?? null;
|
|
103
101
|
const claim = store.saveLeaderDispatch({
|
|
104
102
|
task,
|
|
105
103
|
role,
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// a new native host. Keep the old fixed Session as evidence while
|
|
109
|
-
// claiming a short-lived Run so the existing failure path can record a
|
|
110
|
-
// durable, retryable recovery obligation before any provider call.
|
|
111
|
-
session: reopenIdentityDrift ? null : existingSession,
|
|
104
|
+
turn,
|
|
105
|
+
session: reopening && !compatible ? null : existingSession,
|
|
112
106
|
wakeup,
|
|
113
|
-
...(
|
|
114
|
-
wakeId:
|
|
115
|
-
wakeFromCursor:
|
|
107
|
+
...(envelope === null ? {} : {
|
|
108
|
+
wakeId: envelope.wakeId,
|
|
109
|
+
wakeFromCursor: envelope.fromCursor
|
|
116
110
|
}),
|
|
117
111
|
now
|
|
118
112
|
});
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
claimed = true;
|
|
124
|
-
if (reopenIdentityDrift) {
|
|
125
|
-
throw new Error(`Leader reopen refused after effective launch identity drift: ${task.id}/${role.name}.`);
|
|
126
|
-
}
|
|
127
|
-
prepared = await delivery.prepareRoleSession({
|
|
128
|
-
taskId: task.id,
|
|
129
|
-
roleName: role.name,
|
|
130
|
-
agentId: role.effective.agentId,
|
|
131
|
-
adapterId: role.effective.adapterId,
|
|
132
|
-
effective: role.effective,
|
|
133
|
-
workspace: role.effective.workspace.root,
|
|
134
|
-
...(run.workspace === undefined
|
|
135
|
-
? {}
|
|
136
|
-
: { managedWorkspace: run.workspace }),
|
|
137
|
-
mode,
|
|
138
|
-
runId: run.id,
|
|
139
|
-
...(mode === "resume" ? { nativeSessionId: existingSession.nativeSessionId } : {}),
|
|
140
|
-
...(mode !== "resume" || existingSession?.launchId === undefined
|
|
141
|
-
? {}
|
|
142
|
-
: { hostActivationId: existingSession.launchId }),
|
|
143
|
-
beforeHostStart: (preflight) => {
|
|
144
|
-
persistPreStartFence(store, task, role, run, existingSession, mode, preflight, now);
|
|
145
|
-
effectiveSession = preflightSession(role, run.effective, existingSession, mode, preflight);
|
|
146
|
-
preStartFencePersisted = true;
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
// Persist the Session identity before submitting the Leader Turn.
|
|
150
|
-
// Starting/restoring a Session is independent from sending Run input.
|
|
151
|
-
if (!preStartFencePersisted) {
|
|
152
|
-
const preparedFenceSession = prepared.session === undefined
|
|
153
|
-
? existingSession
|
|
154
|
-
: validateReadySession(role, run.effective, existingSession, mode, prepared.session);
|
|
155
|
-
effectiveSession = preparedFenceSession;
|
|
156
|
-
store.saveRoleRunPrepared({
|
|
157
|
-
task,
|
|
158
|
-
role,
|
|
159
|
-
run,
|
|
160
|
-
session: preparedFenceSession,
|
|
161
|
-
...(prepared.launchId === undefined ? {} : { launchId: prepared.launchId }),
|
|
162
|
-
now
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
const ready = await delivery.waitUntilReady(prepared);
|
|
166
|
-
const latestTask = store.getTask(task.id);
|
|
167
|
-
if (latestTask === null
|
|
168
|
-
|| latestTask.status !== "active"
|
|
169
|
-
|| latestTask.executionGate.state !== "enabled") {
|
|
170
|
-
delivery.forgetPrepared?.({
|
|
171
|
-
taskId: task.id,
|
|
172
|
-
roleName: role.name,
|
|
173
|
-
runId: run.id,
|
|
174
|
-
...(prepared.launchId === undefined
|
|
175
|
-
? {}
|
|
176
|
-
: { launchId: prepared.launchId })
|
|
177
|
-
});
|
|
178
|
-
results.push({ taskId: task.id, status: "skipped", reason: "unavailable" });
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
effectiveSession = validateReadySession(role, run.effective, existingSession, mode, ready.session);
|
|
182
|
-
store.saveRoleRunPrepared({
|
|
183
|
-
task,
|
|
184
|
-
role,
|
|
185
|
-
run,
|
|
186
|
-
session: effectiveSession,
|
|
187
|
-
...(ready.prepared.launchId === undefined
|
|
188
|
-
? {}
|
|
189
|
-
: { launchId: ready.prepared.launchId }),
|
|
190
|
-
now
|
|
191
|
-
});
|
|
192
|
-
deliveryAttempted = true;
|
|
193
|
-
const outcome = await delivery.sendOnce({
|
|
194
|
-
delivery: ready,
|
|
195
|
-
receiptId: formatAgentRunReceiptId(task.id, run.id),
|
|
196
|
-
text: serializeRunBootstrapEnvelope(run.bootstrapEnvelope)
|
|
197
|
-
});
|
|
198
|
-
if (outcome === "busy" || outcome === "unavailable") {
|
|
199
|
-
delivery.forgetPrepared?.({
|
|
200
|
-
taskId: task.id,
|
|
201
|
-
roleName: role.name,
|
|
202
|
-
runId: run.id,
|
|
203
|
-
...(ready.prepared.launchId === undefined
|
|
204
|
-
? {}
|
|
205
|
-
: { launchId: ready.prepared.launchId })
|
|
206
|
-
});
|
|
207
|
-
results.push({
|
|
208
|
-
taskId: task.id,
|
|
209
|
-
runId: run.id,
|
|
210
|
-
status: "skipped",
|
|
211
|
-
reason: outcome === "busy" ? "busy" : "not-ready"
|
|
212
|
-
});
|
|
213
|
-
continue;
|
|
214
|
-
}
|
|
215
|
-
if (outcome === "rejected") {
|
|
216
|
-
const terminal = store.saveRoleRunDeliveryFailure({
|
|
217
|
-
taskId: task.id,
|
|
218
|
-
roleName: role.name,
|
|
219
|
-
agentId: run.effective.agentId,
|
|
220
|
-
adapterId: run.effective.adapterId,
|
|
221
|
-
runId: run.id,
|
|
222
|
-
mailboxBatchId: formatAgentRunReceiptId(task.id, run.id),
|
|
223
|
-
...(effectiveSession?.nativeSessionId === undefined
|
|
224
|
-
? {}
|
|
225
|
-
: { nativeSessionId: effectiveSession.nativeSessionId }),
|
|
226
|
-
...(ready.prepared.launchId === undefined
|
|
227
|
-
? {}
|
|
228
|
-
: { launchId: ready.prepared.launchId }),
|
|
229
|
-
summary: "Provider rejected the Leader Turn before acceptance; Operator recovery is required.",
|
|
230
|
-
cleanupRequired: false,
|
|
231
|
-
now
|
|
232
|
-
});
|
|
233
|
-
delivery.forgetPrepared?.({
|
|
234
|
-
taskId: task.id,
|
|
235
|
-
roleName: role.name,
|
|
236
|
-
runId: run.id,
|
|
237
|
-
...(ready.prepared.launchId === undefined
|
|
238
|
-
? {}
|
|
239
|
-
: { launchId: ready.prepared.launchId })
|
|
240
|
-
});
|
|
241
|
-
results.push({
|
|
242
|
-
taskId: task.id,
|
|
243
|
-
runId: run.id,
|
|
244
|
-
status: terminal === "failed" ? "failed" : "skipped",
|
|
245
|
-
reason: "provider-rejected",
|
|
246
|
-
...(terminal === "failed" ? { terminalized: true } : {})
|
|
247
|
-
});
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
if (outcome === "delivery-unknown") {
|
|
251
|
-
store.saveRoleRunDelivery({
|
|
252
|
-
task,
|
|
253
|
-
role,
|
|
254
|
-
run,
|
|
255
|
-
session: effectiveSession,
|
|
256
|
-
...(ready.prepared.launchId === undefined
|
|
257
|
-
? {}
|
|
258
|
-
: { launchId: ready.prepared.launchId }),
|
|
259
|
-
now
|
|
260
|
-
});
|
|
261
|
-
delivery.forgetPrepared?.({
|
|
262
|
-
taskId: task.id,
|
|
263
|
-
roleName: role.name,
|
|
264
|
-
runId: run.id,
|
|
265
|
-
...(ready.prepared.launchId === undefined
|
|
266
|
-
? {}
|
|
267
|
-
: { launchId: ready.prepared.launchId })
|
|
268
|
-
});
|
|
269
|
-
results.push({
|
|
270
|
-
taskId: task.id,
|
|
271
|
-
runId: run.id,
|
|
272
|
-
status: "skipped",
|
|
273
|
-
reason: "delivery-uncertain"
|
|
274
|
-
});
|
|
275
|
-
continue;
|
|
276
|
-
}
|
|
277
|
-
store.saveRoleRunDelivery({
|
|
278
|
-
task,
|
|
279
|
-
role,
|
|
280
|
-
run,
|
|
281
|
-
session: effectiveSession,
|
|
282
|
-
...(ready.prepared.launchId === undefined
|
|
283
|
-
? {}
|
|
284
|
-
: { launchId: ready.prepared.launchId }),
|
|
285
|
-
now
|
|
286
|
-
});
|
|
287
|
-
delivery.forgetPrepared?.({
|
|
288
|
-
taskId: task.id,
|
|
289
|
-
roleName: role.name,
|
|
290
|
-
runId: run.id,
|
|
291
|
-
...(ready.prepared.launchId === undefined
|
|
292
|
-
? {}
|
|
293
|
-
: { launchId: ready.prepared.launchId })
|
|
294
|
-
});
|
|
295
|
-
results.push({ taskId: task.id, runId: run.id, status: "dispatched" });
|
|
296
|
-
continue;
|
|
113
|
+
results.push(claim === "claimed"
|
|
114
|
+
? { taskId: task.id, turnId: turn.id, status: "dispatched" }
|
|
115
|
+
: { taskId: task.id, status: "skipped", reason: claim });
|
|
297
116
|
}
|
|
298
117
|
catch (error) {
|
|
299
|
-
const detail = error instanceof Error ? error.message : String(error);
|
|
300
|
-
const message = `Leader dispatch failed: ${detail}`;
|
|
301
|
-
if (claimed && run !== null) {
|
|
302
|
-
// Scheduler single-flight backpressure: the Role runtime lifecycle
|
|
303
|
-
// lane was busy when the launch was reserved. The claimed Run stays
|
|
304
|
-
// active-unpushed; the active-Run delivery path retries it after the
|
|
305
|
-
// lane settles. This is contention before any semantic launch, not a
|
|
306
|
-
// Run failure and not grounds for a Leader failure record.
|
|
307
|
-
if (error instanceof RuntimeLifecycleBusyError) {
|
|
308
|
-
delivery.forgetPrepared?.({
|
|
309
|
-
taskId: task.id,
|
|
310
|
-
roleName: role.name,
|
|
311
|
-
runId: run.id
|
|
312
|
-
});
|
|
313
|
-
results.push({
|
|
314
|
-
taskId: task.id,
|
|
315
|
-
runId: run.id,
|
|
316
|
-
status: "skipped",
|
|
317
|
-
reason: "not-ready",
|
|
318
|
-
error: message
|
|
319
|
-
});
|
|
320
|
-
continue;
|
|
321
|
-
}
|
|
322
|
-
store.recordAgentError?.({
|
|
323
|
-
taskId: task.id,
|
|
324
|
-
roleName: role.name,
|
|
325
|
-
runId: run.id,
|
|
326
|
-
source: error instanceof RuntimeLaunchError ? "host" : "yui",
|
|
327
|
-
phase: deliveryAttempted
|
|
328
|
-
? "turn-submit"
|
|
329
|
-
: mode === "new" ? "session-start" : "session-restore",
|
|
330
|
-
message: detail,
|
|
331
|
-
raw: serializeAgentErrorRaw(error),
|
|
332
|
-
inputDisposition: deliveryAttempted ? "unknown" : "not-accepted"
|
|
333
|
-
}, now);
|
|
334
|
-
if (!deliveryAttempted) {
|
|
335
|
-
const failedSession = store.getRoleSession(task.id, role.name, run.effective.agentId);
|
|
336
|
-
const terminal = store.saveRoleRunDeliveryFailure({
|
|
337
|
-
taskId: task.id,
|
|
338
|
-
roleName: role.name,
|
|
339
|
-
agentId: run.effective.agentId,
|
|
340
|
-
adapterId: run.effective.adapterId,
|
|
341
|
-
runId: run.id,
|
|
342
|
-
mailboxBatchId: formatAgentRunReceiptId(task.id, run.id),
|
|
343
|
-
...(failedSession?.nativeSessionId === undefined
|
|
344
|
-
? {}
|
|
345
|
-
: { nativeSessionId: failedSession.nativeSessionId }),
|
|
346
|
-
...(prepared?.launchId === undefined && failedSession?.launchId === undefined
|
|
347
|
-
? {}
|
|
348
|
-
: { launchId: prepared?.launchId ?? failedSession.launchId }),
|
|
349
|
-
summary: `Leader Session preparation failed before Turn acceptance: ${message}`,
|
|
350
|
-
cleanupRequired: false,
|
|
351
|
-
now
|
|
352
|
-
});
|
|
353
|
-
if (terminal === "failed") {
|
|
354
|
-
delivery.forgetPrepared?.({
|
|
355
|
-
taskId: task.id,
|
|
356
|
-
roleName: role.name,
|
|
357
|
-
runId: run.id,
|
|
358
|
-
...(prepared?.launchId === undefined
|
|
359
|
-
? {}
|
|
360
|
-
: { launchId: prepared.launchId })
|
|
361
|
-
});
|
|
362
|
-
results.push({
|
|
363
|
-
taskId: task.id,
|
|
364
|
-
runId: run.id,
|
|
365
|
-
status: "failed",
|
|
366
|
-
reason: "unavailable",
|
|
367
|
-
error: message,
|
|
368
|
-
terminalized: true
|
|
369
|
-
});
|
|
370
|
-
continue;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
// A managed Provider lifecycle operation may still be settling. Keep
|
|
374
|
-
// this newly-claimed Run as the sole mailbox owner; active-Run delivery
|
|
375
|
-
// retries after the lifecycle lane clears.
|
|
376
|
-
if (error instanceof RuntimeLaunchError && error.retryable) {
|
|
377
|
-
results.push({
|
|
378
|
-
taskId: task.id,
|
|
379
|
-
runId: run.id,
|
|
380
|
-
status: "skipped",
|
|
381
|
-
reason: error.reason === "writable-client"
|
|
382
|
-
? "writer-attached"
|
|
383
|
-
: "not-ready",
|
|
384
|
-
error: message
|
|
385
|
-
});
|
|
386
|
-
continue;
|
|
387
|
-
}
|
|
388
|
-
// Once delivery begins, a send may have succeeded even when receipt
|
|
389
|
-
// observation or the aggregate write failed. Preserve the exact
|
|
390
|
-
// durable Run and let receipt-backed active delivery recover it.
|
|
391
|
-
if (deliveryAttempted) {
|
|
392
|
-
results.push({
|
|
393
|
-
taskId: task.id,
|
|
394
|
-
runId: run.id,
|
|
395
|
-
status: "failed",
|
|
396
|
-
reason: "delivery-uncertain",
|
|
397
|
-
error: message
|
|
398
|
-
});
|
|
399
|
-
continue;
|
|
400
|
-
}
|
|
401
|
-
delivery.forgetPrepared?.({
|
|
402
|
-
taskId: task.id,
|
|
403
|
-
roleName: role.name,
|
|
404
|
-
runId: run.id,
|
|
405
|
-
...(prepared?.launchId === undefined
|
|
406
|
-
? {}
|
|
407
|
-
: { launchId: prepared.launchId })
|
|
408
|
-
});
|
|
409
|
-
results.push({
|
|
410
|
-
taskId: task.id,
|
|
411
|
-
runId: run.id,
|
|
412
|
-
status: "skipped",
|
|
413
|
-
reason: "not-ready",
|
|
414
|
-
error: message
|
|
415
|
-
});
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
118
|
results.push({
|
|
419
119
|
taskId: task.id,
|
|
420
|
-
runId: run?.id,
|
|
421
120
|
status: "failed",
|
|
422
121
|
reason: "not-ready",
|
|
423
|
-
error: message
|
|
122
|
+
error: error instanceof Error ? error.message : String(error)
|
|
424
123
|
});
|
|
425
124
|
}
|
|
426
125
|
}
|
|
427
126
|
return results;
|
|
428
127
|
}
|
|
429
|
-
function
|
|
430
|
-
if (
|
|
431
|
-
return
|
|
432
|
-
const status = store.getTaskRoleSessionSet?.(taskId, roleName)
|
|
433
|
-
?.providerBinding?.turn?.status;
|
|
434
|
-
return status !== undefined
|
|
435
|
-
&& ["submitting", "accepted", "running", "delivery-unknown"].includes(status);
|
|
436
|
-
}
|
|
437
|
-
function validateReadySession(role, effective, existing, mode, session) {
|
|
438
|
-
if (mode === "new" && session === null)
|
|
439
|
-
return null;
|
|
440
|
-
if (session === null)
|
|
441
|
-
throw new Error("Leader resume returned no fixed native session.");
|
|
442
|
-
if (session.agentId !== effective.agentId || session.adapterId !== effective.adapterId) {
|
|
443
|
-
throw new Error(`Ready session belongs to another Agent: ${session.agentId}.`);
|
|
128
|
+
function leaderWakeInputSource(reasons) {
|
|
129
|
+
if (reasons.length > 0 && reasons.every((reason) => reason === "user-message")) {
|
|
130
|
+
return { type: "yui", channel: "user-message" };
|
|
444
131
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
: effectiveLaunchSnapshotsCompatible(session.effective, effective);
|
|
448
|
-
if (!compatible) {
|
|
449
|
-
throw new Error("Ready Leader session effective snapshot changed.");
|
|
132
|
+
if (reasons.length > 0 && reasons.every((reason) => reason.startsWith("input-answered:"))) {
|
|
133
|
+
return { type: "yui", channel: "input-response" };
|
|
450
134
|
}
|
|
451
|
-
|
|
452
|
-
|
|
135
|
+
return { type: "yui", channel: "leader-wakeup" };
|
|
136
|
+
}
|
|
137
|
+
async function forceLeaderSteer(store, delivery, taskId, roleName, active, now) {
|
|
138
|
+
const target = { kind: "role", taskId, roleName };
|
|
139
|
+
const mailbox = store.getWorkMailbox(target);
|
|
140
|
+
const pending = mailbox?.pending;
|
|
141
|
+
const existing = mailbox?.processing;
|
|
142
|
+
if (existing === null || existing === undefined) {
|
|
143
|
+
if (pending === null || pending === undefined) {
|
|
144
|
+
return { taskId, turnId: active.id, status: "skipped", reason: "state-changed" };
|
|
145
|
+
}
|
|
453
146
|
}
|
|
454
|
-
|
|
455
|
-
|
|
147
|
+
const owner = `leader-steer:${active.id}`;
|
|
148
|
+
const batchId = existing?.batchId
|
|
149
|
+
?? `leader-steer:${encodeURIComponent(taskId)}:${encodeURIComponent(active.id)}:${pending.fromSequence}-${pending.toSequence}`;
|
|
150
|
+
const claim = store.claimWorkMailbox({ target, batchId, owner, now });
|
|
151
|
+
if (claim.status === "empty") {
|
|
152
|
+
return { taskId, turnId: active.id, status: "skipped", reason: "state-changed" };
|
|
456
153
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
status: "
|
|
460
|
-
...(mode === "resume" && existing !== null
|
|
461
|
-
? { effective: existing.effective }
|
|
462
|
-
: {})
|
|
463
|
-
};
|
|
464
|
-
}
|
|
465
|
-
function persistPreStartFence(store, task, role, run, existingSession, mode, preflight, now) {
|
|
466
|
-
if (preflight.owner.scope !== "task"
|
|
467
|
-
|| preflight.owner.taskId !== task.id
|
|
468
|
-
|| preflight.owner.roleName !== role.name
|
|
469
|
-
|| preflight.runId !== run.id
|
|
470
|
-
|| preflight.launchId.trim().length === 0) {
|
|
471
|
-
throw new Error(`Pre-start launch fence changed the Leader Run: ${task.id}/${role.name}.`);
|
|
154
|
+
const processing = claim.processing;
|
|
155
|
+
if (processing.batchId !== batchId || processing.owner !== owner) {
|
|
156
|
+
return { taskId, turnId: active.id, status: "skipped", reason: "busy" };
|
|
472
157
|
}
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
158
|
+
const sessions = store.getTaskRoleSessionSet?.(taskId, roleName) ?? null;
|
|
159
|
+
const session = sessions?.sessions[active.effective.agentId];
|
|
160
|
+
const binding = sessions?.providerBinding;
|
|
161
|
+
const providerTurn = binding?.turn;
|
|
162
|
+
const authority = binding?.authority;
|
|
163
|
+
if (session?.launchId === undefined || session.nativeSessionId === undefined
|
|
164
|
+
|| providerTurn === null || providerTurn === undefined
|
|
165
|
+
|| providerTurn.turnId !== active.id || providerTurn.nativeTurnId === undefined
|
|
166
|
+
|| providerTurn.status !== "accepted"
|
|
167
|
+
|| authority?.owner !== "controller" || authority.holderId === undefined) {
|
|
168
|
+
store.releaseWorkMailbox(target, batchId);
|
|
169
|
+
return { taskId, status: "failed", reason: "not-ready", error: "Active Leader Turn has no steerable Provider fence." };
|
|
170
|
+
}
|
|
171
|
+
const batch = processing.batch;
|
|
172
|
+
const directive = [
|
|
173
|
+
`Aggregated Leader events: ${batch.reasons.join(", ")}.`,
|
|
174
|
+
`The first event arrived at ${batch.firstQueuedAt} and has waited at least 10 minutes while this Leader Turn remained active.`,
|
|
175
|
+
"Process these events now and update durable Task or WorkItem facts when needed.",
|
|
176
|
+
"After the events are handled, continue the work you were doing before this interruption.",
|
|
177
|
+
`Load the current exact context for ${taskId}/${active.id}; the event batch may have grown while this input was delivered.`
|
|
178
|
+
].join(" ");
|
|
179
|
+
const input = createTurnInput({
|
|
180
|
+
source: { type: "yui", channel: "leader-forced-wakeup" },
|
|
181
|
+
directive,
|
|
182
|
+
deltaRefIds: []
|
|
481
183
|
});
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
:
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
184
|
+
const outcome = await delivery.steerOnce({
|
|
185
|
+
taskId,
|
|
186
|
+
roleName,
|
|
187
|
+
agentId: active.effective.agentId,
|
|
188
|
+
adapterId: active.effective.adapterId,
|
|
189
|
+
launchId: session.launchId,
|
|
190
|
+
nativeSessionId: session.nativeSessionId,
|
|
191
|
+
nativeTurnId: providerTurn.nativeTurnId,
|
|
192
|
+
authority: {
|
|
193
|
+
epoch: authority.epoch,
|
|
194
|
+
owner: "controller",
|
|
195
|
+
holderId: authority.holderId
|
|
196
|
+
},
|
|
197
|
+
receiptId: `turn-input:${taskId}/${active.id}/${batchId}`,
|
|
198
|
+
text: directive
|
|
199
|
+
});
|
|
200
|
+
if (outcome !== "sent" && outcome !== "already-sent") {
|
|
201
|
+
if (outcome !== "delivery-unknown")
|
|
202
|
+
store.releaseWorkMailbox(target, batchId);
|
|
203
|
+
return {
|
|
204
|
+
taskId,
|
|
205
|
+
turnId: active.id,
|
|
206
|
+
status: outcome === "busy" ? "skipped" : "failed",
|
|
207
|
+
reason: outcome === "busy" ? "busy" : "not-ready",
|
|
208
|
+
error: outcome
|
|
494
209
|
};
|
|
495
|
-
|
|
210
|
+
}
|
|
211
|
+
const saved = store.saveLeaderSteer({ taskId, turnId: active.id, batchId, input, now });
|
|
212
|
+
if (saved !== "claimed")
|
|
213
|
+
store.releaseWorkMailbox(target, batchId);
|
|
214
|
+
return saved === "claimed"
|
|
215
|
+
? { taskId, turnId: active.id, status: "steered" }
|
|
216
|
+
: { taskId, turnId: active.id, status: "skipped", reason: saved };
|
|
496
217
|
}
|
|
497
218
|
function hasNativeSession(session) {
|
|
498
|
-
return session !== null
|
|
499
|
-
typeof session.nativeSessionId === "string"
|
|
500
|
-
session.nativeSessionId.trim().length > 0;
|
|
501
|
-
}
|
|
502
|
-
/**
|
|
503
|
-
* Issue 04 (long-term design): resolves the minimal wake envelope for a
|
|
504
|
-
* Leader wake. The envelope carries only the aggregated reason tags, the
|
|
505
|
-
* delta window, and read pointers; the Agent reads delta content on demand
|
|
506
|
-
* with `yui task wake show`. Returns null when the adapter lacks the
|
|
507
|
-
* projection, so the wake falls back to the full `yui task context`
|
|
508
|
-
* instruction.
|
|
509
|
-
*/
|
|
510
|
-
function resolveLeaderWakeEnvelope(store, taskId) {
|
|
511
|
-
if (typeof store.getTaskWakeEnvelope !== "function")
|
|
512
|
-
return null;
|
|
513
|
-
return store.getTaskWakeEnvelope(taskId);
|
|
514
|
-
}
|
|
515
|
-
function leaderWakeupInput(taskId, runId, reasons) {
|
|
516
|
-
return [
|
|
517
|
-
`For every Leader decision, milestone, or Work Item lifecycle command that is meaningful progress, carry this exact current-turn assertion on that command: YUI_LEADER_ACTION_RUN_ID=${runId} YUI_LEADER_ACTION_RECEIPT_ID=${formatAgentRunReceiptId(taskId, runId)}. The native Session environment may retain an older YUI_RUN_ID/launch; never copy those values, and never reuse this assertion after the turn changes.`,
|
|
518
|
-
`Wake reasons: ${reasons.join(", ")}. Load exact context for ${taskId}/${runId}.`
|
|
519
|
-
].join("\n");
|
|
219
|
+
return session !== null
|
|
220
|
+
&& typeof session.nativeSessionId === "string"
|
|
221
|
+
&& session.nativeSessionId.trim().length > 0;
|
|
520
222
|
}
|