@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
@@ -1,4 +1,4 @@
1
- import { normalizedUniqueIdentities, requireIdentity, requireText } from "../domain/validation.js";
1
+ import { normalizedUniqueText, requireIdentity, requireText } from "../domain/validation.js";
2
2
  import { validateContextSnapshotRef } from "./contextSnapshot.js";
3
3
  export const TURN_INPUT_PROTOCOL_VERSION = 1;
4
4
  export const TURN_INPUT_PROTOCOL = "yui-turn/v1";
@@ -106,7 +106,7 @@ function normalizeInput(input) {
106
106
  const snapshot = input.contextSnapshotRef === undefined
107
107
  ? undefined
108
108
  : validateContextSnapshotRef(input.contextSnapshotRef);
109
- const deltaRefIds = normalizedUniqueIdentities(input.deltaRefIds, "Turn input delta ref");
109
+ const deltaRefIds = normalizedUniqueText(input.deltaRefIds, "Turn input delta ref");
110
110
  if (deltaRefIds.length > TURN_INPUT_MAX_DELTAS) {
111
111
  throw new Error(`Turn input supports at most ${TURN_INPUT_MAX_DELTAS} delta refs.`);
112
112
  }
@@ -175,7 +175,8 @@ function normalizeSubject(subject) {
175
175
  "workItemId",
176
176
  "reviewRoundId",
177
177
  "executionGroupId",
178
- "executionLaneId"
178
+ "executionLaneId",
179
+ "sourceExecutionGroupId"
179
180
  ];
180
181
  if (Object.keys(normalized).some((key) => !allowed.includes(key))) {
181
182
  throw new Error("Turn input subject contains an unknown field.");
@@ -183,9 +184,15 @@ function normalizeSubject(subject) {
183
184
  if ((normalized.executionGroupId === undefined) !== (normalized.executionLaneId === undefined)) {
184
185
  throw new Error("Turn input execution lineage is incomplete.");
185
186
  }
187
+ if (normalized.sourceExecutionGroupId !== undefined
188
+ && ((normalized.workItemId === undefined && normalized.reviewRoundId === undefined)
189
+ || normalized.executionGroupId !== undefined)) {
190
+ throw new Error("Turn input source ExecutionGroup requires a WorkItem or Review main subject.");
191
+ }
186
192
  if (normalized.taskId === undefined
187
193
  && (normalized.workItemId !== undefined || normalized.reviewRoundId !== undefined
188
- || normalized.executionGroupId !== undefined)) {
194
+ || normalized.executionGroupId !== undefined
195
+ || normalized.sourceExecutionGroupId !== undefined)) {
189
196
  throw new Error("Turn input child subject requires a Task id.");
190
197
  }
191
198
  return Object.freeze(normalized);
@@ -28,17 +28,24 @@ export function buildTaskWakeEnvelope(reader, request) {
28
28
  }
29
29
  const fromTime = Date.parse(request.fromCursor);
30
30
  const events = reader.listEvents(request.taskId);
31
+ const deltaEvents = events.filter((record) => Date.parse(record.createdAt) > fromTime);
32
+ const turns = operationalTaskRecords(reader.listTurns(request.taskId), events, "turn");
33
+ const referencedTurnIds = referencedWakeTurnIds(turns, events, deltaEvents);
34
+ const changedTurnIds = new Set([
35
+ ...turns
36
+ .filter((record) => Date.parse(record.createdAt) > fromTime)
37
+ .map(({ id }) => id),
38
+ ...referencedTurnIds
39
+ ]);
31
40
  const counts = {
32
- events: events
33
- .filter((record) => Date.parse(record.createdAt) > fromTime).length,
41
+ events: deltaEvents.length,
34
42
  messages: operationalTaskRecords(reader.listMessages(request.taskId), events, "message")
35
43
  .filter((record) => Date.parse(record.createdAt) > fromTime).length,
36
- turns: operationalTaskRecords(reader.listTurns(request.taskId), events, "turn")
37
- .filter((record) => Date.parse(record.createdAt) > fromTime).length
44
+ turns: changedTurnIds.size
38
45
  };
39
46
  const activeReviews = reader.listReviewRounds(request.taskId).filter((round) => ((round.scope ?? "work-item") === "task"
40
47
  && (round.status === "pending" || round.status === "running")));
41
- const reviewOrientation = activeReviews.slice(0, 3).map((round) => {
48
+ const renderReviewOrientation = (limit) => activeReviews.slice(0, limit).map((round) => {
42
49
  const projects = round.taskCandidate?.projects ?? [];
43
50
  const heads = projects.slice(0, 2).map(({ projectId, commit }) => (`${projectId}@${commit.slice(0, 12)}`)).join("+");
44
51
  return `${round.id}/${round.reviewerRoleName}`
@@ -47,36 +54,91 @@ export function buildTaskWakeEnvelope(reader, request) {
47
54
  + `@${heads || round.reviewBaseCommit.slice(0, 12)}`
48
55
  + `${projects.length > 2 ? `+${projects.length - 2}` : ""}`;
49
56
  }).join(", ");
50
- const lines = [
51
- `Wake: ${request.wakeId} delta since ${request.fromCursor}`,
52
- ` Reasons: ${renderReasons(request.reasons)}`,
53
- ` Changed: ${counts.events} events, ${counts.messages} messages, ${counts.turns} Turns`
54
- + ` → yui task wake show ${request.taskId} ${request.wakeId}`,
55
- ` Active Task Reviews: ${activeReviews.length === 0
56
- ? "none"
57
- : `${reviewOrientation}${activeReviews.length > 3 ? `, … (+${activeReviews.length - 3})` : ""}`}`,
58
- `Full context: yui task context ${request.taskId}`
59
- ];
60
- const body = lines.join("\n");
61
- const totalBytes = byteLength(body) + 1;
62
- if (totalBytes > WAKE_ENVELOPE_HARD_BYTES) {
63
- throw new Error(`Wake envelope ${request.wakeId} exceeds the structural hard budget of`
64
- + ` ${WAKE_ENVELOPE_HARD_BYTES} bytes (${totalBytes}).`);
57
+ const render = (reasonLimit, resultTurnLimit, reviewLimit) => {
58
+ const reviewOrientation = renderReviewOrientation(reviewLimit);
59
+ return [
60
+ `Wake: ${request.wakeId} delta since ${request.fromCursor}`,
61
+ ` Reasons: ${renderReasons(request.reasons, reasonLimit)}`,
62
+ ` Changed: ${counts.events} events, ${counts.messages} messages, ${counts.turns} Turns`
63
+ + ` → yui task wake show ${request.taskId} ${request.wakeId}`,
64
+ ` Result Turns: ${renderResultTurns(request.taskId, referencedTurnIds, resultTurnLimit)}`,
65
+ ` Active Task Reviews: ${activeReviews.length === 0
66
+ ? "none"
67
+ : reviewLimit === 0
68
+ ? `${activeReviews.length} yui task context ${request.taskId}`
69
+ : `${reviewOrientation}${activeReviews.length > reviewLimit
70
+ ? `, (+${activeReviews.length - reviewLimit})`
71
+ : ""}`}`,
72
+ `Full context: yui task context ${request.taskId}`
73
+ ].join("\n");
74
+ };
75
+ let reasonLimit = Math.min(REASON_DISPLAY_LIMIT, request.reasons.length);
76
+ let resultTurnLimit = Math.min(4, referencedTurnIds.length);
77
+ let reviewLimit = Math.min(3, activeReviews.length);
78
+ let body = render(reasonLimit, resultTurnLimit, reviewLimit);
79
+ while (byteLength(body) + 1 > WAKE_ENVELOPE_HARD_BYTES) {
80
+ if (resultTurnLimit > 0)
81
+ resultTurnLimit -= 1;
82
+ else if (reasonLimit > 0)
83
+ reasonLimit -= 1;
84
+ else if (reviewLimit > 0)
85
+ reviewLimit -= 1;
86
+ else
87
+ break;
88
+ body = render(reasonLimit, resultTurnLimit, reviewLimit);
65
89
  }
90
+ if (byteLength(body) + 1 > WAKE_ENVELOPE_HARD_BYTES) {
91
+ body = fitUtf8([
92
+ `Wake: ${request.wakeId}`,
93
+ `Inspect: yui task wake show ${request.taskId} ${request.wakeId}`,
94
+ `Full context: yui task context ${request.taskId}`
95
+ ].join("\n"), WAKE_ENVELOPE_HARD_BYTES - 1);
96
+ }
97
+ const totalBytes = byteLength(body) + 1;
66
98
  return Object.freeze({
67
99
  taskId: request.taskId,
68
100
  wakeId: request.wakeId,
69
101
  fromCursor: request.fromCursor,
102
+ referencedTurnIds: Object.freeze(referencedTurnIds),
70
103
  totalBytes,
71
104
  text: `${body}\n`
72
105
  });
73
106
  }
74
- function renderReasons(reasons) {
75
- const selected = reasons.slice(0, REASON_DISPLAY_LIMIT);
107
+ export function referencedWakeTurnIds(turns, allEvents, terminalEvents) {
108
+ const turnsById = new Map(operationalTaskRecords(turns, allEvents, "turn").map((turn) => [turn.id, turn]));
109
+ return [...new Set(terminalEvents.flatMap((event) => {
110
+ if (!["turn.completed", "turn.failed", "turn.cancelled"].includes(event.type))
111
+ return [];
112
+ const turnId = event.payload.turnId;
113
+ return turnId !== undefined && turnsById.has(turnId) ? [turnId] : [];
114
+ }))];
115
+ }
116
+ function renderReasons(reasons, limit) {
117
+ if (limit === 0)
118
+ return `${reasons.length} reason tags`;
119
+ const selected = reasons.slice(0, limit);
76
120
  const elided = reasons.length - selected.length;
77
121
  const rendered = selected.map(renderWakeReason).join(", ");
78
122
  return elided === 0 ? rendered : `${rendered}, … (+${elided} more)`;
79
123
  }
124
+ function renderResultTurns(taskId, turnIds, limit) {
125
+ if (turnIds.length === 0)
126
+ return "none";
127
+ if (limit === 0)
128
+ return `${turnIds.length} → inspect the wake delta`;
129
+ return `${turnIds.slice(0, limit)
130
+ .map((turnId) => `${turnId} → yui task turn show ${taskId}/${turnId}`)
131
+ .join(", ")}${turnIds.length > limit ? `, … (+${turnIds.length - limit})` : ""}`;
132
+ }
133
+ function fitUtf8(value, maxBytes) {
134
+ let fitted = "";
135
+ for (const character of value) {
136
+ if (byteLength(fitted) + byteLength(character) > maxBytes)
137
+ break;
138
+ fitted += character;
139
+ }
140
+ return fitted;
141
+ }
80
142
  function byteLength(value) {
81
143
  return Buffer.byteLength(value, "utf8");
82
144
  }
@@ -102,7 +102,7 @@ export class AgentRuntimeObserver {
102
102
  ? tokenObservationIdentity("baseline", fence, source.sourceId, baselineKey)
103
103
  : usageObservationIdentity(fence, source.sourceId, latestOccurrence);
104
104
  this.inbox.enqueueObservation(createRuntimeObservation({
105
- schemaVersion: 2,
105
+ schemaVersion: 4,
106
106
  eventId: identity.eventId,
107
107
  semanticKey: identity.semanticKey,
108
108
  kind: "activity.observed",
@@ -137,7 +137,7 @@ export class AgentRuntimeObserver {
137
137
  const health = JSON.stringify([sample.status, sample.detail ?? null]);
138
138
  if (state.health !== health) {
139
139
  this.inbox.enqueueObservation(createRuntimeObservation({
140
- schemaVersion: 2,
140
+ schemaVersion: 4,
141
141
  eventId: observationId("health", fence, source.sourceId, health),
142
142
  semanticKey: observationId("health", fence, source.sourceId, health),
143
143
  kind: "observer.health",
@@ -183,7 +183,7 @@ export class AgentRuntimeObserver {
183
183
  usages.forEach((occurrence, usageIndex) => {
184
184
  const identity = usageObservationIdentity(fence, source.sourceId, occurrence);
185
185
  this.inbox.enqueueObservation(createRuntimeObservation({
186
- schemaVersion: 2,
186
+ schemaVersion: 4,
187
187
  eventId: identity.eventId,
188
188
  semanticKey: identity.semanticKey,
189
189
  kind: "activity.observed",
@@ -213,7 +213,7 @@ export class AgentRuntimeObserver {
213
213
  });
214
214
  if (activityChanged && state.cursor !== undefined) {
215
215
  this.inbox.enqueueObservation(createRuntimeObservation({
216
- schemaVersion: 2,
216
+ schemaVersion: 4,
217
217
  eventId: observationId("activity", fence, source.sourceId, sample.activityId),
218
218
  semanticKey: observationId("activity", fence, source.sourceId, sample.activityId),
219
219
  kind: "activity.observed",
@@ -297,7 +297,7 @@ export class AgentRuntimeObserver {
297
297
  continue;
298
298
  }
299
299
  const fence = accepted.fence;
300
- const generation = taskObservations.filter((observation) => (sessionGenerationFenceMatches(fence, observation.fence)
300
+ const generation = taskObservations.filter((observation) => (sessionRuntimeGenerationFenceMatches(fence, observation.fence)
301
301
  && observation.payload.sourceId === source.sourceId));
302
302
  const persistedUsage = generation.filter((observation) => (observation.kind === "activity.observed"
303
303
  && observation.payload.usage !== undefined)).at(-1);
@@ -316,8 +316,7 @@ export class AgentRuntimeObserver {
316
316
  fence.turnId,
317
317
  fence.agentId,
318
318
  fence.driverId,
319
- fence.launchId,
320
- fence.sessionGenerationId,
319
+ fence.runtimeGenerationId,
321
320
  fence.nativeSessionId,
322
321
  source.sourceId
323
322
  ]),
@@ -463,21 +462,19 @@ function tokenObservationId(kind, fence, sourceId, value) {
463
462
  fence.roleName,
464
463
  fence.agentId,
465
464
  fence.driverId,
466
- fence.launchId,
467
- fence.sessionGenerationId,
465
+ fence.runtimeGenerationId,
468
466
  fence.nativeSessionId ?? null,
469
467
  sourceId,
470
468
  value
471
469
  ])).digest("hex")}`;
472
470
  }
473
- function sessionGenerationFenceMatches(expected, actual) {
471
+ function sessionRuntimeGenerationFenceMatches(expected, actual) {
474
472
  for (const field of [
475
473
  "taskId",
476
474
  "roleName",
477
475
  "agentId",
478
476
  "driverId",
479
- "launchId",
480
- "sessionGenerationId",
477
+ "runtimeGenerationId",
481
478
  "nativeSessionId"
482
479
  ]) {
483
480
  if (expected[field] !== actual[field])
@@ -88,7 +88,7 @@ export async function ensureFileTaskController(home, options = {}) {
88
88
  }
89
89
  /** Start and await readiness for a captured Controller identity. */
90
90
  export async function ensureFileTaskControllerIdentity(home, identity, options = {}) {
91
- assertExpectedControllerLaunchIdentity(identity);
91
+ assertExpectedControllerRuntimeGenerationIdentity(identity);
92
92
  const status = await ensureFileTaskController(home, {
93
93
  ...options,
94
94
  expectedVersion: identity.version
@@ -102,36 +102,36 @@ export async function ensureFileTaskControllerIdentity(home, identity, options =
102
102
  const actual = await call(home, "controller.identity", {}, {
103
103
  timeoutMs: options.requestTimeoutMs
104
104
  });
105
- assertControllerLaunchIdentity(actual, identity);
105
+ assertControllerRuntimeGenerationIdentity(actual, identity);
106
106
  return status;
107
107
  }
108
- function assertExpectedControllerLaunchIdentity(identity) {
108
+ function assertExpectedControllerRuntimeGenerationIdentity(identity) {
109
109
  if (typeof identity.executablePath !== "string"
110
110
  || identity.executablePath.length === 0
111
111
  || !Array.isArray(identity.args)
112
112
  || identity.args.some((arg) => typeof arg !== "string")
113
113
  || typeof identity.version !== "string"
114
114
  || identity.version.length === 0) {
115
- throw new Error("Expected Controller launch identity is malformed; refusing to start or accept a Controller.");
115
+ throw new Error("Expected Controller runtime generation identity is malformed; refusing to start or accept a Controller.");
116
116
  }
117
117
  }
118
- function assertControllerLaunchIdentity(actual, expected) {
118
+ function assertControllerRuntimeGenerationIdentity(actual, expected) {
119
119
  if (!isJsonRecord(actual)) {
120
- throw new Error("Authenticated Controller launch identity is malformed; refusing to accept readiness.");
120
+ throw new Error("Authenticated Controller runtime generation identity is malformed; refusing to accept readiness.");
121
121
  }
122
122
  const actualArgs = actual.args;
123
123
  if (typeof actual.executablePath !== "string"
124
124
  || !Array.isArray(actualArgs)
125
125
  || actualArgs.some((arg) => typeof arg !== "string")
126
126
  || typeof actual.version !== "string") {
127
- throw new Error("Authenticated Controller launch identity is malformed; refusing to accept readiness.");
127
+ throw new Error("Authenticated Controller runtime generation identity is malformed; refusing to accept readiness.");
128
128
  }
129
129
  const argsMatch = actualArgs.length === expected.args.length
130
130
  && actualArgs.every((arg, index) => arg === expected.args[index]);
131
131
  if (actual.executablePath !== expected.executablePath
132
132
  || !argsMatch
133
133
  || actual.version !== expected.version) {
134
- throw new Error("Authenticated Controller launch identity does not match the captured executable, argv, and version; refusing readiness.");
134
+ throw new Error("Authenticated Controller runtime generation identity does not match the captured executable, argv, and version; refusing readiness.");
135
135
  }
136
136
  }
137
137
  function assertCompatibleControllerStatus(status, expectedVersion) {
@@ -479,7 +479,7 @@ export class FileTaskWorkflowRuntime {
479
479
  agentId: input.agentId,
480
480
  adapterId: input.adapterId,
481
481
  nativeSessionId: input.nativeSessionId,
482
- ...(input.launchId === undefined ? {} : { launchId: input.launchId }),
482
+ ...(input.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: input.runtimeGenerationId }),
483
483
  sessionUpdatedAt: input.sessionUpdatedAt
484
484
  });
485
485
  if (target === null) {
@@ -563,7 +563,7 @@ export class FileTaskWorkflowRuntime {
563
563
  if (blockers.length === 0)
564
564
  return;
565
565
  throw new WorkspaceCleanupBlockedError("physical-resource-live", `task:${taskId}`, true, `Task archive blocked: ${blockers.length} owned physical resource(s) still live: `
566
- + blockers.map((entry) => (`${entry.owner.roleName}/${entry.launchId}`
566
+ + blockers.map((entry) => (`${entry.owner.roleName}/${entry.runtimeGenerationId}`
567
567
  + ` (pid ${entry.physical?.alive === true ? entry.physical.pid : "?"})`)).join("; "));
568
568
  }
569
569
  async stopGlobalRoleSession(roleName) {
@@ -622,10 +622,10 @@ export class FileTaskWorkflowRuntime {
622
622
  if (termination.outcome !== "stop-confirmed") {
623
623
  throw new Error(`Role runtime cleanup could not prove physical exit: ${runtimeOwnerLabel(candidate.owner)}; `
624
624
  + termination.remaining
625
- .map(({ record, detail }) => `${record.launchId}: ${detail}`)
625
+ .map(({ record, detail }) => `${record.runtimeGenerationId}: ${detail}`)
626
626
  .join("; "));
627
627
  }
628
- if (candidate.owner.scope === "task" && candidate.launchId !== undefined) {
628
+ if (candidate.owner.scope === "task" && candidate.runtimeGenerationId !== undefined) {
629
629
  const isolation = new FileTaskRuntimeIsolation({
630
630
  runtimeRoot: `${this.home}.task-runtimes`,
631
631
  controlPlane: {
@@ -637,7 +637,7 @@ export class FileTaskWorkflowRuntime {
637
637
  });
638
638
  isolation.cleanupTaskLaunch({
639
639
  taskId: candidate.owner.taskId,
640
- launchId: candidate.launchId,
640
+ runtimeGenerationId: candidate.runtimeGenerationId,
641
641
  reason: this.store.getTask(candidate.owner.taskId)?.status === "completed"
642
642
  ? "completion"
643
643
  : "interruption"
@@ -97,7 +97,7 @@ export async function runControllerSchedulerPass(store, delivery, now, workspace
97
97
  : [])));
98
98
  // Phase-one Leader Turns did not exist at the pass's liveness boundary.
99
99
  // Keep every newly claimed Turn outside destructive absence decisions until
100
- // a later pass can observe its stable provider/session generation.
100
+ // a later pass can observe its stable provider/runtime generation.
101
101
  for (const result of initialWakeupResults) {
102
102
  if (result.turnId !== undefined
103
103
  && store.getActiveTurn(result.taskId, "leader")?.id === result.turnId) {
@@ -220,7 +220,7 @@ async function processSelectedRoleRuntimeCleanups(store, delivery, lifecycleHost
220
220
  }
221
221
  if (target.kind === "role-runtime") {
222
222
  const session = store.getRoleSession(target.taskId, target.roleName);
223
- const reservedLaunchId = isRuntimeLaunchReservation(mailbox.processing)
223
+ const reservedRuntimeGenerationId = isRuntimeLaunchReservation(mailbox.processing)
224
224
  ? mailbox.processing.batchId
225
225
  : undefined;
226
226
  // A failed fresh-Conversation launch can leave two exact resource
@@ -228,19 +228,19 @@ async function processSelectedRoleRuntimeCleanups(store, delivery, lifecycleHost
228
228
  // replacement reservation. They are not competing authorities. The
229
229
  // owner-wide stop has already proven physical zero, so clean both
230
230
  // exact launch roots idempotently before settling the mailbox.
231
- const launchIds = new Set([
232
- reservedLaunchId,
233
- session?.launchId
234
- ].filter((launchId) => launchId !== undefined));
231
+ const runtimeGenerationIds = new Set([
232
+ reservedRuntimeGenerationId,
233
+ session?.runtimeGenerationId
234
+ ].filter((runtimeGenerationId) => runtimeGenerationId !== undefined));
235
235
  if (lifecycleHost.cleanupTaskLaunch !== undefined) {
236
236
  const task = store.getTask(target.taskId);
237
237
  const reason = task?.status === "completed"
238
238
  ? "completion"
239
239
  : "interruption";
240
- for (const launchId of launchIds) {
240
+ for (const runtimeGenerationId of runtimeGenerationIds) {
241
241
  lifecycleHost.cleanupTaskLaunch({
242
242
  taskId: target.taskId,
243
- launchId,
243
+ runtimeGenerationId,
244
244
  reason
245
245
  });
246
246
  }
@@ -338,7 +338,7 @@ async function reconcileDormantRuntimeOwners(store, delivery, lifecycleHost, sco
338
338
  for (const candidate of candidates) {
339
339
  if (byOwner.get(runtimeOwnerIdentity(candidate.owner))?.state
340
340
  === "stopped") {
341
- if (candidate.launchId !== undefined) {
341
+ if (candidate.runtimeGenerationId !== undefined) {
342
342
  // The exact launch-owned resources must settle through the durable
343
343
  // cleanup lane before its Host fact is detached. The resumable Session
344
344
  // remains active; the candidate is the CAS fence against a concurrent
@@ -1600,9 +1600,9 @@ export class FileTaskController {
1600
1600
  taskId: failure.taskId,
1601
1601
  roleName: failure.roleName,
1602
1602
  turnId: failure.turnId,
1603
- ...(failure.launchId === undefined
1603
+ ...(failure.runtimeGenerationId === undefined
1604
1604
  ? {}
1605
- : { launchId: failure.launchId })
1605
+ : { runtimeGenerationId: failure.runtimeGenerationId })
1606
1606
  });
1607
1607
  if (!this.#stopped)
1608
1608
  this.signal(key);