@zq-silk/yui 0.16.1 → 1.0.0-alpha

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 (193) hide show
  1. package/ARCHITECTURE.md +12 -0
  2. package/ARCHITECTURE.zh-CN.md +8 -0
  3. package/README.md +9 -4
  4. package/dist/agent/agent.js +4 -9
  5. package/dist/agent/executionComponents.js +4 -4
  6. package/dist/agent/managedRuntimeEnvironment.js +0 -4
  7. package/dist/agentRun/agentRun.js +13 -23
  8. package/dist/artifacts/managedGit.js +3 -56
  9. package/dist/brief/taskBrief.js +3 -3
  10. package/dist/cli/agentConfigurationPicker.js +24 -21
  11. package/dist/cli/commandCatalog.js +18 -10
  12. package/dist/cli/roleWizard.js +41 -30
  13. package/dist/cli/updateCommand.js +35 -13
  14. package/dist/cli/updateOrchestrator.js +73 -44
  15. package/dist/cli/updatePorts.js +76 -86
  16. package/dist/cli/upgradeCommand.js +4 -8
  17. package/dist/cli.js +39 -33
  18. package/dist/commands/controllerCommands.js +2 -2
  19. package/dist/commands/executionAuditCommands.js +2 -2
  20. package/dist/commands/projectCommands.js +1 -1
  21. package/dist/commands/releaseCommands.js +9 -38
  22. package/dist/commands/taskCommands.js +91 -81
  23. package/dist/commands/taskCompletionGate.js +0 -117
  24. package/dist/commands/taskRoleRuntimeStatus.js +2 -2
  25. package/dist/commands/taskUpstreamCommands.js +93 -54
  26. package/dist/context/runContextPack.js +30 -54
  27. package/dist/context/runInputContract.js +9 -0
  28. package/dist/context/sessionBootstrapManifest.js +11 -19
  29. package/dist/controller/agentHostObservation.js +4 -2
  30. package/dist/controller/agentRuntimeObserver.js +4 -4
  31. package/dist/controller/clientRuntime.js +19 -44
  32. package/dist/controller/controller.js +24 -10
  33. package/dist/controller/fileSchedulerStoreAdapter.js +91 -24
  34. package/dist/controller/globalInputDelivery.js +31 -8
  35. package/dist/controller/globalRuntimeAttention.js +34 -0
  36. package/dist/controller/jobSupervisor.js +3 -3
  37. package/dist/controller/operatorNotification.js +31 -0
  38. package/dist/controller/providerRetryAdmission.js +3 -1
  39. package/dist/controller/providerRetryDelivery.js +136 -119
  40. package/dist/controller/runtime.js +2 -28
  41. package/dist/controller/sessionOwnerReconciliation.js +42 -24
  42. package/dist/controller/structuredProviderObservation.js +28 -1
  43. package/dist/controller/updateReconciliation.js +72 -20
  44. package/dist/coordination/workMailbox.js +4 -4
  45. package/dist/core/controllerIdentity.js +25 -0
  46. package/dist/core/controllerProcessIdentity.js +2 -2
  47. package/dist/core/controllerServer.js +4 -2
  48. package/dist/core/protocol.js +1 -1
  49. package/dist/doctor/doctor.js +2 -1
  50. package/dist/domain/validation.js +6 -0
  51. package/dist/event/taskEvent.js +3 -3
  52. package/dist/execution/workItemExecution.js +2 -2
  53. package/dist/executor/agentAdapter.js +28 -96
  54. package/dist/executor/agentConfigurationCatalog.js +13 -68
  55. package/dist/executor/agentConfigurationFields.js +120 -0
  56. package/dist/executor/agentConfigurationProbe.js +55 -80
  57. package/dist/executor/agentExecutor.js +11 -8
  58. package/dist/executor/effectiveLaunch.js +3 -3
  59. package/dist/executor/executorRegistry.js +0 -9
  60. package/dist/executor/fileRoleLaunchPlanner.js +12 -11
  61. package/dist/grant/capabilityGrant.js +2 -2
  62. package/dist/input/inputRequest.js +4 -4
  63. package/dist/integration/changeSet.js +3 -3
  64. package/dist/integration/integrationAttempt.js +3 -3
  65. package/dist/integration/integrationSourceApplication.js +1 -1
  66. package/dist/interaction/operatorPresentation.js +2 -1
  67. package/dist/job/durableJob.js +1 -1
  68. package/dist/job/jobRunner.js +2 -2
  69. package/dist/message/message.js +8 -6
  70. package/dist/message/messageContinuation.js +8 -9
  71. package/dist/milestone/milestone.js +3 -3
  72. package/dist/observability/executionAudit.js +1 -10
  73. package/dist/observability/runtimeIdentity.js +0 -23
  74. package/dist/output/agentConfigurationPresentation.js +4 -2
  75. package/dist/profile/agentProfile.js +3 -3
  76. package/dist/release/releaseHandover.js +2 -2
  77. package/dist/release/releaseIdempotencyStore.js +0 -23
  78. package/dist/release/releaseWorkflowPorts.js +8 -4
  79. package/dist/release/runtimeRelease.js +9 -7
  80. package/dist/repository/gitWorkspace.js +66 -19
  81. package/dist/repository/project.js +3 -3
  82. package/dist/repository/taskWorkspacePreparer.js +75 -68
  83. package/dist/resources/liveReferences.js +1 -1
  84. package/dist/resources/resourceRegistry.js +90 -44
  85. package/dist/resources/sqliteResourceRegistry.js +5 -7
  86. package/dist/review/reviewRound.js +5 -5
  87. package/dist/role/role.js +7 -8
  88. package/dist/runtime/acpProtocol.js +2 -3
  89. package/dist/runtime/acpSession.js +21 -5
  90. package/dist/runtime/agentDriverObservation.js +1 -1
  91. package/dist/runtime/agentEndpoint.js +4 -1
  92. package/dist/runtime/agentHost.js +25 -65
  93. package/dist/runtime/agentHostCleanup.js +85 -0
  94. package/dist/runtime/agentHostProtocol.js +3 -3
  95. package/dist/runtime/builtinAgentDrivers.js +46 -119
  96. package/dist/runtime/builtinTranscriptObserver.js +10 -6
  97. package/dist/runtime/codexAppServerRuntime.js +55 -89
  98. package/dist/runtime/codexInteractiveHost.js +1 -1
  99. package/dist/runtime/jsonLineChannel.js +35 -7
  100. package/dist/runtime/launchBroker.js +1 -1
  101. package/dist/runtime/processExitObservation.js +1 -1
  102. package/dist/runtime/providerContinuationReconciliationService.js +86 -38
  103. package/dist/runtime/providerRetry.js +15 -0
  104. package/dist/runtime/providerRuntimeIdentity.js +3 -3
  105. package/dist/runtime/providerRuntimeReconciler.js +12 -2
  106. package/dist/runtime/runtimeCoherence.js +7 -3
  107. package/dist/runtime/runtimeObservation.js +3 -3
  108. package/dist/runtime/sessionOwnerIdentity.js +1 -1
  109. package/dist/runtime/structuredProviderHost.js +106 -81
  110. package/dist/runtime/taskRuntimeIsolation.js +3 -3
  111. package/dist/runtime/tmuxAdapters.js +3 -3
  112. package/dist/scheduler/activeRoleRunDelivery.js +5 -1
  113. package/dist/scheduler/operatorInputNotificationProcessor.js +7 -17
  114. package/dist/scheduler/taskWake.js +1 -1
  115. package/dist/storage/baselineSchema.js +606 -0
  116. package/dist/storage/homeLayout.js +5 -16
  117. package/dist/storage/recordValidation.js +16 -4
  118. package/dist/storage/sqliteSchema.js +106 -1741
  119. package/dist/storage/sqliteStore.js +16 -14
  120. package/dist/storage/storageSchema.js +8 -7
  121. package/dist/storage/storageVersions.js +23 -16
  122. package/dist/storage/taskStore.js +3 -29
  123. package/dist/storage/upgrade/upgradeOrchestrator.js +14 -112
  124. package/dist/task/nextAction.js +33 -23
  125. package/dist/task/task.js +17 -8
  126. package/dist/task/taskActivation.js +5 -4
  127. package/dist/telemetry/sqliteTelemetryStore.js +2 -2
  128. package/dist/verification/gateArtifact.js +5 -3
  129. package/dist/verification/verificationPlan.js +6 -7
  130. package/dist/web/assets/assetManifest.js +2 -0
  131. package/dist/web/assets/client/app.js +72 -3
  132. package/dist/web/assets/client/components.js +2 -1
  133. package/dist/web/assets/client/i18n.js +2 -0
  134. package/dist/web/assets/client/taskSummary.js +345 -0
  135. package/dist/web/assets/client/taskSurface.js +44 -26
  136. package/dist/web/assets/client/view.js +33 -0
  137. package/dist/web/assets/shell.js +1 -0
  138. package/dist/web/assets/styles/cards.js +21 -0
  139. package/dist/web/webServer.js +39 -5
  140. package/dist/web/webSessions.js +165 -0
  141. package/dist/web/webSnapshot.js +23 -0
  142. package/dist/web/webTaskSurface.js +23 -0
  143. package/dist/workItem/workItem.js +6 -6
  144. package/dist/workspace/cleanupInspection.js +1 -9
  145. package/dist/worktree/managedWorkspace.js +3 -3
  146. package/docs/managed-turn-and-session-runtime.md +50 -7
  147. package/docs/managed-turn-and-session-runtime.zh-CN.md +36 -5
  148. package/docs/observability/README.md +47 -0
  149. package/docs/observability/README.zh-CN.md +37 -0
  150. package/docs/project-refresh.md +9 -0
  151. package/docs/project-refresh.zh-CN.md +8 -0
  152. package/docs/provider-retry.md +35 -0
  153. package/docs/release-workflow.md +70 -214
  154. package/docs/release-workflow.zh-CN.md +53 -157
  155. package/docs/roles-and-configuration.md +30 -0
  156. package/docs/roles-and-configuration.zh-CN.md +20 -0
  157. package/docs/sqlite-control-plane-design.md +48 -289
  158. package/docs/sqlite-control-plane-design.zh-CN.md +37 -53
  159. package/docs/storage-baseline.md +132 -0
  160. package/docs/storage-baseline.zh-CN.md +106 -0
  161. package/docs/task-delivery.md +110 -2
  162. package/docs/task-delivery.zh-CN.md +82 -2
  163. package/docs/task-discovery.md +9 -0
  164. package/docs/task-discovery.zh-CN.md +6 -0
  165. package/docs/testing/verification-levels.md +42 -164
  166. package/docs/testing/verification-levels.zh-CN.md +29 -115
  167. package/i18n/README.zh-CN.md +7 -4
  168. package/package.json +1 -1
  169. package/skills/yui-leader/SKILL.md +11 -0
  170. package/skills/yui-leader/references/execution.md +22 -0
  171. package/skills/yui-leader/references/planning.md +6 -2
  172. package/skills/yui-operator/SKILL.md +45 -13
  173. package/skills/yui-operator/references/task-delivery.md +99 -0
  174. package/skills/yui-runtime/SKILL.md +5 -3
  175. package/skills/yui-runtime/references/publication.md +56 -5
  176. package/skills/yui-runtime/references/recovery.md +12 -2
  177. package/dist/runtime/agentHostCompatibility.js +0 -127
  178. package/dist/storage/migrations/agentFailureContext.js +0 -22
  179. package/dist/storage/migrations/agentRunContract.js +0 -159
  180. package/dist/storage/migrations/artifactsToGit.js +0 -338
  181. package/dist/storage/migrations/collapseWorktreeLayout.js +0 -963
  182. package/dist/storage/migrations/currentInputContract.js +0 -86
  183. package/dist/storage/migrations/currentRuntimeContract.js +0 -228
  184. package/dist/storage/migrations/historicalVerificationPlan.js +0 -35
  185. package/dist/storage/migrations/integrationContinuation.js +0 -105
  186. package/dist/storage/migrations/narrowAgentFailureContext.js +0 -65
  187. package/dist/storage/migrations/notificationOnlyWakes.js +0 -74
  188. package/dist/storage/migrations/removeRuntimeGeneration.js +0 -207
  189. package/dist/storage/migrations/submitIntent.js +0 -126
  190. package/dist/storage/migrations/unifyHomeLayout.js +0 -925
  191. package/dist/storage/migrations/verificationPlanV1.js +0 -162
  192. package/dist/storage/migrations/verificationPolicy.js +0 -74
  193. package/dist/storage/migrations/workItemHistory.js +0 -46
@@ -7,7 +7,7 @@ import WebSocket from "ws";
7
7
  import { YUI_VERSION } from "../version.js";
8
8
  import { AcpStructuredProviderSession } from "./acpSession.js";
9
9
  import { acpDesiredSessionConfiguration } from "./acpSessionConfiguration.js";
10
- import { serializeAgentErrorRaw } from "./agentError.js";
10
+ import { providerDeliveryFailureFrom, serializeAgentErrorRaw } from "./agentError.js";
11
11
  import { unsupportedAgentRunConfiguration } from "./agentRunConfiguration.js";
12
12
  import { codexAppServerErrorIsMissing, CodexAppServerRequestError, CodexAppServerRuntime, codexClientInitialization, codexGoalNotification, codexTurnInput, codexTurnOutput } from "./codexAppServerRuntime.js";
13
13
  import { JsonLineChannel, PROVIDER_MESSAGE_MAX_BYTES, terminateProcessGroup } from "./jsonLineChannel.js";
@@ -65,6 +65,7 @@ export async function startStructuredProviderSession(payload, input = {}) {
65
65
  ? {}
66
66
  : { nativeSessionId: control.nativeSessionId }),
67
67
  ...(input.onTerminal === undefined ? {} : { onTerminal: input.onTerminal }),
68
+ ...(input.onDiagnostic === undefined ? {} : { onDiagnostic: input.onDiagnostic }),
68
69
  mirror
69
70
  });
70
71
  return Object.freeze({ session });
@@ -79,7 +80,7 @@ export async function startStructuredProviderSession(payload, input = {}) {
79
80
  goal: opened.goal
80
81
  });
81
82
  }
82
- const session = await ClaudeStructuredProviderSession.open(child, exit, processInstanceId, control, input.onAccepted, input.onTerminal, input.onGoal, input.onActivity, mirror);
83
+ const session = await ClaudeStructuredProviderSession.open(child, exit, processInstanceId, control, input.onAccepted, input.onTerminal, input.onGoal, input.onActivity, input.onDiagnostic, mirror);
83
84
  return Object.freeze({ session });
84
85
  }
85
86
  catch (error) {
@@ -325,6 +326,7 @@ class CodexStructuredProviderSession {
325
326
  onGoal;
326
327
  onInput;
327
328
  onActivity;
329
+ mirror;
328
330
  nativeAccountHome;
329
331
  #turnAttempts = new Map();
330
332
  adapterId = "codex";
@@ -335,7 +337,7 @@ class CodexStructuredProviderSession {
335
337
  #bufferedStarts = [];
336
338
  #bufferedTerminals = [];
337
339
  #bufferedActivities = [];
338
- constructor(child, exit, processInstanceId, conversationId, runtime, onStarted, onTerminal, onGoal, onInput, onActivity, nativeAccountHome) {
340
+ constructor(child, exit, processInstanceId, conversationId, runtime, onStarted, onTerminal, onGoal, onInput, onActivity, mirror, nativeAccountHome) {
339
341
  this.child = child;
340
342
  this.exit = exit;
341
343
  this.processInstanceId = processInstanceId;
@@ -346,6 +348,7 @@ class CodexStructuredProviderSession {
346
348
  this.onGoal = onGoal;
347
349
  this.onInput = onInput;
348
350
  this.onActivity = onActivity;
351
+ this.mirror = mirror;
349
352
  this.nativeAccountHome = nativeAccountHome;
350
353
  }
351
354
  static async open(child, exit, processInstanceId, payload, control, onStarted, onTerminal, onGoal, onInput, onActivity, mirror) {
@@ -387,7 +390,7 @@ class CodexStructuredProviderSession {
387
390
  name: control.sessionTitle
388
391
  });
389
392
  }
390
- const session = new CodexStructuredProviderSession(child, exit, processInstanceId, conversationId, runtime, onStarted, onTerminal, onGoal, onInput, onActivity, optionalId(initialized.codexHome));
393
+ const session = new CodexStructuredProviderSession(child, exit, processInstanceId, conversationId, runtime, onStarted, onTerminal, onGoal, onInput, onActivity, mirror, optionalId(initialized.codexHome));
391
394
  session.#activeTurnId = resumedActiveTurnId;
392
395
  const ownedTurn = control.kind === "restore" ? control.ownedTurn : undefined;
393
396
  session.#clientOwnedTurnId = ownedTurn?.turnId;
@@ -445,9 +448,21 @@ class CodexStructuredProviderSession {
445
448
  #observeMessage(message, emit) {
446
449
  const method = typeof message.method === "string" ? message.method : "";
447
450
  const params = object(message.params) ?? {};
448
- if (optionalId(params.threadId) !== this.conversationId)
451
+ const threadId = optionalId(params.threadId);
452
+ if (threadId !== this.conversationId) {
453
+ if (threadId === undefined && (method === "turn/started" || method === "turn/completed")) {
454
+ this.mirror("stderr", `Codex protocol: ${method} has no thread identity; ignored.\n`);
455
+ }
449
456
  return undefined;
450
- const goal = codexGoalNotification({ method, params });
457
+ }
458
+ let goal;
459
+ try {
460
+ goal = codexGoalNotification({ method, params });
461
+ }
462
+ catch {
463
+ this.mirror("stderr", "Codex protocol: invalid Goal notification; ignored.\n");
464
+ return undefined;
465
+ }
451
466
  if (goal !== undefined) {
452
467
  if (emit)
453
468
  this.onGoal?.(goal);
@@ -456,17 +471,20 @@ class CodexStructuredProviderSession {
456
471
  if (emit && (method === "item/started" || method === "item/completed"
457
472
  || method === "item/agentMessage/delta" || method === "item/reasoning/summaryTextDelta")) {
458
473
  const item = object(params.item);
459
- const id = optionalId(item?.id) ?? optionalId(params.itemId);
474
+ const delta = method === "item/agentMessage/delta" || method === "item/reasoning/summaryTextDelta";
475
+ const id = optionalId(delta ? params.itemId : item?.id);
460
476
  const nativeTurnId = optionalId(params.turnId);
461
- const tool = ["commandExecution", "mcpToolCall", "dynamicToolCall", "fileChange"].includes(String(item?.type));
462
- const model = ["agentMessage", "reasoning"].includes(String(item?.type)) || method.endsWith("Delta") || method.endsWith("/delta");
463
- if (id !== undefined && nativeTurnId !== undefined && (tool || model)) {
477
+ const tool = typeof item?.type === "string"
478
+ && ["commandExecution", "mcpToolCall", "dynamicToolCall", "fileChange"].includes(item.type);
479
+ const model = delta || item?.type === "agentMessage" || item?.type === "reasoning";
480
+ const phase = model ? "model" : tool ? codexToolPhase(item, method === "item/started") : undefined;
481
+ if (tool && phase === undefined) {
482
+ this.mirror("stderr", "Codex protocol: tool item has no valid lifecycle status; ignored.\n");
483
+ }
484
+ if (id !== undefined && nativeTurnId !== undefined && phase !== undefined) {
464
485
  const activity = {
465
486
  conversationId: this.conversationId, nativeSessionId: this.conversationId,
466
- nativeTurnId, id, observedAt: new Date().toISOString(),
467
- phase: model ? "model" : method === "item/started" ? "started"
468
- : item?.status === "failed" || (typeof item?.exitCode === "number" && item.exitCode !== 0)
469
- ? "failed" : "completed"
487
+ nativeTurnId, id, observedAt: new Date().toISOString(), phase
470
488
  };
471
489
  if (this.#submissionPending)
472
490
  this.#bufferedActivities.push(activity);
@@ -486,10 +504,10 @@ class CodexStructuredProviderSession {
486
504
  return undefined;
487
505
  }
488
506
  if (method === "turn/started") {
489
- const turnId = nestedId(params, "turn") ?? optionalId(params.turnId);
490
- if (turnId !== undefined) {
507
+ const turn = object(params.turn);
508
+ const turnId = optionalId(turn?.id);
509
+ if (turnId !== undefined && turn?.status === "inProgress") {
491
510
  this.#activeTurnId = turnId;
492
- const turn = object(params.turn) ?? {};
493
511
  const input = codexTurnInput(turn);
494
512
  const started = {
495
513
  conversationId: this.conversationId,
@@ -503,14 +521,20 @@ class CodexStructuredProviderSession {
503
521
  else if (emit)
504
522
  this.#emitStarted(started);
505
523
  }
524
+ else {
525
+ this.mirror("stderr", "Codex protocol: turn/started has no valid Turn identity/status; ignored.\n");
526
+ }
506
527
  return undefined;
507
528
  }
508
529
  if (method !== "turn/completed")
509
530
  return undefined;
510
- const turn = object(params.turn) ?? {};
511
- const nativeTurnId = optionalId(turn.id) ?? optionalId(params.turnId);
512
- if (nativeTurnId === undefined)
531
+ const turn = object(params.turn);
532
+ const nativeTurnId = optionalId(turn?.id);
533
+ if (nativeTurnId === undefined || turn === null
534
+ || (turn.status !== "completed" && turn.status !== "failed" && turn.status !== "interrupted")) {
535
+ this.mirror("stderr", "Codex protocol: turn/completed has no valid terminal Turn identity/status; ignored.\n");
513
536
  return undefined;
537
+ }
514
538
  const status = turn.status === "failed"
515
539
  ? "failed"
516
540
  : turn.status === "interrupted" ? "cancelled" : "completed";
@@ -680,6 +704,7 @@ class ClaudeStructuredProviderSession {
680
704
  conversationId;
681
705
  channel;
682
706
  onGoal;
707
+ mirror;
683
708
  adapterId = "claude";
684
709
  get ownedProcessId() { return this.child.pid; }
685
710
  #activeAttemptId;
@@ -689,22 +714,33 @@ class ClaudeStructuredProviderSession {
689
714
  #openToolIds = new Set();
690
715
  #resultAttempts = new Map();
691
716
  #lastGoalKey;
692
- constructor(child, exit, processInstanceId, conversationId, channel, onGoal) {
717
+ constructor(child, exit, processInstanceId, conversationId, channel, onGoal, mirror) {
693
718
  this.child = child;
694
719
  this.exit = exit;
695
720
  this.processInstanceId = processInstanceId;
696
721
  this.conversationId = conversationId;
697
722
  this.channel = channel;
698
723
  this.onGoal = onGoal;
724
+ this.mirror = mirror;
699
725
  }
700
- static async open(child, exit, processInstanceId, control, onAccepted, onTerminal, onGoal, onActivity, mirror) {
701
- const channel = new JsonLineChannel(child, mirror);
726
+ static async open(child, exit, processInstanceId, control, onAccepted, onTerminal, onGoal, onActivity, onDiagnostic, mirror) {
702
727
  const nativeSessionId = control.nativeSessionId;
703
728
  if (nativeSessionId === undefined) {
704
729
  throw new Error("Managed Claude launch requires a preallocated native Session id.");
705
730
  }
706
- const session = new ClaudeStructuredProviderSession(child, exit, processInstanceId, nativeSessionId, channel, onGoal);
707
- channel.onMessage((message) => session.#receive(message, onTerminal, onAccepted, onActivity));
731
+ let receivingAttemptId;
732
+ const channel = new JsonLineChannel(child, mirror, error => onDiagnostic?.({
733
+ nativeSessionId,
734
+ ...((receivingAttemptId ?? session.#activeAttemptId) === undefined
735
+ ? {} : { attemptId: receivingAttemptId ?? session.#activeAttemptId }),
736
+ failure: providerDeliveryFailureFrom(error, { phase: "turn-reconcile", inputDisposition: "unknown" })
737
+ }));
738
+ const session = new ClaudeStructuredProviderSession(child, exit, processInstanceId, nativeSessionId, channel, onGoal, mirror);
739
+ channel.onMessage((message) => {
740
+ receivingAttemptId = session.#activeAttemptId;
741
+ session.#receive(message, onTerminal, onAccepted, onActivity);
742
+ receivingAttemptId = undefined;
743
+ });
708
744
  // This client owns the whole Claude execution process, unlike a Codex
709
745
  // proxy. An exit without a result ends the exact local input as failure,
710
746
  // not as continuing work merely because the supervising Host is alive.
@@ -855,24 +891,35 @@ class ClaudeStructuredProviderSession {
855
891
  }
856
892
  return;
857
893
  }
858
- if (message.type !== "result"
859
- || optionalId(message.session_id) !== this.conversationId)
894
+ if (message.type !== "result")
860
895
  return;
896
+ const sessionId = optionalId(message.session_id);
897
+ if (sessionId !== this.conversationId) {
898
+ if (sessionId === undefined)
899
+ this.mirror("stderr", "Claude protocol: result has no Session identity; ignored.\n");
900
+ return;
901
+ }
861
902
  // A result UUID identifies this message, not the Provider execution.
862
903
  // Retain its local association so a delayed duplicate cannot be assigned
863
904
  // to a successor request on the same long-lived process.
864
905
  const resultId = optionalId(message.uuid);
865
- const priorAttempt = resultId === undefined ? undefined : this.#resultAttempts.get(resultId);
906
+ const subtype = message.subtype;
907
+ const failed = subtype === "success" ? message.is_error
908
+ : ["error_during_execution", "error_max_turns", "error_max_budget_usd",
909
+ "error_max_structured_output_retries"].includes(String(subtype)) ? true : undefined;
910
+ if (resultId === undefined || typeof message.is_error !== "boolean" || failed === undefined) {
911
+ this.mirror("stderr", "Claude protocol: result has no valid identity/status; ignored.\n");
912
+ return;
913
+ }
914
+ const priorAttempt = this.#resultAttempts.get(resultId);
866
915
  const attemptId = priorAttempt ?? this.#activeAttemptId;
867
916
  if (attemptId === undefined)
868
917
  return;
869
- if (resultId !== undefined)
870
- this.#resultAttempts.set(resultId, attemptId);
918
+ this.#resultAttempts.set(resultId, attemptId);
871
919
  if (attemptId === this.#activeAttemptId) {
872
920
  this.#activeAttemptId = undefined;
873
921
  this.#openToolIds.clear();
874
922
  }
875
- const failed = message.is_error === true || message.subtype === "error_during_execution";
876
923
  const result = typeof message.result === "string" && message.result.length > 0
877
924
  ? message.result
878
925
  : providerErrorEvidence(message).error;
@@ -891,64 +938,44 @@ class ClaudeStructuredProviderSession {
891
938
  });
892
939
  }
893
940
  }
941
+ function codexToolPhase(item, started) {
942
+ if (started)
943
+ return item.status === "inProgress" ? "started" : undefined;
944
+ if (item.status === "failed")
945
+ return "failed";
946
+ if (item.status === "declined"
947
+ && (item.type === "commandExecution" || item.type === "fileChange"))
948
+ return "failed";
949
+ if (item.status !== "completed")
950
+ return undefined;
951
+ if (item.type === "commandExecution" && typeof item.exitCode === "number" && item.exitCode !== 0) {
952
+ return "failed";
953
+ }
954
+ if (item.type === "dynamicToolCall" && item.success === false)
955
+ return "failed";
956
+ return "completed";
957
+ }
894
958
  function claudeActiveGoal(message, conversationId) {
895
- if (!Object.hasOwn(message, "active_goal"))
959
+ if (message.type !== "active_goal" || optionalId(message.session_id) !== conversationId)
896
960
  return undefined;
897
- if (message.active_goal === null)
961
+ if (message.value === null)
898
962
  return null;
899
- const raw = object(message.active_goal);
963
+ const raw = object(message.value);
900
964
  if (raw === null)
901
965
  return undefined;
902
- const objective = typeof raw.objective === "string" ? raw.objective.trim() : "";
966
+ const objective = typeof raw.condition === "string" ? raw.condition.trim() : "";
903
967
  if (objective.length === 0)
904
968
  return undefined;
905
- const status = providerGoalStatus(raw.status);
906
- if (status === undefined)
907
- return undefined;
908
- const tokenBudget = positiveOptionalInteger(raw.token_budget ?? raw.tokenBudget);
909
969
  return Object.freeze({
910
970
  conversationId,
911
- status,
971
+ // Claude emits a live goal or clears it. There is no Codex-style Goal
972
+ // status/budget/Turn field on this event, and clearing is not success.
973
+ status: "active",
912
974
  objective,
913
- updatedAt: providerTimestamp(raw.updated_at ?? raw.updatedAt),
914
- ...(optionalId(raw.turn_id ?? raw.turnId) === undefined
915
- ? {}
916
- : { nativeTurnId: optionalId(raw.turn_id ?? raw.turnId) }),
917
- ...(tokenBudget === undefined ? {} : { tokenBudget })
975
+ // set_at is creation time, not a last-update timestamp.
976
+ updatedAt: new Date().toISOString()
918
977
  });
919
978
  }
920
- function providerGoalStatus(value) {
921
- switch (value) {
922
- case "active":
923
- case "paused":
924
- case "blocked":
925
- case "complete":
926
- return value;
927
- case "usageLimited":
928
- case "usage_limited":
929
- case "usage-limited":
930
- return "usage-limited";
931
- case "budgetLimited":
932
- case "budget_limited":
933
- case "budget-limited":
934
- return "budget-limited";
935
- default:
936
- return undefined;
937
- }
938
- }
939
- function providerTimestamp(value) {
940
- if (typeof value === "string" && Number.isFinite(Date.parse(value))) {
941
- return new Date(value).toISOString();
942
- }
943
- if (Number.isSafeInteger(value) && value >= 0) {
944
- const epoch = value;
945
- return new Date(epoch < 1_000_000_000_000 ? epoch * 1_000 : epoch).toISOString();
946
- }
947
- return new Date().toISOString();
948
- }
949
- function positiveOptionalInteger(value) {
950
- return Number.isSafeInteger(value) && value > 0 ? value : undefined;
951
- }
952
979
  function childExit(child, processInstanceId) {
953
980
  return new Promise((resolvePromise, reject) => {
954
981
  child.once("error", reject);
@@ -971,10 +998,8 @@ function object(value) {
971
998
  : null;
972
999
  }
973
1000
  function optionalId(value) {
974
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
975
- }
976
- function nestedId(value, key) {
977
- return optionalId(object(value[key])?.id);
1001
+ return typeof value === "string" && !value.includes("\0") && value.length > 0
1002
+ && value.trim() === value ? value : undefined;
978
1003
  }
979
1004
  function providerErrorEvidence(value) {
980
1005
  const error = object(value);
@@ -154,7 +154,7 @@ export function createTaskRuntimeIsolationDescriptor(input) {
154
154
  const portPreference = ports(input.policy?.portPreference ?? [], "Port preference");
155
155
  const portAllocations = allocations(input.policy?.portAllocations ?? []);
156
156
  return Object.freeze({
157
- schemaVersion: 2,
157
+ schemaVersion: 1,
158
158
  kind: "yui-task-runtime-isolation",
159
159
  taskId,
160
160
  workspace: Object.freeze({ owner, root: canonicalPath(workspace.root, "Workspace root") }),
@@ -181,7 +181,7 @@ export function parseTaskRuntimeIsolationDescriptor(serialized) {
181
181
  if (!isRecord(value) || value.kind !== "yui-task-runtime-isolation") {
182
182
  throw new Error(`Expected yui-task-runtime-isolation descriptor; found ${isRecord(value) && typeof value.kind === "string" ? value.kind : "unknown"}.`);
183
183
  }
184
- if (value.schemaVersion !== 2) {
184
+ if (value.schemaVersion !== 1) {
185
185
  throw new Error("Task runtime isolation descriptor schema version is invalid.");
186
186
  }
187
187
  const workspace = requireRecord(value.workspace, "Task runtime workspace");
@@ -189,7 +189,7 @@ export function parseTaskRuntimeIsolationDescriptor(serialized) {
189
189
  const external = requireRecord(value.externalCapabilities, "Task runtime external capabilities");
190
190
  const owner = taskRuntimeWorkspaceOwner(requireRecord(workspace.owner, "Task runtime workspace owner"));
191
191
  const descriptor = {
192
- schemaVersion: 2,
192
+ schemaVersion: 1,
193
193
  kind: "yui-task-runtime-isolation",
194
194
  taskId: requireIdentity(value.taskId, "Task id"),
195
195
  workspace: {
@@ -249,8 +249,8 @@ export class TmuxSessionHost {
249
249
  const yuiHome = planned.launch.env.YUI_HOME;
250
250
  const childLifecycle = planned.launch.childLifecycle;
251
251
  // Global Codex retains the native TUI inside a thin Host that acknowledges
252
- // its own App Server startup response. Existing live TUIs (including
253
- // 0.15.0 Sessions) remain directly attachable without replacing them.
252
+ // its own App Server startup response. Current live TUIs remain directly
253
+ // attachable without replacing their native conversation.
254
254
  if (reuseInteractivePane
255
255
  || (!interactiveCodex && (yuiHome === undefined
256
256
  || childLifecycle === undefined
@@ -310,7 +310,7 @@ export class TmuxSessionHost {
310
310
  throw new Error("Managed Task Agent Host launch is missing its Session Manifest.");
311
311
  }
312
312
  const reservation = broker.reserve(Object.freeze({
313
- schemaVersion: 2,
313
+ schemaVersion: 1,
314
314
  ...(request.runId === undefined ? {} : { startupRunId: request.runId }),
315
315
  command: planned.launch.command,
316
316
  args: [...planned.launch.args],
@@ -1,5 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { serializeRunInputEnvelope } from "../context/runInputContract.js";
3
+ import { readRunContextSnapshot } from "../context/runContextPack.js";
3
4
  import { roleSessionMayContinue, sameEffectiveLaunch } from "../executor/effectiveLaunch.js";
4
5
  import { RuntimeLifecycleBusyError } from "../runtime/lifecycleReservation.js";
5
6
  import { managedProviderTurnId } from "../runtime/providerRuntimeIdentity.js";
@@ -121,6 +122,9 @@ async function deliverActiveRun(store, delivery, task, role, run, now) {
121
122
  let prepared;
122
123
  let submitted = false;
123
124
  try {
125
+ // Validate the dispatch contract before starting any Provider resources.
126
+ readRunContextSnapshot(store, run);
127
+ const text = serializeRunInputEnvelope(runInputEnvelope(run));
124
128
  const nativeSessionId = mode === "resume"
125
129
  ? requireResumeSession(role, run, existingSession)
126
130
  : undefined;
@@ -172,7 +176,7 @@ async function deliverActiveRun(store, delivery, task, role, run, now) {
172
176
  const outcome = await delivery.sendOnce({
173
177
  delivery: ready,
174
178
  receiptId: attemptId,
175
- text: serializeRunInputEnvelope(runInputEnvelope(run))
179
+ text
176
180
  });
177
181
  if (outcome.status === "pending") {
178
182
  // The original Host request is still in flight. Its durable submitting
@@ -1,6 +1,6 @@
1
1
  import { createOperatorBatchPresentation } from "../interaction/operatorPresentation.js";
2
2
  import { mailboxHasWork, nextPendingBatch } from "../coordination/workMailbox.js";
3
- export async function processOperatorInputNotifications(store, delivery, selection, now = new Date()) {
3
+ export async function processOperatorInputNotifications(store, selection, now = new Date()) {
4
4
  if (selection !== undefined && !selection.full && !selection.operator)
5
5
  return [];
6
6
  const targetMailbox = { kind: "operator" };
@@ -35,30 +35,20 @@ export async function processOperatorInputNotifications(store, delivery, selecti
35
35
  store.completeWorkMailbox(targetMailbox, processing.batchId);
36
36
  return [];
37
37
  }
38
- const target = store.getOperatorDeliveryTarget();
39
- if (target === null || delivery.notifyOperatorInputOnce === undefined) {
40
- const reason = target === null ? "operator-unavailable" : "delivery-unsupported";
41
- store.releaseWorkMailbox(targetMailbox, processing.batchId);
42
- return attentions.map((attention) => skipped(attention, reason));
43
- }
44
38
  try {
45
39
  const presentation = createOperatorBatchPresentation(processing.batchId, attentions.map(toPresentationItem));
46
- const outcome = await delivery.notifyOperatorInputOnce({
47
- ...target,
40
+ const outcome = store.queueOperatorNotification({
41
+ batchId: processing.batchId,
48
42
  receiptId: presentation.receiptId,
49
43
  text: presentation.text
50
- });
51
- if (outcome === "unavailable" || outcome === "not-ready") {
44
+ }, now);
45
+ if (outcome.status === "unavailable") {
52
46
  store.releaseWorkMailbox(targetMailbox, processing.batchId);
53
- const reason = outcome === "unavailable" ? "operator-unavailable" : "operator-not-ready";
54
- return attentions.map((attention) => skipped(attention, reason));
47
+ return attentions.map((attention) => skipped(attention, "operator-unavailable"));
55
48
  }
56
- if (outcome === "sent")
57
- store.markOperatorRunStarted(now);
58
- store.completeWorkMailbox(targetMailbox, processing.batchId);
59
49
  return attentions.map((attention) => ({
60
50
  ...attentionIdentity(attention),
61
- status: outcome
51
+ ...outcome
62
52
  }));
63
53
  }
64
54
  catch (error) {
@@ -1,7 +1,7 @@
1
1
  import { requireIdentity, requirePositiveInteger, requireText, requireTimestamp } from "../domain/validation.js";
2
2
  import { TASK_RECORD_ID_PREFIXES } from "../task/taskRecordReference.js";
3
3
  import { copyRef } from "../coordination/workMailbox.js";
4
- export const CURRENT_TASK_WAKE_SCHEMA_VERSION = 2;
4
+ export const CURRENT_TASK_WAKE_SCHEMA_VERSION = 1;
5
5
  export function createTaskWake(input) {
6
6
  if (Object.hasOwn(input, "runId"))
7
7
  throw new Error("A notification wake cannot dispatch an AgentRun.");