@caupulican/pi-adaptative 0.90.2 → 0.90.5

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 (174) hide show
  1. package/CHANGELOG.md +41 -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 +6 -1
  10. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -1
  11. package/dist/core/autonomy/lane-tracker.js +17 -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 +2 -0
  33. package/dist/core/delegation/worker-authority-resolver.d.ts.map +1 -1
  34. package/dist/core/delegation/worker-authority-resolver.js +49 -6
  35. package/dist/core/delegation/worker-authority-resolver.js.map +1 -1
  36. package/dist/core/delegation/worker-delegation-controller.d.ts +8 -5
  37. package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
  38. package/dist/core/delegation/worker-delegation-controller.js +158 -40
  39. package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
  40. package/dist/core/delegation/worker-fleet-limits.d.ts +9 -2
  41. package/dist/core/delegation/worker-fleet-limits.d.ts.map +1 -1
  42. package/dist/core/delegation/worker-fleet-limits.js +39 -3
  43. package/dist/core/delegation/worker-fleet-limits.js.map +1 -1
  44. package/dist/core/delegation/worker-lane-projection.d.ts.map +1 -1
  45. package/dist/core/delegation/worker-lane-projection.js +10 -0
  46. package/dist/core/delegation/worker-lane-projection.js.map +1 -1
  47. package/dist/core/delegation/worker-lease-heartbeat.d.ts +16 -0
  48. package/dist/core/delegation/worker-lease-heartbeat.d.ts.map +1 -0
  49. package/dist/core/delegation/worker-lease-heartbeat.js +37 -0
  50. package/dist/core/delegation/worker-lease-heartbeat.js.map +1 -0
  51. package/dist/core/delegation/worker-lifecycle.d.ts +1 -0
  52. package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
  53. package/dist/core/delegation/worker-lifecycle.js +6 -0
  54. package/dist/core/delegation/worker-lifecycle.js.map +1 -1
  55. package/dist/core/delegation/worker-notification-coordinator.d.ts.map +1 -1
  56. package/dist/core/delegation/worker-notification-coordinator.js +2 -1
  57. package/dist/core/delegation/worker-notification-coordinator.js.map +1 -1
  58. package/dist/core/delegation/worker-profile-resolver.d.ts +28 -1
  59. package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
  60. package/dist/core/delegation/worker-profile-resolver.js +38 -9
  61. package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
  62. package/dist/core/delegation/worker-runner.js +2 -2
  63. package/dist/core/delegation/worker-runner.js.map +1 -1
  64. package/dist/core/delegation/worker-terminal-handoff-coordinator.d.ts +1 -0
  65. package/dist/core/delegation/worker-terminal-handoff-coordinator.d.ts.map +1 -1
  66. package/dist/core/delegation/worker-terminal-handoff-coordinator.js +1 -0
  67. package/dist/core/delegation/worker-terminal-handoff-coordinator.js.map +1 -1
  68. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts +4 -2
  69. package/dist/core/delegation/worker-tree-budget-coordinator.d.ts.map +1 -1
  70. package/dist/core/delegation/worker-tree-budget-coordinator.js +10 -2
  71. package/dist/core/delegation/worker-tree-budget-coordinator.js.map +1 -1
  72. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +14 -0
  73. package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -1
  74. package/dist/core/delegation/worker-write-reservation-coordinator.js +121 -33
  75. package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -1
  76. package/dist/core/foreground-terminal-handoff-controller.d.ts +5 -0
  77. package/dist/core/foreground-terminal-handoff-controller.d.ts.map +1 -1
  78. package/dist/core/foreground-terminal-handoff-controller.js +28 -12
  79. package/dist/core/foreground-terminal-handoff-controller.js.map +1 -1
  80. package/dist/core/orchestration/capability-gateway.d.ts +2 -1
  81. package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
  82. package/dist/core/orchestration/capability-gateway.js +9 -2
  83. package/dist/core/orchestration/capability-gateway.js.map +1 -1
  84. package/dist/core/orchestration/contracts.d.ts +16 -1
  85. package/dist/core/orchestration/contracts.d.ts.map +1 -1
  86. package/dist/core/orchestration/contracts.js +5 -0
  87. package/dist/core/orchestration/contracts.js.map +1 -1
  88. package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
  89. package/dist/core/orchestration/profile-registry.js +38 -1
  90. package/dist/core/orchestration/profile-registry.js.map +1 -1
  91. package/dist/core/orchestration/risk-budget.d.ts +10 -0
  92. package/dist/core/orchestration/risk-budget.d.ts.map +1 -1
  93. package/dist/core/orchestration/risk-budget.js +14 -0
  94. package/dist/core/orchestration/risk-budget.js.map +1 -1
  95. package/dist/core/orchestration/task-runtime-reducer.d.ts +1 -0
  96. package/dist/core/orchestration/task-runtime-reducer.d.ts.map +1 -1
  97. package/dist/core/orchestration/task-runtime-reducer.js +34 -0
  98. package/dist/core/orchestration/task-runtime-reducer.js.map +1 -1
  99. package/dist/core/orchestration/task-runtime.d.ts +1 -0
  100. package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
  101. package/dist/core/orchestration/task-runtime.js +24 -1
  102. package/dist/core/orchestration/task-runtime.js.map +1 -1
  103. package/dist/core/orchestration/worker-model-pins.d.ts +28 -0
  104. package/dist/core/orchestration/worker-model-pins.d.ts.map +1 -0
  105. package/dist/core/orchestration/worker-model-pins.js +141 -0
  106. package/dist/core/orchestration/worker-model-pins.js.map +1 -0
  107. package/dist/core/provider-prompt-contracts.d.ts.map +1 -1
  108. package/dist/core/provider-prompt-contracts.js +2 -1
  109. package/dist/core/provider-prompt-contracts.js.map +1 -1
  110. package/dist/core/reflection-controller.d.ts.map +1 -1
  111. package/dist/core/reflection-controller.js +8 -1
  112. package/dist/core/reflection-controller.js.map +1 -1
  113. package/dist/core/runtime-builder.d.ts.map +1 -1
  114. package/dist/core/runtime-builder.js +1 -0
  115. package/dist/core/runtime-builder.js.map +1 -1
  116. package/dist/core/settings-manager.d.ts +6 -3
  117. package/dist/core/settings-manager.d.ts.map +1 -1
  118. package/dist/core/settings-manager.js +26 -2
  119. package/dist/core/settings-manager.js.map +1 -1
  120. package/dist/core/tools/bash.d.ts +3 -0
  121. package/dist/core/tools/bash.d.ts.map +1 -1
  122. package/dist/core/tools/bash.js +13 -2
  123. package/dist/core/tools/bash.js.map +1 -1
  124. package/dist/core/tools/delegate-status.d.ts +3 -0
  125. package/dist/core/tools/delegate-status.d.ts.map +1 -1
  126. package/dist/core/tools/delegate-status.js +26 -1
  127. package/dist/core/tools/delegate-status.js.map +1 -1
  128. package/dist/core/tools/delegate.d.ts +15 -1
  129. package/dist/core/tools/delegate.d.ts.map +1 -1
  130. package/dist/core/tools/delegate.js +234 -68
  131. package/dist/core/tools/delegate.js.map +1 -1
  132. package/dist/core/tools/edit.d.ts.map +1 -1
  133. package/dist/core/tools/edit.js +14 -1
  134. package/dist/core/tools/edit.js.map +1 -1
  135. package/dist/core/tools/file-failure-recovery.d.ts +3 -0
  136. package/dist/core/tools/file-failure-recovery.d.ts.map +1 -1
  137. package/dist/core/tools/file-failure-recovery.js +11 -0
  138. package/dist/core/tools/file-failure-recovery.js.map +1 -1
  139. package/dist/core/tools/orchestration-panel.d.ts +1 -1
  140. package/dist/core/tools/orchestration-panel.d.ts.map +1 -1
  141. package/dist/core/tools/orchestration-panel.js +1 -0
  142. package/dist/core/tools/orchestration-panel.js.map +1 -1
  143. package/dist/core/tools/profile-writer.d.ts.map +1 -1
  144. package/dist/core/tools/profile-writer.js +2 -8
  145. package/dist/core/tools/profile-writer.js.map +1 -1
  146. package/dist/core/tools/search-command-guard.d.ts.map +1 -1
  147. package/dist/core/tools/search-command-guard.js +10 -3
  148. package/dist/core/tools/search-command-guard.js.map +1 -1
  149. package/dist/core/tools/write.d.ts.map +1 -1
  150. package/dist/core/tools/write.js +10 -1
  151. package/dist/core/tools/write.js.map +1 -1
  152. package/dist/modes/interactive/components/activity-lane.d.ts +1 -1
  153. package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -1
  154. package/dist/modes/interactive/components/activity-lane.js +11 -2
  155. package/dist/modes/interactive/components/activity-lane.js.map +1 -1
  156. package/dist/modes/interactive/components/settings-selector.js +1 -1
  157. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  158. package/dist/utils/shell.d.ts +2 -0
  159. package/dist/utils/shell.d.ts.map +1 -1
  160. package/dist/utils/shell.js +3 -1
  161. package/dist/utils/shell.js.map +1 -1
  162. package/docs/harness-architecture.md +6 -3
  163. package/docs/settings.md +39 -6
  164. package/docs/tool-repair.md +1 -1
  165. package/docs/worker-profiles.md +2 -2
  166. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  167. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  168. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  169. package/examples/extensions/sandbox/package-lock.json +2 -2
  170. package/examples/extensions/sandbox/package.json +1 -1
  171. package/examples/extensions/with-deps/package-lock.json +2 -2
  172. package/examples/extensions/with-deps/package.json +1 -1
  173. package/npm-shrinkwrap.json +12 -12
  174. package/package.json +4 -4
@@ -14,6 +14,7 @@ import { MAX_ORCHESTRATION_DISPATCH_INSTRUCTIONS_LENGTH, } from "../orchestratio
14
14
  import { SessionTaskProfileStore } from "../orchestration/session-task-profile-store.js";
15
15
  import { TaskProfileWriter, } from "../orchestration/task-profile-writer.js";
16
16
  import { createWorkerExecutionContract, verifierWorkerExecutionContract, } from "../orchestration/worker-execution-contract.js";
17
+ import { resolveWorkerModelPin } from "../orchestration/worker-model-pins.js";
17
18
  import { registerInFlightWork } from "../reload-blockers.js";
18
19
  import { createDelegateToolDefinition } from "../tools/delegate.js";
19
20
  import { disposePersistentShellSession } from "../tools/shell-session.js";
@@ -29,16 +30,17 @@ import { WorkerConversationStore, } from "./worker-conversation-store.js";
29
30
  import { parseWorkerDelegationAuthorityRequest } from "./worker-delegation-request.js";
30
31
  import { WorkerDispatchScheduler } from "./worker-dispatch-scheduler.js";
31
32
  import { buildWorkerExecutionPlan, compileWorkerExecutionGrant, narrowWorkerExecutionPlan, workerExecutionAuthorityFromPlan, } from "./worker-execution-policy.js";
32
- import { DEFAULT_WORKER_FLEET_LIMITS, evaluateNewWorkerAdmission, pendingVerifierSubjectTaskIds, } from "./worker-fleet-limits.js";
33
+ import { DEFAULT_WORKER_FLEET_LIMITS, evaluateNewWorkerAdmission, intersectWorkerDelegationLimits, pendingVerifierSubjectTaskIds, resolveWorkerFleetLimits, } from "./worker-fleet-limits.js";
34
+ import { WorkerLeaseHeartbeat } from "./worker-lease-heartbeat.js";
33
35
  import { createLocalWorkerProcessOwnerId } from "./worker-process-owner.js";
34
- import { WorkerProfileResolver } from "./worker-profile-resolver.js";
36
+ import { WorkerProfileResolver, } from "./worker-profile-resolver.js";
35
37
  import { WorkerRecoveryCoordinator } from "./worker-recovery-coordinator.js";
36
38
  import { selectWorkerResourcePointers } from "./worker-resource-catalog.js";
37
39
  import { materializeWorkerResourceBundle } from "./worker-resource-materializer.js";
38
40
  import { finalizeWorkerClaim } from "./worker-terminal-finalizer.js";
39
41
  import { WorkerTerminalHandoffCoordinator, } from "./worker-terminal-handoff-coordinator.js";
40
42
  import { collectWorkerTreeBudgetSeeds, WorkerTreeBudgetCoordinator } from "./worker-tree-budget-coordinator.js";
41
- import { WorkerWriteReservationCoordinator } from "./worker-write-reservation-coordinator.js";
43
+ import { WorkerWriteReservationCoordinator, } from "./worker-write-reservation-coordinator.js";
42
44
  export function isLocalExecutionModel(model) {
43
45
  if (model.provider === "ollama" || model.provider === "transformers" || model.provider === "llama-cpp") {
44
46
  return true;
@@ -82,6 +84,7 @@ export class WorkerDelegationController {
82
84
  this.shellSessionKeys = new Set();
83
85
  this.publishedTerminalAttemptIds = new Set();
84
86
  this.yieldedCapacityAttemptIds = new Map();
87
+ this.yieldedWriteReservations = new Map();
85
88
  this.conversations = new WorkerConversationStore();
86
89
  this.treeBudgets = new WorkerTreeBudgetCoordinator();
87
90
  this.inFlightLedgers = new Map();
@@ -150,7 +153,8 @@ export class WorkerDelegationController {
150
153
  ? this.workerProjectionHeadroomSkipReason(contract)
151
154
  : "orchestration_execution_contract_missing";
152
155
  },
153
- yieldCapacity: (callerAgentId, targetAgentId) => this.yieldWorkerCapacity(callerAgentId, targetAgentId),
156
+ waitBlockedByCaller: (callerAgentId, targetAgentIds) => this.waitTargetsBlockedByCaller(callerAgentId, targetAgentIds),
157
+ yieldCallerForWait: (callerAgentId) => this.yieldWorkerForWait(callerAgentId),
154
158
  warn: (message) => this.safeWarn(message),
155
159
  });
156
160
  this.terminalHandoffs = new WorkerTerminalHandoffCoordinator({
@@ -166,8 +170,10 @@ export class WorkerDelegationController {
166
170
  getParentSessionId: () => this.deps.getSessionId(),
167
171
  ownerId: this.agentControl.getProcessOwnerId(),
168
172
  drainQueuedWorkers: () => {
169
- if (!this.deps.isDisposed())
170
- this.scheduler.drain(true);
173
+ if (this.deps.isDisposed())
174
+ return;
175
+ this.scheduler.drain(true);
176
+ this.agentControl.signalStateChanged();
171
177
  },
172
178
  warn: (message) => this.safeWarn(message),
173
179
  });
@@ -427,20 +433,27 @@ export class WorkerDelegationController {
427
433
  createTaskProfile(input) {
428
434
  return this.getTaskProfileWriter().createTaskProfile(input);
429
435
  }
430
- resolveWorkerShipment(request, settings) {
431
- const resolved = this.getWorkerProfileResolver().resolve(request, settings.orchestrationProfile);
432
- return resolved.ok ? { ok: true, shipment: resolved.resolved } : { ok: false, skipReason: resolved.reason };
436
+ resolveWorkerPreset(request, settings) {
437
+ const resolved = this.getWorkerProfileResolver().resolvePreset(request, settings.orchestrationProfile);
438
+ return resolved.ok ? { ok: true, preset: resolved.resolved } : { ok: false, skipReason: resolved.reason };
433
439
  }
434
- resolveRequiredVerifier(profile) {
440
+ resolveRequiredVerifier(profile, modelPinPolicy) {
435
441
  if (!profile.requireIndependentVerification)
436
442
  return { ok: true };
437
- const resolved = this.getWorkerProfileResolver().resolveVerifier(profile);
438
- if (!resolved.ok)
439
- return { ok: false, skipReason: `independent_verifier_unavailable:${resolved.reason}` };
443
+ const preset = this.getWorkerProfileResolver().resolveVerifierPreset(profile);
444
+ if (!preset.ok)
445
+ return { ok: false, skipReason: `independent_verifier_unavailable:${preset.reason}` };
446
+ const modelPin = resolveWorkerModelPin(modelPinPolicy, "verifier");
447
+ const resolved = this.getWorkerProfileResolver().bindPreset(preset.resolved, modelPin?.binding);
448
+ if (!resolved.ok) {
449
+ const reason = modelPin ? "worker_model_pin_unavailable:verifier" : resolved.reason;
450
+ return { ok: false, skipReason: `independent_verifier_unavailable:${reason}` };
451
+ }
440
452
  // Fresh verifier profiles pass through the same shipment admission owner as fresh workers.
441
453
  // Recovery-pinned verifier contracts bypass this path and preserve their immutable grant.
442
454
  const admitted = resolveWorkerAuthority({
443
455
  base: resolved.resolved,
456
+ ...(modelPin ? { modelPin: modelPin.binding } : {}),
444
457
  modelRegistry: this.deps.getModelRegistry(),
445
458
  isModelExhausted: (model) => this.deps.isModelExhausted(model),
446
459
  });
@@ -449,9 +462,10 @@ export class WorkerDelegationController {
449
462
  : { ok: false, skipReason: `independent_verifier_unavailable:${admitted.reason}` };
450
463
  }
451
464
  /**
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.
465
+ * A descendant may select a different routing profile, but that preset cannot introduce context or
466
+ * recursive authority its ancestor never admitted. Pointer ids alone are insufficient authority:
467
+ * retain only pointers whose complete immutable metadata matches the ancestral contract, require
468
+ * exact soul text, and intersect durable delegation limits.
455
469
  */
456
470
  narrowWorkerShipmentContext(shipment, boundary) {
457
471
  const boundaryPointers = new Map(boundary.resourcePointers.map((pointer) => [pointer.id, pointer]));
@@ -466,10 +480,15 @@ export class WorkerDelegationController {
466
480
  if (shipment.soul !== undefined && shipment.soul !== boundary.soul) {
467
481
  return { ok: false, skipReason: "orchestration_context_authority_exceeded" };
468
482
  }
483
+ const delegationLimits = intersectWorkerDelegationLimits(shipment.profile.delegationLimits, boundary.profile.delegationLimits);
469
484
  return {
470
485
  ok: true,
471
486
  shipment: {
472
487
  ...shipment,
488
+ profile: {
489
+ ...shipment.profile,
490
+ ...(delegationLimits ? { delegationLimits } : {}),
491
+ },
473
492
  resourcePointers,
474
493
  ...(shipment.soul ? { soul: shipment.soul } : {}),
475
494
  },
@@ -494,7 +513,11 @@ export class WorkerDelegationController {
494
513
  }
495
514
  /** Reject a new logical identity before creating its task, transcript, agent, or queue entry. */
496
515
  newWorkerFleetSkipReason(request, requiredAgentSlots = 1) {
497
- const decision = evaluateNewWorkerAdmission(this.lifecycle.getTaskRuntimeSnapshot().agents, request.parentAgentId, DEFAULT_WORKER_FLEET_LIMITS, requiredAgentSlots);
516
+ const parentAttempt = request.parentAgentId
517
+ ? this.lifecycle.getLatestAgentAttempt(request.parentAgentId)
518
+ : undefined;
519
+ const limits = resolveWorkerFleetLimits(parentAttempt?.dispatch.executionContract?.worker.profile.delegationLimits);
520
+ const decision = evaluateNewWorkerAdmission(this.lifecycle.getTaskRuntimeSnapshot().agents, request.parentAgentId, limits, requiredAgentSlots);
498
521
  return decision.ok ? undefined : decision.reasonCode;
499
522
  }
500
523
  requiredAgentSlotsForAdmission(request, admission) {
@@ -515,6 +538,12 @@ export class WorkerDelegationController {
515
538
  const settings = this.deps.getSettingsManager().getWorkerDelegationSettings();
516
539
  if (!settings.enabled)
517
540
  return { ok: false, skipReason: "worker_delegation_disabled" };
541
+ const modelPinPolicy = pinnedContract
542
+ ? { status: "absent" }
543
+ : this.deps.getSettingsManager().getWorkerModelPinPolicy();
544
+ if (modelPinPolicy.status === "invalid") {
545
+ return { ok: false, skipReason: "worker_model_pins_invalid" };
546
+ }
518
547
  const parentAgent = request.parentAgentId ? this.lifecycle.getAgent(request.parentAgentId) : undefined;
519
548
  if (request.parentAgentId && !parentAgent) {
520
549
  return { ok: false, skipReason: "orchestration_parent_agent_unknown" };
@@ -540,6 +569,7 @@ export class WorkerDelegationController {
540
569
  }
541
570
  }
542
571
  let baseShipment;
572
+ let basePreset;
543
573
  if (pinnedContract) {
544
574
  const pinned = this.getWorkerProfileResolver().resolveContract(pinnedContract.worker);
545
575
  if (!pinned.ok)
@@ -553,22 +583,41 @@ export class WorkerDelegationController {
553
583
  baseShipment = inherited.resolved;
554
584
  }
555
585
  else if (request.profileId || settings.orchestrationProfile) {
556
- const configured = this.resolveWorkerShipment(request, settings);
586
+ const configured = this.resolveWorkerPreset(request, settings);
557
587
  if (!configured.ok)
558
588
  return configured;
559
- baseShipment = configured.shipment;
589
+ basePreset = configured.preset;
590
+ }
591
+ const effectiveRole = authority?.role ?? baseShipment?.profile.role ?? basePreset?.profile.role ?? "orchestrator";
592
+ const modelPin = resolveWorkerModelPin(modelPinPolicy, effectiveRole);
593
+ if (basePreset) {
594
+ const bound = this.getWorkerProfileResolver().bindPreset(basePreset, modelPin?.binding);
595
+ if (!bound.ok) {
596
+ return {
597
+ ok: false,
598
+ skipReason: modelPin ? `worker_model_pin_unavailable:${effectiveRole}` : bound.reason,
599
+ };
600
+ }
601
+ baseShipment = bound.resolved;
560
602
  }
561
603
  const adaptive = pinnedContract
562
604
  ? { ok: true, shipment: baseShipment }
563
605
  : resolveWorkerAuthority({
564
606
  authority,
565
607
  ...(baseShipment ? { base: baseShipment } : {}),
608
+ ...(modelPin ? { modelPin: modelPin.binding } : {}),
566
609
  ...(this.deps.getModel() ? { foregroundModel: this.deps.getModel() } : {}),
567
610
  modelRegistry: this.deps.getModelRegistry(),
568
611
  isModelExhausted: (model) => this.deps.isModelExhausted(model),
569
612
  });
570
- if (!adaptive.ok)
571
- return { ok: false, skipReason: adaptive.reason };
613
+ if (!adaptive.ok) {
614
+ return {
615
+ ok: false,
616
+ skipReason: modelPin && adaptive.reason === "orchestration_model_unavailable"
617
+ ? `worker_model_pin_unavailable:${effectiveRole}`
618
+ : adaptive.reason,
619
+ };
620
+ }
572
621
  let shipment = adaptive.shipment;
573
622
  if (parentContract) {
574
623
  const narrowed = this.narrowWorkerShipmentContext(shipment, parentContract.worker);
@@ -594,7 +643,7 @@ export class WorkerDelegationController {
594
643
  verifierShipment = verifier.resolved;
595
644
  }
596
645
  else {
597
- const verifier = this.resolveRequiredVerifier(shipment.profile);
646
+ const verifier = this.resolveRequiredVerifier(shipment.profile, modelPinPolicy);
598
647
  if (!verifier.ok)
599
648
  return verifier;
600
649
  verifierShipment = verifier.shipment;
@@ -829,37 +878,89 @@ export class WorkerDelegationController {
829
878
  const status = snapshot.attempts[attemptId]?.status;
830
879
  if (status === "leased" || status === "running")
831
880
  yielded += 1;
832
- else
881
+ else {
833
882
  this.yieldedCapacityAttemptIds.delete(attemptId);
883
+ this.yieldedWriteReservations.delete(attemptId);
884
+ }
834
885
  }
835
886
  return Math.max(0, this.getWorkerLifecycle().getRunningCount() - yielded) < settings.maxConcurrent;
836
887
  }
837
- yieldWorkerCapacity(callerAgentId, targetAgentId) {
888
+ waitTargetsBlockedByCaller(callerAgentId, targetAgentIds) {
838
889
  const caller = this.lifecycle.getAgent(callerAgentId);
839
- const target = this.lifecycle.getAgent(targetAgentId);
840
- if (!caller || !target || caller.rootAgentId !== target.rootAgentId)
841
- return () => undefined;
890
+ const callerAttempt = caller ? this.lifecycle.getLatestAgentAttempt(caller.agentId) : undefined;
891
+ if (!callerAttempt || (callerAttempt.status !== "leased" && callerAttempt.status !== "running"))
892
+ return [];
893
+ const blockedAgentIds = [];
894
+ for (const targetAgentId of targetAgentIds) {
895
+ const target = this.lifecycle.getAgent(targetAgentId);
896
+ const targetAttempt = target ? this.lifecycle.getLatestAgentAttempt(target.agentId) : undefined;
897
+ if (targetAttempt?.status === "queued" &&
898
+ this.writeReservations.isBlockedBy(targetAttempt.taskId, callerAttempt.taskId)) {
899
+ blockedAgentIds.push(targetAgentId);
900
+ }
901
+ }
902
+ return blockedAgentIds;
903
+ }
904
+ yieldWorkerForWait(callerAgentId) {
905
+ const caller = this.lifecycle.getAgent(callerAgentId);
906
+ if (!caller)
907
+ return () => true;
842
908
  const attempt = this.lifecycle.getLatestAgentAttempt(caller.agentId);
843
909
  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;
910
+ return () => true;
911
+ const existingYields = this.yieldedCapacityAttemptIds.get(attempt.attemptId) ?? 0;
912
+ if (existingYields === 0 && attempt.lease) {
913
+ const yieldedReservation = this.writeReservations.yieldForWait(attempt.taskId, attempt.attemptId, attempt.lease.fencingToken);
914
+ if (yieldedReservation)
915
+ this.yieldedWriteReservations.set(attempt.attemptId, yieldedReservation);
916
+ }
917
+ this.yieldedCapacityAttemptIds.set(attempt.attemptId, existingYields + 1);
918
+ let restored = false;
919
+ const restore = () => {
920
+ if (restored)
921
+ return true;
852
922
  const leases = this.yieldedCapacityAttemptIds.get(attempt.attemptId);
853
- if (leases === undefined)
854
- return;
923
+ if (leases === undefined) {
924
+ restored = true;
925
+ return true;
926
+ }
855
927
  if (leases > 1) {
856
928
  this.yieldedCapacityAttemptIds.set(attempt.attemptId, leases - 1);
857
- return;
929
+ restored = true;
930
+ return true;
931
+ }
932
+ const current = this.lifecycle.getLatestAgentAttempt(caller.agentId);
933
+ if (!this.deps.isDisposed() &&
934
+ current?.attemptId === attempt.attemptId &&
935
+ (current.status === "leased" || current.status === "running")) {
936
+ const yieldedReservation = this.yieldedWriteReservations.get(attempt.attemptId);
937
+ if (yieldedReservation) {
938
+ const reservation = this.writeReservations.restoreAfterWait(yieldedReservation);
939
+ if (reservation.kind === "blocked")
940
+ return false;
941
+ if (reservation.kind === "denied") {
942
+ this.laneAbortControllers.get(attempt.taskId)?.abort(reservation.reasonCode);
943
+ throw new Error(`Worker wait could not restore its write reservation: ${reservation.reasonCode}.`);
944
+ }
945
+ }
858
946
  }
859
947
  this.yieldedCapacityAttemptIds.delete(attempt.attemptId);
948
+ this.yieldedWriteReservations.delete(attempt.attemptId);
949
+ restored = true;
860
950
  if (!this.deps.isDisposed())
861
- this.scheduler.drain();
951
+ this.scheduler.drain(true);
952
+ return true;
862
953
  };
954
+ try {
955
+ this.scheduler.drain(true);
956
+ }
957
+ catch (error) {
958
+ if (!restore()) {
959
+ throw new AggregateError([error], "Worker wait dispatch failed before its write reservation could be restored.");
960
+ }
961
+ throw error;
962
+ }
963
+ return restore;
863
964
  }
864
965
  workerDispatchAdmission(request, record) {
865
966
  if (this.recovery.deferRetryIfNeeded(record, request))
@@ -942,13 +1043,14 @@ export class WorkerDelegationController {
942
1043
  workerContextForkMode(request, contract) {
943
1044
  if (request.verificationOfTaskId)
944
1045
  return { kind: "none" };
1046
+ const mode = request.forkTurns ?? (request.parentAgentId ? "none" : undefined);
945
1047
  return resolveWorkerContextInheritanceMode({
946
1048
  parent: this.workerContextParentModel(request),
947
1049
  worker: {
948
1050
  provider: contract.worker.modelBinding.provider,
949
1051
  model: contract.worker.modelBinding.modelId,
950
1052
  },
951
- ...(request.forkTurns !== undefined ? { mode: request.forkTurns } : {}),
1053
+ ...(mode !== undefined ? { mode } : {}),
952
1054
  });
953
1055
  }
954
1056
  workerContextForkAdmissionSkipReason(request, contract) {
@@ -1412,6 +1514,7 @@ export class WorkerDelegationController {
1412
1514
  startWorkerDelegation: (childRequest) => this.start({ ...childRequest, parentAgentId: agentId }),
1413
1515
  runWorkerDelegation: (childRequest) => this.runOnce({ ...childRequest, parentAgentId: agentId }),
1414
1516
  orchestrationProfiles: this.getProfileCatalog(),
1517
+ workerModelPinPolicy: this.deps.getSettingsManager().getWorkerModelPinPolicy(),
1415
1518
  workerAgentControl: this.agentControl,
1416
1519
  caller: { kind: "worker", agentId },
1417
1520
  resolveMessageReplayScope: () => ({
@@ -1499,6 +1602,16 @@ export class WorkerDelegationController {
1499
1602
  const laneAbortController = new AbortController();
1500
1603
  this.laneAbortControllers.set(startedRecord.laneId, laneAbortController);
1501
1604
  const workerSignal = AbortSignal.any([this.workerAbort.signal, laneAbortController.signal]);
1605
+ const leaseHeartbeat = new WorkerLeaseHeartbeat({
1606
+ leaseTtlMs: immutableProfile.leaseTtlMs,
1607
+ renew: () => {
1608
+ lifecycle.renewLease(startedRecord.laneId, immutableProfile.leaseTtlMs);
1609
+ },
1610
+ onFailure: (error) => {
1611
+ this.safeWarn(`Worker ${startedRecord.laneId} lease renewal failed: ${error.message}`);
1612
+ laneAbortController.abort(error);
1613
+ },
1614
+ });
1502
1615
  // Registered for the lane's full run so the reload gate waits it out; deregistered in the
1503
1616
  // finally below no matter how this lane terminates (success, disposal, or a thrown error).
1504
1617
  // registerInFlightWork is a pure sync map op (cannot throw), so placing it as the last
@@ -1551,7 +1664,9 @@ export class WorkerDelegationController {
1551
1664
  request: workerRequest,
1552
1665
  handle: durableHandle,
1553
1666
  });
1667
+ leaseHeartbeat.start();
1554
1668
  const executionResult = await executor.run();
1669
+ leaseHeartbeat.assertHealthy();
1555
1670
  const rawOutcome = executionResult.rawOutcome;
1556
1671
  // Attempt ladder: a retryable bounded failure suspends and re-enqueues instead of
1557
1672
  // terminalizing, resuming from the persisted transcript under a fresh fence.
@@ -1733,7 +1848,10 @@ export class WorkerDelegationController {
1733
1848
  return { started: true, record };
1734
1849
  }
1735
1850
  finally {
1851
+ leaseHeartbeat.stop();
1736
1852
  this.writeReservations.release(startedRecord.laneId, durableHandle.attemptId, durableHandle.fencingToken);
1853
+ this.yieldedCapacityAttemptIds.delete(durableHandle.attemptId);
1854
+ this.yieldedWriteReservations.delete(durableHandle.attemptId);
1737
1855
  this.inFlightLedgers.delete(startedRecord.laneId);
1738
1856
  this.laneAbortControllers.delete(startedRecord.laneId);
1739
1857
  try {