@zq-silk/yui 0.13.8 → 0.13.9

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 (67) hide show
  1. package/README.md +9 -8
  2. package/dist/cli/commandCatalog.js +21 -2
  3. package/dist/cli.js +42 -13
  4. package/dist/commands/agentCommands.js +1 -1
  5. package/dist/commands/configCommands.js +1 -86
  6. package/dist/commands/executionAuditCommands.js +17 -16
  7. package/dist/commands/globalRoleCommands.js +4 -4
  8. package/dist/commands/sessionCommands.js +2 -6
  9. package/dist/commands/taskActor.js +1 -2
  10. package/dist/commands/taskCommands.js +92 -9
  11. package/dist/commands/taskRoleRuntimeStatus.js +3 -3
  12. package/dist/config/configCatalog.js +1 -6
  13. package/dist/config/yuiConfig.js +0 -79
  14. package/dist/controller/clientRuntime.js +40 -3
  15. package/dist/controller/controller.js +29 -52
  16. package/dist/controller/fileSchedulerStoreAdapter.js +305 -1056
  17. package/dist/controller/runtime.js +12 -5
  18. package/dist/controller/runtimeHookRunFence.js +3 -9
  19. package/dist/controller/runtimeLaunchCoordinator.js +44 -67
  20. package/dist/controller/structuredProviderObservation.js +18 -5
  21. package/dist/coordination/workMailbox.js +4 -4
  22. package/dist/execution/executionHealth.js +1 -1
  23. package/dist/executor/agentExecutor.js +92 -68
  24. package/dist/executor/executorRegistry.js +8 -20
  25. package/dist/executor/fileRoleLaunchPlanner.js +24 -90
  26. package/dist/executor/turnCompletion.js +5 -5
  27. package/dist/lifecycle/exactRunTerminalization.js +1 -1
  28. package/dist/observability/executionAudit.js +40 -94
  29. package/dist/operator/operatorSessionHistory.js +7 -5
  30. package/dist/role/role.js +1 -1
  31. package/dist/run/agentRun.js +4 -54
  32. package/dist/runtime/agentDriver.js +2 -0
  33. package/dist/runtime/agentError.js +114 -0
  34. package/dist/runtime/agentHost.js +55 -82
  35. package/dist/runtime/builtinAgentDrivers.js +21 -9
  36. package/dist/runtime/builtinAgentErrorMappers.js +150 -0
  37. package/dist/runtime/exactControlPlane.js +6 -12
  38. package/dist/runtime/index.js +0 -1
  39. package/dist/runtime/launchBroker.js +5 -19
  40. package/dist/runtime/lifecycleReservation.js +20 -4
  41. package/dist/runtime/providerRuntimeIdentity.js +3 -2
  42. package/dist/runtime/runtimeBinding.js +0 -27
  43. package/dist/runtime/runtimeObservation.js +7 -16
  44. package/dist/runtime/runtimeSessionCandidate.js +3 -10
  45. package/dist/runtime/sessionLaunchRequest.js +1 -2
  46. package/dist/runtime/sessionReconciliation.js +2 -2
  47. package/dist/runtime/structuredProviderHost.js +44 -79
  48. package/dist/runtime/taskRuntimeIsolation.js +0 -7
  49. package/dist/runtime/tmuxAdapters.js +6 -49
  50. package/dist/scheduler/activeRoleRunDelivery.js +218 -168
  51. package/dist/scheduler/leaderWakeupProcessor.js +126 -86
  52. package/dist/scheduler/roleRunLiveness.js +4 -1
  53. package/dist/scheduler/roleRunStall.js +7 -11
  54. package/dist/scheduler/wakeReason.js +4 -0
  55. package/dist/storage/migration/productionRegistry.js +332 -0
  56. package/dist/storage/sqliteSchema.js +54 -2
  57. package/dist/storage/sqliteStore.js +11 -44
  58. package/dist/storage/taskStore.js +7 -35
  59. package/package.json +1 -1
  60. package/skills/yui-leader/SKILL.md +30 -8
  61. package/skills/yui-operator/SKILL.md +14 -6
  62. package/skills/yui-runtime/SKILL.md +6 -4
  63. package/dist/lifecycle/providerErrorClass.js +0 -152
  64. package/dist/run/providerRetry.js +0 -226
  65. package/dist/run/providerRetryConfig.js +0 -27
  66. package/dist/runtime/providerErrorCodes.js +0 -278
  67. package/dist/runtime/providerRecoveryDecision.js +0 -55
@@ -5,27 +5,6 @@ export function createRuntimeBinding(input) {
5
5
  const hostCreated = input.hostCreated === undefined
6
6
  ? undefined
7
7
  : requireBoolean(input.hostCreated, "Runtime host-created flag");
8
- const initialTurnRunId = input.initialTurnRunId === undefined
9
- ? undefined
10
- : requireSafeIdentity(input.initialTurnRunId, "Initial Turn Run id");
11
- const initialTurnDeliveryUnknownRunId = input.initialTurnDeliveryUnknownRunId === undefined
12
- ? undefined
13
- : requireSafeIdentity(input.initialTurnDeliveryUnknownRunId, "Delivery-unknown initial Turn Run id");
14
- const initialTurnRejectedRunId = input.initialTurnRejectedRunId === undefined
15
- ? undefined
16
- : requireSafeIdentity(input.initialTurnRejectedRunId, "Rejected initial Turn Run id");
17
- const initialTurnBusyRunId = input.initialTurnBusyRunId === undefined
18
- ? undefined
19
- : requireSafeIdentity(input.initialTurnBusyRunId, "Busy initial Turn Run id");
20
- if ([
21
- initialTurnRunId,
22
- initialTurnDeliveryUnknownRunId,
23
- initialTurnBusyRunId,
24
- initialTurnRejectedRunId
25
- ]
26
- .filter((value) => value !== undefined).length > 1) {
27
- throw new TypeError("Runtime binding must report at most one initial Turn outcome.");
28
- }
29
8
  return {
30
9
  id: requireSafeIdentity(input.id, "Runtime binding id"),
31
10
  launchId: requireSafeIdentity(input.launchId, "Launch id"),
@@ -34,12 +13,6 @@ export function createRuntimeBinding(input) {
34
13
  adapterId: requireSafeIdentity(input.adapterId, "Agent adapter id"),
35
14
  hostRef: requireText(input.hostRef, "Session host reference"),
36
15
  ...(hostCreated === undefined ? {} : { hostCreated }),
37
- ...(initialTurnRunId === undefined ? {} : { initialTurnRunId }),
38
- ...(initialTurnDeliveryUnknownRunId === undefined
39
- ? {}
40
- : { initialTurnDeliveryUnknownRunId }),
41
- ...(initialTurnBusyRunId === undefined ? {} : { initialTurnBusyRunId }),
42
- ...(initialTurnRejectedRunId === undefined ? {} : { initialTurnRejectedRunId }),
43
16
  ...(input.nativeSessionId === undefined
44
17
  ? {}
45
18
  : { nativeSessionId: requireText(input.nativeSessionId, "Native session id") }),
@@ -1,5 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { requireDriverId } from "./agentDriver.js";
3
+ import { isStandardAgentError } from "./agentError.js";
3
4
  export const RUNTIME_OBSERVATION_TASK_EVENT = "runtime.observation";
4
5
  /**
5
6
  * Numeric usage and value-less partial request boundaries are both durable
@@ -435,7 +436,7 @@ export function runtimeObservationSemanticKey(input) {
435
436
  ...continuationIdentity,
436
437
  fence.continuationId ?? fence.nativeTurnId ?? "none",
437
438
  input.kind,
438
- input.payload?.outcome ?? input.payload?.failure?.code ?? "terminal",
439
+ input.payload?.outcome ?? input.payload?.failure?.error.code ?? "terminal",
439
440
  input.kind === "continuation.settled" ? input.payload?.resultRef ?? "none" : "none",
440
441
  input.kind === "turn.failed" && input.payload?.failure?.runTerminal === true
441
442
  ? "run-terminal"
@@ -494,21 +495,17 @@ function normalizeFailure(input) {
494
495
  if (input === null || typeof input !== "object" || Array.isArray(input)) {
495
496
  throw new Error("Runtime failure evidence must be an object.");
496
497
  }
498
+ if (!isStandardAgentError(input.error)) {
499
+ throw new Error("Runtime failure requires a standard Agent error.");
500
+ }
497
501
  return Object.freeze({
498
- ...(input.errorCode === undefined ? {} : { errorCode: input.errorCode }),
499
- code: requireText(input.code, "Runtime failure code"),
500
- ...(input.details === undefined
501
- ? {}
502
- : { details: requireText(input.details, "Runtime failure details") }),
502
+ error: Object.freeze({ ...input.error }),
503
503
  ...(input.lastOutput === undefined
504
504
  ? {}
505
505
  : { lastOutput: requireText(input.lastOutput, "Runtime failure last output") }),
506
506
  ...(input.runTerminal === undefined
507
507
  ? {}
508
- : { runTerminal: requireBoolean(input.runTerminal, "Runtime failure runTerminal") }),
509
- ...(input.retryAfterMs === undefined
510
- ? {}
511
- : { retryAfterMs: requirePositiveMilliseconds(input.retryAfterMs) })
508
+ : { runTerminal: requireBoolean(input.runTerminal, "Runtime failure runTerminal") })
512
509
  });
513
510
  }
514
511
  function requireBoolean(value, label) {
@@ -516,12 +513,6 @@ function requireBoolean(value, label) {
516
513
  throw new Error(`${label} must be boolean.`);
517
514
  return value;
518
515
  }
519
- function requirePositiveMilliseconds(value) {
520
- if (!Number.isSafeInteger(value) || value <= 0) {
521
- throw new Error("Runtime failure retryAfterMs must be a positive safe integer.");
522
- }
523
- return value;
524
- }
525
516
  function validateUsage(input) {
526
517
  if (!["cumulative-session", "request-context", "remaining-context"].includes(input.semantics)) {
527
518
  throw new Error("Runtime usage semantics are invalid.");
@@ -1,14 +1,8 @@
1
1
  import { activeRoleAgentSession } from "../executor/agentExecutor.js";
2
- /** Exact completed-Task cleanup contract shared by projection writers/readers. */
3
- export function runtimeSessionRequiresCleanup(input) {
4
- if (input.status === "stopped" || input.status === "broken")
5
- return false;
6
- return input.status === "running" || input.launchId !== undefined;
7
- }
8
- /** Projects only the current active Agent Session; stopped history disappears. */
2
+ /** Projects only the current active Agent Session; ended history disappears. */
9
3
  export function projectRuntimeSessionCandidate(sessions) {
10
4
  const active = activeRoleAgentSession(sessions);
11
- if (active === null || active.status === "stopped")
5
+ if (active === null || active.status === "ended")
12
6
  return null;
13
7
  return {
14
8
  owner: sessions.owner.scope === "task"
@@ -22,9 +16,8 @@ export function projectRuntimeSessionCandidate(sessions) {
22
16
  adapterId: active.adapterId,
23
17
  nativeSessionId: active.nativeSessionId,
24
18
  ...(active.launchId === undefined ? {} : { launchId: active.launchId }),
25
- status: active.status,
26
19
  sessionUpdatedAt: active.updatedAt,
27
- cleanupRequired: runtimeSessionRequiresCleanup(active)
20
+ cleanupRequired: active.launchId !== undefined
28
21
  };
29
22
  }
30
23
  /** Deterministic owner order shared by all storage backends. */
@@ -18,8 +18,7 @@ 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
22
- || runtimeIsolation.generation.runId !== input.runId)) {
21
+ || runtimeIsolation.generation.launchId !== input.launchId)) {
23
22
  throw new TypeError("Session launch request does not match its Task runtime isolation descriptor.");
24
23
  }
25
24
  const common = {
@@ -41,14 +41,14 @@ function reconcileOne(record, input) {
41
41
  mismatch = "identity-conflict";
42
42
  }
43
43
  else if (physical?.alive === true) {
44
- if (durable === undefined || durable.status === "stopped" || durable.status === "broken") {
44
+ if (durable === undefined || durable.status === "ended") {
45
45
  mismatch = "durable-terminal-physical-live";
46
46
  }
47
47
  }
48
48
  else if (physical === undefined) {
49
49
  verificationGap = "/proc identity unavailable";
50
50
  }
51
- else if (durable !== undefined && durable.status === "running") {
51
+ else if (durable !== undefined && durable.status === "active") {
52
52
  mismatch = "durable-live-physical-absent";
53
53
  }
54
54
  const terminalTask = taskStatus === "completed"
@@ -3,6 +3,7 @@ import { randomUUID } from "node:crypto";
3
3
  import { Duplex } from "node:stream";
4
4
  import WebSocket from "ws";
5
5
  import { CodexAppServerRequestError, CodexAppServerRuntime, codexAppServerErrorIsMissing } from "./codexAppServerRuntime.js";
6
+ import { serializeAgentErrorRaw } from "./agentError.js";
6
7
  import { PROVIDER_ACCEPT_TIMEOUT_MS } from "./runtimeDeadlines.js";
7
8
  import { YUI_VERSION } from "../version.js";
8
9
  const PROVIDER_MESSAGE_MAX_BYTES = 16 * 1024 * 1024;
@@ -399,7 +400,7 @@ class CodexStructuredProviderSession {
399
400
  }
400
401
  const session = new CodexStructuredProviderSession(child, exit, processInstanceId, conversationId, runtime, onTerminal);
401
402
  session.#activeTurnId = resumedActiveTurnId;
402
- const ownedTurn = control.kind === "ensure" ? control.ownedTurn : undefined;
403
+ const ownedTurn = control.kind === "restore" ? control.ownedTurn : undefined;
403
404
  session.#clientOwnedTurnId = ownedTurn?.turnId;
404
405
  stopOpeningBuffer();
405
406
  let recoveredTerminal;
@@ -426,7 +427,12 @@ class CodexStructuredProviderSession {
426
427
  ? "failed"
427
428
  : recovered.status === "interrupted" ? "cancelled" : "completed",
428
429
  observedAt: new Date().toISOString(),
429
- ...(recovered.error === undefined ? {} : { error: recovered.error })
430
+ ...(recovered.status !== "failed"
431
+ ? {}
432
+ : {
433
+ error: recovered.error ?? "Provider Turn failed.",
434
+ rawError: serializeAgentErrorRaw(recovered)
435
+ })
430
436
  };
431
437
  session.#clientOwnedTurnId = undefined;
432
438
  }
@@ -459,13 +465,16 @@ class CodexStructuredProviderSession {
459
465
  const status = turn.status === "failed"
460
466
  ? "failed"
461
467
  : turn.status === "interrupted" ? "cancelled" : "completed";
468
+ const failure = status === "failed"
469
+ ? providerErrorEvidence(turn.error)
470
+ : undefined;
462
471
  const terminal = {
463
472
  conversationId: this.conversationId,
464
473
  nativeSessionId: this.conversationId,
465
474
  nativeTurnId,
466
475
  status,
467
476
  observedAt: new Date().toISOString(),
468
- ...(status !== "failed" ? {} : { error: providerErrorText(turn.error) })
477
+ ...(failure === undefined ? {} : failure)
469
478
  };
470
479
  if (this.#submissionPending && emit) {
471
480
  this.#bufferedTerminals.push(terminal);
@@ -546,7 +555,6 @@ class ClaudeStructuredProviderSession {
546
555
  channel;
547
556
  adapterId = "claude";
548
557
  #activeTurnId;
549
- #waiter;
550
558
  constructor(child, exit, processInstanceId, conversationId, channel) {
551
559
  this.child = child;
552
560
  this.exit = exit;
@@ -562,14 +570,6 @@ class ClaudeStructuredProviderSession {
562
570
  }
563
571
  const session = new ClaudeStructuredProviderSession(child, exit, processInstanceId, nativeSessionId, channel);
564
572
  channel.onMessage((message) => session.#receive(message, onTerminal));
565
- exit.then(() => {
566
- const waiter = session.#waiter;
567
- if (waiter === undefined)
568
- return;
569
- clearTimeout(waiter.timer);
570
- session.#waiter = undefined;
571
- waiter.reject(new ProviderDeliveryUnknownError("Claude process exited before replaying the submitted user message.", waiter.attemptId));
572
- }).catch(() => { });
573
573
  return session;
574
574
  }
575
575
  get nativeSessionId() {
@@ -579,24 +579,9 @@ class ClaudeStructuredProviderSession {
579
579
  return this.#activeTurnId;
580
580
  }
581
581
  async submitTurn(turn) {
582
- if (this.#activeTurnId !== undefined || this.#waiter !== undefined) {
582
+ if (this.#activeTurnId !== undefined) {
583
583
  throw new ProviderTurnRejectedError("Provider Conversation already has an unsettled Turn.", turn.attemptId);
584
584
  }
585
- let deliveryTimer;
586
- const receipt = new Promise((resolvePromise, reject) => {
587
- deliveryTimer = setTimeout(() => {
588
- if (this.#waiter?.attemptId === turn.attemptId)
589
- this.#waiter = undefined;
590
- reject(new ProviderDeliveryUnknownError("Claude did not replay the submitted user message before the acknowledgement deadline.", turn.attemptId));
591
- }, PROVIDER_ACCEPT_TIMEOUT_MS);
592
- this.#waiter = {
593
- attemptId: turn.attemptId,
594
- text: turn.boundedText,
595
- resolve: resolvePromise,
596
- reject,
597
- timer: deliveryTimer
598
- };
599
- });
600
585
  try {
601
586
  await this.channel.send({
602
587
  type: "user",
@@ -607,12 +592,22 @@ class ClaudeStructuredProviderSession {
607
592
  });
608
593
  }
609
594
  catch (error) {
610
- if (deliveryTimer !== undefined)
611
- clearTimeout(deliveryTimer);
612
- this.#waiter = undefined;
613
- throw new ProviderDeliveryUnknownError(`Claude input write did not produce an exact replay acknowledgement: ${error instanceof Error ? error.message : String(error)}`, turn.attemptId);
595
+ throw new ProviderDeliveryUnknownError(`Claude input write did not complete: ${error instanceof Error ? error.message : String(error)}`, turn.attemptId);
614
596
  }
615
- return await receipt;
597
+ // AgentHost is the sole writer to this dedicated stream-json process.
598
+ // A completed pipe write is the smallest reliable acceptance boundary;
599
+ // Claude's later `result` is the matching terminal for this serialized
600
+ // Turn. Requiring an echoed user-message creates a second, brittle
601
+ // protocol without improving delivery safety.
602
+ const nativeTurnId = `claude-stream:${turn.attemptId}`;
603
+ this.#activeTurnId = nativeTurnId;
604
+ return Object.freeze({
605
+ attemptId: turn.attemptId,
606
+ conversationId: this.conversationId,
607
+ nativeSessionId: this.conversationId,
608
+ nativeTurnId,
609
+ acceptedAt: new Date().toISOString()
610
+ });
616
611
  }
617
612
  waitForExit() {
618
613
  return this.exit;
@@ -621,42 +616,17 @@ class ClaudeStructuredProviderSession {
621
616
  terminateProcessGroup(this.child, signal);
622
617
  }
623
618
  #receive(message, onTerminal) {
624
- if (message.type === "user") {
625
- const waiter = this.#waiter;
626
- if (waiter === undefined || claudeUserText(message) !== waiter.text)
627
- return;
628
- const observedSessionId = optionalId(message.session_id);
629
- if (observedSessionId !== this.conversationId) {
630
- clearTimeout(waiter.timer);
631
- this.#waiter = undefined;
632
- waiter.reject(new ProviderDeliveryUnknownError("Claude replayed input for a different native Session.", waiter.attemptId));
633
- return;
634
- }
635
- const nativeTurnId = optionalId(message.uuid);
636
- if (nativeTurnId === undefined) {
637
- clearTimeout(waiter.timer);
638
- this.#waiter = undefined;
639
- waiter.reject(new ProviderDeliveryUnknownError("Claude replayed input without a native message identity.", waiter.attemptId));
640
- return;
641
- }
642
- this.#activeTurnId = nativeTurnId;
643
- clearTimeout(waiter.timer);
644
- this.#waiter = undefined;
645
- waiter.resolve(Object.freeze({
646
- attemptId: waiter.attemptId,
647
- conversationId: this.conversationId,
648
- nativeSessionId: this.conversationId,
649
- nativeTurnId,
650
- acceptedAt: new Date().toISOString()
651
- }));
619
+ if (message.type === "user")
652
620
  return;
653
- }
654
621
  if (message.type !== "result" || this.#activeTurnId === undefined
655
622
  || optionalId(message.session_id) !== this.conversationId)
656
623
  return;
657
624
  const nativeTurnId = this.#activeTurnId;
658
625
  this.#activeTurnId = undefined;
659
626
  const failed = message.is_error === true || message.subtype === "error_during_execution";
627
+ const result = typeof message.result === "string" && message.result.length > 0
628
+ ? message.result
629
+ : "Provider Turn failed.";
660
630
  onTerminal?.({
661
631
  conversationId: this.conversationId,
662
632
  nativeSessionId: this.conversationId,
@@ -664,9 +634,11 @@ class ClaudeStructuredProviderSession {
664
634
  clientOwned: true,
665
635
  status: failed ? "failed" : "completed",
666
636
  observedAt: new Date().toISOString(),
667
- ...(typeof message.result === "string" && message.result.length > 0
668
- ? failed ? { error: message.result } : { summary: message.result }
669
- : {})
637
+ ...(failed
638
+ ? { error: result, rawError: providerErrorEvidence(message).rawError }
639
+ : typeof message.result === "string" && message.result.length > 0
640
+ ? { summary: message.result }
641
+ : {})
670
642
  });
671
643
  }
672
644
  }
@@ -712,19 +684,12 @@ function optionalId(value) {
712
684
  function nestedId(value, key) {
713
685
  return optionalId(object(value[key])?.id);
714
686
  }
715
- function providerErrorText(value) {
687
+ function providerErrorEvidence(value) {
716
688
  const error = object(value);
717
- if (typeof error?.message === "string" && error.message.length > 0)
718
- return error.message;
719
- return "Provider Turn failed.";
720
- }
721
- function claudeUserText(message) {
722
- const content = object(message.message)?.content;
723
- if (!Array.isArray(content))
724
- return undefined;
725
- const text = content.flatMap((entry) => {
726
- const block = object(entry);
727
- return block?.type === "text" && typeof block.text === "string" ? [block.text] : [];
728
- });
729
- return text.length === 1 ? text[0] : text.join("");
689
+ const message = typeof error?.message === "string" && error.message.length > 0
690
+ ? error.message
691
+ : typeof value === "string" && value.length > 0
692
+ ? value
693
+ : "Provider Turn failed.";
694
+ return { error: message, rawError: serializeAgentErrorRaw(value) };
730
695
  }
@@ -212,9 +212,6 @@ export function createTaskRuntimeIsolationDescriptor(input) {
212
212
  const workspace = validateManagedWorkspace(input.workspace);
213
213
  const owner = taskRuntimeWorkspaceOwner(workspace.owner);
214
214
  const taskId = requireIdentity(owner.taskId, "Task id");
215
- const runId = input.runId === undefined
216
- ? undefined
217
- : requireIdentity(input.runId, "Run id");
218
215
  const launchId = requireIdentity(input.launchId, "Launch id");
219
216
  const generationId = requireIdentity(input.generationId, "Generation id");
220
217
  const runtimeRoot = canonicalPath(input.runtimeRoot, "Task runtime root");
@@ -240,7 +237,6 @@ export function createTaskRuntimeIsolationDescriptor(input) {
240
237
  portAllocations,
241
238
  externalCapabilities: Object.freeze({ declared, requested }),
242
239
  generation: Object.freeze({
243
- ...(runId === undefined ? {} : { runId }),
244
240
  launchId,
245
241
  generationId
246
242
  })
@@ -287,9 +283,6 @@ export function parseTaskRuntimeIsolationDescriptor(serialized) {
287
283
  requested: capabilities(external.requested, "Requested external capability")
288
284
  },
289
285
  generation: {
290
- ...(generation.runId === undefined
291
- ? {}
292
- : { runId: requireIdentity(generation.runId, "Run id") }),
293
286
  launchId: requireIdentity(generation.launchId, "Launch id"),
294
287
  generationId: requireIdentity(generation.generationId, "Generation id")
295
288
  }
@@ -37,7 +37,7 @@ export class TmuxSessionHost {
37
37
  async start(request, beforeHostStart) {
38
38
  return this.#launch(request, beforeHostStart);
39
39
  }
40
- async resume(request, beforeHostStart) {
40
+ async restore(request, beforeHostStart) {
41
41
  return this.#launch(request, beforeHostStart);
42
42
  }
43
43
  async stop(binding) {
@@ -228,10 +228,7 @@ export class TmuxSessionHost {
228
228
  ...(planned.launch.env.YUI_SESSION_TITLE === undefined
229
229
  ? {}
230
230
  : { sessionTitle: planned.launch.env.YUI_SESSION_TITLE }),
231
- ...(nativeSessionId === undefined ? {} : { nativeSessionId }),
232
- ...(planned.initialTurnRunId === undefined
233
- ? {}
234
- : { initialTurnRunId: planned.initialTurnRunId })
231
+ ...(nativeSessionId === undefined ? {} : { nativeSessionId })
235
232
  });
236
233
  const yuiHome = planned.launch.env.YUI_HOME;
237
234
  const childLifecycle = planned.launch.childLifecycle;
@@ -264,9 +261,6 @@ export class TmuxSessionHost {
264
261
  roleName: request.owner.roleName
265
262
  }),
266
263
  hostCreated,
267
- ...(hostCreated && planned.initialTurnRunId !== undefined
268
- ? { initialTurnRunId: planned.initialTurnRunId }
269
- : {}),
270
264
  ...(nativeSessionId === undefined ? {} : { nativeSessionId })
271
265
  });
272
266
  if (hostCreated) {
@@ -277,7 +271,6 @@ export class TmuxSessionHost {
277
271
  if (request.mode === "new"
278
272
  && request.owner.scope === "task"
279
273
  && request.runId !== undefined
280
- && planned.initialTurnRunId === request.runId
281
274
  && this.#waitForNativeSession !== undefined) {
282
275
  binding = createRuntimeBinding({
283
276
  ...binding,
@@ -348,10 +341,6 @@ export class TmuxSessionHost {
348
341
  }
349
342
  };
350
343
  let hostCreated = false;
351
- let providerAcknowledged = false;
352
- let providerDeliveryUnknown = false;
353
- let providerBusy = false;
354
- let providerRejected = false;
355
344
  let providerDispatchObserved = false;
356
345
  let providerSnapshot;
357
346
  try {
@@ -363,17 +352,8 @@ export class TmuxSessionHost {
363
352
  ...(request.owner.scope === "task" ? { taskId: request.owner.taskId } : {}),
364
353
  roleName: request.owner.roleName,
365
354
  launchId: reservation.launchId,
366
- requireTurnAck: planned.initialTurnRunId !== undefined
355
+ requireTurnAck: false
367
356
  });
368
- providerDeliveryUnknown = providerSnapshot.state === "delivery-unknown";
369
- providerBusy = planned.initialTurnRunId !== undefined
370
- && providerSnapshot.state === "busy";
371
- providerRejected = planned.initialTurnRunId !== undefined
372
- && providerSnapshot.state === "rejected";
373
- providerAcknowledged = !providerDeliveryUnknown && !providerBusy && !providerRejected;
374
- if (providerSnapshot.state === "rejected" && !providerRejected) {
375
- throw new Error("Agent Host rejected a launch without an initial Provider Turn.");
376
- }
377
357
  providerDispatchObserved = true;
378
358
  }
379
359
  if (!hostCreated) {
@@ -396,25 +376,13 @@ export class TmuxSessionHost {
396
376
  if (controlResult.outcome === "active-same-launch") {
397
377
  broker.revoke(request.launchId);
398
378
  }
399
- const acceptableState = controlResult.snapshot.state === "ready"
400
- || (planned.initialTurnRunId === undefined
401
- && controlResult.snapshot.state === "idle");
402
- const deliveryUnknownState = planned.initialTurnRunId !== undefined
403
- && controlResult.snapshot.state === "delivery-unknown";
404
- const busyState = planned.initialTurnRunId !== undefined
405
- && controlResult.snapshot.state === "busy";
406
- const rejectedState = planned.initialTurnRunId !== undefined
407
- && controlResult.snapshot.state === "rejected";
408
- if ((!acceptableState && !deliveryUnknownState && !busyState && !rejectedState)
379
+ const acceptableState = ["idle", "ready", "busy"].includes(controlResult.snapshot.state);
380
+ if (!acceptableState
409
381
  || controlResult.snapshot.launchId !== reservation.launchId) {
410
382
  broker.revoke(request.launchId);
411
383
  throw new Error(`Agent Host did not return an exact Provider acknowledgement for ${reservation.launchId}.`);
412
384
  }
413
385
  providerSnapshot = controlResult.snapshot;
414
- providerAcknowledged = acceptableState;
415
- providerDeliveryUnknown = deliveryUnknownState;
416
- providerBusy = busyState;
417
- providerRejected = rejectedState;
418
386
  providerDispatchObserved = true;
419
387
  }
420
388
  }
@@ -457,18 +425,6 @@ export class TmuxSessionHost {
457
425
  roleName: request.owner.roleName
458
426
  }),
459
427
  hostCreated,
460
- ...(providerAcknowledged && planned.initialTurnRunId !== undefined
461
- ? { initialTurnRunId: planned.initialTurnRunId }
462
- : {}),
463
- ...(providerDeliveryUnknown && planned.initialTurnRunId !== undefined
464
- ? { initialTurnDeliveryUnknownRunId: planned.initialTurnRunId }
465
- : {}),
466
- ...(providerBusy && planned.initialTurnRunId !== undefined
467
- ? { initialTurnBusyRunId: planned.initialTurnRunId }
468
- : {}),
469
- ...(providerRejected && planned.initialTurnRunId !== undefined
470
- ? { initialTurnRejectedRunId: planned.initialTurnRunId }
471
- : {}),
472
428
  ...((providerSnapshot?.nativeSessionId ?? nativeSessionId) === undefined
473
429
  ? {}
474
430
  : { nativeSessionId: providerSnapshot?.nativeSessionId ?? nativeSessionId }),
@@ -575,6 +531,7 @@ export class AgentHostPromptPushAdapter {
575
531
  type: "submit-turn",
576
532
  launchId: request.binding.launchId,
577
533
  nativeSessionId: request.binding.nativeSessionId,
534
+ runId: request.envelope.source.localId,
578
535
  authority: request.binding.providerAuthority,
579
536
  turn: {
580
537
  attemptId: request.envelope.id,