@caupulican/pi-adaptative 0.90.2 → 0.90.4

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 (162) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/dist/core/agent-session-contracts.d.ts +2 -0
  3. package/dist/core/agent-session-contracts.d.ts.map +1 -1
  4. package/dist/core/agent-session-contracts.js.map +1 -1
  5. package/dist/core/autonomy/bounded-completion.d.ts +10 -1
  6. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -1
  7. package/dist/core/autonomy/bounded-completion.js +24 -2
  8. package/dist/core/autonomy/bounded-completion.js.map +1 -1
  9. package/dist/core/autonomy/lane-tracker.d.ts +1 -1
  10. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
  11. package/dist/core/autonomy/lane-tracker.js +9 -1
  12. package/dist/core/autonomy/lane-tracker.js.map +1 -1
  13. package/dist/core/background-lane-controller.d.ts +1 -3
  14. package/dist/core/background-lane-controller.d.ts.map +1 -1
  15. package/dist/core/background-lane-controller.js.map +1 -1
  16. package/dist/core/compaction-controller.d.ts.map +1 -1
  17. package/dist/core/compaction-controller.js +0 -1
  18. package/dist/core/compaction-controller.js.map +1 -1
  19. package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -1
  20. package/dist/core/delegation/managed-lane-controller.js +5 -1
  21. package/dist/core/delegation/managed-lane-controller.js.map +1 -1
  22. package/dist/core/delegation/worker-agent-control-coordinator.d.ts +8 -1
  23. package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -1
  24. package/dist/core/delegation/worker-agent-control-coordinator.js +94 -36
  25. package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -1
  26. package/dist/core/delegation/worker-agent-control.d.ts +1 -0
  27. package/dist/core/delegation/worker-agent-control.d.ts.map +1 -1
  28. package/dist/core/delegation/worker-agent-control.js.map +1 -1
  29. package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -1
  30. package/dist/core/delegation/worker-attempt-executor.js +7 -2
  31. package/dist/core/delegation/worker-attempt-executor.js.map +1 -1
  32. package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -1
  33. package/dist/core/delegation/worker-authority-resolver.js +26 -3
  34. package/dist/core/delegation/worker-authority-resolver.js.map +1 -1
  35. package/dist/core/delegation/worker-delegation-controller.d.ts +7 -4
  36. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  37. package/dist/core/delegation/worker-delegation-controller.js +110 -27
  38. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  39. package/dist/core/delegation/worker-fleet-limits.d.ts +9 -2
  40. package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -1
  41. package/dist/core/delegation/worker-fleet-limits.js +39 -3
  42. package/dist/core/delegation/worker-fleet-limits.js.map +1 -1
  43. package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -1
  44. package/dist/core/delegation/worker-lane-projection.js +4 -0
  45. package/dist/core/delegation/worker-lane-projection.js.map +1 -1
  46. package/dist/core/delegation/worker-lease-heartbeat.d.ts +16 -0
  47. package/dist/core/delegation/worker-lease-heartbeat.d.ts.map +1 -0
  48. package/dist/core/delegation/worker-lease-heartbeat.js +37 -0
  49. package/dist/core/delegation/worker-lease-heartbeat.js.map +1 -0
  50. package/dist/core/delegation/worker-lifecycle.d.ts +1 -0
  51. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  52. package/dist/core/delegation/worker-lifecycle.js +6 -0
  53. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  54. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
  55. package/dist/core/delegation/worker-notification-coordinator.js +2 -1
  56. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
  57. package/dist/core/delegation/worker-runner.js +2 -2
  58. package/dist/core/delegation/worker-runner.js.map +1 -1
  59. package/dist/core/delegation/worker-terminal-handoff-coordinator.d.ts +1 -0
  60. package/dist/core/delegation/worker-terminal-handoff-coordinator.d.ts.map +1 -1
  61. package/dist/core/delegation/worker-terminal-handoff-coordinator.js +1 -0
  62. package/dist/core/delegation/worker-terminal-handoff-coordinator.js.map +1 -1
  63. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +4 -2
  64. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -1
  65. package/dist/core/delegation/worker-tree-budget-coordinator.js +10 -2
  66. package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -1
  67. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +14 -0
  68. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
  69. package/dist/core/delegation/worker-write-reservation-coordinator.js +121 -33
  70. package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
  71. package/dist/core/foreground-terminal-handoff-controller.d.ts +5 -0
  72. package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
  73. package/dist/core/foreground-terminal-handoff-controller.js +28 -12
  74. package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
  75. package/dist/core/orchestration/capability-gateway.d.ts +2 -1
  76. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  77. package/dist/core/orchestration/capability-gateway.js +9 -2
  78. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  79. package/dist/core/orchestration/contracts.d.ts +16 -1
  80. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  81. package/dist/core/orchestration/contracts.js +5 -0
  82. package/dist/core/orchestration/contracts.js.map +1 -1
  83. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  84. package/dist/core/orchestration/profile-registry.js +38 -1
  85. package/dist/core/orchestration/profile-registry.js.map +1 -1
  86. package/dist/core/orchestration/risk-budget.d.ts +10 -0
  87. package/dist/core/orchestration/risk-budget.d.ts.map +1 -1
  88. package/dist/core/orchestration/risk-budget.js +14 -0
  89. package/dist/core/orchestration/risk-budget.js.map +1 -1
  90. package/dist/core/orchestration/task-runtime-reducer.d.ts +1 -0
  91. package/dist/core/orchestration/task-runtime-reducer.d.ts.map +1 -1
  92. package/dist/core/orchestration/task-runtime-reducer.js +34 -0
  93. package/dist/core/orchestration/task-runtime-reducer.js.map +1 -1
  94. package/dist/core/orchestration/task-runtime.d.ts +1 -0
  95. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  96. package/dist/core/orchestration/task-runtime.js +24 -1
  97. package/dist/core/orchestration/task-runtime.js.map +1 -1
  98. package/dist/core/provider-prompt-contracts.d.ts.map +1 -1
  99. package/dist/core/provider-prompt-contracts.js +2 -1
  100. package/dist/core/provider-prompt-contracts.js.map +1 -1
  101. package/dist/core/reflection-controller.d.ts.map +1 -1
  102. package/dist/core/reflection-controller.js +8 -1
  103. package/dist/core/reflection-controller.js.map +1 -1
  104. package/dist/core/settings-manager.d.ts +2 -2
  105. package/dist/core/settings-manager.d.ts.map +1 -1
  106. package/dist/core/settings-manager.js +2 -2
  107. package/dist/core/settings-manager.js.map +1 -1
  108. package/dist/core/tools/bash.d.ts +3 -0
  109. package/dist/core/tools/bash.d.ts.map +1 -1
  110. package/dist/core/tools/bash.js +13 -2
  111. package/dist/core/tools/bash.js.map +1 -1
  112. package/dist/core/tools/delegate-status.d.ts +1 -0
  113. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  114. package/dist/core/tools/delegate-status.js +19 -1
  115. package/dist/core/tools/delegate-status.js.map +1 -1
  116. package/dist/core/tools/delegate.d.ts +9 -1
  117. package/dist/core/tools/delegate.d.ts.map +1 -1
  118. package/dist/core/tools/delegate.js +198 -64
  119. package/dist/core/tools/delegate.js.map +1 -1
  120. package/dist/core/tools/edit.d.ts.map +1 -1
  121. package/dist/core/tools/edit.js +14 -1
  122. package/dist/core/tools/edit.js.map +1 -1
  123. package/dist/core/tools/file-failure-recovery.d.ts +3 -0
  124. package/dist/core/tools/file-failure-recovery.d.ts.map +1 -1
  125. package/dist/core/tools/file-failure-recovery.js +11 -0
  126. package/dist/core/tools/file-failure-recovery.js.map +1 -1
  127. package/dist/core/tools/orchestration-panel.d.ts +1 -1
  128. package/dist/core/tools/orchestration-panel.d.ts.map +1 -1
  129. package/dist/core/tools/orchestration-panel.js +1 -0
  130. package/dist/core/tools/orchestration-panel.js.map +1 -1
  131. package/dist/core/tools/profile-writer.d.ts.map +1 -1
  132. package/dist/core/tools/profile-writer.js +2 -8
  133. package/dist/core/tools/profile-writer.js.map +1 -1
  134. package/dist/core/tools/search-command-guard.d.ts.map +1 -1
  135. package/dist/core/tools/search-command-guard.js +10 -3
  136. package/dist/core/tools/search-command-guard.js.map +1 -1
  137. package/dist/core/tools/write.d.ts.map +1 -1
  138. package/dist/core/tools/write.js +10 -1
  139. package/dist/core/tools/write.js.map +1 -1
  140. package/dist/modes/interactive/components/activity-lane.d.ts +1 -1
  141. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
  142. package/dist/modes/interactive/components/activity-lane.js +11 -2
  143. package/dist/modes/interactive/components/activity-lane.js.map +1 -1
  144. package/dist/modes/interactive/components/settings-selector.js +1 -1
  145. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  146. package/dist/utils/shell.d.ts +2 -0
  147. package/dist/utils/shell.d.ts.map +1 -1
  148. package/dist/utils/shell.js +3 -1
  149. package/dist/utils/shell.js.map +1 -1
  150. package/docs/harness-architecture.md +6 -3
  151. package/docs/settings.md +8 -6
  152. package/docs/tool-repair.md +1 -1
  153. package/docs/worker-profiles.md +2 -2
  154. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  155. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  156. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  157. package/examples/extensions/sandbox/package-lock.json +2 -2
  158. package/examples/extensions/sandbox/package.json +1 -1
  159. package/examples/extensions/with-deps/package-lock.json +2 -2
  160. package/examples/extensions/with-deps/package.json +1 -1
  161. package/npm-shrinkwrap.json +12 -12
  162. package/package.json +4 -4
@@ -29,7 +29,8 @@ import { WorkerConversationStore, } from "./worker-conversation-store.js";
29
29
  import { parseWorkerDelegationAuthorityRequest } from "./worker-delegation-request.js";
30
30
  import { WorkerDispatchScheduler } from "./worker-dispatch-scheduler.js";
31
31
  import { buildWorkerExecutionPlan, compileWorkerExecutionGrant, narrowWorkerExecutionPlan, workerExecutionAuthorityFromPlan, } from "./worker-execution-policy.js";
32
- import { DEFAULT_WORKER_FLEET_LIMITS, evaluateNewWorkerAdmission, pendingVerifierSubjectTaskIds, } from "./worker-fleet-limits.js";
32
+ import { DEFAULT_WORKER_FLEET_LIMITS, evaluateNewWorkerAdmission, intersectWorkerDelegationLimits, pendingVerifierSubjectTaskIds, resolveWorkerFleetLimits, } from "./worker-fleet-limits.js";
33
+ import { WorkerLeaseHeartbeat } from "./worker-lease-heartbeat.js";
33
34
  import { createLocalWorkerProcessOwnerId } from "./worker-process-owner.js";
34
35
  import { WorkerProfileResolver } from "./worker-profile-resolver.js";
35
36
  import { WorkerRecoveryCoordinator } from "./worker-recovery-coordinator.js";
@@ -38,7 +39,7 @@ import { materializeWorkerResourceBundle } from "./worker-resource-materializer.
38
39
  import { finalizeWorkerClaim } from "./worker-terminal-finalizer.js";
39
40
  import { WorkerTerminalHandoffCoordinator, } from "./worker-terminal-handoff-coordinator.js";
40
41
  import { collectWorkerTreeBudgetSeeds, WorkerTreeBudgetCoordinator } from "./worker-tree-budget-coordinator.js";
41
- import { WorkerWriteReservationCoordinator } from "./worker-write-reservation-coordinator.js";
42
+ import { WorkerWriteReservationCoordinator, } from "./worker-write-reservation-coordinator.js";
42
43
  export function isLocalExecutionModel(model) {
43
44
  if (model.provider === "ollama" || model.provider === "transformers" || model.provider === "llama-cpp") {
44
45
  return true;
@@ -82,6 +83,7 @@ export class WorkerDelegationController {
82
83
  this.shellSessionKeys = new Set();
83
84
  this.publishedTerminalAttemptIds = new Set();
84
85
  this.yieldedCapacityAttemptIds = new Map();
86
+ this.yieldedWriteReservations = new Map();
85
87
  this.conversations = new WorkerConversationStore();
86
88
  this.treeBudgets = new WorkerTreeBudgetCoordinator();
87
89
  this.inFlightLedgers = new Map();
@@ -150,7 +152,8 @@ export class WorkerDelegationController {
150
152
  ? this.workerProjectionHeadroomSkipReason(contract)
151
153
  : "orchestration_execution_contract_missing";
152
154
  },
153
- yieldCapacity: (callerAgentId, targetAgentId) => this.yieldWorkerCapacity(callerAgentId, targetAgentId),
155
+ waitBlockedByCaller: (callerAgentId, targetAgentIds) => this.waitTargetsBlockedByCaller(callerAgentId, targetAgentIds),
156
+ yieldCallerForWait: (callerAgentId) => this.yieldWorkerForWait(callerAgentId),
154
157
  warn: (message) => this.safeWarn(message),
155
158
  });
156
159
  this.terminalHandoffs = new WorkerTerminalHandoffCoordinator({
@@ -166,8 +169,10 @@ export class WorkerDelegationController {
166
169
  getParentSessionId: () => this.deps.getSessionId(),
167
170
  ownerId: this.agentControl.getProcessOwnerId(),
168
171
  drainQueuedWorkers: () => {
169
- if (!this.deps.isDisposed())
170
- this.scheduler.drain(true);
172
+ if (this.deps.isDisposed())
173
+ return;
174
+ this.scheduler.drain(true);
175
+ this.agentControl.signalStateChanged();
171
176
  },
172
177
  warn: (message) => this.safeWarn(message),
173
178
  });
@@ -449,9 +454,10 @@ export class WorkerDelegationController {
449
454
  : { ok: false, skipReason: `independent_verifier_unavailable:${admitted.reason}` };
450
455
  }
451
456
  /**
452
- * A descendant may select a different routing profile, but that preset cannot introduce context
453
- * its ancestor never admitted. Pointer ids alone are insufficient authority: retain only pointers
454
- * whose complete immutable metadata matches the ancestral contract, and require exact soul text.
457
+ * A descendant may select a different routing profile, but that preset cannot introduce context or
458
+ * recursive authority its ancestor never admitted. Pointer ids alone are insufficient authority:
459
+ * retain only pointers whose complete immutable metadata matches the ancestral contract, require
460
+ * exact soul text, and intersect durable delegation limits.
455
461
  */
456
462
  narrowWorkerShipmentContext(shipment, boundary) {
457
463
  const boundaryPointers = new Map(boundary.resourcePointers.map((pointer) => [pointer.id, pointer]));
@@ -466,10 +472,15 @@ export class WorkerDelegationController {
466
472
  if (shipment.soul !== undefined && shipment.soul !== boundary.soul) {
467
473
  return { ok: false, skipReason: "orchestration_context_authority_exceeded" };
468
474
  }
475
+ const delegationLimits = intersectWorkerDelegationLimits(shipment.profile.delegationLimits, boundary.profile.delegationLimits);
469
476
  return {
470
477
  ok: true,
471
478
  shipment: {
472
479
  ...shipment,
480
+ profile: {
481
+ ...shipment.profile,
482
+ ...(delegationLimits ? { delegationLimits } : {}),
483
+ },
473
484
  resourcePointers,
474
485
  ...(shipment.soul ? { soul: shipment.soul } : {}),
475
486
  },
@@ -494,7 +505,11 @@ export class WorkerDelegationController {
494
505
  }
495
506
  /** Reject a new logical identity before creating its task, transcript, agent, or queue entry. */
496
507
  newWorkerFleetSkipReason(request, requiredAgentSlots = 1) {
497
- const decision = evaluateNewWorkerAdmission(this.lifecycle.getTaskRuntimeSnapshot().agents, request.parentAgentId, DEFAULT_WORKER_FLEET_LIMITS, requiredAgentSlots);
508
+ const parentAttempt = request.parentAgentId
509
+ ? this.lifecycle.getLatestAgentAttempt(request.parentAgentId)
510
+ : undefined;
511
+ const limits = resolveWorkerFleetLimits(parentAttempt?.dispatch.executionContract?.worker.profile.delegationLimits);
512
+ const decision = evaluateNewWorkerAdmission(this.lifecycle.getTaskRuntimeSnapshot().agents, request.parentAgentId, limits, requiredAgentSlots);
498
513
  return decision.ok ? undefined : decision.reasonCode;
499
514
  }
500
515
  requiredAgentSlotsForAdmission(request, admission) {
@@ -829,37 +844,89 @@ export class WorkerDelegationController {
829
844
  const status = snapshot.attempts[attemptId]?.status;
830
845
  if (status === "leased" || status === "running")
831
846
  yielded += 1;
832
- else
847
+ else {
833
848
  this.yieldedCapacityAttemptIds.delete(attemptId);
849
+ this.yieldedWriteReservations.delete(attemptId);
850
+ }
834
851
  }
835
852
  return Math.max(0, this.getWorkerLifecycle().getRunningCount() - yielded) < settings.maxConcurrent;
836
853
  }
837
- yieldWorkerCapacity(callerAgentId, targetAgentId) {
854
+ waitTargetsBlockedByCaller(callerAgentId, targetAgentIds) {
838
855
  const caller = this.lifecycle.getAgent(callerAgentId);
839
- const target = this.lifecycle.getAgent(targetAgentId);
840
- if (!caller || !target || caller.rootAgentId !== target.rootAgentId)
841
- return () => undefined;
856
+ const callerAttempt = caller ? this.lifecycle.getLatestAgentAttempt(caller.agentId) : undefined;
857
+ if (!callerAttempt || (callerAttempt.status !== "leased" && callerAttempt.status !== "running"))
858
+ return [];
859
+ const blockedAgentIds = [];
860
+ for (const targetAgentId of targetAgentIds) {
861
+ const target = this.lifecycle.getAgent(targetAgentId);
862
+ const targetAttempt = target ? this.lifecycle.getLatestAgentAttempt(target.agentId) : undefined;
863
+ if (targetAttempt?.status === "queued" &&
864
+ this.writeReservations.isBlockedBy(targetAttempt.taskId, callerAttempt.taskId)) {
865
+ blockedAgentIds.push(targetAgentId);
866
+ }
867
+ }
868
+ return blockedAgentIds;
869
+ }
870
+ yieldWorkerForWait(callerAgentId) {
871
+ const caller = this.lifecycle.getAgent(callerAgentId);
872
+ if (!caller)
873
+ return () => true;
842
874
  const attempt = this.lifecycle.getLatestAgentAttempt(caller.agentId);
843
875
  if (!attempt || (attempt.status !== "leased" && attempt.status !== "running"))
844
- return () => undefined;
845
- this.yieldedCapacityAttemptIds.set(attempt.attemptId, (this.yieldedCapacityAttemptIds.get(attempt.attemptId) ?? 0) + 1);
846
- this.scheduler.drain();
847
- let released = false;
848
- return () => {
849
- if (released)
850
- return;
851
- released = true;
876
+ return () => true;
877
+ const existingYields = this.yieldedCapacityAttemptIds.get(attempt.attemptId) ?? 0;
878
+ if (existingYields === 0 && attempt.lease) {
879
+ const yieldedReservation = this.writeReservations.yieldForWait(attempt.taskId, attempt.attemptId, attempt.lease.fencingToken);
880
+ if (yieldedReservation)
881
+ this.yieldedWriteReservations.set(attempt.attemptId, yieldedReservation);
882
+ }
883
+ this.yieldedCapacityAttemptIds.set(attempt.attemptId, existingYields + 1);
884
+ let restored = false;
885
+ const restore = () => {
886
+ if (restored)
887
+ return true;
852
888
  const leases = this.yieldedCapacityAttemptIds.get(attempt.attemptId);
853
- if (leases === undefined)
854
- return;
889
+ if (leases === undefined) {
890
+ restored = true;
891
+ return true;
892
+ }
855
893
  if (leases > 1) {
856
894
  this.yieldedCapacityAttemptIds.set(attempt.attemptId, leases - 1);
857
- return;
895
+ restored = true;
896
+ return true;
897
+ }
898
+ const current = this.lifecycle.getLatestAgentAttempt(caller.agentId);
899
+ if (!this.deps.isDisposed() &&
900
+ current?.attemptId === attempt.attemptId &&
901
+ (current.status === "leased" || current.status === "running")) {
902
+ const yieldedReservation = this.yieldedWriteReservations.get(attempt.attemptId);
903
+ if (yieldedReservation) {
904
+ const reservation = this.writeReservations.restoreAfterWait(yieldedReservation);
905
+ if (reservation.kind === "blocked")
906
+ return false;
907
+ if (reservation.kind === "denied") {
908
+ this.laneAbortControllers.get(attempt.taskId)?.abort(reservation.reasonCode);
909
+ throw new Error(`Worker wait could not restore its write reservation: ${reservation.reasonCode}.`);
910
+ }
911
+ }
858
912
  }
859
913
  this.yieldedCapacityAttemptIds.delete(attempt.attemptId);
914
+ this.yieldedWriteReservations.delete(attempt.attemptId);
915
+ restored = true;
860
916
  if (!this.deps.isDisposed())
861
- this.scheduler.drain();
917
+ this.scheduler.drain(true);
918
+ return true;
862
919
  };
920
+ try {
921
+ this.scheduler.drain(true);
922
+ }
923
+ catch (error) {
924
+ if (!restore()) {
925
+ throw new AggregateError([error], "Worker wait dispatch failed before its write reservation could be restored.");
926
+ }
927
+ throw error;
928
+ }
929
+ return restore;
863
930
  }
864
931
  workerDispatchAdmission(request, record) {
865
932
  if (this.recovery.deferRetryIfNeeded(record, request))
@@ -942,13 +1009,14 @@ export class WorkerDelegationController {
942
1009
  workerContextForkMode(request, contract) {
943
1010
  if (request.verificationOfTaskId)
944
1011
  return { kind: "none" };
1012
+ const mode = request.forkTurns ?? (request.parentAgentId ? "none" : undefined);
945
1013
  return resolveWorkerContextInheritanceMode({
946
1014
  parent: this.workerContextParentModel(request),
947
1015
  worker: {
948
1016
  provider: contract.worker.modelBinding.provider,
949
1017
  model: contract.worker.modelBinding.modelId,
950
1018
  },
951
- ...(request.forkTurns !== undefined ? { mode: request.forkTurns } : {}),
1019
+ ...(mode !== undefined ? { mode } : {}),
952
1020
  });
953
1021
  }
954
1022
  workerContextForkAdmissionSkipReason(request, contract) {
@@ -1499,6 +1567,16 @@ export class WorkerDelegationController {
1499
1567
  const laneAbortController = new AbortController();
1500
1568
  this.laneAbortControllers.set(startedRecord.laneId, laneAbortController);
1501
1569
  const workerSignal = AbortSignal.any([this.workerAbort.signal, laneAbortController.signal]);
1570
+ const leaseHeartbeat = new WorkerLeaseHeartbeat({
1571
+ leaseTtlMs: immutableProfile.leaseTtlMs,
1572
+ renew: () => {
1573
+ lifecycle.renewLease(startedRecord.laneId, immutableProfile.leaseTtlMs);
1574
+ },
1575
+ onFailure: (error) => {
1576
+ this.safeWarn(`Worker ${startedRecord.laneId} lease renewal failed: ${error.message}`);
1577
+ laneAbortController.abort(error);
1578
+ },
1579
+ });
1502
1580
  // Registered for the lane's full run so the reload gate waits it out; deregistered in the
1503
1581
  // finally below no matter how this lane terminates (success, disposal, or a thrown error).
1504
1582
  // registerInFlightWork is a pure sync map op (cannot throw), so placing it as the last
@@ -1551,7 +1629,9 @@ export class WorkerDelegationController {
1551
1629
  request: workerRequest,
1552
1630
  handle: durableHandle,
1553
1631
  });
1632
+ leaseHeartbeat.start();
1554
1633
  const executionResult = await executor.run();
1634
+ leaseHeartbeat.assertHealthy();
1555
1635
  const rawOutcome = executionResult.rawOutcome;
1556
1636
  // Attempt ladder: a retryable bounded failure suspends and re-enqueues instead of
1557
1637
  // terminalizing, resuming from the persisted transcript under a fresh fence.
@@ -1733,7 +1813,10 @@ export class WorkerDelegationController {
1733
1813
  return { started: true, record };
1734
1814
  }
1735
1815
  finally {
1816
+ leaseHeartbeat.stop();
1736
1817
  this.writeReservations.release(startedRecord.laneId, durableHandle.attemptId, durableHandle.fencingToken);
1818
+ this.yieldedCapacityAttemptIds.delete(durableHandle.attemptId);
1819
+ this.yieldedWriteReservations.delete(durableHandle.attemptId);
1737
1820
  this.inFlightLedgers.delete(startedRecord.laneId);
1738
1821
  this.laneAbortControllers.delete(startedRecord.laneId);
1739
1822
  try {