@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
@@ -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-completed") {
115
- outcome = this.applyNativeTurnCompleted(event, now);
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
- applyNativeTurnCompleted(event, now) {
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.launchId === undefined ? {} : { launchId: event.launchId }),
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
- summary: event.summary
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.classifyRuntimeTurnCompleted?.(input) ?? "apply";
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.observeRuntimeTurnCompleted(input, now);
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.launchId === undefined ? {} : { launchId: event.launchId }),
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
- summary: event.summary
211
+ providerStatus: event.providerStatus,
212
+ outcome: event.outcome
250
213
  };
251
- if (this.observer.classifyGlobalRuntimeTurnCompleted?.(input) !== "obsolete") {
252
- this.observer.observeGlobalRuntimeTurnCompleted(input, now);
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
- launchId: fence.launchId,
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.launchId === undefined ? {} : { launchId: event.launchId }),
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.launchId,
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
- observeRuntimeTurnCompleted: (input, now) => withNow("observeRuntimeTurnCompleted", input, now),
531
- observeGlobalRuntimeTurnCompleted: (input, now) => withNow("observeGlobalRuntimeTurnCompleted", input, now),
532
- classifyRuntimeTurnCompleted: (input) => call("classifyRuntimeTurnCompleted", [input]),
533
- classifyGlobalRuntimeTurnCompleted: (input) => call("classifyGlobalRuntimeTurnCompleted", [input]),
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-completed") {
579
- outcome = await this.applyNativeTurnCompleted(event, now);
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 applyNativeTurnCompleted(event, now) {
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.launchId === undefined ? {} : { launchId: event.launchId }),
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
- summary: event.summary
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.classifyRuntimeTurnCompleted?.(input)) ?? "apply";
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.observeRuntimeTurnCompleted(input, now);
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.launchId === undefined ? {} : { launchId: event.launchId }),
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
- summary: event.summary
644
+ providerStatus: event.providerStatus,
645
+ outcome: event.outcome
706
646
  };
707
- if ((await this.observer.classifyGlobalRuntimeTurnCompleted?.(input)) !== "obsolete") {
708
- await this.observer.observeGlobalRuntimeTurnCompleted(input, now);
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
- launchId: fence.launchId,
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.launchId === undefined ? {} : { launchId: event.launchId }),
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
- * launch identity. The immutable event is revalidated by the inbox fold.
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.launchId !== launchId
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
- launchId,
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 = store.getWorkMailbox(runtimeLifecycleTarget({
103
- scope: "task",
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(runtime?.turnId
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, launchId, agentId, adapterId);
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(environment.YUI_TURN_ID ?? runtime?.turnId, "Turn id")
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
- let effectiveRuntime = runtime;
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.launchId !== effectiveLaunchId
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
- launchId: effectiveLaunchId,
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.launchId !== binding.fence.launchId
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.launchId !== binding.fence.launchId
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
  }