@zq-silk/yui 0.13.3 → 0.13.5

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.
Files changed (48) hide show
  1. package/README.md +8 -8
  2. package/dist/cli/commandCatalog.js +22 -21
  3. package/dist/cli/interactionPolicy.js +0 -14
  4. package/dist/cli.js +42 -0
  5. package/dist/commands/executionAuditCommands.js +1 -1
  6. package/dist/commands/taskCommands.js +60 -326
  7. package/dist/commands/taskContextCommand.js +3 -14
  8. package/dist/commands/taskExecutionCommands.js +254 -0
  9. package/dist/commands/taskNextActionCommand.js +1 -3
  10. package/dist/commands/taskOverviewCommand.js +9 -2
  11. package/dist/commands/taskRoleRuntimeStatus.js +2 -25
  12. package/dist/controller/agentRuntimeObserver.js +4 -2
  13. package/dist/controller/clientRuntime.js +45 -2
  14. package/dist/controller/controller.js +6 -3
  15. package/dist/controller/fileSchedulerStoreAdapter.js +70 -188
  16. package/dist/controller/jobControl.js +3 -2
  17. package/dist/controller/runtime.js +6 -33
  18. package/dist/controller/runtimeEventProcessor.js +8 -4
  19. package/dist/controller/runtimeHookRunFence.js +4 -10
  20. package/dist/execution/executionHealth.js +8 -16
  21. package/dist/executor/agentExecutor.js +13 -14
  22. package/dist/executor/fileRoleLaunchPlanner.js +9 -16
  23. package/dist/lifecycle/exactRunTerminalization.js +24 -322
  24. package/dist/repository/taskWorkspaceCoordinator.js +0 -9
  25. package/dist/runtime/agentHost.js +20 -80
  26. package/dist/runtime/exactControlPlane.js +15 -9
  27. package/dist/runtime/providerContinuationReconciliationService.js +1 -1
  28. package/dist/runtime/providerRecoveryDecision.js +1 -1
  29. package/dist/runtime/providerRuntimeIdentity.js +25 -15
  30. package/dist/scheduler/activeRoleRunDelivery.js +1 -19
  31. package/dist/scheduler/leaderWakeupProcessor.js +12 -63
  32. package/dist/scheduler/ports.js +3 -2
  33. package/dist/scheduler/roleRunLiveness.js +4 -1
  34. package/dist/scheduler/roleRunStall.js +0 -2
  35. package/dist/scheduler/taskExecutionProjection.js +18 -1
  36. package/dist/scheduler/wakeupQueue.js +2 -1
  37. package/dist/storage/migration/productionRegistry.js +65 -0
  38. package/dist/storage/sqliteStore.js +10 -2
  39. package/dist/storage/taskStore.js +11 -3
  40. package/dist/task/completionReadiness.js +0 -67
  41. package/dist/task/nextAction.js +16 -32
  42. package/dist/task/task.js +38 -3
  43. package/dist/web/assets/client/i18n.js +0 -4
  44. package/dist/web/assets/client/view.js +0 -18
  45. package/dist/web/webSnapshot.js +7 -13
  46. package/package.json +1 -1
  47. package/dist/run/recoveryProjection.js +0 -252
  48. package/dist/runtime/conversationSwitch.js +0 -277
@@ -1,277 +0,0 @@
1
- import { roleAgentSessionResumeMode } from "../executor/agentExecutor.js";
2
- import { effectiveLaunchSnapshotsCompatibleForTaskSession } from "../executor/effectiveLaunch.js";
3
- import { currentProviderActivation, currentProviderConversation } from "./providerRuntimeIdentity.js";
4
- import { blockingProviderContinuations } from "./runtimeContinuationProjection.js";
5
- import { runtimeObservationFromTaskEvent } from "./runtimeObservation.js";
6
- export const CONVERSATION_SWITCH_REQUESTED_EVENT = "runtime.conversation-switch-requested";
7
- export const CONVERSATION_SWITCH_RESOLVED_EVENT = "runtime.conversation-switch-resolved";
8
- export const CONVERSATION_SWITCH_DETACHED_EVENT = "runtime.conversation-switch-detached";
9
- export function providerConversationGeneration(sessions) {
10
- const binding = sessions?.providerBinding;
11
- if (binding === null || binding === undefined)
12
- return null;
13
- const current = currentProviderConversation(binding);
14
- return `${binding.providerNamespace}:${binding.accountScope}:${current.epoch}:${current.conversationId}`;
15
- }
16
- export function projectConversationSwitch(events, roleName, sessions) {
17
- const requests = events.filter((event) => (event.type === CONVERSATION_SWITCH_REQUESTED_EVENT
18
- && event.payload.roleName === roleName));
19
- const request = requests.at(-1);
20
- if (request === undefined)
21
- return null;
22
- const requestId = request.payload.requestId;
23
- const generation = request.payload.generation;
24
- const requestedBy = request.payload.requestedBy;
25
- const reason = request.payload.reason;
26
- if (requestId === undefined || generation === undefined || reason === undefined
27
- || (requestedBy !== "user" && requestedBy !== "operator" && requestedBy !== "leader")) {
28
- return null;
29
- }
30
- const resolution = [...events].reverse().find((event) => (event.type === CONVERSATION_SWITCH_RESOLVED_EVENT
31
- && event.payload.requestId === requestId));
32
- const explicitStatus = resolution?.payload.status;
33
- const currentGeneration = providerConversationGeneration(sessions);
34
- const status = explicitStatus === "applied" || explicitStatus === "obsolete"
35
- ? explicitStatus
36
- : currentGeneration !== null && currentGeneration !== generation
37
- ? "obsolete"
38
- : "pending";
39
- return {
40
- requestId,
41
- roleName,
42
- generation,
43
- requestedBy,
44
- reason,
45
- requestedAt: request.createdAt,
46
- status,
47
- ...(resolution === undefined ? {} : { resolvedAt: resolution.createdAt })
48
- };
49
- }
50
- export function pendingConversationSwitch(events, roleName, sessions) {
51
- const projected = projectConversationSwitch(events, roleName, sessions);
52
- return projected?.status === "pending" ? projected : null;
53
- }
54
- export function roleSessionDispatchModeWithConversationSwitch(sessions, events, mailbox, roleName, agentId, effective) {
55
- const ordinary = roleAgentSessionResumeMode(sessions, agentId, effective);
56
- if (ordinary !== "resume") {
57
- if (sessions?.providerBinding !== null && sessions?.providerBinding !== undefined) {
58
- if (freshConversationLaunchAllowed({ sessions, events, mailbox, roleName })) {
59
- return "new";
60
- }
61
- const existing = sessions.sessions[agentId];
62
- if (existing?.nativeSessionId !== undefined
63
- && (existing.status === "stopped" || existing.status === "broken")
64
- && effectiveLaunchSnapshotsCompatibleForTaskSession(existing.effective, effective)) {
65
- // A terminal local Activation does not prove the Provider Conversation
66
- // is gone. Reattach to the same native identity by default.
67
- return "resume";
68
- }
69
- throw new Error(`Fresh Provider Conversation is not yet safe: ${sessions.owner.taskId}/${roleName}.`);
70
- }
71
- return ordinary;
72
- }
73
- if (sessions?.providerBinding !== null && sessions?.providerBinding !== undefined
74
- && freshConversationLaunchAllowed({ sessions, events, mailbox, roleName })) {
75
- return "new";
76
- }
77
- return "resume";
78
- }
79
- export function conversationDetachmentBasis(input) {
80
- const { sessions, mailbox } = input;
81
- const binding = sessions.providerBinding;
82
- const activation = binding === null ? null : currentProviderActivation(binding);
83
- if (input.runMode !== "new" || binding === null || activation === null
84
- || sessions.inFlight?.runId !== input.runId
85
- || mailbox?.processing?.batchId !== sessions.inFlight.receiptId
86
- || mailbox.processing.owner !== "controller"
87
- || mailbox.processing.executionRef?.type !== "run"
88
- || mailbox.processing.executionRef.taskId !== sessions.owner.taskId
89
- || mailbox.processing.executionRef.id !== input.runId
90
- || !actorRequestedSwitchBoundaryReady(sessions, mailbox)
91
- || currentConversationExecutionBlockers(sessions, input.events, input.roleName).length > 0
92
- || pendingConversationSwitch(input.events, input.roleName, sessions) === null) {
93
- return null;
94
- }
95
- return "actor-request";
96
- }
97
- export function conversationReplacementBasis(input) {
98
- const { sessions, mailbox } = input;
99
- const binding = sessions.providerBinding;
100
- if (input.runMode !== "new" || binding === null
101
- || sessions.inFlight?.runId !== input.runId
102
- || mailbox?.processing?.batchId !== sessions.inFlight.receiptId
103
- || mailbox.processing.owner !== "controller"
104
- || mailbox?.processing?.executionRef?.type !== "run"
105
- || mailbox.processing.executionRef.taskId !== sessions.owner.taskId
106
- || mailbox.processing.executionRef.id !== input.runId
107
- || mailbox.inputDelivery !== null
108
- || !conversationIsQuiescent(sessions, mailbox)
109
- || currentConversationExecutionBlockers(sessions, input.events, input.roleName).length > 0) {
110
- return null;
111
- }
112
- if (currentConversationIsExactlyUnrecoverable(sessions, input.events, input.roleName))
113
- return "exact-unrecoverable";
114
- return pendingConversationSwitch(input.events, input.roleName, sessions) === null
115
- ? null
116
- : "actor-request";
117
- }
118
- export function freshConversationLaunchAllowed(input) {
119
- return freshConversationLaunchBlockers(input).length === 0;
120
- }
121
- /** Exact reasons a fresh Conversation cannot currently be admitted. */
122
- export function freshConversationLaunchBlockers(input) {
123
- const { sessions } = input;
124
- if (sessions === null)
125
- return [];
126
- const session = sessions.sessions[sessions.activeAgentId];
127
- if (sessions.providerBinding === null) {
128
- return session === undefined
129
- || session.status === "stopped"
130
- || session.status === "broken"
131
- ? []
132
- : ["native-session-not-terminal"];
133
- }
134
- const request = pendingConversationSwitch(input.events, input.roleName, sessions);
135
- const binding = sessions.providerBinding;
136
- const blockers = [];
137
- if (input.mailbox?.inputDelivery != null)
138
- blockers.push("provider-input-delivery-unsettled");
139
- if (binding.turn !== null
140
- && ["submitting", "accepted", "running", "delivery-unknown"].includes(binding.turn.status))
141
- blockers.push("provider-turn-unsettled");
142
- blockers.push(...currentConversationExecutionBlockers(sessions, input.events, input.roleName));
143
- if (blockers.length > 0)
144
- return blockers;
145
- if (request !== null && actorRequestedSwitchBoundaryReady(sessions, input.mailbox, input.candidateRunId))
146
- return [];
147
- if (currentProviderActivation(binding) !== null)
148
- blockers.push("provider-activation-active");
149
- if (binding.authority.owner !== "none")
150
- blockers.push("provider-writer-authority-owned");
151
- if (blockers.length > 0)
152
- return blockers;
153
- if (currentProviderConversation(binding).recoverability === "unrecoverable") {
154
- return currentConversationIsExactlyUnrecoverable(sessions, input.events, input.roleName) ? [] : ["exact-unrecoverable-evidence-missing"];
155
- }
156
- if (request !== null)
157
- return ["actor-switch-boundary-not-ready"];
158
- return ["current-conversation-recoverable"];
159
- }
160
- function actorRequestedSwitchBoundaryReady(sessions, mailbox, candidateRunId) {
161
- const binding = sessions?.providerBinding;
162
- if (sessions === null || sessions === undefined
163
- || binding === null || binding === undefined
164
- || mailbox?.inputDelivery != null)
165
- return false;
166
- const turnSettled = binding.turn === null
167
- || ["completed", "failed", "cancelled", "rejected"].includes(binding.turn.status);
168
- if (!turnSettled)
169
- return false;
170
- const session = sessions.sessions[sessions.activeAgentId];
171
- if (session?.status === "running")
172
- return false;
173
- const activation = currentProviderActivation(binding);
174
- if (activation === null)
175
- return binding.authority.owner === "none";
176
- if (binding.authority.owner !== "controller"
177
- || binding.authority.holderId !== activation.activationId)
178
- return false;
179
- if (session === undefined)
180
- return false;
181
- if (sessions.inFlight === null) {
182
- if (mailbox?.processing === null)
183
- return true;
184
- return candidateRunId !== undefined
185
- && mailbox?.processing?.owner === "controller"
186
- && mailbox.processing.executionRef?.type === "run"
187
- && mailbox.processing.executionRef.taskId === sessions.owner.taskId
188
- && mailbox.processing.executionRef.id === candidateRunId;
189
- }
190
- return mailbox?.processing?.batchId === sessions.inFlight.receiptId
191
- && mailbox.processing.owner === "controller"
192
- && mailbox.processing.executionRef?.type === "run"
193
- && mailbox.processing.executionRef.taskId === sessions.owner.taskId
194
- && mailbox.processing.executionRef.id === sessions.inFlight.runId;
195
- }
196
- function conversationIsQuiescent(sessions, mailbox) {
197
- const binding = sessions?.providerBinding;
198
- if (binding === null || binding === undefined)
199
- return false;
200
- const turnSettled = binding.turn === null
201
- || ["completed", "failed", "cancelled", "rejected"].includes(binding.turn.status);
202
- return turnSettled
203
- && currentProviderActivation(binding) === null
204
- && binding.authority.owner === "none"
205
- && mailbox?.inputDelivery == null;
206
- }
207
- /**
208
- * A projected recoverability flag is necessary but not sufficient to replace
209
- * a Conversation. Require the exact structured missing-Conversation fact for
210
- * the current Provider identity and latest Activation generation, so an old
211
- * observation cannot authorize a later fresh Conversation. The binding's Run
212
- * id is deliberately excluded: replacement work rebinds that fence before
213
- * launching, while the missing fact necessarily came from the preceding Run's
214
- * exact attempt to resume this same Activation.
215
- */
216
- function currentConversationIsExactlyUnrecoverable(sessions, events, roleName) {
217
- const binding = sessions.providerBinding;
218
- if (binding === null)
219
- return false;
220
- const conversation = currentProviderConversation(binding);
221
- if (conversation.recoverability !== "unrecoverable")
222
- return false;
223
- const activation = [...binding.activations].reverse().find((entry) => (entry.conversationId === conversation.conversationId));
224
- const generationStartedAt = activation?.startedAt ?? conversation.createdAt;
225
- return events.some((event) => {
226
- const observation = runtimeObservationFromTaskEvent(event);
227
- if (observation === null
228
- || observation.kind !== "conversation.observed"
229
- || observation.payload.recoverability !== "unrecoverable"
230
- || (observation.authority !== "provider-structured"
231
- && observation.authority !== "controller"))
232
- return false;
233
- const fence = observation.fence;
234
- if (fence.taskId !== sessions.owner.taskId
235
- || fence.roleName !== roleName
236
- || fence.agentId !== binding.accountScope
237
- || fence.driverId !== binding.providerNamespace
238
- || fence.conversationId !== conversation.conversationId
239
- || (activation !== undefined && fence.activationId !== activation.activationId)) {
240
- return false;
241
- }
242
- return Date.parse(observation.observedAt ?? observation.receivedAt)
243
- >= Date.parse(generationStartedAt);
244
- });
245
- }
246
- /** Current Provider-owned work that may outlive a foreground Turn. */
247
- function currentConversationExecutionBlockers(sessions, events, roleName) {
248
- const binding = sessions.providerBinding;
249
- if (binding === null)
250
- return [];
251
- const conversation = currentProviderConversation(binding);
252
- const activation = [...binding.activations].reverse().find((entry) => (entry.conversationId === conversation.conversationId));
253
- if (activation === undefined)
254
- return ["provider-activation-identity-missing"];
255
- const activeOperation = events.some((event) => {
256
- const observation = runtimeObservationFromTaskEvent(event);
257
- if (observation?.kind !== "operation.started")
258
- return false;
259
- const fence = observation.fence;
260
- return fence.taskId === sessions.owner.taskId
261
- && fence.roleName === roleName
262
- && fence.agentId === binding.accountScope
263
- && fence.driverId === binding.providerNamespace
264
- && (fence.conversationId ?? fence.nativeSessionId) === conversation.conversationId
265
- && (fence.activationId ?? fence.launchId) === activation.activationId;
266
- });
267
- const blockingContinuation = blockingProviderContinuations(events).some((entry) => (entry.taskId === sessions.owner.taskId
268
- && entry.roleName === roleName
269
- && entry.identity.providerNamespace === binding.providerNamespace
270
- && entry.identity.accountScope === binding.accountScope
271
- && entry.identity.conversationId === conversation.conversationId
272
- && entry.identity.activationId === activation.activationId));
273
- return [
274
- ...(activeOperation ? ["provider-operation-active"] : []),
275
- ...(blockingContinuation ? ["provider-continuation-writer-owned"] : [])
276
- ];
277
- }