@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.
Files changed (179) hide show
  1. package/ARCHITECTURE.md +64 -35
  2. package/README.md +258 -125
  3. package/dist/agent/argumentPolicy.js +2 -1
  4. package/dist/agent/managedRuntimeEnvironment.js +5 -8
  5. package/dist/cli/commandCatalog.js +74 -109
  6. package/dist/cli/helpRenderer.js +1 -2
  7. package/dist/cli/interactionCandidates.js +10 -0
  8. package/dist/cli/interactionPolicy.js +76 -37
  9. package/dist/cli/roleWizard.js +5 -6
  10. package/dist/cli/updateOrchestrator.js +10 -8
  11. package/dist/cli/updatePorts.js +17 -13
  12. package/dist/cli/upgradeCommand.js +2 -5
  13. package/dist/cli.js +268 -231
  14. package/dist/commands/agentCommands.js +13 -0
  15. package/dist/commands/configCommands.js +7 -19
  16. package/dist/commands/configOverview.js +3 -2
  17. package/dist/commands/durableJobCommands.js +1 -1
  18. package/dist/commands/executionAuditCommands.js +4 -9
  19. package/dist/commands/globalRoleCommands.js +17 -0
  20. package/dist/commands/profileCommands.js +200 -30
  21. package/dist/commands/sessionCommands.js +1 -1
  22. package/dist/commands/taskActor.js +29 -127
  23. package/dist/commands/taskChangeSetCommands.js +1 -3
  24. package/dist/commands/taskCommands.js +1771 -2107
  25. package/dist/commands/taskCompletionGate.js +27 -103
  26. package/dist/commands/taskContextCommand.js +47 -80
  27. package/dist/commands/taskExecutionCommands.js +9 -27
  28. package/dist/commands/taskInputCommands.js +10 -10
  29. package/dist/commands/taskIntegrationCommands.js +69 -61
  30. package/dist/commands/taskIntegrationQueueCommands.js +1 -1
  31. package/dist/commands/taskNextActionCommand.js +8 -29
  32. package/dist/commands/taskOverviewCommand.js +25 -3
  33. package/dist/commands/taskPublicationCommands.js +151 -85
  34. package/dist/commands/taskPublicationVerifyCommand.js +181 -0
  35. package/dist/commands/taskRemoteDeliveryCommand.js +134 -0
  36. package/dist/commands/taskRoleRuntimeStatus.js +5 -6
  37. package/dist/commands/taskUpstreamCommands.js +79 -95
  38. package/dist/config/configCatalog.js +1 -1
  39. package/dist/context/contextSnapshot.js +17 -2
  40. package/dist/context/sessionBootstrapManifest.js +18 -1
  41. package/dist/context/sourceTurnContext.js +30 -0
  42. package/dist/context/turnContextPack.js +107 -48
  43. package/dist/context/turnInputContract.js +11 -4
  44. package/dist/context/wakeNotification.js +84 -22
  45. package/dist/controller/agentRuntimeObserver.js +9 -12
  46. package/dist/controller/clientRuntime.js +13 -13
  47. package/dist/controller/controller.js +11 -11
  48. package/dist/controller/fileSchedulerStoreAdapter.js +262 -219
  49. package/dist/controller/jobControl.js +11 -10
  50. package/dist/controller/resourceInventory.js +6 -6
  51. package/dist/controller/resourceInventoryLinux.js +2 -2
  52. package/dist/controller/runtime.js +18 -61
  53. package/dist/controller/runtimeEventInbox.js +57 -34
  54. package/dist/controller/runtimeEventProcessor.js +36 -96
  55. package/dist/controller/runtimeHookTurnFence.js +33 -57
  56. package/dist/controller/runtimeLaunchCoordinator.js +44 -40
  57. package/dist/controller/runtimeObservationHook.js +18 -12
  58. package/dist/controller/sessionNotify.js +43 -28
  59. package/dist/controller/sessionOwnerReconciliation.js +21 -21
  60. package/dist/controller/structuredProviderObservation.js +13 -16
  61. package/dist/coordination/workMailboxQueue.js +132 -0
  62. package/dist/core/controllerServer.js +1 -0
  63. package/dist/domain/agentResultTransport.js +60 -0
  64. package/dist/execution/executionHealth.js +111 -118
  65. package/dist/execution/reviewMainTurn.js +161 -0
  66. package/dist/execution/workItemExecution.js +454 -0
  67. package/dist/execution/workItemExecutionProjection.js +309 -0
  68. package/dist/execution/workItemMainTurn.js +164 -0
  69. package/dist/executor/agentExecutor.js +19 -19
  70. package/dist/executor/executorRegistry.js +7 -28
  71. package/dist/executor/fileRoleLaunchPlanner.js +51 -83
  72. package/dist/external/githubPublicationVerifier.js +114 -0
  73. package/dist/external/gitlabPublicationVerifier.js +158 -0
  74. package/dist/external/pinnedCommandRunner.js +73 -0
  75. package/dist/integration/changeSetManifest.js +0 -3
  76. package/dist/integration/deliveryObligation.js +43 -6
  77. package/dist/integration/gitIntegrationService.js +284 -101
  78. package/dist/integration/integrationAttempt.js +64 -14
  79. package/dist/integration/integrationQueueEntry.js +5 -35
  80. package/dist/integration/integrationQueueService.js +65 -194
  81. package/dist/lifecycle/canonicalLifecycleEvent.js +16 -15
  82. package/dist/lifecycle/exactTurnTerminalization.js +100 -97
  83. package/dist/message/message.js +16 -0
  84. package/dist/observability/executionAudit.js +4 -25
  85. package/dist/observability/faultClassification.js +58 -70
  86. package/dist/observability/orchestrationMetrics.js +8 -50
  87. package/dist/profile/agentProfile.js +60 -15
  88. package/dist/profile/agentProfileRuntime.js +100 -0
  89. package/dist/release/releaseWorkflowPorts.js +5 -68
  90. package/dist/repository/executionLaneGitSnapshot.js +80 -0
  91. package/dist/repository/gitWorkspace.js +9 -67
  92. package/dist/repository/taskBaseFreshness.js +3 -1
  93. package/dist/repository/taskWorkspaceCoordinator.js +32 -4
  94. package/dist/repository/taskWorkspacePreparer.js +252 -411
  95. package/dist/resources/liveReferences.js +6 -55
  96. package/dist/resources/resourceDiscovery.js +1 -30
  97. package/dist/resources/resourceRegistrar.js +0 -23
  98. package/dist/review/deltaRecheck.js +8 -65
  99. package/dist/review/reviewAcceptance.js +22 -19
  100. package/dist/review/reviewConfig.js +0 -10
  101. package/dist/review/reviewDecision.js +2 -2
  102. package/dist/review/reviewRound.js +147 -273
  103. package/dist/review/reviewerAvailability.js +13 -23
  104. package/dist/role/role.js +3 -0
  105. package/dist/runtime/agentDriverObservation.js +1 -1
  106. package/dist/runtime/agentHost.js +51 -51
  107. package/dist/runtime/builtinAgentDrivers.js +9 -2
  108. package/dist/runtime/codexAppServerRuntime.js +23 -5
  109. package/dist/runtime/exactControlPlane.js +2 -267
  110. package/dist/runtime/firstProgressAdvisory.js +1 -1
  111. package/dist/runtime/index.js +1 -1
  112. package/dist/runtime/launchBroker.js +11 -11
  113. package/dist/runtime/lifecycleReservation.js +2 -2
  114. package/dist/runtime/managedCaller.js +111 -0
  115. package/dist/runtime/ports.js +16 -3
  116. package/dist/runtime/preallocatedNativeSession.js +2 -2
  117. package/dist/runtime/processExitObservation.js +3 -2
  118. package/dist/runtime/providerContinuationReconciliationService.js +1 -1
  119. package/dist/runtime/runtimeBinding.js +1 -1
  120. package/dist/runtime/runtimeObservation.js +33 -16
  121. package/dist/runtime/runtimeSessionCandidate.js +2 -2
  122. package/dist/runtime/runtimeStopReceipt.js +11 -11
  123. package/dist/runtime/sessionLaunchRequest.js +2 -2
  124. package/dist/runtime/sessionOwnerIdentity.js +9 -9
  125. package/dist/runtime/sessionOwnerRegistry.js +13 -13
  126. package/dist/runtime/sessionReconciliation.js +4 -4
  127. package/dist/runtime/sessionTerminationGuard.js +9 -9
  128. package/dist/runtime/sessionTokenMetrics.js +5 -7
  129. package/dist/runtime/structuredProviderHost.js +5 -5
  130. package/dist/runtime/taskRuntimeIsolation.js +24 -24
  131. package/dist/runtime/tmuxAdapters.js +32 -30
  132. package/dist/scheduler/activeRoleTurnDelivery.js +37 -15
  133. package/dist/scheduler/leaderWakeupProcessor.js +78 -55
  134. package/dist/scheduler/roleTurnLiveness.js +6 -6
  135. package/dist/scheduler/roleTurnStall.js +8 -9
  136. package/dist/scheduler/taskExecutionProjection.js +19 -41
  137. package/dist/scheduler/taskObservabilityProjection.js +75 -122
  138. package/dist/storage/sqliteSchema.js +1 -21
  139. package/dist/storage/sqliteStore.js +62 -47
  140. package/dist/storage/storageSchema.js +1 -8
  141. package/dist/storage/storageVersions.js +7 -4
  142. package/dist/storage/taskStore.js +8 -8
  143. package/dist/storage/upgrade/upgradeOrchestrator.js +112 -83
  144. package/dist/task/completionReadiness.js +17 -98
  145. package/dist/task/deliveryGuard.js +9 -11
  146. package/dist/task/draftPlan.js +142 -0
  147. package/dist/task/nextAction.js +179 -477
  148. package/dist/task/publicationVerification.js +1 -0
  149. package/dist/task/remoteDelivery.js +233 -0
  150. package/dist/task/task.js +108 -4
  151. package/dist/task/taskRecordReference.js +0 -1
  152. package/dist/turn/turn.js +109 -16
  153. package/dist/verification/verificationGateService.js +0 -26
  154. package/dist/web/assets/client/components.js +99 -121
  155. package/dist/web/assets/client/i18n.js +136 -58
  156. package/dist/web/assets/client/view.js +44 -0
  157. package/dist/web/assets/styles/cards.js +3 -15
  158. package/dist/web/assets/styles/widgets.js +4 -0
  159. package/dist/web/webSnapshot.js +29 -14
  160. package/dist/workItem/dependencyGate.js +34 -0
  161. package/dist/workItem/workItem.js +99 -266
  162. package/dist/workspace/workItemChangeSetManager.js +15 -59
  163. package/docs/task-local-identity.md +1 -1
  164. package/i18n/README.zh-CN.md +165 -59
  165. package/package.json +1 -1
  166. package/skills/yui-leader/SKILL.md +272 -782
  167. package/skills/yui-operator/SKILL.md +190 -365
  168. package/skills/yui-reviewer/SKILL.md +40 -33
  169. package/skills/yui-runtime/SKILL.md +27 -6
  170. package/skills/yui-worker/SKILL.md +19 -6
  171. package/dist/execution/candidateConvergence.js +0 -623
  172. package/dist/execution/executionGroup.js +0 -854
  173. package/dist/execution/resourceBroker.js +0 -426
  174. package/dist/executor/launchPlan.js +0 -16
  175. package/dist/review/reviewFinding.js +0 -240
  176. package/dist/review/reviewFindingLedger.js +0 -550
  177. package/dist/review/reviewOutcomeClassifier.js +0 -255
  178. package/dist/scheduler/resourceQueueProjection.js +0 -71
  179. package/dist/task/repairWave.js +0 -150
@@ -239,7 +239,7 @@ function assertCallerAuthorized(store, caller, taskId) {
239
239
  || binding === undefined
240
240
  || agentId === undefined
241
241
  || caller.adapterId === undefined
242
- || caller.launchId === undefined
242
+ || caller.runtimeGenerationId === undefined
243
243
  || sessions === null
244
244
  || sessions.activeAgentId !== role.activeAgentId
245
245
  || session === null
@@ -247,7 +247,7 @@ function assertCallerAuthorized(store, caller, taskId) {
247
247
  || binding.adapterId !== caller.adapterId
248
248
  || session.agentId !== agentId
249
249
  || session.adapterId !== caller.adapterId
250
- || session.launchId !== caller.launchId
250
+ || session.runtimeGenerationId !== caller.runtimeGenerationId
251
251
  || (caller.nativeSessionId !== undefined
252
252
  && session.nativeSessionId !== caller.nativeSessionId)) {
253
253
  throw jobControlError("UNAUTHORIZED", "DurableJob control requires the current managed global Agent Session.");
@@ -257,11 +257,12 @@ function assertCallerAuthorized(store, caller, taskId) {
257
257
  if (caller.taskId !== taskId) {
258
258
  throw jobControlError("UNAUTHORIZED", "A managed Task Session may not start or cancel Jobs for a different Task.");
259
259
  }
260
- if (caller.turnId === undefined) {
261
- throw jobControlError("UNAUTHORIZED", "A managed Task Session must bind its request to a Turn.");
262
- }
263
- const run = store.getTurn(taskId, caller.turnId);
264
- if (run === null || run.status !== "active" || run.roleName !== caller.role) {
260
+ // The Turn is resolved from durable state rather than presented by the
261
+ // caller: a long-lived Session process cannot hold a current Turn in its
262
+ // frozen environment, and its own claim would add nothing the store does
263
+ // not already own.
264
+ const run = caller.role === undefined ? null : store.getActiveTurn(taskId, caller.role);
265
+ if (run === null || run.status !== "active") {
265
266
  throw jobControlError("UNAUTHORIZED", "A managed Task Session's Role is not bound to an active Turn.");
266
267
  }
267
268
  // rr13: Verify the non-replayable per-Session caller key. The key is injected
@@ -489,7 +490,7 @@ function parseCaller(value) {
489
490
  }
490
491
  const record = value;
491
492
  const allowed = new Set([
492
- "scope", "taskId", "role", "agentId", "adapterId", "launchId", "nativeSessionId",
493
+ "scope", "taskId", "role", "agentId", "adapterId", "runtimeGenerationId", "nativeSessionId",
493
494
  "turnId", "callerKey"
494
495
  ]);
495
496
  for (const key of Object.keys(record)) {
@@ -510,7 +511,7 @@ function parseCaller(value) {
510
511
  const role = optionalId("role");
511
512
  const agentId = optionalId("agentId");
512
513
  const adapterId = optionalId("adapterId");
513
- const launchId = optionalId("launchId");
514
+ const runtimeGenerationId = optionalId("runtimeGenerationId");
514
515
  const nativeSessionId = optionalId("nativeSessionId");
515
516
  const turnId = optionalId("turnId");
516
517
  const callerKey = record.callerKey === undefined
@@ -522,7 +523,7 @@ function parseCaller(value) {
522
523
  ...(role === undefined ? {} : { role }),
523
524
  ...(agentId === undefined ? {} : { agentId }),
524
525
  ...(adapterId === undefined ? {} : { adapterId }),
525
- ...(launchId === undefined ? {} : { launchId }),
526
+ ...(runtimeGenerationId === undefined ? {} : { runtimeGenerationId }),
526
527
  ...(nativeSessionId === undefined ? {} : { nativeSessionId }),
527
528
  ...(turnId === undefined ? {} : { turnId }),
528
529
  ...(callerKey === undefined ? {} : { callerKey })
@@ -36,7 +36,7 @@ export function createRuntimeResourceActivityTracker() {
36
36
  identity.agentId,
37
37
  identity.adapterId,
38
38
  identity.nativeSessionId ?? null,
39
- identity.launchId ?? null
39
+ identity.runtimeGenerationId ?? null
40
40
  ]);
41
41
  const current = {
42
42
  identity: identityKey,
@@ -261,7 +261,7 @@ function roleOwner(role) {
261
261
  agentId: role.agentId,
262
262
  ...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
263
263
  ...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
264
- ...(role.launchId === undefined ? {} : { launchId: role.launchId }),
264
+ ...(role.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: role.runtimeGenerationId }),
265
265
  ...(role.turnId === undefined ? {} : { turnId: role.turnId })
266
266
  };
267
267
  }
@@ -274,7 +274,7 @@ function roleOwner(role) {
274
274
  agentId: role.agentId,
275
275
  ...(role.adapterId === undefined ? {} : { adapterId: role.adapterId }),
276
276
  ...(role.nativeSessionId === undefined ? {} : { nativeSessionId: role.nativeSessionId }),
277
- ...(role.launchId === undefined ? {} : { launchId: role.launchId }),
277
+ ...(role.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: role.runtimeGenerationId }),
278
278
  ...(role.turnId === undefined ? {} : { turnId: role.turnId })
279
279
  };
280
280
  }
@@ -444,7 +444,7 @@ function matchesResourceIdentity(identity, owner) {
444
444
  || typeof identity.adapterId !== "string"
445
445
  || identity.adapterId.length === 0
446
446
  || (identity.nativeSessionId !== undefined && !hasIdentityText(identity.nativeSessionId))
447
- || (identity.launchId !== undefined && !hasIdentityText(identity.launchId)))
447
+ || (identity.runtimeGenerationId !== undefined && !hasIdentityText(identity.runtimeGenerationId)))
448
448
  return false;
449
449
  if (owner.kind !== "task-role"
450
450
  || owner.taskId !== identity.taskId
@@ -453,12 +453,12 @@ function matchesResourceIdentity(identity, owner) {
453
453
  || owner.agentId !== identity.agentId
454
454
  || owner.adapterId !== identity.adapterId)
455
455
  return false;
456
- if (!hasIdentityText(identity.nativeSessionId) && !hasIdentityText(identity.launchId))
456
+ if (!hasIdentityText(identity.nativeSessionId) && !hasIdentityText(identity.runtimeGenerationId))
457
457
  return false;
458
458
  if (identity.nativeSessionId !== undefined
459
459
  && owner.nativeSessionId !== identity.nativeSessionId)
460
460
  return false;
461
- if (identity.launchId !== undefined && owner.launchId !== identity.launchId)
461
+ if (identity.runtimeGenerationId !== undefined && owner.runtimeGenerationId !== identity.runtimeGenerationId)
462
462
  return false;
463
463
  return true;
464
464
  }
@@ -634,7 +634,7 @@ function loadHomeState(home, warnings, options) {
634
634
  agentId,
635
635
  ...(adapterId === undefined ? {} : { adapterId }),
636
636
  ...(session === null ? {} : { nativeSessionId: session.nativeSessionId }),
637
- ...(session?.launchId === undefined ? {} : { launchId: session.launchId })
637
+ ...(session?.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId })
638
638
  };
639
639
  });
640
640
  const appendTaskRole = (task, role) => {
@@ -652,7 +652,7 @@ function loadHomeState(home, warnings, options) {
652
652
  agentId,
653
653
  ...(adapterId === undefined ? {} : { adapterId }),
654
654
  ...(session === null ? {} : { nativeSessionId: session.nativeSessionId }),
655
- ...(session?.launchId === undefined ? {} : { launchId: session.launchId }),
655
+ ...(session?.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: session.runtimeGenerationId }),
656
656
  ...(run === null ? {} : { turnId: run.id })
657
657
  });
658
658
  };
@@ -25,7 +25,7 @@ import { createFileArtifactPort, createLinuxProcessPort, DurableJobSupervisor }
25
25
  import { createDurableJobControl } from "./jobControl.js";
26
26
  import { FileRuntimeEventInbox } from "./runtimeEventInbox.js";
27
27
  import { AgentRuntimeObserver } from "./agentRuntimeObserver.js";
28
- import { AsyncRuntimeEventProcessor, FileRuntimeEventProcessor, createAsyncRuntimeObserver } from "./runtimeEventProcessor.js";
28
+ import { AsyncRuntimeEventProcessor, FileRuntimeEventProcessor, createAsyncRuntimeObserver, } from "./runtimeEventProcessor.js";
29
29
  import { RuntimeLaunchCoordinator } from "./runtimeLaunchCoordinator.js";
30
30
  import { ephemeralDomainFromEnvironment, recordEphemeralTmuxTarget } from "./domainIdentity.js";
31
31
  import { createEphemeralResourceReaper } from "./ephemeralResourceReaper.js";
@@ -41,41 +41,6 @@ import { appendGlobalProcessExitObservation } from "../runtime/globalProcessExit
41
41
  import { builtinAgentDriverRegistry } from "../runtime/builtinAgentDrivers.js";
42
42
  import { createRuntimeObservation, runtimeObservationFromTaskEvent } from "../runtime/runtimeObservation.js";
43
43
  import { createTaskEvent } from "../event/taskEvent.js";
44
- /** Refreshes only the exact Task runtime generation folded by the event transaction. */
45
- export function refreshAppliedTaskRuntimeDescriptor(store, planner, input) {
46
- if (input.launchId === undefined)
47
- return;
48
- const run = input.turnId === undefined
49
- ? null
50
- : store.getTurn(input.taskId, input.turnId);
51
- if (input.turnId !== undefined && run === null) {
52
- throw new Error("Prepared Task runtime generation is not current.");
53
- }
54
- // A terminal completion has already settled this exact Turn and no later
55
- // prompt can use its descriptor. Acknowledge the applied provider fact
56
- // without republishing a dead generation.
57
- if (run !== null && run.status !== "active")
58
- return;
59
- const session = store.getTaskRoleSessionSet(input.taskId, input.roleName)
60
- ?.sessions[input.agentId];
61
- const effective = run?.effective ?? session?.effective;
62
- if (effective === undefined
63
- || session === undefined
64
- || session.agentId !== input.agentId
65
- || session.adapterId !== input.adapterId
66
- || session.launchId !== input.launchId
67
- || session.nativeSessionId !== input.nativeSessionId
68
- || (run !== null && (run.roleName !== input.roleName
69
- || run.effective.agentId !== input.agentId
70
- || run.effective.adapterId !== input.adapterId))) {
71
- throw new Error("Prepared Task runtime generation is not current.");
72
- }
73
- planner.refreshTaskRuntimeDescriptor({
74
- ...input,
75
- launchId: input.launchId,
76
- workspace: effective.workspace.root
77
- });
78
- }
79
44
  /** Production composition root for the current SQLite TaskStore + tmux Controller. */
80
45
  export async function startFileTaskControllerRuntime(home, options = {}) {
81
46
  // The current Home always uses SQLite. The persistence worker is enabled by
@@ -159,7 +124,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
159
124
  while (!signal.aborted) {
160
125
  const session = schedulerStore.getRoleSession(owner.taskId, owner.roleName, request.agentId);
161
126
  if (session !== null
162
- && session.launchId === request.launchId
127
+ && session.runtimeGenerationId === request.runtimeGenerationId
163
128
  && typeof session.nativeSessionId === "string"
164
129
  && session.nativeSessionId.trim().length > 0) {
165
130
  return session.nativeSessionId;
@@ -170,7 +135,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
170
135
  && event.observation.fence.taskId === owner.taskId
171
136
  && event.observation.fence.roleName === owner.roleName
172
137
  && event.observation.fence.agentId === request.agentId
173
- && event.observation.fence.launchId === request.launchId
138
+ && event.observation.fence.runtimeGenerationId === request.runtimeGenerationId
174
139
  && typeof event.observation.fence.nativeSessionId === "string"
175
140
  && event.observation.fence.nativeSessionId.trim().length > 0) {
176
141
  return event.observation.fence.nativeSessionId;
@@ -186,7 +151,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
186
151
  owner: binding.owner,
187
152
  agentId: binding.agentId,
188
153
  adapterId: binding.adapterId,
189
- launchId: binding.launchId,
154
+ runtimeGenerationId: binding.runtimeGenerationId,
190
155
  ...(binding.nativeSessionId === undefined
191
156
  ? {}
192
157
  : { nativeSessionId: binding.nativeSessionId }),
@@ -222,7 +187,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
222
187
  return sessionOwners.terminateOwner(owner).then((result) => {
223
188
  if (result.outcome === "stop-blocked") {
224
189
  (options.onError ?? (() => undefined))(new Error(`Role runtime cleanup could not prove physical exit: ${result.remaining
225
- .map(({ record, detail }) => `${record.launchId}: ${detail}`)
190
+ .map(({ record, detail }) => `${record.runtimeGenerationId}: ${detail}`)
226
191
  .join("; ")}`));
227
192
  }
228
193
  return result.outcome === "stop-confirmed";
@@ -294,9 +259,9 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
294
259
  return [];
295
260
  const identity = owner.turnId === undefined
296
261
  || owner.adapterId === undefined
297
- || (owner.nativeSessionId === undefined && owner.launchId === undefined)
262
+ || (owner.nativeSessionId === undefined && owner.runtimeGenerationId === undefined)
298
263
  || (owner.nativeSessionId !== undefined && owner.nativeSessionId.trim().length === 0)
299
- || (owner.launchId !== undefined && owner.launchId.trim().length === 0)
264
+ || (owner.runtimeGenerationId !== undefined && owner.runtimeGenerationId.trim().length === 0)
300
265
  ? undefined
301
266
  : {
302
267
  taskId: owner.taskId,
@@ -307,7 +272,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
307
272
  ...(owner.nativeSessionId === undefined
308
273
  ? {}
309
274
  : { nativeSessionId: owner.nativeSessionId }),
310
- ...(owner.launchId === undefined ? {} : { launchId: owner.launchId })
275
+ ...(owner.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: owner.runtimeGenerationId })
311
276
  };
312
277
  const changed = !active || input.turnId === undefined
313
278
  ? false
@@ -320,7 +285,7 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
320
285
  ...(input.nativeSessionId === undefined
321
286
  ? {}
322
287
  : { nativeSessionId: input.nativeSessionId }),
323
- ...(input.launchId === undefined ? {} : { launchId: input.launchId })
288
+ ...(input.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: input.runtimeGenerationId })
324
289
  }, resource);
325
290
  return [{
326
291
  taskId: owner.taskId,
@@ -464,16 +429,8 @@ export async function startFileTaskControllerRuntime(home, options = {}) {
464
429
  workspacePreparer,
465
430
  runtimeEventProcessor: options.runtimeEventProcessor
466
431
  ?? (useWorker && asyncStoreClient !== undefined
467
- ? new AsyncRuntimeEventProcessor(runtimeEventInbox, createAsyncRuntimeObserver((method, args) => asyncStoreClient.invokeObserver(method, args)), {
468
- onTaskRuntimeApplied: (input) => {
469
- refreshAppliedTaskRuntimeDescriptor(store, planner, input);
470
- }
471
- })
472
- : new FileRuntimeEventProcessor(runtimeEventInbox, schedulerStore, {
473
- onTaskRuntimeApplied: (input) => {
474
- refreshAppliedTaskRuntimeDescriptor(store, planner, input);
475
- }
476
- })),
432
+ ? new AsyncRuntimeEventProcessor(runtimeEventInbox, createAsyncRuntimeObserver((method, args) => asyncStoreClient.invokeObserver(method, args)))
433
+ : new FileRuntimeEventProcessor(runtimeEventInbox, schedulerStore)),
477
434
  runtimeObserver: options.runtimeObserver
478
435
  ?? new AgentRuntimeObserver(store, runtimeEventInbox),
479
436
  domainIdentity,
@@ -567,7 +524,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
567
524
  roleName: value.roleName,
568
525
  ...(value.turnId === undefined ? {} : { turnId: value.turnId }),
569
526
  agentId: value.agentId,
570
- launchId: value.launchId,
527
+ runtimeGenerationId: value.runtimeGenerationId,
571
528
  nativeSessionId: value.nativeSessionId,
572
529
  attemptId: value.attemptId,
573
530
  authorityEpoch: value.authorityEpoch,
@@ -634,7 +591,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
634
591
  const runtime = runtimeObservationFromTaskEvent(event);
635
592
  return runtime !== null
636
593
  && runtime.fence.turnId === observation.turnId
637
- && runtime.fence.launchId === observation.launchId
594
+ && runtime.fence.runtimeGenerationId === observation.runtimeGenerationId
638
595
  && runtime.kind === "turn.failed"
639
596
  && Date.parse(runtime.receivedAt) <= Date.parse(observation.observedAt);
640
597
  });
@@ -661,7 +618,7 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
661
618
  observationId: observation.observationId,
662
619
  processKind: observation.processKind,
663
620
  roleName: observation.roleName,
664
- launchId: observation.launchId,
621
+ runtimeGenerationId: observation.runtimeGenerationId,
665
622
  observedAt: observation.observedAt,
666
623
  classification,
667
624
  observation: JSON.stringify(observation)
@@ -674,16 +631,16 @@ export function createRuntimeLifecycleDispatcher(store, schedulerStore, sessionH
674
631
  if (params === null || typeof params !== "object" || Array.isArray(params)) {
675
632
  throw applicationError("INVALID_PARAMS", "Launch redemption params are invalid.");
676
633
  }
677
- const launchId = params.launchId;
634
+ const runtimeGenerationId = params.runtimeGenerationId;
678
635
  const ticket = params.ticket;
679
636
  const hostPid = params.hostPid;
680
- if (typeof launchId !== "string" || typeof ticket !== "string"
637
+ if (typeof runtimeGenerationId !== "string" || typeof ticket !== "string"
681
638
  || !Number.isSafeInteger(hostPid) || hostPid <= 0) {
682
639
  throw applicationError("INVALID_PARAMS", "Launch redemption identity is invalid.");
683
640
  }
684
641
  // The launch payload is validated at reservation time and every member
685
642
  // of its discriminated Provider-control union is JSON serializable.
686
- return launchBrokerForHome(store.rootDirectory()).redeem(launchId, ticket);
643
+ return launchBrokerForHome(store.rootDirectory()).redeem(runtimeGenerationId, ticket);
687
644
  }
688
645
  if (method === "runtime.replace-agent-environment") {
689
646
  if (environmentRefresher === undefined) {
@@ -1124,7 +1081,7 @@ function providerTurnControlParams(params) {
1124
1081
  roleName: requiredParam(value.roleName),
1125
1082
  ...(value.turnId === undefined ? {} : { turnId: requiredParam(value.turnId) }),
1126
1083
  agentId: requiredParam(value.agentId),
1127
- launchId: requiredParam(value.launchId),
1084
+ runtimeGenerationId: requiredParam(value.runtimeGenerationId),
1128
1085
  nativeSessionId: requiredParam(value.nativeSessionId),
1129
1086
  attemptId: requiredParam(value.attemptId),
1130
1087
  authorityEpoch: authorityEpoch,
@@ -2,7 +2,7 @@ import { createHash, randomUUID } from "node:crypto";
2
2
  import { closeSync, constants, existsSync, fchmodSync, fsyncSync, linkSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, rmSync, unlinkSync, writeFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { createRuntimeObservation, isRuntimeTokenEvidence } from "../runtime/runtimeObservation.js";
5
- export const MAX_RUNTIME_TURN_SUMMARY_BYTES = 32 * 1024;
5
+ import { boundedTurnFailureDiagnostic, transportAgentResult } from "../domain/agentResultTransport.js";
6
6
  export const MAX_RUNTIME_EVENT_FILE_BYTES = 16 * 1024 * 1024;
7
7
  const RUNTIME_EVENT_DIRECTORY = join("runtime", "inbox");
8
8
  const INVALID_RUNTIME_EVENT_DIRECTORY = join("runtime", "inbox-invalid");
@@ -39,12 +39,12 @@ export class FileRuntimeEventInbox {
39
39
  });
40
40
  return this.publish(event);
41
41
  }
42
- enqueueTurnCompleted(input) {
43
- const normalized = normalizeNativeTurnCompletedInput(input);
42
+ enqueueTurnTerminal(input) {
43
+ const normalized = normalizeNativeTurnTerminalInput(input);
44
44
  return this.publish(Object.freeze({
45
45
  schemaVersion: 1,
46
- id: runtimeEventId("native-turn-completed", normalized),
47
- type: "native-turn-completed",
46
+ id: runtimeEventId("native-turn-terminal", normalized),
47
+ type: "native-turn-terminal",
48
48
  receivedAt: this.now().toISOString(),
49
49
  ...normalized
50
50
  }));
@@ -275,27 +275,31 @@ function runtimeEventId(type, input) {
275
275
  provider.roleName,
276
276
  provider.agentId,
277
277
  provider.adapterId,
278
- provider.launchId ?? null,
278
+ provider.runtimeGenerationId ?? null,
279
279
  provider.nativeSessionId,
280
280
  provider.nativeTurnId,
281
281
  provider.turnId ?? null
282
282
  ];
283
283
  return `turn-${createHash("sha256").update(JSON.stringify(common)).digest("hex")}`;
284
284
  }
285
- function normalizeNativeTurnCompletedInput(input) {
285
+ function normalizeNativeTurnTerminalInput(input) {
286
286
  const scope = input.scope;
287
287
  if (scope !== "task" && scope !== "global")
288
288
  throw invalidEvent();
289
- if (typeof input.summary !== "string" || input.summary.includes("\0"))
289
+ if (!["completed", "failed", "cancelled"].includes(input.providerStatus))
290
290
  throw invalidEvent();
291
+ const outcome = normalizeRuntimeTurnTerminalOutcome(input.outcome);
292
+ if (outcome.status === "completed" && input.providerStatus !== "completed") {
293
+ throw invalidEvent("Only a completed Provider Turn may carry a completed Agent result.");
294
+ }
291
295
  const common = {
292
296
  scope,
293
297
  roleName: requireIdentityText(input.roleName, "Role name"),
294
298
  agentId: requireIdentityText(input.agentId, "Agent id"),
295
299
  adapterId: input.adapterId,
296
- ...(input.launchId === undefined
300
+ ...(input.runtimeGenerationId === undefined
297
301
  ? {}
298
- : { launchId: requireIdentityText(input.launchId, "Launch id") }),
302
+ : { runtimeGenerationId: requireIdentityText(input.runtimeGenerationId, "Runtime generation id") }),
299
303
  nativeSessionId: requireIdentityText(input.nativeSessionId, "Native session id"),
300
304
  nativeTurnId: requireIdentityText(input.nativeTurnId, "Provider native Turn id"),
301
305
  ...(input.turnId === undefined
@@ -304,15 +308,41 @@ function normalizeNativeTurnCompletedInput(input) {
304
308
  ...(input.title === undefined
305
309
  ? {}
306
310
  : { title: requireIdentityText(input.title, "Session title") }),
307
- summary: truncateUtf8(input.summary.trim(), MAX_RUNTIME_TURN_SUMMARY_BYTES)
311
+ providerStatus: input.providerStatus,
312
+ outcome
308
313
  };
309
- if ((common.adapterId !== "codex" && common.adapterId !== "claude")
310
- || common.summary.length === 0)
314
+ if (common.adapterId !== "codex" && common.adapterId !== "claude")
311
315
  throw invalidEvent();
312
316
  return scope === "task"
313
317
  ? { ...common, taskId: requireIdentityText(input.taskId, "Task id") }
314
318
  : common;
315
319
  }
320
+ function normalizeRuntimeTurnTerminalOutcome(input) {
321
+ if (!isObject(input)) {
322
+ throw invalidEvent("Runtime Turn terminal outcome is invalid.");
323
+ }
324
+ if (input.status === "completed")
325
+ return transportAgentResult(input.output);
326
+ if (input.status !== "failed"
327
+ || ![
328
+ "startup-failed",
329
+ "runtime-failed",
330
+ "delivery-unknown",
331
+ "missing-result",
332
+ "workspace-unavailable",
333
+ "workspace-dirty",
334
+ "workspace-branch-mismatch",
335
+ "cancelled"
336
+ ]
337
+ .includes(input.failureReason)) {
338
+ throw invalidEvent("Runtime Turn failure outcome is invalid.");
339
+ }
340
+ return {
341
+ status: "failed",
342
+ diagnostic: boundedTurnFailureDiagnostic(input.diagnostic),
343
+ failureReason: input.failureReason
344
+ };
345
+ }
316
346
  function normalizeDurableJobTerminalInput(input) {
317
347
  if (input.scope !== "task")
318
348
  throw invalidEvent();
@@ -335,7 +365,7 @@ function parseRuntimeEvent(value) {
335
365
  throw invalidEvent();
336
366
  switch (value.type) {
337
367
  case "runtime-observation": return parseRuntimeObservationEvent(value);
338
- case "native-turn-completed": return parseNativeTurnCompletedEvent(value);
368
+ case "native-turn-terminal": return parseNativeTurnTerminalEvent(value);
339
369
  case "durable-job-terminal": return parseDurableJobTerminalEvent(value);
340
370
  default: throw invalidEvent();
341
371
  }
@@ -380,20 +410,22 @@ function parseDurableJobTerminalEvent(value) {
380
410
  ...normalized
381
411
  });
382
412
  }
383
- function parseNativeTurnCompletedEvent(value) {
413
+ function parseNativeTurnTerminalEvent(value) {
384
414
  const scope = value.scope;
385
415
  const expected = scope === "task"
386
416
  ? [
387
417
  "schemaVersion", "id", "type", "receivedAt", "scope", "taskId",
388
- "roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId", "summary",
389
- ...(value.launchId === undefined ? [] : ["launchId"]),
418
+ "roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId",
419
+ "providerStatus", "outcome",
420
+ ...(value.runtimeGenerationId === undefined ? [] : ["runtimeGenerationId"]),
390
421
  ...(value.turnId === undefined ? [] : ["turnId"]),
391
422
  ...(value.title === undefined ? [] : ["title"])
392
423
  ]
393
424
  : [
394
425
  "schemaVersion", "id", "type", "receivedAt", "scope",
395
- "roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId", "summary",
396
- ...(value.launchId === undefined ? [] : ["launchId"]),
426
+ "roleName", "agentId", "adapterId", "nativeSessionId", "nativeTurnId",
427
+ "providerStatus", "outcome",
428
+ ...(value.runtimeGenerationId === undefined ? [] : ["runtimeGenerationId"]),
397
429
  ...(value.turnId === undefined ? [] : ["turnId"]),
398
430
  ...(value.title === undefined ? [] : ["title"])
399
431
  ];
@@ -402,23 +434,24 @@ function parseNativeTurnCompletedEvent(value) {
402
434
  || !hasExactKeys(value, expected))
403
435
  throw invalidEvent();
404
436
  const receivedAt = requireTimestamp(value.receivedAt);
405
- const normalized = normalizeNativeTurnCompletedInput({
437
+ const normalized = normalizeNativeTurnTerminalInput({
406
438
  scope,
407
439
  ...(scope === "task" ? { taskId: value.taskId } : {}),
408
440
  roleName: value.roleName,
409
441
  agentId: value.agentId,
410
442
  adapterId: value.adapterId,
411
- ...(value.launchId === undefined ? {} : { launchId: value.launchId }),
443
+ ...(value.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: value.runtimeGenerationId }),
412
444
  nativeSessionId: value.nativeSessionId,
413
445
  nativeTurnId: value.nativeTurnId,
414
446
  ...(value.turnId === undefined ? {} : { turnId: value.turnId }),
415
447
  ...(value.title === undefined ? {} : { title: value.title }),
416
- summary: value.summary
448
+ providerStatus: value.providerStatus,
449
+ outcome: value.outcome
417
450
  });
418
451
  return Object.freeze({
419
452
  schemaVersion: 1,
420
453
  id: requireIdentityText(value.id, "Event id"),
421
- type: "native-turn-completed",
454
+ type: "native-turn-terminal",
422
455
  receivedAt,
423
456
  ...normalized
424
457
  });
@@ -438,15 +471,6 @@ function requireTimestamp(value) {
438
471
  throw invalidEvent();
439
472
  return timestamp;
440
473
  }
441
- function truncateUtf8(value, maximumBytes) {
442
- const encoded = Buffer.from(value, "utf8");
443
- if (encoded.length <= maximumBytes)
444
- return value;
445
- let end = maximumBytes;
446
- while (end > 0 && (encoded[end] & 0b1100_0000) === 0b1000_0000)
447
- end -= 1;
448
- return encoded.subarray(0, end).toString("utf8");
449
- }
450
474
  function ensureInboxDirectory(directory) {
451
475
  mkdirSync(directory, { recursive: true, mode: 0o700 });
452
476
  }
@@ -471,12 +495,11 @@ function hasSameIdentity(left, right) {
471
495
  && (!("roleName" in left) || !("roleName" in right) || left.roleName === right.roleName)
472
496
  && (!("agentId" in left) || !("agentId" in right) || left.agentId === right.agentId)
473
497
  && (!("adapterId" in left) || !("adapterId" in right) || left.adapterId === right.adapterId)
474
- && (!("launchId" in left) || !("launchId" in right) || left.launchId === right.launchId)
498
+ && (!("runtimeGenerationId" in left) || !("runtimeGenerationId" in right) || left.runtimeGenerationId === right.runtimeGenerationId)
475
499
  && (!("nativeSessionId" in left)
476
500
  || !("nativeSessionId" in right)
477
501
  || left.nativeSessionId === right.nativeSessionId)
478
502
  && (!("turnId" in left) || !("turnId" in right) || left.turnId === right.turnId)
479
- && (!("turnId" in left) || !("turnId" in right) || left.turnId === right.turnId)
480
503
  && (!("jobId" in left) || !("jobId" in right) || left.jobId === right.jobId);
481
504
  }
482
505
  function compareRuntimeEvents(left, right) {