@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
@@ -86,8 +86,8 @@ const PROVIDER_STATE = new Set([
86
86
  "operation.failed"
87
87
  ]);
88
88
  export function createRuntimeObservation(input) {
89
- if (input.schemaVersion !== 2)
90
- throw new Error("Runtime observation schemaVersion must be 2.");
89
+ if (input.schemaVersion !== 4)
90
+ throw new Error("Runtime observation schemaVersion must be 4.");
91
91
  if (!KINDS.includes(input.kind))
92
92
  throw new Error("Runtime observation kind is invalid.");
93
93
  if (!AUTHORITIES.includes(input.authority))
@@ -133,7 +133,7 @@ export function createRuntimeObservation(input) {
133
133
  throw new Error("Runtime observation ordinal must be a non-negative safe integer.");
134
134
  }
135
135
  return Object.freeze({
136
- schemaVersion: 2,
136
+ schemaVersion: 4,
137
137
  eventId: requireIdentity(input.eventId, "Runtime observation event id"),
138
138
  semanticKey: requireIdentity(input.semanticKey, "Runtime observation semantic key"),
139
139
  kind: input.kind,
@@ -155,8 +155,7 @@ export function runtimeObservationFenceMatches(expected, actual) {
155
155
  "turnId",
156
156
  "agentId",
157
157
  "driverId",
158
- "launchId",
159
- "sessionGenerationId",
158
+ "runtimeGenerationId",
160
159
  "conversationId",
161
160
  "activationId",
162
161
  "continuationId",
@@ -172,7 +171,7 @@ export function runtimeObservationFenceMatches(expected, actual) {
172
171
  return true;
173
172
  }
174
173
  /**
175
- * Matches observations that belong to one durable Turn/Session generation.
174
+ * Matches observations that belong to one durable Turn/Runtime generation.
176
175
  * A provider may advance its native Turn while background subagents from an
177
176
  * earlier Turn are still active and later mailbox activations use their own
178
177
  * exactly-once receipt, so nativeTurnId and receiptId are intentionally
@@ -185,8 +184,7 @@ export function runtimeObservationTurnFenceMatches(expected, actual) {
185
184
  "turnId",
186
185
  "agentId",
187
186
  "driverId",
188
- "launchId",
189
- "sessionGenerationId",
187
+ "runtimeGenerationId",
190
188
  "nativeSessionId"
191
189
  ]) {
192
190
  if (expected[field] !== actual[field])
@@ -203,7 +201,7 @@ export function runtimeObservationTaskEventPayload(input) {
203
201
  roleName: observation.fence.roleName,
204
202
  agentId: observation.fence.agentId,
205
203
  driverId: observation.fence.driverId,
206
- launchId: observation.fence.launchId,
204
+ runtimeGenerationId: observation.fence.runtimeGenerationId,
207
205
  ...(observation.fence.taskId === undefined ? {} : { taskId: observation.fence.taskId }),
208
206
  ...(observation.fence.turnId === undefined ? {} : { turnId: observation.fence.turnId }),
209
207
  ...(observation.fence.nativeSessionId === undefined
@@ -247,8 +245,7 @@ function normalizeFence(input) {
247
245
  ...(input.turnId === undefined ? {} : { turnId: requireIdentity(input.turnId, "Turn id") }),
248
246
  agentId: requireIdentity(input.agentId, "Agent id"),
249
247
  driverId: requireDriverId(input.driverId),
250
- launchId: requireIdentity(input.launchId, "Launch id"),
251
- sessionGenerationId: requireIdentity(input.sessionGenerationId, "Session generation id"),
248
+ runtimeGenerationId: requireIdentity(input.runtimeGenerationId, "Runtime generation id"),
252
249
  ...(input.nativeSessionId === undefined
253
250
  ? {}
254
251
  : { nativeSessionId: requireIdentity(input.nativeSessionId, "Native Session id") }),
@@ -323,6 +320,12 @@ function normalizePayload(kind, input) {
323
320
  if (kind === "turn.failed" && input.failure === undefined) {
324
321
  throw new Error("turn.failed requires normalized failure evidence.");
325
322
  }
323
+ if (input.resultTransportDiagnostic !== undefined && kind !== "turn.completed") {
324
+ throw new Error("Only turn.completed may carry a result transport diagnostic.");
325
+ }
326
+ if (input.output !== undefined && input.resultTransportDiagnostic !== undefined) {
327
+ throw new Error("A runtime observation cannot carry Agent output and a result diagnostic.");
328
+ }
326
329
  if (kind === "conversation.observed"
327
330
  && !["unknown", "recoverable", "unrecoverable"].includes(input.recoverability ?? "")) {
328
331
  throw new Error("conversation.observed requires recoverability.");
@@ -404,6 +407,14 @@ function normalizePayload(kind, input) {
404
407
  : { observerDetail: requireText(input.observerDetail, "Runtime observer detail") }),
405
408
  ...(failure === undefined ? {} : { failure }),
406
409
  ...(input.input === undefined ? {} : { input: requireText(input.input, "Provider-visible input") }),
410
+ ...(input.output === undefined
411
+ ? {}
412
+ : { output: requireResultText(input.output, "Runtime Turn output") }),
413
+ ...(input.resultTransportDiagnostic === undefined
414
+ ? {}
415
+ : {
416
+ resultTransportDiagnostic: requireText(input.resultTransportDiagnostic, "Runtime Turn result diagnostic")
417
+ }),
407
418
  ...(input.summary === undefined ? {} : { summary: requireText(input.summary, "Runtime summary") }),
408
419
  ...(input.execution === undefined ? {} : { execution: input.execution }),
409
420
  ...(input.outcome === undefined ? {} : { outcome: input.outcome }),
@@ -449,8 +460,8 @@ export function runtimeObservationSemanticKey(input) {
449
460
  const continuationIdentity = [
450
461
  fence.driverId,
451
462
  fence.agentId,
452
- fence.conversationId ?? fence.nativeSessionId ?? fence.launchId,
453
- fence.activationId ?? fence.launchId,
463
+ fence.conversationId ?? fence.nativeSessionId ?? fence.runtimeGenerationId,
464
+ fence.activationId ?? fence.runtimeGenerationId,
454
465
  fence.continuationId ?? "none",
455
466
  fence.continuationGeneration ?? "none"
456
467
  ];
@@ -475,7 +486,7 @@ export function runtimeObservationSemanticKey(input) {
475
486
  return [
476
487
  "goal-state",
477
488
  fence.driverId,
478
- fence.conversationId ?? fence.nativeSessionId ?? fence.launchId,
489
+ fence.conversationId ?? fence.nativeSessionId ?? fence.runtimeGenerationId,
479
490
  input.payload?.goalStatus ?? "unknown",
480
491
  input.payload?.goalUpdatedAt ?? "unknown"
481
492
  ].join(":");
@@ -504,8 +515,8 @@ export function runtimeObservationSemanticKey(input) {
504
515
  return [
505
516
  "provider-sequence",
506
517
  fence.driverId,
507
- fence.conversationId ?? fence.nativeSessionId ?? fence.launchId,
508
- fence.activationId ?? fence.launchId,
518
+ fence.conversationId ?? fence.nativeSessionId ?? fence.runtimeGenerationId,
519
+ fence.activationId ?? fence.runtimeGenerationId,
509
520
  fence.continuationId ?? fence.nativeTurnId ?? "none",
510
521
  fence.continuationGeneration ?? "none",
511
522
  input.sequence,
@@ -589,3 +600,9 @@ function requireText(value, label) {
589
600
  }
590
601
  return normalized;
591
602
  }
603
+ function requireResultText(value, label) {
604
+ if (typeof value !== "string" || value.includes("\0") || value.trim().length === 0) {
605
+ throw new Error(`${label} is invalid.`);
606
+ }
607
+ return value;
608
+ }
@@ -15,9 +15,9 @@ export function projectRuntimeSessionCandidate(sessions) {
15
15
  agentId: active.agentId,
16
16
  adapterId: active.adapterId,
17
17
  nativeSessionId: active.nativeSessionId,
18
- ...(active.launchId === undefined ? {} : { launchId: active.launchId }),
18
+ ...(active.runtimeGenerationId === undefined ? {} : { runtimeGenerationId: active.runtimeGenerationId }),
19
19
  sessionUpdatedAt: active.updatedAt,
20
- cleanupRequired: active.launchId !== undefined
20
+ cleanupRequired: active.runtimeGenerationId !== undefined
21
21
  };
22
22
  }
23
23
  /** Deterministic owner order shared by all storage backends. */
@@ -1,16 +1,16 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
3
3
  import { join, resolve } from "node:path";
4
- export function writeRuntimeStopReceipt(home, launchId, requestedAt) {
4
+ export function writeRuntimeStopReceipt(home, runtimeGenerationId, requestedAt) {
5
5
  const receipt = Object.freeze({
6
6
  schemaVersion: 1,
7
7
  receiptId: `runtime-stop-${createHash("sha256")
8
- .update(`${launchId}\0${requestedAt.toISOString()}`)
8
+ .update(`${runtimeGenerationId}\0${requestedAt.toISOString()}`)
9
9
  .digest("hex")}`,
10
- launchId,
10
+ runtimeGenerationId,
11
11
  requestedAt: requestedAt.toISOString()
12
12
  });
13
- const path = stopReceiptPath(home, launchId);
13
+ const path = stopReceiptPath(home, runtimeGenerationId);
14
14
  mkdirSync(resolve(join(home, "runtime", "stop-receipts")), { recursive: true, mode: 0o700 });
15
15
  const temporary = `${path}.tmp-${process.pid}`;
16
16
  writeFileSync(temporary, `${JSON.stringify(receipt)}\n`, { mode: 0o600 });
@@ -18,10 +18,10 @@ export function writeRuntimeStopReceipt(home, launchId, requestedAt) {
18
18
  chmodSync(path, 0o600);
19
19
  return receipt;
20
20
  }
21
- export function readRuntimeStopReceipt(home, launchId) {
21
+ export function readRuntimeStopReceipt(home, runtimeGenerationId) {
22
22
  try {
23
- const value = JSON.parse(readFileSync(stopReceiptPath(home, launchId), "utf8"));
24
- if (value.schemaVersion !== 1 || value.launchId !== launchId
23
+ const value = JSON.parse(readFileSync(stopReceiptPath(home, runtimeGenerationId), "utf8"));
24
+ if (value.schemaVersion !== 1 || value.runtimeGenerationId !== runtimeGenerationId
25
25
  || typeof value.receiptId !== "string" || !Number.isFinite(Date.parse(value.requestedAt))) {
26
26
  throw new Error("Runtime stop receipt is invalid.");
27
27
  }
@@ -33,10 +33,10 @@ export function readRuntimeStopReceipt(home, launchId) {
33
33
  throw error;
34
34
  }
35
35
  }
36
- export function removeRuntimeStopReceipt(home, launchId) {
37
- rmSync(stopReceiptPath(home, launchId), { force: true });
36
+ export function removeRuntimeStopReceipt(home, runtimeGenerationId) {
37
+ rmSync(stopReceiptPath(home, runtimeGenerationId), { force: true });
38
38
  }
39
- function stopReceiptPath(home, launchId) {
40
- const name = createHash("sha256").update(launchId).digest("hex");
39
+ function stopReceiptPath(home, runtimeGenerationId) {
40
+ const name = createHash("sha256").update(runtimeGenerationId).digest("hex");
41
41
  return resolve(join(home, "runtime", "stop-receipts", `${name}.json`));
42
42
  }
@@ -18,11 +18,11 @@ export function createSessionLaunchRequest(input) {
18
18
  if (runtimeIsolation !== undefined && (input.owner.scope !== "task"
19
19
  || runtimeIsolation.taskId !== input.owner.taskId
20
20
  || runtimeIsolation.workspace.root !== workspace
21
- || runtimeIsolation.generation.launchId !== input.launchId)) {
21
+ || runtimeIsolation.generation.runtimeGenerationId !== input.runtimeGenerationId)) {
22
22
  throw new TypeError("Session launch request does not match its Task runtime isolation descriptor.");
23
23
  }
24
24
  const common = {
25
- launchId: requireSafeIdentity(input.launchId, "Launch id"),
25
+ runtimeGenerationId: requireSafeIdentity(input.runtimeGenerationId, "Runtime generation id"),
26
26
  owner: normalizeRuntimeOwner(input.owner),
27
27
  agentId,
28
28
  adapterId,
@@ -29,7 +29,7 @@ export function createSessionOwnerIdentity(input) {
29
29
  }
30
30
  const tmux = input.tmux;
31
31
  return Object.freeze({
32
- schemaVersion: 1,
32
+ schemaVersion: 2,
33
33
  kind: "yui-session-owner",
34
34
  owner: Object.freeze({
35
35
  scope: owner.scope,
@@ -38,7 +38,7 @@ export function createSessionOwnerIdentity(input) {
38
38
  }),
39
39
  agentId: requireSafeIdentity(input.agentId, "Agent id"),
40
40
  adapterId: requireText(input.adapterId, "Adapter id"),
41
- launchId: requireSafeIdentity(input.launchId, "Launch id"),
41
+ runtimeGenerationId: requireSafeIdentity(input.runtimeGenerationId, "Runtime generation id"),
42
42
  ...(input.nativeSessionId === undefined
43
43
  ? {}
44
44
  : { nativeSessionId: requireText(input.nativeSessionId, "Native session id") }),
@@ -134,12 +134,12 @@ export function isLinuxProcessLive(pid, startIdentity) {
134
134
  return current.startIdentity === startIdentity;
135
135
  }
136
136
  /**
137
- * Discovers the Provider root for one launch by the exact YUI_LAUNCH_ID
137
+ * Discovers the Provider root for one launch by the exact YUI_RUNTIME_GENERATION_ID
138
138
  * environment fence. Returns undefined when no same-user process carries the
139
139
  * fence — the caller must not guess from a process name or cwd.
140
140
  */
141
- export function discoverProviderRootByLaunchEnv(launchId) {
142
- const matches = listLaunchFencedProcesses(launchId);
141
+ export function discoverProviderRootByLaunchEnv(runtimeGenerationId) {
142
+ const matches = listLaunchFencedProcesses(runtimeGenerationId);
143
143
  for (const pid of matches) {
144
144
  const identity = readLinuxProcessIdentity(pid);
145
145
  if (identity !== undefined)
@@ -149,13 +149,13 @@ export function discoverProviderRootByLaunchEnv(launchId) {
149
149
  }
150
150
  /**
151
151
  * Lists every live process whose initial environment carries the exact
152
- * `YUI_LAUNCH_ID=<launchId>` fence. The fence is inherited by Provider
152
+ * `YUI_RUNTIME_GENERATION_ID=<runtimeGenerationId>` fence. The fence is inherited by Provider
153
153
  * children, so this is the exact, PID-reuse-safe attribution for a surviving
154
154
  * child after its root has exited: a recycled PID never carries the fence.
155
155
  * Processes without the fence are unattributed and must never be signaled.
156
156
  */
157
- export function listLaunchFencedProcesses(launchId) {
158
- if (!Number.isSafeInteger(launchId) && !/^[A-Za-z0-9_.:-]+$/u.test(launchId)) {
157
+ export function listLaunchFencedProcesses(runtimeGenerationId) {
158
+ if (!Number.isSafeInteger(runtimeGenerationId) && !/^[A-Za-z0-9_.:-]+$/u.test(runtimeGenerationId)) {
159
159
  return [];
160
160
  }
161
161
  let entries;
@@ -165,7 +165,7 @@ export function listLaunchFencedProcesses(launchId) {
165
165
  catch {
166
166
  return [];
167
167
  }
168
- const needle = `YUI_LAUNCH_ID=${launchId}`;
168
+ const needle = `YUI_RUNTIME_GENERATION_ID=${runtimeGenerationId}`;
169
169
  const matches = [];
170
170
  for (const entry of entries) {
171
171
  if (!/^[0-9]+$/u.test(entry))
@@ -4,7 +4,7 @@ import { createSessionOwnerIdentity } from "./sessionOwnerIdentity.js";
4
4
  /**
5
5
  * Durable, enumerable physical owner records for runtime generations.
6
6
  *
7
- * One JSON file per launch id under `<home>/runtime/session-owners/`. The
7
+ * One JSON file per runtime generation id under `<home>/runtime/session-owners/`. The
8
8
  * directory is runtime state (like the tmux socket), not aggregate domain
9
9
  * state, so it needs no schema migration; it survives a Controller restart and
10
10
  * stays enumerable after the durable Session map or history is cleared, which
@@ -22,16 +22,16 @@ export class FileSessionOwnerRegistry {
22
22
  /** Atomically records (or replaces) one generation's owner identity. */
23
23
  record(identity) {
24
24
  mkdirSync(this.#directory, { recursive: true, mode: 0o700 });
25
- const target = this.#path(identity.launchId);
25
+ const target = this.#path(identity.runtimeGenerationId);
26
26
  const temporary = `${target}.tmp-${process.pid}`;
27
27
  writeFileSync(temporary, JSON.stringify(identity, null, 2) + "\n", { mode: 0o600 });
28
28
  renameSync(temporary, target);
29
29
  }
30
- get(launchId) {
31
- if (!isSafeLaunchId(launchId))
30
+ get(runtimeGenerationId) {
31
+ if (!isSafeRuntimeGenerationId(runtimeGenerationId))
32
32
  return null;
33
33
  try {
34
- return parseOwnerRecord(readFileSync(this.#path(launchId), "utf8"));
34
+ return parseOwnerRecord(readFileSync(this.#path(runtimeGenerationId), "utf8"));
35
35
  }
36
36
  catch {
37
37
  return null;
@@ -66,11 +66,11 @@ export class FileSessionOwnerRegistry {
66
66
  && record.owner.roleName === owner.roleName));
67
67
  }
68
68
  /** Removes a record whose physical resources were proven absent. */
69
- remove(launchId) {
70
- if (!isSafeLaunchId(launchId))
69
+ remove(runtimeGenerationId) {
70
+ if (!isSafeRuntimeGenerationId(runtimeGenerationId))
71
71
  return;
72
72
  try {
73
- rmSync(this.#path(launchId), { force: true });
73
+ rmSync(this.#path(runtimeGenerationId), { force: true });
74
74
  }
75
75
  catch {
76
76
  // A stale record is harmless: reconciliation re-verifies physical
@@ -80,12 +80,12 @@ export class FileSessionOwnerRegistry {
80
80
  exists() {
81
81
  return existsSync(this.#directory);
82
82
  }
83
- #path(launchId) {
84
- return join(this.#directory, `${launchId}.json`);
83
+ #path(runtimeGenerationId) {
84
+ return join(this.#directory, `${runtimeGenerationId}.json`);
85
85
  }
86
86
  }
87
- function isSafeLaunchId(launchId) {
88
- return /^[A-Za-z0-9_.:-]+$/u.test(launchId);
87
+ function isSafeRuntimeGenerationId(runtimeGenerationId) {
88
+ return /^[A-Za-z0-9_.:-]+$/u.test(runtimeGenerationId);
89
89
  }
90
90
  function parseOwnerRecord(raw) {
91
91
  const parsed = JSON.parse(raw);
@@ -104,7 +104,7 @@ function parseOwnerRecord(raw) {
104
104
  },
105
105
  agentId: String(record.agentId),
106
106
  adapterId: String(record.adapterId),
107
- launchId: String(record.launchId),
107
+ runtimeGenerationId: String(record.runtimeGenerationId),
108
108
  ...(record.nativeSessionId === undefined
109
109
  ? {}
110
110
  : { nativeSessionId: String(record.nativeSessionId) }),
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Bidirectional durable <-> physical reconciliation for Session generations.
2
+ * Bidirectional durable <-> physical reconciliation for Runtime generations.
3
3
  *
4
4
  * Durable -> physical: every owner record's Provider root must be absent once
5
5
  * its durable Session is terminal; a live root with a terminal durable state
@@ -34,7 +34,7 @@ function reconcileOne(record, input) {
34
34
  ? input.taskStatus(owner.taskId)
35
35
  : undefined;
36
36
  const tmuxPane = input.inspectPane(owner.taskId, owner.roleName);
37
- const lastStopOutcome = input.lastStopOutcome(owner.taskId, owner.roleName, record.launchId);
37
+ const lastStopOutcome = input.lastStopOutcome(owner.taskId, owner.roleName, record.runtimeGenerationId);
38
38
  let mismatch;
39
39
  let verificationGap;
40
40
  if (physical?.identityConflict === true) {
@@ -64,7 +64,7 @@ function reconcileOne(record, input) {
64
64
  },
65
65
  agentId: record.agentId,
66
66
  adapterId: record.adapterId,
67
- launchId: record.launchId,
67
+ runtimeGenerationId: record.runtimeGenerationId,
68
68
  ...(record.nativeSessionId === undefined
69
69
  ? {}
70
70
  : { nativeSessionId: record.nativeSessionId }),
@@ -83,7 +83,7 @@ function matchDurable(record, durable) {
83
83
  && fact.roleName === record.owner.roleName
84
84
  && (record.owner.scope === "global" || fact.taskId === record.owner.taskId)
85
85
  && fact.agentId === record.agentId));
86
- const byLaunch = candidates.find((fact) => fact.launchId !== undefined && fact.launchId === record.launchId);
86
+ const byLaunch = candidates.find((fact) => fact.runtimeGenerationId !== undefined && fact.runtimeGenerationId === record.runtimeGenerationId);
87
87
  if (byLaunch !== undefined)
88
88
  return byLaunch;
89
89
  const byNative = candidates.find((fact) => fact.nativeSessionId !== undefined
@@ -26,7 +26,7 @@ export async function terminateSessionOwners(owner, records, ports, options = {}
26
26
  ports.emit({
27
27
  stage: "stop-requested",
28
28
  owner,
29
- launchId: record.launchId,
29
+ runtimeGenerationId: record.runtimeGenerationId,
30
30
  ...(record.nativeSessionId === undefined
31
31
  ? {}
32
32
  : { nativeSessionId: record.nativeSessionId }),
@@ -37,7 +37,7 @@ export async function terminateSessionOwners(owner, records, ports, options = {}
37
37
  // inventory: /proc entries can disappear between the directory and
38
38
  // environment reads. Retain every exact child identity observed during the
39
39
  // stop so one later scan miss cannot be mistaken for physical zero.
40
- const trackedChildren = new Map(records.map((record) => [record.launchId, new Map()]));
40
+ const trackedChildren = new Map(records.map((record) => [record.runtimeGenerationId, new Map()]));
41
41
  for (const record of records) {
42
42
  refreshTrackedFencedChildren(record, ports, trackedChildren);
43
43
  }
@@ -102,7 +102,7 @@ export async function terminateSessionOwners(owner, records, ports, options = {}
102
102
  continue;
103
103
  }
104
104
  if (verdict.kind === "gap") {
105
- verificationGap = `/proc unreadable for launch ${record.launchId}`;
105
+ verificationGap = `/proc unreadable for launch ${record.runtimeGenerationId}`;
106
106
  remaining.push({ record, detail: verificationGap });
107
107
  continue;
108
108
  }
@@ -111,7 +111,7 @@ export async function terminateSessionOwners(owner, records, ports, options = {}
111
111
  record,
112
112
  detail: root.kind === "live"
113
113
  ? `provider root pid ${record.providerRoot.pid} still live`
114
- : `provider children still live for launch ${record.launchId}`
114
+ : `provider children still live for launch ${record.runtimeGenerationId}`
115
115
  });
116
116
  }
117
117
  const outcome = remaining.length === 0 ? "stop-confirmed" : "stop-blocked";
@@ -121,7 +121,7 @@ export async function terminateSessionOwners(owner, records, ports, options = {}
121
121
  ...(outcome === "stop-blocked"
122
122
  ? {
123
123
  detail: remaining
124
- .map(({ record, detail }) => `${record.launchId}: ${detail}`)
124
+ .map(({ record, detail }) => `${record.runtimeGenerationId}: ${detail}`)
125
125
  .join("; ")
126
126
  }
127
127
  : {}),
@@ -169,11 +169,11 @@ function treeVerdict(record, ports, trackedChildren) {
169
169
  return { kind: "absent" };
170
170
  }
171
171
  function refreshTrackedFencedChildren(record, ports, trackedChildren) {
172
- const tracked = trackedChildren.get(record.launchId);
172
+ const tracked = trackedChildren.get(record.runtimeGenerationId);
173
173
  if (tracked === undefined)
174
174
  return true;
175
175
  let verificationGap = false;
176
- for (const pid of ports.listLaunchFencedProcesses(record.launchId)) {
176
+ for (const pid of ports.listLaunchFencedProcesses(record.runtimeGenerationId)) {
177
177
  if (pid === record.providerRoot.pid)
178
178
  continue;
179
179
  const identity = ports.processIdentity(pid);
@@ -189,7 +189,7 @@ function refreshTrackedFencedChildren(record, ports, trackedChildren) {
189
189
  return verificationGap;
190
190
  }
191
191
  function trackedChildrenVerdict(record, ports, trackedChildren) {
192
- const tracked = trackedChildren.get(record.launchId);
192
+ const tracked = trackedChildren.get(record.runtimeGenerationId);
193
193
  if (tracked === undefined)
194
194
  return { kind: "gap" };
195
195
  let verificationGap = false;
@@ -242,7 +242,7 @@ function escalateRecord(record, ports, trackedChildren, signal) {
242
242
  if (root.kind !== "absent")
243
243
  return;
244
244
  refreshTrackedFencedChildren(record, ports, trackedChildren);
245
- const tracked = trackedChildren.get(record.launchId);
245
+ const tracked = trackedChildren.get(record.runtimeGenerationId);
246
246
  if (tracked === undefined)
247
247
  return;
248
248
  for (const [pid, startIdentity] of tracked) {
@@ -6,7 +6,7 @@ export function resolveSessionTokenIdentity(input) {
6
6
  || input.roleName === undefined
7
7
  || input.agentId === undefined
8
8
  || input.adapterId === undefined
9
- || input.launchId === undefined
9
+ || input.runtimeGenerationId === undefined
10
10
  || input.nativeSessionId === undefined)
11
11
  return null;
12
12
  let driverId;
@@ -21,9 +21,8 @@ export function resolveSessionTokenIdentity(input) {
21
21
  roleName: input.roleName,
22
22
  agentId: input.agentId,
23
23
  driverId,
24
- launchId: input.launchId,
25
- nativeSessionId: input.nativeSessionId,
26
- sessionGenerationId: input.launchId
24
+ runtimeGenerationId: input.runtimeGenerationId,
25
+ nativeSessionId: input.nativeSessionId
27
26
  });
28
27
  }
29
28
  /**
@@ -156,9 +155,8 @@ function matchesSessionGeneration(observation, identity) {
156
155
  && fence.roleName === identity.roleName
157
156
  && fence.agentId === identity.agentId
158
157
  && fence.driverId === identity.driverId
159
- && fence.launchId === identity.launchId
160
- && fence.nativeSessionId === identity.nativeSessionId
161
- && fence.sessionGenerationId === identity.sessionGenerationId;
158
+ && fence.runtimeGenerationId === identity.runtimeGenerationId
159
+ && fence.nativeSessionId === identity.nativeSessionId;
162
160
  }
163
161
  function compareObservations(left, right) {
164
162
  return left.receivedAt.localeCompare(right.receivedAt)
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { Duplex } from "node:stream";
4
4
  import WebSocket from "ws";
5
- import { CodexAppServerRequestError, CodexAppServerRuntime, codexGoalNotification, codexAppServerErrorIsMissing, codexTurnInput, codexTurnSummary } from "./codexAppServerRuntime.js";
5
+ import { CodexAppServerRequestError, CodexAppServerRuntime, codexGoalNotification, codexAppServerErrorIsMissing, codexTurnInput, codexTurnOutput } from "./codexAppServerRuntime.js";
6
6
  import { serializeAgentErrorRaw } from "./agentError.js";
7
7
  import { PROVIDER_ACCEPT_TIMEOUT_MS } from "./runtimeDeadlines.js";
8
8
  import { YUI_VERSION } from "../version.js";
@@ -433,7 +433,7 @@ class CodexStructuredProviderSession {
433
433
  ? "failed"
434
434
  : recovered.status === "interrupted" ? "cancelled" : "completed",
435
435
  observedAt: new Date().toISOString(),
436
- ...(recovered.summary === undefined ? {} : { summary: recovered.summary }),
436
+ ...(recovered.output === undefined ? {} : { output: recovered.output }),
437
437
  ...(recovered.status !== "failed"
438
438
  ? {}
439
439
  : {
@@ -497,7 +497,7 @@ class CodexStructuredProviderSession {
497
497
  const failure = status === "failed"
498
498
  ? providerErrorEvidence(turn.error)
499
499
  : undefined;
500
- const summary = codexTurnSummary(turn);
500
+ const output = codexTurnOutput(turn);
501
501
  const input = codexTurnInput(turn);
502
502
  const terminal = {
503
503
  conversationId: this.conversationId,
@@ -506,7 +506,7 @@ class CodexStructuredProviderSession {
506
506
  status,
507
507
  observedAt: new Date().toISOString(),
508
508
  ...(input === undefined ? {} : { input }),
509
- ...(summary === undefined ? {} : { summary }),
509
+ ...(output === undefined ? {} : { output }),
510
510
  ...(failure === undefined ? {} : failure)
511
511
  };
512
512
  if (this.#submissionPending && emit) {
@@ -744,7 +744,7 @@ class ClaudeStructuredProviderSession {
744
744
  ...(failed
745
745
  ? { error: result, rawError: providerErrorEvidence(message).rawError }
746
746
  : typeof message.result === "string" && message.result.length > 0
747
- ? { summary: message.result }
747
+ ? { output: message.result }
748
748
  : {})
749
749
  });
750
750
  }