@zq-silk/yui 0.14.0 → 0.14.2
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 +64 -35
- package/README.md +258 -125
- package/dist/agent/argumentPolicy.js +2 -1
- package/dist/agent/managedRuntimeEnvironment.js +5 -8
- package/dist/cli/commandCatalog.js +74 -109
- package/dist/cli/helpRenderer.js +1 -2
- package/dist/cli/interactionCandidates.js +10 -0
- package/dist/cli/interactionPolicy.js +76 -37
- package/dist/cli/roleWizard.js +5 -6
- package/dist/cli/updateOrchestrator.js +10 -8
- package/dist/cli/updatePorts.js +17 -13
- package/dist/cli/upgradeCommand.js +2 -5
- package/dist/cli.js +268 -231
- package/dist/commands/agentCommands.js +13 -0
- package/dist/commands/configCommands.js +7 -19
- package/dist/commands/configOverview.js +3 -2
- package/dist/commands/durableJobCommands.js +1 -1
- package/dist/commands/executionAuditCommands.js +4 -9
- package/dist/commands/globalRoleCommands.js +17 -0
- package/dist/commands/profileCommands.js +200 -30
- package/dist/commands/sessionCommands.js +1 -1
- package/dist/commands/taskActor.js +29 -127
- package/dist/commands/taskChangeSetCommands.js +1 -3
- package/dist/commands/taskCommands.js +1771 -2107
- package/dist/commands/taskCompletionGate.js +27 -103
- package/dist/commands/taskContextCommand.js +47 -80
- package/dist/commands/taskExecutionCommands.js +9 -27
- package/dist/commands/taskInputCommands.js +10 -10
- package/dist/commands/taskIntegrationCommands.js +69 -61
- package/dist/commands/taskIntegrationQueueCommands.js +1 -1
- package/dist/commands/taskNextActionCommand.js +8 -29
- package/dist/commands/taskOverviewCommand.js +25 -3
- package/dist/commands/taskPublicationCommands.js +151 -85
- package/dist/commands/taskPublicationVerifyCommand.js +181 -0
- package/dist/commands/taskRemoteDeliveryCommand.js +134 -0
- package/dist/commands/taskRoleRuntimeStatus.js +5 -6
- package/dist/commands/taskUpstreamCommands.js +79 -95
- package/dist/config/configCatalog.js +1 -1
- package/dist/context/contextSnapshot.js +17 -2
- package/dist/context/sessionBootstrapManifest.js +18 -1
- package/dist/context/sourceTurnContext.js +30 -0
- package/dist/context/turnContextPack.js +107 -48
- package/dist/context/turnInputContract.js +11 -4
- package/dist/context/wakeNotification.js +84 -22
- package/dist/controller/agentRuntimeObserver.js +9 -12
- package/dist/controller/clientRuntime.js +13 -13
- package/dist/controller/controller.js +11 -11
- package/dist/controller/fileSchedulerStoreAdapter.js +262 -219
- package/dist/controller/jobControl.js +11 -10
- package/dist/controller/resourceInventory.js +6 -6
- package/dist/controller/resourceInventoryLinux.js +2 -2
- package/dist/controller/runtime.js +18 -61
- package/dist/controller/runtimeEventInbox.js +57 -34
- package/dist/controller/runtimeEventProcessor.js +36 -96
- package/dist/controller/runtimeHookTurnFence.js +33 -57
- package/dist/controller/runtimeLaunchCoordinator.js +44 -40
- package/dist/controller/runtimeObservationHook.js +18 -12
- package/dist/controller/sessionNotify.js +43 -28
- package/dist/controller/sessionOwnerReconciliation.js +21 -21
- package/dist/controller/structuredProviderObservation.js +13 -16
- package/dist/coordination/workMailboxQueue.js +132 -0
- package/dist/core/controllerServer.js +1 -0
- package/dist/domain/agentResultTransport.js +60 -0
- package/dist/execution/executionHealth.js +111 -118
- package/dist/execution/reviewMainTurn.js +161 -0
- package/dist/execution/workItemExecution.js +454 -0
- package/dist/execution/workItemExecutionProjection.js +309 -0
- package/dist/execution/workItemMainTurn.js +164 -0
- package/dist/executor/agentExecutor.js +19 -19
- package/dist/executor/executorRegistry.js +7 -28
- package/dist/executor/fileRoleLaunchPlanner.js +51 -83
- package/dist/external/githubPublicationVerifier.js +114 -0
- package/dist/external/gitlabPublicationVerifier.js +158 -0
- package/dist/external/pinnedCommandRunner.js +73 -0
- package/dist/integration/changeSetManifest.js +0 -3
- package/dist/integration/deliveryObligation.js +43 -6
- package/dist/integration/gitIntegrationService.js +284 -101
- package/dist/integration/integrationAttempt.js +64 -14
- package/dist/integration/integrationQueueEntry.js +5 -35
- package/dist/integration/integrationQueueService.js +65 -194
- package/dist/lifecycle/canonicalLifecycleEvent.js +16 -15
- package/dist/lifecycle/exactTurnTerminalization.js +100 -97
- package/dist/message/message.js +16 -0
- package/dist/observability/executionAudit.js +4 -25
- package/dist/observability/faultClassification.js +58 -70
- package/dist/observability/orchestrationMetrics.js +8 -50
- package/dist/profile/agentProfile.js +60 -15
- package/dist/profile/agentProfileRuntime.js +100 -0
- package/dist/release/releaseWorkflowPorts.js +5 -68
- package/dist/repository/executionLaneGitSnapshot.js +80 -0
- package/dist/repository/gitWorkspace.js +9 -67
- package/dist/repository/taskBaseFreshness.js +3 -1
- package/dist/repository/taskWorkspaceCoordinator.js +32 -4
- package/dist/repository/taskWorkspacePreparer.js +252 -411
- package/dist/resources/liveReferences.js +6 -55
- package/dist/resources/resourceDiscovery.js +1 -30
- package/dist/resources/resourceRegistrar.js +0 -23
- package/dist/review/deltaRecheck.js +8 -65
- package/dist/review/reviewAcceptance.js +22 -19
- package/dist/review/reviewConfig.js +0 -10
- package/dist/review/reviewDecision.js +2 -2
- package/dist/review/reviewRound.js +147 -273
- package/dist/review/reviewerAvailability.js +13 -23
- package/dist/role/role.js +3 -0
- package/dist/runtime/agentDriverObservation.js +1 -1
- package/dist/runtime/agentHost.js +51 -51
- package/dist/runtime/builtinAgentDrivers.js +9 -2
- package/dist/runtime/codexAppServerRuntime.js +23 -5
- package/dist/runtime/exactControlPlane.js +2 -267
- package/dist/runtime/firstProgressAdvisory.js +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/launchBroker.js +11 -11
- package/dist/runtime/lifecycleReservation.js +2 -2
- package/dist/runtime/managedCaller.js +111 -0
- package/dist/runtime/ports.js +16 -3
- package/dist/runtime/preallocatedNativeSession.js +2 -2
- package/dist/runtime/processExitObservation.js +3 -2
- package/dist/runtime/providerContinuationReconciliationService.js +1 -1
- package/dist/runtime/runtimeBinding.js +1 -1
- package/dist/runtime/runtimeObservation.js +33 -16
- package/dist/runtime/runtimeSessionCandidate.js +2 -2
- package/dist/runtime/runtimeStopReceipt.js +11 -11
- package/dist/runtime/sessionLaunchRequest.js +2 -2
- package/dist/runtime/sessionOwnerIdentity.js +9 -9
- package/dist/runtime/sessionOwnerRegistry.js +13 -13
- package/dist/runtime/sessionReconciliation.js +4 -4
- package/dist/runtime/sessionTerminationGuard.js +9 -9
- package/dist/runtime/sessionTokenMetrics.js +5 -7
- package/dist/runtime/structuredProviderHost.js +5 -5
- package/dist/runtime/taskRuntimeIsolation.js +24 -24
- package/dist/runtime/tmuxAdapters.js +32 -30
- package/dist/scheduler/activeRoleTurnDelivery.js +37 -15
- package/dist/scheduler/leaderWakeupProcessor.js +78 -55
- package/dist/scheduler/roleTurnLiveness.js +6 -6
- package/dist/scheduler/roleTurnStall.js +8 -9
- package/dist/scheduler/taskExecutionProjection.js +19 -41
- package/dist/scheduler/taskObservabilityProjection.js +75 -122
- package/dist/storage/sqliteSchema.js +1 -21
- package/dist/storage/sqliteStore.js +62 -47
- package/dist/storage/storageSchema.js +1 -8
- package/dist/storage/storageVersions.js +7 -4
- package/dist/storage/taskStore.js +8 -8
- package/dist/storage/upgrade/upgradeOrchestrator.js +112 -83
- package/dist/task/completionReadiness.js +17 -98
- package/dist/task/deliveryGuard.js +9 -11
- package/dist/task/draftPlan.js +142 -0
- package/dist/task/nextAction.js +179 -477
- package/dist/task/publicationVerification.js +1 -0
- package/dist/task/remoteDelivery.js +233 -0
- package/dist/task/task.js +108 -4
- package/dist/task/taskRecordReference.js +0 -1
- package/dist/turn/turn.js +109 -16
- package/dist/verification/verificationGateService.js +0 -26
- package/dist/web/assets/client/components.js +99 -121
- package/dist/web/assets/client/i18n.js +136 -58
- package/dist/web/assets/client/view.js +44 -0
- package/dist/web/assets/styles/cards.js +3 -15
- package/dist/web/assets/styles/widgets.js +4 -0
- package/dist/web/webSnapshot.js +29 -14
- package/dist/workItem/dependencyGate.js +34 -0
- package/dist/workItem/workItem.js +99 -266
- package/dist/workspace/workItemChangeSetManager.js +15 -59
- package/docs/task-local-identity.md +1 -1
- package/i18n/README.zh-CN.md +165 -59
- package/package.json +1 -1
- package/skills/yui-leader/SKILL.md +272 -782
- package/skills/yui-operator/SKILL.md +190 -365
- package/skills/yui-reviewer/SKILL.md +40 -33
- package/skills/yui-runtime/SKILL.md +27 -6
- package/skills/yui-worker/SKILL.md +19 -6
- package/dist/execution/candidateConvergence.js +0 -623
- package/dist/execution/executionGroup.js +0 -854
- package/dist/execution/resourceBroker.js +0 -426
- package/dist/executor/launchPlan.js +0 -16
- package/dist/review/reviewFinding.js +0 -240
- package/dist/review/reviewFindingLedger.js +0 -550
- package/dist/review/reviewOutcomeClassifier.js +0 -255
- package/dist/scheduler/resourceQueueProjection.js +0 -71
- package/dist/task/repairWave.js +0 -150
|
@@ -111,8 +111,8 @@ export class FileRuntimeEventProcessor {
|
|
|
111
111
|
foldOne(candidate, now) {
|
|
112
112
|
const event = candidate.event;
|
|
113
113
|
let outcome = "applied";
|
|
114
|
-
if (event.type === "native-turn-
|
|
115
|
-
outcome = this.
|
|
114
|
+
if (event.type === "native-turn-terminal") {
|
|
115
|
+
outcome = this.applyNativeTurnTerminal(event, now);
|
|
116
116
|
}
|
|
117
117
|
else if (event.type === "runtime-observation") {
|
|
118
118
|
outcome = this.applyRuntimeObservation(event, now);
|
|
@@ -124,14 +124,7 @@ export class FileRuntimeEventProcessor {
|
|
|
124
124
|
// converges without re-processing. No state change to apply.
|
|
125
125
|
this.applyDurableJobTerminal(event);
|
|
126
126
|
}
|
|
127
|
-
return {
|
|
128
|
-
candidate,
|
|
129
|
-
outcome,
|
|
130
|
-
notifyTaskRuntime: outcome === "applied" && ((event.type === "runtime-observation" && event.scope === "task"
|
|
131
|
-
&& ["session.started", "session.ready", "turn.accepted", "turn.completed"]
|
|
132
|
-
.includes(event.observation.kind))
|
|
133
|
-
|| (event.type === "native-turn-completed" && event.scope === "task"))
|
|
134
|
-
};
|
|
127
|
+
return { candidate, outcome };
|
|
135
128
|
}
|
|
136
129
|
applyRuntimeObservation(event, now) {
|
|
137
130
|
const taskId = event.observation.fence.taskId;
|
|
@@ -152,38 +145,6 @@ export class FileRuntimeEventProcessor {
|
|
|
152
145
|
this.acknowledge(candidate.representedEventIds.filter((id) => id !== candidate.event.id), acknowledged);
|
|
153
146
|
return undefined;
|
|
154
147
|
}
|
|
155
|
-
if (folded.notifyTaskRuntime) {
|
|
156
|
-
const event = candidate.event;
|
|
157
|
-
if (event.scope === "task"
|
|
158
|
-
&& event.taskId !== undefined
|
|
159
|
-
&& event.type !== "durable-job-terminal") {
|
|
160
|
-
if (event.type === "runtime-observation") {
|
|
161
|
-
const fence = event.observation.fence;
|
|
162
|
-
if (fence.taskId !== undefined && fence.nativeSessionId !== undefined) {
|
|
163
|
-
this.options.onTaskRuntimeApplied?.({
|
|
164
|
-
taskId: fence.taskId,
|
|
165
|
-
roleName: fence.roleName,
|
|
166
|
-
agentId: fence.agentId,
|
|
167
|
-
adapterId: this.drivers.require(fence.driverId).adapterId,
|
|
168
|
-
launchId: fence.launchId,
|
|
169
|
-
nativeSessionId: fence.nativeSessionId,
|
|
170
|
-
...(fence.turnId === undefined ? {} : { turnId: fence.turnId })
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
else if (event.type === "native-turn-completed") {
|
|
175
|
-
this.options.onTaskRuntimeApplied?.({
|
|
176
|
-
taskId: event.taskId,
|
|
177
|
-
roleName: event.roleName,
|
|
178
|
-
agentId: event.agentId,
|
|
179
|
-
adapterId: event.adapterId,
|
|
180
|
-
...(event.launchId === undefined ? {} : { launchId: event.launchId }),
|
|
181
|
-
nativeSessionId: event.nativeSessionId,
|
|
182
|
-
...(event.turnId === undefined ? {} : { turnId: event.turnId })
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
148
|
this.acknowledge(candidate.representedEventIds, acknowledged);
|
|
188
149
|
return undefined;
|
|
189
150
|
}
|
|
@@ -202,7 +163,7 @@ export class FileRuntimeEventProcessor {
|
|
|
202
163
|
// transaction as the terminal transition.
|
|
203
164
|
void event;
|
|
204
165
|
}
|
|
205
|
-
|
|
166
|
+
applyNativeTurnTerminal(event, now) {
|
|
206
167
|
if (event.scope === "task") {
|
|
207
168
|
const task = this.observer.getTask(event.taskId);
|
|
208
169
|
const input = {
|
|
@@ -211,11 +172,12 @@ export class FileRuntimeEventProcessor {
|
|
|
211
172
|
roleName: event.roleName,
|
|
212
173
|
agentId: event.agentId,
|
|
213
174
|
adapterId: event.adapterId,
|
|
214
|
-
...(event.
|
|
175
|
+
...(event.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: event.runtimeGenerationId }),
|
|
215
176
|
nativeSessionId: event.nativeSessionId,
|
|
216
177
|
nativeTurnId: event.nativeTurnId,
|
|
217
178
|
...(event.turnId === undefined ? {} : { turnId: event.turnId }),
|
|
218
|
-
|
|
179
|
+
providerStatus: event.providerStatus,
|
|
180
|
+
outcome: event.outcome
|
|
219
181
|
};
|
|
220
182
|
if (task === null)
|
|
221
183
|
return "obsolete";
|
|
@@ -223,14 +185,14 @@ export class FileRuntimeEventProcessor {
|
|
|
223
185
|
this.recordObsolete(event, task.status === "archived" ? "task-archived" : "task-retired", now);
|
|
224
186
|
return "obsolete";
|
|
225
187
|
}
|
|
226
|
-
const disposition = this.observer.
|
|
188
|
+
const disposition = this.observer.classifyRuntimeTurnTerminal?.(input) ?? "apply";
|
|
227
189
|
if (disposition === "deferred")
|
|
228
190
|
return disposition;
|
|
229
191
|
if (disposition === "obsolete") {
|
|
230
192
|
this.recordObsolete(event, "identity-mismatch-or-terminal", now);
|
|
231
193
|
return disposition;
|
|
232
194
|
}
|
|
233
|
-
const observed = this.observer.
|
|
195
|
+
const observed = this.observer.observeRuntimeTurnTerminal(input, now);
|
|
234
196
|
if (isObsoleteRuntimeTurnObservation(observed)) {
|
|
235
197
|
this.recordObsolete(event, "runtime-cleanup-or-stopped-session", now);
|
|
236
198
|
return "obsolete";
|
|
@@ -242,14 +204,15 @@ export class FileRuntimeEventProcessor {
|
|
|
242
204
|
roleName: event.roleName,
|
|
243
205
|
agentId: event.agentId,
|
|
244
206
|
adapterId: event.adapterId,
|
|
245
|
-
...(event.
|
|
207
|
+
...(event.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: event.runtimeGenerationId }),
|
|
246
208
|
nativeSessionId: event.nativeSessionId,
|
|
247
209
|
nativeTurnId: event.nativeTurnId,
|
|
248
210
|
...(event.title === undefined ? {} : { title: event.title }),
|
|
249
|
-
|
|
211
|
+
providerStatus: event.providerStatus,
|
|
212
|
+
outcome: event.outcome
|
|
250
213
|
};
|
|
251
|
-
if (this.observer.
|
|
252
|
-
this.observer.
|
|
214
|
+
if (this.observer.classifyGlobalRuntimeTurnTerminal?.(input) !== "obsolete") {
|
|
215
|
+
this.observer.observeGlobalRuntimeTurnTerminal(input, now);
|
|
253
216
|
return "applied";
|
|
254
217
|
}
|
|
255
218
|
return "obsolete";
|
|
@@ -268,7 +231,7 @@ export class FileRuntimeEventProcessor {
|
|
|
268
231
|
roleName: fence.roleName,
|
|
269
232
|
agentId: fence.agentId,
|
|
270
233
|
...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
|
|
271
|
-
|
|
234
|
+
runtimeGenerationId: fence.runtimeGenerationId,
|
|
272
235
|
nativeSessionId: fence.nativeSessionId,
|
|
273
236
|
reason
|
|
274
237
|
}, now);
|
|
@@ -285,7 +248,7 @@ export class FileRuntimeEventProcessor {
|
|
|
285
248
|
roleName: event.roleName,
|
|
286
249
|
agentId: event.agentId,
|
|
287
250
|
...(event.turnId === undefined ? {} : { turnId: event.turnId }),
|
|
288
|
-
...(event.
|
|
251
|
+
...(event.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: event.runtimeGenerationId }),
|
|
289
252
|
nativeSessionId: event.nativeSessionId,
|
|
290
253
|
reason
|
|
291
254
|
}, now);
|
|
@@ -416,7 +379,7 @@ function progressStreamKey(event) {
|
|
|
416
379
|
fence.roleName,
|
|
417
380
|
fence.agentId,
|
|
418
381
|
fence.driverId,
|
|
419
|
-
fence.
|
|
382
|
+
fence.runtimeGenerationId,
|
|
420
383
|
fence.nativeSessionId ?? null,
|
|
421
384
|
fence.turnId ?? null,
|
|
422
385
|
payload.activity,
|
|
@@ -527,10 +490,10 @@ export function createAsyncRuntimeObserver(invoke) {
|
|
|
527
490
|
return {
|
|
528
491
|
getTask: (taskId) => call("getTask", [taskId]),
|
|
529
492
|
observeRuntimeObservation: (input, now) => withNow("observeRuntimeObservation", input, now),
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
493
|
+
observeRuntimeTurnTerminal: (input, now) => withNow("observeRuntimeTurnTerminal", input, now),
|
|
494
|
+
observeGlobalRuntimeTurnTerminal: (input, now) => withNow("observeGlobalRuntimeTurnTerminal", input, now),
|
|
495
|
+
classifyRuntimeTurnTerminal: (input) => call("classifyRuntimeTurnTerminal", [input]),
|
|
496
|
+
classifyGlobalRuntimeTurnTerminal: (input) => call("classifyGlobalRuntimeTurnTerminal", [input]),
|
|
534
497
|
observeObsoleteRuntimeEvent: (input, now) => withNow("observeObsoleteRuntimeEvent", input, now)
|
|
535
498
|
};
|
|
536
499
|
}
|
|
@@ -575,8 +538,8 @@ export class AsyncRuntimeEventProcessor {
|
|
|
575
538
|
continue;
|
|
576
539
|
try {
|
|
577
540
|
let outcome = "applied";
|
|
578
|
-
if (event.type === "native-turn-
|
|
579
|
-
outcome = await this.
|
|
541
|
+
if (event.type === "native-turn-terminal") {
|
|
542
|
+
outcome = await this.applyNativeTurnTerminal(event, now);
|
|
580
543
|
}
|
|
581
544
|
else if (event.type === "runtime-observation") {
|
|
582
545
|
outcome = await this.applyRuntimeObservation(event, now);
|
|
@@ -631,25 +594,9 @@ export class AsyncRuntimeEventProcessor {
|
|
|
631
594
|
}
|
|
632
595
|
const outcome = (await this.observer.observeRuntimeObservation?.(event.observation, now))
|
|
633
596
|
?? "obsolete";
|
|
634
|
-
const fence = event.observation.fence;
|
|
635
|
-
if (outcome === "applied"
|
|
636
|
-
&& fence.taskId !== undefined
|
|
637
|
-
&& fence.nativeSessionId !== undefined
|
|
638
|
-
&& ["session.started", "session.ready", "turn.accepted", "turn.completed"]
|
|
639
|
-
.includes(event.observation.kind)) {
|
|
640
|
-
this.options.onTaskRuntimeApplied?.({
|
|
641
|
-
taskId: fence.taskId,
|
|
642
|
-
roleName: fence.roleName,
|
|
643
|
-
agentId: fence.agentId,
|
|
644
|
-
adapterId: this.drivers.require(fence.driverId).adapterId,
|
|
645
|
-
launchId: fence.launchId,
|
|
646
|
-
nativeSessionId: fence.nativeSessionId,
|
|
647
|
-
...(fence.turnId === undefined ? {} : { turnId: fence.turnId })
|
|
648
|
-
});
|
|
649
|
-
}
|
|
650
597
|
return outcome;
|
|
651
598
|
}
|
|
652
|
-
async
|
|
599
|
+
async applyNativeTurnTerminal(event, now) {
|
|
653
600
|
if (event.scope === "task") {
|
|
654
601
|
const task = await this.observer.getTask(event.taskId);
|
|
655
602
|
const input = {
|
|
@@ -658,11 +605,12 @@ export class AsyncRuntimeEventProcessor {
|
|
|
658
605
|
roleName: event.roleName,
|
|
659
606
|
agentId: event.agentId,
|
|
660
607
|
adapterId: event.adapterId,
|
|
661
|
-
...(event.
|
|
608
|
+
...(event.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: event.runtimeGenerationId }),
|
|
662
609
|
nativeSessionId: event.nativeSessionId,
|
|
663
610
|
nativeTurnId: event.nativeTurnId,
|
|
664
611
|
...(event.turnId === undefined ? {} : { turnId: event.turnId }),
|
|
665
|
-
|
|
612
|
+
providerStatus: event.providerStatus,
|
|
613
|
+
outcome: event.outcome
|
|
666
614
|
};
|
|
667
615
|
if (task === null)
|
|
668
616
|
return "obsolete";
|
|
@@ -670,27 +618,18 @@ export class AsyncRuntimeEventProcessor {
|
|
|
670
618
|
await this.recordObsolete(event, task.status === "archived" ? "task-archived" : "task-retired", now);
|
|
671
619
|
return "obsolete";
|
|
672
620
|
}
|
|
673
|
-
const disposition = (await this.observer.
|
|
621
|
+
const disposition = (await this.observer.classifyRuntimeTurnTerminal?.(input)) ?? "apply";
|
|
674
622
|
if (disposition === "deferred")
|
|
675
623
|
return disposition;
|
|
676
624
|
if (disposition === "obsolete") {
|
|
677
625
|
await this.recordObsolete(event, "identity-mismatch-or-terminal", now);
|
|
678
626
|
return disposition;
|
|
679
627
|
}
|
|
680
|
-
const observed = await this.observer.
|
|
628
|
+
const observed = await this.observer.observeRuntimeTurnTerminal(input, now);
|
|
681
629
|
if (isObsoleteRuntimeTurnObservation(observed)) {
|
|
682
630
|
await this.recordObsolete(event, "runtime-cleanup-or-stopped-session", now);
|
|
683
631
|
return "obsolete";
|
|
684
632
|
}
|
|
685
|
-
this.options.onTaskRuntimeApplied?.({
|
|
686
|
-
taskId: event.taskId,
|
|
687
|
-
roleName: event.roleName,
|
|
688
|
-
agentId: event.agentId,
|
|
689
|
-
adapterId: event.adapterId,
|
|
690
|
-
...(event.launchId === undefined ? {} : { launchId: event.launchId }),
|
|
691
|
-
nativeSessionId: event.nativeSessionId,
|
|
692
|
-
...(event.turnId === undefined ? {} : { turnId: event.turnId })
|
|
693
|
-
});
|
|
694
633
|
return "applied";
|
|
695
634
|
}
|
|
696
635
|
const input = {
|
|
@@ -698,14 +637,15 @@ export class AsyncRuntimeEventProcessor {
|
|
|
698
637
|
roleName: event.roleName,
|
|
699
638
|
agentId: event.agentId,
|
|
700
639
|
adapterId: event.adapterId,
|
|
701
|
-
...(event.
|
|
640
|
+
...(event.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: event.runtimeGenerationId }),
|
|
702
641
|
nativeSessionId: event.nativeSessionId,
|
|
703
642
|
nativeTurnId: event.nativeTurnId,
|
|
704
643
|
...(event.title === undefined ? {} : { title: event.title }),
|
|
705
|
-
|
|
644
|
+
providerStatus: event.providerStatus,
|
|
645
|
+
outcome: event.outcome
|
|
706
646
|
};
|
|
707
|
-
if ((await this.observer.
|
|
708
|
-
await this.observer.
|
|
647
|
+
if ((await this.observer.classifyGlobalRuntimeTurnTerminal?.(input)) !== "obsolete") {
|
|
648
|
+
await this.observer.observeGlobalRuntimeTurnTerminal(input, now);
|
|
709
649
|
return "applied";
|
|
710
650
|
}
|
|
711
651
|
return "obsolete";
|
|
@@ -724,7 +664,7 @@ export class AsyncRuntimeEventProcessor {
|
|
|
724
664
|
roleName: fence.roleName,
|
|
725
665
|
agentId: fence.agentId,
|
|
726
666
|
...(fence.turnId === undefined ? {} : { turnId: fence.turnId }),
|
|
727
|
-
|
|
667
|
+
runtimeGenerationId: fence.runtimeGenerationId,
|
|
728
668
|
nativeSessionId: fence.nativeSessionId,
|
|
729
669
|
reason
|
|
730
670
|
}, now);
|
|
@@ -737,7 +677,7 @@ export class AsyncRuntimeEventProcessor {
|
|
|
737
677
|
roleName: event.roleName,
|
|
738
678
|
agentId: event.agentId,
|
|
739
679
|
...(event.turnId === undefined ? {} : { turnId: event.turnId }),
|
|
740
|
-
...(event.
|
|
680
|
+
...(event.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: event.runtimeGenerationId }),
|
|
741
681
|
nativeSessionId: event.nativeSessionId,
|
|
742
682
|
reason
|
|
743
683
|
}, now);
|
|
@@ -2,7 +2,6 @@ import { openCurrentTaskStore } from "../storage/currentTaskStore.js";
|
|
|
2
2
|
import { hasRuntimeCleanupObligation, isRuntimeLaunchReservation, runtimeLifecycleTarget } from "../runtime/lifecycleReservation.js";
|
|
3
3
|
import { nativeSessionIdForLaunch } from "../runtime/preallocatedNativeSession.js";
|
|
4
4
|
import { runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
|
|
5
|
-
import { YUI_CONTROL_PLANE_DESCRIPTOR, YUI_TASK_RUNTIME_DESCRIPTOR, assertExactTaskRuntimeEnvironment, exactControlPlaneDigest, parseExactControlPlaneDescriptor, refreshReusedTaskRuntimeDescriptorSource } from "../runtime/exactControlPlane.js";
|
|
6
5
|
import { formatTurnReceiptId } from "../task/taskRecordReference.js";
|
|
7
6
|
import { managedProviderTurnId } from "../runtime/providerRuntimeIdentity.js";
|
|
8
7
|
/**
|
|
@@ -10,7 +9,7 @@ import { managedProviderTurnId } from "../runtime/providerRuntimeIdentity.js";
|
|
|
10
9
|
* exception is a Driver-declared startup Session Hook, which can arrive before
|
|
11
10
|
* Session projection and is fenced by the exact Turn-bound launch reservation.
|
|
12
11
|
* Preallocated identities are additionally checked against Yui's deterministic
|
|
13
|
-
*
|
|
12
|
+
* runtime generation identity. The immutable event is revalidated by the inbox fold.
|
|
14
13
|
*/
|
|
15
14
|
export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativeSessionId, options = {}) {
|
|
16
15
|
if (environment.YUI_SESSION_SCOPE !== "task") {
|
|
@@ -24,17 +23,7 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
24
23
|
const roleName = requireIdentity(environment.YUI_ROLE, "Role name");
|
|
25
24
|
const agentId = requireIdentity(environment.YUI_AGENT_ID, "Agent id");
|
|
26
25
|
const workspace = requireIdentity(environment.YUI_WORKSPACE, "YUI workspace");
|
|
27
|
-
const runtimeSource = environment[YUI_TASK_RUNTIME_DESCRIPTOR];
|
|
28
|
-
const runtime = runtimeSource === undefined
|
|
29
|
-
? undefined
|
|
30
|
-
: assertExactTaskRuntimeEnvironment(runtimeSource, environment, exactControlPlaneDigest(parseExactControlPlaneDescriptor(requireIdentity(environment[YUI_CONTROL_PLANE_DESCRIPTOR], "Exact control-plane descriptor"))), home);
|
|
31
|
-
const launchId = requireIdentity(runtime?.launchId ?? environment.YUI_LAUNCH_ID, "Launch id");
|
|
32
26
|
const nativeSessionId = requireIdentity(payloadNativeSessionId, "Provider session id");
|
|
33
|
-
const expectedNativeSessionId = runtime?.nativeSessionId ?? environment.YUI_NATIVE_SESSION_ID;
|
|
34
|
-
if (expectedNativeSessionId !== undefined
|
|
35
|
-
&& nativeSessionId !== requireIdentity(expectedNativeSessionId, "YUI native session id")) {
|
|
36
|
-
throw new Error("Runtime observation Hook native Session does not match its launch envelope.");
|
|
37
|
-
}
|
|
38
27
|
const store = openCurrentTaskStore(home);
|
|
39
28
|
const task = store.getTask(taskId);
|
|
40
29
|
if (task === null
|
|
@@ -53,6 +42,22 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
53
42
|
const session = sessions?.sessions[agentId];
|
|
54
43
|
const activeTurn = store.getActiveTurn(taskId, roleName);
|
|
55
44
|
const providerTurn = sessions?.providerBinding?.turn;
|
|
45
|
+
// Launch generation and Turn are durable facts, never envelope facts. A
|
|
46
|
+
// native pane outlives both, so anything it inherited at launch is stale for
|
|
47
|
+
// every later generation; the Session's own record (or the in-flight launch
|
|
48
|
+
// reservation during startup) is the only current answer.
|
|
49
|
+
const lifecycleMailbox = store.getWorkMailbox(runtimeLifecycleTarget({
|
|
50
|
+
scope: "task",
|
|
51
|
+
taskId,
|
|
52
|
+
roleName
|
|
53
|
+
}));
|
|
54
|
+
const reservedRuntimeGenerationId = isRuntimeLaunchReservation(lifecycleMailbox?.processing)
|
|
55
|
+
? lifecycleMailbox?.processing?.batchId
|
|
56
|
+
: undefined;
|
|
57
|
+
const runtimeGenerationId = requireIdentity(session?.runtimeGenerationId ?? reservedRuntimeGenerationId, "Runtime generation id");
|
|
58
|
+
const durableTurnId = activeTurn?.id
|
|
59
|
+
?? managedProviderTurnId(providerTurn)
|
|
60
|
+
?? undefined;
|
|
56
61
|
const directProviderTurn = providerTurn !== null
|
|
57
62
|
&& providerTurn !== undefined
|
|
58
63
|
&& providerTurn.turnId === undefined
|
|
@@ -62,7 +67,7 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
62
67
|
if (directProviderTurn || sessionOnlyObservation) {
|
|
63
68
|
if (session === undefined
|
|
64
69
|
|| session.adapterId !== adapterId
|
|
65
|
-
|| session.
|
|
70
|
+
|| session.runtimeGenerationId !== runtimeGenerationId
|
|
66
71
|
|| session.nativeSessionId !== nativeSessionId
|
|
67
72
|
|| session.effective.workspace.root !== workspace) {
|
|
68
73
|
throw new Error("Runtime observation Hook Session does not match durable state.");
|
|
@@ -71,7 +76,7 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
71
76
|
taskId,
|
|
72
77
|
roleName,
|
|
73
78
|
agentId,
|
|
74
|
-
|
|
79
|
+
runtimeGenerationId,
|
|
75
80
|
...(directProviderTurn ? { receiptId: providerTurn.attemptId } : {}),
|
|
76
81
|
nativeSessionId,
|
|
77
82
|
workspace
|
|
@@ -99,17 +104,12 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
99
104
|
continuationId: options.continuationId,
|
|
100
105
|
continuationGeneration: options.continuationGeneration ?? 1
|
|
101
106
|
}));
|
|
102
|
-
const mailbox =
|
|
103
|
-
|
|
104
|
-
taskId,
|
|
105
|
-
roleName
|
|
106
|
-
}));
|
|
107
|
-
const exactReservation = isRuntimeLaunchReservation(mailbox?.processing, launchId)
|
|
107
|
+
const mailbox = lifecycleMailbox;
|
|
108
|
+
const exactReservation = isRuntimeLaunchReservation(mailbox?.processing, runtimeGenerationId)
|
|
108
109
|
&& !hasRuntimeCleanupObligation(mailbox);
|
|
109
110
|
const startupTurnId = options.startupSession === undefined
|
|
110
111
|
? undefined
|
|
111
|
-
: requireIdentity(
|
|
112
|
-
?? environment.YUI_TURN_ID, "Turn id");
|
|
112
|
+
: requireIdentity(durableTurnId, "Turn id");
|
|
113
113
|
const startupReservation = startupTurnId !== undefined
|
|
114
114
|
&& exactReservation
|
|
115
115
|
&& !hasRuntimeCleanupObligation(mailbox);
|
|
@@ -122,17 +122,19 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
122
122
|
&& startupReservation
|
|
123
123
|
&& startupTurn?.mode === "new"
|
|
124
124
|
&& session.status === "ended";
|
|
125
|
+
// The startup mode itself says whether Yui preallocated the native Session
|
|
126
|
+
// id or the Provider reports it. A preallocated startup is proven against
|
|
127
|
+
// Yui's deterministic runtime generation identity, which is stronger than comparing a
|
|
128
|
+
// value the launch envelope carried.
|
|
125
129
|
const preallocatedStartup = options.startupSession === "preallocated"
|
|
126
|
-
&& expectedNativeSessionId !== undefined
|
|
127
130
|
&& (session === undefined || replacementStartup)
|
|
128
131
|
&& startupReservation
|
|
129
|
-
&& nativeSessionId === nativeSessionIdForLaunch(home,
|
|
132
|
+
&& nativeSessionId === nativeSessionIdForLaunch(home, runtimeGenerationId, agentId, adapterId);
|
|
130
133
|
const discoveredStartup = options.startupSession === "discovered"
|
|
131
|
-
&& expectedNativeSessionId === undefined
|
|
132
134
|
&& (session === undefined || replacementStartup)
|
|
133
135
|
&& startupReservation;
|
|
134
136
|
const terminalTurnId = options.terminal === true && acceptedBinding === null
|
|
135
|
-
? requireIdentity(
|
|
137
|
+
? requireIdentity(durableTurnId, "Turn id")
|
|
136
138
|
: undefined;
|
|
137
139
|
const terminalTurn = acceptedBinding !== null
|
|
138
140
|
? store.getTurn(taskId, acceptedBinding.fence.turnId)
|
|
@@ -156,33 +158,7 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
156
158
|
?? activeTurn?.id
|
|
157
159
|
?? startupTurnId
|
|
158
160
|
?? terminalTurnId;
|
|
159
|
-
|
|
160
|
-
let effectiveLaunchId = acceptedBinding?.fence.launchId ?? launchId;
|
|
161
|
-
const sessionLaunchId = session?.launchId;
|
|
162
|
-
if (acceptedBinding === null
|
|
163
|
-
&& runtime !== undefined
|
|
164
|
-
&& session !== undefined
|
|
165
|
-
&& !replacementStartup
|
|
166
|
-
&& sessionLaunchId !== undefined
|
|
167
|
-
&& typeof runtimeSource === "string"
|
|
168
|
-
&& !runtimeSource.trimStart().startsWith("{")
|
|
169
|
-
&& (runtime.turnId !== turnId
|
|
170
|
-
|| runtime.launchId !== sessionLaunchId
|
|
171
|
-
|| runtime.nativeSessionId !== session.nativeSessionId)) {
|
|
172
|
-
// A reused native pane keeps its original descriptor source. Advance only
|
|
173
|
-
// that Hook-owned source to the current durable generation before the
|
|
174
|
-
// volatile fence; the Controller no longer scans history to keep it fresh.
|
|
175
|
-
effectiveRuntime = refreshReusedTaskRuntimeDescriptorSource(runtimeSource, home, store, {
|
|
176
|
-
turnId,
|
|
177
|
-
launchId: sessionLaunchId,
|
|
178
|
-
nativeSessionId: session.nativeSessionId
|
|
179
|
-
});
|
|
180
|
-
effectiveLaunchId = effectiveRuntime.launchId;
|
|
181
|
-
}
|
|
182
|
-
if (acceptedBinding === null
|
|
183
|
-
&& effectiveRuntime?.turnId !== undefined && effectiveRuntime.turnId !== turnId) {
|
|
184
|
-
throw new Error("Runtime observation Hook Turn does not match its current descriptor.");
|
|
185
|
-
}
|
|
161
|
+
const effectiveRuntimeGenerationId = acceptedBinding?.fence.runtimeGenerationId ?? runtimeGenerationId;
|
|
186
162
|
const turn = acceptedBinding !== null || exactTerminal
|
|
187
163
|
? terminalTurn
|
|
188
164
|
: store.getActiveTurn(taskId, roleName);
|
|
@@ -198,7 +174,7 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
198
174
|
}
|
|
199
175
|
if (session !== undefined && acceptedBinding === null && !replacementStartup) {
|
|
200
176
|
if (session.adapterId !== adapterId
|
|
201
|
-
|| session.
|
|
177
|
+
|| session.runtimeGenerationId !== effectiveRuntimeGenerationId
|
|
202
178
|
|| session.nativeSessionId !== nativeSessionId
|
|
203
179
|
|| session.effective.workspace.root !== workspace) {
|
|
204
180
|
throw new Error("Runtime observation Hook Session does not match its durable generation.");
|
|
@@ -213,7 +189,7 @@ export function resolveRuntimeHookTurnFence(environment, adapterId, payloadNativ
|
|
|
213
189
|
taskId,
|
|
214
190
|
roleName,
|
|
215
191
|
agentId,
|
|
216
|
-
|
|
192
|
+
runtimeGenerationId: effectiveRuntimeGenerationId,
|
|
217
193
|
turnId,
|
|
218
194
|
...(acceptedBinding?.fence.receiptId === undefined
|
|
219
195
|
? activationReceiptId === undefined ? {} : { receiptId: activationReceiptId }
|
|
@@ -242,7 +218,7 @@ function knownContinuationBinding(events, expected) {
|
|
|
242
218
|
if (binding === null)
|
|
243
219
|
return null;
|
|
244
220
|
if (matches.some((candidate) => candidate.fence.turnId !== binding.fence.turnId
|
|
245
|
-
|| candidate.fence.
|
|
221
|
+
|| candidate.fence.runtimeGenerationId !== binding.fence.runtimeGenerationId
|
|
246
222
|
|| candidate.fence.receiptId !== binding.fence.receiptId)) {
|
|
247
223
|
throw new Error("Runtime observation Hook continuation has conflicting durable Turn bindings.");
|
|
248
224
|
}
|
|
@@ -267,7 +243,7 @@ function acceptedTurnBinding(events, expected) {
|
|
|
267
243
|
if (binding === null)
|
|
268
244
|
return null;
|
|
269
245
|
if (matches.some((candidate) => candidate.fence.turnId !== binding.fence.turnId
|
|
270
|
-
|| candidate.fence.
|
|
246
|
+
|| candidate.fence.runtimeGenerationId !== binding.fence.runtimeGenerationId
|
|
271
247
|
|| candidate.fence.receiptId !== binding.fence.receiptId)) {
|
|
272
248
|
throw new Error("Runtime observation Hook native Turn has conflicting durable Turn bindings.");
|
|
273
249
|
}
|