@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
@@ -3,7 +3,7 @@ import { GitIntegrationService } from "../integration/gitIntegrationService.js";
3
3
  import { createIntegrationAttempt } from "../integration/integrationAttempt.js";
4
4
  import { NodeGitWorkspace } from "../repository/gitWorkspace.js";
5
5
  import { publicationExternalKey } from "../task/publicationReference.js";
6
- import { isAcceptedTaskReviewBaseline } from "../review/reviewAcceptance.js";
6
+ import { isCompletedTaskReviewEvidence } from "../review/reviewAcceptance.js";
7
7
  import { workspaceProjectEntry } from "../worktree/managedWorkspace.js";
8
8
  /**
9
9
  * Verify the one supported ancestry waiver before `task complete` mutates any
@@ -113,7 +113,7 @@ export function assertTaskCompletionPublishedTreeProof(store, task, publicationI
113
113
  if (proof.reviewRoundId !== undefined) {
114
114
  const review = store.getReviewRound(task.id, proof.reviewRoundId);
115
115
  if (review === null
116
- || !isAcceptedTaskReviewBaseline(store, review)
116
+ || !isCompletedTaskReviewEvidence(store, review)
117
117
  || review.taskCandidate === undefined
118
118
  || !sameTaskCandidate(review.taskCandidate, actualCandidate)) {
119
119
  throw usageError(`Task-final Review evidence changed before published-tree completion: ${task.id}.`);
@@ -142,7 +142,7 @@ function requireCurrentVerifiedPublication(store, taskId, publicationId) {
142
142
  }
143
143
  function acceptedTaskFinalReviews(store, taskId) {
144
144
  return store.listReviewRounds(taskId)
145
- .filter((round) => isAcceptedTaskReviewBaseline(store, round))
145
+ .filter((round) => isCompletedTaskReviewEvidence(store, round))
146
146
  .sort((left, right) => (right.id.localeCompare(left.id, undefined, { numeric: true })));
147
147
  }
148
148
  function sameTaskCandidate(left, right) {
@@ -154,35 +154,22 @@ function sameTaskCandidate(left, right) {
154
154
  * Reconcile configured remote baselines before a Task completion attempt.
155
155
  *
156
156
  * Remote resolution and fetches happen from the Task's managed worktree. A
157
- * moved remote is represented by a new Integration Attempt that reuses the
158
- * already integrated ChangeSets, runs the existing Project checks, and lets
159
- * the normal target CAS advance the Task branch. Stable Project checkouts
160
- * are never refreshed or otherwise mutated here.
157
+ * moved remote is represented by a normal upstream Integration Attempt. The
158
+ * normal check and CAS path advances only the Task clone; stable Project
159
+ * checkouts are never refreshed or otherwise mutated here.
161
160
  */
162
161
  export async function reconcileTaskRemoteBaselines(taskId, store, home, options = {}) {
163
162
  const task = store.getTask(taskId);
164
163
  if (task === null)
165
164
  throw usageError(`Task not found: ${taskId}.`);
166
- // The delivery contract opts Project-backed Tasks into committed
167
- // Integration evidence. Metadata-only Tasks retain their existing local
168
- // completion semantics and have no remote baseline to reconcile here.
169
- if (task.projectBindings.length === 0
170
- || !store.listIntegrationAttempts(task.id).some(({ status }) => status === "committed")) {
165
+ if (task.projectBindings.length === 0) {
171
166
  return [];
172
167
  }
173
168
  const workspace = requireTaskWorkspace(store, task);
174
169
  const git = options.git ?? new NodeGitWorkspace();
175
- if (git.fetchRemoteHeadIntoWorktree === undefined
176
- || git.mergeRemoteIntoWorktree === undefined) {
170
+ if (git.fetchRemoteHeadIntoWorktree === undefined) {
177
171
  throw usageError(`Task ${task.id} cannot verify remote baselines: managed Git workspace support is unavailable.`);
178
172
  }
179
- // A completed Task-final Review that exactly covers the current frozen heads
180
- // is the final review evidence. Do not reconcile the remote after a clean
181
- // review, as merging a moved remote would change the reviewed head and
182
- // invalidate the review.
183
- if (await hasCompletedTaskFinalReviewForCurrentCandidate(store, task, workspace, git)) {
184
- return [];
185
- }
186
173
  const plans = [];
187
174
  for (const binding of task.projectBindings) {
188
175
  const project = store.getProject(binding.projectId);
@@ -196,69 +183,47 @@ export async function reconcileTaskRemoteBaselines(taskId, store, home, options
196
183
  throw usageError(`Task ${task.id} has no writable managed main workspace for remote Project ${project.id}.`);
197
184
  }
198
185
  const currentCommit = (await git.inspect(entry.path, "HEAD")).baseCommit;
199
- const previousIntegration = latestCommittedIntegration(store, task.id, project.id);
200
- // A completed Task-final Review for the exact current head freezes the
201
- // Task baseline: the delivery has been reviewed and approved, so the
202
- // completion gate must not merge remote changes that would invalidate
203
- // the review evidence.
204
- if (hasFrozenTaskBaseline(store, task.id, project.id, currentCommit)) {
205
- continue;
206
- }
207
- // Let the existing exact-head Task-final gate report local post-
208
- // Integration drift before attempting any network operation. This keeps
209
- // completion read-only for an already-invalid candidate and preserves its
210
- // precise recovery guidance.
211
- if (previousIntegration !== undefined
212
- && previousIntegration.candidateCommit !== currentCommit) {
213
- continue;
186
+ if (binding.currentCommit !== currentCommit || binding.baseCommit === undefined) {
187
+ throw usageError(`Project ${project.id} Task commit record does not match its authoritative main clone.`);
214
188
  }
215
189
  const remote = await fetchRemote(git, entry, project);
216
190
  if (remote.commit === currentCommit)
217
191
  continue;
218
192
  if (await git.isAncestor(entry.path, remote.commit, currentCommit))
219
193
  continue;
220
- if (previousIntegration === undefined) {
221
- throw usageError(`Project ${project.id} remote target moved to ${remote.commit}, but no committed `
222
- + "Integration can establish a safe Task baseline.");
223
- }
224
- if (previousIntegration.candidateCommit !== currentCommit) {
225
- throw usageError(`Project ${project.id} Task head ${currentCommit} does not match its latest committed `
226
- + `Integration ${previousIntegration.id}; settle that drift before remote reconciliation.`);
227
- }
228
194
  if (!await git.isClean(entry.path)) {
229
195
  throw usageError(`Project ${project.id} managed Task workspace is dirty; commit or clean it before remote reconciliation.`);
230
196
  }
231
- plans.push({ project, entry, remote, currentCommit, previousIntegration });
197
+ plans.push({
198
+ project,
199
+ entry,
200
+ remote,
201
+ currentCommit,
202
+ taskBaseCommit: binding.baseCommit
203
+ });
232
204
  }
233
205
  const reconciled = [];
234
206
  for (const plan of plans) {
235
207
  const attempt = store.transaction((tx) => {
236
- // Re-check the frozen baseline inside the transaction: a Task-final
237
- // Review may have completed during the async remote fetch, freezing
238
- // the head after the initial check. Creating a new Integration here
239
- // would move the reviewed head and invalidate the review evidence.
240
- if (hasFrozenTaskBaseline(tx, task.id, plan.project.id, plan.currentCommit)) {
241
- return null;
242
- }
243
208
  const created = createIntegrationAttempt({
244
209
  id: tx.nextIntegrationAttemptId(task.id),
245
210
  taskId: task.id,
246
211
  projectId: plan.project.id,
247
212
  targetRef: plan.entry.branch,
248
- expectedHead: plan.currentCommit,
249
- changeSetIds: plan.previousIntegration.changeSetIds,
250
- checkCommands: plan.previousIntegration.checkCommands
213
+ beforeCommit: plan.currentCommit,
214
+ source: {
215
+ kind: "upstream",
216
+ branch: plan.remote.branch,
217
+ remoteCommit: plan.remote.commit,
218
+ taskBaseCommit: plan.taskBaseCommit,
219
+ strategy: "rebase"
220
+ },
221
+ checkCommands: []
251
222
  }, options.now?.() ?? new Date());
252
223
  tx.saveIntegrationAttempt(task.id, created);
253
224
  return created;
254
225
  });
255
- if (attempt === null)
256
- continue;
257
- const baseline = {
258
- remoteUrl: plan.project.remoteUrl,
259
- branch: plan.remote.branch
260
- };
261
- const result = await new GitIntegrationService(home, store, git, options.now ?? (() => new Date()), options.environment, undefined, options.jobPort).integrate(task.id, attempt.id, { remoteBaseline: baseline });
226
+ const result = await new GitIntegrationService(home, store, git, options.now ?? (() => new Date()), options.environment, undefined, options.jobPort).integrate(task.id, attempt.id);
262
227
  // rr6/f3: A moved remote with non-empty checks spawns a DurableJob. This
263
228
  // is a pending completion outcome, not a failure: name the exact
264
229
  // Integration and Job and the exact continuation command (mirroring the
@@ -307,44 +272,3 @@ function requireTaskWorkspace(store, task) {
307
272
  }
308
273
  return workspace;
309
274
  }
310
- /**
311
- * Check whether an accepted Task-final ReviewRound is completed and its
312
- * immutable candidate exactly matches the current actual heads for every
313
- * Project in the Task. When this holds, the reviewed head is the final
314
- * head and remote reconciliation must not change it.
315
- */
316
- async function hasCompletedTaskFinalReviewForCurrentCandidate(store, task, workspace, git) {
317
- const actualProjects = [];
318
- for (const binding of task.projectBindings) {
319
- const entry = workspaceProjectEntry(workspace, binding.projectId);
320
- if (entry === undefined || entry.access !== "write")
321
- return false;
322
- const actualHead = (await git.inspect(entry.path, "HEAD")).baseCommit;
323
- actualProjects.push({ projectId: binding.projectId, commit: actualHead });
324
- }
325
- const actualCandidate = {
326
- schemaVersion: 1,
327
- projects: actualProjects
328
- };
329
- return acceptedTaskFinalReviews(store, task.id).some((round) => (round.taskCandidate !== undefined
330
- && sameTaskCandidate(round.taskCandidate, actualCandidate)));
331
- }
332
- function latestCommittedIntegration(store, taskId, projectId) {
333
- return store.listIntegrationAttempts(taskId)
334
- .filter((attempt) => attempt.projectId === projectId && attempt.status === "committed")
335
- .sort((left, right) => left.id.localeCompare(right.id, undefined, { numeric: true }))
336
- .at(-1);
337
- }
338
- /**
339
- * A Task baseline is frozen when a completed (clean) Task-final ReviewRound
340
- * reviewed the exact current head for the given Project. Once frozen, the
341
- * completion gate skips remote baseline reconciliation to prevent merging
342
- * unreviewed remote changes into the approved delivery.
343
- */
344
- function hasFrozenTaskBaseline(store, taskId, projectId, currentCommit) {
345
- return store.listReviewRounds(taskId)
346
- .some((round) => ((round.scope ?? "work-item") === "task"
347
- && isAcceptedTaskReviewBaseline(store, round)
348
- && round.taskCandidate !== undefined
349
- && round.taskCandidate.projects.some((entry) => (entry.projectId === projectId && entry.commit === currentCommit))));
350
- }
@@ -4,10 +4,10 @@ import { formatTimestamp } from "../output/timePresentation.js";
4
4
  import { isRoleTurnStalled, latestStallProgressAt } from "../scheduler/roleTurnStall.js";
5
5
  import { buildTaskExecutionProjection } from "../scheduler/taskExecutionProjection.js";
6
6
  import { projectNextAction } from "../task/nextAction.js";
7
- import { summarizeExecutionGroup } from "../execution/executionGroup.js";
8
- import { currentWorkItemExecutionGroup } from "../workItem/workItem.js";
7
+ import { projectWorkItemExecution } from "../execution/workItemExecutionProjection.js";
9
8
  import { operationalTaskRecords } from "../task/taskRecordRetirement.js";
10
9
  import { projectReviewDecision } from "../review/reviewDecision.js";
10
+ import { projectTaskRemoteDeliveryFromStore, renderTaskRemoteDelivery } from "./taskRemoteDeliveryCommand.js";
11
11
  const RECENT_RECORD_LIMIT = 5;
12
12
  const RELATED_RECORD_LIMIT = 5;
13
13
  const SUMMARY_TEXT_LIMIT = 400;
@@ -49,6 +49,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
49
49
  const changeSets = chronological(reader.listChangeSets(task.id));
50
50
  const integrations = chronological(reader.listIntegrationAttempts(task.id));
51
51
  const publications = chronological(reader.listPublicationReferences(task.id));
52
+ const remoteDelivery = projectTaskRemoteDeliveryFromStore(reader, task, currentTaskReviewCandidate);
52
53
  const nextActionFacts = reader.readNextActionFacts(task.id);
53
54
  if (nextActionFacts === null) {
54
55
  throw new Error(`Task next-action facts disappeared: ${task.id}.`);
@@ -80,6 +81,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
80
81
  changeSets,
81
82
  integrations,
82
83
  publications,
84
+ remoteDelivery,
83
85
  messages: operationalTaskRecords(reader.listMessages(task.id), events, "message"),
84
86
  openInputRequests: inputRequests.filter((request) => request.status === "open"),
85
87
  resolvedInputRequests: inputRequests.filter((request) => request.status !== "open"),
@@ -91,10 +93,11 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
91
93
  })
92
94
  };
93
95
  });
94
- const { task, execution, reviewConfig, reviewDecision, brief, activeDecisions, milestones, roles, managedWorkspaces, roleSessionSets, coordinationMailboxes, workItems, turns, reviewRounds, changeSets, integrations, publications, messages, openInputRequests, resolvedInputRequests, events, nextAction } = data;
96
+ const { task, execution, reviewConfig, reviewDecision, brief, activeDecisions, milestones, roles, managedWorkspaces, roleSessionSets, coordinationMailboxes, workItems, turns, reviewRounds, changeSets, integrations, publications, remoteDelivery, messages, openInputRequests, resolvedInputRequests, events, nextAction } = data;
95
97
  const timeZone = store.getConfig().timeZone;
96
98
  const displayedActiveDecisions = activeDecisions.slice(-RECENT_RECORD_LIMIT);
97
99
  const displayedWorkItems = currentAndRecentWorkItems(workItems);
100
+ const currentWorkItems = workItems.filter(({ status }) => status !== "retired");
98
101
  const displayedOpenInputRequests = openInputRequests.slice(-RECENT_RECORD_LIMIT);
99
102
  const displayedResolvedInputRequests = resolvedInputRequests.slice(-RECENT_RECORD_LIMIT);
100
103
  const displayedActiveTurns = execution.activeTurns;
@@ -132,6 +135,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
132
135
  ...(task.retirementSummary === undefined ? [] : [`Retirement summary: ${task.retirementSummary}`]),
133
136
  ...(task.replacementTaskId === undefined ? [] : [`Replacement Task: ${task.replacementTaskId}`]),
134
137
  ...(task.archiveSummary === undefined ? [] : [`Archive summary: ${task.archiveSummary}`]),
138
+ renderTaskRemoteDelivery(remoteDelivery).trimEnd(),
135
139
  "Execution:",
136
140
  ` Status: ${execution.status}`,
137
141
  ` Owner/action: ${execution.owner}/${execution.action}`,
@@ -173,12 +177,12 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
173
177
  ? [" None."]
174
178
  : managedWorkspaces.map((workspace) => (` ${managedWorkspaceLabel(workspace)}: ${workspace.root} (${workspace.entries.filter(({ access }) => access === "write").length} writable / ${workspace.entries.length} Projects)`))),
175
179
  `Type: ${task.type ?? "unspecified"}`,
176
- `Execution topology: ${workItems.length === 0
180
+ `Execution topology: ${currentWorkItems.length === 0
177
181
  ? "Leader-owned Task main"
178
- : `${workItems.length} independently owned WorkItem(s), integrated on Task main`}`,
182
+ : `${currentWorkItems.length} independently owned WorkItem(s), integrated on Task main`}`,
179
183
  `Completion evidence: ${task.projectBindings.length === 0
180
184
  ? "no Project evidence required"
181
- : workItems.length === 0
185
+ : currentWorkItems.length === 0
182
186
  ? "clean committed Task main required"
183
187
  : "each delivered WorkItem requires a ChangeSet and committed Integration"}`,
184
188
  `Global review: ${reviewConfig === null
@@ -285,9 +289,7 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
285
289
  ...(observability.workItems.find(({ workItemId }) => workItemId === item.id) === undefined
286
290
  ? []
287
291
  : [renderWorkItemObservability(observability.workItems.find(({ workItemId }) => workItemId === item.id))]),
288
- ...(currentWorkItemExecutionGroup(item) === undefined
289
- ? []
290
- : renderExecutionGroup(currentWorkItemExecutionGroup(item), executionGroupsById.get(currentWorkItemExecutionGroup(item).id))),
292
+ ...renderWorkItemExecution(projectWorkItemExecution(item, turns, roleSessionSets)),
291
293
  ...(item.acceptance.length === 0
292
294
  ? []
293
295
  : [` Acceptance: ${item.acceptance.map(compactText).join("; ")}`]),
@@ -309,9 +311,12 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
309
311
  : [
310
312
  ` Turns: ${itemRuns.length}; latest ${latestTurn.id} [${latestTurn.status}] ${latestTurn.effective.agentId}/${latestTurn.effective.adapterId} · effective r${latestTurn.effective.sourceDesiredRevision}/${latestTurn.effective.profileAccess}/${latestTurn.effective.permission.strategy}`,
311
313
  ` Assignment: ${latestTurn.inputs[0].input.source.channel}${latestTurn.inputs[0].input.directive === undefined ? "" : ` · ${compactText(latestTurn.inputs[0].input.directive)}`}`,
312
- ...(latestTurn.result === undefined
314
+ ...(latestTurn.result?.output === undefined
315
+ ? []
316
+ : [` Result: ${compactText(latestTurn.result.output)}`]),
317
+ ...(latestTurn.result?.diagnostic === undefined
313
318
  ? []
314
- : [` Summary: ${compactText(latestTurn.result.output)}`])
319
+ : [` Failure: ${compactText(latestTurn.result.diagnostic)}`])
315
320
  ]),
316
321
  ...renderReviewRounds(reviewRounds.filter((round) => round.workItemId === item.id), executionGroupsById)
317
322
  ];
@@ -323,7 +328,10 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
323
328
  ...recentSection("Turns", turns, (run) => [
324
329
  ` ${run.id} [${run.status}/${run.purpose}] ${run.roleName} via ${run.effective.agentId}/${run.effective.adapterId}`,
325
330
  ` Effective: r${run.effective.sourceDesiredRevision}; Profile intent: ${run.effective.profileAccess}; permission: ${run.effective.permission.strategy}; model: ${run.effective.model ?? "default"}; effort: ${run.effective.effort ?? "default"}`,
326
- ...(run.result === undefined ? [] : [` Result: ${compactText(run.result.output)}`])
331
+ ...(run.result?.output === undefined ? [] : [` Result: ${compactText(run.result.output)}`]),
332
+ ...(run.result?.diagnostic === undefined
333
+ ? []
334
+ : [` Failure: ${compactText(run.result.diagnostic)}`])
327
335
  ]),
328
336
  "",
329
337
  "Runtime health:",
@@ -347,7 +355,11 @@ export function runTaskContextCommand(args, store, currentTaskReviewCandidate =
347
355
  `Integration Attempts (${integrations.length}):`,
348
356
  ...(integrations.length === 0
349
357
  ? [" None."]
350
- : integrations.slice(-RECENT_RECORD_LIMIT).map((integration) => (` ${integration.id} [${integration.status}/${integration.projectId}] — ${integration.targetRef}; ${integration.changeSetIds.join(", ")}`))),
358
+ : integrations.slice(-RECENT_RECORD_LIMIT).map((integration) => (` ${integration.id} [${integration.status}/${integration.projectId}] — ${integration.targetRef}; ${integration.source.kind === "work-item"
359
+ ? `WorkItem ${integration.source.workItemId}@${integration.source.resultCommit.slice(0, 12)}`
360
+ : integration.source.kind === "upstream"
361
+ ? `upstream ${integration.source.branch}@${integration.source.remoteCommit.slice(0, 12)}`
362
+ : `historical ChangeSets ${integration.source.changeSetIds.join(", ")}`}`))),
351
363
  "",
352
364
  `Publication references (${publications.length}):`,
353
365
  ...(publications.length === 0
@@ -435,15 +447,7 @@ function renderReviewRounds(rounds, executionGroupsById = new Map()) {
435
447
  ? [` Review mode: full`]
436
448
  : [
437
449
  ` Review mode: delta-recheck (rechecks ${latest.deltaRecheck.previousReviewRoundId}@${latest.deltaRecheck.previousBaseCommit.slice(0, 12)})`,
438
- ` Delta: ${latest.deltaRecheck.changedFiles.length} file(s), +${latest.deltaRecheck.addedLines}/-${latest.deltaRecheck.deletedLines}, digest ${latest.deltaRecheck.diffDigest.slice(0, 12)}`,
439
- ...(latest.deltaRecheck.disposition === undefined
440
- ? []
441
- : [
442
- ` Delta disposition: ${latest.deltaRecheck.disposition}`,
443
- ...(latest.deltaRecheck.escalatedToReviewRoundId === undefined
444
- ? []
445
- : [` Escalated to: ${latest.deltaRecheck.escalatedToReviewRoundId}`])
446
- ])
450
+ ` Delta: ${latest.deltaRecheck.changedFiles.length} file(s), +${latest.deltaRecheck.addedLines}/-${latest.deltaRecheck.deletedLines}, digest ${latest.deltaRecheck.diffDigest.slice(0, 12)}`
447
451
  ])
448
452
  ]
449
453
  : []),
@@ -451,16 +455,18 @@ function renderReviewRounds(rounds, executionGroupsById = new Map()) {
451
455
  ? "not prepared"
452
456
  : `${latest.workspace.root} (${latest.workspace.entries.length} writable Projects)`}`,
453
457
  ` Workspace disposition: ${latest.workspaceDisposition?.kind ?? "pending"}`,
454
- ` Diagnostic evidence: ${latest.evidenceCommit ?? "none"}`,
455
- ` Checks: ${latest.checks === undefined || latest.checks.length === 0
456
- ? "none"
457
- : latest.checks.map(({ name, outcome }) => `${name}=${outcome}`).join(", ")}`,
458
- ...(latest.summary === undefined
458
+ ` Main Reviewer Turn: ${latest.reviewerTurnId ?? "not dispatched"}`,
459
+ ...(latest.failure === undefined
459
460
  ? []
460
- : [` Review summary: ${compactText(latest.summary)}`]),
461
+ : [` Core failure: ${latest.failure.kind} · ${compactText(latest.failure.message)}`]),
461
462
  ...(latest.executionGroup === undefined
462
463
  ? []
463
- : renderExecutionGroup(latest.executionGroup, executionGroupsById.get(latest.executionGroup.id)).map((line) => ` ${line.trimStart()}`))
464
+ : [
465
+ ` Execution shape: replicated`,
466
+ ` Execution Group: ${latest.executionGroup.id}`,
467
+ ...latest.executionGroup.lanes.map((lane) => (` Producer ${lane.id} (#${lane.ordinal}, ${lane.roleName}): `
468
+ + `${lane.disposition}; turn=${lane.currentTurnId ?? "not dispatched"}`))
469
+ ])
464
470
  ];
465
471
  }
466
472
  function renderResolvedInputRequest(request, timeZone) {
@@ -553,57 +559,19 @@ function managedWorkspaceLabel(workspace) {
553
559
  return `execution-lane ${workspace.owner.executionGroupId}/${workspace.owner.executionLaneId}`;
554
560
  }
555
561
  }
556
- function renderExecutionGroup(group, projected) {
557
- const summary = projected
558
- ?? summarizeExecutionGroup(group);
559
- const health = projected?.health;
560
- const resources = projected?.resources;
562
+ function renderWorkItemExecution(projection) {
561
563
  return [
562
- ` Execution Group ${summary.groupId} [${summary.purpose}/${summary.strategy.mode}]: ${summary.activeLaneCount} active / ${summary.terminalLaneCount} terminal; ${summary.failedLaneCount} failed; ${summary.skippedLaneCount} skipped`,
563
- ...(health === undefined
564
- ? []
565
- : [
566
- ` Health: active=${health.activeLaneCount}, silent=${health.silentLaneCount}, suspected-stalled=${health.suspectedStalledLaneCount}, confirmed-dead=${health.confirmedDeadLaneCount}`,
567
- ` Recovery: reusable=${health.reusableLaneIds.length}, retryable=${health.retryableLaneIds.length}`
568
- ]),
569
- ...(resources === undefined
570
- ? []
571
- : [
572
- ` Resources: tokens=${resourceUsageLabel(resources.tokens, resources.tokensRemaining, resources.tokensObservable)}; tools=${resourceUsageLabel(resources.toolCalls, resources.toolCallsRemaining, resources.toolCallsObservable)}; wall=${resources.wallClockSeconds}s${resources.wallClockSecondsRemaining === undefined ? "" : `, remaining=${resources.wallClockSecondsRemaining}s`}`,
573
- ` Completion: usable=${resources.usableLaneCount}/${group.stage?.resources?.quorum ?? "legacy"}; quorum=${resources.quorumMet ? "met" : "open"}; deadline=${resources.deadlineReached ? "reached" : "open"}; budgets=${resources.exhaustedBudgets.join(",") || "open"}; queued=${resources.pendingLaneIds.length}; stragglers=${resources.stragglerLaneIds.length}`
574
- ]),
575
- ...summary.laneSummaries.flatMap((lane) => {
576
- const laneHealth = projected?.laneSummaries.find(({ laneId }) => laneId === lane.laneId);
577
- return [
578
- ` Lane ${lane.laneId} (#${lane.ordinal}, ${lane.roleName}${lane.turnId === undefined ? "" : `, run ${lane.turnId}`}) [${lane.status}${laneHealth?.runtimeHealth === undefined ? "" : `/${laneHealth.runtimeHealth}`}]${lane.summary === undefined ? "" : `: ${compactText(lane.summary)}`}`,
579
- ...(lane.effective === undefined
580
- ? []
581
- : [` Config: ${lane.effective.adapterId}/${lane.effective.model ?? "default"}/${lane.effective.effort ?? "default"}; profile=${lane.effective.profileAccess}`]),
582
- ...(laneHealth !== undefined && laneHealth.recovery !== "none"
583
- ? [` Recovery: ${laneHealth.recovery}; ${compactText(laneHealth.reason)}`]
584
- : []),
585
- ...(lane.report === undefined ? [] : [` Report: ${compactText(lane.report)}`]),
586
- ...(lane.checks === undefined || lane.checks.length === 0
587
- ? []
588
- : [` Checks: ${lane.checks.map(({ name, outcome }) => `${name}:${outcome}`).join(", ")}`]),
589
- ...(lane.findings === undefined || lane.findings.length === 0
590
- ? []
591
- : [` Findings: ${lane.findings.map(({ id, severity, status }) => `${id}:${severity}/${status}`).join(", ")}`]),
592
- ...(lane.evidence === undefined || lane.evidence.length === 0
593
- ? []
594
- : [` Evidence: ${lane.evidence.length} item(s)`]),
595
- ...(lane.evidenceCommit === undefined
596
- ? []
597
- : [` Evidence commit: ${lane.evidenceCommit}`]),
598
- ...(lane.decision === undefined ? [] : [` Decision: ${lane.decision}`])
599
- ];
600
- }),
601
- ...(summary.openHighPriorityFindingIds.length === 0
602
- ? []
603
- : [` Open high findings: ${summary.openHighPriorityFindingIds.join(", ")}`]),
604
- ...(summary.resolution === undefined
564
+ ` WorkItem execution [${projection.shape}]${projection.groupId === undefined ? "" : `: ${projection.groupId}`}`,
565
+ ...projection.lanes.map((lane) => (` Lane ${lane.laneId} (#${lane.ordinal}, ${lane.roleName}) [${lane.status}]: `
566
+ + `turn=${lane.currentTurnId ?? "unknown"}; session=${lane.session}; `
567
+ + `retry=${lane.retryTurnId ?? "none"}; settle=${lane.settleTurnId ?? "none"}`)),
568
+ ` Synthesis: ${projection.synthesis.status} (${projection.synthesis.successfulLaneCount}/${projection.synthesis.requiredSuccessfulLaneCount} successful)`,
569
+ ` Main Turn: ${projection.mainTurn.turnId ?? "unobserved"} [${projection.mainTurn.status}]; session=${projection.mainTurn.session}`,
570
+ ` Candidate source: ${projection.candidate.candidateId ?? "none"} [${projection.candidate.status}]; main=${projection.candidate.mainTurnId ?? "unobserved"}`,
571
+ ...(projection.candidate.sourceExecutionGroupId === undefined
605
572
  ? []
606
- : [` Resolution: ${summary.resolution.decision} ${compactText(summary.resolution.summary)}`])
573
+ : [` Provenance: ${projection.candidate.mainTurnId ?? "unobserved"} -> ${projection.candidate.sourceExecutionGroupId} -> ${projection.candidate.successfulLaneTurns.map(({ laneId, successfulTurnId }) => `${laneId} -> ${successfulTurnId}`).join(", ") || "unobserved"}`]),
574
+ ` Next: ${projection.nextAction.kind}; owner=${projection.nextAction.owners.join(", ") || "none"}; target=${projection.nextAction.targetIds.join(", ") || "none"}`
607
575
  ];
608
576
  }
609
577
  function resourceUsageLabel(used, remaining, observable) {
@@ -612,6 +580,5 @@ function resourceUsageLabel(used, remaining, observable) {
612
580
  return `${used}${remaining === undefined ? "" : `, remaining=${remaining}`}`;
613
581
  }
614
582
  function renderWorkItemObservability(item) {
615
- const stages = item.stages.map((stage) => (`${stage.stage ?? "single"}${stage.round === undefined ? "" : `#${stage.round}`}${stage.stageAttempt === undefined ? "" : `/a${stage.stageAttempt}`}`)).join(", ");
616
- return ` Observability: stages=${stages || "none"}; tokens=${item.cost.tokens}; tools=${item.cost.toolCalls}; wall=${item.cost.wallClockSeconds}s; retries=${item.cost.retryCount}; snapshots=${item.context.snapshotCount}; evidence=${item.evidenceCount}; open-findings=${item.openFindingCount}; compression=${item.context.compressionStatus}`;
583
+ return ` Observability (read-only): tokens=${item.cost.tokensObservable ? item.cost.tokens : "unobserved"}; tools=${item.cost.toolCallsObservable ? item.cost.toolCalls : "unobserved"}; wall=${item.cost.wallClockSeconds}s; retries=${item.cost.retryCount}; snapshots=${item.context.snapshotCount}; agent-results=${item.resultCount ?? "unobserved"}; compression=${item.context.compressionStatus}`;
617
584
  }
@@ -1,12 +1,11 @@
1
1
  import { createTaskEvent } from "../event/taskEvent.js";
2
- import { recordExecutionLaneResult } from "../execution/executionGroup.js";
2
+ import { updateExecutionLane } from "../execution/workItemExecution.js";
3
3
  import { usageError } from "../errors/cliError.js";
4
4
  import { requestDurableJobCancel } from "../job/durableJob.js";
5
5
  import { finishReviewRound, updateReviewExecutionGroup } from "../review/reviewRound.js";
6
6
  import { failTurn } from "../turn/turn.js";
7
7
  import { queueLeaderWakeup } from "../scheduler/wakeupQueue.js";
8
8
  import { startTaskExecution, stopTaskExecution } from "../task/task.js";
9
- import { updateWorkItemExecutionGroup, workItemExecutionGroupById } from "../workItem/workItem.js";
10
9
  import { taskActor } from "./taskActor.js";
11
10
  export function parseTaskExecutionStopRequest(args) {
12
11
  const taskId = args[0];
@@ -183,44 +182,27 @@ function taskRuntimeRoleNames(store, taskId, turns) {
183
182
  }
184
183
  function failExecutionAttempts(store, taskId, turns, reason, now) {
185
184
  const summary = `Task execution stopped: ${reason}`;
186
- const workItems = new Map(store.listWorkItems(taskId).map((item) => [item.id, item]));
187
185
  const reviewRounds = new Map(store.listReviewRounds(taskId).map((round) => [round.id, round]));
188
186
  const affectedReviewRoundIds = new Set();
189
187
  for (const turn of turns) {
190
- if (turn.executionGroupId === undefined || turn.executionLaneId === undefined)
191
- continue;
192
- if (turn.workItemId !== undefined) {
193
- const item = workItems.get(turn.workItemId);
194
- const group = item === undefined
195
- ? undefined
196
- : workItemExecutionGroupById(item, turn.executionGroupId);
197
- const lane = group?.lanes.find(({ id }) => id === turn.executionLaneId);
198
- if (item !== undefined && group !== undefined && lane !== undefined
199
- && item.currentExecutionGroupId === group.id
200
- && !["completed", "failed", "skipped"].includes(lane.status)) {
201
- const updated = updateWorkItemExecutionGroup(item, recordExecutionLaneResult(group, lane.id, { summary }, "failed", now), now);
202
- workItems.set(item.id, updated);
203
- }
204
- }
205
188
  if (turn.reviewRoundId !== undefined) {
206
189
  affectedReviewRoundIds.add(turn.reviewRoundId);
190
+ if (turn.executionGroupId === undefined || turn.executionLaneId === undefined)
191
+ continue;
207
192
  const round = reviewRounds.get(turn.reviewRoundId);
208
193
  const group = round?.executionGroup?.id === turn.executionGroupId
209
194
  ? round.executionGroup
210
195
  : undefined;
211
196
  const lane = group?.lanes.find(({ id }) => id === turn.executionLaneId);
212
197
  if (round !== undefined && group !== undefined && lane !== undefined
213
- && !["completed", "failed", "skipped"].includes(lane.status)) {
214
- reviewRounds.set(round.id, updateReviewExecutionGroup(round, recordExecutionLaneResult(group, lane.id, { summary }, "failed", now)));
198
+ && lane.disposition === "open") {
199
+ reviewRounds.set(round.id, updateReviewExecutionGroup(round, updateExecutionLane(group, lane.id, {
200
+ currentTurnId: turn.id,
201
+ disposition: "failed"
202
+ }, now)));
215
203
  }
216
204
  }
217
205
  }
218
- for (const item of workItems.values()) {
219
- const original = store.getWorkItem(item.taskId, item.id);
220
- if (original !== null && original.revision !== item.revision) {
221
- store.saveWorkItem(item.taskId, item);
222
- }
223
- }
224
206
  for (const reviewRoundId of affectedReviewRoundIds) {
225
207
  const round = reviewRounds.get(reviewRoundId);
226
208
  const original = store.getReviewRound(round.taskId, round.id);
@@ -228,7 +210,7 @@ function failExecutionAttempts(store, taskId, turns, reason, now) {
228
210
  continue;
229
211
  const changed = JSON.stringify(original.executionGroup) !== JSON.stringify(round.executionGroup);
230
212
  const terminal = round.status === "pending" || round.status === "running"
231
- ? finishReviewRound(round, "failed", summary, now)
213
+ ? finishReviewRound(round, "failed", now, { kind: "execution", message: summary })
232
214
  : round;
233
215
  if (changed || terminal !== round)
234
216
  store.saveReviewRound(round.taskId, terminal);
@@ -255,12 +255,12 @@ export function isCurrentGlobalOperator(store, environment) {
255
255
  return false;
256
256
  const agentId = exactIdentity(environment.YUI_AGENT_ID);
257
257
  const adapterId = exactIdentity(environment.YUI_ADAPTER_ID);
258
- const launchId = exactIdentity(environment.YUI_LAUNCH_ID);
258
+ const runtimeGenerationId = exactIdentity(environment.YUI_RUNTIME_GENERATION_ID);
259
259
  const nativeSessionId = exactIdentity(environment.YUI_NATIVE_SESSION_ID);
260
260
  const binding = role.agentBindings[role.activeAgentId];
261
261
  if (agentId === undefined
262
262
  || adapterId === undefined
263
- || launchId === undefined
263
+ || runtimeGenerationId === undefined
264
264
  || binding === undefined
265
265
  || binding.agentId !== agentId
266
266
  || binding.adapterId !== adapterId)
@@ -277,7 +277,7 @@ export function isCurrentGlobalOperator(store, environment) {
277
277
  roleName: role.name,
278
278
  agentId,
279
279
  adapterId,
280
- launchId
280
+ runtimeGenerationId
281
281
  });
282
282
  }
283
283
  // A fresh Codex launch discovers its native Session asynchronously. Its
@@ -290,14 +290,14 @@ export function isCurrentGlobalOperator(store, environment) {
290
290
  || (nativeSessionId === undefined
291
291
  && binding.adapterId === "codex"
292
292
  && session.adapterId === "codex"
293
- && session.launchId !== undefined
294
- && session.launchId === launchId));
293
+ && session.runtimeGenerationId !== undefined
294
+ && session.runtimeGenerationId === runtimeGenerationId));
295
295
  return binding.agentId === session.agentId
296
296
  && binding.adapterId === session.adapterId
297
297
  && session.agentId === agentId
298
298
  && session.adapterId === adapterId
299
- && session.launchId !== undefined
300
- && session.launchId === launchId
299
+ && session.runtimeGenerationId !== undefined
300
+ && session.runtimeGenerationId === runtimeGenerationId
301
301
  && nativeSessionMatches;
302
302
  }
303
303
  function currentProcessBelongsToReservedGlobalLaunch(store, input) {
@@ -307,16 +307,16 @@ function currentProcessBelongsToReservedGlobalLaunch(store, input) {
307
307
  scope: "global",
308
308
  roleName: input.roleName
309
309
  }));
310
- if (!isRuntimeLaunchReservation(mailbox?.processing, input.launchId)
310
+ if (!isRuntimeLaunchReservation(mailbox?.processing, input.runtimeGenerationId)
311
311
  || hasRuntimeCleanupObligation(mailbox))
312
312
  return false;
313
- const owner = store.getSessionOwner(input.launchId);
313
+ const owner = store.getSessionOwner(input.runtimeGenerationId);
314
314
  if (owner === null
315
315
  || owner.owner.scope !== "global"
316
316
  || owner.owner.roleName !== input.roleName
317
317
  || owner.agentId !== input.agentId
318
318
  || owner.adapterId !== input.adapterId
319
- || owner.launchId !== input.launchId
319
+ || owner.runtimeGenerationId !== input.runtimeGenerationId
320
320
  || owner.providerRoot.attribution !== "launch-env"
321
321
  || !isLinuxProcessLive(owner.providerRoot.pid, owner.providerRoot.startIdentity)) {
322
322
  return false;